Filed by the domain:spec execution seat, session session_01KB5PFtxuy1x3dcR5gxudx6, 2026-09-16T17:26Z, out of the at-tier contract review of PR #18486 (card #18123), record 5701703741, flag F3 — 「ESCALATED, PM to file」. ⛔ Unlabelled beyond finding and unassigned; grading and routing are triage's.
The defect: a mutation can shrink the battery while the printed count stays non-zero
packages/spec/scripts/check-duration-unit-keys.ts predates the SELF_TEST_BATTERIES / floor / handshake discipline. It has no battery roster, no pinned per-battery minimum, and no module-level verdict flag — so a return above its verdict would print nothing and exit 0.
Measured, twice, on two different heads:
empty the DURATION_ROOTS map:
at the PR head 103 registered → 101 registered (95 green + 6 red)
at the prior head 101 registered → 99 registered (94 green + 5 red)
⇒ the two per-root module-coupling cases are generated by iterating the map (for (const root of DURATION_ROOTS.keys())), so emptying the map de-registers them. The battery shrinks by 2 and the printed count is still a plausible non-zero number. ⭐ A reader watching the count would see 101 and conclude the suite ran; what actually happened is that two of its cases stopped existing.
⚠️ This is the 「a printed case count is EVIDENCE, NOT PROOF」 shape, and it is measured here rather than hypothesised. A floor would catch it; there is no floor.
Two residual vacuous cases, carried here rather than filed separately
The same review measured two cases that stay green under the vocabulary ablation while naming the vocabulary:
compliant by TYPE: name, describe and type all agree — expects '', which 0 sites also satisfies.
the declared duration units are units this reader actually knows — an every over an empty map, which is vacuously true.
⇒ population 2, same root cause (no floor, no handshake), so they belong in the same retrofit rather than in their own card.
⭐ For contrast, the case that was tightened in PR #18486 now discriminates: the old rulesOf(...).join() === '' read true on a site outside the population and true under ablation; the new assertion reads false on both and true only on the admitted DurationMs site. ⇒ the retrofit shape is known to work; it just has not been applied to the rest of the file.
What the round owes
- Give this gate the three parts
scripts/check-agent-model-declared.mjs carries — SELF_TEST_BATTERIES, SELF_TEST_BATTERY_FLOOR, selfTestReachedVerdict — per AGENTS.md's 「Copy a landed one — ⛔ never import one」. ⚠️ Copy it, ⛔ do not import it: each self-test must keep running standalone as node scripts/<x>.mjs --self-test.
- Make the two vacuous cases above discriminate, using the tightening already landed in this file as the pattern.
- ⚠️ Prove the floor bites: with the roster in place, de-register a battery and show the run goes red on the floor rather than merely printing a smaller number. ⛔ A floor you never saw fire is the same defect one level up.
⛔ Scope fences
Dedupe words
check-duration-unit-keys SELF_TEST_BATTERIES · self-test floor retrofit duration-unit-keys · de-register case count · selfTestReachedVerdict · printed count is evidence not proof
Refs
#18123 / PR #18486 (where it was measured) · scripts/check-agent-model-declared.mjs (the landed pattern) · #18124 (step 3 on this same gate's vocabulary) · #18500 (dimensionless renderer half, the other owed half of this gate's mechanism — already filed, ⛔ not this card)
Generated by Claude Code
Filed by the
domain:specexecution seat, sessionsession_01KB5PFtxuy1x3dcR5gxudx6, 2026-09-16T17:26Z, out of the at-tier contract review of PR #18486 (card #18123), record5701703741, flag F3 — 「ESCALATED, PM to file」. ⛔ Unlabelled beyondfindingand unassigned; grading and routing are triage's.The defect: a mutation can shrink the battery while the printed count stays non-zero
packages/spec/scripts/check-duration-unit-keys.tspredates theSELF_TEST_BATTERIES/ floor / handshake discipline. It has no battery roster, no pinned per-battery minimum, and no module-level verdict flag — so areturnabove its verdict would print nothing and exit 0.Measured, twice, on two different heads:
⇒ the two per-root module-coupling cases are generated by iterating the map (
for (const root of DURATION_ROOTS.keys())), so emptying the map de-registers them. The battery shrinks by 2 and the printed count is still a plausible non-zero number. ⭐ A reader watching the count would see101and conclude the suite ran; what actually happened is that two of its cases stopped existing.Two residual vacuous cases, carried here rather than filed separately
The same review measured two cases that stay green under the vocabulary ablation while naming the vocabulary:
compliant by TYPE: name, describe and type all agree— expects'', which 0 sites also satisfies.the declared duration units are units this reader actually knows— aneveryover an empty map, which is vacuously true.⇒ population 2, same root cause (no floor, no handshake), so they belong in the same retrofit rather than in their own card.
⭐ For contrast, the case that was tightened in PR #18486 now discriminates: the old
rulesOf(...).join() === ''read true on a site outside the population and true under ablation; the new assertion reads false on both and true only on the admittedDurationMssite. ⇒ the retrofit shape is known to work; it just has not been applied to the rest of the file.What the round owes
scripts/check-agent-model-declared.mjscarries —SELF_TEST_BATTERIES,SELF_TEST_BATTERY_FLOOR,selfTestReachedVerdict— perAGENTS.md's 「Copy a landed one — ⛔ never import one」.node scripts/<x>.mjs --self-test.⛔ Scope fences
skip-changeset).Dedupe words
check-duration-unit-keys SELF_TEST_BATTERIES·self-test floor retrofit duration-unit-keys·de-register case count·selfTestReachedVerdict·printed count is evidence not proofRefs
#18123 / PR #18486 (where it was measured) ·
scripts/check-agent-model-declared.mjs(the landed pattern) · #18124 (step 3 on this same gate's vocabulary) · #18500 (dimensionlessrenderer half, the other owed half of this gate's mechanism — already filed, ⛔ not this card)Generated by Claude Code