- commit
- 65a59464f6dafcb3e4e563b3ff81ea24a4ff4960
- parent
- dc618c760165e48ceffab664e08c9b4b0e54497c
- author
- Dami <dami.etoile@gmail.com>
| A | openspec/ | 2 | + |
| A | openspec/ | 90 | +++++++++++++++++++++++ |
| A | openspec/ | 58 | +++++++++++++++ |
| A | openspec/ | 115 | ++++++++++++++++++++++++++++++ |
| A | openspec/ | 45 | ++++++++++++ |
@@ -0,0 +1,90 @@
1+## Glossary contract2+3+The optional pack field is:4+5+```js6+properties: {7+ TICK: {8+ accent: 'tick',9+ describe: 'Repeats its steps, one for each of your turns.',10+ },11+}12+```13+14+Glossary keys SHALL be uppercase custom property tokens. Each value SHALL be15+an object with only `accent` and `describe`. `accent` SHALL be one of16+`you`, `push`, `stop`, `win`, `sink`, `defeat`, or `tick`; it maps to the17+existing property colour tokens, with `tick` using the signal-lime colour.18+`describe` SHALL be a non-empty plain-text sentence of at most 8019+characters. Unknown fields, invalid keys, invalid accents, empty descriptions,20+and overlong descriptions SHALL reject the whole pack before catalog mutation.21+22+For this change, a level's implemented custom property set is the union of its23+`automata[].property` values. A glossary entry supplies presentation metadata24+for such a word; it does not by itself add a parser predicate or engine25+behavior. Pair words are deliberately reserved for W13. A missing glossary26+entry uses the documented TICK-lime fallback only when that property is27+otherwise implemented by the level.28+29+## Metadata plumbing30+31+Normalization SHALL preserve the glossary in the pack source, pack-service32+views, CommonJS export, and data-only share payload. Catalog level records SHALL33+expose the pack glossary and the level's derived implemented-property set to the34+stage. The same normalized values SHALL be used for local CommonJS and shared35+payloads; notes or first-encounter state SHALL NOT become authored pack data.36+37+## Board and ledger38+39+The board SHALL classify every word in the current level's implemented custom40+property set as a property tile. It SHALL use the glossary accent when present,41+and the TICK-lime fallback when absent. Operators and nouns keep their current42+roles. The ledger SHALL use the same derived classification and accent mapping43+as the board, so a custom property cannot appear as a noun in one presentation44+and a property in another.45+46+The board and ledger APIs SHALL accept this data as options or a pure view47+model. They SHALL not inspect the pack registry, local storage, or CommonJS48+source directly. D21's beat strip remains an independent consumer of the same49+level metadata and keeps its accepted current/next-step behavior.50+51+## First-encounter card52+53+When the player enters a proof containing a custom property word with a54+glossary description, the stage SHALL request a card before normal play. The55+card data SHALL contain pack ID, property word, tile accent, description, and56+one example sentence formed from the level's own visible noun and the property57+word, such as `MOUSE IS TICK`. The card SHALL have an ENTER acknowledgement and58+an accessible equivalent of the same content.59+60+Encounter state SHALL be keyed by pack ID and property word and persisted at61+the existing progress boundary. Re-entering another proof in the same pack62+shall not show the card again for that word. A different pack using the same63+word shall have its own first encounter. Core properties SHALL never create a64+card. If a property has no glossary description, it remains renderable but has65+no teaching card.66+67+## Inspect and ledger details68+69+Inspect mode and the ledger's hover or keyboard-focus details affordance SHALL70+expose the glossary description for a declared custom property. The accessible71+text SHALL include the property word and its description, and SHALL remain72+available after the first-encounter card is dismissed. The details path SHALL73+not mutate engine state or progress beyond the first-encounter acknowledgement.74+75+## Compatibility76+77+Packs without `properties` remain valid. Existing core properties retain their78+current colors and behavior. Existing packs without custom properties have no79+new card or metadata state. Shared payloads that predate this field continue to80+decode with an empty glossary.81+82+## Browser acceptance fixture83+84+Use a small data-only imported pack with a non-TICK property such as `WIND` and85+an accent/description. The fixture SHALL verify that the word is a chamfered86+property tile, the card appears once and can be acknowledged, a second proof87+does not repeat it, and inspect/ledger details expose the description. Repeat88+the checks at desktop width, 390x844, and prefers-reduced-motion, with no89+browser console errors. The existing Clockwork automata fixture SHALL continue90+to verify beat-strip behavior separately.@@ -0,0 +1,58 @@
1+## Why2+3+The engine can already activate a level-scoped automaton from a custom rule4+such as `MOUSE IS TICK`, but the board and ledger still recognize only the5+hard-coded property vocabulary. A mod-defined word therefore looks like a6+noun, and the player has no in-board explanation for what the new word does.7+Clockwork's `TICK` glossary and the accepted D24 presentation need a stable8+data path from CommonJS pack loading through the board and stage.9+10+## What Changes11+12+- Validate and normalize an optional pack-level `properties` glossary with13+ property colour accents and short descriptions.14+- Derive the property-word set from the current level's implemented custom15+ properties, and pass glossary metadata through catalog, pack-service, and16+ share views without changing simulation semantics.17+- Render declared custom properties as chamfered property tiles and glossary18+ colours in the board and rule ledger.19+- Show a first-encounter custom-word card with its tile, description, and a20+ level-derived example sentence, persisted once per pack and word.21+- Make the description available through inspect mode and ledger hover or its22+ equivalent accessible details affordance.23+- Add browser acceptance for local/imported custom-property packs on desktop,24+ mobile, and reduced-motion presentation paths.25+26+## Capabilities27+28+### New Capabilities29+30+- `custom-property-presentation`: glossary validation, metadata plumbing,31+ property tile and ledger presentation, first-encounter teaching, and32+ accessible inspection copy.33+34+### Modified Capabilities35+36+- `commonjs-mods`: validate the optional property glossary and preserve it in37+ normalized and shared pack data.38+- `game-presentation`: consume level-local custom property metadata in the39+ board, ledger, and first-encounter card.40+41+## Dependencies42+43+- `add-rule-driven-automata` supplies the current level-local source of44+ implemented custom properties through `level.automata[].property`.45+- The D21 automata beat strip remains a separate presentation change. This46+ change may provide its property metadata seam but does not alter beat-strip47+ geometry, cue glyphs, or timing.48+49+## Deliberately Deferred50+51+- `level.pairs`, `OPEN`/`SHUT`, and their destroy-both or enter collision effect52+ remain W13. This change does not make glossary entries executable rules or53+ add pair semantics.54+- Arbitrary custom rule callbacks, new engine phases, solver state, and55+ changes to rule precedence are out of scope.56+- Exact card typography, motion timing, and final visual composition remain57+ designer-owned within the accepted Motion language; the implementation58+ must expose a stable card request and data model for those decisions.@@ -0,0 +1,115 @@
1+## ADDED Requirements2+3+### Requirement: Packs MAY declare a validated custom-property glossary4+5+The loader SHALL validate and preserve an optional `properties` glossary.6+A pack MAY declare it as a map from uppercase custom property tokens to7+`{ accent, describe }`, and the loader SHALL accept only the documented accent8+tokens and descriptions of 80 characters or fewer, reject unsupported fields9+and malformed values atomically, and preserve valid glossary data through10+normalization, catalog views, CommonJS export, and data-only sharing.11+12+#### Scenario: A valid glossary survives loading and sharing13+14+- **WHEN** a pack declares `TICK` with accent `tick` and a 55-character15+ description16+- **THEN** loading succeeds and the same normalized glossary is present in the17+ catalog view, exported CommonJS data, and decoded shared payload18+19+#### Scenario: A malformed glossary leaves the catalog unchanged20+21+- **WHEN** a pack declares an unsupported accent, an empty description, an22+ overlong description, or an unknown glossary field23+- **THEN** loading or installation fails with a field-specific error and no24+ pack or active-level catalog state is mutated25+26+### Requirement: A level's implemented custom properties SHALL be data-driven27+28+The host SHALL derive the current level's implemented custom-property set from29+its normalized automaton property declarations. Glossary metadata SHALL affect30+presentation only; it SHALL not create parser predicates or engine behavior.31+32+#### Scenario: A non-TICK automaton property is implemented locally33+34+- **WHEN** a level declares an automaton with property `WIND` and contains the35+ word `WIND`36+- **THEN** `WIND` is exposed to presentation as a custom property for that37+ level, while a glossary entry for an unrelated word does not change rules38+39+#### Scenario: A legacy pack has no glossary40+41+- **WHEN** a valid pack omits `properties`42+- **THEN** loading succeeds with an empty glossary and existing core and43+ automata behavior remains unchanged44+45+### Requirement: Declared custom properties SHALL render consistently46+47+The board and rule ledger SHALL classify every current-level implemented custom48+property as a property tile, using its glossary accent when present and the49+documented TICK-lime fallback when absent. The same property classification and50+accent SHALL be used by accessible rule details.51+52+#### Scenario: A custom property is visible as a property tile53+54+- **WHEN** the board contains `MOUSE IS WIND` and the level implements `WIND`55+ with glossary accent `push`56+- **THEN** the `WIND` word and its ledger predicate use the chamfered property57+ tile treatment and push accent, rather than noun styling58+59+#### Scenario: D21 beat presentation remains independent60+61+- **WHEN** an active TICK automaton advances a beat62+- **THEN** its accepted current/next beat strip and cue behavior remain63+ unchanged while the shared property metadata supplies only word styling and64+ details65+66+### Requirement: The first custom-property encounter SHALL teach the word67+68+The stage SHALL request an acknowledgement card before accepting proof input69+when a player enters a proof containing a glossary-described custom property.70+The card SHALL contain the pack ID, property word, tile accent, description, an71+example sentence using a visible level noun, and an accessible equivalent.72+Encounter state SHALL persist by pack ID and property word.73+74+#### Scenario: The first encounter shows a teach card75+76+- **WHEN** the player enters the first proof in pack `clockwork` containing77+ described property `TICK`78+- **THEN** the card appears before play with the TICK tile, its description,79+ and an example such as `MOUSE IS TICK`, and ENTER acknowledges it80+81+#### Scenario: Acknowledgement suppresses repeats within a pack82+83+- **WHEN** the player acknowledges TICK and enters another Clockwork proof84+ containing TICK85+- **THEN** the card does not appear again for Clockwork while the description86+ remains available through details87+88+#### Scenario: The same word in another pack is independent89+90+- **WHEN** another pack introduces its own described TICK property91+- **THEN** that pack may show its own first-encounter card independently92+93+### Requirement: Inspect and ledger details SHALL expose custom descriptions94+95+Inspect mode and the ledger's hover or keyboard-focus details affordance SHALL96+expose the property word and glossary description after or without the teach97+card, without changing simulation state or progress.98+99+#### Scenario: Details remain available after acknowledgement100+101+- **WHEN** the player acknowledges the TICK card and opens details for TICK102+- **THEN** accessible text includes `TICK` and its glossary description, and the103+ engine snapshot and move count are unchanged104+105+### Requirement: W12 SHALL defer pair mechanics106+107+This change SHALL not implement or infer `level.pairs`, OPEN/SHUT contact108+effects, entry overrides, or pair-specific animation. Those behaviors SHALL109+remain subject to the separate W13 contract.110+111+#### Scenario: Pair data is not silently executed by W12112+113+- **WHEN** a pack contains draft OPEN/SHUT pair data114+- **THEN** W12 does not execute a pair effect or alter contact resolution, and115+ the pack is handled according to the separately versioned W13 capability@@ -0,0 +1,45 @@
1+## 1. Contract and validation2+3+- [ ] 1.1 Add strict validation for `properties[WORD].accent`,4+ `properties[WORD].describe`, and unsupported glossary fields; reject packs5+ atomically with field-specific errors.6+- [ ] 1.2 Normalize glossary keys/values and derive each level's implemented7+ custom-property set from `automata[].property` without adding behavior from8+ glossary data alone.9+- [ ] 1.3 Add loader, catalog, pack-service, CommonJS export, and shared-link10+ tests for valid glossaries, malformed glossaries, missing glossaries, and11+ atomic failure preservation.12+13+## 2. Board and ledger presentation14+15+- [ ] 2.1 Thread normalized glossary and level-property metadata through the16+ catalog/stage presentation boundary.17+- [ ] 2.2 Make board word roles and property colors data-driven while retaining18+ core-property behavior and TICK fallback.19+- [ ] 2.3 Make ledger roles and accessible rule details use the same metadata;20+ avoid changing the D21 beat-strip geometry or timing.21+- [ ] 2.4 Add focused renderer tests for a non-TICK custom property and for22+ consistency between board and ledger classification.23+24+## 3. First-encounter teaching25+26+- [ ] 3.1 Add a progress-backed encounter store keyed by pack ID and property27+ word, with legacy progress preserved.28+- [ ] 3.2 Emit a stable card request containing tile, accent, description, and a29+ level-derived example sentence before proof input is accepted.30+- [ ] 3.3 Implement ENTER acknowledgement, accessible card copy, and repeat31+ suppression within a pack while allowing the same word in another pack.32+- [ ] 3.4 Expose the same description through inspect and ledger hover or33+ keyboard-focus details without mutating gameplay state.34+35+## 4. Verification and coordination36+37+- [ ] 4.1 Add the desktop, 390x844 mobile, reduced-motion, and no-console-error38+ browser fixture for a non-TICK imported custom-property pack.39+- [ ] 4.2 Re-run the existing automata browser fixtures to ensure D21 beat-strip40+ behavior remains unchanged.41+- [ ] 4.3 Run the full Node suite, production build, strict OpenSpec validation,42+ and relevant share/import flows.43+- [ ] 4.4 Post the renderer/card evidence to the design inbox for D24 review;44+ obtain a separate worlds-team handoff before bundling Clockwork.45+- [ ] 4.5 Leave `pairs`/OPEN-SHUT implementation and acceptance to W13.