CB-WP-0030: a control for the wrong-subject family
Some checks failed
ci / check (push) Failing after 4s
Some checks failed
ci / check (push) Failing after 4s
Seven claims in this project have been wrong the same way — the arithmetic right, the subject wrong. Four reached a document or another repo. ADR-0018 states the rule: a measured claim names the variable it depends on and shows the measurement moving with it. GameDesign §1.4 adds it as a fourth admissibility clause; the existing three are untouched. Honest yield is 3 clear + 1 partial of 7. It misses a count never made and a claim that is not a number, and D3 names those so nobody stops looking. The tempting fix — closing facts-check's 62 untagged literals — would have caught 1 of 7 and is deferred as separate work rather than bundled. loop-lint gains check_sensitivity_stated over arithmetic register rows, mutation-proven red on F17 and green when restored, with four self-test controls. It checks presence, never adequacy, and says so in its output. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
ffd2279e16
commit
d7279483f6
6 changed files with 503 additions and 6 deletions
168
evidence/CB-EV-0028-a-number-that-does-not-move.md
Normal file
168
evidence/CB-EV-0028-a-number-that-does-not-move.md
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue