Some checks failed
ci / check (push) Failing after 3s
The rule adopted in CB-EV-0012 -- quote the previous pass's final cost, never your own -- was applied here for the first time and did not hold. This file opened quoting CB-WP-0014 at $7.47/34, which is what make status reported then; by the close it read $8.56/48. A pass's window runs to the next pass's first commit, so the previous pass is not final until the pass after it starts. The rule fixed the wrong boundary. Recorded as owed rather than changed silently. Also: CB-EV-0009's prediction now has a point on each side. CB-WP-0014 opened above the SH-1 hard line at 0.220 $/response; CB-WP-0015 opened below it, after a compaction, at 0.111. Both on the predicted side, and the second is the control the last report said was missing -- but n=2, different tiers and subjects, and the compaction that supplied the control is also what makes the passes differ. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
232 lines
11 KiB
Markdown
232 lines
11 KiB
Markdown
# CB-EV-0013 — two inert clauses, and an estimator that was wrong twice
|
||
|
||
CB-WP-0015 T03. Measured 2026-08-02 at `7e9ab22`+. Pass kind `product`,
|
||
tier **S** (chaos d4=2, no override). Declaration 10 of 12.
|
||
|
||
Per the rule adopted in CB-EV-0012, the cost table quotes **CB-WP-0014's**
|
||
figure and declines to quote this pass's own — and §5 records that the
|
||
rule, applied here for the first time, **did not hold**: the number moved
|
||
15% between the start of this pass and its end.
|
||
|
||
---
|
||
|
||
## 1. The machine wanders by 2.5×, and that is the whole story
|
||
|
||
Before any of this could be measured, the instrument had to survive the
|
||
machine. Folding the same log on an unchanged binary, seconds apart:
|
||
|
||
| leg | observed range, one afternoon |
|
||
|---|---|
|
||
| 5,000-event fold | 11.2 M – 55.7 M ev/s |
|
||
| 100,000-event fold | 9.7 M – 45.9 M ev/s |
|
||
|
||
**A 5× swing in absolute throughput.** Any single reading of either number
|
||
is worthless, and AM-6 already knew this — it takes best-of-3 and says so.
|
||
What AM-6's estimator cannot do is survive being turned into a ratio.
|
||
|
||
## 2. AM-7's scaling clause: three estimators, two of them wrong
|
||
|
||
`mutation-check` had said the same thing every run since CB-WP-0005: *"no
|
||
code computes the ratio of throughput @100k to @5k or compares it to 0.9;
|
||
Criterion reports both and nothing relates them."* Worse, the test next to
|
||
it is called `replay_100k_events_is_linear_and_fast` and checks the two
|
||
sizes **independently** — it computes both numbers, prints both, and never
|
||
divides one by the other. **The name asserts the property the body does
|
||
not test.**
|
||
|
||
| estimator | result on an unchanged binary | why it failed |
|
||
|---|---|---|
|
||
| best-of-5 per leg, then divide (AM-6's) | **0.581 – 1.085** | the legs are measured minutes apart; noise multiplies rather than cancels |
|
||
| legs back-to-back inside one sample | medians 1.004 / 0.931 / 0.956 | closer, but a 50 ms leg samples a *point* on the drift rather than averaging it |
|
||
| legs interleaved per fold, 10 M events each, median of 9 | **0.987 / 0.991 / 0.989** | drift becomes common-mode and divides out |
|
||
|
||
The third one holds up under abuse: with eight busy-loops pinned against
|
||
eight cores, absolute throughput fell 4× and the **median ratio stayed at
|
||
0.989**. Inside a real `make all`, after the build has just hammered every
|
||
core, it read **0.965** (worst sample 0.944) — the condition the first
|
||
guard failed on, now passing with margin.
|
||
|
||
**The measured answer is ~0.97–0.99 against a 0.9 floor.** Nothing in
|
||
`GroundState` grows with log length, so the fold is O(1) per event by
|
||
construction; the residual few percent is cache residency on streaming a
|
||
20×-longer `Vec`.
|
||
|
||
### The guard that was wrong for the same reason the estimator was
|
||
|
||
The first version declared INDETERMINATE if *any* sample fell on the other
|
||
side of the floor — unanimity. Under contention the median read 0.971,
|
||
which is a good measurement, and one sample read **0.899** — a thousandth
|
||
under — and the guard failed the build. It also fired intermittently
|
||
inside `mutation-check`, where this test runs straight after a 50-second
|
||
rebuild.
|
||
|
||
A gate that fails when the machine is busy is a flake, and a flake gets
|
||
suppressed rather than fixed. It now requires a **two-thirds majority**
|
||
agreeing with the median: the guard keeps its purpose — refusing to read a
|
||
coin-flip as a verdict — without treating one outlier as one.
|
||
|
||
### The mutation, and the control that says AM-7 is not a second AM-6
|
||
|
||
To make the property false you must make fold cost grow *with history*,
|
||
which is precisely boardgame.io's measured defect. Growing the deck by one
|
||
card per fold and scanning it drives the ratio to **0.751** — red, tight,
|
||
no straddle.
|
||
|
||
**And the control matters more than the mutation.** AM-6's mutation adds a
|
||
*constant* per-event cost. It halves throughput, 28 M → 15 M ev/s, and
|
||
leaves this ratio at **0.999× — green**. The two rows catch different
|
||
things: a constant slowdown is AM-6's, a history-proportional one is
|
||
AM-7's. Without that check, "AM-7 goes red" would have been consistent
|
||
with AM-7 being a redundant copy of a row we already had.
|
||
|
||
## 3. AM-8's N: the spec was right and the runner was wrong
|
||
|
||
Eight passes of the runner executing each scenario **twice** while the row
|
||
said ten. Closing it needed an argument, because *"the spec says ten"* is
|
||
not one.
|
||
|
||
A **deterministic** divergence — a seed threaded wrong, an order-dependent
|
||
fold — shows on run 2 exactly as reliably as on run 10. For that class the
|
||
double-run is sufficient and eight more runs across 25 scenarios cost 47 s
|
||
a build to re-answer an answered question.
|
||
|
||
**The measurement settled it.** Perturbing the RNG only from its fourth
|
||
construction onward, on `gr-r06-round-resolve`:
|
||
|
||
| | result |
|
||
|---|---|
|
||
| `cb-sim --runs 2` | **PASS** |
|
||
| `cb-sim --runs 10` | FAIL — *"run 1 hash … != run 4 hash … (of 10)"* |
|
||
|
||
A late-onset divergence is a real class the double-run structurally cannot
|
||
see, and it is **deterministic, not probabilistic** — so it can be a
|
||
control rather than a coin flip. The spec value stands unamended; what
|
||
changed is that it is now enforced, on one scenario in `make am8` (~2 s)
|
||
rather than on all 25.
|
||
|
||
The primary defence against the *probabilistic* class remains the
|
||
`HashMap`/`HashSet` deny lint — this row's other clause, already live.
|
||
Ten runs are defence in depth against that exclusion failing, which is why
|
||
one workload's worth is proportionate rather than 25.
|
||
|
||
## 4. What the acceptance table now claims
|
||
|
||
| row | before | after |
|
||
|---|---|---|
|
||
| AM-7 | PARTIAL 2/3 | **red, 3/3** |
|
||
| AM-8 | PARTIAL 1/2 | **red, 2/2** |
|
||
|
||
**M-D1-MUT: 10 of 14 rows enforced**, from 8. The prediction of record
|
||
(≥10 of 14, from ADR-0005's 9-of-12) is **MET** for the first time.
|
||
|
||
**The denominator did not move, and that was the live risk.** This pass
|
||
could have improved its score two ways, and one of them was deleting a
|
||
question — amending AM-8's N down to 2, or splitting AM-7's scaling clause
|
||
into a fifteenth row. Both were considered and both were refused. The four
|
||
rows that remain unenforced are the four that were already unenforceable:
|
||
AM-3 blocked on an unbuilt artifact, AM-4c withdrawn and retained on
|
||
purpose, AM-5 declared ungated by the spec, AM-10 withdrawn.
|
||
|
||
### And the run found a third thing, in the instrument itself
|
||
|
||
The first full `mutation-check` of this pass reported **AM-4a
|
||
HARNESS-BROKEN**, and correctly refused to publish any score at all. Its
|
||
mutation still pointed at `"shipped-runtime": 250_000` — the target
|
||
**ADR-0008 D3 moved to 161,000 in CB-WP-0013**. The find-string had been
|
||
stale ever since, because no full mutation-check had been run in between.
|
||
|
||
Positive control 1 doing exactly its job. But it only *can* do that job on
|
||
a full run, and a full run is deliberately not in `make all` — it rebuilds
|
||
the workspace once per mutated row. So a mutation can rot for passes at a
|
||
time while every build stays green.
|
||
|
||
The cheap half of that check needs no build at all: does each find-string
|
||
still occur in the file it names? That is now a `--self-test` assertion,
|
||
and `self-tests` **is** in `make all`. Verified both ways — perturbing the
|
||
target by one digit turns it red naming `AM-4a`, restoring it turns it
|
||
green.
|
||
|
||
Two rows were repaired by this pass and a third by the run that measured
|
||
it. The AM-4 family has now produced four defects, none of them found by
|
||
looking for them.
|
||
|
||
### The tool now measures a claim it used to assert
|
||
|
||
`mutation-check`'s clause flags were hand-maintained booleans saying
|
||
whether an assertion existed — which is the same shape of claim the tool
|
||
was built to stop trusting. A clause may now carry its own verify command
|
||
and mutation, and then its `enforced` flag is **measured**; a declaration
|
||
that disagrees with its own measurement is refused as HARNESS-BROKEN
|
||
rather than reported as either verdict. Two clauses carry one so far, and
|
||
they print as `red*`. The rest still print as the author's word, which is
|
||
what they always were.
|
||
|
||
## 5. Cost, and the prediction that came due
|
||
|
||
| pass | kind | responses | cost | $/response |
|
||
|---|---|---|---|---|
|
||
| CB-WP-0013 | meta | 47 | $8.26 | 0.176 |
|
||
| **CB-WP-0014** | product | 48 | **$8.56** | **0.178** |
|
||
| CB-WP-0015 | product | *provisional — not quoted, per CB-EV-0012 §5* | | |
|
||
|
||
### The self-quoting rule is not enough, and this pass is the proof
|
||
|
||
CB-EV-0012 adopted the rule that an evidence file quotes the **previous**
|
||
pass's final cost and never its own, because four passes running had
|
||
under-reported themselves mid-flight. This file opened by quoting
|
||
CB-WP-0014 at **$7.47 / 34 responses**, which is what `make status` said
|
||
at the time. By the time this pass closed, the same tool reported
|
||
CB-WP-0014 at **$8.56 / 48** — the figure moved by 15% *after* it was
|
||
supposed to be final.
|
||
|
||
The cause is mechanical: a pass's window runs to the next pass's first
|
||
commit, so CB-WP-0014's window was still open until CB-WP-0015 declared.
|
||
**"The previous pass's final cost" is not final until the pass after it
|
||
starts** — the rule fixed the wrong boundary. Quoting from two passes back
|
||
would be safe; that is a change to the rule, and it is recorded here as
|
||
owed rather than made silently.
|
||
|
||
### CB-EV-0009's prediction now has a point on each side
|
||
|
||
It predicted a pass opening above the SH-1 hard line would cost more than
|
||
**0.123 $/response**. For three passes it was untestable because every one
|
||
opened below the line.
|
||
|
||
| pass | SH-1 at open | $/response |
|
||
|---|---|---|
|
||
| CB-WP-0014 | above the 300,000 hard line (347,720) | **0.220** |
|
||
| CB-WP-0015 | below it (237,533, after a compaction) | **0.111** |
|
||
|
||
Both fall on the predicted side, and the second is the **control the last
|
||
report said was missing**. That is a real strengthening — but it is n=2,
|
||
the two passes differ in tier, kind and subject, and the compaction that
|
||
supplied the control is also the thing that makes the passes different.
|
||
Consistent with the prediction; not yet a demonstration of it.
|
||
|
||
**Meta budget: 26% `[OVER]`** the soft 25%, on CB-WP-0013's $8.26 sitting
|
||
in a trailing three with two product passes. No product work was displaced
|
||
and ADR-0006 D2 exempts instrument repair anyway.
|
||
|
||
## 6. Open
|
||
|
||
- **AM-4b's scope defect (408,237 uncounted lines)** and its unmeasured
|
||
proc-macro share. Unchanged from CB-EV-0012 §3.
|
||
- **INTENT stage 1: one human verification** — `cb-play --serve 0`, open
|
||
the URL, confirm the table reads and a drag works. Unchanged.
|
||
- **`python3` as a toolchain dependency was never argued.**
|
||
- **AM-4a still cannot survive stage 2** — 1,741,979 against 161,000.
|
||
- **ADR-0007 D3's acquisition rule** remains unratified, having now
|
||
decided two dependency questions.
|
||
- **AM-3 stays blocked** on an artifact nobody has built, and it is now
|
||
one of only four unenforced rows rather than one of six.
|
||
- **`cb-cost --self-test` failed once and passed on re-run**, on
|
||
*"pass_costs windows sum to the unwindowed total"*, inside a `make all`
|
||
during this session. The obvious hypothesis is that it reads the session
|
||
transcript while this session is appending to it — a self-test racing
|
||
the file it measures. **That is a hypothesis, not a finding: it has not
|
||
been reproduced or instrumented.** Recorded because an intermittent
|
||
positive control is worth more attention than a failing one, and because
|
||
a flake in the tool that prices every pass would be quietly corrosive.
|
||
- **The self-quoting rule fixed the wrong boundary.** §5. Quoting two
|
||
passes back would be safe; the change is owed, not made here.
|
||
- **Chaos: 10 of 12 declarations, 1 override.**
|