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
|
|
@ -1,6 +1,12 @@
|
|||
//! cb-events — event envelope, append-only log, snapshots, canonical
|
||||
//! serialization, and state hashing (GameKernel §2.4, K4, K7, K9–K11).
|
||||
|
||||
pub mod store;
|
||||
|
||||
pub use store::{
|
||||
conformance as log_store_conformance, FileLogStore, LogStore, MemLogStore, StoreError,
|
||||
};
|
||||
|
||||
use cb_kernel::{EventSeq, GameId};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
|
@ -15,9 +21,12 @@ pub struct Envelope<E> {
|
|||
pub payload: E,
|
||||
}
|
||||
|
||||
/// In-memory append-only event log. File-backed storage arrives in a later
|
||||
/// loop pass behind the same interface (AM-11 pairs this with storage
|
||||
/// impls under one conformance suite).
|
||||
/// In-memory append-only event log of typed envelopes.
|
||||
///
|
||||
/// Durable framing and the `LogStore` port live in [`store`]; this type is
|
||||
/// the typed, sequence-enforcing layer above it. Until CB-WP-0006 T05 the
|
||||
/// comment here promised file-backed storage "in a later loop pass" — that
|
||||
/// pass is this one.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct EventLog<E> {
|
||||
events: Vec<Envelope<E>>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue