# CB-EV-0028 — a number that does not move CB-WP-0030 T04. Tier M (structural M — adds an admissibility requirement; chaos d8 = 7 → no override). **Declaration 1 of chaos window 3**, opened 2026-08-07 by ADR-0017. Closed 2026-08-07. **Delivered:** [ADR-0018](../decisions/ADR-0018-a-number-that-does-not-move.md), `GameDesign.md` §1.4, `check_sensitivity_stated` in `loop-lint` with four self-test controls, and a mutation proof that it goes red on a real row. --- ## 1. The seven instances, re-run against the rule The workplan's own falsifier: **if fewer than 3 of 7, the rule is not the one.** | # | the claim | caught? | by what, exactly | |---|---|---|---| | 1 | `csv` costs 21,613 against 3,798 of headroom | **yes** | vary which crates AM-4a scopes and the headroom moves — that *is* the error | | 2 | *"12 in the file"* | no | §1.2's row-level rule, born from it, does | | 3 | SOLVE offered on a face-down Problem | no | **not a number** | | 4 | 112–161 µs per node | **yes** | cost must rise with branching; it fell | | 5 | too easy at 5–6 seats | **yes** | vary the policy, the rate goes 100% → 0% on the same deals | | 6 | 2 Focus/Blame conflicts | **partly** | varying seat count scales a real conflict; a phantom one need not | | 7 | window 2 had zero overrides | no | **a count never made has no sensitivity** | **Three clear, one partial, three missed.** Above the falsifier, and not by much. **The distribution matters more than the count.** The two it catches outright, 4 and 5, are the two that travelled furthest — instance 4 sat in a published survey, instance 5 was queued for `ground-game`, which was blocked on that exact number. **The three it misses were each caught by a human re-reading**, which is the mechanism the rule generalises and cannot replace. **Row 6 is honestly "partly" and stays that way.** A phantom conflict from comparing the wrong disc set *might* scale with seats too. The variation would have prompted the question *what am I comparing*, which is what actually found it — but that is the rule working as a **prompt**, not as a test, and writing it down as a catch would inflate the yield. ## 2. What the untagged surface is worth, since it was measured `facts-check` reports **62 untagged literal copies** across 7 registry keys and fails on none. **Against this family it is worth 1 of 7, and arguably 0.** Instance 1's denominator was a registry fact and was **correct** — 3,798 *is* AM-4a's target. The error was that AM-4a does not cover the code being priced. A provenance tag would have reproduced the wrong subject faithfully and with a citation. > **A tag proves a number came from somewhere. It cannot prove the > somewhere was the right place.** Instances 2, 4, 5 and 6 were **fresh measurements** — there was no registry key to tag. **It is still worth closing, for a different failure mode**: a literal that drifts from its registry key is a copy that disagrees, and `facts-check` exists for exactly that. **Named as separate work and not done here** — bundling it would have let this pass claim a victory it did not win, which is this family's own error applied to itself. ## 3. Is a presence-only lint worth having The strongest argument against: **a green lint reads as "the claim was verified."** If it trains the eye to stop at green, it is worse than nothing, because five of the seven instances were caught by an eye that did not stop. Three things decide it in favour. **It says what it is, in its own output.** The finding text ends *"NOTE: this checks presence, not adequacy."* A reader who stops at green is stopping against an explicit statement rather than an implied one. **Its cost is bounded by scope.** It binds arithmetic register rows, not every number in every artifact — 62 untagged literals are this project's own evidence of what an unenforced everywhere-rule produces (ADR-0018 D4). **The failure it prevents is forgetting, and forgetting is what happened.** `RetrospectiveAnalysis` §4.1's policy panel and `attack-value.rs`'s one-varying-number sweep both exist. Both were built **after** an instance. Nothing asked for either **before**. **Verdict: worth having, on the condition it never grows a claim it cannot cash.** The moment its output implies verification, ADR-0006 D3 and ADR-0017 D2 both apply and it should be deleted. ## 4. The check fired on three real rows, and all three were wrong to fire First run: F12, F15, F21 — **every one a `note`**. A note is by definition a finding **without** a reproduction (GameDesign §3.1). There is no measurement, so there is nothing for a sensitivity statement to be about; the check was demanding one anyway. **The fix went into the check, not into three exemptions.** Three hand-written `sensitivity-exempt` comments would have produced green with the rule still wrong, and the next note would have needed a fourth. **That is the difference between a rule and a pile of special cases**, and the exemption mechanism exists for genuine one-offs, not for a category the rule should never have covered. ## 5. The mutation, and the moment it nearly passed as proof The control is that the check **fails on a real row** — a lint that cannot go red is decoration. **The first mutation attempt did not fire, and I nearly read that as a failed check.** I had rewritten two phrases in F17's prose ("varies exactly one number" → "uses a policy") and expected red. Green. A debug probe showed F17 *was* being reached, kind `degenerate`, state `raised`, prose found — and still matched, because the text elsewhere said *"one number varied."* **The check was right and the mutation was incomplete.** Stripping every trigger word produces: ``` [sensitivity] specs/FindingRegister.md F17 (degenerate) states a quantity and names no variable it depends on (GameDesign §1.4). ... NOTE: this checks presence, not adequacy. ``` and restoring the file returns it to green. **This is worth recording because the near-miss is the same family.** *"The lint does not fire"* was a correct observation about the wrong subject — I had measured my mutation, not the check. A debug probe printing what the check actually saw settled it in one run, which is the second-computation mechanism §1 credits with catching all seven. **Four self-test controls**, because a check that cannot say NO is decoration and one that cannot say YES fires on everything: it catches a bare arithmetic claim, **clears one that names its variable**, skips non-arithmetic kinds, and skips notes. ## 6. A vocabulary defect, caught by a gate that already existed This workplan shipped as `kind: process`. The vocabulary is **product | meta | mixed**, and `make self-tests` said so immediately. **No new control was needed and none was added.** Corrected to `meta` — the workplan changes how the loop constrains its own operation, which is what `meta` means. Worth one line here because the pass that added a gate was itself caught by an older one, working exactly as intended. ## 7. Cost `make cost`, not inlined (§Single source of fact). CB-EV-0019 §4's unbounded chain is still unbounded. ## Open after this pass - **The untagged-facts surface** (§2) — 62 copies, measured, deferred, unclosed. - **The rule catches 3½ of 7 and the family is not closed.** Instances 3 and 7 need different controls: a wrong condition is not a number, and a count never made needs counting. - **The lint's honesty is a claim about readers, not code** (§3), and only a later pass reading a green run tests it. - **F18** — `Relations`, `DARVO`, `Player_Mats`, `Glossary` unvendored; still the only open register row with no reproduction. - **Three of four scenarios never dealt**, carried from ADR-0015 D5.