119 lines
5.3 KiB
Markdown
119 lines
5.3 KiB
Markdown
|
|
# ADR-0011: vendor the edition, read it by hand, and let the hashes move
|
|||
|
|
|
|||
|
|
status: accepted
|
|||
|
|
date: 2026-08-04
|
|||
|
|
decided by: agent, under the standing loop authorization
|
|||
|
|
tier: M (structural M — adds or refuses an external dependency and changes
|
|||
|
|
how a game is set up; chaos d8=7 → no override). Tier M merges survey and
|
|||
|
|
decision into one document, which this is.
|
|||
|
|
references: [CB-WP-0021](../workplans/CB-WP-0021-import-the-edition.md),
|
|||
|
|
[ADR-0007](ADR-0007-render-html-not-a-port.md) D3 (the acquisition rule),
|
|||
|
|
GROUND-WP-0002 T01 and GROUND-WP-0004 (ground-game's rulings)
|
|||
|
|
|
|||
|
|
## Context
|
|||
|
|
|
|||
|
|
`editions/ground-darvo-r0/Problems.csv` is authoritative (ground-game,
|
|||
|
|
2026-08-03) and the engine has been inventing Problem values and suits.
|
|||
|
|
GR-S01's deal was then ruled (2026-08-04): **Surface always ∪ hidden
|
|||
|
|
`1..k`**, k = 2/3/4, giving available points **6 / 9 / 12** — which holds
|
|||
|
|
*only* with the real values.
|
|||
|
|
|
|||
|
|
## Correction: the constraint was measured against the wrong budget
|
|||
|
|
|
|||
|
|
**CB-WP-0021's declaration said a CSV crate costs 21,613 lines against
|
|||
|
|
AM-4a's 3,798 of headroom — "5.7× over, settled by measurement rather
|
|||
|
|
than preference."**
|
|||
|
|
|
|||
|
|
`setup` and `problem_priorities` are `#[cfg(feature = "scenarios")]`.
|
|||
|
|
**They are not in the shipped runtime at all**, so AM-4a never sees them
|
|||
|
|
and never would have. The budget that applies is AM-4b, and measured
|
|||
|
|
against *its* graph:
|
|||
|
|
|
|||
|
|
| | lines |
|
|||
|
|
|---|---:|
|
|||
|
|
| AM-4b headroom (745,000 − 725,258) | **19,742** |
|
|||
|
|
| `csv` marginal cost (`csv` + `csv-core`; `ryu`, `itoa`, `memchr` already present via `serde_json`) | **17,651** |
|
|||
|
|
|
|||
|
|
**It fits, with 2,091 lines to spare.** The declaration's confident
|
|||
|
|
"settled by measurement" was measurement of the wrong thing — the third
|
|||
|
|
premise this pass has had to correct, and the second where a real number
|
|||
|
|
was computed against a mis-chosen denominator.
|
|||
|
|
|
|||
|
|
## Decision 1 — refuse `csv`, on proportion rather than impossibility
|
|||
|
|
|
|||
|
|
It fits and it is still refused, and the distinction matters because the
|
|||
|
|
argument has to survive someone re-running the numbers.
|
|||
|
|
|
|||
|
|
**17,651 lines is 89% of everything AM-4b has left, to read 20 rows.** The
|
|||
|
|
next dependency after it would have 2,091 lines to live in. A hand-rolled
|
|||
|
|
reader for this grammar is ~50 lines we own.
|
|||
|
|
|
|||
|
|
INTENT's rule is *"assimilate the implementation"* — but that is about
|
|||
|
|
**mature optimized libraries** for hard problems. Splitting quoted CSV
|
|||
|
|
fields is not one, and `Problems.csv` is 20 rows read once at setup.
|
|||
|
|
Taking a general parser here would spend the budget's remaining capacity
|
|||
|
|
on the easiest problem we have.
|
|||
|
|
|
|||
|
|
**If the data grows into something a hand reader should not own — nested
|
|||
|
|
quoting, embedded newlines, multiple files with differing dialects — this
|
|||
|
|
decision is wrong and `csv` is the answer.** That is the condition to
|
|||
|
|
revisit under, stated now rather than left to taste.
|
|||
|
|
|
|||
|
|
## Decision 2 — vendor the file, with a checked provenance
|
|||
|
|
|
|||
|
|
`ground-game` is a separate repository. Two options:
|
|||
|
|
|
|||
|
|
| | cost |
|
|||
|
|
|---|---|
|
|||
|
|
| **sibling checkout** | the build depends on a path that may not exist. CI runs `rust:1.97` with this repo only, so `make all` would fail or silently skip — and a silent skip is the class this project has found seven times |
|
|||
|
|
| **vendor a copy** | clay-borg carries content it does not own, and a stale copy is worse than no copy |
|
|||
|
|
|
|||
|
|
**Vendored**, at `editions/ground-darvo-r0/Problems.csv`, with a
|
|||
|
|
`PROVENANCE` note naming the upstream repo, path and revision.
|
|||
|
|
|
|||
|
|
The staleness answer is a **committed digest of the upstream file**. A
|
|||
|
|
check compares it when `../ground-game` is present, and reports
|
|||
|
|
**`upstream not checked out`** as a distinct outcome when it is not — never
|
|||
|
|
a pass. That is the shape ADR-0009 used for `node`: an absent thing is
|
|||
|
|
reported absent, not treated as satisfied.
|
|||
|
|
|
|||
|
|
**Acquisition rule (ADR-0007 D3):** this is content the build causes to be
|
|||
|
|
present, and it is ours now. It is not third-party *code* and does not
|
|||
|
|
enter AM-4, but the provenance note is what stops it becoming
|
|||
|
|
unattributed.
|
|||
|
|
|
|||
|
|
## Decision 3 — the hashes move, and nothing pins them
|
|||
|
|
|
|||
|
|
Problem values and suits enter `GroundState`, which is hashed (K7). The
|
|||
|
|
declaration called this *"the reason the ADR exists."* Measured:
|
|||
|
|
|
|||
|
|
| | |
|
|||
|
|
|---|---|
|
|||
|
|
| scenario files pinning a state hash | **0** |
|
|||
|
|
| replay bundles committed | **0** |
|
|||
|
|
| scenarios asserting on `problems.N.*` | **10 of 25** |
|
|||
|
|
|
|||
|
|
**So the feared blast radius is not there.** K8's double-run compares two
|
|||
|
|
runs of the same build; AM-7's probe compares segments within one run;
|
|||
|
|
`replay-test` generates its bundle at run time. All are self-consistent
|
|||
|
|
and survive a content change by construction.
|
|||
|
|
|
|||
|
|
What breaks is **scenario expectations** — which is exactly what *should*
|
|||
|
|
break when the content changes, and is why they are written as `expect`
|
|||
|
|
blocks rather than hashes.
|
|||
|
|
|
|||
|
|
**No hash is grandfathered and none is recorded as "was".** A recorded
|
|||
|
|
hash that outlives the content it describes is a lie with a timestamp.
|
|||
|
|
|
|||
|
|
## Consequences
|
|||
|
|
|
|||
|
|
- The deal fix and the import land **together**. The ruled 6/9/12 holds
|
|||
|
|
only with real values; the same deal with the stand-in gives 6/10/15, a
|
|||
|
|
game nobody ruled on.
|
|||
|
|
- `gd0001` is **inverted, not deleted** — it is the record of why the game
|
|||
|
|
became winnable.
|
|||
|
|
- If ground-game revises `r0` in place, the digest check fails loudly.
|
|||
|
|
Per GROUND-WP-0002 T01's proposed contract, `point_value` and
|
|||
|
|
`required_solution` may not change within a revision; this is the
|
|||
|
|
mechanism that notices if they do.
|