Files
TheLastGarden/content/dialogue/season1/compost-acknowledgements.ink
T
josh 572c86192f feat(02-03): journal + reveal modal + harvest pointer wiring
Task 2 of Plan 02-03: ship the Memory Journal UI surfaces (D-23/D-24/D-25)
and wire harvest + compost pointer events through the Garden scene to the
sim → store → React reveal flow.

src/ui/journal/ (new module):
- Journal.tsx — full-screen modal (D-24); fragments grouped by Season;
  DOM-rendered text with userSelect: text per MEMR-05; reads
  harvestedFragmentIds from the store; resolves ids against the eager
  `fragments` corpus (defensive — unresolvable ids skip silently).
- FragmentRevealModal.tsx — D-25 active-play reveal modal; backdrop click
  + inner Close button dismiss; event.stopPropagation on the article
  body so clicking inside the text doesn't dismiss; defensive silent
  dismiss on unresolvable id.
- journal-icon.tsx — D-23 + D-29 corner affordance; gated by
  selectJournalRevealed (`harvestedFragmentIds.length > 0`); local open
  state (no store pollution); 'j' hotkey deferred to Plan 02-05.
- index.ts — barrel.
- 16 new Vitest cases across 3 test files (Journal: 7 / FragmentRevealModal:
  6 / journal-icon: 3); all green.

src/App.tsx — mount FragmentRevealModal + JournalIcon as DOM siblings of
PhaserGame.

src/ui/index.ts — re-export ./journal.

src/game/scenes/Garden.ts — harvest/compost pointer flow:
- create() builds a SimContext from the eager `fragments` corpus filtered
  to Season 1; passed to every simulateOneTick call (Phase 4+ should swap
  to await loadSeasonFragments(currentSeason) when Season transitions land).
- handleTilePointerDown branches on tile state: empty → seed picker
  event; ready plant → enqueue 'harvest' command; immature plant → enqueue
  'compost' command (TODO Plan 02-04: render the Ink-authored compost
  acknowledgement beat from compost-acknowledgements.ink).
- update() detects newly-appended harvestedFragmentIds and sets
  fragmentRevealId so the reveal modal pops with the new fragment text.
- BLOCKER 3 invariant preserved — sim writes tickCount, never lastTickAt.

content/dialogue/season1/compost-acknowledgements.ink — authored content
for the GARD-04 + D-07 compost beat. 6 short lines in the gardener-keeper
voice (NOT Lura — she's the warmth anchor; the garden's voice is the
contrast). Plan 02-04 wires the inkjs runtime; Plan 02-03 ships the
content so the writer can iterate independently.

214/214 tests green (was 163; +51 new this plan); npm run lint exits 0;
npm run ci exits 0; npm run build exits 0 with the expected
INEFFECTIVE_DYNAMIC_IMPORT warnings (eager `fragments` export still
imports the Season-1 yaml/md statically alongside the lazy
loadSeasonFragments path — documented in 02-02-SUMMARY.md).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 10:05:45 -04:00

44 lines
1.7 KiB
Plaintext

// content/dialogue/season1/compost-acknowledgements.ink
//
// Plan 02-03 ships the AUTHORED CONTENT for the compost tonal beat
// (CONTEXT D-07 + GARD-04). Plan 02-04 owns the Ink runtime — this file
// is loaded by the Ink runtime (inkjs) at that point and one of these
// short lines is dripped into the dialogue overlay each time the player
// composts an immature plant.
//
// In Plan 02-03 the React surface (Garden.ts handleTilePointerDown's
// compost branch) does NOT yet render these lines — there's a TODO
// comment at the call site marking the Plan 02-04 wiring point. The
// content lives here so the writer can iterate on voice without waiting
// for the runtime to land.
//
// Tone (CLAUDE.md): warm, specific, intermittent, sometimes funny,
// sometimes devastating. The gardener-keeper voice. NOT Lura. The garden
// is acknowledging the player's choice to let go — never sentimental,
// never reassuring, never "it's okay." Just the small fact of the choice,
// honored.
//
// Phase 2 ships ~6 short lines so the player rarely hears the same line
// twice in a single session. Plan 02-04 will randomize selection (via
// the same mulberry32 pattern as the fragment selector, or a simple
// weighted pick — implementer's choice).
=== compost_beats ===
* The earth takes it back without comment.
->DONE
* Some things are tended into being. Others are tended into not being. Both count.
->DONE
* The space the plant occupied is now space. That is a kind of progress.
->DONE
* It returns to the soil it came from. Not poetry — just composting. Mostly.
->DONE
* The garden is bigger by one empty tile.
->DONE
* You changed your mind. The garden has nothing to say about it.
->DONE