clone

a browser grid puzzle game where you push words around to rewrite the rules of each level

main
miau-is-true / openspec / changes / add-channel-linked-gates / specs / channel-linked-gates / spec.md
spec.md 6.4K rendered
1## ADDED Requirements23### Requirement: Channel metadata SHALL be stable and declarative45Authored channel metadata SHALL be validated against the host channel palette,6remain attached to its authored entity ID through noun transformations, and7contain no executable behavior.89#### Scenario: A channel-linked pair loads1011- **WHEN** a level declares a PLATE and GATE with the same supported channel12- **THEN** both entities load with their stable channel metadata and participate13 in one circuit1415#### Scenario: A malformed channel fails closed1617- **WHEN** a pack uses an unknown channel, unsupported metadata field, or18 executable channel value19- **THEN** validation rejects the pack before installation with the declaration20 path2122#### Scenario: Channel survives a noun transform2324- **WHEN** `GATE IS CRATE` transforms an authored gate25- **THEN** the entity becomes an ordinary CRATE while retaining its authored26 channel for a later transformation back to GATE2728### Requirement: Plate pressure SHALL use final occupancy2930At the end of an accepted turn, after movement, transforms, automata, and contacts, a current-noun PLATE SHALL be pressed when any other surviving entity occupies its cell. Words and objects count regardless of properties.3132#### Scenario: Anything can press a plate3334- **WHEN** a word, non-PUSH YOU object, pushed object, or automaton actor ends35 on a plate36- **THEN** the plate is pressed at the settled boundary3738#### Scenario: A plate does not press itself3940- **WHEN** a plate has no other surviving entity in its cell41- **THEN** it is unpressed even though the plate entity occupies the cell4243#### Scenario: SINK releases a plate on the same turn4445- **WHEN** the only presser on a plate is destroyed by SINK or DEFEAT during a46 turn47- **THEN** the settled plate is unpressed and its linked gate is recomputed from48 the released final occupancy4950### Requirement: Closed gates SHALL block from the prior settled state5152During movement planning, a current-noun GATE SHALL block entry as an53unconditional STOP when its prior settled projection is closed. Gate changes54SHALL not take effect mid-turn.5556#### Scenario: Pressing a plate does not open the gate mid-turn5758- **WHEN** a mover enters a plate on the same turn that it would cross the59 linked closed gate60- **THEN** the gate blocks that turn and is available on the following turn if61 the plate remains pressed6263#### Scenario: Rules cannot reopen a closed gate6465- **WHEN** a closed gate has a rule that would otherwise remove or override STOP66- **THEN** movement into the gate remains blocked6768#### Scenario: An open gate is traversable6970- **WHEN** the prior settled projection is open71- **THEN** the gate contributes no movement blocker and does not crush an entity72 entering or occupying its cell7374### Requirement: Gate openness SHALL be memoryless and channel linked7576After contacts, each current-noun GATE SHALL be open exactly when its channel77has a pressed current-noun PLATE or another surviving entity occupies the gate78cell. A transformed-away gate SHALL leave the circuit; a gate transformed back79SHALL recompute its state from the final board without remembered openness.8081#### Scenario: A jam keeps a gate open8283- **WHEN** a gate would lose its pressed plate but another surviving entity84 occupies the gate cell after contacts85- **THEN** the gate remains open and is marked jammed until that cell is empty8687#### Scenario: A gate closes after the jam clears8889- **WHEN** the jammed gate cell becomes empty and no linked plate is pressed90- **THEN** the settled gate becomes closed9192#### Scenario: Transforming away and back recomputes9394- **WHEN** a gate transforms to CRATE, later transforms back to GATE, and the95 final channel plate and gate cell are empty96- **THEN** it rejoins closed; no prior open state affects the result9798The gate and plate projections SHALL be a derived mechanic contract. `open`,99`jammed`, and `pressed` SHALL NOT be persisted as hidden mutable mechanic100fields or redundantly encoded in solver frontier bytes. They SHALL be101recomputed from the restored objects, rules, occupancy, and authored channel102metadata.103104### Requirement: Gate and plate changes SHALL be observable in settled events105106Settled results SHALL expose cloned `gateChanged` and `plateChanged` arrays when107their final projections change. Gate records SHALL contain `id`, `open`, and108`jammed`; plate records SHALL contain `id` and `pressed`.109110#### Scenario: A circuit transition emits both records111112- **WHEN** a crate leaves a plate and the linked gate closes113- **THEN** the settled result reports the plate release and gate closure with114 stable authored IDs115116#### Scenario: Returned events cannot mutate state117118- **WHEN** a caller edits a returned gateChanged or plateChanged record119- **THEN** the engine's next `getState()` and turn use the original projections120121### Requirement: Gate state SHALL survive history and solver replay122123Reset, Undo, restore, public transitions, and fast solver transitions SHALL124derive identical gate and plate projections from the same settled object/rule125state. The compact solver identity SHALL not omit any value that affects the126prior settled blocker projection and SHALL reject hidden mutable gate fields.127128#### Scenario: Undo restores a jam and release129130- **WHEN** a turn opens or jams a gate and the player invokes Undo131- **THEN** the prior plate and gate projections return and the next movement132 matches direct replay133134#### Scenario: Solver parity preserves the next gate decision135136- **WHEN** a compact snapshot is decoded and restored before a movement that137 approaches a gate138- **THEN** public and fast transitions agree on accepted status, object state,139 gate projection, and emitted gate/plate changes140141#### Scenario: Restore recomputes a memoryless projection142143- **WHEN** a snapshot containing the same authoritative objects and channel144 metadata is restored after a prior gate projection145- **THEN** the gate and plate projections are recomputed identically without146 carrying an `open`, `jammed`, or `pressed` bit from the prior state147148#### Scenario: Hidden gate state fails closed149150- **WHEN** a gate implementation attempts to encode a mutable openness field151 that is not part of the derived projection inputs152- **THEN** the mechanic registry or solver codec rejects the state before play153 or search154155#### Scenario: Two channels remain independent156157- **WHEN** an amber plate is pressed while a teal plate is not158- **THEN** only amber gates open or jam; teal gates remain governed by teal159 occupancy