Skip to content

feat: adopt signed AdCP 3.3.0-beta.3 and serve the reporting-subscription surface - #3559

Merged
bokelley merged 4 commits into
mainfrom
bokelley/reporting-subscription-beta3
Oct 31, 2026
Merged

bokelley merged 4 commits into
mainfrom
bokelley/reporting-subscription-beta3

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Summary

Adopts the signed AdCP 3.3.0-beta.3 release and serves its reporting-subscription surface: T1(a) of the reporting-subscriptions DX plan (#3504).

Stacks on #3557 (bokelley/reporting-subscription-dx-docs, the top of the #3504 stack) plus a clean merge of origin/main. It targets main so CI runs; the diff against main includes the whole stack.

Review these commits:

  • 5e35609e feat: adopt signed AdCP 3.3.0-beta.3 and serve the reporting-subscription surface
  • 4e881b08 fix: carry the task status on terminal webhook results and update fixtures for beta.3
  • (9924a4b4 merges origin/main; no conflicts)

The engine rules beta.3 adds (#8617, #8618, #8619, #8620, #8622) land in the follow-up PR on bokelley/reporting-subscription-beta3-engine.

Release

  • v3.3.0-beta.3, spec commit a6106149a2b5c929eec0caa0042adbae4ccf3a9c
  • Bundle SHA-256 ba61919ca0c9d67874604fbbca8945c133eaceed65da1ac962f78d94d7879f00, cosign-verified (ADCP_REQUIRE_SIGNATURE=1 ADCP_GITHUB_FALLBACK=0)
  • The pin is 3.3.0-beta.3, and the wire version is 3.3-beta.3.

Warning

Beta-channel break. The SDK advertises and negotiates only 3.3-beta.3. A beta.2 peer (SDK 17.0.0-beta.10) falls back to a shared stable release (3.2.7, 3.1.31 or 3.0.25). An explicit adcpVersion: '3.3.0-beta.2' pin now throws.

What changes

Signed sync and generated files (following #3541)

  • ADCP_VERSION, version.ts, package.json (adcp_version and the packaged compliance cache).
  • Regenerated: types, Zod, enums, manifest, entity hydration, wire-spec fields, llms.txt, TYPE-SUMMARY.md and the worksheet.
  • Canonical storyboard provenance moves to the beta.3 tag and commit. The principal.yaml and reporting-core.yaml bytes are unchanged.
  • The A2A vectors are byte-identical; only the README provenance changed.
  • Commercial-terms semantics: beta.3 carries the beta.2 contracts, which I checked against the bundle. The beta.3 entry reuses the beta.2 one.

Reporting subscriptions

  • wire.ts and every TODO(3.3.0-beta.2) are deleted. The generated ReportingDeliveryOffering, ReportingSubscriptionCoverage and ReportingSubscriptionState carry all of these fields:

    • standard_dimensions
    • inactive_intervals
    • prior_versions[].configuration
    • previous_timezone
    • per-offering offering_id
    • status: inactive with deactivated_at

    ReportingSubscriptionOfferingV1 is now an alias of ReportingDeliveryOffering. The wire.ts file-budget line is dropped.

  • authorization.regranted_at joins ACCOUNT_AUTHORIZATION_WIRE_KEYS, which unblocks the spec repo's "Generate TypeScript SDK" check. toWireAccount and windDownGrant keep it.

  • Readback totals (adcp#8619). Without these, beta.3 responses fail validation.

    • prior_versions_count, accounts_with_exceptions_count and accounts_unauthorized_count are served.
    • prior_versions is capped at 16 inline.
    • Each total is gated on the served bundle, like the other settled fields.
  • Release gate. It is kept for callers served older releases. It now resolves local #/definitions refs, because beta.3 names its item shapes. A response with no served release uses the pinned release, which matches Python's serves_subscriptions and plan §3.1. So inactive coverage is now served to beta.3 callers and to unpinned direct calls.

Canonical vectors

  • Re-pinned to a6106149 (tag v3.3.0-beta.3; main is identical for this directory) with npm run sync:reporting-subscription-vectors.
  • vectors.json sha256 is 56cc381b…, and there are 120 cases.
  • 111 cases pass. The 9 the engine doesn't satisfy yet are named expected failures in EXPECTED_FAILURES. Each still runs and must fail, so a fixed case fails the suite until its entry is removed. Each entry names its spec PR (#8617 ×2, #8618 ×3, #8619 ×1, #8622 ×3). The engine PR removes them all.

Beta.3 contracts outside reporting (#8547 composes the protocol envelope on every response)

  • Codegen: proposal submitted arms. materializeProposalResponseBranches now folds the allOf members of a referenced arm. In beta.3, compact-task-submitted.json composes task-submitted.json, so the submitted arms of request_proposals, refine_proposals and decline_proposals keep status: 'submitted' and the required task_id. Before this fix, a completed refine response with no products passed Zod.

  • Codegen: Zod constraints. postProcessCanonicalPrimitiveConstraints follows core $refs and envelope-in-envelope composition. Generated responses keep their constraints on adcp_version, adcp_major_version, top-level task_id and message. Before this fix, 82 response schemas had dropped the adcp_version regex.

  • Server: terminal webhook result. On 3.1+ it now carries the task status, as a synchronous response does. A lifecycle value in status moves to media_buy_status. A 3.2 list_products/decline_proposals result or a 3.0 result is unchanged.

  • Notifications. creative.staged_update_changed joins ACCOUNT_NOTIFICATION_TYPES.

  • Test fixtures. They now follow the beta.3 contracts:

    • status on every 3.3 response
    • request_account money terms (#8620)
    • confirmed_at/revision on a completed create
    • the canonical-format product seeded through comply_test_controller
    • validation-only storyboard steps

    Version pins read ADCP_VERSION where possible.

Checks

  • Signed sync of 3.3.0-beta.3.
  • typecheck, build:lib, lint:boundaries, ci:codegen-strict, check:skill-sync, ci:doc-links and check:canonical-storyboard-fixtures all pass.
  • check:publish-protocol-artifacts, typecheck:examples, typecheck:skill-examples, check:adopter-types(-narrow), test:zod-openapi-portability and test:schemas-browser also pass, as does Prettier on the changed files.
  • check:package-size: 26,825,751 bytes packed (25.6 MiB), 140.6 MiB unpacked, 8,528 files. The packed budget goes to 26,870,000 and the file count rises by 21 (eleven new source schemas plus storyboards), with comments.
  • test:node:fast: 24,026 tests locally, all passing on this head. test:node:slow: passes. @adcp/reporting-storage: 177 passed and 1 skipped. Postgres-only cases run in CI.

Spec ambiguities and deviations

  • Absent served release. TS used to serve none of the settled fields when no release was negotiated. It now uses the pin, as Python and plan §3.1 do.
  • decline_proposals without status at 3.3. The buyer coordinator and the oracle treat it as the seller's defect and don't fill it in, as the envelope shim documents. They don't copy request_proposals' lenient normalization.

🤖 Generated with Claude Code

bokelley and others added 3 commits October 31, 2026 11:03
…tion surface

Replace the 3.3.0-beta.2 pin with the signed 3.3.0-beta.3 bundle (spec commit
a6106149, sha256 ba61919c..., cosign-verified). The SDK now advertises and
negotiates only 3.3-beta.3; beta.2 peers fall back to a shared stable release.

- Regenerate types, Zod schemas, manifest constants, wire-spec fields and docs.
- Delete the hand-modelled reporting wire types (wire.ts) and every
  TODO(3.3.0-beta.2): the generated types carry standard_dimensions,
  inactive_intervals, prior_versions[].configuration, previous_timezone,
  per-offering offering_id and status inactive with deactivated_at.
- authorization.regranted_at joins the account authorization wire keys;
  toWireAccount and windDownGrant keep it.
- Serve the readback totals (prior_versions_count, accounts_with_exceptions_count,
  accounts_unauthorized_count) and cap prior_versions at 16 inline (adcp#8619),
  gated by the served bundle like the other settled fields. The gate follows
  local $refs and treats an absent served release as the pin, as Python does.
- Re-pin the canonical coverage vectors to v3.3.0-beta.3; the nine cases the
  engine does not satisfy yet are named expected failures.
- Codegen: fold composed members of a referenced proposal arm so the submitted
  arm keeps status submitted and task_id, and restore envelope-inherited Zod
  constraints through core $refs.
- Commercial-terms semantics: beta.3 carries the beta.2 contracts.
- creative.staged_update_changed joins ACCOUNT_NOTIFICATION_TYPES.
- Tests follow the beta.3 contracts (status on every 3.3 response, account
  request money terms, seeded canonical-format products) and read ADCP_VERSION.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tures for beta.3

A terminal task webhook's result is the task's full response, so on 3.1+ it
carries the task status like a synchronous one; a media-buy lifecycle value in
status moves to media_buy_status as on the synchronous path. 3.2
list_products/decline_proposals and 3.0 results are left as returned.

Give the multi-tenant example's governance responses their now-required status,
and make the async discovery and webhook fixtures schema-complete.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
aao-secretariat[bot]
aao-secretariat Bot previously approved these changes Oct 31, 2026

@aao-secretariat aao-secretariat 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.

Ladon verdict: Approve

Approve — beta.3 delta is clean, no blocking findings.

Reviewed the beta.3-specific delta (commits 5e35609, 4e881b0 over the merged #3504 stack); generated files and the already-reviewed stack excluded.

What was checked:

  • commercial-terms: clean extract-and-reuse of beta.2 semantics for beta.3.
  • Codegen fixes (foldComposedOverlay, $ref-following primitive()) recover composed-envelope status/task_id/adcp_version constraints, gated by ci:codegen-strict.
  • Terminal-webhook status change (webhookResultForRelease) is conservative — no-ops on undefined/pre-3.1/envelope-omitting releases; media_buy_status move is tested in server-decisioning-from-platform.test.js.
  • Release-gate default flip (undefined served → pinned release, not NONE) is a documented deviation aligned with the Python SDK (DR-0008 canon).
  • Readback counts (adcp#8619) set at build and projected per release; canonical-vector EXPECTED_FAILURES discipline (9 named must-fail cases, crashes still surface) is correct.
  • Changeset present, minor, with a prominent beta-break note consistent with #3541.

High-risk note: high_risk is true only because bin/adcp.js was modified. Per the change-kind rules a (modified) high-risk file with no medium-or-higher findings is presumed safe; it does not escalate on the flag alone.

Low (non-blocking) follow-up: prior_versions capped at 16 unconditionally while prior_versions_count is stripped for releases lacking it — a silent truncation for an older external schema root, but unreachable via negotiation since beta.1/beta.2 left COMPATIBLE_ADCP_VERSIONS.

No gated paths, no no-auto-approve team match, no critical/high/medium findings. Falls through to row 9.

Copy link
Copy Markdown
Contributor Author

Thanks. On the low note (prior_versions capped at 16 while prior_versions_count is stripped for a release without it): agreed that it only affects an older external schema root, since beta.1 and beta.2 left COMPATIBLE_ADCP_VERSIONS. The engine follow-up (bokelley/reporting-subscription-beta3-engine) adds get_principal reporting_subscription_page, which pages the full prior_versions list from history at the pinned release. I'm leaving the older-root case as is: those roots have no paging and no count field to signal truncation.

🤖 Generated with Claude Code

bokelley added a commit to adcontextprotocol/adcp-client-python that referenced this pull request Oct 31, 2026
…e regranted_at

Align with adcontextprotocol/adcp-client#3559 and #3560:

- resolve_reporting_subscription_package, the TypeScript
  resolveReportingSubscriptionPackageV1, is the sticky per-package
  resolution the buyer and the seller share, exported from
  adcp.reporting.advanced.
- assert_reporting_task_granted, the TypeScript assertReportingTaskGrantedV1,
  refuses a task a resolved account's grant leaves out with
  SCOPE_INSUFFICIENT.
- A host reports a re-grant inside the chain as authorization.regranted_at,
  as AuthorizedAccount.regranted_at or GrantObservation.regranted_at. The
  grant journal dates the re-grant from it when it falls between the loss
  and the observation. authorized_at keeps the chain start.
- grant-cases.json is the TypeScript copy: the re-grant step names
  regranted_at, not the engine-only granted_at.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@bokelley
bokelley dismissed aao-secretariat[bot]’s stale review October 31, 2026 14:22

The merge-base changed after approval.

@aao-secretariat aao-secretariat 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.

Re-approval: no reviewable delta since the prior approval; re-submitting after stale-review dismissal.

@bokelley
bokelley merged commit 71227f4 into main Oct 31, 2026
45 checks passed
@bokelley
bokelley deleted the bokelley/reporting-subscription-beta3 branch October 31, 2026 19:33
bokelley added a commit that referenced this pull request Oct 31, 2026
…it merges (#3565)

#3559/#3560 (AdCP 3.3.0-beta.3) and #3564 (creative package-fit decisions)
landed in parallel. #3564's test pinned adcpVersion 3.3.0-beta.2, which the SDK
no longer bundles, and its published guide put the package one file over
#3559's exact file-count budget. Read ADCP_VERSION in the test, count the guide,
and raise the packed cap to cover the combined size plus the release PR's
CHANGELOG growth.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bokelley added a commit that referenced this pull request Nov 1, 2026
…adroom (#3568)

* fix(packaging): stop shipping duplicate compliance and declaration bytes

Trim @adcp/sdk from 26,862,556 to 24,993,401 packed bytes (8,529 to
8,176 files) without changing runtime behavior:

- Exclude compliance/cache/*/domains/ from the package. Every bundle's
  domains/ is a byte-identical copy of protocols/, the only directory the
  storyboard loader reads (-286,556 bytes, -353 files).
- Emit one-line ESM facades for the type-only generated declarations
  (types/core.generated, types/tools.generated, registry/types.generated),
  as types/schemas.generated already did, instead of copying 5.7 MB of
  declarations (-1,174,602 bytes).
- Store the self-contained MCP tools/list request projections as compact
  JSON. They are only ever JSON.parse'd (-407,997 bytes).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ci(packaging): size budgets with headroom and a per-PR growth check

The packed-byte and file-count budgets were pinned to the measurement, so
two PRs that each added a file or a few KB passed alone and broke main
together (#3510 + #3541, #3564 + #3559/#3560). Replace the pins with:

- Ceilings with headroom in scripts/package-size-budget.json: @adcp/sdk
  26,000,000 packed bytes / 135,000,000 unpacked / 8,450 files against a
  measured 24,993,401 / 129,047,083 / 8,176 (about 4%), and
  @adcp/reporting-storage 490,000 / 2,250,000 / 150. A warning fires when
  less than two PRs' allowance of headroom is left.
- A per-PR growth check. main caches each commit's measurement; a pull
  request compares itself with the record for its exact merge base and may
  add 100 KB / 25 files to the SDK (15 KB / 8 files to the storage
  package). More needs the same PR to raise the ceiling, so the growth is
  reviewed in the diff. A missing record skips only this comparison.
- The focused-client eager graph count becomes a ceiling (230, measured
  216) instead of an exact pin; the named heavy-module exclusions stay.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant