- commit
- 16e1a2d6fd33b4474c6d6b3fac9445eb2325892c
- parent
- 97ffbc0bbe9480864c906b9252e011cad9258b45
- author
- Dami <dami.etoile@gmail.com>
| A | .codex/ | 159 | +++++++++++++++++ |
| A | .codex/ | 117 | ++++++++++++ |
| A | .codex/ | 287 | ++++++++++++++++++++++++++++++ |
| A | .codex/ | 111 | ++++++++++++ |
| A | .codex/ | 147 | +++++++++++++++ |
| A | docs/ | 247 | ++++++++++++++++++++++++++ |
| A | openspec/ | 2 | + |
| A | openspec/ | 81 | ++++++++ |
| A | openspec/ | 29 | +++ |
| A | openspec/ | 30 | +++ |
| A | openspec/ | 37 | ++++ |
| A | openspec/ | 34 | ++++ |
| A | openspec/ | 76 | ++++++++ |
| A | openspec/ | 40 | ++++ |
| A | openspec/ | 23 | ++ |
| A | progress.md | 9 | + |
@@ -0,0 +1,159 @@
1+---2+name: openspec-apply-change3+description: Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.4+license: MIT5+compatibility: Requires openspec CLI.6+metadata:7+ author: openspec8+ version: "1.0"9+ generatedBy: "1.4.1"10+---11+12+Implement tasks from an OpenSpec change.13+14+**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.15+16+**Steps**17+18+1. **Select the change**19+20+ If a name is provided, use it. Otherwise:21+ - Infer from conversation context if the user mentioned a change22+ - Auto-select if only one active change exists23+ - If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select24+25+ Always announce: "Using change: <name>" and how to override (e.g., `/opsx:apply <other>`).26+27+2. **Check status to understand the schema**28+ ```bash29+ openspec status --change "<name>" --json30+ ```31+ Parse the JSON to understand:32+ - `schemaName`: The workflow being used (e.g., "spec-driven")33+ - `planningHome`, `changeRoot`, and `actionContext`: planning scope and edit constraints34+ - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others)35+36+3. **Get apply instructions**37+38+ ```bash39+ openspec instructions apply --change "<name>" --json40+ ```41+42+ This returns:43+ - `contextFiles`: artifact ID -> array of concrete file paths (varies by schema - could be proposal/specs/design/tasks or spec/tests/implementation/docs)44+ - Progress (total, complete, remaining)45+ - Task list with status46+ - Dynamic instruction based on current state47+48+ **Handle states:**49+ - If `state: "blocked"` (missing artifacts): show message, suggest using openspec-continue-change50+ - If `state: "all_done"`: congratulate, suggest archive51+ - Otherwise: proceed to implementation52+53+ **Workspace guard:** If status JSON reports `actionContext.mode: "workspace-planning"` and `allowedEditRoots` is empty, explain that full workspace apply is not supported in this slice. Treat linked repos and folders as read-only context, ask the user to select an affected area through an explicit implementation workflow, and STOP before editing files.54+55+4. **Read context files**56+57+ Read every file path listed under `contextFiles` from the apply instructions output.58+ The files depend on the schema being used:59+ - **spec-driven**: proposal, specs, design, tasks60+ - Other schemas: follow the contextFiles from CLI output61+62+5. **Show current progress**63+64+ Display:65+ - Schema being used66+ - Progress: "N/M tasks complete"67+ - Remaining tasks overview68+ - Dynamic instruction from CLI69+70+6. **Implement tasks (loop until done or blocked)**71+72+ For each pending task:73+ - Show which task is being worked on74+ - Make the code changes required75+ - Keep changes minimal and focused76+ - Mark task complete in the tasks file: `- [ ]` → `- [x]`77+ - Continue to next task78+79+ **Pause if:**80+ - Task is unclear → ask for clarification81+ - Implementation reveals a design issue → suggest updating artifacts82+ - Error or blocker encountered → report and wait for guidance83+ - User interrupts84+85+7. **On completion or pause, show status**86+87+ Display:88+ - Tasks completed this session89+ - Overall progress: "N/M tasks complete"90+ - If all done: suggest archive91+ - If paused: explain why and wait for guidance92+93+**Output During Implementation**94+95+```96+## Implementing: <change-name> (schema: <schema-name>)97+98+Working on task 3/7: <task description>99+[...implementation happening...]100+✓ Task complete101+102+Working on task 4/7: <task description>103+[...implementation happening...]104+✓ Task complete105+```106+107+**Output On Completion**108+109+```110+## Implementation Complete111+112+**Change:** <change-name>113+**Schema:** <schema-name>114+**Progress:** 7/7 tasks complete ✓115+116+### Completed This Session117+- [x] Task 1118+- [x] Task 2119+...120+121+All tasks complete! Ready to archive this change.122+```123+124+**Output On Pause (Issue Encountered)**125+126+```127+## Implementation Paused128+129+**Change:** <change-name>130+**Schema:** <schema-name>131+**Progress:** 4/7 tasks complete132+133+### Issue Encountered134+<description of the issue>135+136+**Options:**137+1. <option 1>138+2. <option 2>139+3. Other approach140+141+What would you like to do?142+```143+144+**Guardrails**145+- Keep going through tasks until done or blocked146+- Always read context files before starting (from the apply instructions output)147+- If task is ambiguous, pause and ask before implementing148+- If implementation reveals issues, pause and suggest artifact updates149+- Keep code changes minimal and scoped to each task150+- Update task checkbox immediately after completing each task151+- Pause on errors, blockers, or unclear requirements - don't guess152+- Use contextFiles from CLI output, don't assume specific file names153+154+**Fluid Workflow Integration**155+156+This skill supports the "actions on a change" model:157+158+- **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions159+- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly@@ -0,0 +1,117 @@
1+---2+name: openspec-archive-change3+description: Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.4+license: MIT5+compatibility: Requires openspec CLI.6+metadata:7+ author: openspec8+ version: "1.0"9+ generatedBy: "1.4.1"10+---11+12+Archive a completed change in the experimental workflow.13+14+**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.15+16+**Steps**17+18+1. **If no change name provided, prompt for selection**19+20+ Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.21+22+ Show only active changes (not already archived).23+ Include the schema used for each change if available.24+25+ **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.26+27+2. **Check artifact completion status**28+29+ Run `openspec status --change "<name>" --json` to check artifact completion.30+31+ Parse the JSON to understand:32+ - `schemaName`: The workflow being used33+ - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context34+ - `artifacts`: List of artifacts with their status (`done` or other)35+36+ If status reports `actionContext.mode: "workspace-planning"`, explain that workspace archive is not supported in this slice and STOP. Do not move workspace changes into repo-local archives or edit linked repos.37+38+ **If any artifacts are not `done`:**39+ - Display warning listing incomplete artifacts40+ - Use **AskUserQuestion tool** to confirm user wants to proceed41+ - Proceed if user confirms42+43+3. **Check task completion status**44+45+ Read the tasks file (typically `tasks.md`) to check for incomplete tasks.46+47+ Count tasks marked with `- [ ]` (incomplete) vs `- [x]` (complete).48+49+ **If incomplete tasks found:**50+ - Display warning showing count of incomplete tasks51+ - Use **AskUserQuestion tool** to confirm user wants to proceed52+ - Proceed if user confirms53+54+ **If no tasks file exists:** Proceed without task-related warning.55+56+4. **Assess delta spec sync state**57+58+ Use `artifactPaths.specs.existingOutputPaths` from status JSON to check for delta specs. If none exist, proceed without sync prompt.59+60+ **If delta specs exist:**61+ - Compare each delta spec with its corresponding main spec at `openspec/specs/<capability>/spec.md`62+ - Determine what changes would be applied (adds, modifications, removals, renames)63+ - Show a combined summary before prompting64+65+ **Prompt options:**66+ - If changes needed: "Sync now (recommended)", "Archive without syncing"67+ - If already synced: "Archive now", "Sync anyway", "Cancel"68+69+ If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change '<name>'. Delta spec analysis: <include the analyzed delta spec summary>"). Proceed to archive regardless of choice.70+71+5. **Perform the archive**72+73+ Create an `archive` directory under `planningHome.changesDir` if it doesn't exist:74+ ```bash75+ mkdir -p "<planningHome.changesDir>/archive"76+ ```77+78+ Generate target name using current date: `YYYY-MM-DD-<change-name>`79+80+ **Check if target already exists:**81+ - If yes: Fail with error, suggest renaming existing archive or using different date82+ - If no: Move `changeRoot` to the archive directory83+84+ ```bash85+ mv "<changeRoot>" "<planningHome.changesDir>/archive/YYYY-MM-DD-<name>"86+ ```87+88+6. **Display summary**89+90+ Show archive completion summary including:91+ - Change name92+ - Schema that was used93+ - Archive location94+ - Whether specs were synced (if applicable)95+ - Note about any warnings (incomplete artifacts/tasks)96+97+**Output On Success**98+99+```100+## Archive Complete101+102+**Change:** <change-name>103+**Schema:** <schema-name>104+**Archived to:** the archive path derived from `planningHome.changesDir`/YYYY-MM-DD-<name>/105+**Specs:** ✓ Synced to main specs (or "No delta specs" or "Sync skipped")106+107+All artifacts complete. All tasks complete.108+```109+110+**Guardrails**111+- Always prompt for change selection if not provided112+- Use artifact graph (openspec status --json) for completion checking113+- Don't block archive on warnings - just inform and confirm114+- Preserve .openspec.yaml when moving to archive (it moves with the directory)115+- Show clear summary of what happened116+- If sync is requested, use openspec-sync-specs approach (agent-driven)117+- If delta specs exist, always run the sync assessment and show the combined summary before prompting@@ -0,0 +1,287 @@
1+---2+name: openspec-explore3+description: Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.4+license: MIT5+compatibility: Requires openspec CLI.6+metadata:7+ author: openspec8+ version: "1.0"9+ generatedBy: "1.4.1"10+---11+12+Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.13+14+**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.15+16+**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.17+18+---19+20+## The Stance21+22+- **Curious, not prescriptive** - Ask questions that emerge naturally, don't follow a script23+- **Open threads, not interrogations** - Surface multiple interesting directions and let the user follow what resonates. Don't funnel them through a single path of questions.24+- **Visual** - Use ASCII diagrams liberally when they'd help clarify thinking25+- **Adaptive** - Follow interesting threads, pivot when new information emerges26+- **Patient** - Don't rush to conclusions, let the shape of the problem emerge27+- **Grounded** - Explore the actual codebase when relevant, don't just theorize28+29+---30+31+## What You Might Do32+33+Depending on what the user brings, you might:34+35+**Explore the problem space**36+- Ask clarifying questions that emerge from what they said37+- Challenge assumptions38+- Reframe the problem39+- Find analogies40+41+**Investigate the codebase**42+- Map existing architecture relevant to the discussion43+- Find integration points44+- Identify patterns already in use45+- Surface hidden complexity46+47+**Compare options**48+- Brainstorm multiple approaches49+- Build comparison tables50+- Sketch tradeoffs51+- Recommend a path (if asked)52+53+**Visualize**54+```55+┌─────────────────────────────────────────┐56+│ Use ASCII diagrams liberally │57+├─────────────────────────────────────────┤58+│ │59+│ ┌────────┐ ┌────────┐ │60+│ │ State │────────▶│ State │ │61+│ │ A │ │ B │ │62+│ └────────┘ └────────┘ │63+│ │64+│ System diagrams, state machines, │65+│ data flows, architecture sketches, │66+│ dependency graphs, comparison tables │67+│ │68+└─────────────────────────────────────────┘69+```70+71+**Surface risks and unknowns**72+- Identify what could go wrong73+- Find gaps in understanding74+- Suggest spikes or investigations75+76+---77+78+## OpenSpec Awareness79+80+You have full context of the OpenSpec system. Use it naturally, don't force it.81+82+### Check for context83+84+At the start, quickly check what exists:85+```bash86+openspec list --json87+```88+89+This tells you:90+- If there are active changes91+- Their names, schemas, and status92+- What the user might be working on93+94+### When no change exists95+96+Think freely. When insights crystallize, you might offer:97+98+- "This feels solid enough to start a change. Want me to create a proposal?"99+- Or keep exploring - no pressure to formalize100+101+### When a change exists102+103+If the user mentions a change or you detect one is relevant:104+105+1. **Resolve and read existing artifacts for context**106+ - Run `openspec status --change "<name>" --json`.107+ - Use `changeRoot`, `artifactPaths`, and `actionContext` from the status JSON.108+ - Read existing files from `artifactPaths.<artifact>.existingOutputPaths`.109+110+2. **Reference them naturally in conversation**111+ - "Your design mentions using Redis, but we just realized SQLite fits better..."112+ - "The proposal scopes this to premium users, but we're now thinking everyone..."113+114+3. **Offer to capture when decisions are made**115+116+ | Insight Type | Where to Capture |117+ |----------------------------|--------------------------------|118+ | New requirement discovered | `specs/<capability>/spec.md` |119+ | Requirement changed | `specs/<capability>/spec.md` |120+ | Design decision made | `design.md` |121+ | Scope changed | `proposal.md` |122+ | New work identified | `tasks.md` |123+ | Assumption invalidated | Relevant artifact |124+125+ Example offers:126+ - "That's a design decision. Capture it in design.md?"127+ - "This is a new requirement. Add it to specs?"128+ - "This changes scope. Update the proposal?"129+130+4. **The user decides** - Offer and move on. Don't pressure. Don't auto-capture.131+132+---133+134+## What You Don't Have To Do135+136+- Follow a script137+- Ask the same questions every time138+- Produce a specific artifact139+- Reach a conclusion140+- Stay on topic if a tangent is valuable141+- Be brief (this is thinking time)142+143+---144+145+## Handling Different Entry Points146+147+**User brings a vague idea:**148+```149+User: I'm thinking about adding real-time collaboration150+151+You: Real-time collab is a big space. Let me think about this...152+153+ COLLABORATION SPECTRUM154+ ════════════════════════════════════════════155+156+ Awareness Coordination Sync157+ │ │ │158+ ▼ ▼ ▼159+ ┌────────┐ ┌────────┐ ┌────────┐160+ │Presence│ │Cursors │ │ CRDT │161+ │ "3 │ │ Multi │ │Conflict│162+ │online" │ │ select │ │ free │163+ └────────┘ └────────┘ └────────┘164+ │ │ │165+ trivial moderate complex166+167+ Where's your head at?168+```169+170+**User brings a specific problem:**171+```172+User: The auth system is a mess173+174+You: [reads codebase]175+176+ ┌─────────────────────────────────────────────┐177+ │ CURRENT AUTH FLOW │178+ └─────────────────────────────────────────────┘179+ │180+ ┌─────────────┼─────────────┐181+ ▼ ▼ ▼182+ ┌─────────┐ ┌─────────┐ ┌─────────┐183+ │ Google │ │ GitHub │ │ Email │184+ │ OAuth │ │ OAuth │ │ Magic │185+ └────┬────┘ └────┬────┘ └────┬────┘186+ │ │ │187+ └─────────────┼─────────────┘188+ ▼189+ ┌───────────┐190+ │ Session │191+ └─────┬─────┘192+ │193+ ▼194+ ┌───────────┐195+ │ Perms │196+ └───────────┘197+198+ I see three tangles. Which one's burning?199+```200+201+**User is stuck mid-implementation:**202+```203+User: /opsx:explore add-auth-system204+ The OAuth integration is more complex than expected205+206+You: [reads change artifacts]207+208+ You're on task 4: "Implement OAuth flow"209+210+ Let me trace what's involved...211+212+ [draws diagram, explores options, suggests paths]213+214+ Want to update the design to reflect this?215+ Or add a spike task to investigate?216+```217+218+**User wants to compare options:**219+```220+User: Should we use Postgres or SQLite?221+222+You: Generic answer is boring. What's the context?223+224+User: A CLI tool that tracks local dev environments225+226+You: That changes everything.227+228+ ┌─────────────────────────────────────────────────┐229+ │ CLI TOOL DATA STORAGE │230+ └─────────────────────────────────────────────────┘231+232+ Key constraints:233+ • No daemon running234+ • Must work offline235+ • Single user236+237+ SQLite Postgres238+ Deployment embedded ✓ needs server ✗239+ Offline yes ✓ no ✗240+ Single file yes ✓ no ✗241+242+ SQLite. Not even close.243+244+ Unless... is there a sync component?245+```246+247+---248+249+## Ending Discovery250+251+There's no required ending. Discovery might:252+253+- **Flow into a proposal**: "Ready to start? I can create a change proposal."254+- **Result in artifact updates**: "Updated design.md with these decisions"255+- **Just provide clarity**: User has what they need, moves on256+- **Continue later**: "We can pick this up anytime"257+258+When it feels like things are crystallizing, you might summarize:259+260+```261+## What We Figured Out262+263+**The problem**: [crystallized understanding]264+265+**The approach**: [if one emerged]266+267+**Open questions**: [if any remain]268+269+**Next steps** (if ready):270+- Create a change proposal271+- Keep exploring: just keep talking272+```273+274+But this summary is optional. Sometimes the thinking IS the value.275+276+---277+278+## Guardrails279+280+- **Don't implement** - Never write code or implement features. Creating OpenSpec artifacts is fine, writing application code is not.281+- **Don't fake understanding** - If something is unclear, dig deeper282+- **Don't rush** - Discovery is thinking time, not task time283+- **Don't force structure** - Let patterns emerge naturally284+- **Don't auto-capture** - Offer to save insights, don't just do it285+- **Do visualize** - A good diagram is worth many paragraphs286+- **Do explore the codebase** - Ground discussions in reality287+- **Do question assumptions** - Including the user's and your own@@ -0,0 +1,111 @@
1+---2+name: openspec-propose3+description: Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.4+license: MIT5+compatibility: Requires openspec CLI.6+metadata:7+ author: openspec8+ version: "1.0"9+ generatedBy: "1.4.1"10+---11+12+Propose a new change - create the change and generate all artifacts in one step.13+14+I'll create a change with artifacts:15+- proposal.md (what & why)16+- design.md (how)17+- tasks.md (implementation steps)18+19+When ready to implement, run /opsx:apply20+21+---22+23+**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.24+25+**Steps**26+27+1. **If no clear input provided, ask what they want to build**28+29+ Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:30+ > "What change do you want to work on? Describe what you want to build or fix."31+32+ From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`).33+34+ **IMPORTANT**: Do NOT proceed without understanding what the user wants to build.35+36+2. **Create the change directory**37+ ```bash38+ openspec new change "<name>"39+ ```40+ This creates a scaffolded change in the planning home resolved by the CLI with `.openspec.yaml`.41+42+3. **Get the artifact build order**43+ ```bash44+ openspec status --change "<name>" --json45+ ```46+ Parse the JSON to get:47+ - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`)48+ - `artifacts`: list of all artifacts with their status and dependencies49+ - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths.50+51+4. **Create artifacts in sequence until apply-ready**52+53+ Use the **TodoWrite tool** to track progress through the artifacts.54+55+ Loop through artifacts in dependency order (artifacts with no pending dependencies first):56+57+ a. **For each artifact that is `ready` (dependencies satisfied)**:58+ - Get instructions:59+ ```bash60+ openspec instructions <artifact-id> --change "<name>" --json61+ ```62+ - The instructions JSON includes:63+ - `context`: Project background (constraints for you - do NOT include in output)64+ - `rules`: Artifact-specific rules (constraints for you - do NOT include in output)65+ - `template`: The structure to use for your output file66+ - `instruction`: Schema-specific guidance for this artifact type67+ - `resolvedOutputPath`: Resolved path or pattern to write the artifact68+ - `dependencies`: Completed artifacts to read for context69+ - Read any completed dependency files for context70+ - Create the artifact file using `template` as the structure and write it to `resolvedOutputPath`71+ - Apply `context` and `rules` as constraints - but do NOT copy them into the file72+ - Show brief progress: "Created <artifact-id>"73+74+ b. **Continue until all `applyRequires` artifacts are complete**75+ - After creating each artifact, re-run `openspec status --change "<name>" --json`76+ - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array77+ - Stop when all `applyRequires` artifacts are done78+79+ c. **If an artifact requires user input** (unclear context):80+ - Use **AskUserQuestion tool** to clarify81+ - Then continue with creation82+83+5. **Show final status**84+ ```bash85+ openspec status --change "<name>"86+ ```87+88+**Output**89+90+After completing all artifacts, summarize:91+- Change name and location92+- List of artifacts created with brief descriptions93+- What's ready: "All artifacts created! Ready for implementation."94+- Prompt: "Run `/opsx:apply` or ask me to implement to start working on the tasks."95+96+**Artifact Creation Guidelines**97+98+- Follow the `instruction` field from `openspec instructions` for each artifact type99+- The schema defines what each artifact should contain - follow it100+- Read dependency artifacts for context before creating new ones101+- Use `template` as the structure for your output file - fill in its sections102+- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file103+ - Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact104+ - These guide what you write, but should never appear in the output105+106+**Guardrails**107+- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)108+- Always read dependency artifacts before creating a new one109+- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum110+- If a change with that name already exists, ask if user wants to continue it or create a new one111+- Verify each artifact file exists after writing before proceeding to next@@ -0,0 +1,147 @@
1+---2+name: openspec-sync-specs3+description: Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change.4+license: MIT5+compatibility: Requires openspec CLI.6+metadata:7+ author: openspec8+ version: "1.0"9+ generatedBy: "1.4.1"10+---11+12+Sync delta specs from a change to main specs.13+14+This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement).15+16+**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.17+18+**Steps**19+20+1. **If no change name provided, prompt for selection**21+22+ Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.23+24+ Show changes that have delta specs (under `specs/` directory).25+26+ **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.27+28+2. **Resolve change context**29+30+ Run:31+ ```bash32+ openspec status --change "<name>" --json33+ ```34+35+ If status reports `actionContext.mode: "workspace-planning"`, explain that workspace spec sync is not supported in this slice and STOP. Do not fall back to repo-local paths or edit linked repos.36+37+3. **Find delta specs**38+39+ Use `artifactPaths.specs.existingOutputPaths` from the status JSON as the list of delta spec files.40+41+ Each delta spec file contains sections like:42+ - `## ADDED Requirements` - New requirements to add43+ - `## MODIFIED Requirements` - Changes to existing requirements44+ - `## REMOVED Requirements` - Requirements to remove45+ - `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format)46+47+ If no delta specs found, inform user and stop.48+49+4. **For each delta spec, apply changes to main specs**50+51+ For each repo-local capability delta spec path returned by the CLI:52+53+ a. **Read the delta spec** to understand the intended changes54+55+ b. **Read the main spec** at `openspec/specs/<capability>/spec.md` (may not exist yet)56+57+ c. **Apply changes intelligently**:58+59+ **ADDED Requirements:**60+ - If requirement doesn't exist in main spec → add it61+ - If requirement already exists → update it to match (treat as implicit MODIFIED)62+63+ **MODIFIED Requirements:**64+ - Find the requirement in main spec65+ - Apply the changes - this can be:66+ - Adding new scenarios (don't need to copy existing ones)67+ - Modifying existing scenarios68+ - Changing the requirement description69+ - Preserve scenarios/content not mentioned in the delta70+71+ **REMOVED Requirements:**72+ - Remove the entire requirement block from main spec73+74+ **RENAMED Requirements:**75+ - Find the FROM requirement, rename to TO76+77+ d. **Create new main spec** if capability doesn't exist yet:78+ - Create `openspec/specs/<capability>/spec.md`79+ - Add Purpose section (can be brief, mark as TBD)80+ - Add Requirements section with the ADDED requirements81+82+5. **Show summary**83+84+ After applying all changes, summarize:85+ - Which capabilities were updated86+ - What changes were made (requirements added/modified/removed/renamed)87+88+**Delta Spec Format Reference**89+90+```markdown91+## ADDED Requirements92+93+### Requirement: New Feature94+The system SHALL do something new.95+96+#### Scenario: Basic case97+- **WHEN** user does X98+- **THEN** system does Y99+100+## MODIFIED Requirements101+102+### Requirement: Existing Feature103+#### Scenario: New scenario to add104+- **WHEN** user does A105+- **THEN** system does B106+107+## REMOVED Requirements108+109+### Requirement: Deprecated Feature110+111+## RENAMED Requirements112+113+- FROM: `### Requirement: Old Name`114+- TO: `### Requirement: New Name`115+```116+117+**Key Principle: Intelligent Merging**118+119+Unlike programmatic merging, you can apply **partial updates**:120+- To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios121+- The delta represents *intent*, not a wholesale replacement122+- Use your judgment to merge changes sensibly123+124+**Output On Success**125+126+```127+## Specs Synced: <change-name>128+129+Updated main specs:130+131+**<capability-1>**:132+- Added requirement: "New Feature"133+- Modified requirement: "Existing Feature" (added 1 scenario)134+135+**<capability-2>**:136+- Created new spec file137+- Added requirement: "Another Feature"138+139+Main specs are now updated. The change remains active - archive when implementation is complete.140+```141+142+**Guardrails**143+- Read both delta and main specs before making changes144+- Preserve existing content not mentioned in delta145+- If something is unclear, ask for clarification146+- Show what you're changing as you go147+- The operation should be idempotent - running twice should give same result@@ -0,0 +1,247 @@
1+# Dynamic-rule Sokoban engine: design backbone2+3+This document is a vocabulary and execution contract for a grid puzzle engine4+that combines Sokoban-style pushing with Baba Is You-style rules that are5+physical, editable objects. It separates observations about the reference6+games from recommendations for this engine so that a mod author can tell7+which behavior is compatibility-oriented and which behavior is ours to choose.8+9+## Design thesis10+11+The core puzzle loop is: inspect a board, form or break a rule, observe the12+new affordances, then make a deliberately ordered sequence of movement and13+pushes. The board contains both the objects affected by rules and the words14+that define the rules. A rule is therefore state, level geometry, and puzzle15+clue at the same time.16+17+This is a direct synthesis of two proven constraints:18+19+* Sokoban's single verb is constrained pushing. The player can walk and push20+ but cannot pull, so a push can permanently remove future options. The creator21+ Hiroyuki Imabayashi describes the 1981 prototype as a puzzle in which a bad22+ box placement can make further progress impossible ([creator interview](https://sokoboxes.com/articles/my-conversation-with-mr-hiroyuki-imabayashi/)).23+* Baba Is You makes the rules themselves pushable blocks. Teikari's GDC slides24+ describe the basic rule as object + verb + quality, with rules being25+ re-detected after words move ([GDC talk PDF](https://media.gdcvault.com/gdc2020/presentations/Reading%20the%20rules_Teikari_Arvi.pdf), pp. 8–14).26+27+Recommendation: make every turn replayable and undoable from the beginning.28+This preserves Sokoban's meaningful irreversible pushes while allowing players29+to explore a dynamic rule system without paying a restart tax.30+31+## Vocabulary inventory32+33+The engine should distinguish *surface words* (what a module places and the34+player reads) from *semantic capabilities* (what the simulation executes).35+This avoids making the parser and renderer depend on JavaScript class names.36+37+### Tier 0: board invariants38+39+These are the smallest shared concepts and should be stable in the public mod40+API.41+42+| Term | Meaning | Required invariant |43+| --- | --- | --- |44+| `cell` | One integer grid coordinate | A cell can hold zero or more entities and terrain layers. |45+| `entity` | A runtime instance with identity and position | Identity survives movement; two entities may share a cell. |46+| `kind` | Entity type, such as `baba`, `wall`, `rock`, or `text_baba` | Rules target kinds, not individual IDs, unless a mod opts into IDs. |47+| `layer` | Terrain, actor, item, text, or effect ordering | Rendering order must not silently change collision order. |48+| `direction` | Facing or movement vector | Cardinal movement is the baseline; diagonal support is an explicit extension. |49+| `occupancy` | Entities currently in a cell | Never encode occupancy as a single sprite slot: stacked words and objects are valid. |50+| `property` | A capability or tag attached by active rules | Properties are recomputed from the current rule set, not permanently mutated. |51+| `goal` | A predicate over state that ends or advances a level | A goal may be an object property (`WIN`) or a mod-defined predicate. |52+| `turn` | One accepted player intent plus all resulting resolution | Undo restores the complete pre-turn snapshot, including rules and effects. |53+54+The stacked-word invariant is evidence-based: Teikari says the shipped system55+had to be rewritten to account for words sharing a cell and to test possible56+permutations ([Game Developer interview](https://www.gamedeveloper.com/design/designing-i-baba-is-you-i-s-delightfully-innovative-rule-writing-system), lines 68–71).57+58+### Tier 1: nouns, operators, and properties59+60+The initial built-in lexicon should be small enough to teach in a few levels.61+Words are data records, not reserved identifiers; a mod can add synonyms or a62+new word that maps to an existing semantic capability.63+64+**Nouns (things that can be targeted):**65+66+`YOU`'s subject kinds such as `BABA` and `KEKE`; board kinds such as `WALL`,67+`ROCK`, `FLAG`, `WATER`, `LAVA`, `GRASS`; and meta kinds `TEXT`, `LEVEL`,68+`ALL`, `EMPTY`, `WORD`. `ALL` and `EMPTY` are selectors rather than ordinary69+spawnable kinds and need explicit scope rules.70+71+**Core relation verbs:**72+73+`IS` assigns properties or transforms one kind into another; `HAS` emits or74+creates a kind when the subject is destroyed; `MAKE` is an optional explicit75+spawn relation. Start with `IS` and `HAS`; keep `MAKE` out until a concrete76+level needs its semantics.77+78+**Core properties / capabilities:**79+80+`YOU` makes every matching entity player-controlled; `PUSH` allows an entity to81+be pushed; `PULL` makes it drag an adjacent entity when it moves; `STOP` blocks82+movement; `OPEN` and `SHUT` form a paired interaction; `SINK` consumes both83+participants; `WIN` satisfies the level goal on contact; `DEFEAT` resets or84+removes the controlled entity; `HOT` and `MELT` form a paired interaction;85+`FLOAT` chooses a collision layer; `MOVE` supplies autonomous movement; `SHIFT`86+transfers entities on contact.87+88+**Connectives and modifiers:**89+90+`AND` bundles adjacent nouns or properties; `NOT` negates a term; `ON`, `NEAR`,91+`FACING`, and `LONELY` constrain a rule by spatial context. A parser must retain92+the exact token sequence and source coordinates so diagnostics and editor93+highlighting can explain why a rule is active.94+95+These categories follow Teikari's documented progression: three-part rules,96+then `AND` and `ON`, then parameterized conditionals such as `NEAR` and97+`FACING`, then `LONELY`, `NOT`, letters, and stacked rules ([GDC talk PDF](https://media.gdcvault.com/gdc2020/presentations/Reading%20the%20rules_Teikari_Arvi.pdf), pp. 15–21).98+99+### Tier 2: derived systems100+101+These are useful after the core loop is stable:102+103+* **Rule text:** words have their own kind and can be targeted by `TEXT`,104+ transformed, destroyed, or made controllable.105+* **Plural and wildcard selectors:** `ALL IS YOU` expands to all eligible106+ kinds; expansion must be a deterministic snapshot for the turn.107+* **Conditional predicates:** a rule can query the subject's neighbors,108+ supporting cell, facing vector, or count. Predicates should be pure queries.109+* **Creation and destruction:** `HAS`, `SINK`, `DEFEAT`, `MELT`, and `OPEN /110+ SHUT` are effect relationships, not movement properties.111+* **Meta-board entities:** the level map, level-select map, or UI may become112+ simulation entities, but only in an opt-in extension tier.113+114+Teikari's implementation uses multiple passes: find candidate straight-line115+sentences, filter word-type order, validate syntax, convert to rule records,116+then apply expansion and disabling. It accepts only left-to-right and117+top-to-bottom straight lines and discards lines shorter than three words118+([GDC talk PDF](https://media.gdcvault.com/gdc2020/presentations/Reading%20the%20rules_Teikari_Arvi.pdf), pp. 10–14).119+That is a good default grammar because it is predictable to read and easy to120+debug.121+122+## Turn pipeline and precedence123+124+The following order is the recommended engine contract. It makes each phase125+observable for debugging and deterministic for mods.126+127+1. **Accept intent.** Read one cardinal input (`up`, `down`, `left`, `right`),128+ `wait`, `undo`, or `reset`. Reject input while a level transition is being129+ committed.130+2. **Snapshot.** Save the entire state, including entity identities, positions,131+ directions, text stacks, active rules, RNG seed, and pending effects.132+3. **Resolve movement intent.** Determine controlled entities from the active133+ `YOU` rules. For each requested move, compute the push chain in a stable134+ order. A blocked chain fails atomically; a legal chain moves as one action.135+4. **Apply movement and pushes.** Move entities from back to front. A push136+ cannot pull an entity unless `PULL` independently creates that behavior.137+ Resolve simultaneous controlled entities with a documented ordering key138+ (for example entity ID), then expose collision groups to mods.139+5. **Re-scan rules if relevant state changed.** If any text moved, was created,140+ destroyed, transformed, or stacked, parse the board again. The reference141+ implementation tracks whether words changed and only rewrites rules when142+ needed ([Game Developer interview](https://www.gamedeveloper.com/design/designing-i-baba-is-you-i-s-delightfully-innovative-rule-writing-system), lines 46–52).143+6. **Compile semantic rules.** Validate syntax, expand `AND` / `ALL`, apply144+ negation and disablement, and replace the active rule table atomically.145+ Contradictions must be deterministic: a negative rule such as `BABA IS NOT146+ YOU` suppresses the positive `BABA IS YOU` rule, as in the reference game.147+7. **Resolve interactions.** Run paired effects (`OPEN`/`SHUT`, `SINK`,148+ `DEFEAT`, `MELT`) using a fixed priority list. Recommended initial order:149+ structural destruction and transformations, then defeat, then win. A mod150+ can register a priority but cannot create a cycle.151+8. **Run autonomous behavior.** Apply `MOVE`, `SHIFT`, and similar behaviors as152+ a new deterministic substep, then re-run rule and interaction phases if153+ they changed text or occupancy. Cap cascading substeps and report a cycle.154+9. **Evaluate goals.** Evaluate `WIN` and mod goals against the settled state.155+ If both win and defeat occur in a turn, use the explicit goal policy (the156+ recommended default is defeat before win unless the level opts into157+ “reaching win ends immediately”).158+10. **Commit presentation.** Emit a replay event list, sound/effect cues, and159+ text highlighting. Rendering and particles must not mutate simulation160+ state.161+162+This pipeline is an engine recommendation inferred from the source's163+multi-pass rule detection and from Sokoban's need to reason about pushes as164+irreversible state changes. It is not a claim that the commercial games use165+this exact sequence.166+167+## Puzzle pedagogy168+169+Use a vocabulary curriculum, not a feature dump. Teach one new noun or170+property in a low-pressure board; immediately give a second level where the171+same word combines with an older word; then make the player manipulate the172+word tile itself. Keep the number of initially active rules low. Teikari says173+levels were cut when the intended interaction could be bypassed, required too174+many supporting rules, or became overwhelming with many active rules175+([Game Developer interview](https://www.gamedeveloper.com/design/designing-i-baba-is-you-i-s-delightfully-innovative-rule-writing-system), lines 59–64).176+177+Preserve a visible escape route from difficulty spikes. Teikari grouped areas178+by introduced words and used “Extra” markers to signal unusually difficult179+levels, while acknowledging that sequential numbering worked against returning180+later ([same interview](https://www.gamedeveloper.com/design/designing-i-baba-is-you-i-s-delightfully-innovative-rule-writing-system), lines 82–87).181+For this engine, a mod should be able to mark levels as `required`, `optional`,182+or `challenge`, and the campaign should unlock around a hard puzzle.183+184+Sokoban pedagogy depends on the player learning which pushes are unsafe. A185+crate in a non-goal corner is a simple deadlock; more complex deadlocks arise186+from wall corridors, frozen crate groups, and goal ordering. Deadlock research187+exists because these states make Sokoban difficult even for non-optimal solving188+([Cazenave, “Towards deadlock free Sokoban”](https://www.lamsade.dauphine.fr/~cazenave/papers/sokoban.pdf)).189+Make deadlocks legible through undo, restart, and optional post-failure hints;190+do not silently auto-solve or remove every consequence.191+192+For a design tool, validate levels with at least: reachability of controlled193+entities, a goal witness or solver result, detection of static dead squares,194+and a report of active rules at level start. Unique-solution or minimum-push195+claims are optional metadata, not a requirement for a fun level.196+197+## CommonJS mod boundary198+199+Mods should export data and pure hooks through a narrow CommonJS contract:200+201+```js202+module.exports = {203+ id: 'garden-01',204+ vocabulary: { nouns: [], verbs: [], properties: [] },205+ levels: [{ id: 'intro', width: 9, height: 7, cells: [] }],206+ systems: {207+ onTurnStart(ctx) {},208+ onCollision(ctx) {},209+ onGoalCheck(ctx) { return false }210+ }211+}212+```213+214+The host owns parsing, snapshots, input, rendering, replay, and persistence.215+Mods may register words, level data, serializers, pure predicates, and named216+effect handlers. They should not access DOM nodes, mutate the active rule table217+in place, replace the scheduler, use wall-clock time, or depend on object218+iteration order. The host passes a capability-scoped context with read-only219+queries and queued commands (`spawn`, `destroy`, `setDirection`, `emitEffect`).220+221+This boundary is a recommendation for deterministic, shareable content. It is222+also a practical security boundary: CommonJS is code, so untrusted mods need a223+worker or restricted loader with explicit resource and API limits.224+225+## Explicit non-goals and open decisions226+227+The first engine should not promise full commercial Baba compatibility, natural228+language parsing, diagonal movement, continuous time, physics simulation,229+network multiplayer, arbitrary UI-as-level semantics, or unrestricted code230+execution in mods. Those features multiply ambiguity before the basic turn231+contract is proven.232+233+Open decisions to settle with executable examples: whether entities can occupy234+multiple layers in one cell; whether `YOU` entities move simultaneously or in235+ID order; whether win precedes defeat; whether a failed push still consumes a236+turn; how `ALL`, `EMPTY`, and `TEXT` select targets; whether rule scan uses237+nearest valid sentence or all overlapping valid sentences; and whether effects238+are allowed to trigger recursive rule scans. Each decision should become a239+small fixture level and a replay test before the mod API is frozen.240+241+The GDC talk explicitly cautions that a perfectly robust parser would require242+removing some desirable complexity; Teikari kept unstable but fitting elements243+and limited player access to the worst cases, while treating `IF` as not worth244+the implementation pain at that stage ([GDC talk PDF](https://media.gdcvault.com/gdc2020/presentations/Reading%20the%20rules_Teikari_Arvi.pdf), pp. 19–21).245+That is a useful product constraint: keep the grammar deliberately small and246+make quirky extensions opt-in and testable.247+@@ -0,0 +1,81 @@
1+## Context2+3+This change establishes the first playable browser foundation in an otherwise small Vite project. The existing MVP direction is a deterministic JavaScript engine (`src/engine.js`), an emoji and text grid, built-in levels, and local CommonJS modules. The supplied design backbone calls for words as physical entities, straight horizontal or vertical rule scans, atomic pushes, derived properties, complete undo snapshots, and a narrow mod boundary. The implementation must remain small enough to validate through fixtures before adding the broader Baba Is You vocabulary.4+5+## Goals / Non-Goals6+7+**Goals:**8+9+- Define a stable state model and turn pipeline for stacked entities and movable words.10+- Implement the six initial properties: `YOU`, `PUSH`, `STOP`, `WIN`, `SINK`, and `DEFEAT`.11+- Support `IS`, `AND`, noun-to-noun transformation, push chains, rule re-scan, undo, and reset.12+- Ship three built-in MIAU teaching puzzles with browser keyboard and touch controls.13+- Load validated local CommonJS manifests for nouns, emoji, and levels.14+- Keep rendering, Pretext effects, and feedback downstream of simulation state.15+16+**Non-Goals:**17+18+- Full commercial Baba Is You compatibility, natural-language parsing, `NOT`, `HAS`, `PULL`, conditionals, autonomous movement, or recursive rule effects.19+- Diagonal movement, continuous physics, network play, persistence, or arbitrary UI-as-level semantics.20+- A secure sandbox for untrusted third-party JavaScript. Local mods are a trusted development/content boundary for this MVP.21+- Using text metrics or animation layout to determine grid coordinates.22+23+## Decisions24+25+### 1. Keep simulation state separate from rendering26+27+The engine owns immutable-by-convention state snapshots, entity identity, rule records, history, and effects. The UI subscribes to cloned state and event data. Renderers cannot mutate simulation objects. This keeps replay, undo, and deterministic fixtures possible. A DOM or canvas scene graph was considered, but it would couple layout and collision state too early.28+29+### 2. Use a compact data model with stacked entities30+31+Levels contain `width`, `height`, metadata, and an `objects` array. Each object has an id, coordinate, and either `kind: "word", text` or `kind: "object", noun`. Occupancy is derived by coordinate, so words and objects can share cells. Words are `PUSH` by default and are included in normal push-chain resolution.32+33+### 3. Parse only straight `NOUN IS VALUE` lines with `AND`34+35+Rule scanning examines left-to-right and top-to-bottom cardinal lines. `AND` expands adjacent nouns or values into multiple rule records. Values are either one of the six properties or a noun. Malformed lines are ignored. The active rule table is replaced atomically after word movement and after noun transformation. A map keyed by subject/value pair removes duplicate records while retaining deterministic discovery order.36+37+### 4. Resolve one accepted cardinal intent as one transaction38+39+The engine snapshots before movement, resolves controlled entities in a stable direction-aware order, recursively plans push chains, and commits only successful movement. It then re-scans rules, applies noun transformations, re-scans again, resolves sink/defeat/win contacts, and emits presentation events. A failed push is a no-op and does not consume a move. This order makes the consequences of editing a rule visible on the next settled state.40+41+### 5. Make undo a snapshot stack42+43+Successful moves push a deep clone of the complete pre-turn state. `undo` restores the last snapshot, including rules, effects, move count, and win state. Reset rebuilds the original state and clears history. The initial MVP can cap history at a fixed size, provided the cap is documented and deterministic.44+45+### 6. Keep the CommonJS manifest narrow46+47+The host loads `module.exports` and validates an object with a `manifest` containing id, name, and semantic version, plus `levels`, optional `vocabulary`, and optional `palette` records. The host owns parsing, snapshots, input, rendering, and persistence. The browser loader allows only the documented engine helper import and does not resolve URLs or packages. Since local CommonJS is trusted in this MVP, isolation means registration and error containment rather than a security sandbox; a worker or restricted loader is a later extension.48+49+### 7. Treat Pretext as UI text decoration50+51+Pretext can animate variable-length hints, active-rule labels, and feedback. Grid cells use fixed integer coordinates and CSS or canvas cell dimensions. This avoids letting proportional emoji widths or changing text effects alter collisions.52+53+### 8. Test behavior through engine fixtures and browser smoke checks54+55+Small level fixtures cover parser expansion, push success/failure, transformations, each contact effect, rule edits, undo, reset, mod validation, and win progression. Browser checks cover loading built-ins, keyboard/touch intent routing, rule display, and readable fallback rendering. These tests verify contracts rather than implementation details.56+57+## Risks / Trade-offs58+59+- [Overlapping words create ambiguous sentences] → Scan only cardinal straight lines, require explicit `IS`, and deduplicate exact rule records; add fixtures for shared cells.60+- [Multiple YOU entities can produce order-dependent pushes] → Sort by direction projection and stable id, document the ordering, and test multi-entity moves.61+- [Contact effects can conflict] → Use a fixed MVP order and explicit win/defeat behavior; postpone extensible priorities until a concrete level requires them.62+- [Trusted CommonJS can execute arbitrary browser code] → Keep the loader local and opt-in, validate manifests, isolate module errors, and document that untrusted mods are unsupported.63+- [Emoji widths and animation can harm readability] → Use fixed cells, text fallbacks, accessible labels, and reduced-motion-safe static feedback.64+- [A tiny vocabulary may constrain level design] → Preserve the manifest vocabulary extension point and add capabilities only with new fixtures and OpenSpec changes.65+66+## Migration Plan67+68+1. Preserve the current engine API while adding fixtures around its state and turn behavior.69+2. Keep the three built-in MIAU levels and the browser shell consuming `getState`, `step`, `undo`, and `reset`.70+3. Keep the local CommonJS loader behind an explicit file selection path; a loader failure leaves built-ins available.71+4. Add the emoji/text renderer and active-rule panel, then run build, engine tests, and browser smoke checks.72+5. If the rule grammar or mod contract changes, update the relevant delta spec before changing implementation.73+74+Rollback is deleting or disabling the new app shell and mod registration path while retaining the engine fixtures; no external data migration is required.75+76+## Open Questions77+78+- Should failed movement remain a no-op forever, or become a counted wait in a later ruleset?79+- What exact presentation should represent several stacked entities in one fixed cell?80+- Should a `SINK` contact always remove the sink entity itself, or can a future level opt into selective consumption?81+- When a turn creates both `WIN` and `DEFEAT`, should the level-specific policy be exposed before adding more effects?@@ -0,0 +1,29 @@
1+## Why2+3+We need a playable foundation for a browser puzzle game where moving word tiles rewrites the rules of a Sokoban grid. A shared vocabulary and explicit turn order will keep puzzles, mods, and the interface consistent as the game grows.4+5+## What Changes6+7+- Add a deterministic grid engine with push chains, overlapping objects, active sentence detection, object properties, and undo.8+- Establish a deliberately small first vocabulary: nouns, `IS`, `AND`, `YOU`, `PUSH`, `STOP`, `WIN`, `SINK`, and `DEFEAT`, plus noun-to-noun transformation.9+- Add a small sequence of playable teaching levels and browser controls.10+- Render the grid with emoji objects and animated word tiles, with active rules visible beside the board.11+- Load local CommonJS mods that define new nouns, emoji, and levels through a validated manifest.12+- Document the vocabulary, turn pipeline, and extension boundaries for future releases.13+14+## Capabilities15+16+### New Capabilities17+18+- `rule-engine`: Parsing movable words and resolving deterministic turns, properties, collisions, transformations, and undo.19+- `playable-puzzles`: Built-in teaching levels, progression, reset, and keyboard or touch input.20+- `commonjs-mods`: Loading and validating local CommonJS level and palette modules.21+- `game-presentation`: Emoji grid rendering, active rule display, feedback, and readable layout.22+23+### Modified Capabilities24+25+None. This is a new project.26+27+## Impact28+29+Adds the browser app, engine API, level and mod formats, tests, OpenSpec artifacts, and a dependency on Pretext for variable-length interface text. Uses a small selection of CC0 Kenney sounds from the supplied asset collection.@@ -0,0 +1,30 @@
1+## ADDED Requirements2+3+### Requirement: The app SHALL load local CommonJS mods through a validated manifest4+The mod loader SHALL load local CommonJS source and read its `module.exports` object containing a required `manifest` (`id`, `name`, and semantic `version`), one or more `levels`, and optional `vocabulary` and `palette` records. The host SHALL validate the complete export before registering any content and SHALL keep built-in content available when a mod fails validation.5+6+#### Scenario: A valid mod registers a level7+- **WHEN** a local module exports a valid manifest, level definition, vocabulary, and palette8+- **THEN** the loader registers its level and uses its palette for noun presentation under that mod id9+10+#### Scenario: A malformed mod is rejected11+- **WHEN** a module has no id, duplicate identifiers, invalid coordinates, or unsupported vocabulary values12+- **THEN** the loader rejects it with a diagnostic and does not partially register its content13+14+### Requirement: Mods SHALL use the host engine contract15+Mods SHALL define vocabulary, palette, and level data through the exported object. Mods SHALL NOT directly mutate the active rule table, DOM, renderer scheduler, or persisted engine state; the host SHALL pass validated level data to the engine.16+17+#### Scenario: A mod adds a noun and emoji18+- **WHEN** a manifest declares noun `KEKE` and its emoji representation19+- **THEN** levels from that mod can place `KEKE` objects and the presentation uses the declared mapping20+21+#### Scenario: A mod cannot bypass the engine state contract22+- **WHEN** a mod supplies malformed level state or attempts to change state through data outside the documented manifest fields23+- **THEN** the host registers only validated manifest, vocabulary, palette, and level data and keeps engine state under host control24+25+### Requirement: Mod loading SHALL be deterministic for the local MVP26+The loader SHALL run local mods with the host's documented CommonJS compatibility layer, allow only the host's supported helper import, and avoid URL or package resolution. Module execution and validation errors SHALL be isolated to the affected mod and shown in diagnostics.27+28+#### Scenario: A mod error does not break built-in play29+- **WHEN** a local module throws while loading or requests an unsupported import30+- **THEN** the app reports the mod error and keeps built-in levels playable@@ -0,0 +1,37 @@
1+## ADDED Requirements2+3+### Requirement: The app SHALL render the simulation as a readable emoji grid4+The renderer SHALL display each grid cell at a stable coordinate with stacked entities in a consistent visual order. Object nouns SHALL use emoji mappings, word entities SHALL remain legible as text tiles, and the board SHALL expose enough contrast and spacing to distinguish adjacent cells and stacked words.5+6+#### Scenario: Stacked entities remain visible7+- **WHEN** multiple objects or words occupy one cell8+- **THEN** the renderer preserves their identity and indicates the stack without changing simulation occupancy9+10+#### Scenario: A modded noun has no emoji fallback11+- **WHEN** a noun has no declared emoji mapping12+- **THEN** the renderer uses a readable text fallback containing the noun instead of hiding the entity13+14+### Requirement: The app SHALL show active rules and turn feedback15+The presentation SHALL display the currently active rules beside or below the board and SHALL update them after each settled turn. It SHALL provide visible feedback for blocked movement, undo, reset, transformations, defeat, and victory without changing engine state.16+17+#### Scenario: Active rules update after a word push18+- **WHEN** a word tile is pushed into or out of a sentence19+- **THEN** the displayed rule list reflects the engine's new active rule table after the turn20+21+#### Scenario: Victory is readable22+- **WHEN** the engine enters the won state23+- **THEN** the app shows a victory message and a clear continue or reset action24+25+### Requirement: Text effects SHALL support variable-length labels without driving grid geometry26+The app MAY use Pretext or an equivalent text-effect layer for animated labels, rule emphasis, hints, and feedback. Text effects SHALL be laid out within the UI surface and SHALL not determine the integer coordinates or collision geometry of the simulation grid.27+28+#### Scenario: A long hint does not move cells29+- **WHEN** a level hint is longer than the available sidebar width30+- **THEN** the hint wraps or scrolls while every grid cell retains its original coordinate and size31+32+### Requirement: The presentation SHALL provide accessible control feedback33+The app SHALL expose text labels or accessible names for movement, undo, reset, and continue controls and SHALL communicate rule and level status in a readable text representation in addition to animation and emoji.34+35+#### Scenario: Controls are understandable without animation36+- **WHEN** reduced motion is enabled or animation is unavailable37+- **THEN** the board, active rules, current level, and control actions remain understandable from static text and emoji@@ -0,0 +1,34 @@
1+## ADDED Requirements2+3+### Requirement: The app SHALL provide three built-in MIAU teaching puzzles4+The app SHALL ship exactly three deterministic ordered built-in levels using `MIAU` as the initial controlled noun. The puzzles SHALL cover movement and pushing, `YOU`, `PUSH` and `STOP`, word manipulation, `WIN`, and `AND` subject expansion; each level SHALL include dimensions, entities, and title or hint metadata.5+6+#### Scenario: The first MIAU level is playable without a mod7+- **WHEN** the app is started with no mod selected8+- **THEN** it loads the first MIAU level and displays its board, word tiles, and current rules9+10+#### Scenario: Completing a teaching puzzle advances the campaign11+- **WHEN** the active level reaches its win state and the player chooses continue12+- **THEN** the app loads the next built-in level while preserving the campaign order13+14+### Requirement: The app SHALL expose reset, undo, and cardinal controls15+The app SHALL provide reset and undo actions and SHALL accept up, down, left, and right intents from keyboard input and touch controls. Controls SHALL call the same engine intent API and SHALL show the current move count and whether undo is available.16+17+#### Scenario: Keyboard and touch produce the same move18+- **WHEN** the player uses a keyboard arrow or the corresponding touch direction control19+- **THEN** the engine receives the same cardinal intent and the resulting state is identical20+21+#### Scenario: Reset is available after a deadlock22+- **WHEN** the player has made moves that cannot reach the goal23+- **THEN** reset restores the initial level and move count without reloading the page24+25+#### Scenario: Undo is disabled at the initial state26+- **WHEN** the current level has no successful moves27+- **THEN** the undo control is visibly unavailable and invoking it has no effect28+29+### Requirement: Level definitions SHALL be validated before play30+The app SHALL reject a built-in level whose dimensions, coordinates, entity ids, word text, or object nouns are invalid, and SHALL report the level id and validation problem in developer-visible diagnostics.31+32+#### Scenario: An out-of-bounds entity is rejected33+- **WHEN** a level definition places an entity outside its declared width or height34+- **THEN** the level does not start and validation reports the offending entity@@ -0,0 +1,76 @@
1+## ADDED Requirements2+3+### Requirement: The engine SHALL represent a deterministic stacked grid state4+The engine SHALL represent a level as a bounded rectangular grid containing uniquely identified object and word entities. Multiple entities, including words, SHALL be allowed in one cell, and a turn snapshot SHALL include positions, entity kinds, word text, active rules, move count, win state, and the complete history needed for undo.5+6+#### Scenario: Multiple words share a cell7+- **WHEN** two word entities occupy the same coordinate8+- **THEN** both remain addressable and rule scanning considers both word texts at that coordinate9+10+#### Scenario: Invalid movement is rejected11+- **WHEN** a caller requests a diagonal move, an out-of-bounds move, or a move after the level is won12+- **THEN** the engine leaves state and undo history unchanged13+14+### Requirement: The engine SHALL derive the MVP rule vocabulary from movable words15+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.16+17+#### Scenario: An AND sentence expands to multiple properties18+- **WHEN** the board contains `BABA IS YOU AND PUSH` in one straight line19+- **THEN** the active rule table contains `BABA IS YOU` and `BABA IS PUSH`20+21+#### Scenario: A moved word changes the active rules22+- **WHEN** a legal move changes the position of a word entity23+- **THEN** the engine replaces the active rule table with rules parsed from the new word positions before the next player intent24+25+#### Scenario: A malformed line is ignored26+- **WHEN** a word line lacks `IS` or has no noun and value on both sides27+- **THEN** the line produces no active rule and does not make the turn fail28+29+### Requirement: The engine SHALL resolve controlled movement and pushes atomically30+Entities whose noun has `YOU` SHALL receive the requested cardinal intent. A moving entity SHALL push a contiguous chain of `PUSH` entities when every destination is in bounds and free of `STOP` entities; a blocked chain SHALL not move any member. Word entities SHALL be pushable by default so that players can edit rules.31+32+#### Scenario: A legal push moves the complete chain33+- **WHEN** a `YOU` entity moves toward one or more adjacent `PUSH` entities with an empty in-bounds destination34+- **THEN** the chain moves one cell in the requested direction and the move count increases by one35+36+#### Scenario: STOP blocks a push37+- **WHEN** a requested movement would push an entity into a `STOP` entity or outside the grid38+- **THEN** no entity moves and the move count does not increase39+40+#### Scenario: Several YOU entities use stable ordering41+- **WHEN** more than one `YOU` entity receives the same intent42+- **THEN** the engine resolves them in a documented stable order and produces the same state for the same initial state and intent43+44+### Requirement: The engine SHALL apply transformations and contact effects deterministically45+After movement, the engine SHALL apply active noun-to-noun transformations, then resolve contact effects using the MVP properties. `SINK` SHALL remove all occupants of a contact cell, `DEFEAT` SHALL remove controlled entities sharing its cell, and `WIN` SHALL mark the level won when a controlled entity shares a cell with a winning entity. The engine SHALL expose the settled state only after these effects complete.46+47+#### Scenario: A noun transforms48+- **WHEN** the active rule `BABA IS KEKE` is present after a successful turn49+- **THEN** every object with noun `BABA` becomes noun `KEKE` before the next rule scan50+51+#### Scenario: Sink removes contact occupants52+- **WHEN** an entity with `SINK` shares a cell with another entity after movement53+- **THEN** every entity in that cell is removed before the turn is committed54+55+#### Scenario: Defeat removes YOU56+- **WHEN** a `YOU` entity shares a cell with an entity having `DEFEAT`57+- **THEN** the controlled entity is removed and the level is not marked won by that contact58+59+#### Scenario: Win marks the level complete60+- **WHEN** a `YOU` entity shares a cell with an entity having `WIN`61+- **THEN** the engine marks the level won and rejects later movement until reset or progression62+63+### Requirement: The engine SHALL support complete turn undo and reset64+The engine SHALL save the complete pre-turn state before each successful movement and SHALL restore it with `undo`. `reset` SHALL restore the original level, clear history, clear the win state, and rebuild rules and derived effects.65+66+#### Scenario: Undo restores a rule edit67+- **WHEN** a successful push moves a word and the caller invokes `undo`68+- **THEN** the word positions, active rules, objects, move count, and win state match the state before that push69+70+#### Scenario: Undo with no history is harmless71+- **WHEN** the caller invokes `undo` before any successful move72+- **THEN** the engine returns a false or equivalent no-op result and leaves the state unchanged73+74+#### Scenario: Reset returns to the level start75+- **WHEN** the caller invokes `reset` after any sequence of moves and effects76+- **THEN** the initial entities and rules are restored, move count is zero, win is false, and undo history is empty@@ -0,0 +1,40 @@
1+## 1. Engine contract and fixtures2+3+- [ ] 1.1 Define the level, entity, rule, snapshot, and settled turn event types used by the engine and tests.4+- [ ] 1.2 Add fixtures for straight-line `IS` parsing, `AND` expansion, malformed lines, duplicate words, and shared cells.5+- [ ] 1.3 Add fixtures for the six properties and noun-to-noun transformation, including re-scan after a word move.6+7+## 2. Deterministic turn resolution8+9+- [ ] 2.1 Implement cardinal `YOU` intent handling with stable ordering for multiple controlled entities.10+- [ ] 2.2 Implement atomic push-chain planning, default pushability for word entities, bounds checks, and `STOP` blocking.11+- [ ] 2.3 Implement post-move transformation and deterministic `SINK`, `DEFEAT`, and `WIN` contact effects.12+- [ ] 2.4 Implement complete snapshot undo, reset, move counts, win lockout, and no-op behavior for invalid or blocked intents.13+- [ ] 2.5 Verify engine fixtures cover every requirement scenario and run the engine test command.14+15+## 3. Three built-in levels and input16+17+- [ ] 3.1 Define and validate the three ordered MIAU teaching puzzles covering movement, pushing, rule editing, `STOP`, `WIN`, and `AND` subject expansion.18+- [ ] 3.2 Add the app shell and level selection state for the three built-in levels.19+- [ ] 3.3 Route keyboard arrows, touch direction controls, undo, reset, and continue through the common engine API.20+- [ ] 3.4 Display move count, undo availability, level title/hint, victory, defeat, and blocked-move feedback.21+22+## 4. CommonJS mod boundary23+24+- [ ] 4.1 Define the local CommonJS export shape for `manifest`, `levels`, `vocabulary`, and `palette`.25+- [ ] 4.2 Implement manifest validation with duplicate, coordinate, vocabulary, and level diagnostics.26+- [ ] 4.3 Register valid mod content atomically and isolate loading or import failures without removing built-in content.27+- [ ] 4.4 Add fixtures for a valid noun/emoji/level mod and rejected or throwing modules.28+29+## 5. Emoji and text presentation30+31+- [ ] 5.1 Implement fixed-coordinate grid rendering with stable stack order and noun text fallback.32+- [ ] 5.2 Render word tiles and the active rule table from settled engine state.33+- [ ] 5.3 Add Pretext-backed or equivalent effects for hints, rule emphasis, transformations, and turn feedback without coupling to grid geometry.34+- [ ] 5.4 Add accessible labels, readable text status, and reduced-motion-safe presentation for all controls and outcomes.35+36+## 6. Integration verification37+38+- [ ] 6.1 Run the full test suite and production build after wiring the browser shell.39+- [ ] 6.2 Run browser smoke checks for built-in start, keyboard/touch movement, word push/rule update, undo/reset, win progression, and mod fallback.40+- [ ] 6.3 Update implementation notes or the relevant OpenSpec artifacts for any behavior discovered during verification.@@ -0,0 +1,23 @@
1+schema: spec-driven2+3+context: |4+ Project: Miau Is True, a browser grid puzzle engine with physical word rules and Sokoban movement.5+ Stack: JavaScript ES modules, Vite, Canvas rendering, Node's built-in test runner, Pretext for variable-length UI text.6+ Built-in vocabulary for the first release: nouns, IS, AND, YOU, PUSH, STOP, WIN, SINK, DEFEAT, and noun transformation.7+ Mods are local CommonJS modules with validated data manifests. The engine owns deterministic state transitions.8+ Design rationale and vocabulary inventory live in docs/design-backbone.md.9+10+rules:11+ specs:12+ - Include a concrete scenario for each behavior with observable before and after state.13+ - Keep future vocabulary distinct from requirements of the first release.14+ tasks:15+ - Include verification of browser controls, rule changes, mod loading, and undo.16+17+operations:18+ apply:19+ guidance:20+ - Mark tasks complete only after implementation and relevant verification.21+ archive:22+ guidance:23+ - Summarize which requirements became the live specs and any deliberately deferred features.@@ -0,0 +1,9 @@
1+Original prompt: I want to create a web app game engine that supports 'baba is you' dynamic rules and sokoban style with mods defined as commonjs modules. /Users/dami/game-dev-asset-packs has assets to use. I think we would stylize using emoji and text effects. Pretext might be useful to have text effects on the emoji, understand placement, etc to drive the grid well.2+3+2026-09-23: Empty workspace. Building a browser game with a separate rule engine, emoji canvas renderer, and local CommonJS mod loader. Pretext will lay out variable-length UI copy; fixed grid cells remain independent of text metrics. Selected Kenney UI sound effects from the user's asset collection.4+5+2026-09-23: Research inventory added at docs/design-backbone.md, drawing from creator interviews, GDC material, and Sokoban design literature. OpenSpec initialized for Codex; active change `build-dynamic-rule-engine` has proposal, four capability specs, design, and tasks. Git initialized on main with focused commits requested by the user.6+7+2026-09-23: Engine, three teaching levels, CommonJS loader, UI, and audio assets implemented in parallel. `npm test` and `npm run build` pass at this point. First Playwright canvas screenshot exposed a missing MIAU emoji mapping and interface gaps; fixes are in progress.8+9+TODO: Re-run browser checks after UI and level updates; verify mod import and win progression; reconcile OpenSpec task checklist with shipped behavior; archive the change after verification.