39563f6934
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>
304 lines
18 KiB
Markdown
304 lines
18 KiB
Markdown
---
|
||
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 && 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')"</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 && 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 02–06 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>
|