Repository navigation
feat(protocol)!: adopt the signed AdCP 3.3.0-beta.0 bundle - #1662
Conversation
66bbc41 to
8967f6b
Compare
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — packaging/docs/schema-bundle pass with no blocking findings.
This pass is confined to docs, packaging (MANIFEST.in, pyproject.toml), auto-generated shared-type-names.md, and the pinned signed AdCP 3.3.0-beta.0 bundle bytes. No hand-written source changed; the source wiring was prior-reviewed. Packaging is complete and consistent: the new 3.3.0-beta.0 cache/_schemas/_compliance trees are added to both MANIFEST.in and package-data, and retired _identity_schemas/_identity_preview entries are removed from both package-data and the ruff exclude.
Decision-table walk: the high_risk flag is true only because many new schemas/** files are added (plus three renames) — all (added)/(renamed), no (deleted) and no modified high-risk file carrying a medium finding, so rows 3 and 5 do not fire. gated_paths is false and no no-auto-approve team matches. No critical/high/medium findings. Only two Low doc-accuracy nits recorded, which are omitted from blocking but noted below. Falls through to row 9 → approve.
Nits (non-blocking):
- docs/adcp-3.3-sdk-inventory.md:143 — inventory status for list_collections/list_proposals contradicts PR body's "wired" claim.
- MIGRATION_v9_to_v10.md:53 — PositiveDuration/Domain RootModel→ScalarStr (.root removed) shape change not mentioned in the migration note (semver signal otherwise present via feat!/BREAKING CHANGE).
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — AdCP 3.3.0-beta.0 bundle adoption, subsequent pass with no actionable findings.
The delta is overwhelmingly generated artifacts (schema cache under schemas/cache/3.3.0-beta.0/**, domain types, conformance vectors). The reviewer verified the hand-written layer:
- New
list_collections/list_proposalswiring across client/base/mcp/a2a/builder/mcp_tools/types — consistent and complete. compat/versions.pytranslation (_admits_version_envelopesafe;is_convertible_versionmatches documented prerelease design)._forward_compat.pyoperation_id retirement verified against 3.3 schema constraints.decisioning/accounts.pyloader fail-closes on id mismatch with multi-tenant scoping documented.post_generate_fixes.pyregex_engine preservation intact.- Semver signal present (
feat(protocol)!+ BREAKING CHANGE footer +MIGRATION_v9_to_v10.md); pathway-back rule satisfied (product_ids_exclusive refused, dropped default recorded as loss).
Decision-table walk: no critical/high/medium findings (row 1 no). gated_paths=false (row 2 no) and review_decision is APPROVED regardless. High-risk flag is true but all reasons are (added) scaffolding or (renamed) codegen churn — no (deleted) (row 3 no), no medium findings to pair with (rows 4/5 no). Prior decision was approve, not escalate (row 6 no). No no-auto-approve team match (row 7 no). Zero medium findings (row 8 no). Falls through to row 9 — approve. Clean net-improvement iteration on top of a prior clean approve.
8967f6b to
0d27045
Compare
|
Ladon cannot review this PR until merge conflicts are resolved. |
0d27045 to
2ade6f8
Compare
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — AdCP 3.3.0-beta.0 migration delta, clean pass.
The reviewer found no critical/high/medium findings. Checked:
- Walked the decision table top-down. No critical/high findings (row 1 no), gated_paths is false (row 2 no), no
(deleted)entries in high_risk_reasons — only(added)and(renamed)(rows 3 no). No medium findings at all, so rows 4/5/8 don't fire. Prior decision wasapprove, notescalate, so row 6 doesn't apply. No no-auto-approve team match (row 7 no). Falls through to row 9 → approve. high_risk: trueis driven entirely by added/renamedschemas/cache/**codegen artifacts — new-file scaffolding and traversal-order renumbering, which the rules explicitly treat as normal non-escalation-worthy churn when the reviewer surfaces no medium-or-higher concerns.- Hand-written logic (version-line translation, brand_jwks bounds/timeouts, JSON bounds scanner, webhook_receiver, forward-compat retirement, pixel_tracker) all verified clean; breaking public-surface changes carry the
feat!/BREAKING CHANGE semver signal;video_briefroutes correctly in both asset unions and vocabularies.
No blocking findings, no medium findings, no escalation trigger.
2ade6f8 to
7b9a89f
Compare
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean pass on PR #1662.
No critical/high/medium findings. Walking the decision table top-down:
- Row 1 (critical/high): no findings — skip.
- Row 2 (gated_paths unsatisfied): gated_paths is false, and review_decision is APPROVED anyway — skip.
- Row 3 (high-risk deleted): high_risk is true, but all high_risk_reasons entries are
(added)or(renamed); no(deleted)— skip. The renamedcore/agent-onboarding*entries are treated as modifications, not deletions, and carried no findings. - Row 4 (medium data-loss/schema/infra): no findings — skip.
- Row 5 (high-risk modified + medium): no medium findings — skip.
- Row 6 (sticky escalate): prior decision was
approve, not escalate — skip. - Row 7 (no-auto-approve team): no team match — skip.
- Row 8 (≥3 medium): zero medium — skip.
- Row 9: approve.
The high_risk flag fires only because the diff adds the 3.3.0-beta.0 schema cache tree (schemas/**), which is normal scaffolding/regeneration output — not an escalation trigger. The reviewer verified the hand-written delta: the ADCP_VERSION 3.2.4 → 3.3.0-beta.0 bump carries the correct feat(protocol)!: breaking marker plus MIGRATION_v9_to_v10.md; new list_collections/list_proposals tasks are fully wired and snapshot-tested; cross-version translation helpers are covered at both transport boundaries down to 3.0/3.1; _forward_compat.py changes and the open asset-union vocabulary check out. Prior pass was clean and remains so.
7b9a89f to
aa56bf1
Compare
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean 3.3.0-beta.0 adoption with no findings.
No critical/high/medium findings surfaced. The delta since the prior approve is a rebase + full regeneration (gen date 2026-10-26); the ClassNameN renumber churn is codegen, not a schema delta.
Checks verified by the reviewer:
- Load-bearing version-translation logic (compat/versions.py
_wire_for_line/is_convertible_version/_admits_version_envelope) correctly steps 3.3-beta.0↔3.2↔3.1↔3.0 and dropsadcp_versiononly where the target contract forbids it (list_products), with matching cross-version + logging tests — DR-0032/DR-0033 pathway coverage present. - signing/autosign.py clamps 3.3 to the 3.2 RFC 9421 profile.
- reporting_webhook.operation_id / identity-preview forward-compat retirements are backed by the generated 3.3 class carrying the same constraints + NoExplicitNull — no fallback arm lost.
- Semver signal present (feat!: + BREAKING CHANGE squash, MIGRATION_v9_to_v10.md).
- No generated-tree hand-edits, no credentials in ctx_metadata, import layering intact, CI gates armed.
Gating posture: high_risk is true, but all schema matches are (added) or (renamed) (treated as modification) scaffolding/regeneration with no medium-or-higher finding on them, so rows 3–5 do not fire. gated_paths is false and review_decision is APPROVED. No no-auto-approve team match. Prior decision was approve, so sticky escalation (row 6) does not apply. No findings → rows 1, 8 do not fire. Falls through to row 9 = approve.
8d8a66c to
2bcd3a4
Compare
Pin src/adcp/ADCP_VERSION to 3.3.0-beta.0 (schemas/releases/3.3.0-beta.0.json: source a2d7eac3, release.yml@refs/heads/main, sha256 and cosign verified), regenerate the types from its schemas, package the 3.3.0-beta.0 schema cache and compliance bundle, and keep the signed 3.2.4 bytes installed as the 3.2 contract (PREVIEW_VERSIONS) beside 3.1.27. Advertise 3.3 as the exact pre-release (3.3-beta.0), negotiate and translate the 3.3 line through the bundled schemas (3.3-beta.0 <-> 3.2 <-> 3.1 <-> 3.0), and let a server restricted to older supported_versions pin to its newest listed release. Map the 3.3 line to the 3.2 RFC 9421 signing profile; the profile's 3.3 deprecation warns by default. Retire the identity preview (adcp.types._identity_preview, the vendored _identity_schemas tree and scripts/generate_identity_preview.py): the bundle declares those schemas, so adcp.types.experimental_identity binds the generated 3.3 types and adcp.signing.trust validates against the bundle. Retire the reporting_webhook.operation_id runtime patch (native since 3.3, adcp#7895). Wire list_collections and list_proposals through the client, handler, adapters, CLI and MCP tool definitions; add the 3.3 test-controller params and scenarios. Generator: scalar roots whose pattern needs lookaround keep the python-re engine (PositiveDuration, Domain); the canonical direct scan reads scalar and root-model values as the dump would. BREAKING CHANGE: the wire pin is AdCP 3.3.0-beta.0 (adcp_version "3.3-beta.0" by default; pin adcp_version="3.2" for a 3.2 contract). adcp.types.UniversalMacro is a RootModel union; the closed enum is UniversalMacro3. The identity preview modules are removed and adcp.types.experimental_identity binds the generated 3.3 types (RequestSigning.profiles is list[Profile], PrincipalChangedWebhook.reason is the generated enum). adcp.signing.identity_schema_bundle is removed. Legacy RFC 9421 SigningConfig / RequestSignatureVerification construction emits a DeprecationWarning. evaluator_id is gone from evaluator specs. See MIGRATION_v9_to_v10.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2bcd3a4 to
f701081
Compare
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — subsequent clean pass on the AdCP 3.3 upgrade.
No critical/high/medium findings. Walking the decision table top-down:
- Row 1 (critical/high): no such findings.
- Row 2 (gated_paths): gated_paths is false; also review_decision is APPROVED. Not triggered.
- Row 3 (high_risk + deleted): high_risk is true, but the high_risk_reasons entries are all
(added)or(renamed)— no(deleted). Renames of a few core schema files are codegen churn, not destructive. Not triggered. - Row 4 (medium + data-loss/schema/infra): no medium findings.
- Row 5 (high_risk modified + medium): no
(modified)entries carry a medium finding (no mediums at all). Not triggered. - Row 6 (sticky escalate): prior decision was approve, not escalate. Not triggered.
- Row 7 (no-auto-approve team): no team match.
- Row 8 (≥3 mediums): zero mediums.
- Row 9: approve.
The high-risk flag fires only because the diff touches schemas/** cache files — these are added/renamed generated schema cache artifacts (AdCP 3.3.0-beta.0), normal scaffolding/regeneration output, not escalation-worthy on the flag alone.
Reviewer verified the load-bearing contracts: semver signal (9→10 major carries ! + BREAKING CHANGE + MIGRATION note), forward-compat unions (no fallback arm removed, discriminator intact), the version-translation pathway (droppable/refused/moves handled with tests), and A2A fail-closed hardening. One Low nit in scripts/post_generate_fixes.py (unused extra_constraints) is non-blocking and omitted from the gate.
Closes #1560. Follows the main → next sync (#1578) and the inventory (#1660). Squash-merge, keeping the
!and theBREAKING CHANGE:footer from the commit message (below).The bundle
schemas/releases/3.3.0-beta.0.jsonpins the signed release: source commita2d7eac350f0325331ae544bc071301afe01d2f2, identityrelease.yml@refs/heads/main, four artifacts with sizes and sha256. Verified locally as the release notes prescribe:sha256sum -cOK andcosign verify-blob"Verified OK" against that identity;scripts/sync_schemas.py --require-signed-releasere-verifies the same four artifacts and the signature on every sync.src/adcp/ADCP_VERSIONis3.3.0-beta.0; the bundle key keeps the full identifier (schemas/cache/3.3.0-beta.0,src/adcp/_schemas/3.3.0-beta.0,src/adcp/_compliance/3.3.0-beta.0: 4443 manifest files, 242 provenance files), withMANIFEST.inandpackage-dataentries, so the protocol repo's "Generate Python SDK" check finds the pinned key. The signed 3.2.4 bytes stay installed underschemas/cache/3.2as a preview bundle (PREVIEW_VERSIONS = ("3.2.4", "3.1.27")) for negotiation and translation with 3.2 peers.SCHEMA_DELTAS.md); the numbered-class churn in it is a consequence of new sibling schemas and cannot be discarded. No hand-written module referenced a removed numbered name.make validate-generatedis deterministic on the new tree.skills/adcp-media-buy/SKILL.md, the request-signing conformance vectors (130 files, manifest pinned), the 3.3 compliance package.Version negotiation and translation
COMPATIBLE_ADCP_VERSIONSadds3.3;get_supported_adcp_versions()advertises the exact pre-release3.3-beta.0(never a stable3.3):3.0, 3.1, 3.2, 3.3-beta.0, 3.2-rc.7.adcp.compat.versionsconverts the 3.3 line: the SDK's served pre-release is its line's representative (_wire_for_line), so3.3-beta.0 ↔ 3.2 ↔ 3.1 ↔ 3.0step through the bundled schemas; any other pre-release keeps its own contract (is_convertible_version). Downgrades still go through_require_target_valid(3.2 to 3.1 conversion emits payloads 3.1 refuses: empty notification event_types, and geo_regions as {} #1621 / fix(compat): never downgrade into a payload the older schema refuses #1630): a converted payload the older schema refuses fails asADCPVersionConversionError. The version envelope is stamped only where the target contract admits it: 3.3 addedadcp_versiontolist_productsresponses, whose 3.2 schema forbids it._convert_outgoing_requestno longer treats it as a historical pin), and aserver_versionpin keeps wire precision ("3.1.0-beta.1"→"3.1-beta.1"), so a pre-release pin is never echoed as its bundle key.supported_versionswithoutadcp_versionpins to its newest listed release (version_policy.default_adcp_version) instead of refusing because the SDK default moved past it. The decisioning capabilities gate (startswith("3.2")) is now "3.2 or later".rfc9421_deprecation_active()is now true by default, so legacySigningConfig/RequestSignatureVerificationconstruction warns, as 3.3 deprecates those profiles.Forward-compat patches retired (each verified against the 3.3 schema)
reporting_webhook.operation_id(adcp#7895):core/reporting-webhook.jsondeclares it withminLength1,maxLength255 and the same pattern, optional, never null. The_forward_compat.pyruntime patch and_ReportingOperationIdare deleted;ReportingWebhookand the request facades bind the generated classes.tests/test_reporting_webhook_operation_id.pypasses unchanged.list_creativescreatives[].platform_id(adcp#8175): native in 3.3 (Creative.platform_id). This SDK carried no forward-compat patch for it, so there was nothing to retire.canonical_creativescapability patch (3.3 does not declare it), the targeting-overlay rc.3 bridge and the readback manifest patches.Identity preview retired
The vendored identity schemas (
src/adcp/signing/_identity_schemas/, adcp main277e0a5) are semantically identical to the bundle's (only$refprefixes differ), soadcp.types._identity_preview, the vendored tree andscripts/generate_identity_preview.pyare deleted.adcp.types.experimental_identitykeeps every exported name on the generated 3.3 types;AgentOnboardingRequirement.kindstays open (enum | str, the schema enum isx-extensible) throughinherit_fieldredeclarations down the capabilities tree, with one exemption recorded intests/test_redeclared_fields_inherit.py.adcp.signing.trustvalidates trust records and requirement kinds against the bundle throughget_named_validator/get_named_schema_document;identity_schema_bundle()is gone.3.3 task surface
list_collectionsandlist_proposalsare wired throughADCPClient,ADCPMultiAgentClient,ADCPHandler(not-supported defaults), the MCP and A2A adapters, the CLI dispatch and the MCP tool definitions, the waylist_productsis. The test controller gains the 3.3simulate_deliveryparams (property_delivery,installment_delivery,installment_property_delivery) and the four new scenarios, raisingNotImplementedErrorlike every other unimplemented scenario.sales-fixed-ratejoins the specialism enum and maps.Generator
model_config = ConfigDict(regex_engine="python-re");_scalar_root_specnow keeps that engine as a constraint, soPositiveDurationandDomainbecomeScalarStrsubclasses like every other scalar root.UniversalMacrois aRootModelunion in 3.3 (enum |GDPR_CONSENT_<gvl_id>pattern); the canonical direct scan reads scalar-root and root-model values as the dump would instead of falling back to a full dump.Reporting
The production and feed code derived wire versions correctly once the client stopped echoing bundle keys;
feed/snapshot.py's unversioned-walk branch accepts any served release at or above 3.2-rc.6 instead of a literal 3.2 set. The production reporting mount still advertises exactly its pin, so an SDK 10 mount on the default pin refuses 3.2 buyers unless constructed withadcp_version="3.2"(flagged for workstream 3 in the inventory). The receipt-submission plan stays tagged 3.2 (frozen bytes).Breaking changes (see
MIGRATION_v9_to_v10.md)Wire pin 3.3.0-beta.0 and default
adcp_version: "3.3-beta.0";UniversalMacrounion (UniversalMacro3is the enum); the identity preview modules removed andexperimental_identitybound to generated types (RequestSigning.profiles: list[Profile],PrincipalChangedWebhook.reasonis the generated enum);identity_schema_bundle()removed; RFC 9421 construction warns;evaluator_idgone from evaluator specs;server_versionpins keep wire precision; schema defaults appear in dumps for the new 3.3 fields (include_collections,hold_extension); delivery rows may omitimpressions.For workstream 2 (first items)
get_productsrequest carriesinclude_collections: false, which a 3.3 → 3.2 downgrade drops with a recorded loss and a buyer-side warning per request, andcriteria.product_ids_exclusive: falsehad to be special-cased on the legacy catalog route. Dumping outgoing requests with "what the caller set" semantics would remove the class.x-extensibleenums generate closed (agent-onboarding-requirement-kind,advertiser-industry,media-buy-action-mode); the identity facade widens one by hand.v33versioned view modules yet (scripts/generate_versioned_stubs.VERSIONS).Validation (local, Python 3.12)
make lint,make typecheck-all,make validate-generated: pass. Full suite (pytest tests/ -n auto): 19073 passed, 2730 skipped; the 12 failures and 1 error of the parallel run (a2a context id, freezegun fresh process, versioned-bases mypy subprocess, two staging-reuse writer tests, a notification-outbox import test, plus the four fixed here) all pass serially, as they did on #1578. Postgres lanes are skipped locally.BREAKING CHANGE: the wire pin is AdCP 3.3.0-beta.0 and the default adcp_version is "3.3-beta.0" (pin adcp_version="3.2" for a 3.2 contract); adcp.types.UniversalMacro is a RootModel union whose closed enum is UniversalMacro3; the identity preview modules (adcp.types._identity_preview, adcp.signing._identity_schemas, scripts/generate_identity_preview.py) are removed and adcp.types.experimental_identity binds the generated 3.3 types (RequestSigning.profiles is list[Profile], PrincipalChangedWebhook.reason is the generated enum); adcp.signing.identity_schema_bundle is removed; legacy RFC 9421 SigningConfig and RequestSignatureVerification construction emits a DeprecationWarning; evaluator_id is gone from evaluator specs; server_version pins keep wire precision; schema defaults for the new 3.3 fields appear in dumps. See MIGRATION_v9_to_v10.md.
🤖 Generated with Claude Code