CB-WP-0008-T01: bots — the kernel's first non-scenario consumer
Some checks failed
ci / check (push) Failing after 4s
Some checks failed
ci / check (push) Failing after 4s
A Policy trait, a seeded random policy and a greedy one with a stated heuristic, a legal-command generator that filters candidates through validate, and a driver that runs a 3-player all-bot game to GameEnded. Same-seed runs are hash-identical (K8), and a different policy seed produces a different game — without that second assertion the first is satisfied by a bot that ignores its RNG. Every failure is loud, because the one a bot driver must not have is the silent one: no legal move, passing where an action is required, an out-of-range index (not clamped), a rejected command, and a stall guard. What the second consumer found, none of it fixed here: - GR-A13 admits SOLVE against an already-claimed Problem and resolution then does nothing — the action is silently wasted. The policy avoids it; the rule is left for a ruling. - The 3-player standard fixture cannot reach GR-E01's threshold of 7: three Problems valued 1,2,3 cap the total at 6. No scenario noticed because none plays to scoring. - K13's Project trait still has zero implementors. T02 is its first. Mutation-checked by hand. The first mutation was a no-op and survived; removing the Resolve call outright turned three tests red for the stated reason. Third instance of the weak-mutation class. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
be2d7a3e5a
commit
6197677126
4 changed files with 926 additions and 2 deletions
64
history/260801-cb-wp-0008-log.md
Normal file
64
history/260801-cb-wp-0008-log.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# 2026-08-01 — CB-WP-0008 delivery notes
|
||||
|
||||
Kept out of the workplan file so it stays loadable (`loop-lint`).
|
||||
|
||||
## T01 — bots
|
||||
|
||||
`games/ground/src/bot.rs`, 8 tests. `Policy` + `RandomPolicy` (seeded
|
||||
`ChaChaRng`) + `GreedyPolicy` (stated heuristic, deterministic), a
|
||||
`legal_commands` generator that filters candidates through `validate`, and
|
||||
a driver that reaches `GameEnded`.
|
||||
|
||||
Measured, 3-player, seed 42, both policies to GR-R09's fifth round:
|
||||
|
||||
| policy | commands | events | claimed | total vs threshold |
|
||||
|---|---|---|---|---|
|
||||
| random | 36 | 81 | 1 | 2 / 7 |
|
||||
| greedy | 30 | 51 | 2 | 3 / 7 |
|
||||
|
||||
**The module is not gated on `scenarios`; its tests are.** A bot needs
|
||||
only the aggregate, but the setup presets live behind that feature. That
|
||||
is a real seam and it is left visible rather than papered over with a
|
||||
feature the bot does not need.
|
||||
|
||||
### What the second consumer found
|
||||
|
||||
INTENT's second-use rule is why T01 was worth doing before the CLI. Three
|
||||
findings, none of them fixed here, because fixing a rule from inside a bot
|
||||
is exactly the invention-in-isolation the rule guards against.
|
||||
|
||||
1. **GR-A13 admits SOLVE against an already-claimed Problem.** The rule
|
||||
names "a face-up, non-Denied Problem"; `claimed_by` is not mentioned,
|
||||
so `check_targeting` accepts it and resolution then does nothing. The
|
||||
action is silently wasted. Greedy hit this immediately — it spent all
|
||||
fifteen selections re-solving Problem 1 and scored 1. The **policy**
|
||||
now avoids it; the **rule** is untouched and this is a U-item
|
||||
candidate for GroundRules.
|
||||
|
||||
2. **The 3-player standard fixture cannot succeed.** GR-S01 gives 3
|
||||
Problems at 3–4 players, the preset values them by priority (1, 2, 3 —
|
||||
maximum 6), and GR-E01 sets the 3–4p threshold at **7**.
|
||||
`group_success` is therefore unreachable at 3 players regardless of
|
||||
play. No scenario noticed because no scenario plays to scoring with
|
||||
maximal claiming. The fixture is documented as placeholder ("Problem
|
||||
content is scenario data") — so this is evidence that the placeholder
|
||||
is not neutral, not that GR-E01 is wrong.
|
||||
|
||||
3. **K13's `Project` trait has zero implementors.** `grep` finds no
|
||||
`impl Project` anywhere in the tree. T02 is its first consumer, and
|
||||
the projection will be written against a trait that has never been
|
||||
exercised.
|
||||
|
||||
### Process
|
||||
|
||||
The acceptance tests were mutation-checked by hand (no `mutation-check`
|
||||
row — that denominator is the GameKernel acceptance table, and adding a
|
||||
game-level row would move a metric by changing its question).
|
||||
|
||||
**The first mutation was a no-op and SURVIVED**: it changed
|
||||
`apply(...)?` to `let _ = apply(...)`, which still issues the command.
|
||||
Removing the `Resolve` call outright turned three tests red for their
|
||||
stated reason. Third recorded instance of the weak-mutation class — the
|
||||
retrospective in `260801-instrument-the-table-retrospective.md` predicted
|
||||
mutation strength would stay a standing maintenance cost, and this is
|
||||
that cost arriving on the next pass.
|
||||
Loading…
Add table
Add a link
Reference in a new issue