133 lines
5.9 KiB
Markdown
133 lines
5.9 KiB
Markdown
|
|
# ADR-0016: a token is a view, and the supply is not a rule we get to invent
|
|||
|
|
|
|||
|
|
status: accepted
|
|||
|
|
date: 2026-08-07
|
|||
|
|
decided by: agent, under the standing loop authorization
|
|||
|
|
tier: M (structural M — imports another edition file under AM-4's budgets;
|
|||
|
|
chaos d8=4 → no override). Tier M merges survey and decision.
|
|||
|
|
references: [CB-WP-0029](../workplans/CB-WP-0029-the-tokens-on-the-table.md),
|
|||
|
|
[ADR-0015](ADR-0015-the-cards-own-words.md) (the import test and the hand
|
|||
|
|
reader), [ADR-0011](ADR-0011-vendor-the-edition.md),
|
|||
|
|
[GameDesign.md](../specs/GameDesign.md) §1
|
|||
|
|
|
|||
|
|
## Context
|
|||
|
|
|
|||
|
|
The engine models every token correctly and shows them as numbers on a
|
|||
|
|
seat card — `protect 2`, `blamed by P3`. `Tokens.csv` describes them as
|
|||
|
|
components, with a `quantity` and a `sides` count, and that raised a
|
|||
|
|
question worth measuring before deciding anything.
|
|||
|
|
|
|||
|
|
## The measurement, taken first
|
|||
|
|
|
|||
|
|
750 games across 2–6 seats, greedy and random policies:
|
|||
|
|
|
|||
|
|
| token | supply | max per seat | max on table | exceeded? |
|
|||
|
|
|---|---:|---:|---:|---|
|
|||
|
|
| Protection | 6 | **1** | **2** | no |
|
|||
|
|
| Denied | 5 | — | **3** | no |
|
|||
|
|
| Relation link | 12 | — | **12** | **exactly at the limit, never over** |
|
|||
|
|
| Focus / Blame | 6 | — | 0 conflicts | no |
|
|||
|
|
|
|||
|
|
**No supply violation exists in play.**
|
|||
|
|
|
|||
|
|
**And the first version of that check was wrong.** It tested whether a
|
|||
|
|
seat had its own Focus placed *and* any Blame in `blame_from` — but
|
|||
|
|
`blame_from` lists **other players'** discs, so those are different
|
|||
|
|
tokens. It reported 2 conflicts. Corrected, it reports 0. **Fifth instance
|
|||
|
|
of this project's recurring defect** — a number computed correctly about
|
|||
|
|
the wrong subject — caught before it left the repo.
|
|||
|
|
|
|||
|
|
**The link row is the interesting one.** Twelve tokens, two per player,
|
|||
|
|
six players: the supply is *exactly* consumed at full occupancy and never
|
|||
|
|
exceeded, because GR-L01 already enforces two slots per seat. **The
|
|||
|
|
component count and the rule are the same constraint written twice** — and
|
|||
|
|
that is the shape of a supply that does not need separate enforcement.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## D1 — vendor `Tokens.csv`
|
|||
|
|
|
|||
|
|
ADR-0015's test: does it carry text a player reads? `front_text` (READY,
|
|||
|
|
DENIED, PROTECTION, FOCUS, LEAD, ROUND) and `use` do. `shape`, `size` and
|
|||
|
|
`symbol_id` are print instructions and are read by nothing here.
|
|||
|
|
|
|||
|
|
Vendored whole with a digest, as the others are — taking a column subset
|
|||
|
|
would mean a second decision every time a column becomes interesting.
|
|||
|
|
|
|||
|
|
## D2 — a token is a **view**, not a type
|
|||
|
|
|
|||
|
|
**The aggregate gains no `Token`.** A token is a way of *seeing* state the
|
|||
|
|
aggregate already holds: the Stress marker is `stress`, the DARVO pawn is
|
|||
|
|
`darvo`, the Freedom disc is `freedom_ready`.
|
|||
|
|
|
|||
|
|
Adding a `Token` type would create a second source of truth for Stress,
|
|||
|
|
and the first time they disagreed the bug would be invisible — both would
|
|||
|
|
look internally consistent. **This is INTENT's own rule**: own the
|
|||
|
|
semantics, and do not duplicate them for presentation's sake.
|
|||
|
|
|
|||
|
|
So `Tokens.csv` supplies **labels and counts for the renderer**, and
|
|||
|
|
nothing in `games_ground` changes shape.
|
|||
|
|
|
|||
|
|
## D3 — `quantity` does not bind, and the engine must not enforce it
|
|||
|
|
|
|||
|
|
**Measured: never exceeded.** But the reason for the decision is not the
|
|||
|
|
measurement.
|
|||
|
|
|
|||
|
|
> **A component limit the rules do not state is not a rule.**
|
|||
|
|
|
|||
|
|
`GroundRules.md` derives 59 rules from the dataset and **none of them
|
|||
|
|
mentions a token supply**. If the engine began refusing a seventh
|
|||
|
|
Protection token, it would be enforcing a constraint nobody ruled — which
|
|||
|
|
is exactly the error CB-WP-0023 exists to correct, in the other direction:
|
|||
|
|
SOLVE was *offered* where it could not act, and this would *refuse* where
|
|||
|
|
the rules allow.
|
|||
|
|
|
|||
|
|
**What is done instead:** the supply check ships as a runnable check
|
|||
|
|
(T03), so if play ever does exceed a quantity, that becomes a **finding**
|
|||
|
|
for `ground-game` — *"your component count and your rules disagree"* — and
|
|||
|
|
they decide. Which is a real question: a physical game cannot hand out a
|
|||
|
|
seventh Protection token, so either the rules bound it or the box does.
|
|||
|
|
|
|||
|
|
**Not registered as a finding today**, because nothing was found. **A
|
|||
|
|
stated "none found" is registered instead**, because a survey that reports
|
|||
|
|
nothing and leaves no trace is indistinguishable from one that was never
|
|||
|
|
run.
|
|||
|
|
|
|||
|
|
## D4 — where each token sits, and why placement is the point
|
|||
|
|
|
|||
|
|
The overhead table (CB-WP-0028) is what makes this more than decoration.
|
|||
|
|
|
|||
|
|
| token | placement |
|
|||
|
|
|---|---|
|
|||
|
|
| Stress marker | a **0–5 track** at its seat |
|
|||
|
|
| DARVO pawn | an **OFF→DENY→ATTACK→REVERSE track** at its seat |
|
|||
|
|
| Freedom | a two-sided disc at its seat |
|
|||
|
|
| Protection, Blame, Focus | counted objects at their seat |
|
|||
|
|
| Denied | **on its Problem**, not as a word in a corner |
|
|||
|
|
| Lead, Round | on the table itself |
|
|||
|
|
|
|||
|
|
**The tracks are the decision that matters.** `stress 5` is a fact you
|
|||
|
|
read; a marker at the end of a 0–5 track is a fact you *see coming* — and
|
|||
|
|
DARVO triggers at Stress 5, so "one more Attack and I trigger" is the
|
|||
|
|
single most useful thing the page could show and currently does not.
|
|||
|
|
|
|||
|
|
## Consequences
|
|||
|
|
|
|||
|
|
- `editions/ground-darvo-r0/Tokens.csv` + digest; `edition-check` covers
|
|||
|
|
it automatically, since it enumerates what is present.
|
|||
|
|
- `edition.rs` gains a `tokens()` reader over the existing `Table`.
|
|||
|
|
- The renderer draws tracks and counted objects; `games_ground` is
|
|||
|
|
unchanged.
|
|||
|
|
- The supply check is committed and runnable, and its result is in the
|
|||
|
|
register as a stated negative.
|
|||
|
|
|
|||
|
|
## What was rejected
|
|||
|
|
|
|||
|
|
| rejected | why |
|
|||
|
|
|---|---|
|
|||
|
|
| a `Token` type in the aggregate | a second source of truth for Stress; INTENT forbids it |
|
|||
|
|
| enforcing `quantity` | a limit the rules do not state is not a rule (CB-WP-0023, inverted) |
|
|||
|
|
| importing only some columns | a second decision every time a column becomes interesting |
|
|||
|
|
| leaving the supply unchecked | *"probably safe"* is not an answer, and a negative that leaves no trace cannot be told from an unrun survey |
|
|||
|
|
| keeping Stress as a number | the track is what makes DARVO visible before it fires |
|