Skip to content

BC5 readiness: forward-compat spec, briefs, parity lint#293

Merged
jeremy merged 16 commits into
mainfrom
bc5-readiness-spec-foundations
Jul 22, 2026
Merged

BC5 readiness: forward-compat spec, briefs, parity lint#293
jeremy merged 16 commits into
mainfrom
bc5-readiness-spec-foundations

Conversation

@jeremy

@jeremy jeremy commented May 1, 2026

Copy link
Copy Markdown
Member

Summary

Foundation PR for BC5 release readiness. Additive across the board — no behavior changes, no breaking renames.

  • Forward-compat Smithy additions for BC5 read paths on existing operations:
    • Notification gains bubble_up_url, bubble_up_at
    • GetMyNotificationsOutput gains bubble_ups, scheduled_bubble_ups
    • Person gains tagline (alias of bio)
    • Todo gains steps (reuses existing CardStep shape)
    • Todoset gains todos_count, completed_loose_todos_count, todos_url, app_todos_url
    • memories member documented as observed-current behavior pending BC team's back-compat decision
  • Parallel BC4/BC5 provenance: spec/api-provenance.json restructured for parallel branch tracking. Post-launch topology (BC5 launched 2026-05-27; five merged into master, BC4 moved to the four branch): .bc3 tracks BC5 master (pinned at e52453ff, 2026-07-17 — main's Todos Update/Edit/Replace: merge-safe writes across all 6 SDKs #375 sync baseline, kept through the rebase; still pre-train, so it claims no coverage of the BC5 API train resources) and .compatibility.bc3-four keeps the BC4 baseline (four @ 9d73959a). Existing tooling reads the same .bc3 keys and works unchanged; sync-status iterates .compatibility keys generically.
  • make generate aggregator runs Smithy build, behavior model, URL routes, provenance sync, and per-language SDKs in dependency order.
  • make check-bucket-flat-parity flags bucket-scoped GET list operations without flat counterparts. Initial allowlist seeded with webhooks (legitimately per-project).
  • Branch-aware make sync-status reports drift for the active branch and the BC4 compatibility branch as two clearly-labeled blocks.
  • API gap registry at spec/api-gaps/ — 11 entries aligned with the BC3 parity plan's Phase 3 deliverables, plus COORDINATION.md describing the SDK ↔ BC3 plan relationship and the absorption lifecycle.
  • make validate-api-gaps validates frontmatter and required body sections (Ruby stdlib only, no gem deps).

The api-gap registry is durable: each entry transitions through a documented lifecycle (no-json-contractaddressed-in-bc3-pr-Nabsorbed-in-sdk) with status changes flowing through git history. Living next to basecamp.smithy in spec/ makes the spec-ecosystem mental model explicit — entries describe expected future spec state and link back to Smithy structures on absorption.

Commit structure

  1. spec(bc5) — Smithy additions + provenance restructure + parity-lint allowlist seed
  2. build(make) — generate aggregator + parity lint + branch-aware sync-status + validator make-target
  3. docs(api-gaps) — API gap registry + COORDINATION.md + validator + CONTRIBUTING updates
    4-9. One commit per SDK (ts, ruby, python, kotlin, swift, go) for regenerated artifacts

Cross-team contract decisions (called out in COORDINATION.md)

Two items the SDK canary will surface that need BC team resolution before release:

  • memories: [] on BC5 — back-compat or accept-and-document.
  • Longstanding app_todoslists_url typo — server fix, alias period, or SDK accommodation.

Test plan

  • make smithy-check, make behavior-model-check, make provenance-check, make sync-spec-version-check, make sync-api-version-check
  • make go-check-drift, make kt-check-drift, make py-check-drift, make auth-routable-check
  • make ts-check, make rb-check, make py-check, make kt-check, make swift-check, make go-check
  • make conformance-{go,kotlin,typescript,ruby,python}
  • make check-bucket-flat-parity (1 bucket-scoped list op, allowlisted)
  • make validate-api-gaps (11 entries + allowlist, clean)
  • make sync-status reports both .bc3 (primary: master) and .compatibility.bc3-four (compat: four) blocks, clearly labeled
  • bash scripts/validate-api-gaps.sh passes from a clean shell (env -i ..., ruby --disable-gems ...)
  • make lint-actions

What this PR is NOT

This PR is the foundation. It does not include:

  • The TS canonical wire-capture canary (PR 2, stacked on this one)
  • Cross-language wire-replay decoders (PR 3)
  • Pairwise BC4↔BC5 comparison + check-bc5-compat orchestrator (PR 4)
  • API gap detector tooling (PR 5)
  • New SDK services for any registered gap — those land per-entry as BC3 ships each Phase 3 deliverable

Copilot AI review requested due to automatic review settings May 1, 2026 21:58
@github-actions github-actions Bot added documentation Improvements or additions to documentation typescript Pull requests that update TypeScript code ruby Pull requests that update the Ruby SDK go kotlin swift spec Changes to the Smithy spec or OpenAPI labels May 1, 2026
@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown

Spec Change Impact

  • Operations/Types/Resources Added: None

  • Operations/Types/Resources Modified: Forward-compat changes, briefs updates, and parity improvements. Specific modifications not detailed.

  • Operations/Types/Resources Removed: None

  • SDKs Needing Regeneration: All SDKs require regeneration due to spec changes.

  • Breaking API Change: No breaking changes (no removed operations/fields).

Checklist of SDKs needing updates:

  • Go
  • TypeScript
  • Ruby
  • Kotlin
  • Swift

@github-actions github-actions Bot added enhancement New feature or request and removed documentation Improvements or additions to documentation labels May 1, 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

Foundation work to prepare the SDK repo for BC5 readiness: additive Smithy/OpenAPI model updates, new repo-level spec/brief validation tooling, and regenerated multi-language SDK artifacts pinned to the updated API version.

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:

  • Add BC5 forward-compat fields to the Smithy spec (notifications bubble-up fields, todo steps, todoset counts/URLs, person tagline) and regenerate OpenAPI + SDK model artifacts.
  • Introduce repo lints/utilities: bucket↔flat parity check, API gap brief validator, and branch-aware BC3 drift reporting wired into make check/make sync-status.
  • Add and validate API gap briefs + allowlist schema/docs, and add make generate as a full regeneration aggregator.

Reviewed changes

Copilot reviewed 34 out of 50 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
typescript/src/generated/schema.d.ts Generated TS schema typings updated for new BC5 fields + descriptions.
typescript/src/generated/openapi-stripped.json Generated stripped OpenAPI updated (version + new schema fields/docs).
typescript/src/generated/metadata.json Regeneration timestamp update.
typescript/src/client.ts Bump TS SDK API_VERSION to 2026-05-01.
swift/Sources/Basecamp/Generated/Models/Todoset.swift Generated Swift model updated with new todoset fields.
swift/Sources/Basecamp/Generated/Models/Todo.swift Generated Swift model updated with embedded steps.
swift/Sources/Basecamp/Generated/Models/Person.swift Generated Swift model updated with tagline.
swift/Sources/Basecamp/Generated/Models/Notification.swift Generated Swift model updated with bubble-up fields.
swift/Sources/Basecamp/Generated/Models/GetMyNotificationsResponseContent.swift Generated Swift response content updated with bubble-up collections.
swift/Sources/Basecamp/BasecampConfig.swift Bump Swift SDK apiVersion to 2026-05-01.
spec/bucket-scoped-allowlist.txt New allowlist for bucket-scoped list ops without flat counterparts.
spec/basecamp.smithy Smithy service version bump + additive BC5 model fields.
spec/api-provenance.json Provenance structure updated to track active branch + compatibility baseline.
scripts/validate-briefs.sh Shell entrypoint for briefs validation (Ruby).
scripts/validate-briefs.rb Ruby validator for brief frontmatter/body sections + allowlist schema checks.
scripts/report-bc3-drift.sh New helper to report drift for an arbitrary BC3 baseline/branch/label.
scripts/check-bucket-flat-parity.sh New lint to enforce bucket↔flat list-operation parity (with allowlist).
ruby/lib/basecamp/version.rb Bump Ruby SDK API_VERSION to 2026-05-01.
ruby/lib/basecamp/generated/types.rb Regenerated Ruby types with BC5 additive fields.
ruby/lib/basecamp/generated/metadata.json Regeneration timestamp update.
python/src/basecamp/generated/types.py Regenerated Python TypedDicts with BC5 additive fields.
python/src/basecamp/_version.py Bump Python SDK API_VERSION to 2026-05-01.
openapi.json Generated OpenAPI updated (version + new schema fields/docs).
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/models/Todoset.kt Regenerated Kotlin model updated with new todoset fields.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/models/Todo.kt Regenerated Kotlin model updated with embedded steps.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/models/Person.kt Regenerated Kotlin model updated with tagline.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/BasecampConfig.kt Bump Kotlin SDK API_VERSION to 2026-05-01.
go/pkg/generated/client.gen.go Regenerated Go client models with BC5 additive fields.
go/pkg/basecamp/version.go Bump Go SDK APIVersion to 2026-05-01.
go/pkg/basecamp/api-provenance.json Go copy of provenance updated to new structure.
briefs/api-gaps/todoset-completed-list-visibility.md New API gap brief.
briefs/api-gaps/step-top-level.md New API gap brief.
briefs/api-gaps/stack-doc-and-smithy.md New API gap brief.
briefs/api-gaps/search-filter-additions.md New API gap brief.
briefs/api-gaps/scratchpad.md New API gap brief.
briefs/api-gaps/schema.json New JSON schema for brief frontmatter.
briefs/api-gaps/rich-text-project-attachable.md New API gap brief.
briefs/api-gaps/recording-bubbleupable-field.md New API gap brief.
briefs/api-gaps/recordable-subtypes-doc.md New API gap brief.
briefs/api-gaps/everything-aggregates.md New API gap brief.
briefs/api-gaps/calendar.md New API gap brief.
briefs/api-gaps/allowlist.yml New allowlist for detector-classified routes that don’t require briefs.
briefs/api-gaps/allowlist-schema.json JSON schema for the briefs allowlist format.
briefs/api-gaps/activity-timeline.md New API gap brief.
briefs/api-gaps/README.md Overview doc + table of briefs + validation instructions.
briefs/COORDINATION.md Cross-team coordination doc for BC3 parity + SDK absorption lifecycle.
behavior-model.json Behavior model updated for new Person.tagline JSON path.
Makefile Add generate aggregator; wire new lints/validators into check; improve sync-status.
CONTRIBUTING.md Document make generate, parity lint, and briefs workflow.
.gitignore Ignore Kotlin .kotlin/ build artifacts.

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

Comment thread scripts/check-bucket-flat-parity.sh Outdated
Comment thread scripts/check-bucket-flat-parity.sh Outdated
Comment thread scripts/validate-api-gaps.rb

@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 50 files

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread scripts/validate-api-gaps.rb Outdated
Comment thread spec/api-gaps/schema.json Outdated
Comment thread scripts/check-bucket-flat-parity.sh Outdated
Comment thread scripts/check-bucket-flat-parity.sh Outdated
Comment thread scripts/validate-api-gaps.rb Outdated
Comment thread COORDINATION.md Outdated
@jeremy
jeremy force-pushed the bc5-readiness-spec-foundations branch from 1e1c949 to 5bd407c Compare May 1, 2026 22:21
@jeremy
jeremy requested a review from Copilot May 1, 2026 22:21
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label May 1, 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

Copilot reviewed 34 out of 50 changed files in this pull request and generated 4 comments.


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

Comment thread scripts/check-bucket-flat-parity.sh Outdated
Comment thread COORDINATION.md Outdated
Comment thread spec/api-gaps/README.md Outdated
Comment thread Makefile
@jeremy
jeremy force-pushed the bc5-readiness-spec-foundations branch from 5bd407c to 63205bf Compare May 1, 2026 22:49
@jeremy
jeremy requested a review from Copilot May 1, 2026 22:49

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 34 out of 50 changed files in this pull request and generated 3 comments.


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

Comment thread scripts/check-bucket-flat-parity.sh Outdated
Comment thread scripts/check-bucket-flat-parity.sh Outdated
Comment thread COORDINATION.md Outdated

@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: 63205bfebc

ℹ️ 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 Makefile Outdated
@jeremy
jeremy force-pushed the bc5-readiness-spec-foundations branch from 63205bf to 7e9c434 Compare May 1, 2026 23:03
@jeremy
jeremy requested a review from Copilot May 1, 2026 23:03

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 34 out of 50 changed files in this pull request and generated 2 comments.


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

Comment thread scripts/check-bucket-flat-parity.sh Outdated
Comment thread spec/api-gaps/todoset-completed-list-visibility.md
@jeremy
jeremy requested a review from Copilot May 13, 2026 20:43

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 30 out of 47 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • typescript/package-lock.json: Generated file

Comment thread scripts/check-bucket-flat-parity.sh
Comment thread spec/api-provenance.json

@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: 839b69037f

ℹ️ 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 scripts/check-bucket-flat-parity.sh Outdated
Comment thread spec/basecamp.smithy
…sh advisories

Three high-severity advisories published since main's last green security
run (2026-07-20) trip npm Audit on the TypeScript SDK:

- fast-uri GHSA-4c8g-83qw-93j6 (host confusion via failed IDN
  canonicalization): override >=3.1.2 -> >=3.1.3, resolves 4.1.1
- brace-expansion GHSA-3jxr-9vmj-r5cp (DoS via exponential expansion):
  override >=5.0.6 -> >=5.0.7
- js-yaml GHSA-52cp-r559-cp3m (quadratic CPU via merge-key chains):
  new override ^4.3.0, pinned to the 4.x patched line since js-yaml 5
  is a major bump for openapi-typescript's transitive use

npm audit clean; ts-generate + ts-generate-services + ts-check verified
green under the new resolutions.
Copilot AI review requested due to automatic review settings July 22, 2026 02:41
@github-actions github-actions Bot removed the documentation Improvements or additions to documentation label Jul 22, 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

Copilot reviewed 30 out of 47 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • typescript/package-lock.json: Generated file

Comment thread Makefile Outdated
Comment thread Makefile Outdated
jeremy added a commit that referenced this pull request Jul 22, 2026
Surface the BC5 forward-compat fields filed in
go/BRIEF-bc5-forward-compat-wrappers.md through the hand-written wrapper
layer. PR 1 (#293) added these on the generated client; this commit closes
the wrapper gap so basecamp-cli Phase 1 can read them.

  - Todo: + Steps []CardStep (BC5 jbuilder reuses the steps/step partial,
    matching the existing CardStep shape; reuse rather than introduce a
    new type)
  - Todoset: + TodosCount, CompletedLooseTodosCount, TodosURL, AppTodosURL
  - Person: + Tagline (alias of Bio; surfaced as a separate wrapper field
    per the spec note so consumers can distinguish presence)
  - Notification: + BubbleUpURL, BubbleUpAt (time.Time, following the
    existing ReadAt/UnreadAt zero-value pattern)
  - NotificationsResult: + BubbleUps, ScheduledBubbleUps

These wrappers all decode through the existing FromGenerated paths (Todo,
Todoset, Person) or direct JSON unmarshal (Notification, NotificationsResult)
with struct tags; no new conversion pattern is needed.

Refs: go/BRIEF-bc5-forward-compat-wrappers.md
- sync-status: pass BC3_REPO through to report-bc3-drift.sh in both the
  primary and compatibility invocations — make variables aren't exported
  to recipe environments, so 'make sync-status BC3_REPO=org/fork' was
  silently querying the default repo
- parity lint: use [[:space:]] instead of the non-POSIX \s escape in the
  allowlist filter; accept {projectId} alongside {bucketId} in the
  bucket-path pattern (and strip logic) for forward-compat with the
  documented Smithy path convention; use # as the sed delimiter to keep
  the ERE alternation unambiguous across GNU/BSD sed

Candidate count and lint verdict unchanged (verified against openapi.json
before/after).
Copilot AI review requested due to automatic review settings July 22, 2026 02:54
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Jul 22, 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

Copilot reviewed 30 out of 47 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • typescript/package-lock.json: Generated file

Comment thread scripts/check-bucket-flat-parity.sh Outdated
Comment thread Makefile
- parity lint: accept literal filter segments (e.g. /todos/completed.json)
  in addition to path-parameter variants — the header always promised
  (/<filter>)? coverage but the regex only matched /{param}. Candidate
  set unchanged today (verified: single-resource GETs carry no .json
  suffix in this spec, so the anchor keeps the match tight).
- sync-status: guard on jq alongside the existing gh guards.
Copilot AI review requested due to automatic review settings July 22, 2026 03:02
@github-actions github-actions Bot removed the documentation Improvements or additions to documentation label Jul 22, 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

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

Files not reviewed (1)
  • typescript/package-lock.json: Generated file

@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: 66f9dfa926

ℹ️ 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
@jeremy
jeremy merged commit fd8b196 into main Jul 22, 2026
49 checks passed
@jeremy
jeremy deleted the bc5-readiness-spec-foundations branch July 22, 2026 04:38
jeremy added a commit that referenced this pull request Jul 22, 2026
Surface the BC5 forward-compat fields filed in
go/BRIEF-bc5-forward-compat-wrappers.md through the hand-written wrapper
layer. PR 1 (#293) added these on the generated client; this commit closes
the wrapper gap so basecamp-cli Phase 1 can read them.

  - Todo: + Steps []CardStep (BC5 jbuilder reuses the steps/step partial,
    matching the existing CardStep shape; reuse rather than introduce a
    new type)
  - Todoset: + TodosCount, CompletedLooseTodosCount, TodosURL, AppTodosURL
  - Person: + Tagline (alias of Bio; surfaced as a separate wrapper field
    per the spec note so consumers can distinguish presence)
  - Notification: + BubbleUpURL, BubbleUpAt (time.Time, following the
    existing ReadAt/UnreadAt zero-value pattern)
  - NotificationsResult: + BubbleUps, ScheduledBubbleUps

These wrappers all decode through the existing FromGenerated paths (Todo,
Todoset, Person) or direct JSON unmarshal (Notification, NotificationsResult)
with struct tags; no new conversion pattern is needed.

Refs: go/BRIEF-bc5-forward-compat-wrappers.md
jeremy added a commit that referenced this pull request Jul 22, 2026
…eck (#309)

* wrappers: standardize nested Person on personFromGenerated

Every *FromGenerated function that built a nested *Person value (Creator,
Completer, Approver, Booster, Participants, top-level Person) previously
inlined a 6-field shallow copy that silently dropped Bio, Location, Title,
PersonableType, AttachableSGID, Client, Employee, TimeZone, CanPing,
CanAccessHillCharts, CanAccessTimesheet, CanManageProjects, CanManagePeople,
Company, CreatedAt, and UpdatedAt on every nested context.

Replace each shallow copy with a personFromGenerated() call. Pure refactor;
zero field additions on the wrapper struct side. The change is forward-compat
additive — fields that were dropped before are now populated when present in
the generated payload; no removals.

This makes every subsequent additive Person field (e.g. Tagline) flow through
every nested context for free, instead of requiring per-context re-adds.

* wrappers: cross-cutting Recording-shaped fields

Add the pervasive Category B fields (BookmarkURL, BoostsCount, BoostsURL,
CommentsCount, CommentsURL, SubscriptionURL, InheritsStatus, VisibleToClients,
Title) — and Content where applicable — to the wrappers that already share
the Recording shape but were missing one or more.

Affected wrappers:
  - Recording: + Content, CommentsCount, CommentsURL, SubscriptionURL
  - Comment: + VisibleToClients, Title, InheritsStatus, BookmarkURL,
    BoostsCount, BoostsURL
  - Message: + VisibleToClients, Title, InheritsStatus, BookmarkURL,
    BoostsURL, CommentsCount, CommentsURL, SubscriptionURL
  - MessageBoard: + VisibleToClients, InheritsStatus, BookmarkURL
  - Forward: + VisibleToClients, Title, InheritsStatus, BookmarkURL,
    SubscriptionURL
  - ForwardReply: + VisibleToClients, Title, InheritsStatus, BookmarkURL,
    BoostsCount, BoostsURL
  - Inbox: + VisibleToClients, InheritsStatus, BookmarkURL
  - CampfireLine: + BookmarkURL, BoostsURL
  - ScheduleEntry: + BoostsCount, BoostsURL
  - QuestionAnswer: + BoostsCount, BoostsURL
  - Todolist: + BoostsCount, BoostsURL
  - TimesheetEntry: + Status, VisibleToClients, Title, InheritsStatus, Type,
    URL, AppURL, BookmarkURL

Forward-compat additive — fields default to zero/empty when absent. Wrapper
JSON serialization uses omitempty on newly-added fields to match the
upstream serialization behavior.

* wrappers: BC5 forward-compat fields

Surface the BC5 forward-compat fields filed in
go/BRIEF-bc5-forward-compat-wrappers.md through the hand-written wrapper
layer. PR 1 (#293) added these on the generated client; this commit closes
the wrapper gap so basecamp-cli Phase 1 can read them.

  - Todo: + Steps []CardStep (BC5 jbuilder reuses the steps/step partial,
    matching the existing CardStep shape; reuse rather than introduce a
    new type)
  - Todoset: + TodosCount, CompletedLooseTodosCount, TodosURL, AppTodosURL
  - Person: + Tagline (alias of Bio; surfaced as a separate wrapper field
    per the spec note so consumers can distinguish presence)
  - Notification: + BubbleUpURL, BubbleUpAt (time.Time, following the
    existing ReadAt/UnreadAt zero-value pattern)
  - NotificationsResult: + BubbleUps, ScheduledBubbleUps

These wrappers all decode through the existing FromGenerated paths (Todo,
Todoset, Person) or direct JSON unmarshal (Notification, NotificationsResult)
with struct tags; no new conversion pattern is needed.

Refs: go/BRIEF-bc5-forward-compat-wrappers.md

* wrappers: one-off structural fields

Close the remaining Category B one-off structural gaps identified in the
field-level wrapper audit (predates BC5, surfaced during the BC5 readiness
sweep).

  - Campfire: + Topic, Position, BookmarkURL, SubscriptionURL
  - MessageBoard: + AppMessagesURL, Position
  - Template: + URL, AppURL, Dock []DockItem (reuses the existing DockItem
    type from projects.go; conversion shared via dockItemFromGenerated helper)
  - Person: + CanAccessHillCharts, CanAccessTimesheet; also wire CanPing into
    personFromGenerated (struct field existed; propagation did not)
  - Notification: + Creator, Participants, PreviewableAttachments (with new
    companion PreviewableAttachment type mirroring generated.PreviewableAttachment)
  - Gauge: + Creator, Bucket
  - GaugeNeedle: + Creator, Bucket, Parent
  - Inbox: + Position, ForwardsCount, ForwardsURL
  - Forward: + RepliesCount, RepliesURL

The Notification sentinel-creator test fixture was updated to include
`personable_type: "LocalPerson"` (the actual BC3 wire shape for system
actors) so normalizeJSON correctly coerces the string "basecamp" id to 0
and preserves it as system_label; the test now asserts the wrapper exposes
the normalized creator end-to-end rather than silently dropping it.

* wrappers: close remaining structural gaps surfaced by drift audit

The field-level audit (formalized as the new check-wrapper-drift script
in the next commit) surfaced these additional pre-existing structural
gaps that the explicit lists in the prior commits did not cover.

  - Card: + BoostsURL (sibling of existing BoostsCount)
  - CardColumn: + CommentsCount (alongside the existing oddly-named
    CommentCount whose json tag was `comment_count`; the canonical
    `comments_count` tag now also flows through)
  - CardStep: + CompletionURL
  - Document: + BoostsURL
  - Event: + BoostsCount, BoostsURL
  - Todo: + VisibleToClients, SubscriptionURL, BoostsURL, CommentsCount,
    CommentsURL, CompletionURL, CompletionSubscribers []Person
  - Upload: + BoostsURL

All additions follow the same forward-compat additive pattern: zero/empty
when absent on the wire, populated through the existing *FromGenerated
conversion paths.

* scripts: field-level wrapper drift check

Adds a Go AST-based field-level drift check, sibling of the existing
operation-level scripts/check-service-drift.sh. The existing check confirms
that every generated operation has a hand-written service wrapper; this new
check confirms that every generated *struct field* is propagated through the
hand-written wrapper layer (or explicitly marked as intentionally-omitted).

Discovery: walks (wrapper, generated) pairs in two ways —
  1. signature reading of every `xFromGenerated(g generated.Y) X` function
     declaration in go/pkg/basecamp/*.go (non-test).
  2. an explicit `directDecodePairs` map covering wrappers that decode
     straight from JSON bytes (Notification, NotificationsResult,
     MyAssignment, Gauge, GaugeNeedle) without a *FromGenerated function.

Matching is keyed on JSON tag, not Go field name, so shape-equivalent
collisions (`URL string \`json:"url"\`` vs `Url string \`json:"url"\``) are
handled correctly. Opt-out marker format
  // intentionally-omitted: <tag> - <reason>
(ASCII hyphen + space + reason, validated by regex) can appear anywhere
inside the wrapper struct body.

Wired into:
  - new `make go-check-wrapper-drift` target
  - existing `make check` aggregate (next to `go-check-drift`)
  - go.work `use` block, so `go run ./scripts/check-wrapper-drift/`
    works without extra setup.

Self-tests in main_test.go exercise the parser/extractor helpers, the
marker regex (reason-required), the excluded-FromGenerated exception
(webhookPersonFromGenerated → WebhookEventPerson), and a happy/drift
end-to-end pair.

Result on the fully-fixed tree: 51 (wrapper, generated) pairs walked,
842 generated fields verified, zero drift, zero intentionally-omitted
markers required.

* wrappers: tests for new field propagation

Adds wrapper_propagation_test.go with three test patterns:

  1. Test<Type>FromGenerated_PropagatesNewFields — one per wrapper file
     that gained fields. Asserts only the new fields against a
     fully-populated generated.X fixture; the existing
     *FromGenerated_FullPopulated tests still cover the full surface.

  2. TestPerson_NewFields_NestedPropagation — end-to-end check that the
     personFromGenerated standardization causes a fully-populated nested
     generated.Person (Bio, Tagline, Location, Title, AttachableSGID,
     PersonableType, Client, Employee, TimeZone, CanPing,
     CanAccessHillCharts, CanAccessTimesheet, CanManageProjects,
     CanManagePeople, Company, CreatedAt, UpdatedAt) to flow through
     every nested context (Recording, Comment, Message, Todo,
     ScheduleEntry.Creator + Participants, Card.Creator + Completer +
     Assignees). Pins commit 1's standardization end-to-end.

  3. Test<Type>_DirectDecode_PropagatesNewFields — JSON-fixture tests for
     the §C-2 direct-decode wrappers (Notification, NotificationsResult,
     MyAssignment, Gauge, GaugeNeedle) that decode via json.Unmarshal on
     the (sometimes pre-normalized) raw body.

Also commits the original brief at go/BRIEF-bc5-forward-compat-wrappers.md
that triggered this PR — filed by the basecamp-cli dev agent against
SDK commit 7e9c434. Preserving it in-tree keeps the audit trail of why
Category A field additions look the way they do, alongside the wider
audit (Categories B + C) that the brief flagged would be welcome.

21 new tests in total; all pass on the current tree.

* wrappers: gofmt long-tag struct alignment

`gofmt -s -w` rewrites the column-aligned tag layouts in Notification,
NotificationsResult, Person, Todo, and Todoset where the newly-added fields
pushed the existing alignment past gofmt's preferred width. No behavior
change; closes `make fmt-check` (and thus `make check`).

* scripts: wrapper drift check verifies field population, not just tags

The field-level wrapper drift check previously confirmed only that each
generated JSON tag had a matching tag on the wrapper struct. A wrapper
field could carry the right tag yet never be assigned by its
*FromGenerated conversion function, leaving it zero-valued on the wire
while the check passed.

Extend the check with a population pass: for every *FromGenerated-backed
pair it AST-walks the conversion body and confirms each tagged wrapper
field is actually assigned (via the wrapper's composite literal or a
selector-target assignment). A tag-present-but-never-assigned field is
now reported as drift. Direct-decode wrappers are exempt — json.Unmarshal
populates them straight from the tags, so tag presence is population. The
package doc spells out the check's reachability semantics and limits.

Also:
- Remove the dead exclusion loop in run(): it keyed off the wrapper
  struct name (k+"FromGenerated") but collectFromGeneratedPairs already
  filters by function name, so the guard never matched. The inner filter
  is the only effective one.
- Inject the direct-decode pair map into run() so the end-to-end tests
  drive the real run() entry point over their own fixtures instead of
  reimplementing the pipeline. Replaces the partial TestEndToEnd with
  run()-driven cases covering in-sync, missing-tag, tag-present-but-
  unassigned (the population regression), both assignment forms, and
  stale omit-marker detection.
- Drop the unquoted cd $(CURDIR) from the go-check-wrapper-drift target
  so it is safe on paths with spaces; go run with a relative path needs
  no cd.

* wrappers: stop omitempty hiding false bools and zero timestamps

omitempty on a bool drops a legitimate false, and omitempty on a value
time.Time does not suppress the zero time at all — it marshals as
0001-01-01T00:00:00Z instead of being omitted.

- Drop omitempty from the visible_to_clients and inherits_status bool
  response fields on TimesheetEntry, Inbox, Forward, and ForwardReply so
  a false value stays on the wire. This matches the generated structs,
  which carry these tags without omitempty.
- Change Notification.BubbleUpAt from time.Time to *time.Time so an
  unset scheduled resurfacing time omits cleanly (nil) rather than
  emitting the zero-time sentinel. Mirrors the existing *time.Time
  convention for Card.CompletedAt / Todo.CompletedAt.

* wrappers: tighten propagation test assertions to exact values

The propagation tests checked several mapped fields only for non-empty,
so a swapped field mapping would still pass.

- Assert exact URLs for the Message wrapper (BookmarkURL, BoostsURL,
  CommentsURL, SubscriptionURL) instead of just non-empty.
- Assert nested Person CreatedAt/UpdatedAt against the expected RFC3339
  formatted timestamps rather than non-empty strings, catching a
  CreatedAt/UpdatedAt source swap.
- Assert BubbleUpAt against its exact expected value (and nil for the
  unscheduled entry) now that it is a *time.Time, replacing the IsZero
  checks the pointer change broke.
- Drop the unused types import and the var _ = types.Date{} that kept it
  alive; the test no longer references the package.

* scripts: scope wrapper-drift population walk to the wrapper instance

The population walk counted any `x.Field = ...` selector write as a
wrapper-field write, so writes to helper locals (a nested Person, a
WebhookDelivery, a WebhookCopy) could be miscounted as populating the
wrapper and mask genuine drift when the helper local shared a field name
with the wrapper. Identify the wrapper instance up front (named result,
the local bound to the wrapper composite literal, and the returned
identifier) and only count selector writes whose base is that instance.

Also extend directDecodePairs to the nested direct-decode structs reachable
from the top-level raw-body wrappers (PreviewableAttachment, and the
MyAssignmentAssignee/Bucket/Parent companions). These have generated
counterparts but no *FromGenerated, so the parent check previously stopped
at the parent field and would miss future generated-field drift inside
them; listing them carries the tag-presence check into the nested structs.

Rework the pair-extraction test so the unqualified-parameter exclusion is
observable: the excluded function now returns a distinct type whose absence
from the pair map is a meaningful assertion. Add soundness regressions
proving a helper-local selector write is not attributed to the wrapper and
that run() reports drift when a tag is only assigned via such a local.

* wrappers: preserve flexible notification person ids on decode

Exposing Notification.Creator/Participants (this branch's change) routes
notification people through Person.ID, a plain int64. BC3 serializes some
notification person ids as JSON strings, and those person objects often
omit personable_type, so the existing normalizePersonIds pass (keyed on
personable_type) skipped them and the decode failed with a string-into-int64
unmarshal error.

Add normalizeNotificationsJSON for the /my/readings.json path: it runs the
generic person normalization plus a creator/participants pass that coerces
string ids by their structural position regardless of personable_type,
reusing the shared id rule (numeric string to json.Number, non-numeric
sentinel to 0 with the label preserved as system_label, overflow left for
the decoder to reject). Add a decode test covering a string-id creator and
participants without personable_type, including the sentinel case.

* wrappers: preserve flexible gauge person ids; share embedded-person normalize

Gauge and GaugeNeedle gained Creator *Person on this branch but decode raw
via json.Unmarshal, so a string-valued creator.id (BC3 wire format) failed
the whole decode against Person.ID (a plain int64) — the same regression
just fixed for notifications.

Generalize the notification-specific pass into a shared one:
normalizeNotificationPeople becomes normalizeEmbeddedPersonIds and
normalizeNotificationsJSON becomes normalizeEmbeddedPeopleJSON, coercing
string ids on embedded creator/participants people regardless of
personable_type. Route the gauge service decode sites through a
decodeGaugePayload helper that normalizes first, alongside the existing
notifications caller. Add a gauge decode test for a string creator id with
and without personable_type.

* wrappers: drop omitempty from required visible_to_clients/inherits_status

These booleans are required (no omitempty) on generated.Todo, Comment,
Message, and MessageBoard, but the wrapper fields added on this branch
carried omitempty, which drops a legitimate false value when the public
wrapper is marshaled. Match the generated shape so an explicit false stays
on the wire — the same fix already applied to TimesheetEntry, Inbox,
Forward, and ForwardReply. Todo.inherits_status already lacked omitempty,
so only visible_to_clients changes there.

(Gauge/GaugeNeedle keep omitempty on these tags because their generated
counterparts also declare them with omitempty.)

* wrappers: test required-bool marshaling; fix stale normalize name in comment

Add TestRequiredBools_FalseMarshalsExplicitly covering the omitempty removal:
Todo, Comment, Message, and MessageBoard must serialize visible_to_clients /
inherits_status as an explicit false rather than omitting the key. The test
fails if omitempty is reintroduced on either tag.

Also fix a stale reference in the notification decode test comment
(normalizeNotificationsJSON was renamed to normalizeEmbeddedPeopleJSON).

* wrappers: clear golangci-lint findings in normalize.go

The Lint CI job (golangci-lint on go/) flagged two issues the wrapper
person-id normalization introduced: an else-after-return in coercePersonID
(revive indent-error-flow) and the now-orphaned normalizeJSON (superseded by
normalizeEmbeddedPeopleJSON, zero call sites). Lift the err decl out of the
if-init and drop the else; remove the dead function and update the two
comments that referenced it. golangci-lint reports 0 issues; go build/vet and
go test ./pkg/basecamp/... pass.

* scripts: enumerate complete direct-decode pair set

Adds 9 (wrapper, generated) pairs to directDecodePairs so the
field-level drift check covers every public wrapper struct that is
populated by raw json.Unmarshal rather than through a *FromGenerated
function:

  Account              -> Account
  AccountLogo          -> AccountLogo           (nested in Account.logo)
  AccountLimits        -> AccountLimits         (nested in Account.limits)
  AccountSettings      -> AccountSettings       (nested in Account.settings)
  AccountSubscription  -> AccountSubscription   (nested in Account.subscription)
  Preferences          -> Preferences
  OutOfOffice          -> OutOfOffice
  OutOfOfficePerson    -> OutOfOfficePerson     (nested in OutOfOffice.person)
  MyAssignmentsResult  -> GetMyAssignmentsResponseContent

Pair count moves from 55 to 64, generated fields verified from 859
to 903.

Records the derivation recipe in the directDecodePairs declaration so
the next contributor can rederive the set when new endpoints land:
grep raw-decode call sites, identify the ones that target a hand-
written wrapper (rather than a generated.X local routed through a
*FromGenerated function), check the generated package for a matching
counterpart, and add it plus any nested wrapper structs decoded with
their parent. Webhook-flavored parallel types and non-spec endpoints
(launchpad authorization, SDK provenance, error envelopes) are
explicitly out of scope and listed as such.

Adds TestRun_DirectDecodeRenamedPair driving run() end-to-end on the
renamed-pair shape (MyAssignmentsResult vs GetMyAssignmentsResponseContent)
so the runtime behavior of the broader-named pair entries is pinned.

* wrappers: route subscription subscribers through personFromGenerated

subscriptionFromGenerated still inlined a 6-field shallow Person copy
when building Subscription.Subscribers, so the BC5 Tagline plus the
Bio / Location / Title / PersonableType / AttachableSGID / access
flags / Company / timestamps that the rest of the wrapper layer
standardized on personFromGenerated never reached subscription
responses.

Routes the conversion through personFromGenerated to match every other
nested-Person context, and extends TestPerson_NewFields_NestedPropagation
with a subscription.Subscribers subtest so the propagation is pinned the
same way it is for recording/comment/message/todo/schedule_entry/card.

* docs(brief): align omit-marker syntax + BubbleUpAt pointer choice

Two edits keep the brief consistent with the shipped wrapper API and
drift-check implementation:

  * The omit-marker bullet documented a free-form
    'intentionally not surfaced because <reason>' phrasing that the
    drift check does not recognize. Rewritten to spell out the only
    syntax the check honors -
    'intentionally-omitted: <tag> - <reason>' with <tag> the JSON tag
    on the generated struct - and pointing readers at scripts/check-
    wrapper-drift's markerRe for the canonical regex.

  * The Notification.BubbleUpAt proposal still said time.Time and
    pointed at ReadAt/UnreadAt for the zero-value pattern. The shipped
    wrapper (commit 4ec355e) is *time.Time so an absent scheduled
    bubble-up omits the wire key cleanly instead of marshaling as
    0001-01-01T00:00:00Z (Go's omitempty does not suppress zero-valued
    time.Time). Brief now documents the *time.Time choice, names the
    Card.CompletedAt / Todo.CompletedAt precedent, and tells consumers
    to nil-check rather than IsZero.

* scripts: extend wrapper-drift map with inline-converted tier

The directDecodePairs map already covered wrappers populated via raw
json.Unmarshal (Notification, MyAssignment, ...). It did not cover a
third category: wrappers with a generated counterpart and no
*FromGenerated of their own that are populated inline via composite
literal inside a parent *FromGenerated body or a service method.

Codex named CampfireLineAttachment (built in campfireLineFromGenerated)
and EventDetails (built in eventFromGenerated). A wider scan of
go/pkg/basecamp/*.go intersected against go/pkg/generated/client.gen.go
turned up 12 such pairs. If BC5 adds a field to one of these generated
structs, the wrapper would silently drop the new data while the drift
check would pass — exactly the regression the check exists to catch.

Reorganize the map into three explicitly labeled tiers in one tag-
presence check so future contributors see the coverage as a single
surface:
 - Tier 1: *FromGenerated-backed (auto-discovered, both tag-presence and
   population checks)
 - Tier 2: direct-decode via json.Unmarshal (tag-presence only; the
   decoder populates from tags)
 - Tier 3: inline-converted via composite literal (tag-presence only;
   population enforced by review of the composite at the call site)

Rewrite the leading comment block to document the tier model, restate
the derivation recipe (re-scan all wrappers, intersect with generated,
subtract tier-1 and design exclusions, classify what is left), and call
out the out-of-scope list (webhook-flavored parallel types, non-spec
envelopes, outgoing request wrappers with name-clash to generated).

Extend the e2e test to cover a tier-3 pair end-to-end via
TestRun_InlineConvertedPair: confirms the pair is walked via the
injected map and the tag-presence check fires when the inline-converted
wrapper drops a tag the generated struct still emits.

Total pairs walked: 76 (was 64). Conformance-go: 68/0/0 unchanged.

* scripts: extend wrapper-drift walker to population-check tier 3

Tier-3 wrappers (inline-converted via composite literal — 12 of the 30
directDecodePairs entries) previously got the tag-presence check but not
the population check: the walker treated everything in directDecodePairs
as 'no body to walk' and gave the tier a reviewer-enforced floor. A
future generated field added with a matching wrapper tag but a missed
composite-literal update would have passed drift while the SDK silently
returned zero.

Add a composite-literal collector that scans every non-test file in
go/pkg/basecamp/ for literals of any tier3Wrappers type and feeds the
result into the existing population check the same way *FromGenerated
bodies feed for tier 1:

- Bare and pointer literals (Wrapper{...}, &Wrapper{...}) — both forms
  contribute the literal's KeyValueExpr keys.
- Local-bound writes (resp := Wrapper{...}; resp.X = ...) and
  selector-chain bindings (q.Schedule = &Wrapper{...};
  q.Schedule.X = ...) — subsequent selector writes against any path the
  literal is bound to are attributed to the wrapper. The selector-chain
  binding is what makes the QuestionSchedule shape (where six fields are
  set in the literal and three more by conditional q.Schedule.X writes)
  pass the population check end-to-end.

tier3Wrappers is a sentinel set listing the 12 tier-3 names (kept in
sync with the tier-3 section of directDecodePairs). The population-check
gate flips from 'skip if directDecode' to 'skip only if tier 2', so the
existing tier-2 path (raw json.Unmarshal — tag presence is population)
is unchanged.

run() gains a tier3 parameter so tests can drive end-to-end fixtures
without dragging in the production tier-3 set, mirroring the existing
directDecode injection.

Pair count stays 76; field-assignments-verified jumps from 757 to 818
(61 new tier-3 assignments — exactly the gap the prior reviewer-floor
left open).

* scripts: regression tests for tier-3 composite-literal walker

Covers the two construction forms (pointer Field: &Wrapper{...} and
bare Wrapper{...}) and the two binding shapes (bare local resp.X = ...
and selector chain q.Schedule.X = ...) that the tier-3 corpus uses, plus
the dropped-assignment teeth proof for each literal form.

Unit tests for the new helpers (collectCompositeLiteralFields,
exprToPath, pathPrefixAndField) cover identifier roots, deep selector
chains, and non-identifier-rooted expressions (calls, index expressions)
that the walker must safely ignore.

* scripts: run wrapper-drift tests as part of the make target

The go-check-wrapper-drift target only invoked `go run` on the checker, so
`scripts/check-wrapper-drift/main_test.go` (incl. the new tier-3 walker
regression tests) was never exercised by `make check` or CI's gate — the
walker could silently regress while drift kept reporting clean. Run
`go test ./scripts/check-wrapper-drift/` as the first step of the target so
test failures surface before the drift check itself runs.

* wrappers: extend required-bool serialization test to Inbox/Forward/ForwardReply/TimesheetEntry

The PR dropped omitempty from non-omitempty bool response fields on these four
wrappers alongside Todo/Comment/Message/MessageBoard, but the regression test
only pinned the latter four. Symmetric coverage: add the four missing cases so
a future accidental re-introduction of omitempty on any of these wrappers
fails the test instead of silently dropping false on the wire again.

* wrappers: delegate ProjectConstruction.Project to projectFromGenerated

The inline `&Project{...}` literal in projectConstructionFromGenerated
predated the audit and silently dropped StartDate, EndDate, ClientsEnabled,
BookmarkURL, Dock, Bookmarked, ClientCompany, and Clientside — fields the
helper already converts. Composite-literal population checking only runs
for tier-3 wrappers, so a literal for a type that also has a tier-1 helper
escaped the walker. Delegating to the helper closes the gap the same way
nested Person sites were standardized on personFromGenerated; a scan for
other inline wrapper literals outside their helpers found no other sites.
jeremy added a commit to robzolkos/basecamp-sdk that referenced this pull request Jul 22, 2026
…reate-bucket-scope-20260601145434

* origin/main: (28 commits)
  Upstream sync: repin provenance to bc3 ba105ba7 (2026-07-22), register post-train contracts, codify pin semantics (basecamp#390)
  ci: pin conformance uv sync to the matrix Python; parse the fan-in gate (basecamp#388)
  BC5 readiness: pairwise BC4↔BC5 + check-bc5-compat orchestrator + scheduled CI (basecamp#308)
  CI: fold conformance suites into their language test jobs (basecamp#387)
  Fix TypeScript SDK Content-Type on GET requests (basecamp#384)
  BC5 launch reconciliation: registry refresh for the shipped BC5 API train (basecamp#325)
  BC5 readiness: cross-language wire-replay decoders (basecamp#301)
  BC5 readiness: Go wrapper forward-compat audit + field-level drift check (basecamp#309)
  BC5 readiness: TypeScript live wire-capture canary (basecamp#294)
  BC5 readiness: forward-compat spec, briefs, parity lint (basecamp#293)
  deps(ts): bump brace-expansion from 5.0.2 to 5.0.7 in /typescript (basecamp#386)
  typescript: bump fast-uri, brace-expansion, js-yaml overrides for fresh advisories (basecamp#385)
  deps(actions): bump the actions group with 6 updates (basecamp#382)
  deps(ruby): bump the bundler-dependencies group in /ruby with 2 updates (basecamp#379)
  deps(kotlin): bump the gradle-dependencies group (basecamp#383)
  deps(go): bump github.com/oapi-codegen/oapi-codegen/v2 in /go (basecamp#381)
  deps(ts): bump the npm-dependencies group in /typescript with 2 updates (basecamp#380)
  deps(smithy): bump the smithy-gradle-dependencies group (basecamp#378)
  deps(go): bump github.com/oapi-codegen/runtime (basecamp#377)
  Todos Update/Edit/Replace: merge-safe writes across all 6 SDKs (basecamp#375)
  ...

# Conflicts:
#	go/pkg/basecamp/api-provenance.json
#	go/pkg/basecamp/version.go
#	go/pkg/generated/client.gen.go
#	kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/BasecampConfig.kt
#	openapi.json
#	python/src/basecamp/_version.py
#	ruby/lib/basecamp/generated/metadata.json
#	ruby/lib/basecamp/generated/types.rb
#	ruby/lib/basecamp/version.rb
#	spec/api-provenance.json
#	spec/basecamp.smithy
#	swift/Sources/Basecamp/BasecampConfig.swift
#	typescript/src/client.ts
#	typescript/src/generated/metadata.ts
#	typescript/src/generated/openapi-stripped.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file enhancement New feature or request go kotlin 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