# ADR-0018: a number that does not move when its subject moves is measuring something else status: accepted date: 2026-08-07 decided by: agent, under the standing loop authorization tier: M (structural M — adds an admissibility requirement, changing how the loop constrains its own operation; ADR-0006 D5). chaos d8 = 7 → no override. **Declaration 1 of chaos window 3.** references: [CB-WP-0030](../workplans/CB-WP-0030-a-number-that-does-not-move.md), CB-EV-0019 §1 (where the family was named), [GameDesign.md](../specs/GameDesign.md) §1, [RetrospectiveAnalysis.md](../specs/RetrospectiveAnalysis.md) §4.1, [ADR-0017](ADR-0017-chaos-window-2-verdict.md) (instance 7) ## Context Seven claims in this project have been wrong in the same way: the arithmetic was right and the **subject** was not. Four reached a document or another repository. ## D1 — what this does not do, stated first **`facts-check`'s untagged surface is not this family's control.** It reports **62** untagged literal copies across 7 registry keys and fails on none. That is a real gap, and closing it would have caught **at most one** of the seven: - Instance 1's denominator **was** a registry fact and **was correct** — `am4a_target` = 3,798 is right; AM-4a simply does not cover the code being priced. - Instances 2, 4, 5 and 6 were **fresh measurements** with no registry key at all. > **A tag proves a number came from somewhere. It cannot prove the > somewhere was the right place.** The untagged surface is worth closing on its own merits and is **named as separate work**. Bundling it here would let this decision claim a victory it did not win — which is the family's own error, applied to itself. ## D2 — the rule > **A measured claim must name the variable it depends on, and show the > measurement moving with it.** > > **A number that does not move when its subject moves is measuring > something else.** This is not new machinery. It is the generalisation of two things this project already built, each in response to one instance: - `RetrospectiveAnalysis` §4.1's **policy panel** — born from instance 5, which is why a single policy's win rate may not be reported as a difficulty; - `attack-value.rs`'s **one-varying-number sweep** — built for F17, which varies ATTACK's rank and holds everything else fixed. **Both were built after an instance. The rule requires them before.** ## D3 — the yield, instance by instance, including the misses | # | the claim | would D2 have caught it? | |---|---|---| | 1 | `csv` against AM-4a's headroom | **yes** — vary which crates are in scope and the budget moves; that *is* the error | | 2 | *"12 in the file"* | **no** — but §1.2's row-level rule, born from it, does | | 3 | SOLVE's wrong condition | **no** — not a number | | 4 | 112–161 µs per node | **yes** — cost must rise with branching; it fell, and the tell was already printed | | 5 | too easy at 5–6 seats | **yes** — vary the policy and the rate collapses to 0% | | 6 | 2 Focus/Blame conflicts | **partly** — varying seat count would scale a real conflict; it is the weakest row | | 7 | window 2 had zero overrides | **no** — a count that was never made has no sensitivity to state | **Three clear, one partial, three missed.** **The two it catches outright are the two that travelled furthest**, and both were bound for `ground-game`: instance 4 sat in a survey, instance 5 was queued for a repo blocked on that exact number. A control that catches the consequential half is worth having even at 3/7. **What it misses is stated so nobody stops looking.** Instance 7 needs counting, not sensitivity. Instance 3 was not a number. **No syntactic gate detects a wrong subject in general** — it is a semantic error, and claiming otherwise would build a gate that cannot cash out (ADR-0006 D3, ADR-0017 D2). ## D4 — where it binds - **Register findings whose claim is arithmetic** — the same scope GameDesign §1.2 already uses. - **Anything leaving the repo.** Four of the seven were outbound or nearly so, and the recipient caught one we did not. **Not** every number in every artifact. A rule that binds everywhere is obeyed nowhere, and this project has 62 untagged literals as evidence of what a broad, unenforced requirement produces. ## D5 — half of it is mechanical, and only half `loop-lint` can check that a sensitivity line **is present**. It cannot check that the sensitivity is the **right one**, because that is the same judgement the rule exists to force. > **The lint checks presence, not adequacy, and must say so in its own > output** — otherwise a green lint reads as *"the claim was verified"*, > and the control becomes a way of not looking. That is the honest split: the mechanical half stops the requirement being forgotten; the judgement half stays with the author and the reviewer, who between them caught five of the seven. ## Consequences - `GameDesign.md` §1 gains a fourth clause. The existing three are untouched — each was bought by an earlier instance. - `loop-lint` gains a check over the register's arithmetic rows. - Existing rows are brought under it or exempted **with a reason**. - The untagged-facts surface is recorded as separate, unclosed work. ## What was rejected | rejected | why | |---|---| | closing the untagged-facts surface as *the* control | 1 of 7; a tag reproduces a wrong subject faithfully | | requiring a regenerating command on every claim | catches transcription, and six of seven were not transcription errors | | a rule binding every number everywhere | obeyed nowhere; the 62 untagged literals are the evidence | | a lint that claims to verify the claim | it can only see presence, and pretending otherwise trains the eye to stop at green | | stating a yield of "the family is closed" | the family's own error, applied to itself |