1## Context23The Crate Works drafts use ordinary `PLATE` and `GATE` nouns linked by a small4visible channel palette. A plate is pressed while another entity occupies its5cell. A gate is traversable when its channel has a pressed plate, or while6another entity occupies the gate cell after contacts. The latter is a jam, not7hidden history: every settled gate state is recomputed from the current board.89The current engine plans movement through `planAutomatonMove()`, treats all10objects in a cell as contacts, and resolves SINK/DEFEAT before final victory.11The gate contract must use the prior settled gate projection while planning a12turn, then recompute after contacts. This makes pressing a plate take effect on13the next turn and lets a presser destroyed by SINK or DEFEAT release its plate14on the same turn.1516## Goals and non-goals1718### Goals1920- Make channels data-only and stable across noun transformations.21- Keep circuit membership determined by the current noun, with no remembered22 open bit that can disagree with the visible board.23- Make anything except the plate entity itself a valid presser.24- Make closed gates stop movement regardless of current rule properties.25- Preserve behavior through snapshots, Undo, reset, restore, sharing, and the26 compact solver transition boundary.27- Provide bounded settled events for design-owned animation and audio.2829### Non-goals3031- Edge-triggered switches or toggles.32- Gate crushing, damage, or automatic destruction of occupants.33- A new grammar such as `PLATE IS SWITCH` or `GATE IS SHUT`.34- Arbitrary channel names or channel colors supplied by a mod.35- Deciding the separate FRAIL/crumbling mechanic.3637## Decisions3839### Channel metadata stays with the authored entity ID4041An authored object may declare `channel` using one of the host's fixed channel42tokens. The normalized object retains that field through reset, restore, noun43transformation, CommonJS export, catalog installation, and data-only sharing.44The current noun controls participation: an entity participates as a plate only45while its noun is `PLATE`, and as a gate only while its noun is `GATE`.4647When `GATE IS CRATE` transforms a gate, it becomes an ordinary CRATE, leaves48the circuit, and has no remembered open state. If a later rule transforms it49back to GATE, it rejoins using its authored channel and recomputes its state at50the end of that turn from the current plate and gate occupancy.5152### Pressure is occupancy, not entry5354At the post-contact settled boundary, a plate is pressed when at least one55other surviving entity occupies its cell. Words count, regardless of their56properties. The plate entity itself does not press itself. A plate can therefore57be pressed by a non-PUSH YOU object, a pushed word, or an automaton actor.5859For each active gate, openness is recomputed as:6061```text62pressed(channel) || occupiedByOther(gate cell)63```6465The occupancy term is the jam rule. It prevents crushing and keeps a gate open66until the cell is empty. There is no persistent gate bit whose value can differ67from this settled projection.6869### Movement reads the prior settled projection7071Before player or automaton movement, the engine derives gate blockers from the72prior settled state. A closed active gate rejects entry as an unconditional73STOP, regardless of `GATE` properties or other rule predicates. An open gate74has no movement property. Gate changes never occur mid-turn, so pressing a75plate does not permit crossing the gate during that same turn.7677After movement, rule transforms, automata, and SINK/DEFEAT contacts complete,78the engine recomputes active plates and gates. A destroyed presser therefore79releases its plate on that turn. A gate transformed away is removed from the80projection; if transformed back, its state is recomputed from the final cells.8182### Events describe settled changes8384Settled results add these bounded arrays when a value changes:8586```js87gateChanged: [{ id, open, jammed }]88plateChanged: [{ id, pressed }]89```9091`jammed` is true when the gate is open because another surviving entity occupies92its cell while no channel plate is pressed. An active/inactive noun transition93may emit a false/closed change for the prior circuit member so presentation can94remove its state marker. Event records use stable authored IDs and are cloned95before returning to callers.9697### Channel markers are neutral shape data9899The host maps its fixed channels to neutral shape markers such as `▲`, `●`,100`■`, and `◆`. They are drawn in the foreground color and do not use property101colors; a pink or blue gate would be read as DEFEAT or SINK. The renderer may102show the marker on plates and gates and list the channel in the ledger, but103shape mapping is presentation data derived from the validated channel token.104105### Solver identity remains memoryless106107Channel is static authored metadata and current gate openness is derived from108the settled object state. The solver codec must not add a hidden mutable `open`109bit to the search key. Instead, the gate mechanic registry declares its110deterministic derived projection and the codec fails if an implementation tries111to introduce an unregistered dynamic gate field. Public `step()` and the fast112solver transition must derive the same prior projection and produce the same113post-contact events.114115## Risks and mitigations116117- **A gate is treated as a normal STOP object.** Keep gate blocking in the118 movement mechanic boundary so rule precedence cannot reopen a closed gate.119- **A presser disappears during contacts.** Recompute only after contacts and120 add a SINK/DEFEAT release fixture.121- **A transformed gate retains stale state.** Derive participation from noun122 every turn and clear inactive projection entries.123- **The solver encodes derived state inconsistently.** Add same-board parity124 tests and reject unregistered mutable mechanic fields.125- **Channel colors imply properties.** Keep shape markers neutral and test the126 presentation payload separately from property palette colors.127- **Adjacent plate and gate trivialize a level.** Keep the content warning in128 world authoring and validate only structural channel consistency here.129130## Migration and rollback1311321. Add channel metadata validation and data-boundary round trips.1332. Add prior-settled gate blocking and post-contact recomputation.1343. Add events, reset/Undo/restore, and public/fast parity fixtures.1354. Add the D1–D3 and transformed-gate proofs to Crate Works after solver136 acceptance and design review.137138Rollback removes the gate mechanic registration and leaves ordinary objects,139rules, and levels valid. A level using channel metadata must not be bundled140 until the host feature is available.141142## Open questions143144- Should an active gate or plate with no matching channel partner be a load145 warning, a validation error, or an allowed inert circuit?146- If a gate is destroyed rather than transformed, should the event include an147 inactive `gateChanged` record or only the existing destruction record?148- If multiple entities enter and leave the same gate cell during one accepted149 turn, is final post-contact occupancy the sole jam evidence? The current150 proposal assumes yes.151- Should channel tokens be exposed in pack vocabulary or remain metadata-only?