clone

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

Specify settled rule refresh after contact destruction

Dami committed 56fd5f3
commit
56fd5f3ea24cf56bbe83e8e105ce307bfda44fc1
parent
a8d37cd7ed73ca9516e4d3a23514e07b650c8a6f
author
Dami <dami.etoile@gmail.com>
6 files changed, +127 -0
Aopenspec/changes/refresh-rules-after-contact-destruction/.openspec.yaml4+++
Aopenspec/changes/refresh-rules-after-contact-destruction/README.md3++
Aopenspec/changes/refresh-rules-after-contact-destruction/design.md47++++++++++++++++++++++++++++++
Aopenspec/changes/refresh-rules-after-contact-destruction/proposal.md26+++++++++++++++++
Aopenspec/changes/refresh-rules-after-contact-destruction/specs/rule-engine/spec.md32++++++++++++++++++++
Aopenspec/changes/refresh-rules-after-contact-destruction/tasks.md15++++++++++
A openspec/changes/refresh-rules-after-contact-destruction/.openspec.yaml +4 -0
A openspec/changes/refresh-rules-after-contact-destruction/README.md +3 -0
A openspec/changes/refresh-rules-after-contact-destruction/design.md +47 -0
@@ -0,0 +1,47 @@
1+## Context2+3+The engine scans words after controlled and automated movement, transforms objects, then resolves one contact pass. `resolveContacts()` can remove word entities but currently rebuilds indexes against the old `state.rules`. That leaves `state.rules`, `state.sentences`, object properties, automata carriers, and rule deltas describing a board that no longer exists. Tidewater's sunk `STOP` word demonstrates the resulting blocked next move.4+5+## Goals / Non-Goals6+7+**Goals:**8+9+- Make every settled state and event describe rules physically present after destruction.10+- Keep the existing one-pass contact order and deterministic turn boundary.11+- Preserve exact Undo, reset, and restore behavior for the new settled state.12+13+**Non-Goals:**14+15+- A second contact cascade or another noun transformation after a rule word is destroyed.16+- Changes to rule precedence, AND parsing, FLOAT, gates, or switch semantics.17+- A new serialized field or a change to authored level data.18+19+## Decisions20+21+### Refresh derivations at the end of contact removal22+23+Contact effects use the rule set captured immediately before the contact pass. After removing entities, call the existing rule refresh path to parse surviving words and rebuild indexes and automata carriers. Reusing this path keeps reset, `step`, and `wait` consistent. Rebuilding only the cell index would retain the phantom rule; repeating the entire turn resolver would introduce contact cascades and transformation chains outside this fix.24+25+### Evaluate final victory from surviving entities and final properties26+27+Destruction is determined under pre-contact properties. The final victory check considers surviving entities and the refreshed rule set. Thus a destroyed `WIN` word cannot grant a phantom win; a destroyed `YOU` word updates control loss. This follows the existing promise that the settled event describes the surviving board. Contact destruction itself is not repeated if a refreshed rule changes `SINK` or `DEFEAT`.28+29+### Keep rule deltas relative to the pre-turn snapshot30+31+The event builder already compares the pre-turn and settled rule maps. Refreshing before that comparison reports a rule removed by destruction as `rulesRemoved`, including its original source IDs. No intermediate rule table becomes a public state.32+33+## Risks / Trade-offs34+35+- [Risk] A rule removed by SINK changes properties after contact effects have run. → Treat contact effects as a single pass; specify this boundary and add a fixture.36+- [Risk] A final WIN check changes outcomes in levels that relied on a word destroyed during the same turn. → Require survivor-based WIN and run bundled proof and Tidewater solver checks.37+- [Risk] Undo restores rules but indexes reference discarded objects. → Keep the existing index rebuild on Undo and add a destruction/Undo regression.38+39+## Migration Plan40+41+1. Add a failing W8 fixture and the final-state rule contract.42+2. Refresh rule derivations after contact removals; verify step, wait, reset, Undo, and restore.43+3. Run the Node and browser suites, then ask the world team to re-solve Tidewater's seven proofs.44+45+## Open Questions46+47+None for this bounded fix. Broader contact cascades belong to a separate rule-order change.
A openspec/changes/refresh-rules-after-contact-destruction/proposal.md +26 -0
A openspec/changes/refresh-rules-after-contact-destruction/specs/rule-engine/spec.md +32 -0
@@ -0,0 +1,32 @@
1+## MODIFIED Requirements2+3+### Requirement: The engine SHALL derive the MVP rule vocabulary from movable words4+The engine SHALL scan horizontal and vertical straight lines for `NOUN IS VALUE` sentences, with adjacent `AND` terms expanding the noun side or value side. The initial semantic properties SHALL be exactly `YOU`, `PUSH`, `STOP`, `WIN`, `SINK`, and `DEFEAT`; a noun-to-noun value SHALL be treated as a transformation. Rules SHALL be recomputed from the current word positions after a turn that changes board state, including after contact effects remove word entities. The settled active rules, physical sentence spans, derived properties, and rule deltas SHALL describe only surviving words before the next player intent.5+6+#### Scenario: An AND sentence expands to multiple properties7+- **WHEN** the board contains `BABA IS YOU AND PUSH` in one straight line8+- **THEN** the active rule table contains `BABA IS YOU` and `BABA IS PUSH`9+10+#### Scenario: A moved word changes the active rules11+- **WHEN** a legal move changes the position of a word entity12+- **THEN** the engine replaces the active rule table with rules parsed from the new word positions before the next player intent13+14+#### Scenario: A malformed line is ignored15+- **WHEN** a word line lacks `IS` or has no noun and value on both sides16+- **THEN** the line produces no active rule and does not make the turn fail17+18+#### Scenario: SINK removes a rule word19+- **WHEN** a turn causes `SINK` to destroy the `STOP` word in `ROCK IS STOP`20+- **THEN** the settled state has no `ROCK IS STOP` rule or sentence span, the event reports that rule removed, and the next move onto ROCK is not blocked by `STOP`21+22+#### Scenario: Contact removal updates derived control and automata23+- **WHEN** contact destruction removes a word granting `YOU` or a declared automaton property24+- **THEN** the settled state's control and automata carriers reflect the surviving words, and Undo restores the previous derivations25+26+#### Scenario: A destroyed WIN word cannot grant a final victory27+- **WHEN** a contact destroys the word that supplied a surviving entity's `WIN` property28+- **THEN** the final victory check uses the surviving rule table and does not mark the level won from the destroyed word29+30+#### Scenario: Restore a state after rule-word destruction31+- **WHEN** a settled snapshot lacking a destroyed rule word is restored or the level is reset32+- **THEN** the restored state derives rules from its present words, while reset restores the initial words and their rules
A openspec/changes/refresh-rules-after-contact-destruction/tasks.md +15 -0