clay-borg/workplans/CB-WP-0021-import-the-edition.md

195 lines
7.4 KiB
Markdown
Raw Normal View History

---
id: CB-WP-0021
kind: product
title: "Import the edition: the game plays its own data"
status: ready
2026-08-04 00:21:21 +02:00
state_hub_workstream_id: "782b1c37-f3a7-469b-87a3-fa73ebe758d2"
---
# Purpose
```
structural tier M (adds or refuses an external dependency, and changes
how a game is set up — a canonical interface)
chaos d8 = 7 → no override
declared tier M
```
Declaration 4 of chaos window 2.
## The engine has been playing a stand-in
`games/ground/src/lib.rs` builds Problems with `value: priority` and suits
cycled by index. `editions/ground-darvo-r0/Problems.csv` has carried the
real thing since 2026-07-31, and **GROUND-WP-0002 T01 ruled it
authoritative on 2026-08-03**:
| | problems/scenario | values | total | suits |
|---|---:|---|---:|---|
| `Problems.csv` | **5** | 2, 2, 2, 3, 3 | **12** | `required_solution` per problem |
| the stand-in | 3 | 1, 2, 3 | **6** | cycled by index |
## CORRECTION, before any code: the import does not fix GR-E01
**This declaration opened by claiming it would, and the data says
otherwise.** The claim was *"ordinary against 12, unreachable against 6 —
it was never a rules gap."* Measured across all four scenarios:
**GR-S01 deals 2 / 3 / 4 problems by player count, not all five.** So the
points actually in play are never 12:
| players | dealt | available | GR-E01 threshold | |
|---:|---:|---:|---:|---|
| 2 | 2 | **4** | 5 | unreachable |
| 34 | 3 | **6** | 7 | unreachable |
| 56 | 4 | **9** | 9 | reachable, exactly |
Identical in shape to the stand-in, which gave 3 / 6 / 10 against the same
5 / 7 / 9. **So `GR-E01 unreachable below 5 seats` is a real property of
the game, not an artifact of the stand-in**, and
`gr-e01-threshold-unreachable-2p` is asserting something true.
The error was mine and it was the cheap kind to make: 12 points exist in
the file, so I assumed 12 points are in play. **One command over the CSV
settled it, and it was not run until after the declaration was
committed** — the characteristic error of this project, in the pass that
followed a ruling obtained *because* of it.
**CB-EV-0018 is corrected too.** It said the `0` scores were *"confirmed
as the stand-in's doing, not a scoring bug."* Overstated: the zero came
from no Problem being claimed at all, and the threshold gap is
independent of which dataset is loaded.
**What this changes.** The import is still right — the suits, values and
visibility are authoritative and the engine should stop inventing them.
But it resolves nothing about GR-E01, and T03 must send ground-game a
*sharper* question rather than a retirement: **either GR-S01's deal count
is wrong or GR-E01's thresholds are, and no dataset can reconcile them.**
## The constraint, measured before declaring
**AM-4a has 3,798 lines of headroom.** A CSV crate costs, marginally
against the shipped graph:
| crate | lines |
|---|---:|
| `csv` | 14,291 |
| `csv-core` | 3,360 |
| `ryu` | 3,962 |
| **marginal total** | **21,613** |
**5.7× the available headroom.** `itoa`, `memchr`, `serde` and
`serde_core` are already present and cost nothing; the parser itself is
what does not fit.
So the shipped runtime cannot gain a CSV parser, and that is settled by
measurement rather than by preference. What remains is *which* of the
alternatives to take, and that is the ADR.
## Task: decide how the data reaches the game
```task
id: CB-WP-0021-T01
status: todo
priority: high
2026-08-04 00:21:21 +02:00
state_hub_task_id: "68e4fe63-eec6-4fb8-a84f-32c7edee19af"
```
Write `decisions/ADR-0011-*.md` (tier M: survey and decision in one).
**Three questions, and the third is the one that bites.**
**(a) Where does the data live?** `ground-game` is a separate repository.
Depending on a sibling checkout makes the build depend on a path that may
not exist; vendoring a copy makes clay-borg carry content it does not own.
Whichever is chosen must say how a copy is known to be current, because a
silently stale copy is worse than no copy.
**(b) How is it parsed, given a CSV parser does not fit?** Candidates, and
each needs its marginal cost stated rather than assumed:
- hand-rolled reader in `games/ground` — small, but it is a parser we
then own, and `problem_text` contains commas;
- **bake it**: a dev-time step converts the CSV into a generated Rust
module or compact literal, so the shipped runtime parses **nothing**.
Then the generated artifact must be proven to match its source, which
is the DFD class this repo already has machinery for;
- load nothing at runtime and treat the data as scenario input.
**(c) What does this do to determinism?** Problem values and required
suits become part of `GroundState`, which is hashed (K7). **Every recorded
state hash changes.** Before writing code, establish what actually pins a
hash today — `make sim` runs 25 scenarios, `replay-test` re-executes
bundles, and AM-7's probe asserts per-segment hashes. Say which of those
break, and whether any of them are *supposed* to be stable across a
content change.
**This is the reason the ADR exists.** A content import that quietly
invalidates every recorded hash, in a project whose central invariant is
replay determinism, is not a data-loading change.
## Task: import it, and let the thresholds mean something
```task
id: CB-WP-0021-T02
status: todo
priority: high
2026-08-04 00:21:21 +02:00
state_hub_task_id: "28c3ff2c-16ae-47b5-9474-10e754936c60"
```
Replace the stand-in. `setup` must build Problems from the edition data:
`point_value`, `required_solution`, `visibility` (Surface → face up,
Hidden → face down) and `hidden_priority`.
**Controls:**
- **The stand-in must become unreachable.** A test that the fixture
constants no longer appear — a `value: priority` that survives beside
real data is a fallback nobody will notice until the numbers look odd
again.
- **A scenario must be able to reach GR-E01's threshold at 2 players**,
which is the specific thing that was impossible. Assert the arithmetic,
not just that a game runs.
- The 5-problem shape must survive: the stand-in dealt 3, and code that
assumed 3 will not announce itself.
## Task: retire the rules gap that was never one
```task
id: CB-WP-0021-T03
status: todo
priority: medium
2026-08-04 00:21:21 +02:00
state_hub_task_id: "ff3bd923-9066-49ce-aadd-a3552e4964ff"
```
`gr-e01-threshold-unreachable-2p` is tagged `provisional: true` with
`provisional_owner: ground-game`, and its description says group success
*"is unreachable at 2, 3 and 4 players"*. If T02 lands, that scenario is
asserting a property of the **stand-in**, not of the game.
Retire or rewrite it, and **say which of the six provisional items this
resolves**, so GROUND-WP-0002 T03 shrinks rather than being left to
rediscover it. Message `ground-game` with the outcome — the last such
message sat unread for four days because nothing pointed at it.
Do **not** quietly delete a failing-in-fact scenario. CB-EV-0005: *a score
improved by deleting the question is not an improvement.*
## Task: evidence
```task
id: CB-WP-0021-T04
status: todo
priority: high
2026-08-04 00:21:21 +02:00
state_hub_task_id: "ba76138d-a225-470d-bb2a-3a6881f4ca82"
```
`evidence/CB-EV-0019-*.md`.
- **What the import cost**, against the 3,798 lines that were available.
- **What broke**, especially hashes, and whether the blast radius was
predicted in T01 or discovered in T02. If it was discovered, say so —
that is the ADR having missed something.
- **Whether the endings now mean anything**: play one and report the
score against the threshold.
- **Quote CB-WP-0020's cost by re-running the instrument.**
- **Chaos: 4 of 12 in window 2.**