fix(version): auto-derive COMPATIBLE_ADCP_VERSIONS from ADCP_VERSION pin#1706
Merged
Conversation
The 3.0.x patch enumeration in COMPATIBLE_ADCP_VERSIONS was a hardcoded
array literal inside the scripts/sync-version.ts template. Every AdCP
patch bump needed someone to remember to append the new version. The
3.0.9, 3.0.10, and 3.0.11 chore PRs all forgot — the list capped at
3.0.8 even though ADCP_VERSION moved to 3.0.11. Symptom:
isCompatibleWith('3.0.11') === false against the SDK's own pin.
Same root-cause class as the SDK-build-time schema URL pinning drift
surfaced by adcontextprotocol/adcp#4419 (BidMachine reports cite
"/schemas/3.0.1/" against a 3.0.11 seller): a load-bearing version
surface that depends on human discipline at every patch bump.
scripts/sync-version.ts now derives the list dynamically from the
current ADCP_VERSION. Enumerates 3.0.0..3.0.<patch> mechanically. Fails
closed when the version falls outside 3.0.x so a future 3.1.x or 4.x
bump forces the script to be extended explicitly — the compat surface
for a major/minor move is rarely mechanical.
Adds test/lib/compatible-versions-self-consistency.test.js asserting
the regenerated list contains the current pin and fills the
3.0.0..ADCP_VERSION range without gaps. Future regressions (someone
reverting to hardcoded literals) fail loud at CI.
Out of scope: SDK-build-time schema URL pinning in validations.ts
(cited URLs reflect the SDK's pin, not the agent's advertised version).
Tracked separately.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three nits from code-reviewer + security-reviewer on #1706: 1. Cap patch enumeration at MAX_PATCH_ENUMERATION = 500. A hostile or fat-fingered ADCP_VERSION = '3.0.999999999' would have looped ~10⁹ string allocations and OOM'd the build silently. Bounded build-time threat but the fix is one line and the new failure mode is a clean error instead of a hang. 2. Refuse prerelease pins (e.g. 3.0.11-rc.1). Enumerating 3.0.0..3.0.11 from a prerelease pin over-claims GA stability for an unreleased patch. Stricter regex; the bumper for a prerelease must land the GA pin separately when it stabilizes. 3. Test now asserts the COMPATIBLE_PREFIX legacy aliases (v2.5, v2.6, v3, 3.0.0-beta.1, 3.0.0-beta.3) survive — guards against a future "clean up legacy aliases" PR silently dropping pinned adopters. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 12, 2026
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.
Background
While investigating adcontextprotocol/adcp#4419 (BidMachine reports cite
/schemas/3.0.1/against a 3.0.11 seller), I audited the SDK's AdCP-version surface and found a related drift class:COMPATIBLE_ADCP_VERSIONScaps at3.0.8insrc/lib/version.tstoday, even thoughADCP_VERSION = '3.0.11'.isCompatibleWith('3.0.9')/('3.0.10')/('3.0.11')all returnfalseagainst the SDK's own pin. That's load-bearing for callers usingisCompatibleWith()to gate behavior on agent-reportedadcp_version.Root cause
scripts/sync-version.tsgeneratessrc/lib/version.tsfrom a template that embeddedCOMPATIBLE_ADCP_VERSIONSas a hardcoded array literal. Every AdCP patch bump required someone to remember to manually append the new version to the literal inside the script template.Audit of the last three patch bumps:
25af9a01dc04977f126dd1e3ca63b641So the literal hasn't been touched since 3.0.8 even though the pin moved three patches forward. Same root-cause class as the schema URL pinning drift in adcp#4419 — a load-bearing version surface that depends on human discipline at every patch bump.
Fix
scripts/sync-version.tsnow derives the list dynamically from the currentADCP_VERSION. Enumerates3.0.0..3.0.<patch>mechanically; the bumper no longer has to remember anything.ADCP_VERSIONfalls outside the3.0.xrange so a future 3.1.x or 4.x bump forces the script to be extended explicitly. The compat surface for a major/minor move is rarely mechanical — that's the right time to make a human think.test/lib/compatible-versions-self-consistency.test.jsasserting (a) the regenerated list contains the current pin and (b) fills3.0.0..ADCP_VERSIONwithout gaps. Future regressions (someone reverting to hardcoded literals) fail loud at CI.Regenerated
src/lib/version.tsconfirms the fix: list now extends'3.0.9', '3.0.10', '3.0.11'.Out of scope (separate issue forthcoming)
The deeper schema URL pinning drift surfaced by adcp#4419 —
validations.ts:354cites schema URLs using the SDK's build-timeADCP_VERSIONregardless of the agent's advertised version — needs its own design pass. The SDK should fetch schemas dynamically from the agent's reportedadcp_version. Tracked separately at adcp-client#1707.Side-finding worth noting
The diff includes a
LIBRARY_VERSIONbump from6.19.1 → 7.0.0insrc/lib/version.ts, butpackage.jsonon origin/main already says"version": "7.0.0". That means the in-flight "chore: release package #1693" PR bumpedpackage.jsonandpackage-lock.jsonbut didn't regeneratesrc/lib/version.ts. The release pipeline"version": "changeset version && npm run sync-version"script should be runningsync-version; this PR's regenerate also catches that up. Worth a separate look at why release-prep didn't include the regen — probably a fresh-clone-vs-committed-output thing.Test plan
npm run buildcleannpm run format:checkcleannode --test test/lib/compatible-versions-self-consistency.test.js— 3/3 passnpx tsx scripts/sync-version.tsregeneratessrc/lib/version.tswith the extended compat listCOMPATIBLE_ADCP_VERSIONSwill trackADCP_VERSIONautomatically across future patch bumps; the new test fails loud if the auto-derive is reverted.🤖 Generated with Claude Code