clay-borg/decisions/ADR-0015-the-cards-own-words.md
tegwick 4b5b601ce0 CB-WP-0028 T01/T02: the cards say what they do
ADR-0015 and the import. F18's fix: "I don't understand the GROUND card"
was never a design gap -- the card explains itself in the edition and we
never imported the explanation.

THE MEASUREMENT IS THE DECISION, and the gap is bigger than "one file of
nineteen". Of the file we DID vendor, the engine reads 5 of 13 columns:
title, problem_text, front_rules, reveal_effect and unresolved_effect were
discarded at parse time. The cheapest part of this pass costs no new bytes
and was sitting in the repo for eight days. And SCN_01 is hardcoded at
lib.rs:1824 -- the edition ships FOUR scenarios and the engine has never
dealt three of them. Nobody had said so.

ADR-0011's revisit condition is measurably absent, so the dependency
argument does not get re-run: across Actions, Solutions, Modes and
Scenarios there are ZERO doubled quotes and ZERO embedded newlines. The
hand reader's only job is comma-in-quoted-field, which it already did.
Refusing csv on a measurement rather than on a preference.

Vendored Actions, Solutions and Modes -- the text a player reads. Not the
production artifacts (BOM, Print_Manifest, Back_Designs, Symbols). NOT
Extensions.csv, which names content the designer placed outside the core;
importing it would break the claim that this engine plays the edition as
printed. It is now known to exist, which was the real risk.

One Table reader with four callers, because a per-file copy is how a
parser acquires four subtly different bugs. The GROUND card now shows
"Regulate. Restore the frame. Decide." with its GR/OU/ND text on demand;
Problems show their own titles where a priority number used to be.

The load-bearing test asserts the text is a SUBSTRING OF THE VENDORED
FILE rather than equal to a Rust literal -- a test comparing against a
hardcoded expectation would pass for a hand-copied string, which is the
drift this ends.

`edition` came out from behind #[cfg(feature = "scenarios")]. It was gated
because its only consumer was; the edition is the game's own data and the
shipped runtime now reads it. Test machinery and game content are
different things and only one of them is optional.

And edition-check was written for a single-file world: it compared the
first recorded digest against Problems.csv regardless of which file that
digest described. It now checks every file both ways -- a vendored file
with no digest fails, a digest naming an absent file fails -- and asserts
ADR-0015 D3's falsifier directly rather than trusting it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 17:22:04 +02:00

6.9 KiB

ADR-0015: import what a player reads, and read what we already imported

status: accepted date: 2026-08-06 decided by: agent, under the standing loop authorization tier: M (structural M — imports more of an external dataset under AM-4's budgets; chaos d8=1 → no override). Tier M merges survey and decision. references: CB-WP-0028, ADR-0011 (the precedent and its revisit condition), GameDesign.md §1, F18 in FindingRegister.md

Context

A player said "I don't understand the GROUND card." The card explains itself in the edition and the engine never imported the explanation.

The measurements this rests on

Taken before deciding, because ADR-0011's own numbers were computed against the wrong budget and the correction is the reason that ADR exists.

1. The gap is bigger than "one file of nineteen."

edition files in ground-game 19
vendored in clay-borg 1 (Problems.csv)
columns in that file 13
columns the engine reads 5scenario_id, hidden_priority, point_value, required_solution, visibility
scenarios in the file 4 (SCN_01SCN_04)
scenarios the engine deals 1SCN_01, hardcoded at lib.rs:1824

Every Problem already has a title and problem_text sitting in a file we vendored eight days ago, and the page shows Repair 2. The cheapest part of this pass costs no new bytes at all.

2. ADR-0011's revisit condition is not triggered, and that is measured.

ADR-0011 refused the csv crate and said the decision would be wrong "if this data ever grows nested quoting, embedded newlines, or multiple dialects." Across every candidate file:

file rows fields with , with " with newline
Actions 5 12 0 0
Solutions 24 5 0 0
Modes 3 6 0 0
Scenarios 4 2 0 0

Zero doubled quotes, zero embedded newlines. The hand reader's only job is comma-in-quoted-field, which it already does. The dependency argument does not get re-run, because the condition that would re-open it is absent — not because re-running it would be inconvenient.


D1 — read the columns we already have, first

title, problem_text, front_rules, reveal_effect and unresolved_effect are in the vendored file and discarded at parse time. They become part of EditionProblem and reach the page.

This is the whole of observation 2's Problem half and costs zero new dependencies, zero new files and no budget. It is listed first because a pass that imports three new files while ignoring eight columns of the file it already has would be solving the interesting problem and not the real one.

D2 — vendor Actions.csv, Solutions.csv, Modes.csv

These carry the text a player reads:

  • Actions — the five action cards' title, tagline, rules_text. The GROUND card's own words are here, and this is the reported defect.
  • Solutionstitle and microcopy per card, so a hand shows "Ask What Happened" rather than Clarify.
  • Modes — the scoring mode's title, tagline and rules_text, and its scoring_tiebreak, which T07 needs and which we would otherwise have invented.

Each vendored with a digest and a provenance line, exactly as Problems.csv was.

Not vendored: BOM, Print_Manifest, Back_Designs, Symbols, Design_Tokens, README, metadata — production artifacts for a physical print run, with no meaning to a simulator.

Extensions.csv is not imported, and the reason is stated rather than assumed: it names content the designer deliberately placed outside the core (not_in_core_reason is a column). Importing it would put non-core content in an engine whose whole claim is that it plays the edition as printed. It is now known to exist, which was the actual risk.

Relations, DARVO, Tokens, Glossary are deferred, not refused: they describe mechanisms GroundRules.md already encodes as rules, and nothing a player reads is missing from the page without them. If T02 finds a seat's DARVO stage needs its own words, that is the trigger.

D3 — the hand reader stays

Measured above. ~50 lines we own against 17,651 for csv, and the grammar has not grown.

What changes: the reader becomes generic over "a vendored CSV with a header" instead of being Problems.csv-shaped, because it is about to have four callers. A per-file copy is how a parser acquires four subtly different bugs.

Falsifier, restated so it stays live: if any future edition file carries a doubled quote or an embedded newline, this decision is wrong and csv is the answer. The check is one command and belongs in edition-check.py.

D4 — where text and rules disagree, that is a finding

GroundRules.md's 59 rules were hand-derived from these files. Importing the files puts the source beside the transcription for the first time.

A rules_text that contradicts a numbered rule is a register finding — kind inconsistent — not a quiet edit of either.

Neither wins automatically: the dataset is authoritative on the game, but our rule may encode a ruling ground-game has since made. The register is where that gets resolved, and ground-game owns the answer.

This is the most valuable thing the import can produce and it is adversarial to our own work, which is why it is written down before anyone looks.

D5 — the scenario stays hardcoded, and that is now visible

SCN_01 at lib.rs:1824, one of four. Not changed here: choosing a scenario is a setup-surface change (Setup has preset and patch), and bundling it into a text-import pass would make both harder to review.

Recorded as an open item rather than left as a surprise — the engine has never played three quarters of the shipped content, and nobody had said so.

Consequences

  • editions/ground-darvo-r0/ gains three files, each with a digest.
  • edition.rs gains a generic reader and four typed views over it.
  • EditionProblem gains the text columns already present.
  • edition-check.py verifies the new digests and the no-doubled-quotes condition D3 rests on.
  • The page can show the game's own words (T02).

What was rejected

rejected why
the csv crate its revisit condition is measurably absent (§2)
importing all 19 files production artifacts have no meaning to a simulator
Extensions.csv deliberately non-core content; importing it would break the as-printed claim
a per-file parser four copies acquire four subtly different bugs
resolving text-vs-rules conflicts in place that is a finding, and ground-game owns the answer
changing the scenario here a setup-surface change bundled into a text import makes both harder to review