Files
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

304 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: 01
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- package.json
- package-lock.json
- tsconfig.json
- vite.config.ts
- vitest.config.ts
- playwright.config.ts
- src/sim/.gitkeep
- src/render/.gitkeep
- src/ui/.gitkeep
- src/save/.gitkeep
- src/content/.gitkeep
- src/audio/.gitkeep
- src/store/.gitkeep
- content/.gitkeep
- content/dialogue/.gitkeep
- content/seasons/.gitkeep
- assets/.gitkeep
- .gitignore
autonomous: true
requirements: [CORE-01]
must_haves:
truths:
- "Game scaffold builds without errors via `npm run build`"
- "Phaser 4 + React 19 + Vite + TypeScript template is installed and runnable via `npm run dev`"
- "All seven firewall directories (sim, render, ui, save, content, audio, store) exist under src/"
- "All Phase-1 dependencies (idb, lz-string, zod, crc-32, gray-matter, yaml, inkjs, eslint-plugin-boundaries, vitest, @playwright/test, happy-dom, fake-indexeddb, inklecate) are installed at the verified versions"
- "package.json declares all scripts that downstream plans will rely on (lint, test, validate:assets, compile:ink, ci) — stubs allowed"
- "Vitest can find and run a sentinel test that asserts `1+1===2`"
artifacts:
- path: package.json
provides: "Phase-1 dependencies + scripts (dev, build, lint, test, validate:assets, compile:ink, ci)"
contains: "\"vitest\""
- path: vitest.config.ts
provides: "Vitest config with happy-dom env (for IndexedDB shim used by save tests)"
contains: "happy-dom"
- path: playwright.config.ts
provides: "Playwright config (installed only — no specs in Phase 1)"
- path: src/sim/.gitkeep
provides: "Firewall directory marker for Plan 02 ESLint boundaries rule"
- path: src/save/.gitkeep
provides: "Save layer directory (Plan 03 fills with implementation)"
- path: content/.gitkeep
provides: "Repo-root content directory per CONTEXT D-11"
- path: assets/.gitkeep
provides: "Repo-root assets directory per CONTEXT D-12"
key_links:
- from: package.json
to: "Plan 02, 03, 04, 05, 06"
via: "Pre-declared scripts (lint, test, validate:assets, compile:ink) so later plans only fill behaviour, never re-edit script keys"
pattern: "\"scripts\":\\s*\\{[^}]*\"validate:assets\""
---
<objective>
Bootstrap the Phaser 4 + React 19 + Vite + TypeScript scaffold via the official `npm create @phaserjs/game@latest` template, install every Phase-1 dependency at the versions locked in RESEARCH.md, restructure `src/` to expose the seven architectural-firewall directories as siblings to the template-provided `src/game/`, create the repo-root `/content/` and `/assets/` trees, and ship a minimal Vitest + Playwright config plus a sentinel test that proves the test runner works. This plan is the structural prerequisite for every Wave-2 plan: it owns `package.json` scripts wholesale so later parallel plans never touch `package.json`.
Purpose: Without this scaffold there is no project. Without exposing the seven firewall directories Plan 02's ESLint boundaries rule has nothing to lint against. Without the pre-declared scripts and Vitest config Plans 03, 04, 05, 06 cannot run their tests in parallel without colliding on `package.json`.
Output: A buildable, runnable Phaser 4 scaffold with the firewall directory skeleton, all Phase-1 deps installed, and the test infrastructure ready for Wave 2 to drop test files into.
</objective>
<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/01-foundations-and-doctrine/01-CONTEXT.md
@.planning/phases/01-foundations-and-doctrine/01-RESEARCH.md
@CLAUDE.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Scaffold Phaser 4 official template + restructure src/ + install Phase-1 deps</name>
<files>
package.json,
package-lock.json,
tsconfig.json,
.gitignore,
src/sim/.gitkeep,
src/render/.gitkeep,
src/ui/.gitkeep,
src/save/.gitkeep,
src/content/.gitkeep,
src/audio/.gitkeep,
src/store/.gitkeep,
content/.gitkeep,
content/dialogue/.gitkeep,
content/seasons/.gitkeep,
assets/.gitkeep
</files>
<read_first>
- .planning/phases/01-foundations-and-doctrine/01-CONTEXT.md (D-10, D-11, D-12 — scaffold layout, repo-root /content/ and /assets/, single package)
- .planning/phases/01-foundations-and-doctrine/01-RESEARCH.md § "Standard Stack" (verified versions table) and § "Recommended Project Structure"
- CLAUDE.md "Stack" section (locked versions)
</read_first>
<action>
Run the official Phaser 4 template scaffold and merge it into the current repo (which already contains `.git/`, `.planning/`, `.claude/`, and `CLAUDE.md`). The repo cwd is `c:\Users\josh1\Documents\Code\TheLastGarden\` and must remain so — do not nest the template in a subdirectory.
**Step 1 — Bootstrap into a temp dir, then copy in:**
```bash
# Run from a parent directory or temp location
cd "$TMPDIR" || cd /tmp
npm create @phaserjs/game@latest tlg-template -- --template react-ts --yes 2>&1 | tail -20
# If --template/--yes flags are not supported by create-game, run interactively and choose:
# "React + Vite + TypeScript"
# Then copy everything except .git into the repo root:
cp -r tlg-template/{src,public,*.json,*.ts,*.html,*.md,.eslintrc*,.gitignore,vite.config.*} c:/Users/josh1/Documents/Code/TheLastGarden/ 2>&1 || true
rm -rf tlg-template
```
If the template does not provide non-interactive flags, scaffold interactively in a temp dir and then copy.
**Step 2 — Install Phase-1 production deps (versions per RESEARCH.md verified 2026-05-08):**
```bash
cd c:/Users/josh1/Documents/Code/TheLastGarden
npm install idb@^8.0.3 lz-string@^1.5.0 zod@^4.4.3 crc-32@^1.2.2 gray-matter@^4.0.3 yaml@^2.8.4 inkjs@^2.4.0
```
**Step 3 — Install Phase-1 dev deps (note: `fake-indexeddb` is required by Plan 03's IDB tests — happy-dom does not ship IndexedDB; install it here in Plan 01 so Plan 03 Task 2 can `import 'fake-indexeddb/auto'` without re-running install):**
```bash
npm install -D vitest@^4.1.5 @vitest/ui happy-dom fake-indexeddb@^6 @playwright/test@^1.59.1 eslint-plugin-boundaries@^6.0.2 inklecate@^1.8.1
```
**Step 4 — Create the seven firewall directories with .gitkeep markers (per RESEARCH Open Question #3, .gitkeep is the recommendation):**
```bash
mkdir -p src/sim src/render src/ui src/save src/content src/audio src/store
touch src/sim/.gitkeep src/render/.gitkeep src/ui/.gitkeep src/save/.gitkeep src/content/.gitkeep src/audio/.gitkeep src/store/.gitkeep
```
**Step 5 — Create the repo-root /content/ and /assets/ trees (per CONTEXT D-11, D-12):**
```bash
mkdir -p content/dialogue content/seasons assets
touch content/.gitkeep content/dialogue/.gitkeep content/seasons/.gitkeep assets/.gitkeep
```
**Step 6 — Edit `package.json` to add ALL scripts that downstream plans need.** Use the Edit tool to set the `scripts` block to include exactly these keys (preserve any template-provided `dev`/`build`/`preview` entries; add the rest):
```json
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint . --max-warnings 0",
"test": "vitest run --passWithNoTests=false",
"test:watch": "vitest",
"validate:assets": "node scripts/validate-assets.mjs",
"compile:ink": "echo \"[compile:ink] no .ink files yet — Phase 2 will populate /content/dialogue/\" && exit 0",
"ci": "npm run lint && npm run test && npm run validate:assets && npm run build"
}
}
```
Per CONTEXT D-08 RESEARCH § "Pattern 4 — Ink files in Phase 1", `compile:ink` is a no-op stub in Phase 1; Phase 2 will replace it with `inklecate -o src/content/compiled-ink/ content/dialogue/*.ink`.
Per RESEARCH § "Common Pitfalls (CI / Tooling Specific)" CI Pitfall B, the test script MUST include `--passWithNoTests=false`; CI Pitfall C: lint MUST include `--max-warnings 0`.
**Step 7 — Verify `tsconfig.json` has `"strict": true`.** The template should provide it; if not, add it under `compilerOptions`. Per CLAUDE.md "Code Style", TypeScript strict is mandatory.
**Step 8 — Verify `.gitignore` contains `node_modules/`, `dist/`, `coverage/`.** Add if missing.
**Step 9 — Commit with message `chore(01-01): scaffold Phaser 4 template + Phase-1 deps + firewall directories`.** Stage only the files this task touched; do NOT `git add -A` (the repo also has `.planning/` files from upstream that are tracked separately).
</action>
<verify>
<automated>npm run build &amp;&amp; test -d src/sim &amp;&amp; test -d src/render &amp;&amp; test -d src/ui &amp;&amp; test -d src/save &amp;&amp; test -d src/content &amp;&amp; test -d src/audio &amp;&amp; test -d src/store &amp;&amp; test -d content &amp;&amp; test -d assets &amp;&amp; node -e "const p=require('./package.json'); for (const k of ['dev','build','lint','test','validate:assets','compile:ink','ci']) if (!p.scripts[k]) { console.error('missing script: '+k); process.exit(1); } console.log('all scripts present')"</automated>
</verify>
<acceptance_criteria>
- `package.json` exists at repo root and contains `"phaser"`, `"react"`, `"react-dom"`, `"vite"`, `"typescript"`, `"idb"`, `"lz-string"`, `"zod"`, `"crc-32"`, `"gray-matter"`, `"yaml"`, `"inkjs"`, `"vitest"`, `"@playwright/test"`, `"eslint-plugin-boundaries"`, `"happy-dom"`, `"fake-indexeddb"`, `"inklecate"` somewhere in dependencies or devDependencies — verify with `grep -E '"(phaser|idb|lz-string|zod|crc-32|gray-matter|yaml|inkjs|vitest|eslint-plugin-boundaries|happy-dom|fake-indexeddb|inklecate)"' package.json | wc -l` returns at least 13.
- All 7 firewall directories exist as directories: `test -d src/sim && test -d src/render && test -d src/ui && test -d src/save && test -d src/content && test -d src/audio && test -d src/store` exits 0.
- All 7 firewall directories contain `.gitkeep`: `for d in sim render ui save content audio store; do test -f src/$d/.gitkeep || exit 1; done`.
- Repo-root `/content/` and `/assets/` exist: `test -d content && test -d content/dialogue && test -d content/seasons && test -d assets`.
- `package.json` scripts block contains ALL of: `dev`, `build`, `preview`, `lint`, `test`, `test:watch`, `validate:assets`, `compile:ink`, `ci` — verify with `node -e "const p=require('./package.json'); ['dev','build','preview','lint','test','test:watch','validate:assets','compile:ink','ci'].forEach(k=>{ if(!p.scripts[k]) throw new Error('missing '+k); })"` exits 0.
- `npm run build` exits 0 and produces a `dist/` directory.
- `tsconfig.json` contains `"strict": true` — verify with `grep -q '"strict"\\s*:\\s*true' tsconfig.json`.
- The template's existing `src/main.tsx`, `src/App.tsx`, `src/PhaserGame.tsx` are preserved (untouched) — verify with `test -f src/main.tsx && test -f src/App.tsx`.
</acceptance_criteria>
<done>
Phaser 4 template scaffolded into the repo root, all Phase-1 deps installed at the verified versions (including `fake-indexeddb@^6` for Plan 03's IDB tests), all 7 firewall directories created with `.gitkeep`, repo-root `/content/` and `/assets/` trees created, `package.json` has all downstream-required scripts pre-declared, `npm run build` succeeds, commit landed.
</done>
</task>
<task type="auto">
<name>Task 2: Configure Vitest (happy-dom) + Playwright (install only) + sentinel test</name>
<files>
vitest.config.ts,
playwright.config.ts,
src/__sentinel__.test.ts
</files>
<read_first>
- .planning/phases/01-foundations-and-doctrine/01-RESEARCH.md § "Validation Architecture" (Vitest framework table; happy-dom for IndexedDB shim) and § "Wave 0 Gaps" (the test stub list)
- .planning/phases/01-foundations-and-doctrine/01-VALIDATION.md § "Test Infrastructure"
- package.json (verify vitest + happy-dom + @playwright/test installed by Task 1)
</read_first>
<action>
Wave 0 deliverable per RESEARCH § Validation Architecture: stand up Vitest + Playwright config so Wave 2 plans can drop `*.test.ts` files into `src/save/`, `src/content/`, `scripts/` and have them auto-discovered.
**Step 1 — Create `vitest.config.ts`** with happy-dom environment (so `src/save/db.test.ts` in Plan 03 can use `idb` against the happy-dom IndexedDB shim — RESEARCH explicitly calls for this). Use the Write tool with this exact content:
```typescript
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'happy-dom',
include: ['src/**/*.test.ts', 'scripts/**/*.test.ts'],
passWithNoTests: false,
globals: false,
},
});
```
**Step 2 — Create `playwright.config.ts`** with an empty `testDir` pointing at a not-yet-existing `tests/e2e/` directory. Phase 1 installs Playwright but ships no specs (per RESEARCH Standard Stack and CONTEXT — first spec is Phase 2 PIPE-07). Use Write tool:
```typescript
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: 'tests/e2e',
// Phase 1: no specs yet. First spec lands in Phase 2 (PIPE-07).
// This config exists so Plan 01 proves Playwright is installed and configured.
use: { baseURL: 'http://localhost:5173' },
webServer: {
command: 'npm run dev',
url: 'http://localhost:5173',
reuseExistingServer: true,
timeout: 30_000,
},
});
```
**Step 3 — Create a sentinel Vitest test** at `src/__sentinel__.test.ts` that proves the runner works end-to-end. This test will be deleted in Phase 2 (or earlier) once real tests exist; it exists in Phase 1 only to prove `npm test` is wired correctly so Wave 2 plans can rely on it. Use Write tool:
```typescript
import { describe, it, expect } from 'vitest';
describe('phase-1 test infrastructure sentinel', () => {
it('vitest is wired and the happy-dom environment is active', () => {
expect(1 + 1).toBe(2);
// happy-dom provides `window` in the test env, which save tests will rely on
// for IndexedDB. Assert it exists so Plan 03 can trust the env.
expect(typeof globalThis.window).toBe('object');
});
});
```
**Step 4 — Verify the test runs:** `npm test` should produce a green run with exactly 1 test passing.
**Step 5 — Verify Playwright is wired:** `npx playwright --version` should print a version string starting with `1.59`.
**Step 6 — Commit `chore(01-01): wire Vitest (happy-dom) and Playwright config + sentinel test`.**
</action>
<verify>
<automated>npm test &amp;&amp; npx playwright --version</automated>
</verify>
<acceptance_criteria>
- `vitest.config.ts` exists at repo root and contains `happy-dom` and `passWithNoTests: false` — verify with `grep -q "environment: 'happy-dom'" vitest.config.ts && grep -q "passWithNoTests: false" vitest.config.ts`.
- `playwright.config.ts` exists at repo root and references `testDir: 'tests/e2e'` — verify with `grep -q "testDir: 'tests/e2e'" playwright.config.ts`.
- `src/__sentinel__.test.ts` exists and contains a passing test — verify with `npm test 2>&1 | grep -E '✓|passed' | head -5`.
- `npm test` exits 0 with at least 1 test passing.
- `npx playwright --version` prints a version string matching `^Version 1\\.59\\.`.
- The sentinel test asserts both `1+1===2` AND that `window` exists (proving happy-dom is active) — verify with `grep -q "globalThis.window" src/__sentinel__.test.ts`.
</acceptance_criteria>
<done>
Vitest configured with happy-dom env and `passWithNoTests:false`; Playwright config installed (no specs); sentinel test passes proving the runner works; `npm test` returns green; commit landed.
</done>
</task>
</tasks>
<threat_model>
No security-relevant code in this plan; this is scaffold + dev-tooling configuration only. The two threat-model entries identified for Phase 1 (save tampering, malformed Base64 import DoS) are addressed by Plan 03. The `npm install` supply-chain consideration is mitigated by `package-lock.json` being committed — verified by `test -f package-lock.json` in acceptance.
</threat_model>
<verification>
- `npm run build` succeeds (smoke test for CORE-01).
- `npm test` runs and the sentinel test passes (smoke test for the test infrastructure).
- All seven firewall directories exist (structural prerequisite for Plan 02).
- `package.json` has every script downstream plans require — `lint`, `test`, `validate:assets`, `compile:ink`, `ci` — so Plans 0206 only need to add config files and source files, not edit `package.json`.
</verification>
<success_criteria>
- Phaser 4 + React 19 + Vite + TS scaffold builds and runs.
- `src/{sim,render,ui,save,content,audio,store}/` exist with `.gitkeep`.
- Repo-root `/content/` and `/assets/` exist.
- All Phase-1 dependencies installed at versions verified in RESEARCH.md (including `fake-indexeddb@^6` for Plan 03 IDB tests).
- Vitest + Playwright configured; sentinel test passes; `npm test` is green.
- `package.json` scripts pre-declared for the entire plan set: `dev`, `build`, `preview`, `lint`, `test`, `validate:assets`, `compile:ink`, `ci`.
</success_criteria>
<output>
After completion, create `.planning/phases/01-foundations-and-doctrine/01-01-SUMMARY.md` documenting:
- Final dependency versions installed (may differ slightly from RESEARCH if `npm install` resolved a newer patch).
- The exact `package.json` `scripts` block as written (so Wave-2 executors can verify their assumptions).
- Any drift from the template (e.g., did the template ship Vite 6, 7, or 8? did it ship a legacy `.eslintrc.cjs` or already-flat `eslint.config.js`?) — this drift is critical context for Plan 02.
- Sentinel test command and current pass status.
</output>
</output>