diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 9301b8c..ae9a93a 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -42,6 +42,8 @@ | workplan | CB-WP-0032 | done | — | workplans/CB-WP-0032-the-comments-in-the-account.md | | workplan | CB-WP-0033 | done | — | workplans/CB-WP-0033-a-game-is-the-unit.md | | workplan | CB-WP-0034 | done | — | workplans/CB-WP-0034-who-you-are-bonding-with.md | +| workplan | CB-WP-0035 | done | — | workplans/CB-WP-0035-a-session-that-answers-nothing.md | +| workplan | CB-WP-0036 | ready | — | workplans/CB-WP-0036-interactive-mode.md | | task | CB-WP-0001-T01 | done | — | workplans/CB-WP-0001-inner-loop.md | | task | CB-WP-0001-T02 | done | — | workplans/CB-WP-0001-inner-loop.md | | task | CB-WP-0001-T03 | done | — | workplans/CB-WP-0001-inner-loop.md | @@ -207,3 +209,10 @@ | task | CB-WP-0032-T01 | done | — | workplans/CB-WP-0032-the-comments-in-the-account.md | | task | CB-WP-0033-T01 | done | — | workplans/CB-WP-0033-a-game-is-the-unit.md | | task | CB-WP-0034-T01 | done | — | workplans/CB-WP-0034-who-you-are-bonding-with.md | +| task | CB-WP-0035-T01 | done | — | workplans/CB-WP-0035-a-session-that-answers-nothing.md | +| task | CB-WP-0036-T01 | todo | — | workplans/CB-WP-0036-interactive-mode.md | +| task | CB-WP-0036-T02 | todo | — | workplans/CB-WP-0036-interactive-mode.md | +| task | CB-WP-0036-T03 | todo | — | workplans/CB-WP-0036-interactive-mode.md | +| task | CB-WP-0036-T04 | todo | — | workplans/CB-WP-0036-interactive-mode.md | +| task | CB-WP-0036-T05 | todo | — | workplans/CB-WP-0036-interactive-mode.md | +| task | CB-WP-0036-T06 | todo | — | workplans/CB-WP-0036-interactive-mode.md | diff --git a/specs/ArchitectureBlueprint.md b/specs/ArchitectureBlueprint.md index 6d0ed3a..aa88d54 100644 --- a/specs/ArchitectureBlueprint.md +++ b/specs/ArchitectureBlueprint.md @@ -5,6 +5,9 @@ the stable structural decisions: layers, component planes, capability ports, data flows, and repository layout. For motivation and product intent see [`../INTENT.md`](../INTENT.md); for the full originating exploration see [`../history/260730-InitialExploration.md`](../history/260730-InitialExploration.md). +For the boundary between what the rules can see and everything else a +player experiences — and which repository each belongs to as the simulator +grows — see [`Ornamentation.md`](Ornamentation.md). Status: **draft** — this blueprint is normative for new work but still malleable (Clay). Changes go through a decision record in `decisions/`. diff --git a/specs/Ornamentation.md b/specs/Ornamentation.md new file mode 100644 index 0000000..e8dca42 --- /dev/null +++ b/specs/Ornamentation.md @@ -0,0 +1,250 @@ +# Ornamentation — what a game is besides its rules + +Status: **draft**, normative for new work. Changes go through a decision +record in `decisions/`. + +Companion to [`ArchitectureBlueprint.md`](ArchitectureBlueprint.md) +(layers and ports) and [`GameDesign.md`](GameDesign.md) (findings about +the game). This document draws **one boundary**: between what the rules +can see and everything else a player experiences — and says which repo +each belongs to as the simulator grows. + +> **A good game is not only its rules.** It is materials, flow, timing, +> relatability, illustration, typography, and the ceremony around play. +> A simulator that models only the rules models a *part* of the game, and +> should say which part rather than implying it is the whole. + +--- + +## 1. Two categories, and the test between them + +**Mechanism** is anything that can change the state the rules can see. + +**Ornamentation** is everything else the player nonetheless experiences. + +### 1.1 The test + +> **Does it move the state hash?** +> +> If yes, it is mechanism. If no, it is ornamentation. + +This reuses an instrument the project already has and already trusts: +`state_hash` is what makes a session comparable to its replay, and what a +trial note binds to (ADR-0019 D3). **The line is therefore executable, not +editorial** — which matters here more than elsewhere, because everything +downstream depends on the classification being right. + +### 1.2 Ornamentation usually decorates a mechanism rather than replacing it + +The clearest case, and the one that named this document: + +| the fact | category | why | +|---|---|---| +| the deck's permutation | **mechanism** | it decides the deal; in clay-borg it comes from the seed | +| **who shuffles**, and the shuffling | **ornamentation** | no rule can see it | +| the hands after dealing | **mechanism** | the state contains them | +| **who deals**, cards arriving one at a time, entering from the right | **ornamentation** | the same hands either way | + +So ornamentation is typically **a ceremony around, or a presentation of, a +mechanism** — and occasionally a thing with no mechanism under it at all. + +**"Has a decision in it" is NOT the test.** Choosing who deals is a +decision, and it is ornamentation. This was the open question in +CB-WP-0036 and the maintainer settled it: these are ornamental *because +they are not necessary*, not because nobody chooses. + +### 1.3 Why not "ritual" + +`ritual` reads as ceremony only, and half of this category is not +ceremonial — card stock, a typeface, the drift of a discard, how legible a +player mat is. **`ornamentation` covers the material and the ceremonial +together**, and carries the right implication: it is *applied to* the +thing, and it is not structural. + +Ornamentation is **not decoration in the pejorative sense**. This project +uses "decoration" for a control that cannot fail (ADR-0006 D3), and that +word is spoken for. + +--- + +## 2. Why clay-borg names what it will never render + +The rendering belongs downstream (§3). The **classification does not**, +for one reason: + +> **Calling something ornamentation is a claim that it does not matter to +> the game — and claims that something does not matter are exactly the +> claims this project has been wrong about.** + +The register is the evidence. `quantity` in `Tokens.csv` was measured +across 750 games before being declared non-binding (CB-EV-0027 §3), and +the argument that settled it was *not* "nothing exceeded it" — it was that +no numbered rule mentions a supply, so enforcing one would have been the +engine deciding a rules question. F18 stands open because four edition +files were assumed not to matter. CB-WP-0023 exists because SOLVE was +offered where it could not act. + +**A classification is a claim about the game.** It therefore belongs where +this project keeps claims about the game — with a reproduction and a +falsifier (GameDesign §1) — and not in a renderer's stylesheet, where +nothing can contradict it. + +### 2.1 What a declaration carries + +1. **What it ornaments** — the mechanism it accompanies, or `none`. +2. **Why it does not bind** — by rule text where the edition has one, or + by measurement, or explicitly *"provisional, nobody has ruled"*. +3. **What would falsify it** — the rule or observation that would make it + mechanism. A declaration that cannot be wrong is not a claim. + +**Provisional is a legitimate state and must be said out loud.** The +failure mode this project has already committed once is canonising a +provisional default by implementing it quietly. + +### 2.2 Ornamentation is sourced, not invented + +ADR-0015's discipline applies unchanged: **the game's own words, where the +game has words.** Card text, mat layout, the vocabulary in `Glossary` and +the stage names in `DARVO` are ornamentation-bearing data that exists +upstream and is currently **unvendored** (F18). + +Where the edition says nothing, clay-borg may choose — and must **label +the choice as ours**, exactly as the rankings panel labels its one derived +superlative *"clay-borg's reading, not a rule"* (CB-EV-0026 §5). + +--- + +## 3. The module boundary + +```mermaid +flowchart LR + CB["clay-borg + state - rules - admissibility + trials - findings + ornamentation DECLARED + one simple built-in view"] + CA["clay-animate + movement - timing - layering + the interactive pace's presentation"] + CP["clay-physics + material simulation + cards - table - gravity"] + CB -->|"facts + declarations"| CA + CA --> CP +``` + +**clay-borg is the simulation core and stays that way.** Its built-in view +is deliberately plain: simple frontend/backend interaction, simple UI +concepts, so attention stays on the game and the simulation rather than on +a rendering pipeline. **Its native pace is Speed** (§4), and it is tuned +for that. + +**clay-animate** is where movement lives: a card summoned larger beside +the acting seat, shrinking toward its target, a discard drifting without +resizing. It is a *later, separate repository* and needs a client/server +interaction materially more complex than the core should carry. + +**clay-physics** is further out still: real material behaviour. + +### 3.1 The rule that makes the boundary hold + +> **Downstream may read. Downstream may not decide.** + +This is [ADR-0007](../decisions/ADR-0007-hot-seat-in-a-browser.md) D5 — +*the page reports raw pointer facts and constructs no commands* — restated +one level up, at the repository boundary rather than the script boundary. + +A game played through `clay-animate` must be **indistinguishable, in the +record, from the same game played through clay-borg's own view.** If a +renderer can change an outcome it is not a renderer. + +### 3.2 Why the port is not being built yet + +**No consumer exists.** This project's own rules say a kind with no +instance was invented rather than observed (GameDesign §2) and a gate that +cannot go red is decoration (ADR-0006 D3). An interface designed against +an imagined client would be both. + +**What is being fixed now is the vocabulary and the boundary.** The port +gets designed when `clay-animate` exists to pull on it, and the first +version of it should be *the data clay-borg already emits* — the journal +is already the sequence of what happened, and CB-WP-0032 already reads it. + +--- + +## 4. Pace + +`--pace speed | interactive` (proposed; **not** `--mode`, which is +already `ScoringMode`). + +| pace | what it means | +|---|---| +| **speed** | ornamentation is skipped; the view jumps to the result. **The default**, and what `sim`, `trials`, benchmarks and bot play always use | +| **interactive** | ornamentation is performed | + +Pace selects **how much ornamentation is performed**. It can never select +*different mechanism*, which §5 states as an invariant rather than an +intention. + +`prefers-reduced-motion` behaves as **speed**. + +--- + +## 5. Invariants + +These are the document's teeth. **I1–I4 are checkable today, cheaply**, +which is the point — this project has 62 untagged literals as evidence of +what a broad unenforced requirement produces (ADR-0018 D4). + +| | invariant | +|---|---| +| **I1** | Ornamentation never moves `state_hash`. | +| **I2** | Ornamentation never enters the journal or the recording. | +| **I3** | The same seed and the same decisions produce a **byte-identical recording** at any pace, through any renderer. | +| **I4** | Speed pace costs the core **nothing** — not "little": `sim`, `trials` and the benchmarks are unaffected. | +| **I5** | Every ornamentation declaration states what would falsify it (§2.1). | + +**I3 is the falsifier for the whole boundary.** If it ever fails, +something downstream has become mechanism and the split has stopped being +real. + +### 5.1 What to do when ornamentation must be preserved + +I2 keeps the recording canonical, which raises a fair objection: a replay +then cannot reproduce **what a player actually saw**. + +The answer already exists in this repo. A trial keeps *two* files — the +recording and a sibling log of what the player said (GameDesign §5). **A +session's ornamentation goes in a sibling too**, never in the scenario. +One artifact stays replayable; the other stays human. + +--- + +## 6. Where a new capability goes + +In order. The first match wins. + +1. **Can it change a legal move, an outcome, or the state hash?** + → clay-borg, as mechanism, under the existing rule budgets. +2. **Is it a claim that something does *not* matter?** + → clay-borg, as a declared ornamentation with a falsifier (§2.1). + **This is the step that gets skipped**, and skipping it is how a + provisional default becomes canon without anyone deciding. +3. **Is it the presentation, timing or movement of either?** + → clay-animate. +4. **Does it need materials to behave like materials?** + → clay-physics. +5. **None of these?** Then it is not yet understood well enough to place, + and the honest move is a finding, not a module. + +--- + +## 7. Falsifier for this document + +If an ornamentation declaration is ever found to have changed an outcome, +§1.1's test is not the right test and this document is wrong at the root — +not patchable at the edges. + +If, after `clay-animate` exists, **§3.2's deferred port turns out to have +needed designing here all along**, then the "no consumer, no interface" +rule cost more than it saved, and that should be recorded against it. diff --git a/workplans/CB-WP-0035-a-session-that-answers-nothing.md b/workplans/CB-WP-0035-a-session-that-answers-nothing.md index 9b5943a..20c5c99 100644 --- a/workplans/CB-WP-0035-a-session-that-answers-nothing.md +++ b/workplans/CB-WP-0035-a-session-that-answers-nothing.md @@ -3,6 +3,7 @@ id: CB-WP-0035 kind: product title: "A session that answers nothing" status: done +state_hub_workstream_id: "c4c2fcbe-064c-4c19-b851-1d8d5940a24c" --- # Purpose @@ -41,6 +42,7 @@ thrown away. id: CB-WP-0035-T01 status: done priority: high +state_hub_task_id: "7be2de30-1077-439a-8e70-a20031e9ba97" ``` **Controls:** diff --git a/workplans/CB-WP-0036-interactive-mode.md b/workplans/CB-WP-0036-interactive-mode.md index 4233f2f..56e1e52 100644 --- a/workplans/CB-WP-0036-interactive-mode.md +++ b/workplans/CB-WP-0036-interactive-mode.md @@ -1,216 +1,132 @@ --- id: CB-WP-0036 kind: product -title: "Interactive Mode: the rituals and the movement" -status: ready +title: "Pace and ornamentation" +status: active +state_hub_workstream_id: "698651ed-cccd-46f2-84cc-07b0bdb85ad0" --- # Purpose ``` -structural tier L (creates a new capability port -- a pace of play that - the driver, the server and the page all take part in, - plus a class of interaction that is NOT a game - command) +structural tier M (a driver parameter and a declared vocabulary; the + animation architecture that made this L has moved + out of this repo) chaos d8 = 7 → no override -declared tier L +declared tier M ``` -**Declaration 7 of chaos window 3.** +**Re-declared 2026-08-07, declaration 8 of chaos window 3.** -> **Tier L requires a separate-agent adversarial review before code** -> (InnerLoop §Loop tiers, Step 2). **It has not been done**, and this -> workplan is `ready`, not `active`. Ask for it before T02 opens. +## Why this was rewritten, and what it used to say -## The report +Declared on 2026-08-07 as **tier L**, covering an animation layer, +Rust-computed transitions over the journal delta, and a client/server +interaction able to animate other players' moves. Chaos was d8 = 7, no +override. **No code was written**, and the tier-L adversarial review was +never run — which is the only reason this could be re-scoped rather than +unwound. -> *"Interactive-mode should include explicit rituals and visualizations -> inspired by real life physical gameplay. In Speed-mode the UI jumps to -> the result immediately skipping animations and rituals that do not have -> any decisions in them."* +**The maintainer moved the animation out of clay-borg**, and the reasoning +is now [`specs/Ornamentation.md`](../specs/Ornamentation.md): -Named in the report: +> the basic simulator should have the relevant concepts of simulation and +> interaction, feedback mechanisms etc. with very simple ui concepts and +> frontend, backend interactions to keep the focus on the game and +> simulation core -| | | -|---|---| -| **opening ritual** | who shuffles, who deals, who plays first — *"part of the ritual of focusing on the game"* | -| **closing ritual** | handing the cards on, or throwing them down after a loss — before deciding whether to play again | -| **drawing** | explicitly drawing from the stack, or being dealt by the dealer | -| **dealing to hand** | cards enter **from the right** | -| **sorting** | drag-and-drop between hand slots | -| **playing a card** | summoned **larger, on a layer above the game**, next to the player's seat — *"this signals which player is playing the card"* — then shrinking as it travels to its target | -| **discarding** | drifts to the pile **without shrinking**, or barely | -| **other players** | their actions visualized, not jumped past into a log line | +So movement, timing and layering belong to a later, separate +**`clay-animate`**; material behaviour to **`clay-physics`** beyond that. +**What stays here is the vocabulary, the boundary and the pace knob** — +and the invariants that keep the boundary real once something downstream +exists to test it. -## What makes this tier L, and it is not the animation +**Two terms changed and the change is not cosmetic.** "Ritual" became +**ornamentation**, because half the category is material rather than +ceremonial — card stock, a typeface, the drift of a discard. And the test +is no longer *"does it have a decision in it"*: choosing who deals is a +decision and is ornamental. **The test is whether the state hash moves**, +which is executable, and which settles the open question the previous +version of this workplan left for a reviewer. -**Three things in the report are not presentation at all.** - -1. **A ritual is an interaction with no command behind it.** "Who deals" - changes nothing a rule can see. It must therefore be a *driver-level* - decision point that never becomes a `GroundCommand`, never enters the - journal, and **never reaches the recording** — or two players who made - the same moves at different paces would produce different scenarios, - and `record.rs`'s round trip is the test everything else rests on. - -2. **Hand order is not game state.** Sorting your hand must not move - `state_hash`. If it does, sorting breaks every note's binding - (ADR-0019) and every replay. But it also cannot be client-only: the - page reloads after each accepted move (below), so the order would be - lost every turn. It has to be **held by the server and excluded from - the hash** — a category this project does not yet have. - -3. **Animating another player's move requires the page to see a sequence, - not a state.** The page currently renders *the position now*. Interactive - mode needs *what happened since you last looked*, in order. - -**The third is the one that decides the architecture**, and the good news -is that the data already exists: the journal is exactly that sequence -(`Applied { actor, command, events }`), and CB-WP-0032 already reads it -per game. - -## The obstacle to name before anyone starts - -**The page reloads after every accepted command** (`window.location. -reload()`), which destroys the DOM — and you cannot animate across it. - -Two ways out, and only one is allowed: - -| | | -|---|---| -| **JS mutates the DOM instead of reloading** | **Refused.** The script would have to compute what the game now looks like, which is ADR-0007 D5's line. It says the page reports raw pointer facts and constructs nothing | -| **Rust describes the movement; the new page animates into place** | Rust already knows both positions. It emits *transitions* — what moved, from where, to where — and the reloaded page plays them before settling into the state it was served | - -**The second keeps the server authoritative** and makes the animation a -rendering of facts Rust wrote, exactly like the log. - -## Task: decide the pace, and what it may not touch +## Task: the concept, in the spec that governs structure ```task id: CB-WP-0036-T01 -status: todo +status: done priority: high ``` -`decisions/ADR-0020-*.md`. +**Controls:** +- the boundary has a **falsifier**, not just a diagram; +- ornamentation is defined by a test something can **run**, not by taste; +- it says what is deliberately **not** built and why. -- **Name it, and not `mode`.** `--mode` is already `ScoringMode` - (shared/common/coalitions). A second "mode" on the same driver is a - collision waiting to be mis-read; propose `--pace interactive|speed`. -- **Speed stays the default** for `sim`, `trials`, benchmarks and bots. - Animation must cost those nothing — not "be fast", cost *nothing*. -- **State the invariant that protects everything else:** for the same seed - and the same decisions, **the recording is byte-identical in both - paces**. Rituals are not commands. -- **State where hand order lives** and that it is outside the state hash. -- **`prefers-reduced-motion` behaves as Speed**, and say so in the ADR - rather than leaving it to the CSS. +**Done 2026-08-07.** [`specs/Ornamentation.md`](../specs/Ornamentation.md). -## Task: transitions, computed in Rust +**§1.1 makes the line executable** by reusing `state_hash` — the same +instrument that binds a trial note to a position (ADR-0019 D3). + +**§2 is the part that earns its place in this repo rather than a +renderer's stylesheet.** Calling something ornamentation is a claim that +it does not matter, and this project's register is a list of times that +claim was wrong — `quantity` in `Tokens.csv`, F18's four unread files, +SOLVE offered where it could not act. So a declaration carries a +falsifier, and *provisional* is a state it must be able to say out loud. + +**§3.1 restates ADR-0007 D5 one level up:** downstream may read, may not +decide. **§3.2 refuses to design the port**, because no consumer exists +and an interface built against an imagined client is the same defect as a +gate that cannot go red. + +**§5 gives five invariants, four of them checkable today.** I3 — the same +seed and decisions produce a byte-identical recording at any pace, through +any renderer — is the falsifier for the whole split. + +## Task: the pace parameter ```task id: CB-WP-0036-T02 status: todo -priority: high +priority: medium ``` -The journal delta since the page last -rendered, expressed as movements: what moved, from where, to where, and -whether it stays. +`--pace speed | interactive`, defaulting to **speed**, and **not** +`--mode` (taken by `ScoringMode`). -- **The page is told, never asked to work it out** (ADR-0007 D5). -- **A transition names an element the page can already find**, by the same - `data-*` keys the drag code uses — inventing a second addressing scheme - is how the two drift apart. -- **Control: the delta is exact.** A page that has seen commands 0..k - animates k..n and nothing else. Replaying a transition twice, or - skipping one, must fail a test. +**Controls:** +- **I4 measured, not asserted**: `sim`, `trials` and the benchmarks are + unaffected — *nothing*, not *little*; +- `prefers-reduced-motion` behaves as speed; +- **the flag exists before anything reads it**, and that is deliberate: + it is the seam `clay-animate` will attach to, and a seam is cheap while + a retrofit is not. -## Task: the movement itself +## Task: declarations, once there are any to make ```task id: CB-WP-0036-T03 status: todo -priority: high +priority: low ``` -A layer above the game layer; card summoned -larger next to the acting seat, shrinking toward its target; discards -drifting without shrinking. +Ornamentation declarations per §2.1 — what is ornamented, why it does not +bind, what would falsify it. -- **A player must be able to act DURING an animation.** If animation gates - input, interactive mode is worse than speed mode and the pass has failed. -- **Skippable, always**, and skipping lands exactly where the animation - would have. -- **Control: a full game is completable with animations on.** The table - has already been made unplayable once by growing (CB-WP-0028); an - overlay layer is the same hazard wearing a different hat. +**Not started deliberately.** GameDesign §2's rule applies: **no kind +exists without an instance that instantiates it.** The first real +declarations are most likely to come from F18's unvendored files — +`Player_Mats` and `Glossary` are ornamentation-bearing data this engine +has never read — so **vendoring those is the trigger**, not a schema +designed in advance. -## Task: the rituals +## No longer in this repo -```task -id: CB-WP-0036-T04 -status: todo -priority: medium -``` - -Opening — shuffle, deal, first player. Closing — hand the -cards on, or throw them down. - -- **Never a `GroundCommand`.** A ritual is a driver-level decision point. -- **Control: the recording is byte-identical to the same game played in - Speed.** This is the falsifier for the whole task. -- **The closing ritual comes before the play-again decision**, which is - where the report puts it. - -## Task: the hand: dealt from the right, sortable - -```task -id: CB-WP-0036-T05 -status: todo -priority: medium -``` - -Cards enter from the right; drag to reorder. - -- **Control: sorting does not move `state_hash`.** Assert it directly. - Sorting that changed the hash would silently break every trial note's - binding and every replay. -- Order survives a reload, because the page reloads on every move. -- **Drawing becomes explicit** — but only where the rules have a draw to - make explicit. CB-WP-0028 established there is no standalone draw - command: INVESTIGATE's own text is *"…reveal it. **Then draw one - Solution.**"* **Do not build a draw the game does not have.** What is - explicit here is the *animation* of a draw that already happens. - -## Task: evidence - -```task -id: CB-WP-0036-T06 -status: todo -priority: medium -``` - -`evidence/CB-EV-*.md`. - -- **Does it make the game more legible, or only longer?** The report's own - claim is that ritual helps focus. That is testable only by playing, and - the answer may be *no* — say so if it is. -- **What Speed mode cost**, measured, since the whole point is that it - costs nothing. -- **Whether the maintainer still needs the log to follow other players** - (their 2026-08-07 note) — that is this pass's acceptance test and it has - a person attached to it. - -## Open questions the review should settle - -1. **Is a ritual with no decision still a ritual?** The report says - interactive mode skips *"animations and rituals that do not have any - decisions in them"* — but shuffling and dealing have no decisions - either, and the report wants them. The line is not where the report - puts it, and someone has to redraw it. -2. **How many transitions can queue before it stops feeling like play?** - With bots, several commands can land between two human turns. -3. **Does the recording need the pace recorded in it?** Recording it makes - scenarios pace-specific; not recording it means a replay cannot - reproduce what a player actually saw. +- **the animation layer**, transitions over the journal delta, cards + summoned larger beside a seat and shrinking toward a target, discards + drifting — **`clay-animate`**; +- **material simulation** — **`clay-physics`**; +- **hand sorting**, which was T05 here: it is presentation of a hand whose + *contents* are mechanism, so it goes with the renderer. The constraint + survives the move and is now I1: sorting must not move `state_hash`, + because a hash that moved would break every trial note's binding.