Summary
9 unit tests fail on a clean main checkout. They are not caught by CI today — test:server-unit is not gated on the release.yml / deploy.yml push workflows, only on precommit (and pre-commit only runs test:unit, not test:server-unit).
Discovered while landing #2273 — confirmed pre-existing on main by stash + retest, then again by cloning main fresh and running.
Reproduction (commit e6dc441):
git clone --depth 50 https://github.com/adcontextprotocol/adcp.git
cd adcp
npm ci
npm run test:server-unit -- \
server/tests/unit/storyboards.test.ts \
server/tests/unit/comply-test-controller.test.ts \
server/tests/unit/mcp-response-unwrap.test.ts
# Test Files 3 failed | 60 passed | 1 skipped (64)
# Tests 9 failed | 1544 passed | 34 skipped (1587)
All three test files were last touched by PR #2165 (commit b891973), but the failures look like product-side regressions, not test bitrot — see the storyboards group below, which lines up with the storyboard restructure in PR #2265.
Failures
server/tests/unit/storyboards.test.ts (2 failed)
Likely fallout from PR #2265 (storyboards moved into /compliance/{version}/). Phase IDs and task names referenced by the tests no longer appear in the bundles.
media buy storyboard > media_buy_seller covers the full buy lifecycle (line 268)
Expected phaseIds to include 'proposal_refinement'. Got [ 'capability_discovery', …(6) ] without that phase.
brand_rights storyboard > covers brand identity discovery and rights lifecycle (line 692)
Expected tasks to include 'update_rights'. Got [ 'get_adcp_capabilities', …(5) ] without it.
server/tests/unit/comply-test-controller.test.ts (6 failed)
State transitions and delivery simulation not behaving as the tests expect. Reads like a real regression in comply_test_controller.
force_account_status > transitions account through valid states (line 339)
expected 'active' to be 'suspended' — the transition from "active" → "suspended" doesn't stick.
force_account_status > rejects transition from terminal state (line 361)
expected true to be false — terminal transition is being accepted instead of rejected.
force_account_status > blocks create_media_buy when account is suspended (line 411)
expected undefined to be true — the guard appears to no-op (returns undefined where a boolean is asserted).
force_session_status > rejects transition from terminal state (line 554)
Same shape as account version: expected true to be false.
simulate_delivery > injects delivery data and reflects in get_media_buy_delivery (line 609)
expected 0 to be greater than or equal to 10000 — injected delivery isn't being read back.
simulate_delivery > is additive across calls (line 629)
expected 3000 to be 8000 — second call replaces rather than accumulates.
server/tests/unit/mcp-response-unwrap.test.ts (1 failed)
error response handling > extracts structuredContent-only MCP errors when present (line 191)
Asserts unwrapped.errors[0].code === 'RATE_LIMITED' after isAdcpError(unwrapped) === true passes, but the unwrap doesn't surface the error code from the structuredContent-only path.
Why CI didn't catch this
test:server-unit is run by the local precommit hook (sort of — the precommit script actually only runs test:unit && typecheck, not test:server-unit), and there's no GitHub Actions workflow that runs test:server-unit on PRs. The current precommit definition:
\"precommit\": \"npm run test:unit && npm run typecheck\"
Recommendation as part of the fix: add npm run test:server-unit to a CI workflow (e.g. build-check.yml), so future regressions are caught at PR time rather than discovered ad-hoc.
Probable owners
cc: this is unblocking #2273 (signed protocol tarballs) — that PR's typecheck and test:unit are clean; these failures predate it.
Summary
9 unit tests fail on a clean
maincheckout. They are not caught by CI today —test:server-unitis not gated on therelease.yml/deploy.ymlpush workflows, only onprecommit(and pre-commit only runstest:unit, nottest:server-unit).Discovered while landing #2273 — confirmed pre-existing on
mainby stash + retest, then again by cloningmainfresh and running.Reproduction (commit
e6dc441):All three test files were last touched by PR #2165 (commit
b891973), but the failures look like product-side regressions, not test bitrot — see the storyboards group below, which lines up with the storyboard restructure in PR #2265.Failures
server/tests/unit/storyboards.test.ts(2 failed)Likely fallout from PR #2265 (storyboards moved into
/compliance/{version}/). Phase IDs and task names referenced by the tests no longer appear in the bundles.media buy storyboard > media_buy_seller covers the full buy lifecycle(line 268)Expected
phaseIdsto include'proposal_refinement'. Got[ 'capability_discovery', …(6) ]without that phase.brand_rights storyboard > covers brand identity discovery and rights lifecycle(line 692)Expected
tasksto include'update_rights'. Got[ 'get_adcp_capabilities', …(5) ]without it.server/tests/unit/comply-test-controller.test.ts(6 failed)State transitions and delivery simulation not behaving as the tests expect. Reads like a real regression in
comply_test_controller.force_account_status > transitions account through valid states(line 339)expected 'active' to be 'suspended'— the transition from "active" → "suspended" doesn't stick.force_account_status > rejects transition from terminal state(line 361)expected true to be false— terminal transition is being accepted instead of rejected.force_account_status > blocks create_media_buy when account is suspended(line 411)expected undefined to be true— the guard appears to no-op (returns undefined where a boolean is asserted).force_session_status > rejects transition from terminal state(line 554)Same shape as account version:
expected true to be false.simulate_delivery > injects delivery data and reflects in get_media_buy_delivery(line 609)expected 0 to be greater than or equal to 10000— injected delivery isn't being read back.simulate_delivery > is additive across calls(line 629)expected 3000 to be 8000— second call replaces rather than accumulates.server/tests/unit/mcp-response-unwrap.test.ts(1 failed)error response handling > extracts structuredContent-only MCP errors when present(line 191)Asserts
unwrapped.errors[0].code === 'RATE_LIMITED'afterisAdcpError(unwrapped) === truepasses, but the unwrap doesn't surface the error code from the structuredContent-only path.Why CI didn't catch this
test:server-unitis run by the localprecommithook (sort of — theprecommitscript actually only runstest:unit && typecheck, nottest:server-unit), and there's no GitHub Actions workflow that runstest:server-uniton PRs. The currentprecommitdefinition:\"precommit\": \"npm run test:unit && npm run typecheck\"Recommendation as part of the fix: add
npm run test:server-unitto a CI workflow (e.g.build-check.yml), so future regressions are caught at PR time rather than discovered ad-hoc.Probable owners
storyboards.test.tsfailures → owner of PR feat(compliance): move storyboards into protocol + domains/specialisms model (#2176) #2265 (storyboard restructure)comply-test-controller.test.tsfailures → owner of recentcomply_test_controllerworkmcp-response-unwrap.test.tsfailure → owner of recent MCP response unwrap changescc: this is unblocking #2273 (signed protocol tarballs) — that PR's typecheck and
test:unitare clean; these failures predate it.