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>
18 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01 | 01 | execute | 1 |
|
true |
|
|
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.
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_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 Task 1: Scaffold Phaser 4 official template + restructure src/ + install Phase-1 deps 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 - .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) 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).
npm run build && 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 && test -d content && test -d assets && 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')"
- `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`.
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.
Task 2: Configure Vitest (happy-dom) + Playwright (install only) + sentinel test
vitest.config.ts,
playwright.config.ts,
src/__sentinel__.test.ts
- .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)
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`.**
npm test && npx playwright --version
- `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`.
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.
<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>
<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@^6for Plan 03 IDB tests). - Vitest + Playwright configured; sentinel test passes;
npm testis green. package.jsonscripts pre-declared for the entire plan set:dev,build,preview,lint,test,validate:assets,compile:ink,ci. </success_criteria>