CB-WP-0006 T05: K9's assertion, K11's format, and the AM-11 suites
K11 is implemented: crates/cb-events/src/store.rs, magic + version header, 4-byte little-endian length prefix, append-only. Reimplemented not assimilated per ADR-0005 §2 — no new dependency, and AM-4a/AM-4b are unchanged at 246,250 / 317,021 because nothing entered the graph. The operative clause is "detected", so corruption is tested rather than assumed: a tail short by one byte, a half-written length prefix, a length prefix corrupted to claim more than the file holds, foreign magic, and a future format version are each rejected with a distinct error. A reader that accepts a truncated tail is worse than no format, because it silently returns a short history that looks complete. AM-11 is earned. LogStore has two impls — MemLogStore and FileLogStore — driven through ONE conformance(). The trait carries raw/set_raw precisely so the corruption controls live in the shared suite: a format contract that only one impl enforces is not a contract. The same shape is retro-fitted to KernelRng, which is what AM-11 actually names: ChaChaRng and NullRng now pass one suite asserting bounds, draw(1) == 0, determinism across fresh instances, and shuffle preserving the multiset. They were previously exercised by two separate tests, which is why "met, narrow" was never earned and ADR-0005 §4 downgraded it. K9 gets the assertion it did not have: snapshot at seq N + events N+1..M must equal the from-genesis fold, hash-compared, on GroundState, single-seed on purpose — AM-7's probe folds a multi-seed log, which is not a replay of anything, and that defect is not repeated. Two positive controls: the log must exceed 50 events, and the mid-log snapshot must differ from the end state or "apply the remainder" is vacuous. Proof it works: the exact mutation that SURVIVED in CB-WP-0005 — making Snapshot::take discard its EventSeq — now fails on the K9 assertion. AM-11's mutation breaks NullRng::draw to return its bound and the shared suite fails. That is what M-D4-SWAP claims — either impl substitutable — and exactly what two separate per-impl tests could never demonstrate. M-D1-MUT: 7 -> 8 of 14. CB-EV-0001's scoreboard is refreshed: AM-2, AM-5 and AM-9 added, AM-6 moved to enforced, and the headline total corrected from 4 to 8 — it had gone stale inside the same workplan that produced it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
5f7d9015d9
commit
98c6cd24c3
12 changed files with 638 additions and 19 deletions
|
|
@ -211,3 +211,60 @@ become weak when the row's measurement conditions change.**
|
|||
|
||||
**M-D1-MUT: 7 of 14** (unchanged — AM-4c was always going to stay
|
||||
uncounted; what changed is that the reason is now correct and recorded).
|
||||
|
||||
## CB-WP-0006-T05
|
||||
|
||||
**Delivered: K9's real assertion, K11's durable format, the `LogStore`
|
||||
port, and the shared conformance suites that finally earn AM-11.**
|
||||
|
||||
**K11 — `crates/cb-events/src/store.rs`.** Magic + version header, 4-byte
|
||||
little-endian length prefix per record, append-only. Reimplemented, not
|
||||
assimilated (ADR-0005 §2): no new dependency, charged to AM-4a, and
|
||||
AM-4a/AM-4b are unchanged at 246,250 / 317,021 because nothing was added
|
||||
to the graph.
|
||||
|
||||
The operative clause is **detected**, so corruption is tested, not assumed:
|
||||
a tail short by one byte, a half-written length prefix, a length prefix
|
||||
corrupted to claim more than the file holds, foreign magic, and a future
|
||||
format version are each rejected with a distinct error. A reader that
|
||||
accepts a truncated tail is worse than no format, because it silently
|
||||
returns a short history that looks complete.
|
||||
|
||||
**The port and the suite (AM-11).** `LogStore` has two impls —
|
||||
`MemLogStore` and `FileLogStore` — and **one** `conformance()` that both
|
||||
are driven through. The trait carries `raw`/`set_raw` specifically so the
|
||||
corruption controls live in the *shared* suite: a format contract only one
|
||||
impl enforces is not a contract.
|
||||
|
||||
The same shape was retro-fitted to `KernelRng`, which is what AM-11
|
||||
actually names. `ChaChaRng` and `NullRng` now pass one
|
||||
`conformance()` asserting the properties true of both — bounds,
|
||||
`draw(1) == 0`, determinism across fresh instances, and shuffle preserving
|
||||
the multiset. Previously they were exercised by two *separate* tests,
|
||||
which is precisely why `AM-11 | met, narrow` was never earned and ADR-0005
|
||||
§4 downgraded it.
|
||||
|
||||
**K9 — the assertion it did not have.** *Snapshot at seq N + events
|
||||
N+1..M ≡ genesis fold*, hash-compared, on `GroundState`, single-seed on
|
||||
purpose (AM-7's probe folds a multi-seed log, which is not a replay of
|
||||
anything; that defect is not repeated). Two positive controls: the log
|
||||
must exceed 50 events, and the mid-log snapshot must **differ** from the
|
||||
end state, or "apply the remainder" would be vacuous.
|
||||
|
||||
**Proof it works:** the exact mutation that *survived* in CB-WP-0005 —
|
||||
making `Snapshot::take` discard its `EventSeq` — now fails:
|
||||
|
||||
```text
|
||||
assertion `left == right` failed: K9: the snapshot must carry the EventSeq it includes
|
||||
test result: FAILED. 0 passed; 1 failed
|
||||
```
|
||||
|
||||
**AM-11 mutation:** break `NullRng::draw` to return its bound and the
|
||||
*shared* suite fails. That is what M-D4-SWAP claims — that either impl can
|
||||
be substituted — and it is exactly what two separate per-impl tests could
|
||||
never demonstrate.
|
||||
|
||||
**M-D1-MUT: 7 → 8 of 14.** `evidence/CB-EV-0001`'s scoreboard is refreshed
|
||||
with AM-2, AM-5 and AM-9 added, AM-6 moved to enforced, and the headline
|
||||
total corrected from 4 to 8 — it had gone stale within the same workplan
|
||||
that produced it.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue