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>
168 lines
7.6 KiB
Markdown
168 lines
7.6 KiB
Markdown
# 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.
|