--- id: CB-WP-0036 kind: product title: "Pace and ornamentation" status: done state_hub_workstream_id: "698651ed-cccd-46f2-84cc-07b0bdb85ad0" --- # Purpose ``` 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 M ``` **Re-declared 2026-08-07, declaration 8 of chaos window 3.** ## Why this was rewritten, and what it used to say 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. **The maintainer moved the animation out of clay-borg**, and the reasoning is now [`specs/Ornamentation.md`](../specs/Ornamentation.md): > 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 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. **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. ## Task: the concept, in the spec that governs structure ```task id: CB-WP-0036-T01 status: done priority: high state_hub_task_id: "e7602796-cdb7-44cf-a39d-697b1e8e2a7f" ``` **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. **Done 2026-08-07.** [`specs/Ornamentation.md`](../specs/Ornamentation.md). **§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: done priority: medium state_hub_task_id: "e978b93b-fcbd-4853-a27d-5eca00f9ca19" ``` `--pace speed | interactive`, defaulting to **speed**, and **not** `--mode` (taken by `ScoringMode`). **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. **Done 2026-08-07.** `--pace speed|interactive`, `Pace::Speed` the `Default`. **I3 is asserted, not intended.** `pace_cannot_change_the_game` plays the same scripted game at both paces and compares the **serialised recording byte for byte**, plus the end state hash. Mutation-proven: leak the pace into the seed and it fails with *"the recording differs by pace, so a renderer has become mechanism"*. **A misspelt pace is refused rather than defaulting.** `--pace cinematic` errors and names both values. Quietly falling back to Speed would look exactly like `clay-animate` being broken, and that is the seam this flag exists to be. I4 needs no measurement yet and that is worth saying plainly: **nothing reads `pace`**, so the cost to `sim`, `trials` and the benchmarks is zero by construction rather than by benchmark. The measurement becomes real when something reads it. ## Task: declarations, once there are any to make ```task id: CB-WP-0036-T03 status: done priority: low state_hub_task_id: "bf2a68b0-5985-40ff-b4f5-33c40d92cff0" ``` Ornamentation declarations per §2.1 — what is ornamented, why it does not bind, what would falsify it. **Done 2026-08-07.** [`specs/OrnamentRegister.md`](../specs/OrnamentRegister.md), four declarations. **This reverses the reasoning written here earlier**, which said the first declarations would come from F18's unvendored files and that vendoring was the trigger. That was wrong: **instances already existed.** Hand order is the one that prompted the whole category — the request to drag cards between slots — and *"who deals"* was the maintainer's own example. Waiting for F18 would have left the register empty while its instances sat in the conversation that created it. The four: **O1 hand order** (provisional), **O2 who shuffles and deals** (provisional), **O3 where a seat is drawn** (`rule`-grounded — seat *order* is mechanism, GR-R08 rotates Lead; the drawn position is not), **O4 typography and illustration** (provisional, and **nothing may be declared about `Player_Mats` or `Glossary` until they are read** — F18). **I5 is executable**: `check_ornament_falsifier` in `loop-lint` fails any row still `declared` that names no falsifier. Mutation-proven on O1 — strip its falsifier and the lint goes red. Three self-test controls: it catches a bare declaration, clears one that names a falsifier, and skips `refuted` rows as history. **Presence, never adequacy**, and the finding text says so — the same split as ADR-0018 D5. ## No longer in this repo - **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.