# ADR-0002: Game-state kernel — survey approval and implementation decision Date: 2026-07-31 Status: accepted Capability: game.kernel.authoritative-state Inputs: research/CB-RES-0001-game-kernel.md (approved), history/260731-game-kernel-{research,challenge,response}.md ## Approval (InnerLoop step 2) The CB-RES-0001 survey is **approved**. It passed one round of adversarial review: the challenge found one blocking overclaim (degradation attribution) and three significant gaps (memory methodology, omitted candidates OpenSpiel/Ludii, unsourced D3 ceiling); all were resolved with new measurements or corrections, none overturned the comparative conclusions. The candidate set is judged adequate; the baselines are trustworthy within their stated provenance (measured vs cited vs estimated), with the event-sourcing ceiling explicitly parity-capped. **Benchmark-to-beat, named:** boardgame.io 0.50.2 per the survey's baseline table (throughput ~1,100–1,900 moves/s degrading with history in every configuration; 120 deps/37 MB; ~36-LOC declarative game definition), plus the **stipulated engineering target** of ≥100,000 applied events/s with flat scaling (@100k within 10% of @5k) and bit-identical replay. ## Decision (InnerLoop step 3): reimplement, assimilating patterns Build the Clay-Borg semantic kernel as **our own Rust implementation** (`cb-kernel` + `cb-events` + `cb-game-runtime`) — not a wrapper around any surveyed system. Per the Clay-Borg rule, we own the semantics; what we assimilate from the field is *patterns*, each with a named source: | Assimilated pattern | From | Into | |---|---|---| | Declarative game definition (setup/moves/phases as data + pure functions) | boardgame.io | game-package rules API | | Tooling-enforced determinism (not convention) | Rune | seeded RNG service, denied ambient time/random, replay double-run check in the scenario runner | | Command → validate → events → fold, snapshots bound replay | event-sourcing (cqrs-es pattern) | kernel mutation pipeline | | Information-state framing for imperfect information | OpenSpiel | per-player projection model | | Hand-zone / object-visibility semantics | TTS (pattern only) | tabletop layer, later | Rejected alternatives: **assimilate boardgame.io** (inactive, JS-bound, history-degrading in best config — fails D2/D3/D4); **build on OpenSpiel** (right semantics, wrong layer — research kernel without projection/ networking/snapshot surface, heavyweight C++/Python boundary); **ECS as kernel** (bevy_ecs stays in the world layer per the blueprint). ## Expected advantage per dimension (honest trades) - **D3 speed: better.** Flat per-event cost with snapshots; the 100k/s floor. Declared caveat: part of the margin over boardgame.io is language choice; the commitment that matters is flat scaling, and the event-sourcing comparison stays at parity until a Rust comparator is measured. - **D2 weight: better.** Target ≤20 transitive crates for the headless kernel (vs 120 npm packages), measured by M-D2-DEP/M-D2-LOC/M-D2-BLD. - **D1 specification: parity, aiming better.** Match boardgame.io's declarative compactness on the synthetic workload (≤~40 LOC equivalent); surpass via rule-to-scenario traceability (M-D1-COV), which no candidate has. Declared trade: we do not attempt Ludii/GDL-class generality — one game family first, canon only after a second concrete use. - **D4 optionality: better.** Port pattern with null/reference impls from day one, capability boundary WIT-expressible later, zero foreign types in canonical interfaces (M-D4-LEAK=0). No surveyed candidate offers this. ## Gate Per InnerLoop, no kernel implementation code existed before this ADR. Next steps: T05 (GROUND rules spec, derived from ground-game), T06 (kernel spec with acceptance metrics tied to these baselines), T07 (workspace + harness), T08 (code loop).