diff --git a/workplans/CB-WP-0030-a-number-that-does-not-move.md b/workplans/CB-WP-0030-a-number-that-does-not-move.md new file mode 100644 index 0000000..c5d2898 --- /dev/null +++ b/workplans/CB-WP-0030-a-number-that-does-not-move.md @@ -0,0 +1,157 @@ +--- +id: CB-WP-0030 +kind: process +title: "A number that does not move: a control for the wrong-subject family" +status: ready +--- + +# Purpose + +``` +structural tier M (changes how the loop constrains its own operation — + it adds an admissibility requirement, ADR-0006 D5) +chaos d8 = 7 → no override +declared tier M +``` + +**Declaration 1 of chaos window 3**, opened 2026-08-07 at d8 by ADR-0017. + +## The family, with every instance + +Seven claims in this project have been wrong in the same way. CB-EV-0019 +§1 named it: *this project's arithmetic errors are not in the arithmetic.* + +| # | pass | the claim | what was wrong | caught by | +|---|---|---|---|---| +| 1 | CB-WP-0021 | `csv` costs 21,613 against 3,798 of headroom | AM-4a **never sees** that code | re-deriving in ADR-0011 | +| 2 | → ground-game | *"12 in the file"* | a sum with no deal table | **the recipient** | +| 3 | CB-WP-0018 | SOLVE offered on a face-down Problem | the wrong condition named | implementing the ruling | +| 4 | CB-WP-0025 | 112–161 µs per node | the timer bracketed whole games | **adversarial review** | +| 5 | CB-WP-0025 | the game is too easy at 5–6 seats | a win rate attributed to the game | **adversarial review** | +| 6 | CB-WP-0029 | 2 Focus/Blame conflicts | compared *other* players' discs | re-reading the check | +| 7 | ADR-0017 | window 2 had zero overrides | never counted; cited 4× | writing the verdict | + +## What will not work, measured before proposing anything + +**`facts-check` has a real gap and it is not this one.** It reports **62 +untagged literal copies** across 7 registry keys and fails on none of +them — a drift surface it names and does not close. + +**Closing it would have caught at most one of the seven.** Instance 1's +denominator *was* a registry fact and was *correct*; the error was that +AM-4a does not cover the code. Instances 2, 4, 5, 6 were **fresh +measurements** — no registry key existed, and a provenance tag reproduces +a wrong subject faithfully. + +> **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 **bundling it +here would let this pass claim a victory it did not win.** Named as +separate work, not done here. + +## What did work, and it is one thing + +Read the *caught by* column. Every instance was caught when **the number +was computed a second time by something with a different purpose** — a +later pass, a reviewer, the recipient, or the author re-reading. + +Two of them, 4 and 5, share a sharper property: **the claim was tested +against a variation.** + +- #4's cost **fell** as branching **rose**. A per-node cost cannot do that. + The tell was in the published output. +- #5's win rate was attributed to the game; a second policy on the same + deals gave 0% where the first gave 100%. + +And #1 has it too: vary which crates are in scope and the budget changes, +which is the whole error. + +**So the control is to generalise the thing this project already builds +after each instance** — RetrospectiveAnalysis §4.1's policy panel, +CB-WP-0029's attack-value sweep — and require it *before*: + +> **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.** + +**Honest yield: 3 or 4 of 7**, and it catches the two that travelled +furthest. It does **not** catch #7 (a count never made) or #3 (not a +number). **Claiming it closes the family would be the family's own error +applied to itself.** + +## Task: decide the rule and its limits + +```task +id: CB-WP-0030-T01 +status: todo +priority: high +``` + +`decisions/ADR-0018-*.md`. + +- **State the rule** and where it binds: register findings that carry + arithmetic, and anything leaving the repo. +- **State the yield honestly**, instance by instance, including what it + misses. A control whose reach is overstated is worse than none, because + it stops people looking. +- **Decide whether it is a gate or a discipline.** A sensitivity claim is + prose; `loop-lint` can check *presence*, never *adequacy*. Say which + half is mechanical. +- **Do not bundle the untagged-facts surface.** Name it as separate. + +## Task: the rule, in the spec that governs findings + +```task +id: CB-WP-0030-T02 +status: todo +priority: high +``` + +`specs/GameDesign.md` §1 already requires a reproduction that **exists**, +has the **ruled shape**, and **can fail**. This adds the fourth clause, +because §1.2's row-level rule was itself born from instance 2 and covers +only sums. + +**Controls:** +- the clause names the variable and the expected direction, or it is a + sentence with no content; +- **the existing three clauses are unchanged** — this is an addition, and + a rewrite would silently drop what earlier instances bought. + +## Task: make the mechanical half mechanical + +```task +id: CB-WP-0030-T03 +status: todo +priority: high +``` + +`loop-lint` fails when a register row of an arithmetic kind lacks a +sensitivity line. + +**Controls:** +- the check must **fail on a real row**, demonstrated by mutation — a lint + that cannot go red is decoration (ADR-0006 D3, ADR-0017 D2); +- **it checks presence, not adequacy**, and its output says so, so nobody + reads a green lint as *"the claim was verified"*; +- existing register rows are brought under it or explicitly exempted with + a reason — a rule that only binds future rows leaves the six instances + unprotected. + +## Task: evidence + +```task +id: CB-WP-0030-T04 +status: todo +priority: medium +``` + +`evidence/CB-EV-0028-*.md`. + +- **Re-run the seven instances against the rule** and report how many it + would have caught. If the answer is below 3, the rule is not the one. +- **What the untagged surface is worth**, since it was measured here and + deferred. +- **Whether a lint that checks presence is worth having at all**, or + whether it trains the eye to stop at green.