Skip to content

chore(schemas): bump ADCP_VERSION 3.0.7 → 3.0.12 (closes #771)#791

Merged
bokelley merged 3 commits into
mainfrom
bokelley/issue-771-adcp-version-3-0-12
May 22, 2026
Merged

chore(schemas): bump ADCP_VERSION 3.0.7 → 3.0.12 (closes #771)#791
bokelley merged 3 commits into
mainfrom
bokelley/issue-771-adcp-version-3-0-12

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Summary

Catches the SDK schema cache up from upstream ADCP 3.0.7 to 3.0.12. Bumps src/adcp/ADCP_VERSION and re-runs make regenerate-schemas. Drops the PR #753 hand-patches that were temporarily added to the cached schemas while waiting for upstream to land the publisher_domains[] compact form + revoked_publisher_domains[] revocation surface.

Closes #771.

Upstream additions surfaced by the regen

  • tmp/identity-match-request.json: new required field seller_agent_url (URI); package_ids is now optional (was required). The buyer resolves the active package set from seller_agent_url when package_ids is omitted; when present, its composition MUST be statistically independent of the current placement (all-active or fuzzed).
  • protocol/get-adcp-capabilities-response.json: account block is now conditionally required when supported_protocols contains media_buy, encoded via allOf/if/then. Previously supported_billing was unconditionally required at account.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: lastUpdated bump 2026-05-08 → 2026-05-13.
  • skills/call-adcp-agent/SKILL.md: new "Webhook signing — omit authentication for 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_domain is 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 raw adagents.json bytes — 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 bring publisher_domains back 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.pyIdentityMatchRequest fixture gains seller_agent_url.
  • tests/test_capabilities_response_shape_validation.py — invariant assertions for the missing-account case also read the structured issues[] blob, since the schema-driven step now reports /account before the explicit invariant check.
  • tests/test_adagents.py — drop the dead Reason enum 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

  • The declared write scope did not include skills/. make regenerate-schemas synced skills/call-adcp-agent/SKILL.md from the upstream bundle alongside the schemas; the change is upstream protocol drift, equivalent in provenance to the rest of the regen. Reviewers should verify the SKILL.md delta is acceptable; if not, it can be cherry-removed without touching the type generation.
  • make check-schema-drift has a pre-existing quirk: each invocation re-bumps the Generation 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

🤖 Generated with Claude Code

bokelley and others added 2 commits May 22, 2026 04:55
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>
Copy link
Copy Markdown

@aao-ipr-bot aao-ipr-bot Bot left a comment

Choose a reason for hiding this comment

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

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-codegen headers in src/adcp/types/generated_poc/adagents.py, core/publisher_property_selector.py, tmp/identity_match_request.py, protocol/get_adcp_capabilities_response.py all carry the new timestamp: 2026-05-22T08:52:07+00:00. No hand-edits. src/adcp/types/_generated.py only the Generation date: comment moved. src/adcp/ADCP_VERSION reads 3.0.12.
  • Semver signal: chore(schemas): is correct. PR #753's compact form / revocation never reached a tagged release — v5.7.0 is still an open release-please PR (bf96517f), so adding-then-removing in the unreleased window does not require feat!: / 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: Reason and PublisherDomain survive in _generated.py as imports from unrelated modules (creative/sync_creatives_async_response_input_required, protocol/get_adcp_capabilities_response) — symbol collisions, not the removed adagents/selector classes. IdentityMatchRequest re-exports through src/adcp/types/__init__.py:220 and src/adcp/__init__.py:199 carry the new required seller_agent_url field cleanly.
  • XOR auto-enforce patch left in place: src/adcp/types/aliases.py:1822-1914 is now a no-op for valid Selector1/3 instances. The _validate_item(self) path goes through model_dump(); with publisher_domains removed and publisher_domain now Pydantic-required, the helper has nothing to fire on. Confirmed via src/adcp/validation/legacy.py:65-77 field-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-request privacy invariant intact via seller_agent_url + statistically-independent package_ids + silent-drop on unknown IDs; allOf/if/then on 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-141 now ORs across str(err) and the issues[] blob. Invariant still independently enforced at src/adcp/decisioning/validate_capabilities.py:128-151. pytest tests/ -v claim: 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 helpers x-pending-upstream-3.0.13 or adding a sender-side guard until upstream lands the feature.
  • 5.7.0 release PR CHANGELOG drift. The open release PR (bf96517f) advertises feat(adagents): publisher_domains compact form, revoked_publisher_domains for 5.7.0 even though this PR removes both. Regenerate or hand-edit before the release cuts.
  • SKILL.md webhook section is prose-only in a code-heavy file. Every neighboring section in skills/call-adcp-agent/SKILL.md shows a JSON shape; this one doesn't. A four-line push_notification_config snippet without authentication would pin the rule by example and naturally hoist the token carve-out out of footnote position.

Minor nits (non-blocking)

  1. Stale comment after enum removal. src/adcp/validation/legacy.py:226-228 still references "the Reason enum on RevokedPublisherDomain in the generated adagents schema" and a drift test against it. The test in tests/test_adagents.py:3495 was rewritten to pin a static frozenset; the comment should say so. The drift sentinel rationale doesn't apply anymore.
  2. 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 carry extra="allow". If upstream ever flips to extra="forbid", the test will silently switch from "XOR enforcement" to "unknown-field rejection." One-line comment pinning the dependency, or skip alongside the others.
  3. Capabilities-shape assertion is wide. "account" and "supported_billing" substring matches at test_capabilities_response_shape_validation.py:138-141 and :378-381 will accept any unrelated issue that mentions either word. Tighten to any(i["pointer"].startswith("/account") for i in issues) or assert keyword == "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.

@bokelley bokelley enabled auto-merge (squash) May 22, 2026 10:17
@bokelley bokelley merged commit fe09c02 into main May 22, 2026
23 checks passed
@bokelley bokelley deleted the bokelley/issue-771-adcp-version-3-0-12 branch May 22, 2026 10:22
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>
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.

chore(schemas): bump ADCP_VERSION 3.0.7 → 3.0.12, drop hand-patched compact-form schema cache

1 participant