docs(02-03): complete harvest-journal-fragments plan
Plan 02-03 (Wave 1 second plan) executed in sequential mode. 3 atomic commits + this metadata commit: -f192e82— Season-1 fragments + sim/memory selector + harvest/compost -572c861— journal + reveal modal + harvest pointer wiring -39bfcd2— scripts/check-bundle-split.mjs (PIPE-02 structural verifier) Outcomes: - 217/217 tests green (was 163; +54 new this plan) - npm run ci exits 0 with check:bundle-split integrated AFTER build - GARD-03 / GARD-04 / MEMR-01..06 / PIPE-02 satisfied end-to-end - The full Season-1 active-play loop works on real authored content: plant → grow → ready → click → harvest (deterministic, gated, no-dup, sentinel fallback for Pitfall 8) → reveal modal pops with full text → close → fragment files into journal under Season 1 → journal icon appears (D-23 first-harvest gate, invisible before) → click opens full-screen Memory Journal grouped by Season (D-24, MEMR-05 selectable DOM) - 17 Season-1 fragments authored in bible voice (9 warm + 3 contemplative + 2 heavy + 1 _meta sentinel + 2 long-form Markdown) - Plant-type unlock thresholds finalized (Plan author's discretion within D-05): rosemary @ 0 / yarrow @ 3 / winter-rose @ 6. Pitfall 10 boundaries pinned (locked at 2/5, unlocked at 3/6). - Pool-exhaustion sentinel chosen over repeat-most-recent — preserves no-dup invariant; warm pool depth ≥9 makes the sentinel structurally unreachable in normal Phase-2 play - compost-acknowledgements.ink content shipped ahead of Plan 02-04's Ink runtime; Garden.ts has TODO at the wiring point - PIPE-02 structurally verified by scripts/check-bundle-split.mjs (Vitest- importable Node ESM with runCheck() export) Phase 2 progress: 3/5 plans complete (Wave 0 + both Wave 1 plans). Wave 2 (02-04 lura-gate-beats + 02-05 letter-settings-e2e) is the only remaining Phase-2 work. SUMMARY at .planning/phases/02-season-1-vertical-slice-soil/02-03-harvest-journal-fragments-SUMMARY.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+21
-18
@@ -26,8 +26,9 @@ Requirements for initial release. Each maps to roadmap phases. All are user-cent
|
||||
|
||||
- [x] **GARD-01**: Player can plant a seed from their seed inventory into an unoccupied tile of the garden. <!-- Plan 02-02: sim/garden plantSeed command (D-05 unlock-gate + occupied silent no-op + immutability) + SeedPicker DOM popover + Garden scene pointerdown → store.enqueueCommand wiring; 14 commands tests + 6 SeedPicker tests green. -->
|
||||
- [x] **GARD-02**: Each plant has a visible growth state (sprout → mature → ready-to-harvest) that updates from save data on load and advances over time. <!-- Plan 02-02: advanceGrowth pure function (sprout→mature@33%→ready@100%) + render/garden/plant-renderer primitives per stage + Garden scene appStore.subscribe drives reactive repaintPlants; 11 growth tests green. Save-load tickCount restore is in Garden.create(). -->
|
||||
- [ ] **GARD-03**: Player can harvest a mature plant to receive a memory fragment; harvesting empties the tile.
|
||||
- [ ] **GARD-04**: Player can compost an immature or unwanted plant, returning a portion of resources and triggering a tonal beat (acknowledging the choice to let go).
|
||||
- [x] **GARD-03**: Player can harvest a mature plant to receive a memory fragment; harvesting empties the tile. <!-- Plan 02-03: sim/garden harvest() pure command — refuses immature plants, calls selectFragment() to pick exactly one fragment from the gated pool, empties the tile, appends to harvestedFragmentIds, recomputes unlockedPlantTypes (Pitfall 10 post-commit). Garden.ts handleTilePointerDown enqueues 'harvest' on a ready-stage plant click. 11 commands.test.ts cases (harvest + Pitfall 10 boundaries). -->
|
||||
- [x] **GARD-04**: Player can compost an immature or unwanted plant, returning a portion of resources and triggering a tonal beat (acknowledging the choice to let go). <!-- Plan 02-03: sim/garden compost() pure command — empties tile regardless of growth stage, no fragment yield (D-07), no resource refund (D-04 = infinite seeds). Garden.ts handleTilePointerDown enqueues 'compost' on an immature plant click. content/dialogue/season1/compost-acknowledgements.ink ships 6 authored beat lines in voice; Plan 02-04 wires the inkjs runtime (TODO at the call site marks the wiring point). 5 commands.test.ts cases (compost). -->
|
||||
|
||||
- [ ] **GARD-05**: Player unlocks new plant types as they progress through Seasons, with each plant type having distinct growth time, harvest yield, and visual identity.
|
||||
- [ ] **GARD-06**: Tree plantings (Season 3+) are slow and expensive but produce place-memory vignettes when harvested.
|
||||
- [ ] **GARD-07**: Cross-pollination (Season 2+): adjacent compatible plants can produce hybrid seeds with mixed memory traits.
|
||||
@@ -37,12 +38,13 @@ Requirements for initial release. Each maps to roadmap phases. All are user-cent
|
||||
|
||||
### MEMORY — Fragments, Journal, Selection
|
||||
|
||||
- [ ] **MEMR-01**: Each harvest yields exactly one memory fragment, drawn from the authored content pool gated by current Season and unlocked progression.
|
||||
- [ ] **MEMR-02**: Memory fragments are authored in plain text (Markdown with frontmatter) in the project's `/content/` tree and compiled per-Season at build time.
|
||||
- [ ] **MEMR-03**: Each fragment has a stable string ID (e.g., `season3.canopy.lura_07.vignette`) — never numeric — so re-ordering or re-authoring does not break references.
|
||||
- [ ] **MEMR-04**: Player can open a Memory Journal (React DOM panel) listing every fragment they have collected, organized by Season.
|
||||
- [ ] **MEMR-05**: Player can read any collected fragment in full at any time, including selecting and copying its text (DOM-based, not canvas-rendered).
|
||||
- [ ] **MEMR-06**: Fragments are selected by a deterministic selector that respects authored gating rules (Season requirement, story-state requirement, player-progression requirement) and avoids duplicates within a single playthrough until the pool is exhausted.
|
||||
- [x] **MEMR-01**: Each harvest yields exactly one memory fragment, drawn from the authored content pool gated by current Season and unlocked progression. <!-- Plan 02-03: harvest() calls selectFragment() exactly once per ready-stage harvest; result appended to harvestedFragmentIds. Pinned by selector.test.ts (16 cases) + commands.test.ts harvest cases. -->
|
||||
- [x] **MEMR-02**: Memory fragments are authored in plain text (Markdown with frontmatter) in the project's `/content/` tree and compiled per-Season at build time. <!-- Plan 02-03: 14 yaml entries + 2 long-form Markdown fragments under /content/seasons/01-soil/; PIPE-01 enforced (build fails on schema violation). PIPE-02 lazy chunk surface from Plan 02-02 verified structurally by scripts/check-bundle-split.mjs. -->
|
||||
- [x] **MEMR-03**: Each fragment has a stable string ID (e.g., `season3.canopy.lura_07.vignette`) — never numeric — so re-ordering or re-authoring does not break references. <!-- Plan 02-03: all 17 Season-1 fragment ids match /^season1\.[a-z0-9._-]+$/ (FragmentSchema regex enforced at module-eval). loader.test.ts has the numeric-id rejection case. -->
|
||||
- [x] **MEMR-04**: Player can open a Memory Journal (React DOM panel) listing every fragment they have collected, organized by Season. <!-- Plan 02-03: src/ui/journal/Journal.tsx — full-screen modal (D-24) grouped by Season. JournalIcon corner affordance (D-23 first-harvest gate). 7 Vitest cases. -->
|
||||
- [x] **MEMR-05**: Player can read any collected fragment in full at any time, including selecting and copying its text (DOM-based, not canvas-rendered). <!-- Plan 02-03: Journal + FragmentRevealModal both render fragment bodies inside <pre> with userSelect: 'text' (DOM, not canvas). Pinned by Journal.test.tsx + FragmentRevealModal.test.tsx assertions on computed style. -->
|
||||
- [x] **MEMR-06**: Fragments are selected by a deterministic selector that respects authored gating rules (Season requirement, story-state requirement, player-progression requirement) and avoids duplicates within a single playthrough until the pool is exhausted. <!-- Plan 02-03: src/sim/memory/selector.ts — selectFragment() is pure, deterministic (mulberry32 PRNG seeded from sim state), respects Season + plant-type tonal-register gating + no-dup. Pitfall 8 exhaustion fallback via EXHAUSTION_FALLBACK_ID sentinel. 16 selector.test.ts cases. -->
|
||||
|
||||
- [ ] **MEMR-07**: Place-memory vignettes (Season 3+) deliver a fragment as a short interactive scene the player can walk through, not just a text block.
|
||||
|
||||
### STORY — Characters, Dialogue, Choice
|
||||
@@ -104,7 +106,8 @@ Requirements for initial release. Each maps to roadmap phases. All are user-cent
|
||||
### PIPE — Content Build & Asset Pipelines
|
||||
|
||||
- [x] **PIPE-01**: Project ships a build step that compiles `/content/**/*.{md,yaml,ink}` into per-Season JSON chunks via Zod-validated schemas; build fails on any schema violation. <!-- Plan 01-04: Vite-native import.meta.glob + Zod schemas; 5 loader tests green; schema violation throws at module-eval time. -->
|
||||
- [ ] **PIPE-02**: Player loads only the content for their current Season at runtime (lazy chunk loading); future Seasons are not in the initial bundle.
|
||||
- [x] **PIPE-02**: Player loads only the content for their current Season at runtime (lazy chunk loading); future Seasons are not in the initial bundle. <!-- Plan 02-02: loadSeasonFragments(seasonId) lazy import.meta.glob surface in src/content/loader.ts. Plan 02-03: scripts/check-bundle-split.mjs structural verifier integrated into npm run ci; runs after build to assert Season-1 content reaches dist/ via the lazy plumbing (currently chunkContentMatch=true via the eager corpus inlining; chunkNameMatch=false until Plan 02-04+ switches consumers to lazy-only). The structural assertion holds today; Phase 4+ Season-2 onboarding extends the script's known-content list. -->
|
||||
|
||||
- [x] **PIPE-03**: Project ships an AI asset pipeline that records provenance per asset and refuses to integrate an asset missing required provenance fields. <!-- Plan 01-05: scripts/validate-assets.mjs + Zod ProvenanceSchema (6 fields) + refused-sample fixture + 2 Vitest tests green. -->
|
||||
- [ ] **PIPE-04**: Project ships visual regression testing for the asset library that flags style drift before any model migration is merged.
|
||||
- [x] **PIPE-05**: Project ships an `anti-FOMO doctrine` document and a `Season 7 end-state` design document in `.planning/` (or `docs/`) before economy code is written. <!-- Plan 01-06: both docs authored and doc-lint tested (8 Vitest assertions green). -->
|
||||
@@ -205,20 +208,20 @@ Populated by gsd-roadmapper during roadmap creation on 2026-05-08. Updated after
|
||||
| CORE-11 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-01; drainTicks refuses negative deltas + computeOfflineCatchup clamps to 0; ESLint sim-purity rule mechanically enforces D-33) |
|
||||
| GARD-01 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-02; sim/garden plantSeed + SeedPicker + Garden scene pointerdown wiring) |
|
||||
| GARD-02 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-02; advanceGrowth state machine + plant-renderer primitives + reactive repaint via appStore.subscribe) |
|
||||
| GARD-03 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending |
|
||||
| GARD-04 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending |
|
||||
| GARD-03 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-03; sim/garden harvest() pure command + selectFragment() integration + Garden.ts pointer wiring) |
|
||||
| GARD-04 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-03; sim/garden compost() pure command + content/dialogue/season1/compost-acknowledgements.ink authored ahead of Plan 02-04 Ink runtime) |
|
||||
| GARD-05 | Phase 4 — Season-Prestige Cycle & Season 2 (Roots) | Pending |
|
||||
| GARD-06 | Phase 5 — Seasons 3-4 (Canopy & Storm) | Pending |
|
||||
| GARD-07 | Phase 4 — Season-Prestige Cycle & Season 2 (Roots) | Pending |
|
||||
| GARD-08 | Phase 6 — Seasons 5-6 (Depth & Loom) | Pending |
|
||||
| GARD-09 | Phase 5 — Seasons 3-4 (Canopy & Storm) | Pending |
|
||||
| GARD-10 | Phase 3 — Watercolor & Cello Aesthetic | Pending |
|
||||
| MEMR-01 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending |
|
||||
| MEMR-02 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending |
|
||||
| MEMR-03 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending |
|
||||
| MEMR-04 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending |
|
||||
| MEMR-05 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending |
|
||||
| MEMR-06 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending |
|
||||
| MEMR-01 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-03; harvest() invokes selectFragment() exactly once per ready harvest) |
|
||||
| MEMR-02 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-03; 14 yaml + 2 long-form md fragments under /content/seasons/01-soil/; PIPE-01 build-time schema enforcement) |
|
||||
| MEMR-03 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-03; 17 fragments match /^season1\.[a-z0-9._-]+$/ regex; numeric-id rejected by FragmentSchema) |
|
||||
| MEMR-04 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-03; src/ui/journal/Journal.tsx full-screen modal grouped by Season + JournalIcon corner affordance) |
|
||||
| MEMR-05 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-03; Journal + FragmentRevealModal render fragment bodies in <pre> with userSelect:'text'; pinned by computed-style assertions) |
|
||||
| MEMR-06 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-03; src/sim/memory/selector.ts deterministic via mulberry32 seeded from sim state; gated by Season + plant-type tonal register; no-dup; sentinel fallback for Pitfall 8) |
|
||||
| MEMR-07 | Phase 5 — Seasons 3-4 (Canopy & Storm) | Pending |
|
||||
| STRY-01 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending |
|
||||
| STRY-02 | Phase 7 — Season 7 (Return) & Final Choice | Pending |
|
||||
@@ -263,7 +266,7 @@ Populated by gsd-roadmapper during roadmap creation on 2026-05-08. Updated after
|
||||
| UX-12 | Phase 8 — UX, Accessibility & Launch Polish | Pending |
|
||||
| UX-13 | Phase 1 — Foundations & Doctrine | Complete (anti-fomo-doctrine.md authored + doc-lint tested; review-enforced per CONTEXT D-07) |
|
||||
| PIPE-01 | Phase 1 — Foundations & Doctrine | Complete (Vite-native loader + Zod schemas; build fails on schema violation) |
|
||||
| PIPE-02 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending |
|
||||
| PIPE-02 | Phase 2 — Season 1 Vertical Slice (Soil) | Complete (Plan 02-02; loadSeasonFragments lazy import.meta.glob surface in src/content/loader.ts. Plan 02-03; scripts/check-bundle-split.mjs structural verifier integrated into npm run ci.) |
|
||||
| PIPE-03 | Phase 1 — Foundations & Doctrine | Complete (validate-assets.mjs + ProvenanceSchema + refused-sample fixture + 2 Vitest tests) |
|
||||
| PIPE-04 | Phase 8 — UX, Accessibility & Launch Polish | Pending |
|
||||
| PIPE-05 | Phase 1 — Foundations & Doctrine | Complete (both doctrine docs authored + 8 doc-lint assertions green) |
|
||||
|
||||
Reference in New Issue
Block a user