clone

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

main
miau-is-true / openspec / changes / archive / 2026-09-24-validate-mod-feature-contract / specs / commonjs-mods / spec.md
spec.md 3.5K rendered
1## ADDED Requirements23### Requirement: Pack validation SHALL distinguish unknown rule words from unsupported mechanics4The loader SHALL accept optional `manifest.features` as a list of unique supported feature identifiers and SHALL reject unknown required features before registration with an upgrade message. A level SHALL reject an object noun equal to a custom property implemented by that level. A word SHALL count as a known noun when it is placed or named as an automaton subject in that proof, or listed in the pack's palette or vocabulary. Other words that are neither core words nor implemented properties in that proof SHALL receive a nonfatal note with word and proof context, whether or not they currently complete a sentence. A word declared as a property in one proof and used as an object noun in another SHALL receive an ambiguity note even if it is in the pack palette or vocabulary. Existing packs with automata and no feature list SHALL remain valid.56#### Scenario: Unknown predicate receives a note7- **WHEN** a proof contains `DOOR IS SHUT` with `SHUT` absent from that proof's implemented properties and nouns8- **THEN** local preview succeeds, reports a note identifying `SHUT`, the proof, and the noun-transform consequence, without blocking installation910#### Scenario: Loose unknown word receives a note11- **WHEN** a proof places a loose `SHUT` word that can be moved into a sentence but declares no `SHUT` behavior or noun in that proof12- **THEN** preview reports a note for `SHUT` even before the sentence is formed1314#### Scenario: Known noun transformation remains valid15- **WHEN** a proof contains `ROCK IS MIAU` and places a `MIAU` object in that proof16- **THEN** no unknown-word note is returned for `MIAU`1718#### Scenario: Pack-defined transformation target is known19- **WHEN** one proof contains `ROCK IS GEM`, the pack palette or vocabulary defines `GEM`, and no GEM object starts in that proof20- **THEN** no unknown-word note is returned for `GEM`2122#### Scenario: Pack-wide property and thing ambiguity receives a note23- **WHEN** one proof declares `SHUT` as a custom property and another proof uses `SHUT` as an object noun and places its word24- **THEN** preview reports a nonfatal ambiguity note for `SHUT` even if the pack palette or vocabulary names it2526#### Scenario: Declared automaton property remains semantic27- **WHEN** a level declares `TICK` through `automata[].property` and contains `MOUSE IS TICK`28- **THEN** no unknown-predicate warning is returned for `TICK`2930#### Scenario: Property declared only in another proof receives a note31- **WHEN** one proof declares `TICK` through automata and another proof contains `CLOCK IS TICK` without a TICK automaton32- **THEN** the second proof reports that TICK has no property behavior there unless the pack defines TICK as a noun3334#### Scenario: Property noun collision is rejected35- **WHEN** a level declares `TICK` as an automaton property and places an object whose noun is `TICK`36- **THEN** the loader rejects the level with the object's path and does not register part of the pack3738#### Scenario: Unsupported feature is rejected39- **WHEN** a pack declares `manifest.features: ['pairs']` in a host that supports only `automata`40- **THEN** the loader rejects the pack with a readable newer-version message before any level is installed4142#### Scenario: Legacy automata pack remains usable43- **WHEN** a valid existing pack contains automata but omits `manifest.features`44- **THEN** the current loader accepts it and preserves its automata behavior