Two rules, two different answers, which is the point of a task phrased
"implement, or amend and say why".
K18 is implemented. "Criterion benches driving the same scenario format at
scale" was false — the bench hardcoded its commands and never touched
ScenarioFile, while MetricsAndScenarios §3 pointed at a benchmarks/
directory containing only baselines/. benchmarks/synthetic-3p.yaml now
holds the workload and both the bench and bench_shape read it: the
workload is data, not code.
A second defect surfaced while fixing the first. After the bench switched
to the file, bench_shape still hardcoded the same sequence, so the
workload existed twice — deleting end_round from the YAML broke bench-test
while bench_shape kept passing. Duplicated-fact drift in executable form.
Both now read the same include_str! and deleting a command breaks both.
Explicitly not claimed: this does not unblock AM-3. AM-3's baseline is a
declarative game object — moves, turn order, rules. synthetic-3p.yaml is a
command list; the rules live in games/ground. Marking it as AM-3's subject
would compare a script to a game definition, which is the category error
AM-3 is blocked on. The file says so in its own header, where the next
person will be tempted.
K14 is amended. CommitWindow had zero non-test users and GROUND enforces
the same contract inline. Wiring GROUND through it was rejected: it would
change the serialized shape of `selections`, which four scenario files
assert by dot-path and every state hash depends on, for the sole benefit
of making a sentence literally true.
The deciding argument is INTENT's, not convenience: abstractions are
extracted from working games rather than invented in isolation, and no
concept becomes canonical until it survives a second concrete use.
CommitWindow was invented before any game needed it and has survived none.
Imposing it on GROUND would manufacture the first use rather than discover
it. So K14 states what is actually guaranteed, CommitWindow is marked
provisional in the source, and it carries a delete-by date of 2026-12-31.
Kernel spec->code link 16/18 -> 18/18, stated with the caveat the gate
prints every run: that is about names, not assertions.
Two self-tests broke and both broke correctly. rule-coverage's gate test
hardcoded "unlinked rules exist today" and failed when the last one was
linked; it now computes that and asserts the gate fails iff rules are
unlinked. facts' text check rejected k_unlinked once it became
legitimately empty; empty now renders as "(none)" and the check
distinguishes absent from empty.
M-D1-MUT: 8 of 14, unchanged — K14 and K18 are kernel rules, not
acceptance rows.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The gates existed; CI ran half of them and tolerated the failure case.
- cb-sim no longer has a "tolerable" non-zero exit. An unregistered game
prefix is a failure, and a run in which nothing executed is a failure.
Previously CI carried `|| test $? -eq 2`, so renaming a scenario prefix
would have skipped every scenario while the pipeline stayed green.
Verified with a negative control.
- CI now runs make coverage (AM-1) and make dep-weight (AM-4), both
added after CI was written and neither enforced until now.
- dep-weight enforces its targets instead of only reporting them.
- CI lints the shipped-runtime configuration separately, so the feature
split cannot rot unnoticed.
- Dropped the stale `make deps` target, which still measured the retired
crate-count metric.
The positive-control rule is now executable: CI runs
`cargo bench -- --test`, which executes every benchmark once, so a
workload that stalls fails the build.
That step immediately found a fourth instance of the error class it was
written for. The committed replay benchmark was the broken version — an
earlier patch never applied, leaving a command sequence that omits
Resolve, so every round produced nothing and the log-building loop spun
forever. It had never run to completion; the reported AM-7 replay
numbers came from a probe test instead. Fixed, given the same positive
control as the round loop, and re-measured from the benchmark: 100k
events fold in 2.18ms (95% CI 2.14-2.23), against a 5s budget.
Evidence now reports confidence intervals rather than point estimates,
so the 3% regression rule in MetricsAndScenarios is enforceable.
The finding worth carrying: writing the positive-control rule into
InnerLoop v1.0 did not prevent the next instance. Making it a CI step
did.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
evidence/CB-EV-0001-game-kernel.md records the acceptance run against
the CB-RES-0001 baseline.
Met: AM-1 rule coverage 58/58; AM-6 throughput 1.65M events/s against a
100k target; AM-7 scaling 1.08x at 20x workload and a 100k-event replay
in 4.13ms against a 5s budget; AM-8 zero divergence over 10 full runs
with fmt and clippy clean; AM-10 zero foreign collection types.
Not met and reported as such: AM-4 at 33 transitive crates against a
<=20 target. Attribution is in the evidence file. The recommended fix
is making serde_yaml optional (-5, a test-only concern), after which
the remainder is sha2 and rand_chacha, which K5 and K7 require. We are
not hand-rolling crypto primitives to win a dependency count.
AM-12 is recorded as uncomputable: per-task token counts were never
instrumented, and inventing a USD figure would defeat the metric.
A measurement error was found and corrected before publication. The
first benchmark reported 9.3M events/s on a flat curve. The workload
had a player selecting SUPPORT while parked at Stress 4, so GR-R03
rejected it, rounds never completed, and throughput was computed for
rounds that never happened. The bench now asserts the per-round event
count and panics rather than measuring a stalled loop. The corrected
figure is 5.6x lower.
The evidence file states plainly what the boardgame.io comparison does
and does not support: the ~450x command-rate ratio is cross-runtime and
cross-feature-set, so it is a direction, not a verdict, per the
InnerLoop parity-cap rule.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>