---
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`.