chore(schemas): bump ADCP_VERSION 3.0.7 → 3.0.12 (closes #771)#791
Merged
Conversation
Bumps src/adcp/ADCP_VERSION from 3.0.7 to 3.0.12 and re-syncs all generated artifacts (schemas/cache/, src/adcp/types/_generated.py, src/adcp/types/generated_poc/, src/adcp/types/_ergonomic.py, SCHEMA_DELTAS.md, skills/) from the upstream protocol bundle. Upstream additions: - tmp/identity-match-request.json: +seller_agent_url (required), package_ids now optional (was required). - protocol/get-adcp-capabilities-response.json: account.supported_billing is now conditionally required when supported_protocols contains "media_buy" (encoded via allOf/if/then). - adcp/legacy webhook authentication (Bearer/HMAC-SHA256) marked deprecated in descriptions; RFC 9421 is the preferred profile. - creative/asset-types/index.json: lastUpdated bumped 2026-05-08 to 2026-05-13. Upstream regressions vs. the PR #753 hand-patched cache: - adagents.json: revoked_publisher_domains[] is NOT in upstream 3.0.12 (anticipated landing pre-3.0.10 didn't happen). - core/publisher-property-selector.json: publisher_domains[] compact form is NOT in upstream 3.0.12 (same anticipated landing missed). Per issue #771 the right call is to ship the regen and document the divergence rather than re-apply the hand-patch and wait for 3.0.13+. The SDK-side dict-layer helpers (validate_publisher_properties_item, validate_revoked_publisher_domain_entry, _fanout_publisher_properties, get_properties_by_agent) still implement the compact-form / revocation contract for adopters consuming raw adagents.json bytes — only the Pydantic-model layer loses the field. Closes #771 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four test adjustments tracking the schema regen from the previous commit: - tests/test_client.py: IdentityMatchRequest fixture gains seller_agent_url (now required upstream). - tests/test_capabilities_response_shape_validation.py: the ``account``/``supported_billing`` invariant assertions also accept the structured ``issues[]`` blob, since upstream 3.0.12 encodes the requirement via allOf/if/then and the schema-driven step now reports the missing ``/account`` pointer before the explicit invariant check fires. - tests/test_adagents.py: drop the dead ``Reason`` enum cross-check (upstream removed RevokedPublisherDomain.reason); the SDK's ``_REVOCATION_REASONS`` frozenset is pinned directly. Drop the ``PublisherPropertySelector1`` XOR-from-Pydantic case (the field ``publisher_domains`` no longer exists on the generated model). - tests/test_publisher_selector_xor_autoenforce.py: skip the four compact-form cases with a pointer back to issue #771. The Pydantic-layer XOR patch in ``adcp.types.aliases`` has no field to fire on; SDK-layer enforcement still lives in ``adcp.validation.legacy.validate_publisher_properties_item``. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Approving. Clean regen — generated output matches upstream 3.0.12, the defensive Tier-2 validators absorb the schema's encoding shift from account.required: ["supported_billing"] to allOf/if/then, and the documented divergence from PR #753 is the right call.
Things I checked
- Regeneration provenance:
# generated by datamodel-codegenheaders insrc/adcp/types/generated_poc/adagents.py,core/publisher_property_selector.py,tmp/identity_match_request.py,protocol/get_adcp_capabilities_response.pyall carry the newtimestamp: 2026-05-22T08:52:07+00:00. No hand-edits.src/adcp/types/_generated.pyonly theGeneration date:comment moved.src/adcp/ADCP_VERSIONreads3.0.12. - Semver signal:
chore(schemas):is correct. PR #753's compact form / revocation never reached a tagged release —v5.7.0is still an open release-please PR (bf96517f), so adding-then-removing in the unreleased window does not requirefeat!:/BREAKING CHANGE:. Heads-up: the open 5.7.0 release PR's CHANGELOG entry currently lists #753 as a shipped feature — that entry needs regeneration before 5.7.0 cuts, or the changelog will advertise a surface that doesn't exist. - Public-API coherence:
ReasonandPublisherDomainsurvive in_generated.pyas imports from unrelated modules (creative/sync_creatives_async_response_input_required,protocol/get_adcp_capabilities_response) — symbol collisions, not the removed adagents/selector classes.IdentityMatchRequestre-exports throughsrc/adcp/types/__init__.py:220andsrc/adcp/__init__.py:199carry the new requiredseller_agent_urlfield cleanly. - XOR auto-enforce patch left in place:
src/adcp/types/aliases.py:1822-1914is now a no-op for valid Selector1/3 instances. The_validate_item(self)path goes throughmodel_dump(); withpublisher_domainsremoved andpublisher_domainnow Pydantic-required, the helper has nothing to fire on. Confirmed viasrc/adcp/validation/legacy.py:65-77field-introspection logic. Harmless dead weight, follow-up to delete if upstream doesn't bring the field back by 3.0.13+. - Wire-shape soundness (
ad-tech-protocol-expert): all five surfaces sound —identity-match-requestprivacy invariant intact viaseller_agent_url+ statistically-independentpackage_ids+ silent-drop on unknown IDs;allOf/if/thenon capabilities is the right draft-07 idiom for cross-field conditional requireds; webhook auth deprecation language ("switch, not a fallback") closes the rollback-attack pattern. - Test honesty:
tests/test_capabilities_response_shape_validation.py:138-141now ORs acrossstr(err)and theissues[]blob. Invariant still independently enforced atsrc/adcp/decisioning/validate_capabilities.py:128-151.pytest tests/ -vclaim: 4934 passed, 38 skipped, 9 deselected, 1 xfailed.
Follow-ups (non-blocking — file as issues)
- Buyer/seller drift footgun on
validate_publisher_properties_item/validate_revoked_publisher_domain_entry. The SDK helpers still implement compact-form and revocation contracts at the dict layer, but upstream 3.0.12 doesn't carry them. Risk inversion: revocation is one-emits/many-consume (safe —additionalProperties: true); compact-form is many-emit/one-consume — an adopter using the helper to construct compact-form bytes will produce a payload no spec-compliant seller can parse. Recommend marking these helpersx-pending-upstream-3.0.13or adding a sender-side guard until upstream lands the feature. - 5.7.0 release PR CHANGELOG drift. The open release PR (
bf96517f) advertisesfeat(adagents): publisher_domains compact form, revoked_publisher_domainsfor 5.7.0 even though this PR removes both. Regenerate or hand-edit before the release cuts. SKILL.mdwebhook section is prose-only in a code-heavy file. Every neighboring section inskills/call-adcp-agent/SKILL.mdshows a JSON shape; this one doesn't. A four-linepush_notification_configsnippet withoutauthenticationwould pin the rule by example and naturally hoist thetokencarve-out out of footnote position.
Minor nits (non-blocking)
- Stale comment after enum removal.
src/adcp/validation/legacy.py:226-228still references "theReasonenum onRevokedPublisherDomainin the generated adagents schema" and a drift test against it. The test intests/test_adagents.py:3495was rewritten to pin a static frozenset; the comment should say so. The drift sentinel rationale doesn't apply anymore. - Pydantic
extra="allow"is now load-bearing for the surviving XOR test.tests/test_publisher_selector_xor_autoenforce.py:49-59(test_selector1_rejects_both_publisher_fields) is the only un-skipped case and only passes because Selector1/3 carryextra="allow". If upstream ever flips toextra="forbid", the test will silently switch from "XOR enforcement" to "unknown-field rejection." One-line comment pinning the dependency, or skip alongside the others. - Capabilities-shape assertion is wide.
"account"and"supported_billing"substring matches attest_capabilities_response_shape_validation.py:138-141and:378-381will accept any unrelated issue that mentions either word. Tighten toany(i["pointer"].startswith("/account") for i in issues)or assertkeyword == "required"against"supported_billing". Invariant is belt-and-suspenders enforced upstream so this is cosmetic.
Notable that the SDK now ships the dict-layer compact-form contract richer than the wire — for one regen cycle.
Safe to merge.
3 tasks
bokelley
added a commit
that referenced
this pull request
May 22, 2026
…dits (#795) * feat(schemas): patches/ post-process infrastructure Hand-edits to the regenerated schema cache used to get silently overwritten by ``make regenerate-schemas`` — that's exactly how PR #753's forward-looking ``revoked_publisher_domains[]`` + ``publisher_domains[]`` compact-form patches got wiped on PR #791's bump to 3.0.12. The patches were invisible to anyone running the regen, and the loss only surfaced on line-by-line diff review of the regen output. This introduces ``schemas/patches/`` as a tracked, reviewable layer of hand-edits applied AFTER the upstream-verbatim extraction in ``scripts/sync_schemas.py``. Each ``.patch`` file is a unified diff with a comment header (Patch / Reason / Filed / Upstream status / Drop when), applied in lex order from the repo root via ``patch -p1``. The state machine in ``apply_tracked_patches`` classifies each patch as: - **Alive** — forward-applies cleanly → apply, continue. - **Dead** — reverse-applies cleanly (upstream landed it) → exit non-zero with the patch name + directive to delete the file. - **Broken** — neither direction applies → exit non-zero with the patch name + directive to either update the hunks or remove the patch. Dead and broken both fail loudly because silently no-op'ing on dead would let stale ``.patch`` files linger forever, and silently skipping broken would let the SDK ship a cache whose patched fields don't actually exist in the working tree. Patch-application runs ONCE at the end of ``main()`` (after all primary + preview bundles have been extracted), not inside ``_sync_one`` per-bundle. Per-bundle would misclassify a 3.0 patch as "dead" during the subsequent 3.1 preview pass because the cache wouldn't reset between passes. The existing ``make check-schema-drift`` target picks up patch-apply without changes — it already re-runs ``sync_schemas.py`` and diffs the cache. With patches in the directory, the diff now validates that patches still apply AND the resulting cache matches what's checked in. The directory ships empty in this commit. The two #753-restoration patches follow in a separate commit once PR #791 (3.0.12 regen) lands on main — they need the post-regen cache as the diff base. Refs #791, #753 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(schemas): restore #753 + #792 hand-edits via tracked patches Three patches restore prior hand-edits to the 3.0 schema cache that were silently dropped on the 3.0.7 → 3.0.12 regen (#791): 01-adagents-revoked-publisher-domains.patch ``adagents.json`` gains top-level ``revoked_publisher_domains[]`` with the Reason enum. SDK dict-layer helpers (``validate_revoked_publisher_domain_entry``, ``filter_revoked_selectors``) implement the contract today; this patch restores the field on the Pydantic-model layer so adopters get parity across both code paths. Filed in PR #753 — upstream took the shape into 3.1.0-beta.x rather than 3.0.x, so the patch stays alive until the SDK moves to a 3.1 floor. 02-publisher-property-selector-publisher-domains.patch ``publisher-property-selector.json`` gains optional ``publisher_domains[]`` (compact form) on the `all` and `by_tag` selectors, XOR with the singular ``publisher_domain``. SDK helpers (``_fanout_publisher_properties``, ``validate_publisher_properties_item``, ``get_properties_by_agent``) implement the contract; same Pydantic- layer parity restoration. Filed in PR #753 — same upstream-status as patch 01 (landed in 3.1.0-beta.x). 03-manifest-signal-owned-discovery-only.patch ``manifest.json`` removes ``signal_owned`` from ``activate_signal.specialisms`` and ``activate_signal`` from ``signal_owned.exercised_tools``. Owned signal agents are discovery-only by design; upstream's 3.0.12 manifest still includes the old two-specialism shape, which would require owned signal agents to implement ``activate_signal`` (defeating the specialism purpose) and make conformance runners exercise marketplace activation. Filed in PR #792 — SDK self-correction. Drops when upstream updates the manifest shape. Each patch carries its own audit-trail header (Patch / Reason / Filed / Upstream status / Drop when) so the next reader has full context without needing git archaeology. See ``schemas/patches/README.md`` for the convention. Pydantic regen (``make regenerate-schemas``) picks up all three restored fields: src/adcp/types/_generated.py — RevokedPublisherDomain, PublisherDomain (per-arm) src/adcp/types/generated_poc/adagents.py src/adcp/types/generated_poc/core/publisher_property_selector.py SCHEMA_DELTAS.md now reports "no field-shape changes detected" because the post-patch generated types match the prior committed state. PR #791 had recorded the deletions as part of its regen; this commit reverses them via the patches infra. Tests: ``pytest tests/`` — 5026 passed, 30 skipped, 1 xfailed. ruff + mypy clean. Refs #753, #791, #792 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Catches the SDK schema cache up from upstream ADCP 3.0.7 to 3.0.12. Bumps
src/adcp/ADCP_VERSIONand re-runsmake regenerate-schemas. Drops the PR #753 hand-patches that were temporarily added to the cached schemas while waiting for upstream to land thepublisher_domains[]compact form +revoked_publisher_domains[]revocation surface.Closes #771.
Upstream additions surfaced by the regen
tmp/identity-match-request.json: new required fieldseller_agent_url(URI);package_idsis now optional (was required). The buyer resolves the active package set fromseller_agent_urlwhenpackage_idsis omitted; when present, its composition MUST be statistically independent of the current placement (all-active or fuzzed).protocol/get-adcp-capabilities-response.json:accountblock is now conditionally required whensupported_protocolscontainsmedia_buy, encoded viaallOf/if/then. Previouslysupported_billingwas unconditionally required ataccount.required.adagents.json/media-buy/create-media-buy-request.json/core/reporting-webhook.json/enums/auth-scheme.json: description-only changes marking the Bearer / HMAC-SHA256 webhook auth schemes deprecated in favor of RFC 9421. Removed in AdCP 4.0.creative/asset-types/index.json:lastUpdatedbump 2026-05-08 → 2026-05-13.skills/call-adcp-agent/SKILL.md: new "Webhook signing — omitauthenticationfor new integrations" section reinforcing the RFC 9421 default.Divergence vs. PR #753's anticipated landing
Upstream 3.0.12 does not include the two surfaces PR #753 hand-patched into the cache while waiting:
adagents.json:revoked_publisher_domains[]is not in upstream.core/publisher-property-selector.json:publisher_domains[]compact form is not in upstream;publisher_domainis back to required on selectors 1 / 3.Per the issue's risk-3 guidance, this PR takes option (b) — ship the regen, document the divergence, let the user decide whether to re-patch or wait for 3.0.13+. The SDK-side dict-layer helpers (
validate_publisher_properties_item,validate_revoked_publisher_domain_entry,_fanout_publisher_properties,get_properties_by_agent) still implement the compact-form / revocation contract for adopters consuming rawadagents.jsonbytes — only the Pydantic-model layer loses the field.The XOR auto-enforce patch in
src/adcp/types/aliases.py(issue #759) is left in place because it's outside the declared write scope for this regen-focused PR and it harmlessly no-ops on the new model shape (the field it inspects no longer exists). If upstream does not bringpublisher_domainsback by 3.0.13+, a follow-up should remove the dead patch.Consumer fixes (test fixtures only)
Four test files needed alignment with the new generated types:
tests/test_client.py—IdentityMatchRequestfixture gainsseller_agent_url.tests/test_capabilities_response_shape_validation.py— invariant assertions for the missing-accountcase also read the structuredissues[]blob, since the schema-driven step now reports/accountbefore the explicit invariant check.tests/test_adagents.py— drop the deadReasonenum cross-check (upstream removed the enum); drop the XOR-from-Pydantic case (field no longer exists).tests/test_publisher_selector_xor_autoenforce.py— skip the four compact-form cases with a pointer back to issue chore(schemas): bump ADCP_VERSION 3.0.7 → 3.0.12, drop hand-patched compact-form schema cache #771.Out-of-scope notes
skills/.make regenerate-schemassyncedskills/call-adcp-agent/SKILL.mdfrom the upstream bundle alongside the schemas; the change is upstream protocol drift, equivalent in provenance to the rest of the regen. Reviewers should verify theSKILL.mddelta is acceptable; if not, it can be cherry-removed without touching the type generation.make check-schema-drifthas a pre-existing quirk: each invocation re-bumps theGeneration date:comment in_generated.py, so the drift gate trips on the timestamp alone after a clean regen. Not blocking (the target is not in CI).Test plan
pytest tests/test_adagents.py tests/test_validation*.py --tb=short— 210 passed.pytest tests/ --tb=line -q— 4934 passed, 38 skipped (4 new skips tied to chore(schemas): bump ADCP_VERSION 3.0.7 → 3.0.12, drop hand-patched compact-form schema cache #771), 9 deselected, 1 xfailed.ruff check src/— clean.mypy src/adcp/— clean (811 source files).src/adcp/ADCP_VERSIONreads3.0.12.HAND-PATCHED/#753/TODO: drop on 3.0.10markers remain inschemas/cache/.🤖 Generated with Claude Code