fix(deps): bump @adcp/sdk to 8.1.0-beta.21 (storyboard replay-clock fix) + rc.6 support#5265
Conversation
3.0-compat /sales started failing 2026-06-01 with create_media_buy_replay IDEMPOTENCY_CONFLICT (64 clean / floor 65) — branch-independent (main re-run today failed identically) and not self-healing. Root cause: the storyboard runner's resolveMediaBuyWindow used a per-call Date.now(); once the frozen 3.0.15 fixture's start_time (2026-06-01) went past, the window fell to a now-relative default computed independently per step, so the idempotency replay's payload diverged from the initial → conflict. beta.21 (adcp-client #2149, closing #2147) threads a stable per-run clock (runStartMs) into resolveMediaBuyWindow so both steps enrich identically. Verified locally under beta.21: typecheck clean; 3.0-compat matrix returns to floor on every tenant (/sales 65 clean / 304 steps; 0 IDEMPOTENCY_CONFLICT). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Right diagnosis, right SDK bump, but the allowlist expansion missed five sibling assertions and will land CI red. The two tenant-smoke.test.ts assertions in the diff are the same shape as five hardcoded supported_versions arrays in server/tests/unit/training-agent.test.ts — those still end at '3.1-rc.4'. Jest's toMatchObject on arrays enforces length parity, so once SUPPORTED_RELEASE_VERSIONS returns the new 5-element array, all five fail with Array length mismatch (4 vs 5). Same one-token append fix as the tenant-smoke change.
Must fix (blocking)
-
server/tests/unit/training-agent.test.ts— 5 sibling assertions missed. Append'3.1-rc.6'to each:- L7400 (
get_adcp_capabilities→result.adcp.toMatchObject({ supported_versions: [...] })) - L8313 (
task-version-unsupportedrejection envelope →data.supported_versions) - L10136 (
advertises supported_versions and echoes the default served adcp_version) - L10201 (cross-major rejection →
details.supported_versions) - L10222 (
requires pre-release adcp_version pins to match exactly→details.supported_versions)
The PR description's pre-push verification covered the 3.0-compat matrix, current-source matrix, and typecheck. It does not list the unit suite — that is the path that breaks.
- L7400 (
Things I checked
- Replay-clock root cause matches the symptom —
resolveMediaBuyWindowreadingDate.now()per step on a now-relative default, with the 3.0.15 fixture'sstart_time(2026-06-01) crossing the present boundary. Threading a stablerunStartMsper run is the right shape; the canonical payload converges → byte-identical → noIDEMPOTENCY_CONFLICT. Clean fix at the SDK layer, not papered over in the runner. CURRENT_ADCP_VERSIONstays at'3.1-rc.4'while the accept-list expands torc.6. Coherent —CURRENT_ADCP_VERSIONis only the served default (task-handlers.ts:800); the allowlist is independent. No code or test pairs the two.- No parallel hardcoded allowlists elsewhere in
server/src— addie/registry use profile-fedadcp_supported_versions.storyboards.test.tsrc.4 references are hosted-compliance targets, not allowlist assertions, unaffected. - Lockfile diff is minimal — version + integrity only, no transitive churn.
patchchangeset is correct: runtime determinism fix + accept-list widening, no schema or wire-shape change.task-handlers.ts:709and:5569spreadSUPPORTED_RELEASE_VERSIONSinto the response — single source of truth, no other call sites to update.
Follow-ups (non-blocking — file as issues)
task-handlers.ts:10157iterates the pre-release pins for echo-back coverage and still stops at'3.1-rc.4'. Adding'3.1-rc.6'here is coverage parity, not a correctness break — existing pins still echo correctly.- The four-place duplication of the allowlist literal (
task-handlers.ts:639,router.ts:52, plus the tests) is exactly the kind of drift that produced this PR. Worth a follow-up to import the constant into the tests instead of rewriting the literal.
Fix the five test assertions, push, and this is safe to land. Mechanical edit — same shape as the tenant-smoke change already in the diff.
…bump) beta.21 pins the SDK to AdCP 3.1.0-rc.6 (adcp-client #2145), so the storyboard runner negotiates 3.1-rc.6. The training agent's supported-version allowlist stopped at 3.1-rc.4 — a latent skew, since the repo is already on rc.6 — so the agent rejected the runner with VERSION_UNSUPPORTED on the current-source matrix (/sales required-clean vendor_metric_catalog_precondition failed). - Add 3.1-rc.6 to SUPPORTED_RELEASE_VERSIONS (task-handlers.ts) and TRAINING_AGENT_SUPPORTED_RELEASE_VERSIONS (tenants/router.ts). - Bump CURRENT_ADCP_VERSION to 3.1-rc.6 so the agent's current/highest-served version matches the repo (avoids highest != current divergence: a major-pin serves the highest while unpinned validate_input serves CURRENT — both rc.6). - Update tenant-smoke + training-agent.test.ts supported_versions / served-version assertions. Verified: VERSION_UNSUPPORTED cleared; unit suites 481/481; current-source /sales 114/116 clean (canonical_format_validate_input required-clean ✓); the 3 remaining failures are pre-existing local-env artifacts (jwks_uri / account seeding). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
bc1c171 to
19fc980
Compare
There was a problem hiding this comment.
Replay-clock root cause is right and the rc.6 allowlist widening is the right shape. One stale "current version" constant outside this PR's diff will break a sibling CI job under beta.21 — bump it and ship.
Blocking
- Stale
CURRENT_ADCP_VERSIONin the 3.0-compat integration test.server/tests/integration/training-agent-3-0-compat-tools.test.ts:23hard-codesconst CURRENT_ADCP_VERSION = '3.1-rc.4'. Line 181 asserts an unpinnedvalidate_inputresponse.adcp_versionequals that constant. After this PR,resolveServedAdcpVersionForToolatserver/src/training-agent/task-handlers.ts:800substitutes the new sourceCURRENT_ADCP_VERSION = '3.1-rc.6', so the response is'3.1-rc.6'and the assertion fails.npm run test:server-integrationruns that file as a job in.github/workflows/build-check.yml:141. The PR opened to unblock CI breaks a different CI job. Bump line 23 to'3.1-rc.6'.
Things I checked
- All five live allowlist literals in this PR are mutually consistent — the two source constants (
server/src/training-agent/task-handlers.ts:639,server/src/training-agent/tenants/router.ts:52) and every hard-coded array assertion inserver/src/training-agent/tenants/tenant-smoke.test.tsandserver/tests/unit/training-agent.test.tsall carry'3.1-rc.6'as the new tail. DEFAULT_ADCP_VERSION = '3.0'correctly stays put. Patch changeset, wire-default unchanged.rc.4references inserver/tests/unit/storyboards.test.ts:191,192,228,236,237are deliberate selector-input fixtures, not "current version" assertions — correctly left alone.- Changeset
.changeset/sdk-beta-21-replay-clock.mdcategorization (patch) matches the wire-impact: no schema change, no protocol surface change, behavior under a new accepted version only. - Lockfile resolves
@adcp/sdk@8.1.0-beta.21with the published integrity hash and no transitive drift. code-reviewer: sound-with-caveats — surfaced the same stale-constant block, no other findings.
Minor nits (non-blocking)
- PR body contradicts the diff. Description claims "
CURRENT_ADCP_VERSIONstays at rc.4 (only the accept-list needs rc.6 to stop rejecting)." The diff bumps it to rc.6 atserver/src/training-agent/task-handlers.ts:641andserver/tests/unit/training-agent.test.ts:49. The changeset prose has it right; the PR body is what's stale. Worth a fix for the next archaeologist — and the fact that the body and diff disagree on what changed is, notably, exactly the shape of the bug above.
Fix the integration-test constant and this is --approve. Replay-clock thread-through reads clean.
There was a problem hiding this comment.
LGTM. Tight, well-isolated CI-unblock — replay-clock fix lives in the SDK, the repo just consumes it plus the rc.6 allowlist addition that beta.21 forces.
Things I checked
SUPPORTED_RELEASE_VERSIONSandTRAINING_AGENT_SUPPORTED_RELEASE_VERSIONSupdated in lockstep (task-handlers.ts:639, router.ts:52). Both are additive —3.1-rc.4stays, no buyer getsVERSION_UNSUPPORTEDon a prior pin.- Every test assertion against the old 4-tuple is bumped (tenant-smoke.test.ts:237, 363; training-agent.test.ts:7400, 8313, 10136, 10157, 10201, 10222). No stragglers.
CURRENT_ADCP_VERSIONbump (task-handlers.ts:641) flows correctly toresolveServedAdcpVersiondefault at task-handlers.ts:800 — unpinned callers now advertise rc.6 as served.- Changeset present and the wire-impact prose in
.changeset/sdk-beta-21-replay-clock.mdis accurate. - The pre-release fixture references at
server/tests/unit/storyboards.test.ts:191,228,236correctly stay on rc.4 — those are pinned hostedComplianceTarget fixtures, not allowlist tuples.
Follow-ups (non-blocking — file as issues)
- Changeset level worth a second look.
patchfor a PR that adds a new value tosupported_versionsand bumpsCURRENT_ADCP_VERSIONis arguably light — the served/advertised current version is wire-visible to every unpinned caller ofget_adcp_capabilities. Not breaking, so not a block, butminoris defensible. Worth a one-line convention note for next time. - Stale "current release candidate" prose in docs.
docs/reference/whats-new-in-3-1.mdx:8,29,55,164anddocs/reference/release-notes.mdx:14,30,188,228still call rc.4 the current RC. Out of scope for a fleet-unblock fix, but file it — the served version no longer matches the docs.
Minor nits (non-blocking)
- PR body contradicts the diff. The body says "
CURRENT_ADCP_VERSIONstays at rc.4 (only the accept-list needs rc.6 to stop rejecting)" but the diff bumps it to rc.6 (task-handlers.ts:641) and the changeset prose correctly describes the bump. The code and changeset agree; only the PR body is stale. Notable for anyone reading the body to build a mental model.
Safe to merge once CI validates the matrix recovers.
What
Bumps
@adcp/sdkto8.1.0-beta.21to fix the persistent3.0-compat /salesCI failure, plus the rc.6 companion the bump requires.1. The replay-clock fix (the headline)
From 2026-06-01,
Storyboards (3.0-compat /sales)failed withcreate_media_buy_replay: IDEMPOTENCY_CONFLICT→64 clean (floor 65). Not branch-specific — main re-run on 06-01 failed identically (it was green 05-31). The idempotency replay test requires the initial and replaycreate_media_buyrequests to be byte-identical, but the storyboard runner'sresolveMediaBuyWindowresolved the flight window with a per-callDate.now(). Once the frozen 3.0.15 fixture'sstart_time(2026-06-01) went past, the window fell to a now-relative default computed independently per step → different canonical payload → conflict. Not self-healing.@adcp/sdk@8.1.0-beta.21(adcp-client #2149, closing #2147) threads a stable per-run clock (runStartMs) intoresolveMediaBuyWindowso both steps enrich identically.2. rc.6 companion (
fix(training-agent): support AdCP 3.1-rc.6)beta.21 also pins the SDK to AdCP 3.1.0-rc.6 (adcp-client #2145), so the runner now negotiates
3.1-rc.6. The training agent's supported-version allowlist stopped at3.1-rc.4— a latent skew, since the repo is already on rc.6 — so it rejected the runner withVERSION_UNSUPPORTEDon the current-source matrix. Added3.1-rc.6toSUPPORTED_RELEASE_VERSIONS+TRAINING_AGENT_SUPPORTED_RELEASE_VERSIONSand the tenant-smoke assertions.CURRENT_ADCP_VERSIONstays at rc.4 (only the accept-list needs rc.6 to stop rejecting).Verification (local, pre-push matrix green on both)
/sales65 / 304 steps; 0IDEMPOTENCY_CONFLICT.✓ All tenants meet floors;/salesrecovered 107 → 114/116 clean; 0VERSION_UNSUPPORTED.Scope
package.json+ lockfile + 2 version allowlists + 2 test assertions + changeset. No protocol/schema changes. Fleet-blocking — unblocks main and every open PR on3.0-compat /sales.🤖 Generated with Claude Code