Skip to content

feat(protocol): support AdCP 3.1.8 schemas - #992

Merged
bokelley merged 2 commits into
mainfrom
codex/bump-adcp-3-1-8
Jul 29, 2026
Merged

feat(protocol): support AdCP 3.1.8 schemas#992
bokelley merged 2 commits into
mainfrom
codex/bump-adcp-3-1-8

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Bumps the packaged ADCP spec pin from 3.1.1 to 3.1.8 and regenerates the bundled schema cache, generated Pydantic types, skills, and docs metadata.

Updates compatibility glue for the 3.1.8 list_creatives response split and adjusts canonical registry tests for registry v1.2.0 with 29 mappings.

Also hardens a timing-sensitive RegistrySync retry test so it waits for the observed second poll instead of assuming a fixed sleep is enough.

Validation: make regenerate-schemas, pre-commit hooks, mypy, ruff, black --check, git diff --check, focused regression tests, and full pytest (5893 passed, 41 skipped, 9 deselected, 1 xfailed).

await asyncio.wait_for(_wait_for_call_count(lambda: call_count, 2), timeout=1.0)
finally:
await sync.stop()
await task
@aao-ipr-bot

aao-ipr-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

⚠️ Argus review could not complete

The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final gh pr review). A human reviewer should take this PR.

View workflow run

This is an automated message from the Argus AI review workflow.

@bokelley
bokelley enabled auto-merge (squash) July 29, 2026 10:51
@bokelley
bokelley merged commit 0efb159 into main Jul 29, 2026
26 checks passed
@bokelley
bokelley deleted the codex/bump-adcp-3-1-8 branch July 29, 2026 10:51
KonstantinMirin added a commit to KonstantinMirin/adcp-client-python that referenced this pull request Jul 29, 2026
Review follow-up. main moved to 3.1.8 (adcontextprotocol#992) while this branch pinned 3.1.1,
so test_manifest_pins_the_spec_version_the_sdk_targets failed once the two met.

Only spec_version and source change: the 3.1.1 and 3.1.8
dist/compliance/.../test-vectors/request-signing trees are byte-identical, and
regenerating the manifest reproduces all 43 file hashes unchanged. That is the
pin doing its job -- it forced an explicit re-vendor decision on a spec bump
rather than letting the old set ride silently.

Note for the next bump: `python -m tests.conformance.signing.vectors --write`
regenerates `files` only and carries spec_version/source forward, so those two
fields need editing before the regen, not by it.

Refs adcontextprotocol#975.
bokelley pushed a commit that referenced this pull request Jul 29, 2026
…set and pin it against drift (#980)

* test(signing): vendor the complete 3.1.1 request-signing vector set and pin it

The vendored request-signing conformance vectors were an incomplete copy of
the spec set, and the loaders could not tell. Both graders globbed the vector
directory and asserted only that the result was non-empty
(test_verifier_vectors.py, test_canonicalization.py), so any non-empty subset
passed and a missing vector was indistinguishable from a complete set.

Against AdCP 3.1.1 -- the version src/adcp/ADCP_VERSION already targets -- the
vendored copy was missing:

  - 4 of 12 positive vectors (009/010 percent-encoding edges, 011/012 IPv6
    authority)
  - 8 of 28 negative vectors (021-028)
  - canonicalization.json entirely, despite the vendored README documenting
    it and devoting a section to it

Three further vectors (016, 017, 020) had silently drifted from their upstream
contents. 017 is the notable one: it had been vendored at a revision that
revoked test-ed25519-2026, the primary signing key, rather than the dedicated
test-revoked-2026 keypair the spec now uses -- and keys.json had never been
refreshed to carry that key.

Changes:

  - Vendor all 12 missing files plus canonicalization.json, and re-sync the
    three drifted vectors, keys.json and README.md. The tree is now
    byte-identical to dist/compliance/3.1.1/test-vectors/request-signing/.
  - Add tests/conformance/signing/vectors.py: one shared loader whose
    parametrization is gated on a completeness pin, replacing the per-module
    glob-and-assert-non-empty helpers.
  - Add vector_manifest.json, pinning the SHA-256 of every vendored file. It
    fails on a missing file, an unexpected extra file, and on content drift.
    A filename-only manifest would not have caught what happened to 016/017/020,
    so the pin is over content, not names.
  - Add test_vector_completeness.py, which also ties the pin to
    get_adcp_spec_version(), so bumping the targeted spec version without
    re-vendoring fails loudly instead of leaving the SDK graded against a
    stale contract.
  - Wire canonicalization.json into test_canonicalization.py. It earns its own
    grader: it exercises canonicalize_target_uri/canonicalize_authority over
    31 cases including 6 malformed-authority rejections that no signed vector
    covers at all.

The newly graded vectors surface 12 real conformance failures, marked
strict-xfail with the gap each one tracks so a fix XPASSes and forces the
entry to be retired. They fall into two groups:

  - The verifier has no step-1 strict-parse stage, so malformed or ambiguous
    input flows on to a later check and is rejected under the wrong error code
    (negative 021, 022, 023, 026). Conformance grades the code byte-for-byte,
    so "rejected anyway" is not a pass.
  - @target-uri canonicalization applies no UTS-46 A-label conversion, drops a
    trailing empty query, and accepts five malformed authority shapes the spec
    requires be rejected. adcp.signing ships canonicalize_host(), but
    canonical.py never calls it.

Each group is filed separately; this change deliberately adds no production
behavior, only the vectors and the guard that keeps them complete.

* test(signing): cite tracking issues in the strict-xfail ledgers

* test(signing): avoid private _pytest import in vector parametrization

* test(signing): note why _write_manifest replaces files instead of mutating

* test(signing): assert the reject code, not just the refusal

The reject branch asserted a bare ValueError -- but urlsplit raises exactly
that for `https://[::1/p`, so `malformed-ipv6-missing-closing-bracket` passed
on someone else's exception while five sibling cases sat in the xfail ledger.
Six reject cases ship in the data; only five were recorded as gaps.

No case asserted `expected_error_code` at all, so the vector set could not
detect its own incompleteness -- the defect this PR exists to close.

Capture the exception and assert the code the vector ships. All six reject
cases now xfail together under #978 and retire together when the typed error
lands.

* test(signing): re-pin the vendored vectors at AdCP 3.1.8

Review follow-up. main moved to 3.1.8 (#992) while this branch pinned 3.1.1,
so test_manifest_pins_the_spec_version_the_sdk_targets failed once the two met.

Only spec_version and source change: the 3.1.1 and 3.1.8
dist/compliance/.../test-vectors/request-signing trees are byte-identical, and
regenerating the manifest reproduces all 43 file hashes unchanged. That is the
pin doing its job -- it forced an explicit re-vendor decision on a spec bump
rather than letting the old set ride silently.

Note for the next bump: `python -m tests.conformance.signing.vectors --write`
regenerates `files` only and carries spec_version/source forward, so those two
fields need editing before the regen, not by it.

Refs #975.
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