clay-borg/workplans/CB-WP-0021-import-the-edition.md
tegwick fe3852e093 CB-WP-0021: correct the declaration before writing any code
The declaration claimed importing the edition data would resolve GR-E01.
Measured across all four scenarios: GR-S01 deals 2/3/4 problems by player
count, not all five, so 4/6/9 points are in play against thresholds of
5/7/9 -- unreachable at 2p and 3-4p with the REAL data, in the same shape
as the stand-in's 3/6/10. So GR-E01 unreachable below 5 seats is a real
property of the game and gr-e01-threshold-unreachable-2p asserts
something true.

The error was the cheap kind: 12 points exist in the file, so I assumed
12 are in play. One command over the CSV settled it and was not run until
after the declaration was committed -- this project's characteristic
error, in the pass that followed a ruling obtained because of it.

CB-EV-0018 corrected too: 'confirmed as the stand-in's doing' was
overstated. The zero came from no Problem being claimed at all.

T03 now owes ground-game a sharper question than a retirement: either
GR-S01's deal count is wrong or GR-E01's thresholds are, and no dataset
can reconcile them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 20:35:39 +02:00

189 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: CB-WP-0021
kind: product
title: "Import the edition: the game plays its own data"
status: ready
---
# 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
```
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
```
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
```
`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
```
`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.**