Skip to content

Absorb bubble_up_url across the four shapes that carry it - #488

Merged
jeremy merged 4 commits into
mainfrom
feat/bubble-up-url-absorption
Jul 28, 2026
Merged

Absorb bubble_up_url across the four shapes that carry it#488
jeremy merged 4 commits into
mainfrom
feat/bubble-up-url-absorption

Conversation

@jeremy

@jeremy jeremy commented Jul 28, 2026

Copy link
Copy Markdown
Member

Stacked on #487#486#484. Prerequisite for the #477 SDK follow-up.

bubble_up_url was already at the provenance pin in my/readings/_reading.json.jbuilder and modeled on Reading. The post-pin drift is the shared recording and todolist partials — and requiredness is not uniform across the shapes that carry it.

Requiredness differs by shape, and the reason is the call site

app/views/api/recordings/_recording.json.jbuilder:19-21:

if local_assigns[:bubbleupable]
  json.bubble_up_url bucket_recording_bubble_up_url(recording.bucket, recording, api_url_options)
end

app/views/api/todolists/_todolist.json.jbuilder:2:

json.partial! "recordings/recording", recording: recording, commentable: true, boostable: true, bubbleupable: true

That is the only bubbleupable passer in the entire view tree (grep -rn "bubbleupable" app/views/ returns exactly these two hits), and it passes it unconditionally.

Shape Requiredness Why
Todolist @required every list/show/group path renders the todolist partial, which always passes the flag
TodolistGroup @required todolists/groups/{index,show}.json.jbuilder render the same partial
Recording optional polymorphic projection; the generic path never passes the flag
SearchResult optional same, with one variant that does — see below

SearchResult is in scope because Todolists are searchable: Search::Type::TYPE_FILTER_MAPPING maps "Todo" => %w[Todo Todolist], and Searches::ApiHelper#api_search_result_template_path falls through to recording.to_recordable_partial_path, which for a Todolist resolves to todolists/todolist — the partial that passes the flag.

Adding required response members changes generated public types, so this is breaking.

Fixtures — including the field-bearing representatives

Direct shapes: todolists/{get,list}.json and todolist_groups/{get,list}.json.

The two optional shapes needed representatives that actually carry the field, because their existing fixtures correctly do not:

Both are registered in spec/fixtures/manifest.yaml as new targets (recording-list-todolist, search-result-todolist) and added to covered_schemas, so the coverage guard validates them rather than leaving them unchecked. make check-fixture-coverage22 manifest targets.

URLs are derived from each fixture's existing subscription_url/url, so they stay internally consistent and match the real bucket_recording_bubble_up_url shape (.../buckets/<b>/recordings/<id>/bubble_up.json, from the recording_actions concern in config/routes.rb:231).

Go wrappers

make go-check-wrapper-drift named all four shapes; all four wrappers now carry BubbleUpURL and assign it in their *FromGenerated bodies. Required on Todolist/TodolistGroup (no omitempty), omitempty on Recording/SearchResult. Gate reports 83 pairs walked, 1123 generated fields verified.

Go tests assert the field discriminates rather than merely existing: for every recording and every search result, a Todolist must have BubbleUpURL set and every other type must not. A regeneration that made it unconditional would fail.

Smithy examples

spec/overlays/examples.smithy is validated for required-member completeness — the first make generate failed with Missing required structure member bubble_up_url for both GetTodolistOrGroup examples. Both updated.

spec/api-gaps/recording-bubbleupable-field.md stays open

It tracks a distinct boolean bubbleupable field expressing per-user eligibility. bubble_up_url is a URL whose presence is decided by the rendering call site, so it is constant per shape and cannot answer "can this user bubble this up". Annotated the entry to say so, so nobody mistakes this absorption for closing it. make validate-api-gaps → clean, 27 entries.

make check exits 0.


Summary by cubic

Adds bubble_up_url to Todolist, TodolistGroup, Recording, and SearchResult across the API and SDKs. Breaking change: it’s required on Todolist and TodolistGroup; regenerate SDKs and update fixtures/tests.

  • New Features

    • Modeled bubble_up_url across four shapes; required on Todolist/TodolistGroup, optional on Recording/SearchResult (present for Todolist variants). OpenAPI/Smithy updated; Go/Swift/Kotlin/Python/Ruby/TypeScript SDKs regenerated.
    • Fixtures updated and manifest extended with field-bearing reps in recordings/list.json and search/results.json.
  • Bug Fixes

    • Made invented Todolist fixtures self-consistent (bucket IDs, Todoset parent, bookmark SGIDs); Smithy examples updated.
    • TypeScript conformance runner: use performance.now() and allow a 2ms TIMER_SLACK_MS to handle early Node timers.
    • Tests: Ruby now uses canonical todolists/get.json and asserts bubble_up_url; Python stubs include required bubble_up_url; TypeScript adds an explicit assertion.

Written for commit 8365fea. Summary will update on new commits.

Review in cubic

Copilot AI review requested due to automatic review settings July 28, 2026 07:23
@jeremy jeremy added enhancement New feature or request spec Changes to the Smithy spec or OpenAPI breaking Breaking change to public API labels Jul 28, 2026
@github-actions github-actions Bot added typescript Pull requests that update TypeScript code ruby Pull requests that update the Ruby SDK go kotlin swift python Pull requests that update the Python SDK labels Jul 28, 2026
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Spec Change Impact

Summary of Changes

  • Modified Types: bubble_up_url absorbed into four shapes that previously carried it.
  • No operations or resources were added or removed.

Impact on SDKs

  • All SDKs require regeneration to incorporate updated type definitions.
  • This is not a breaking API change as no operations or fields were removed.

SDK Regeneration Checklist

  • Go
  • TypeScript
  • Ruby
  • Kotlin
  • Swift

@github-actions github-actions Bot removed the breaking Breaking change to public API label Jul 28, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR absorbs the bubble_up_url field across the four response shapes that can carry it, modeling requiredness by call-site (required on Todolist/TodolistGroup, optional on the polymorphic Recording/SearchResult) and regenerating all downstream SDK artifacts plus fixtures/examples to match.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Changes:

  • Update Smithy + OpenAPI to add bubble_up_url, required on Todolist/TodolistGroup and optional on Recording/SearchResult.
  • Regenerate SDK models/types across TypeScript, Swift, Kotlin, Ruby, Python, and Go (including Go wrapper propagation).
  • Extend fixtures + manifest coverage and adjust Go tests to pin discriminating presence/absence for polymorphic projections.

Reviewed changes

Copilot reviewed 17 out of 31 changed files in this pull request and generated no comments.

Show a summary per file
File Description
typescript/src/generated/schema.d.ts Adds bubble_up_url to relevant TS schema types with requiredness aligned to shape.
typescript/src/generated/openapi-stripped.json Updates stripped OpenAPI schema + examples to include bubble_up_url and required lists.
typescript/src/generated/metadata.ts Regeneration timestamp update for TS metadata.
swift/Sources/Basecamp/Generated/Models/TodolistGroup.swift Adds required bubbleUpUrl to generated Swift TodolistGroup.
swift/Sources/Basecamp/Generated/Models/Todolist.swift Adds required bubbleUpUrl to generated Swift Todolist.
swift/Sources/Basecamp/Generated/Models/SearchResult.swift Adds optional bubbleUpUrl to generated Swift SearchResult.
swift/Sources/Basecamp/Generated/Models/Recording.swift Adds optional bubbleUpUrl to generated Swift Recording.
spec/overlays/examples.smithy Updates Smithy examples to satisfy new required bubble_up_url members.
spec/fixtures/todolists/list.json Adds required bubble_up_url to todolist list fixture elements.
spec/fixtures/todolists/get.json Adds required bubble_up_url to todolist get fixture.
spec/fixtures/todolist_groups/list.json Adds required bubble_up_url to todolist group list fixture elements.
spec/fixtures/todolist_groups/get.json Adds required bubble_up_url to todolist group get fixture.
spec/fixtures/search/results.json Adds a Todolist-shaped search result fixture carrying bubble_up_url.
spec/fixtures/recordings/list.json Adds a Todolist-shaped recording fixture carrying bubble_up_url.
spec/fixtures/manifest.yaml Registers new fixture targets and updates covered schemas for Recording/SearchResult.
spec/basecamp.smithy Models bubble_up_url on Todolist, TodolistGroup, Recording, and SearchResult with correct requiredness.
spec/api-gaps/recording-bubbleupable-field.md Clarifies that absorbing bubble_up_url does not close the separate bubbleupable boolean gap.
ruby/lib/basecamp/generated/types.rb Regenerates Ruby types to include bubble_up_url (required where appropriate).
ruby/lib/basecamp/generated/metadata.json Regeneration timestamp update for Ruby metadata.
python/src/basecamp/generated/types.py Updates generated Python TypedDicts to include bubble_up_url (required vs NotRequired as modeled).
openapi.json Updates canonical OpenAPI schema + examples and required lists for bubble_up_url.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/models/TodolistGroup.kt Adds required bubbleUpUrl to Kotlin TodolistGroup.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/models/Todolist.kt Adds required bubbleUpUrl to Kotlin Todolist.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/models/Recording.kt Adds optional bubbleUpUrl to Kotlin Recording.
go/pkg/generated/client.gen.go Updates Go generated models for bubble_up_url across the four shapes.
go/pkg/basecamp/todolists.go Propagates required BubbleUpURL into Go wrapper Todolist + mapping.
go/pkg/basecamp/todolist_groups.go Propagates required BubbleUpURL into Go wrapper TodolistGroup + mapping.
go/pkg/basecamp/search.go Propagates optional BubbleUpURL into Go wrapper SearchResult + mapping.
go/pkg/basecamp/search_test.go Updates Go search tests/fixtures expectations to assert discriminating bubble_up_url presence.
go/pkg/basecamp/recordings.go Propagates optional BubbleUpURL into Go wrapper Recording + mapping.
go/pkg/basecamp/recordings_test.go Updates Go recordings tests/fixtures expectations to assert discriminating bubble_up_url presence.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 71aeec274c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread spec/basecamp.smithy
Comment on lines +1545 to +1546
@required
bubble_up_url: String

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Repin provenance for this upstream absorption

This change absorbs a post-pin BC3 contract from the shared recording/todolist partials, but spec/api-provenance.json remains at revision c3086931 dated 2026-07-26. As a result, the recorded conformance baseline does not identify the upstream revision that supplied bubble_up_url, and subsequent drift checks will continue treating the absorbed change as post-pin drift. Update the BC3 revision/date to the current upstream HEAD and run make provenance-sync.

AGENTS.md reference: AGENTS.md:L263-L270

Useful? React with 👍 / 👎.

@jeremy
jeremy force-pushed the fix/search-result-nullability branch from 84b8cac to 3e36e73 Compare July 28, 2026 07:32
Copilot AI review requested due to automatic review settings July 28, 2026 07:34
@jeremy
jeremy force-pushed the feat/bubble-up-url-absorption branch from 71aeec2 to 093137e Compare July 28, 2026 07:34

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed

You’re at about 91% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread spec/fixtures/search/results.json Outdated
Comment thread spec/fixtures/search/results.json
Comment thread spec/fixtures/recordings/list.json
Comment thread spec/fixtures/recordings/list.json Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 31 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 32 changed files in this pull request and generated no new comments.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

You’re at about 95% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread spec/fixtures/search/results.json
@jeremy
jeremy force-pushed the fix/search-result-nullability branch from bd43995 to bdbc370 Compare July 28, 2026 20:26
@jeremy
jeremy force-pushed the feat/bubble-up-url-absorption branch from 091d4ad to e7df40b Compare July 28, 2026 20:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 32 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

spec/basecamp.smithy:8006

  • Same doc-path consistency issue as the Recording shape: this comment cites todolists/_todolist (missing .json.jbuilder) even though other new comments in this PR use the full partial filename. Prefer the fully-qualified partial path for consistency and easier source tracing. (This will require regenerating downstream artifacts that embed this description.)
  /// URL of the Bubble Up record for this recording (BC5 addition). Optional
  /// here because this is a polymorphic projection:
  /// `recordings/_recording.json.jbuilder` emits the key only when the caller
  /// passes `local_assigns[:bubbleupable]`, and `todolists/_todolist` is the
  /// only partial that does. So a Todolist-shaped instance carries it and the
  /// other recording types do not.

spec/basecamp.smithy:6331

  • The doc comment references todolists/_todolist without the .json.jbuilder suffix, while other newly-added comments in this PR (e.g., on Todolist/TodolistGroup) use the full partial filename. Using the full path here too would keep the spec documentation consistent and avoid confusion when tracing the call site that controls bubble_up_url emission. (This will require regenerating downstream artifacts that embed this description.)

This issue also appears on line 8001 of the same file.

  /// URL of the Bubble Up record for this recording (BC5 addition). Optional
  /// here because this is a polymorphic projection:
  /// `recordings/_recording.json.jbuilder` emits the key only when the caller
  /// passes `local_assigns[:bubbleupable]`, and `todolists/_todolist` is the
  /// only partial that does. So a Todolist-shaped instance carries it and the
  /// other recording types do not.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e7df40bb42

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread spec/basecamp.smithy
/// path renders that partial — so the key is present on every projection of
/// this shape.
@required
bubble_up_url: String

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update all response stubs for bubble_up_url

Once this member is required, every Todolist/TodolistGroup response should contain it, but several endpoint tests still return malformed responses without bubble_up_url, including ruby/test/basecamp/services/todolists_service_test.rb:19-65, ruby/test/basecamp/services/todolist_groups_service_test.rb:20-34, python/tests/services/test_todolists_service.py:88-145, and typescript/tests/services/todolistGroups.test.ts:33-88. Because those clients accept these partial mappings without runtime schema validation, the tests continue passing even if the new field is dropped during decoding or service generation; update these stubs and assert that the field flows through.

AGENTS.md reference: AGENTS.md:L310-L315

Useful? React with 👍 / 👎.

Copilot AI review requested due to automatic review settings July 28, 2026 21:22
@jeremy
jeremy force-pushed the feat/bubble-up-url-absorption branch from e7df40b to 9479720 Compare July 28, 2026 21:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 35 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

python/tests/services/test_todolists_service.py:26

  • The docstring says this stub "must not contradict the contract", but the returned payload omits many required Todolist fields (e.g., app_url, bucket, created_at, etc.). That makes the comment misleading; either load the canonical fixture (as other Python tests do) or clarify that this helper is intentionally minimal and only includes bubble_up_url because it became required.
    payload shape — but a stub must not contradict the contract either.
    bubble_up_url is @required on Todolist (todolists/_todolist.json.jbuilder
    always passes bubbleupable: true), so it belongs here even though nothing
    below reads it. Full-shape coverage lives in spec/fixtures, which
    `make check-fixture-coverage` validates.

@jeremy
jeremy force-pushed the fix/search-result-nullability branch from dbbe7b2 to fba66dd Compare July 28, 2026 21:27
@jeremy
jeremy force-pushed the feat/bubble-up-url-absorption branch from 9479720 to 78b436f Compare July 28, 2026 21:28
@jeremy
jeremy requested a review from Copilot July 28, 2026 21:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 35 changed files in this pull request and generated no new comments.

@jeremy

jeremy commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

Correcting myself on the 2,000 ms assertion.

I said Date.now() truncation was the cause and that three clean runs proved it fixed. That was wrong — the assertion failed again on a later run at 1999.8753749999996 ms. Sub-millisecond, so not a rounding artifact: libuv rounds a timer's deadline down internally, so setTimeout(2000) can genuinely elapse in slightly under 2,000 ms of wall clock. Go's timers don't fire early, which is why only this runner ever saw it.

performance.now() is still correct — Date.now() truncation was a real second source of noise — but it needed a documented TIMER_SLACK_MS of 2 ms on the comparison, which is now in place with the reasoning inline. That allowance cannot hide a real regression: a dropped Retry-After halves the backoff (~1,000 ms off) and a missing delay misses by the whole interval.

Three consecutive clean full-runner runs again — but I'm noting the number rather than resting on it, since that's exactly what I did last time.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 35 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

python/tests/services/test_todolists_service.py:33

  • The _todolist() helper claims the stub “must not contradict the contract”, but the returned dict is still missing many required Todolist members (e.g. app_url, url, type, status, inherits_status, created_at/updated_at, parent, bucket, creator). Since this helper is being updated for the new required bubble_up_url, it’s a good place to make the stub minimally contract-valid so these tests can’t accidentally normalize an impossible payload.
    return {
        "id": 2,
        "name": name,
        "description_attachments": [],
        "bubble_up_url": "https://3.basecampapi.com/12345/buckets/1/recordings/2/bubble_up.json",

Base automatically changed from fix/search-result-nullability to main July 28, 2026 22:24
jeremy added 4 commits July 28, 2026 15:24
Already at the provenance pin in my/readings/_reading.json.jbuilder and
modeled on Reading. The post-pin drift is the shared recording and todolist
partials, and requiredness differs by shape.

recordings/_recording.json.jbuilder emits the key only when the caller
passes local_assigns[:bubbleupable]. todolists/_todolist.json.jbuilder is
the ONLY partial that passes it, and it passes bubbleupable: true
unconditionally. Every list, show, and group path renders that partial.

So Todolist and TodolistGroup get @required; Recording and SearchResult
stay optional, because they are polymorphic projections where only the
Todolist variant receives the flag.

SearchResult is in scope because Todolists are searchable —
Search::Type::TYPE_FILTER_MAPPING maps "Todo" => %w[Todo Todolist] — and
Searches::ApiHelper#api_search_result_template_path falls through to
to_recordable_partial_path, which for a Todolist resolves to the same
todolist partial.

Adding required response members changes generated public types, so this
is breaking.

Fixtures: bubble_up_url added to the direct Todolist and group fixtures,
plus field-bearing representatives for the two optional shapes — a
Todolist-shaped element in recordings/list.json and a Todolist search
result. recordings/get.json is a Message and correctly keeps omitting the
key. Both new representatives are registered in the fixture manifest so
the coverage guard validates them, and the Go tests assert the shape
discriminates: Todolist carries it, every other type does not.

spec/api-gaps/recording-bubbleupable-field.md stays open. It tracks a
distinct boolean bubbleupable field expressing per-user eligibility.
bubble_up_url is a URL whose presence is decided by the rendering call
site, so it is constant per shape and cannot answer whether this user can
bubble this up. Noted in the entry.
… flake

Both Todolist elements I added were built by cloning a Message element and
overwriting only the URLs, so their identity fields disagreed: URLs said
bucket 2085958500 while bucket.id said 2085958499, parent was a
Message::Board rather than a Todoset, and the bookmark SGIDs still encoded
the Message's recording id. Every identity-bearing field is now taken from
the real todolists/get.json — one bucket, one recording id, a Todoset
parent, and a bookmark SGID that decodes to the right recording.

Separately, the TypeScript conformance runner captured request timestamps
with Date.now(), which floors to whole milliseconds. Two floored reads
bracketing a 2000ms sleep can legitimately differ by 1999, which is what
turned retry.json's delayBetweenRequests assertion red. The Go runner uses
nanosecond time.Time and never saw it. Switched to performance.now(); the
assertion is unchanged and the SDK really does sleep the full interval.
Three consecutive clean runs of the TypeScript runner.
Ruby's todolists test_get hand-rolled { id, name, description_attachments }.
Todolist has a dozen required members and that stub omits nearly all of
them, so it was a payload BC3 cannot produce — it passed only because Ruby
does not validate required fields at runtime. Repointed at the canonical
spec/fixtures/todolists/get.json, which make check-fixture-coverage
validates, so it can no longer drift from the contract. It now also asserts
bubble_up_url is present.

Python's todolists stubs belong to metadata/hook-identity tests where the
payload is deliberately irrelevant, so rather than inflate them to full
shape I factored a small _todolist() helper that carries the required
bubble_up_url and says why it is there.

TypeScript needed no stub change: todolists.test.ts already imports
spec/fixtures/todolists/get.json directly, so it picked the field up with
the fixture. Added an explicit assertion so that is provable rather than
incidental, and so a fixture regression fails here too. todolistGroups
constructs no Todolist-shaped payload at all — it covers create/reposition
and the absence of get/update.
…recisely

My previous commit blamed Date.now() truncation alone and claimed three
clean runs proved it. That was wrong. With performance.now() the same
assertion later failed at 1999.8753749999996ms — sub-millisecond, so not a
rounding artifact: libuv rounds a timer's deadline down internally, so
setTimeout(2000) can genuinely elapse in slightly under 2000ms of wall
clock. Go's timers do not fire early, which is why only this runner sees it.

performance.now() is still right (Date.now() truncation was a real second
source of noise), but it needed a documented TIMER_SLACK_MS of 2ms on the
comparison. That cannot mask a real regression: a dropped Retry-After
halves the backoff (~1000ms off) and a missing delay misses by the whole
interval.
@jeremy
jeremy force-pushed the feat/bubble-up-url-absorption branch from c529eeb to 8365fea Compare July 28, 2026 22:24
@jeremy
jeremy requested a review from Copilot July 28, 2026 22:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 35 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

python/tests/services/test_todolists_service.py:23

  • The docstring says this stub "must not contradict the contract", but the returned dict still omits many required Todolist members (e.g., url/app_url/created_at/etc.), so that statement is inaccurate/misleading. Either load a full fixture here, or adjust the wording to reflect that this is intentionally not a contract-complete payload.
    These tests are about operation identity and resource-id scoping, not
    payload shape — but a stub must not contradict the contract either.
    bubble_up_url is @required on Todolist (todolists/_todolist.json.jbuilder

@jeremy
jeremy merged commit 058fd11 into main Jul 28, 2026
50 checks passed
@jeremy
jeremy deleted the feat/bubble-up-url-absorption branch July 28, 2026 22:41
@jeremy jeremy added the breaking Breaking change to public API label Jul 29, 2026
This was referenced Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Breaking change to public API conformance Conformance test suite enhancement New feature or request go kotlin python Pull requests that update the Python SDK ruby Pull requests that update the Ruby SDK spec Changes to the Smithy spec or OpenAPI swift typescript Pull requests that update TypeScript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants