Commit Graph

48 Commits

Author SHA1 Message Date
josh 7f39cf6d31 docs(02-06): complete uat-gap-closure plan
5 tasks executed sequentially; all 4 first-impression UX gaps from
2026-05-09 live UAT structurally closed (G1 BLOCKING white halo, G2
BLOCKING no first-run prompt, G3 HIGH dim tile grid, G4 MEDIUM floating
gate). 21 new Vitest cases (312 → 333 green); 3 new Playwright assertions
(16 → 19); npm run ci + npm run test:e2e both exit 0. Phase 3 watercolor
deferral preserved (no painted assets, no new dependencies); V1Payload
unchanged (firstRunHintDismissed is session-state only, no migrations[2]).

Hint copy chosen: "Begin where the soil is bare." (plan's #1 ranked
candidate; bible voice — warm, specific, contemplative). Externalized in
content/seasons/01-soil/ui-strings.yaml; UiStringsSchema extended with
first_run_hint: z.string().min(1) so Zod strip mode does not silently
drop the YAML key from parsed.data.

Verifier handoff unblocked: 02-VERIFICATION.md frontmatter `gaps:` block
ready to flip status from gaps_found → verified. The 6 HUMAN-UAT.md tone
items remain pending (out of scope; addressed by separate workflow).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:21:42 -04:00
josh 0ed79b0eb1 docs(02-06): plan UAT gap closure (G1-G4)
Single Wave 0 plan addressing the 4 first-impression UX gaps from the
2026-05-09 live UAT:

- G1 (BLOCKING) src/index.css imported from main.tsx — body bg #1a1a1a,
  serif color #e8e0d0 — closes the white halo around the dark canvas
- G2 (BLOCKING) FirstRunHint component reading externalized
  'Begin where the soil is bare.' from ui-strings.yaml + UiStringsSchema
  extension (Zod default strip mode would otherwise drop the key) +
  session-slice firstRunHintDismissed flag (NOT V1Payload)
- G3 (HIGH) tile-renderer outline brightening 0x4d4d52 → 0x5a5a60 +
  hover bump 0x7a7a82
- G4 (MEDIUM) gate-renderer wall-band Phaser primitive at gate column
  with alpha 0.15-0.20

Phase 3 watercolor + cello deferral preserved: zero painted assets,
zero new npm dependencies, V1Payload unchanged. Plan-checker found
1 BLOCKER (Zod schema strip mode breaking G2 silently) + 1 WARNING
(hint copy ranking pushed non-bible-voice option first); planner
revised; residual frontmatter + 3 copy refs fixed inline.

Plan: 5 tasks, 16 files_modified, depends_on [02-01..02-05],
requirements [GARD-01, AEST-07, UX-01] supplemental coverage.
ROADMAP.md annotated with Wave 1/Wave 2 headers.

Next: /gsd-execute-phase 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:05:52 -04:00
josh 6f680f4731 test(02): VERIFICATION → gaps_found after live UAT (4 first-impression UX gaps)
User dev-server walkthrough surfaced 4 functional UX gaps beneath the verifier's
24/24 structural PASS:

  G1 (blocking) — no global page CSS → white halo around #1a1a1a canvas
  G2 (blocking) — no first-run prompt after Begin → player confused
                  (A Dark Room rule needs the canonical first-prompt)
  G3 (high)     — tile outlines too dim → grid reads as 'gray check block'
  G4 (medium)   — gate visual at canvas (880, 384) reads as stray rectangle

Phase 3 watercolor deferral preserved — every fix uses Phaser primitives or
one CSS file, not painted assets. STATE.md → status: gaps_found.

Next: /gsd-plan-phase 2 --gaps

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 11:37:44 -04:00
josh 286b4ba446 test(02): persist human verification items as UAT (6 tone/live-loop items)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 11:27:16 -04:00
josh e5d449095d docs(02-05): complete letter-settings-e2e plan
- 02-05-letter-settings-e2e-SUMMARY.md: full plan summary (frontmatter
  + decisions + REQ table + self-check). All 24 Phase-2 REQ-IDs
  structurally satisfied across the 5-plan set.
- STATE.md: marked Plan 02-05 complete; Phase 2 ready for
  /gsd-verify-work; progress 19% → 22%; next action set to verifier.
- ROADMAP.md: Plan 02-05 row marked [x] with duration + SUMMARY ref.
- REQUIREMENTS.md: UX-02 / UX-10 / CORE-03 / PIPE-07 marked complete
  with traceability annotations citing Plan 02-05's contribution;
  per-row Plan 02-05 references added to UX-02, UX-10, CORE-03;
  PIPE-07 traceability table row updated.
2026-05-09 11:16:02 -04:00
josh dd486969a9 test(02-05): playwright e2e for PIPE-07 — full Phase-2 loop
- tests/e2e/season1-loop.spec.ts: PIPE-07 smoke covering load → Begin
  → plant rosemary → fast-forward FakeClock 3min → harvest →
  fragment-reveal modal → close → journal-icon visible → open journal
  → fragment present → reload page → fragment persists. Sidesteps
  Phaser canvas pixel-clicking via window.__tlgStore command dispatch
  (test-only window slot, production-guarded by import.meta.env.PROD).
- playwright.config.ts: bumped webServer timeout 30s → 60s for cold
  Vite startup; pinned port 5273 + --strictPort to avoid collisions
  with other dev servers on the user's machine; reuseExistingServer
  false so the spec always starts a fresh Vite against this project.
- package.json: added test:e2e script (npx playwright test). Not
  added to npm run ci — Playwright is slower than Vitest; manual run
  before /gsd-verify-work + future v1 release pipeline.
- src/content/loader.ts (Rule 3 — Blocking): replaced gray-matter
  with a 15-line parseFrontmatter helper. gray-matter pulls in Node's
  Buffer global which is undefined in Vite's browser bundle; the
  build emits a 'Module "buffer" externalized' warning that masks
  the runtime ReferenceError. Surfaced under Vite dev mode while
  running the e2e — Plan 02-03's Markdown loader path (lura-first-
  letter.md + winter-rose-night.md) was effectively broken in real
  browsers since shipping. parseFrontmatter handles the strict
  '---<yaml>---<body>' shape the .md fragments use; bundle dropped
  from 2.2MB to 1.9MB as a side effect of dropping the unused dep.
- deferred-items.md: tracks the gray-matter package.json cleanup
  (the dep is now unused but kept in package.json for now, scoped
  out of this plan).
- npx playwright test exits 0 (1 spec, 1.5s test runtime); npm run
  ci exits 0; 308/308 vitest still green. PIPE-07 satisfied
  end-to-end.
2026-05-09 11:04:32 -04:00
josh de3f55b1c4 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>
2026-05-09 10:41:24 -04:00
josh 348c76a537 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>
2026-05-09 10:16:02 -04:00
josh d052a35478 docs(02-02): complete begin-plant-grow plan
- Add 02-02-begin-plant-grow-SUMMARY.md (3 atomic commits, 35 new tests, BLOCKER 3 invariant honored, RESEARCH Assumption A5 verified, deviations documented)
- STATE.md — advance to Plan 02-02 complete (2/5 plans in Phase 2; 9 total plans complete)
- ROADMAP.md — mark 02-02 plan complete; phase progress 2/5
- REQUIREMENTS.md — mark GARD-01, GARD-02, AEST-07, UX-01 complete (with traceability comments)
2026-05-09 09:50:05 -04:00
josh 38535bac73 docs(02-01): complete foundations plan
- 02-01-foundations-SUMMARY.md authored with frontmatter dependency
  graph, key-files manifest, decisions log, patterns established,
  test-count breakdown (72 new tests), TICK_MS=200 (no drift), and
  ESLint sim-purity rule landed (defended-option clause did not trigger)
- STATE.md: Phase 2 progress 1/5 plans (Wave 0 complete);
  velocity table updated with Plan 02-01 ~12min entry; decisions log
  cites BLOCKER 3 split, V1Payload extension, ESLint rule
- ROADMAP.md: Phase 2 row updated to 1/5; 02-01 plan marked [x] with
  duration + summary backlink
- REQUIREMENTS.md: CORE-02, CORE-03, CORE-11, UX-10, UX-11 marked
  complete with annotations; traceability table updated

Plan execution metrics:
- 3 atomic commits (58db532, fe99058, 2a8d354)
- 72 new tests across 9 test files (cushion above plan estimate of 54)
- Total test count: 128/128 green
- npm run ci exits 0
- Duration: ~12 min (sequential mode)
2026-05-09 09:26:37 -04:00
josh 5ddaabcdc1 docs(02): cite D-12, D-16, D-32 in plan must_haves + record planning complete
ci / lint + test + validate-assets + build (push) Successful in 9m39s
Decision-coverage gate found three CONTEXT.md decisions structurally
implemented but not literally cited by their D-NN tags. Added one-line
must_haves entries citing each:

- D-12 (Lura as discrete gate visits, 3 beats this Season) → 02-04
- D-16 (all Lura dialogue authored in Ink, runtime via inkjs) → 02-04
- D-32 (Zustand 5 store as the Phaser↔React bridge; sim never imports
  store, CORE-10 enforced) → 02-01

STATE.md flipped from in_progress (context gathered) to ready_to_execute
with the planning summary in stopped_at.

All 24 REQ-IDs + 34 D-XX decisions now covered.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 03:19:44 -04:00
josh a641056364 fix(02): plan revision iter 3 — BLOCKER 3 cross-plan regression + W1/W2
BLOCKER 3 — cross-plan regression: Plans 02-03 and 02-05 BOTH re-author
src/sim/garden/commands.ts but had reverted simulateOneTick to the old
defective return shape (`return { ...next, lastTickAt: currentTick };`).
Wave 1's execution of 02-03 would overwrite 02-02's correct version,
breaking the invariant for the entire phase.

  - 02-03: simulateOneTick return now matches 02-02 line 457 exactly:
    `return { ...next, tickCount: next.tickCount + 1 };`
  - 02-05: same fix for the silent-mode update (Step 6).
  - 02-03 acceptance_criteria: add negative grep
    (`! grep -E "lastTickAt:\s*(this|currentTick)" src/sim/garden/commands.ts`)
    and positive grep (`grep -q "tickCount: next.tickCount" ...`).
  - 02-05 acceptance_criteria: add the same two greps for commands.ts so
    02-05's silent-mode edits cannot silently re-introduce the regression.

W1 — App.tsx import: 02-05 Step 11 used `useEffect` without importing it.
Combined `import { useState }` and `import { useRef }` into a single
`import { useState, useEffect, useRef } from 'react';` line.

W2 — helper arity divergence: Settings.tsx (one-arg, Date.now() inline)
and PhaserGame.tsx (two-arg, clock.now() injected) had two parallel
definitions of buildPayloadFromStore / hydrateStoreFromPayload. Fix:

  - New Step 3.5 introduces `src/save/payload.ts` with the unified
    two-arg signature: `buildPayloadFromStore(state, nowMs)` and
    `hydrateStoreFromPayload(state, payload)`.
  - `src/save/index.ts` re-exports both.
  - Settings.tsx imports from save barrel; passes Date.now() at the
    call site (no clock injection on hand).
  - PhaserGame.tsx imports from save barrel; passes clock.now() (the
    injected wallClock or FakeClock).
  - Inline duplicate definitions in both files removed; replaced with
    a comment pointing to the shared module.
  - files_modified updated to include src/save/payload.ts.
  - acceptance_criteria asserts: shared file exists, both helpers
    exported, both consumers import from save barrel, no inline
    duplicate definitions remain.

VALIDATION.md not updated — no `<automated>` verify command changed;
the new greps live inside `<acceptance_criteria>` (executor-checked
per task), and VALIDATION.md is not present in the phase dir.

All iteration-1 + iteration-2 fixes preserved; no regressions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 03:15:39 -04:00
josh d065922cad revise(02): mark Open Questions RESOLVED + tidy GrowthStage import order
- W1: 02-RESEARCH.md Open Questions section now flagged (RESOLVED) and each
  Recommendation prefixed with RESOLVED + a pointer to the artifact that
  codified the resolution.
- W8: 02-02 Plan example moves `import type { GrowthStage }` to the top of
  commands.ts (alongside the other type-only imports) and drops the trailing
  parenthetical apology — the executor doesn't need to fix anything.
2026-05-09 03:05:51 -04:00
josh e5c55b0aae revise(02): BLOCKER 3 — split lastTickAt (wall-clock) from tickCount (sim counter)
Two distinct fields with strict separation:
  - lastTickAt: wall-clock milliseconds. Written ONLY at saveSync time by
    the application layer. The sim NEVER writes this field.
    computeOfflineCatchup uses it as the wall-clock anchor.
  - tickCount: monotonic sim-internal counter (one per simulate() call).
    Used for STRY-10 narrative gating that must be immune to wall-clock
    manipulation. The sim writes this field; the application layer reads
    it via simAdapter.applyTickCount.

Changes:
  02-01: SimState + V1Payload gain `tickCount: number`; migrations[1]
  defaults to 0; GardenSlice exposes tickCount + lastTickAt + setters;
  simAdapter exposes applyTickCount; tests assert the round-trip.
  02-02: simulateOneTick increments next.tickCount + 1 (not lastTickAt:
  currentTick); Garden scene's SimState snapshot reads lastTickAt
  through from store and writes tickCount: this.currentTick locally;
  acceptance_criteria forbids `lastTickAt: this.*` in the sim and scene.
  02-05: buildPayloadFromStore now persists tickCount (from store);
  hydrateStoreFromPayload restores it via state.setTickCount.

This unblocks the offline-catchup math: computeOfflineCatchup(payload.lastTickAt,
nowMs) now reliably reads wall-clock ms because the sim never overwrites it
with a tick counter.
2026-05-09 03:04:45 -04:00
josh a9f190ed27 revise(02-05): fix migrate() bypass in boot+import paths + lifecycle leak + hotkey
- BLOCKER 1: PhaserGame.tsx boot path now runs unwrap(env) → migrate(raw, env.schemaVersion).
  Casting unwrap(record.envelope) directly to V1Payload silently accepted any
  future-shape payload as the current shape; only migrate() walks the schema
  version chain.
- BLOCKER 2: Settings.tsx onImport now correctly orders importFromBase64 →
  unwrap (CRC verify) → migrate. Previous code discarded migrate's result
  and then read v1.payload as if unwrap returned an envelope rather than
  the payload itself — runtime crash on every import.
- BLOCKER 3: documented the lastTickAt invariant as wall-clock milliseconds,
  written ONLY at saveSync time (never by the sim). Added acceptance_criteria
  greps proving (a) saveSync writes clock.now(), (b) Garden scene does not
  overwrite lastTickAt with a tick counter, (c) sim/garden/Garden.ts (if it
  exists; the Garden scene actually lives at src/game/scenes/Garden.ts)
  contains no lastTickAt: this.* writes.
- W2: D-29 keyboard shortcut wired in App.tsx — comma toggles Settings,
  'j' dispatches a window CustomEvent the JournalIcon picks up.
- W5: lifecycle handle now stored in useRef and detached in the OUTER
  useLayoutEffect cleanup (the previous IIFE-internal return was a closure
  return, never reaching React's effect cleanup contract).
2026-05-09 03:01:27 -04:00
josh 953784ae93 revise(02-03): bump warm-pool fragment count + journal hotkey listener
- W6: warm-tagged pool depth raised to ≥9 (8th-harvest threshold + 1 buffer)
  so a worst-case all-rosemary playthrough never exhausts. Total per-pool
  targets: ≥9 warm, ≥3 contemplative, ≥3 heavy, plus the sentinel.
- W2: JournalIcon now listens for the 'tlg:toggle-journal' window event so
  App.tsx can wire a 'j' hotkey without lifting open/close state into the
  store. Hotkey is gated on the same revealed selector as the icon itself.
2026-05-09 03:01:12 -04:00
josh f6bef061c3 revise(02-04): replace in-test compileAllInk() call with precondition check
Per W9: invoking the compiler from inside ink-loader.test.ts's beforeAll
creates a filesystem race against other concurrent tests because the
script wipes src/content/compiled-ink/ at start. Compile is already part
of the npm run ci chain (via npm run build); the test should only verify
the artefact exists and fail loudly with a fix-it message otherwise.
2026-05-09 02:57:15 -04:00
josh f7428da299 revise(02-04): fix inklecate binary path + drop unused .ink + add last_fragment_title slot
- BLOCKER 4: inklecateBinary() now resolves node_modules/inklecate/bin/inklecate{,.exe};
  the previous path (inklecate-windows/, inklecate-mac/, inklecate-linux/) does not
  exist in the package — fallback verification of Assumption A6 would have masked
  the wrapper-API failure.
- W3: removed lura-greeting-template.ink from files_modified (never authored).
- W4: added last_fragment_title to INK_VARIABLE_MAP (extracts first sentence of the
  most-recently-harvested fragment) so the must_haves slot promise is fulfilled.
2026-05-09 02:56:50 -04:00
josh 63d2d8d5f7 docs(02): create phase 2 plan — 5 plans across 3 waves
Phase 2 (Season 1 Vertical Slice — Soil) plan set:
- 02-01 (Wave 0): foundations (BigQty + Zustand 5 store + tick scheduler + V1Payload extension + save lifecycle hooks + Phaser EventBus + ESLint sim-purity rule)
- 02-02 (Wave 1, parallel): Begin → Plant → Grow vertical slice
- 02-03 (Wave 1, parallel): Harvest → Journal → Compost + Season 1 fragments + PIPE-02 verification
- 02-04 (Wave 2, parallel): Lura's 3 Ink-authored gate beats (1st/4th/8th harvest, STRY-10)
- 02-05 (Wave 2, parallel): Letter + Settings + boot-path save lifecycle + Playwright PIPE-07 e2e

All 24 Phase-2 REQ-IDs covered across the plan set. VALIDATION.md per-task verification map filled (15 tasks); nyquist_compliant: true.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 02:45:56 -04:00
josh 5bc98ba4ac docs(02): map phase 2 file targets to existing analogs
54 file targets classified (49 new, 5 modified) with 87% analog coverage.
Key patterns: V1Payload extension (not v1→v2 migration), per-layer
public barrel pattern, test colocation, Zustand vanilla store + Phaser
EventBus singleton as the dual sim↔React bridge, ESLint sim-purity rule
proposed as a defended option (not auto-locked, per minimum-viable bias).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 02:11:01 -04:00
josh 01e02dcdb8 docs(phase-02): add validation strategy
Nyquist VALIDATION.md scaffold for Phase 2. Defines test infrastructure
(Vitest + Playwright already wired by Phase 1), sampling rates (npm test
after each commit, npm run ci after each wave), Wave-0 dependency surface
(BigQty + scheduler + Zustand store + V1Payload extension), and three
manual-only verifications (AudioContext cross-browser, letter voice review,
cozy-pace playtest). The per-task verification map is intentionally empty —
the planner fills it during plan generation; nyquist_compliant flips to
true once it's complete.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 02:03:17 -04:00
josh c4589a56b4 docs(02): research phase 2 vertical slice — 24 REQ-IDs mapped
5-plan MVP slice proposal across 3 waves: Wave 0 lands the three
deferred foundations (BigQty wrapper around break_eternity.js, Zustand
5 store wiring, tick scheduler / monotonic clock). Wave 1 ships two
parallel vertical slices (Begin+Plant+Grow, Harvest+Journal+Fragments).
Wave 2 ships the Lura gate-visit slice and the offline-letter slice
including Playwright PIPE-07 e2e. All 24 REQ-IDs addressed in the
coverage map; 10 architectural patterns enumerated; tick rate locked at
5Hz with 24h offline cap; AudioContext.resume() bootstrap pattern
documented for first-run + returning-player paths; V1Payload extension
shape locked per CONTEXT D-34 (no migrate_v1_to_v2 added). 10
assumptions logged, 8 are LOW risk; 2 are MEDIUM (canvas-DOM coord
mapping under FIT scale, inklecate Windows binary invocation) and
flagged for early verification in Plans 02-02 and 02-04.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 02:01:22 -04:00
josh 350e976fed docs(state): record phase 2 context session
Phase 2 discuss-phase complete; STATE.md now reflects context-gathered
status, updated stopped_at narrative, and next-action pointer to
/gsd-plan-phase 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 01:39:52 -04:00
josh 69964ba17f docs(02): capture phase context
Phase 2 (Season 1 Vertical Slice — Soil) discuss-phase output. 02-CONTEXT.md
captures 34 implementation decisions across 8 gray areas (garden geometry &
input · time density · Lura's arc · letter composition · Begin screen ·
Memory Journal · plant placeholders · Phase-2 Settings UI scope). Locks the
4×4 grid + click+inline seed picker, 2–5min growth band per plant with
auto-harvest-while-offline, 3 Lura gate visits gated by 1st/4th/8th harvest,
authored Ink letter skeleton with templated slots, full-screen letter on
≥5min absence, tasteful placeholder Begin screen (Phase 3 paints), full-
screen Journal modal revealing after first harvest, simple Phaser-primitive
plants with subtle ready-state pulse, save-management-only Settings.
Phase 2's first commits: BigQty wrapper, Zustand 5 store, tick scheduler.
Save schema is a v1 *extension*, not v1→v2.

02-DISCUSSION-LOG.md preserves the alternatives considered for human review.

Next: /gsd-plan-phase 2

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 01:39:48 -04:00
josh 49ba411a00 verify(01): phase 1 verification — all 16 REQ-IDs PASS, CI green
ci / lint + test + validate-assets + build (push) Successful in 9m38s
All 16 Phase-1 requirements verified against the live codebase:
- CORE-01, CORE-04..CORE-10: scaffold builds; save layer (IDB + fallback,
  envelope, migrations, snapshots, persist, codec) all green (53 tests / 12 files)
- PIPE-01: Vite-native content pipeline; schema violation fails build
- PIPE-03: asset provenance gate; refused-sample fixture proves gate structure
- PIPE-05: both doctrine docs authored + 8 doc-lint assertions green
- PIPE-06: ci.yml runs npm run ci on every push + PR
- AEST-08: ProvenanceSchema 6 fields; CI gate on every commit
- AEST-09: human curation gate in place; IOU records Path C deferral to Phase 5
- STRY-09: /content/ convention established (vacuously satisfied in Phase 1)
- UX-13: anti-fomo-doctrine.md authored + review-enforced

Deferred (non-blocking): 10-20 real north-star images (AEST-09 Task 2) — Phase 5.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 00:17:20 -04:00
josh d3410e207d feat(01-05): commit 2 placeholder north-star assets + IOU (Path C deferral)
User invoked planning-doctrine pushback principle on the 10-20 north-star
curation step. Two 1x1 transparent-PNG placeholders ship with provenance
sidecars marked model_id: 'placeholder' so the validator exercises at >0
assets. Full deferral rationale and resolution path in
.planning/phases/01-foundations-and-doctrine/01-05-IOU.md — to be revisited
at Phase 5 entry (curate then, or amend CONTEXT D-01 if still ceremonial).
2026-05-09 00:06:27 -04:00
josh 8ace3db7b4 docs(01-07): complete ci-workflow plan + Phase 1 closure metadata
- 01-07-ci-workflow-SUMMARY.md: structural enforcement map, Phase 2/8 handoff notes, threat T-01-08 mitigation confirmed
- 01-VALIDATION.md: per-task table populated (12/13 green, 01-05-T2 partial — checkpoint:human-verify awaiting north-star image curation); status flipped to executed
- ROADMAP.md: progress table marks Phase 1 as 7/7 with 01-05 partial annotation
- STATE.md: position advanced to Plan 7 of 7 complete; performance trend; Plan 01-05 Task 2 explicitly tracked as the only outstanding deliverable; next action = human curation pass then /gsd-verify-work
- REQUIREMENTS.md: PIPE-06 marked complete (CI workflow runs Vitest on every push/PR)
2026-05-09 00:00:23 -04:00
josh 0f192ca3c0 chore: merge executor worktree (01-06 doctrine-docs) 2026-05-08 23:48:35 -04:00
josh 2aa61d030e chore: merge executor worktree (01-05 asset-provenance, partial — Task 2 awaits human curation) 2026-05-08 23:48:30 -04:00
josh 4cc3d8dbd2 chore: merge executor worktree (01-03 save-layer) 2026-05-08 23:48:25 -04:00
josh c3289440d6 chore: merge executor worktree (01-04 content-pipeline) 2026-05-08 23:48:15 -04:00
josh 13139547f7 docs(01-03): complete save layer plan
7 commits across 3 TDD tasks (RED + GREEN per task) + .gitkeep cleanup;
36 Vitest tests across 7 test files green; npm run build clean under
TypeScript strict; all 6 CORE requirements (CORE-04 through CORE-09)
covered by at least one assertion.

Key structural decision documented in SUMMARY: SaveDB is a single
common-contract interface, not a union of IDBPDatabase | LocalStorageDBAdapter.
The union shape failed TypeScript-strict at the build gate; the interface
refactor isolates the type-system cast to one location at openSaveDB().
2026-05-08 23:47:01 -04:00
josh de39c1b7c3 docs(01-02): complete eslint-firewall plan
SUMMARY documents the ESLint flat config, the 9 element types, the
single CORE-10 rule, the deliberate-violation fixture, the Vitest test
that runs ESLint programmatically against the violator, and the four
auto-fixed deviations (typescript-eslint parser-only integration,
real render target file for the violator import, eslint-import-resolver-
typescript wiring, tsconfig.app.json test-file exclusion).

Verifies: npm run lint -> 0 errors / 0 warnings; npm test -> 2/2 pass;
npm run build -> green; eslint --no-ignore on violator -> exits 1.

Self-Check: PASSED.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 23:38:19 -04:00
josh f44c108b7c docs(01-06): complete doctrine docs plan
- Both Phase-1 doctrine docs landed under .planning/ (anti-fomo + season-7-end-state)
- Vitest doc-lint test scripts/doctrine.test.ts asserts both docs' structural integrity
  (file existence + required H2 sections + required source citations + boundary disclaimers)
- 'npm test' green: 2 test files, 9 tests passing (sentinel + doctrine)
- Per CONTEXT D-07: anti-FOMO enforced by review, no UX-string lint rule
- Per CONTEXT D-08: Season 7 end-state at principle level, treatment text deferred to Phase 7
- Per CONTEXT D-09: docs live in .planning/, not docs/
- Requirements complete: PIPE-05, UX-13, STRY-09
2026-05-08 23:34:11 -04:00
josh 3625ef85e6 docs(01-04): complete content pipeline plan
PIPE-01 + STRY-09 satisfied. Vite-native loader with literal
import.meta.glob patterns; FragmentSchema regex enforced; demo
fragment proves round-trip; 5 Vitest assertions cover schema
violations; content/README.md is the writer-facing contract.
2026-05-08 23:32:17 -04:00
josh 8521e04ddf docs(01-05): partial summary — Task 1 complete (validator + schema + refused-sample + Vitest), halted at Task 2 human-curate checkpoint
Documents the asset-provenance gate that landed (validator script, Zod sidecar
schema with the 6 CLAUDE.md fields + optional provenance_schema_version, refused-
sample PNG, tmpdir-isolated Vitest enforcement test) and the resume protocol for
Task 2 (Path A AI-generate / Path B hand-painted-or-licensed-photograph fallback /
Path C defer with explicit IOU). Per plan's autonomous: false flag and orchestrator
spawn instructions, the human curates the 10–20 north-star reference images.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 23:32:11 -04:00
josh cde93883bd docs(01-06): author Season 7 end-state principle doctrine + Vitest doc-lint test (PIPE-05)
- .planning/season-7-end-state.md answers principle-level the three questions
  per CONTEXT D-08: (a) what rest state means, (b) what the finite Roothold
  ceiling is tied to (count of authored fragments + Seasons), (c) the coda's
  tonal register (warm/quiet/specific/final). Cites SEAS-04, SEAS-09, SEAS-10,
  STRY-08; ROADMAP Phase 7; PITFALLS #1.
- Includes the explicit 'What this document is NOT' boundary section so
  treatment-level scope creep is structurally rejected (binary-choice scene
  text, ending paragraph text, Lura's final line, credits screen — all
  authored Phase 7, not Phase 1).
- scripts/doctrine.test.ts is the only automated enforcement of both Phase-1
  doctrine docs (per CONTEXT D-07: no UX-string lint rule). Asserts file
  existence + required H2 sections + required source citations + boundary
  disclaimer. 8 assertions / 2 doc files.
- vitest.config.ts include glob extended to scripts/**/*.test.ts so
  doctrine.test.ts is discovered by 'npm test'.
- tsconfig.node.json include extended to scripts/**/*.ts so the strict-TS
  gate covers the new doc-lint test alongside the existing build configs.
- 'npm test' green: 2 test files, 9 tests passing (sentinel + doctrine).
- Per CONTEXT D-09: lives in .planning/, not docs/.

Rule 3 [Blocking]: vitest.config.ts and tsconfig.node.json include globs
extended to discover the new TypeScript test file (existing globs only
covered .mjs scripts and src/ tests).
2026-05-08 23:31:25 -04:00
josh dddadbc1ac docs(01-06): author anti-FOMO doctrine consolidating PROJECT/REQUIREMENTS/CLAUDE/PITFALLS constraints (PIPE-05, UX-13)
- Banned Mechanics table enumerates 17 banned patterns (gacha, lootboxes,
  narrative gating, daily login, streaks, limited-time, energy/stamina,
  rewarded ads, push notifications, loss-aversion copy, countdown timers,
  Season skipping, time-skip purchases, hint systems, mobile nag UX, etc.)
- Allowed Engagement section names the 4 affordances that respect presence
  rather than demand it (Memory Storm opt-in, while-you-were-away letter,
  tab-title bloom indicator, Season-transition save-export reminder)
- Review Checklist provides 3 questions for every UX/copy/monetization change
- Source Documents section cites PROJECT.md, REQUIREMENTS.md, CLAUDE.md,
  .planning/research/PITFALLS.md
- Per CONTEXT D-07: doctrine is enforced by review, NOT by lint rule on UX
  strings (the doc explicitly notes this and proposes no lint rule)
- Per CONTEXT D-09: lives in .planning/ alongside other internal design docs
2026-05-08 23:29:01 -04:00
josh 1e99356b27 docs(01-01): complete scaffold and test infra plan
Wave 1 of Phase 1 complete. Phaser 4 + React 19 + Vite 8 + TypeScript 6
scaffold builds (npm run build green); 15 Phase-1 deps installed at
locked versions; 7 architectural-firewall directories ready under src/;
repo-root /content/ + /assets/ trees ready; Vitest (happy-dom) +
Playwright wired with passing sentinel; package.json scripts
pre-declared for the entire Phase 1 plan-set so Wave 2 can run in
parallel without colliding on package.json.

3 deviations auto-fixed (1 blocking, 2 missing-critical):
1. Built scaffold by hand because @phaserjs/create-game v1.3.2 is
   interactive-only — plan's documented fallback path was used.
2. build script wraps tsc -b before vite build so strict-TS gates
   every build (CLAUDE.md Code Style invariant).
3. Added *.tsbuildinfo to .gitignore (TS 6 incremental cache files).

Wave 2 readiness: Plan 02 must use ESLint 9 flat-config format
(eslint.config.js); legacy .eslintrc.* not supported. fake-indexeddb
pre-installed for Plan 03 IDB tests. inkjs + inklecate installed but
no .ink files compiled (Phase 2 PIPE-02 owns that).
2026-05-08 23:23:15 -04:00
josh 39563f6934 docs(01): plan phase 1 — 7 plans across 3 waves, verified after 1 revision
Wave 1: Plan 01 (scaffold + test infra)
Wave 2: Plans 02 (eslint firewall), 03 (save layer), 04 (content pipeline),
        05 (asset provenance — autonomous:false human-curate checkpoint),
        06 (doctrine docs)
Wave 3: Plan 07 (CI workflow)

All 16 Phase-1 REQ-IDs covered. Plan-checker found 4 blockers + 6 warnings
on first pass; revision iteration 1 landed all 10 fixes; iteration 2
returned VERIFICATION PASSED. Two orchestrator judgment calls during
revision: (1) implement CORE-04 localStorage fallback in Phase 1 (the
literal requirement and ROADMAP success criterion #2 both call for it),
(2) reclassify STRY-09 as vacuously satisfied in Phase 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 23:09:08 -04:00
josh 9c9c6eddbc docs(01): research phase 1 foundations and doctrine 2026-05-08 22:19:21 -04:00
josh 8f58e811b5 docs(01): capture phase 1 context
User locked four implementation decisions:
- AI asset pipeline: minimum-viable schema + sidecar provenance + CI gate;
  vendor/model deferred to Phase 5; 10–20 hand-curated AI generations as
  Phase 1 north-stars
- Save v1: minimal payload (Phase 2 fields only); synthetic v0→v1 migration
  proves the chain works; first real migration ships in Phase 4
- Doctrine docs: anti-FOMO consolidation + Season 7 principle-level rest-state
  contract; both in .planning/; no CI/lint enforcement
- Phase 1 scaffold caps at the 5 success criteria — BigQty, Zustand store, and
  tick scheduler defer to Phase 2

Pushback recorded: user prefers minimum-viable infrastructure for support
systems; no ceremonial workflows.
2026-05-08 22:03:41 -04:00
josh eecb79ae80 docs: create roadmap (8 phases) 2026-05-08 21:37:11 -04:00
josh 3378068884 docs: define v1 requirements 2026-05-08 21:27:24 -04:00
josh d7aa38f37e docs: synthesize research findings 2026-05-08 21:24:01 -04:00
josh a5dc54e95f docs: project research (stack, features, architecture, pitfalls) 2026-05-08 21:23:58 -04:00
josh a9f4efabac chore: add project config 2026-05-08 20:58:54 -04:00
josh de4e094d00 docs: initialize project 2026-05-08 20:57:15 -04:00