feat(wire-version): release-precision pins + wire validator + namespace#1814
Merged
Conversation
Three follow-ups surfaced during the expert review of #1807. Each is small and additive; bundled because they share the wire-version helper surface. Issue #1: resolveBundleKey accepts release-precision pins. AdCP 3.1's supported_versions capability advertises versions in release-precision shape (["3.1-beta"]), and a buyer reading that off the wire must be able to construct a client pinned to it. Before: new AdcpClient({ adcpVersion: '3.1-beta' }) threw ConfigurationError. Now: resolveBundleKey accepts MAJOR.MINOR-PRE and returns verbatim; resolveSchemaRoot fuzzy-resolves to the highest cached prerelease dir whose own release-precision form matches (so '3.1-beta' finds schemas/cache/3.1.0-beta.0/, '3.1-beta.0' matches it exactly). Issue #2: validateAdcpVersionWire public assertion. Throws ConfigurationError with a hint pointing at toReleasePrecisionWire when given a non-spec wire value. Use when constructing request envelopes by hand (storyboard fixtures, conformance harnesses, custom transports). Also wired as a defensive postcondition in buildVersionEnvelope so future refactors can't silently emit non-spec shapes. Issue #3: wireVersion namespace. Groups the three helpers (isSupported, normalize, validate) under one barrel export. Stable target for future additions. Top-level exports kept for back-compat — not deprecated. Tests cover all three plus regression checks against the existing test suites (47 tests pass across the wire-version surface). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI failed on the release-precision-pinned-bundle test because it relied on schemas/cache/3.1.0-beta.0/ existing — that directory is gitignored and only present in dev workspaces that have synced a 3.1 prerelease cache. CI only syncs the SDK-pinned ADCP_VERSION. Fix: create a synthetic 98.0.0-test.0/ fixture directory in before(), exercise the fuzzy lookup against it (a pin of '98.0-test' should resolve via the release-precision form '98.0-test.0'), and clean up in after(). The fixture's major version (98) is far outside any plausible real AdCP cache so a stray leftover can't conflict. 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
Three follow-ups from the expert review of PR #1807. Bundled because they share the wire-version helper surface.
Why this matters
#1: AdCP 3.1's `supported_versions` capability advertises versions in release-precision shape (`["3.1-beta"]`). A buyer reading that off the wire and trying to pin to it would hit a `ConfigurationError` before this change. Discovery → pin asymmetry the protocol expert flagged on #1807.
#2: When the seller AJV-rejects an outgoing request with a pattern mismatch on `adcp_version`, the buyer's stack frame is long gone and the spec PR URL is the only clue. A pre-flight assertion that names `toReleasePrecisionWire` in the error message turns this into a one-line fix instead of a debugging session. DX expert's suggestion on #1807.
#3: The barrel had two version helpers; this PR adds a third. The DX expert flagged that three is the right threshold to flip atomically rather than continuing to add top-level exports. The namespace is the recommended path going forward; top-level exports stay for back-compat (no deprecation churn).
Worked example
```ts
import { wireVersion } from '@adcp/sdk';
// Pin to a version a seller advertised on the wire.
const sellerSupports = ['3.0', '3.1-beta'];
const pin = sellerSupports.find(v => wireVersion.isSupported(v)) ?? '3.0';
// Construct a wire-shaped value defensively.
const wire = wireVersion.normalize('3.1.0-beta.0'); // '3.1-beta.0'
wireVersion.validate(wire); // throws on non-spec shape — error names normalize()
```
Test plan
Reviewer note
Each change is small enough to skip a full run-by-experts round in my judgement. If you want a full pass anyway, say the word and I'll fire the four reviewers in parallel.
🤖 Generated with Claude Code