chore(schemas): sync to AdCP 3.0.7 + strict drift gate#599
Merged
Conversation
Bumps ADCP_VERSION 3.0.5 → 3.0.7 and resyncs schemas/cache/ + generated_poc/ from the 3.0.7 dist bundle (Sigstore-verified). Adds scripts/diff_generated_types.py, an AST-walker that captures per-class field/enum-member sets and produces SCHEMA_DELTAS.md on every regen so consumers can shrink schema-mismatch allowlists without diffing hundreds of generated files by hand. Cleans up PR #429's source-vs-bundle confusion: that PR pulled the error-code enum from upstream's static/schemas/source/ on `main` (which tracks 3.1 WIP), giving us 60 codes vs the 45 every 3.0.x dist ships. The conformance test's `assert len(CANONICAL_CODES) == 60` tripwire is updated to 45 with a docstring spelling out that the canonical source is the dist bundle for the pinned ADCP_VERSION, never `static/schemas/source/`. BILLING_NOT_PERMITTED_FOR_AGENT — the only one of the 17 dropped codes the SDK actually raises — is allowlisted in KNOWN_NON_SPEC_CODES with a TODO pointing at the 3.1 bump; collapsing it to PERMISSION_DENIED would erase the spec's documented `rejected_billing` / `suggested_billing` discriminator. generate_types.py now snapshots the pre-regen tree in-process and writes SCHEMA_DELTAS.md after a successful generation. The diff is class-name-aware (datamodel-codegen's numbered-variant churn is visible by design) and is a no-op for steady-state regens. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the existing permissive 'Check for schema drift' step with two strict checks that close the source-of-truth loophole that let PR #429 land 17 codes pulled from static/schemas/source/ rather than the dist bundle. 1. schemas/cache/ byte-equality. After sync_schemas downloads the dist bundle for the pinned ADCP_VERSION, any diff against the committed cache means the cache was hand-edited or sourced from somewhere other than the bundle. The bundle is byte-stable so this check has no false-positive surface. 2. generated_poc/ field-signature equality. A new 'Snapshot committed types' step captures the pre-regen tree's per-class field and enum-member sets; after generate_types runs, diff_generated_types compares signatures (frozenset of frozensets per file) so datamodel-codegen's numbered-variant class-name churn (PackageUpdate1 vs PackageUpdate4 from APFS-vs-ext4 sort order) stays invisible. Real changes — added or removed fields, classes, enum members — fail the build with a markdown diff and remediation pointer. The previous step intentionally never failed, citing 'numbered-variant churn produces false positives that block release PRs for cosmetic churn'. The signature check sidesteps that exactly: cosmetic class renumbering preserves the multiset of field-name frozensets, so only semantic deltas trip the gate. Hand-edits like 1a6ab9a ('rename format_ to format in FieldModel enum'), and forward-state leaks like #429, both surface here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR #599's first push committed schemas/cache/ in the raw-bundle form (absolute $refs, $id present), missing the fix_schema_refs.py transformation that the repo has committed since the 3.0.5 sync at 008fa3c. That broke two things in CI: 1. Strict cache byte-equality check (the new gate I added) ran AFTER fix_schema_refs.py during the schema-check job, comparing committed pre-fix shape against post-fix CI output — always false, so the gate fired on its own first run. 2. The storyboard runner's runtime schema_loader (continue-on-error but visible in CI) failed with `<urlopen error: '/schemas/3.0.7/ core/context.json'>`. jsonschema's RefResolver joined the absolute $ref against a file:// base_uri to produce file:///schemas/3.0.7/ core/context.json, which isn't keyed in the registry (registry keys are raw $id strings) and doesn't exist on disk. Relative refs like ../core/context.json would have resolved correctly. Fix runs `python scripts/fix_schema_refs.py` against the synced cache and recommits. Refs are now relative; $id stripped from every schema dict (consistent with the convention 008fa3c established). generate_types regenerated against the post-fix cache produces the same field surface as 3.0.5 — `AdcpExtensionFileSchema` no longer has the spurious `field_id` member that the pre-fix 3.0.7 regen introduced (fix_schema_refs strips `$id` even when it appears as a nested property name, which is how that member was being generated). Also moves the strict cache check back to AFTER fix_schema_refs in ci.yml, which is the canonical state that matches what gets committed. Comment updated to spell out the convention so the next sync doesn't make the same mistake. Test plan: - pytest: 4165 passed, 30 skipped, 1 xfailed, 0 failed. - error-code conformance: 15/15 passed. - ruff + mypy: clean on touched files. - Manual: schemas/cache/media-buy/create-media-buy-async-response- submitted.json refs are now `../core/context.json` (relative), matching what was committed at 3.0.5. 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
schemas/cache/andsrc/adcp/types/generated_poc/from the AdCP 3.0.7 dist bundle (ADCP_VERSION3.0.5 → 3.0.7).static/schemas/source/onadcontextprotocol/adcp@main(which tracks 3.1 WIP), giving us 60 codes vs the 45 every 3.0.x dist ships. The conformance test'sassert len(CANONICAL_CODES) == 60tripwire is updated to 45 with a docstring spelling out that the canonical source is the dist bundle for the pinnedADCP_VERSION, neverstatic/schemas/source/.schemas/cache/byte-equality — fails when the committed cache differs from whatsync_schemas.pyproduces from the dist bundle.generated_poc/field-signature equality — fails on real semantic changes (added/removed field, class, enum member) but is invisible todatamodel-codegen's numbered-variant class-name churn (PackageUpdate1vsPackageUpdate4) that filesystem-iteration-order produces between APFS and ext4. The previous step intentionally never failed for that exact reason; the signature check sidesteps the noise.scripts/diff_generated_types.py(AST-walker) and wires it intogenerate_types.pyso every regen writes aSCHEMA_DELTAS.mdlisting per-class field/enum-member changes — gives consumers (e.g. salesagent'sKNOWN_SCHEMA_LIBRARY_MISMATCHES) a trigger to shrink their allowlists without diffing hundreds of files.Why one PR
The CI gate on its own would have failed any PR carrying the
60→45enum delta (which is the regen this PR also performs). They're the same logical fix — bringing main into sync with the dist bundle and gating against future divergence — and reviewing them together makes the cause-and-effect chain easier to follow.Background — how PR #429 leaked 3.1 state into a 3.0.x SDK
static/schemas/source/enums/error-code.jsononadcontextprotocol/adcp@maincarries 62 — codes added during the 3.1 development window (AGENT_SUSPENDED/AGENT_BLOCKED,READ_ONLY_SCOPE/FIELD_NOT_PERMITTED, theBILLING_*andPROVENANCE_*families,CONFIGURATION_ERROR,CREDENTIAL_IN_ARGS).schemas/cache/enums/error-code.jsonto add 15 of those 62, edited the generatedgenerated_poc/enums/error_code.pydirectly, and locked the count withassert len(CANONICAL_CODES) == 60.BILLING_NOT_PERMITTED_FOR_AGENT— the only one of the 17 missing codes the SDK actually raises (src/adcp/decisioning/registry.py:373) — moves toKNOWN_NON_SPEC_CODESwith aTODO: drop when ADCP_VERSION >= 3.1. Collapsing it toPERMISSION_DENIEDwould erase the spec's documentedrejected_billing/suggested_billingdiscriminator, so the allowlist is the right call until 3.1 ships.Drift report
SCHEMA_DELTAS.mdlands in this PR as the per-regen artifact. It's empty for the 3.0.5 → 3.0.7 step (steady state); future regens will populate it with field-level deltas.Test plan
tests/minustests/integration/): 4230 passed, 22 skipped, 1 xfailed, 0 failed.tests/test_error_code_conformance.pyandtests/test_tier2_spec_conformance.pyboth green after the count fix and allowlist addition.ruff checkandmypyclean on touched files.scripts/diff_generated_types.pychecksubcommand verified end-to-end:🤖 Generated with Claude Code