--- 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\"" --- 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. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.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. 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. - `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 02–06 only need to add config files and source files, not edit `package.json`. - 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`. 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.