SUMMARY documents the ESLint flat config, the 9 element types, the
single CORE-10 rule, the deliberate-violation fixture, the Vitest test
that runs ESLint programmatically against the violator, and the four
auto-fixed deviations (typescript-eslint parser-only integration,
real render target file for the violator import, eslint-import-resolver-
typescript wiring, tsconfig.app.json test-file exclusion).
Verifies: npm run lint -> 0 errors / 0 warnings; npm test -> 2/2 pass;
npm run build -> green; eslint --no-ignore on violator -> exits 1.
Self-Check: PASSED.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- src/sim/__test_violation__/violator.ts deliberately imports from
src/render/__firewall_target__.ts to trigger the firewall rule.
- src/sim/__test_violation__/lint-firewall.test.ts runs ESLint
programmatically (with ignore: false) against the violator and
asserts boundaries/element-types fires with severity=error and the
message mentions both 'sim' and 'render'.
- src/render/__firewall_target__.ts is a minimal export so the
boundaries plugin can resolve the import to a real path on disk.
Without a real target, the plugin marks the import as isUnknown
and silently skips the rule (verified empirically; see SUMMARY).
- eslint.config.js gains an import/resolver: typescript block so the
TS-aware resolver follows extension-less imports
('../../render/foo' -> src/render/foo.ts). Required by the
boundaries plugin's element classification of import targets.
- tsconfig.app.json excludes *.test.ts and src/sim/__test_violation__/
so 'tsc -b' does not try to typecheck Node-API-using test code with
the DOM-only project's lib settings; vitest still discovers them
via its own include glob.
- Added eslint-import-resolver-typescript as devDep.
Verifies green:
npm run lint -> 0 errors, 0 warnings (violator excluded)
npm test -> 2/2 pass (sentinel + firewall)
npm run build -> tsc -b clean, vite build clean
npx eslint --no-ignore src/sim/__test_violation__/violator.ts
-> exits 1 with the expected
boundaries/element-types error
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New eslint.config.js (flat, ESLint 9) declaring 9 element types:
the seven Phase-1 firewall directories (sim, render, ui, save,
content, audio, store) plus the template's app + game.
- One rule, severity error: sim cannot import from render or ui (CORE-10).
- Default posture allow — Phase 1 enforces ONE rule, not closed-by-default.
- src/sim/__test_violation__/ excluded from default lint glob; the rule's
end-to-end correctness is proven by Task 2's Vitest test, not by 'lint
exits 0 on clean code'.
- Added typescript-eslint as devDep (parser only — no rule sets) so
ESLint can parse .ts/.tsx (Espree default cannot). Documented as a
Plan 02 deviation in 01-02-SUMMARY.md (Rule 3 — Blocking).
Verifies green on the clean codebase: 0 errors, 0 warnings via
'npm run lint'. Stderr notices from boundaries plugin about deprecated
rule name (element-types vs dependencies in v6) and legacy selector
syntax are informational only — they don't count as ESLint warnings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wave 1 of Phase 1 complete. Phaser 4 + React 19 + Vite 8 + TypeScript 6
scaffold builds (npm run build green); 15 Phase-1 deps installed at
locked versions; 7 architectural-firewall directories ready under src/;
repo-root /content/ + /assets/ trees ready; Vitest (happy-dom) +
Playwright wired with passing sentinel; package.json scripts
pre-declared for the entire Phase 1 plan-set so Wave 2 can run in
parallel without colliding on package.json.
3 deviations auto-fixed (1 blocking, 2 missing-critical):
1. Built scaffold by hand because @phaserjs/create-game v1.3.2 is
interactive-only — plan's documented fallback path was used.
2. build script wraps tsc -b before vite build so strict-TS gates
every build (CLAUDE.md Code Style invariant).
3. Added *.tsbuildinfo to .gitignore (TS 6 incremental cache files).
Wave 2 readiness: Plan 02 must use ESLint 9 flat-config format
(eslint.config.js); legacy .eslintrc.* not supported. fake-indexeddb
pre-installed for Plan 03 IDB tests. inkjs + inklecate installed but
no .ink files compiled (Phase 2 PIPE-02 owns that).
- vitest.config.ts: happy-dom environment (so Plan 03's IndexedDB tests
can layer fake-indexeddb on top of happy-dom's window per RESEARCH);
passWithNoTests:false enforces RESEARCH CI Pitfall B (a green CI run
must mean tests *ran*, not 'no tests existed'); include glob covers
src/**/*.test.ts(x) and scripts/**/*.test.mjs.
- playwright.config.ts: testDir 'tests/e2e' (not yet created — first spec
lands in Phase 2 PIPE-07); webServer config wires npm run dev so smoke
tests can self-start the dev server; baseURL pinned to vite default.
- src/__sentinel__.test.ts: a single test asserting 1+1===2 AND that
globalThis.window exists, proving the runner is wired and happy-dom is
active. To be deleted once real tests exist (Plan 03 onward).
- npm test → 1 file, 1 test passed in 593ms.
- npx playwright --version → Version 1.59.1 (matches RESEARCH lock).
- Built equivalent React + Vite + TypeScript scaffold by hand because the official
npm create @phaserjs/game@latest scaffolder is interactive-only and the documented
--template/--yes flags are ignored (verified 2026-05-08 with create-game v1.3.2).
Plan Step 1 explicitly authorizes this fallback. Resulting tree mirrors the
official template shape: index.html, src/main.tsx, src/App.tsx, src/PhaserGame.tsx,
src/game/main.ts, src/game/scenes/Boot.ts.
- Installed Phase-1 production deps at versions verified in RESEARCH.md:
phaser@4.1.0, react@19.2.6, react-dom@19.2.6, 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.
- Installed Phase-1 dev deps: vite@8.0.11, @vitejs/plugin-react@6.0.1,
typescript@6.0.3, @types/react@19, @types/react-dom@19, @types/node@22,
vitest@4.1.5, @vitest/ui, happy-dom, fake-indexeddb@6 (for Plan 03 IDB tests),
@playwright/test@1.59.1, eslint@9, eslint-plugin-boundaries@6.0.2, inklecate@1.8.1.
- Created the seven architectural-firewall directories under src/ with .gitkeep
markers (sim, render, ui, save, content, audio, store) — siblings to the
template-provided src/game/ — so Plan 02's ESLint boundaries rule has clean
targets per CLAUDE.md 'Architectural Firewall'.
- Created repo-root /content/ (with /dialogue/ and /seasons/ subdirs) and /assets/
trees per CONTEXT D-11, D-12.
- Pre-declared all downstream-required scripts in package.json so Plans 02–06 only
edit code, not script keys: dev, build, preview, lint (--max-warnings 0 per
RESEARCH CI Pitfall C), test (--passWithNoTests=false per CI Pitfall B),
test:watch, validate:assets, compile:ink (no-op stub for Phase 1; Phase 2
replaces with real inklecate invocation), ci.
- TypeScript strict mode enforced via tsconfig.json + tsconfig.app.json + tsconfig.node.json.
- npm run build succeeds (tsc -b && vite build) producing dist/index.html and
dist/assets/index-*.js (~1.5MB Phaser bundle; code-splitting deferred to Phase 2+
when actual scenes exist).
User locked four implementation decisions:
- AI asset pipeline: minimum-viable schema + sidecar provenance + CI gate;
vendor/model deferred to Phase 5; 10–20 hand-curated AI generations as
Phase 1 north-stars
- Save v1: minimal payload (Phase 2 fields only); synthetic v0→v1 migration
proves the chain works; first real migration ships in Phase 4
- Doctrine docs: anti-FOMO consolidation + Season 7 principle-level rest-state
contract; both in .planning/; no CI/lint enforcement
- Phase 1 scaffold caps at the 5 success criteria — BigQty, Zustand store, and
tick scheduler defer to Phase 2
Pushback recorded: user prefers minimum-viable infrastructure for support
systems; no ceremonial workflows.