docs(02-04): complete lura-gate-beats plan

- 02-04-lura-gate-beats-SUMMARY.md created. Documents:
  - 3 Lura Ink beats authored in bible voice (warmth anchor, contrast not co-griever)
  - Build-time inklecate compile pipeline with bundled binary (BLOCKER 4 mitigated)
  - RESEARCH Assumption A6 verified first-try on Windows
  - 47 new Vitest cases (264/264 total green); npm run ci exits 0
  - sim/narrative gating pure-state; STRY-10 mechanically defended
  - sim/* contains zero inkjs imports; ESLint sim-purity rule still green
  - 4 lazy code-split chunks emitted for compiled Ink JSON
  - Compost-toast UI deferred to Plan 02-05 (folded into persistence-toast surface)
  - 5 auto-fix deviations documented (Rule 1 + Rule 3); 2 tightenings; 0 architectural changes
- STATE.md updated: progress 18% → 19%; Phase 2 plans 3/5 → 4/5; 217 → 264 tests;
  per-phase metrics updated (Phase 2 4/5 plans, ~66min, ~16min/plan).
- ROADMAP.md: Plan 02-04 marked complete with duration; progress table updated.
- REQUIREMENTS.md: STRY-01 / STRY-06 / STRY-07 / STRY-10 marked complete with
  full traceability annotations.

Plan 02-05 (offline catchup + letter + Settings + Playwright e2e) is the only
remaining Phase-2 work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-09 10:41:24 -04:00
parent 661f990e9a
commit de3f55b1c4
4 changed files with 395 additions and 25 deletions
+22 -15
View File
@@ -3,15 +3,15 @@ gsd_state_version: 1.0
milestone: v1.0
milestone_name: milestone
status: in_progress
stopped_at: "Phase 2 Wave 1 (Plan 02-03 harvest-journal-fragments) complete. 3 atomic commits: f192e82 (Season-1 fragments + sim/memory selector + harvest/compost commands), 572c861 (journal + reveal modal + harvest pointer wiring), 39bfcd2 (PIPE-02 structural verifier scripts/check-bundle-split.mjs). 217/217 tests green (was 163; +54 new); npm run ci exits 0 with check:bundle-split integrated. GARD-03 / GARD-04 / MEMR-01..06 / PIPE-02 requirements landed end-to-end. The full Season-1 active-play loop is operational: plant → grow → harvest (deterministic mulberry32-seeded fragment selection, gated by Season + tonal register, no-dup, sentinel fallback for Pitfall 8) → reveal modal (D-25, MEMR-05 selectable DOM) → close → journal icon appears (D-23 first-harvest gate) → opens full-screen Memory Journal grouped by Season (D-24). 17 Season-1 fragments authored in bible voice. Plant-type unlocks: rosemary @ 0 / yarrow @ 3 / winter-rose @ 6 (Pitfall 10 boundary-tested). compost-acknowledgements.ink content shipped ahead of Plan 02-04's Ink runtime. Wave 2 (02-04 lura-gate-beats + 02-05 letter-settings-e2e) is the only remaining Phase-2 work. Next: /gsd-execute-phase 2 to continue with Plan 02-04."
last_updated: "2026-05-09T14:08:00.000Z"
stopped_at: "Phase 2 Wave 2 first plan (Plan 02-04 lura-gate-beats) executed in sequential mode. 3 atomic commits: c90f8f1 (ink compilation pipeline + 4 authored Season-1 .ink files + runtime loader), 7b79d11 (sim/narrative — Lura beat gating 1/4/8 harvest, STRY-10), 661f990 (Lura dialogue overlay + Ink runtime + gate visual + Garden scene wiring). 264/264 tests green (was 217; +47 new); npm run ci exits 0 end-to-end with compile:ink integrated into the chain BEFORE test. STRY-01 / STRY-06 / STRY-07 / STRY-10 requirements satisfied. Lura goes on the record as the warmth anchor — 3 authored Ink beats (lura-arrival/mid/farewell) gated at 1st/4th/8th harvest counts (D-14); STRY-10 mechanically defended by FakeClock-24h-no-harvest test. RESEARCH Assumption A6 verified first-try on Windows via the bundled inklecate binary at node_modules/inklecate/bin/. Vite emits 4 lazy code-split chunks for compiled Ink JSON. Sim purity firewall holds: src/sim/narrative/ contains zero inkjs imports. Compost-toast UI deferred to Plan 02-05's persistence-toast surface (compost-acknowledgements.ink rewritten in VAR-driven branch shape, ready for the runtime). Wave 2 final plan (02-05 letter-settings-e2e) is the only remaining Phase-2 work. Next: /gsd-execute-phase 2 to continue with Plan 02-05."
last_updated: "2026-05-09T14:32:00.000Z"
last_activity: 2026-05-09
progress:
total_phases: 8
completed_phases: 1
total_plans: 8
completed_plans: 10
percent: 18
completed_plans: 11
percent: 19
---
# Project State
@@ -21,16 +21,16 @@ progress:
See: .planning/PROJECT.md (updated 2026-05-08)
**Core value:** Every idle mechanic must function as a metaphor that the player absorbs without being told. When economy and meaning conflict, meaning wins.
**Current focus:** Phase 02 — Season 1 Vertical Slice (Soil) — Wave 0 done; Wave 1 done (02-02 + 02-03); Wave 2 (02-04 + 02-05) is the only remaining Phase-2 work
**Current focus:** Phase 02 — Season 1 Vertical Slice (Soil) — Wave 0 done; Wave 1 done (02-02 + 02-03); Wave 2 first plan (02-04) DONE; 02-05 is the only remaining Phase-2 work
## Current Position
Phase: 02 (season-1-vertical-slice-soil) — 3/5 plans complete (Wave 0 + both Wave 1 plans)
Plans: 5 of 5 created (3 waves); Wave 0 (02-01) DONE; Wave 1 (02-02 + 02-03) DONE; Wave 2 (02-04 + 02-05) queued
Status: Plan 02-03 harvest-journal-fragments executed in sequential mode — 3 atomic commits, 54 new tests (217/217 total green), npm run ci exits 0 with check:bundle-split integrated. GARD-03 / GARD-04 / MEMR-01..06 / PIPE-02 satisfied end-to-end. Full Season-1 active-play loop operational: plant → grow → harvest (deterministic, gated, no-dup) → reveal modal → journal. 17 Season-1 fragments authored. Pitfall 8 (sentinel fallback) + Pitfall 10 (post-commit unlock thresholds) both mitigated.
Last activity: 2026-05-09 -- Plan 02-03 execute complete
Phase: 02 (season-1-vertical-slice-soil) — 4/5 plans complete (Wave 0 + Wave 1 + first Wave 2 plan)
Plans: 5 of 5 created (3 waves); Wave 0 (02-01) DONE; Wave 1 (02-02 + 02-03) DONE; Wave 2 first plan (02-04 lura-gate-beats) DONE; Wave 2 final plan (02-05 letter-settings-e2e) queued
Status: Plan 02-04 lura-gate-beats executed in sequential mode — 3 atomic commits, 47 new tests (264/264 total green), npm run ci exits 0 with compile:ink integrated into the chain BEFORE test. STRY-01 / STRY-06 / STRY-07 (vacuous) / STRY-10 satisfied end-to-end. Lura's 3 Season-1 beats authored in voice + ship via the inklecate compile pipeline + inkjs runtime; gate visual indicator + DOM dialogue overlay both green. RESEARCH Assumption A6 verified first-try on Windows. Sim purity firewall holds: src/sim/narrative/ contains zero inkjs imports.
Last activity: 2026-05-09 -- Plan 02-04 execute complete
Progress: [██░░░░░░░░] 18%
Progress: [██░░░░░░░░] 19%
## Verification Results
@@ -70,12 +70,12 @@ Gates run: lint (exit 0), test (53/53 green, 12 files), validate:assets (2 asset
| Phase | Plans | Total | Avg/Plan |
|-------|-------|-------|----------|
| 1. Foundations & Doctrine | 7/7 (complete) | ~30 min | ~5 min |
| 2. Season 1 Vertical Slice (Soil) | 3/5 (Wave 0 + Wave 1 complete) | ~42 min | ~14 min |
| 2. Season 1 Vertical Slice (Soil) | 4/5 (Wave 0 + Wave 1 + first Wave 2 plan complete) | ~66 min | ~16 min |
**Recent Trend:**
- Last 5 plans: [01-06 doctrine-docs · 01-07 ci-workflow · 02-01 foundations · 02-02 begin-plant-grow · 02-03 harvest-journal-fragments — all green]
- Trend: → (02-03 was 12 min — sim/memory + journal UI tier without a new render layer; the architectural firewall edges 02-02 shipped carry over directly so 02-03 is "just" the second half of the active-play loop on top of established surfaces; +54 new tests for 217/217 total green)
- Last 5 plans: [01-07 ci-workflow · 02-01 foundations · 02-02 begin-plant-grow · 02-03 harvest-journal-fragments · 02-04 lura-gate-beats — all green]
- Trend: → (02-04 was 24 min — heaviest Phase-2 plan to date; first real player-narrative integration in the project covers a build pipeline + runtime + sim gate + UI overlay + canvas indicator + Garden scene wiring + 4 authored Ink files all in one plan; +47 new tests for 264/264 total green)
*Updated after each plan completion*
@@ -99,6 +99,13 @@ Recent decisions affecting current work:
- Plan 02-03 (Wave 1): Garden scene loads fragments via the EAGER `fragments` corpus filtered to Season 1, NOT via `await loadSeasonFragments(1)`. Trade-off: simpler synchronous create() vs. INEFFECTIVE_DYNAMIC_IMPORT warnings inherited from Plan 02-02. Lazy plumbing is structurally proven by `scripts/check-bundle-split.mjs`; Phase 4+ should swap to lazy when Season transitions land.
- Plan 02-03 (Wave 1): Compost beat content shipped in `content/dialogue/season1/compost-acknowledgements.ink` ahead of Plan 02-04's Ink runtime; Garden.ts compost branch carries a TODO at the wiring point. The split lets the writer iterate on voice independently of runtime work.
- Plan 02-03 (Wave 1): PIPE-02 verifier `scripts/check-bundle-split.mjs` is structured as Vitest-importable Node ESM (`runCheck()` exported, CLI gated by `import.meta.url`). Pattern reusable for Phase 4 Season-2 onboarding (extend known-content list) and Phase 8 visual-regression baselines (different filename heuristics, same export shape).
- Plan 02-04 (Wave 2): Direct binary invocation chosen over the inklecate npm wrapper API. The wrapper's executableHandler swallows non-zero exit codes silently, the stderr capture surface is undocumented. compile-ink.mjs uses `execFileSync(node_modules/inklecate/bin/inklecate{.exe})` directly so failure modes are loud (full stderr/stdout in the throw). The bundled binary IS stable; the wrapper isn't.
- Plan 02-04 (Wave 2): BLOCKER 4 mitigation — script uses `node_modules/inklecate/bin/inklecate{.exe}`, NOT the stale `inklecate-windows/`/`inklecate-mac/` per-platform-folder strings. The wrapper ships a single `bin/` directory with the .NET self-contained executable + DLLs. Verified via `ls node_modules/inklecate/bin/`. RESEARCH Assumption A6 verified first-try on Windows.
- Plan 02-04 (Wave 2): compileAllInk has a `wipe` toggle (default true for CLI; passed false from the test path) so compile-ink.test.mjs and src/content/ink-loader.test.ts don't race on the wipe step under Vitest's parallel test execution. CI's compile:ink-before-test ordering still guarantees a fully-populated directory.
- Plan 02-04 (Wave 2): compost-beat UI wiring deferred to Plan 02-05's persistence-toast surface (compost is a thinner toast variant separate from Lura's full-screen overlay; Plan 02-05 lands the toast UX alongside CORE-05's persistence-denied surface). Plan 02-04 ships the AUTHORED CONTENT (compost-acknowledgements.ink rewritten in VAR-driven branch shape) + the loadInkStory('compost-acknowledgements') path; only the toast component is missing.
- Plan 02-04 (Wave 2): STRY-07 satisfied vacuously for Phase 2 — zero .ink files contain Keeper-spoken lines. The gardener-keeper voice in compost beats acknowledges the player's actions but is never personified. Phase 7's binary choice surface (SEAS-09 / STRY-08) re-evaluates.
- Plan 02-04 (Wave 2): Cadence values: DEFAULT_DELAY_MS=1500, PER_CHAR_MS=20, MAX_DELAY_MS=4000. Calibrated against typical 80-char line (3.1s) feeling close to a thoughtful texted reply, vs short "Oh." (1.56s) feeling like a beat. Tunable in playtest by editing src/ui/dialogue/ink-runtime.ts; constants exported for the Phase 8 UX-05 reduced-motion hook.
- Plan 02-04 (Wave 2): Lura's `last_plant_type` derives from the most-recently-harvested fragment's tonal-register tag (warm → rosemary, contemplative → yarrow, heavy → winter-rose). The harvest pipeline doesn't currently store source plant type per harvest — Plan 02-05 may add that to offlineEvents. The tag-based proxy is sufficient for Phase 2's voice; Lura's branch on plant type is flavor, not a gate.
- Phases 4-7 deliver the remaining six Seasons in mechanic-introducing pairs (Season 2 alone with prestige, Seasons 3-4, Seasons 5-6, Season 7 alone) — at most one new mechanic per Season per the scope-defense doctrine.
- Plan 01-01: scaffolded by hand (the official `npm create @phaserjs/game@latest` is interactive-only — `--template react-ts --yes` flags are silently ignored as of create-game v1.3.2); plan's documented fallback path was used. Vite 8 + TS 6 referenced-projects tsconfig layout adopted; `build` runs `tsc -b && vite build` so strict-TS gates every build. ESLint 9 installed → Plan 02 must use **flat config** (`eslint.config.js`), not legacy `.eslintrc.*`.
- Plan 01-01: pre-installed `fake-indexeddb@^6` here so Plan 03 doesn't have to re-edit `package.json`. All Phase-1 dep versions match RESEARCH.md exactly within their `^` ranges.
@@ -129,5 +136,5 @@ Items acknowledged and carried forward:
## Session Continuity
Last session: 2026-05-09
Stopped at: Phase 2 Wave 1 second plan (Plan 02-03 harvest-journal-fragments) executed in sequential mode — 3 atomic commits (f192e82, 572c861, 39bfcd2), 54 new tests, 217/217 total green, npm run ci exits 0 (with check:bundle-split integrated). GARD-03/GARD-04/MEMR-01..06/PIPE-02 satisfied end-to-end. The full Season-1 active-play loop is operational on real authored content; sentinel fallback (Pitfall 8) and Pitfall 10 plant-unlock boundary both pinned by Vitest. SUMMARY at .planning/phases/02-season-1-vertical-slice-soil/02-03-harvest-journal-fragments-SUMMARY.md.
Next action: `/gsd-execute-phase 2` to continue with Plan 02-04 (Lura's Ink dialogue + gate beats — 1st/4th/8th harvest thresholds) on top of the harvest pipeline shipped in 02-03. Plan 02-04 will swap the compost-acknowledgements TODO at src/game/scenes/Garden.ts for the inkjs runtime path. Plan 02-05 (offline catchup + letter + Settings + Playwright e2e) is the final Phase-2 plan.
Stopped at: Phase 2 Wave 2 first plan (Plan 02-04 lura-gate-beats) executed in sequential mode — 3 atomic commits (c90f8f1, 7b79d11, 661f990), 47 new tests, 264/264 total green, npm run ci exits 0 (compile:ink integrated into the CI chain BEFORE test). STRY-01/STRY-06/STRY-07/STRY-10 satisfied end-to-end. Lura's 3 Season-1 beats authored in voice via the inklecate compile pipeline + inkjs runtime; gate visual indicator + DOM dialogue overlay both functional. RESEARCH Assumption A6 verified first-try on Windows via the bundled inklecate binary. Sim purity firewall holds: src/sim/narrative/ contains zero inkjs imports; ESLint sim-purity rule still green. Vite emits 4 lazy code-split chunks for compiled Ink JSON. SUMMARY at .planning/phases/02-season-1-vertical-slice-soil/02-04-lura-gate-beats-SUMMARY.md.
Next action: `/gsd-execute-phase 2` to continue with Plan 02-05 (offline catchup + letter + Settings + Playwright e2e — UX-02, UX-10, CORE-03, CORE-11, PIPE-07). Plan 02-05 will fold the compost-toast UI surface alongside the persistence-denied toast (compost-acknowledgements.ink runtime path is already wired; only the toast component is missing). Plan 02-05 is the final Phase-2 plan; completing it means Phase 2 is shippable as a free standalone Season-1 prologue.