diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index ce483bc..3d0eccc 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -106,7 +106,7 @@ Requirements for initial release. Each maps to roadmap phases. All are user-cent - [ ] **PIPE-03**: Project ships an AI asset pipeline that records provenance per asset and refuses to integrate an asset missing required provenance fields. - [ ] **PIPE-04**: Project ships visual regression testing for the asset library that flags style drift before any model migration is merged. - [ ] **PIPE-05**: Project ships an `anti-FOMO doctrine` document and a `Season 7 end-state` design document in `.planning/` (or `docs/`) before economy code is written. -- [ ] **PIPE-06**: Project ships unit tests (Vitest) covering all save migrations and core economy formulas, run on every CI build. +- [x] **PIPE-06**: Project ships unit tests (Vitest) covering all save migrations and core economy formulas, run on every CI build. - [ ] **PIPE-07**: Project ships an end-to-end smoke test (Playwright) that loads the game, plants a seed, harvests a fragment, and verifies persistence across a page reload. ## v2 Requirements @@ -265,7 +265,7 @@ Populated by gsd-roadmapper during roadmap creation on 2026-05-08. | PIPE-03 | Phase 1 — Foundations & Doctrine | Pending | | PIPE-04 | Phase 8 — UX, Accessibility & Launch Polish | Pending | | PIPE-05 | Phase 1 — Foundations & Doctrine | Pending | -| PIPE-06 | Phase 1 — Foundations & Doctrine | Pending | +| PIPE-06 | Phase 1 — Foundations & Doctrine | Complete | | PIPE-07 | Phase 2 — Season 1 Vertical Slice (Soil) | Pending | **Per-Phase Counts:** diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 3591b9e..07530e3 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -37,12 +37,12 @@ Decimal phases appear between their surrounding integers in numeric order. **Plans:** 7 plans Plans: - [x] 01-01-scaffold-and-test-infra-PLAN.md — Bootstrap Phaser 4 official template, install Phase-1 deps, restructure src/ into 7 firewall directories, configure Vitest (happy-dom) + Playwright, pre-declare every package.json script downstream plans need ✓ 2026-05-09 (6 min) — see 01-01-scaffold-and-test-infra-SUMMARY.md -- [ ] 01-02-eslint-firewall-PLAN.md — Migrate to ESLint flat config + eslint-plugin-boundaries, declare 9 element types, enforce CORE-10 (sim cannot import render or ui) with a Vitest-tested deliberate-violation fixture -- [ ] 01-03-save-layer-PLAN.md — Save envelope {schemaVersion, payload, checksum} with CRC-32 over canonical JSON, idb-wrapped IndexedDB with last-3 snapshot retention, synthetic v0→v1 migration chain, navigator.storage.persist API, Base64 export/import with 50MB DoS cap, full round-trip test (CORE-04 through CORE-09) -- [ ] 01-04-content-pipeline-PLAN.md — Vite-native content pipeline using import.meta.glob, Zod schemas for Fragment + SeasonContent, demo fragment under /content/seasons/00-demo/, content/README.md documenting the convention, no-op compile:ink stub for Phase 2 (PIPE-01, STRY-09) -- [ ] 01-05-asset-provenance-PLAN.md — 30-line Node validator script walking /assets/ + Zod sidecar schema covering 6 required fields + optional schema_version, refused-sample fixture proves the gate, Vitest integration test, 10–20 hand-curated north-star reference images committed via human curation checkpoint (AEST-08, AEST-09, PIPE-03) -- [ ] 01-06-doctrine-docs-PLAN.md — Author .planning/anti-fomo-doctrine.md (consolidation per CONTEXT D-07) and .planning/season-7-end-state.md (principle-level per CONTEXT D-08), Vitest doc-lint test enforces structural integrity (PIPE-05, UX-13) -- [ ] 01-07-ci-workflow-PLAN.md — Minimum-viable .github/workflows/ci.yml running npm ci + npm run ci on push to main and PR; structurally enforces every Phase 1 success criterion on every commit going forward (PIPE-06) +- [x] 01-02-eslint-firewall-PLAN.md — Migrate to ESLint flat config + eslint-plugin-boundaries, declare 9 element types, enforce CORE-10 (sim cannot import render or ui) with a Vitest-tested deliberate-violation fixture +- [x] 01-03-save-layer-PLAN.md — Save envelope {schemaVersion, payload, checksum} with CRC-32 over canonical JSON, idb-wrapped IndexedDB with last-3 snapshot retention, synthetic v0→v1 migration chain, navigator.storage.persist API, Base64 export/import with 50MB DoS cap, full round-trip test (CORE-04 through CORE-09) +- [x] 01-04-content-pipeline-PLAN.md — Vite-native content pipeline using import.meta.glob, Zod schemas for Fragment + SeasonContent, demo fragment under /content/seasons/00-demo/, content/README.md documenting the convention, no-op compile:ink stub for Phase 2 (PIPE-01, STRY-09) +- [x] 01-05-asset-provenance-PLAN.md — 30-line Node validator script walking /assets/ + Zod sidecar schema covering 6 required fields + optional schema_version, refused-sample fixture proves the gate, Vitest integration test, 10–20 hand-curated north-star reference images committed via human curation checkpoint (AEST-08, AEST-09, PIPE-03) +- [x] 01-06-doctrine-docs-PLAN.md — Author .planning/anti-fomo-doctrine.md (consolidation per CONTEXT D-07) and .planning/season-7-end-state.md (principle-level per CONTEXT D-08), Vitest doc-lint test enforces structural integrity (PIPE-05, UX-13) +- [x] 01-07-ci-workflow-PLAN.md — Minimum-viable .github/workflows/ci.yml running npm ci + npm run ci on push to main and PR; structurally enforces every Phase 1 success criterion on every commit going forward (PIPE-06) ### Phase 2: Season 1 Vertical Slice (Soil) **Goal**: Player can launch the game, plant a seed, watch it grow, harvest a memory fragment authored in real Season 1 content, meet Lura at the gate, leave the tab for hours, and return to a letter-from-the-garden describing what bloomed — the entire core loop and content pipeline proven on Season 1 with no aesthetic polish required. @@ -143,7 +143,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 | Phase | Plans Complete | Status | Completed | |-------|----------------|--------|-----------| -| 1. Foundations & Doctrine | 1/7 | In Progress | - | +| 1. Foundations & Doctrine | 7/7 (01-05 Task 2 partial — north-star images awaiting human curation; CI shippable today) | In Progress | - | | 2. Season 1 Vertical Slice (Soil) | 0/TBD | Not started | - | | 3. Watercolor & Cello Aesthetic | 0/TBD | Not started | - | | 4. Season-Prestige Cycle & Season 2 (Roots) | 0/TBD | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index 51addb9..bcd1dbc 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,15 +3,15 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: executing -stopped_at: "Plan 01-01 (scaffold + test infra) complete. Phaser 4 + React 19 + Vite 8 + TS 6 scaffold builds; 15 deps installed at locked versions; 7 firewall directories ready; Vitest + Playwright wired with passing sentinel; package.json scripts pre-declared for the entire Phase 1 plan-set. Next: Wave 2 — Plans 02–06 in parallel (firewall, save layer, content pipeline, asset provenance, doctrine docs); Plan 05 has a human-curate checkpoint." -last_updated: "2026-05-09T03:18:51Z" -last_activity: 2026-05-09 -- Plan 01-01 (scaffold + test infra) complete +stopped_at: "Phase 1 closure: Plans 01-01..01-04, 01-06, 01-07 complete; Plan 01-05 Task 1 (validator + refused-sample fixture) merged but Task 2 (10–20 north-star reference images) awaits human curation per the planned checkpoint:human-verify gate. CI workflow shippable today (validator green with 0 assets; will continue green once images land). Next: /gsd-verify-work to UAT Phase 1, then human curation pass on north-star images, then /gsd-discuss-phase 2." +last_updated: "2026-05-09T03:56:45.284Z" +last_activity: 2026-05-09 progress: total_phases: 8 completed_phases: 0 total_plans: 7 - completed_plans: 1 - percent: 14 + completed_plans: 7 + percent: 100 --- # Project State @@ -25,31 +25,31 @@ See: .planning/PROJECT.md (updated 2026-05-08) ## Current Position -Phase: 01 (foundations-and-doctrine) — EXECUTING -Plan: 2 of 7 (next: 01-02-eslint-firewall) -Status: Executing Phase 01 -Last activity: 2026-05-09 -- Plan 01-01 (scaffold + test infra) complete +Phase: 01 (foundations-and-doctrine) — AWAITING VERIFICATION + HUMAN CURATION +Plan: 7 of 7 complete (01-05 Task 2 partial — north-star image curation outstanding) +Status: All Phase-1 automation green; ready for /gsd-verify-work UAT and human curation pass on north-star reference set +Last activity: 2026-05-09 -- Plan 01-07 (CI workflow) complete; PIPE-06 enforced -Progress: [█░░░░░░░░░] 14% +Progress: [██████████] 100% ## Performance Metrics **Velocity:** -- Total plans completed: 1 -- Average duration: 6 min -- Total execution time: 0.1 hours +- Total plans completed: 7 (1 partial) +- Average duration: ~5 min (Wave 1 baseline 6min; Wave 2 plans 4–8min; Plan 07 ~2min) +- Total execution time: ~30 min across all of Phase 1 **By Phase:** | Phase | Plans | Total | Avg/Plan | |-------|-------|-------|----------| -| 1. Foundations & Doctrine | 1/7 | 6 min | 6 min | +| 1. Foundations & Doctrine | 7/7 (1 partial) | ~30 min | ~5 min | **Recent Trend:** -- Last 5 plans: [01-01 scaffold-and-test-infra: 6 min — green] -- Trend: — (1 of 7 plans complete; trend will form after Wave 2) +- Last 5 plans: [01-03 save-layer · 01-04 content-pipeline · 01-05 asset-provenance (partial) · 01-06 doctrine-docs · 01-07 ci-workflow — all green] +- Trend: ↘ (Wave 2/3 plans came in faster than Wave 1's scaffolding; YAML-only Plan 07 was the cheapest at ~2min) *Updated after each plan completion* @@ -65,18 +65,21 @@ Recent decisions affecting current work: - Phases 4-7 deliver the remaining six Seasons in mechanic-introducing pairs (Season 2 alone with prestige, Seasons 3-4, Seasons 5-6, Season 7 alone) — at most one new mechanic per Season per the scope-defense doctrine. - Plan 01-01: scaffolded by hand (the official `npm create @phaserjs/game@latest` is interactive-only — `--template react-ts --yes` flags are silently ignored as of create-game v1.3.2); plan's documented fallback path was used. Vite 8 + TS 6 referenced-projects tsconfig layout adopted; `build` runs `tsc -b && vite build` so strict-TS gates every build. ESLint 9 installed → Plan 02 must use **flat config** (`eslint.config.js`), not legacy `.eslintrc.*`. - Plan 01-01: pre-installed `fake-indexeddb@^6` here so Plan 03 doesn't have to re-edit `package.json`. All Phase-1 dep versions match RESEARCH.md exactly within their `^` ranges. +- Plan 01-07: minimum-viable CI workflow (49 lines) running `npm ci` + `npm run ci` on push/PR to main; ubuntu-latest only, Node 22 only, no matrix per CONTEXT user pushback against ceremony. The workflow's role is to refuse merges that break local `npm run ci`, nothing more. New CI gates (Phase 2 e2e, Phase 8 visual regression) are added by editing `package.json scripts.ci` (or new dedicated workflow files), not by editing `ci.yml` — the workflow stays stable across all future phases. +- Plan 01-07: `npm ci` (lockfile-strict) chosen over `npm install` per RESEARCH § Security Domain; `npm audit` deferred to Phase 8. `actions/setup-node@v4` with `cache: 'npm'` per RESEARCH CI Pitfall A — never cache `node_modules/` directly. ### Pending Todos -None yet. +- **Plan 01-05 Task 2 (human curation):** 10–20 hand-curated AI generations need to be committed to `assets/north-stars/` with provenance sidecars. Each must pass the curation gate (visual consistency, real-species-slightly-wrong, watercolor register). The validator (`npm run validate:assets`) is green today with 0 assets and will continue green when the images land. This is the only outstanding Phase 1 deliverable before `/gsd-verify-work`. ### Blockers/Concerns Carry-forward banner concerns from research: - **7-Season scope risk** is the project's biggest risk; defended by the standalone-Season-1 escape hatch (Phase 2) and the one-mechanic-per-Season cap. -- **Story ends but the loop doesn't** — Season 7 end-state design must land in Phase 1 (PIPE-05); finite Roothold ceiling enforced in Phase 4 (SEAS-04); credits/coda rest-state in Phase 7 (SEAS-10). -- **AI asset style drift** — provenance + curation + locked north-star reference set must land in Phase 1 (AEST-08, AEST-09, PIPE-03) before any production-volume asset generation in Phase 5+; visual regression testing in Phase 8 (PIPE-04). +- **Story ends but the loop doesn't** — Season 7 end-state design landed in Phase 1 (`.planning/season-7-end-state.md`, PIPE-05 ✓); finite Roothold ceiling enforcement deferred to Phase 4 (SEAS-04); credits/coda rest-state to Phase 7 (SEAS-10). +- **AI asset style drift** — provenance schema + CI gate + refused-sample fixture landed in Phase 1 (Plan 01-05 Task 1, PIPE-03 + AEST-08 ✓); locked 10–20-image north-star reference set still pending human curation (Plan 01-05 Task 2 — AEST-09 partial); production-volume asset generation begins Phase 5+; visual regression testing in Phase 8 (PIPE-04). +- **Phase 1 partial closure:** Plan 01-05 Task 2 is the only outstanding deliverable. The CI workflow (Plan 01-07) is shippable today regardless. `/gsd-verify-work` can run after the curation pass. ## Deferred Items @@ -89,6 +92,6 @@ Items acknowledged and carried forward from previous milestone close: ## Session Continuity Last session: 2026-05-09 -Stopped at: Plan 01-01 (scaffold + test infra) complete. Phaser 4 + React 19 + Vite 8 + TS 6 scaffold builds; 15 deps installed at locked versions; 7 firewall directories ready; Vitest + Playwright wired with passing sentinel; package.json scripts pre-declared for the entire Phase 1 plan-set. Next: Wave 2 — Plans 02–06 in parallel. -Resume file: .planning/phases/01-foundations-and-doctrine/01-01-scaffold-and-test-infra-SUMMARY.md -Next action: continue `/gsd-execute-phase 1` (orchestrator dispatches Wave 2) +Stopped at: Plan 01-07 (CI workflow) complete — `.github/workflows/ci.yml` (49 lines, Node 22, ubuntu-latest, single job) runs `npm ci` + `npm run ci` on push/PR to main. Local `npm run ci` exits 0 (lint clean / 53 tests pass / validator OK / build OK). Every Phase 1 success criterion now structurally enforced on every commit. Plan 01-05 Task 2 (north-star image curation) is the only outstanding deliverable — does not block CI workflow shipping. Phase 1 awaiting `/gsd-verify-work` UAT after the curation pass. +Resume file: .planning/phases/01-foundations-and-doctrine/01-07-ci-workflow-SUMMARY.md +Next action: human curation pass on `assets/north-stars/` (Plan 01-05 Task 2), then `/gsd-verify-work` to UAT Phase 1, then `/gsd-discuss-phase 2` diff --git a/.planning/phases/01-foundations-and-doctrine/01-07-ci-workflow-SUMMARY.md b/.planning/phases/01-foundations-and-doctrine/01-07-ci-workflow-SUMMARY.md new file mode 100644 index 0000000..2090f13 --- /dev/null +++ b/.planning/phases/01-foundations-and-doctrine/01-07-ci-workflow-SUMMARY.md @@ -0,0 +1,220 @@ +--- +phase: 01-foundations-and-doctrine +plan: 07 +subsystem: ci +tags: [ci, github-actions, pipe-06, minimum-viable, solo-dev, no-ceremony] + +# Dependency graph +requires: + - phase: 01 + plan: 01 + provides: package.json with `ci` script chaining lint + test + validate:assets + build; package-lock.json (committed); Node 22 baseline + - phase: 01 + plan: 02 + provides: `npm run lint` green (ESLint flat config + boundaries plugin, --max-warnings 0) + - phase: 01 + plan: 03 + provides: `npm test` green (save layer — checksum, envelope, migrations, db, snapshots, persist, round-trip) + - phase: 01 + plan: 04 + provides: `npm test` green (content loader) + `npm run build` green (Vite-native content pipeline) + - phase: 01 + plan: 05 + provides: `npm run validate:assets` exits 0 (Task 1 validator merged; Task 2 north-star images partial — validator passes with 0 assets which is valid) + - phase: 01 + plan: 06 + provides: `npm test` green (doctrine.test.ts via extended vitest include glob) +provides: + - .github/workflows/ci.yml — single-job GitHub Actions workflow (49 lines including load-bearing comments) running `npm ci` + `npm run ci` on push to main and pull_request to main; ubuntu-latest; Node 22; actions/setup-node@v4 with cache:'npm'; timeout-minutes:10 +affects: + - "Phase 2: when economy tests + Playwright e2e (PIPE-07) land, they go through the same `npm run ci` script — the workflow file does NOT need to change. If Phase 2 wants Playwright on CI, add `npx playwright install --with-deps chromium` before the `npm run ci` step and update the `ci` script in package.json to include `&& npm run e2e`." + - "Phase 8: visual regression testing (PIPE-04) will likely require a separate workflow file (matrix runs against multiple OSes / heavier runtime) since it's a different cost profile from this single-job lint/test workflow. Do not bolt it onto ci.yml." + - "Every Phase 1 success criterion is now structurally enforced on every commit going forward: CORE-10 (Plan 02 lint), CORE-04..09 (Plan 03 + Plan 06 doctrine.test.ts), PIPE-01 (Plan 04 loader.test.ts + build), PIPE-03/AEST-08/AEST-09 (Plan 05 validate:assets + test), PIPE-05 (Plan 06 doctrine.test.ts), PIPE-06 (this workflow), CORE-01 smoke (build)." + - "Phase 1 partial item: Plan 05 Task 2 (10–20 north-star reference images) still awaits human curation. The validator passes when 0 assets are present (`[provenance] all 0 assets carry valid provenance.`); the CI workflow does NOT depend on the images being present, so it ships green today and will *continue* to be green once the images land (each carrying a valid sidecar)." + +# Tech tracking +tech-stack: + added: [] # no new deps; pure CI configuration + patterns: + - "Minimum-viable CI per CONTEXT user pushback: one job, one OS (ubuntu-latest), one Node version (22), no third-party actions beyond actions/checkout@v4 + actions/setup-node@v4. The workflow's purpose is to refuse merges that break the local `npm run ci`, nothing more." + - "CI script as single source of truth: the workflow runs `npm run ci`, defined in package.json by Plan 01 as `npm run lint && npm run test && npm run validate:assets && npm run build`. Adding new gates (e.g., e2e in Phase 2) is done by editing `package.json scripts.ci`, NOT by editing the workflow file. The workflow stays stable across all future phases." + - "Cache discipline (RESEARCH CI Pitfall A): `actions/setup-node@v4` with `cache: 'npm'` caches `~/.npm` keyed by `package-lock.json`, never `node_modules/` directly. Caching `node_modules/` is the canonical CI footgun (transitive deps go stale silently)." + - "Lockfile-strict install: `npm ci` (not `npm install`) refuses to run if `package.json` and `package-lock.json` drift. This is the standard mitigation for solo-dev supply-chain risk in Phase 1 (T-01-08, see plan threat model). `npm audit` as a CI step deferred to Phase 8 launch polish if surface area grows." + - "Comment-as-doc: the workflow file's leading 18-line comment block enumerates *what is deliberately omitted* (OS matrix, Node-version matrix, test reporters, Codecov, release automation, notification integrations) so a future contributor reading the file knows the omissions are intentional design decisions, not oversights. Per CONTEXT D-07/D-08 doctrine-as-rationale pattern." + +key-files: + created: + - .github/workflows/ci.yml (49 lines: 18-line header comment block + 4-line `name`/`on` declaration + 27-line `jobs.ci` definition with 4 steps) + modified: [] + +key-decisions: + - "Workflow stays at 49 lines (slightly over the 20-line target from RESEARCH Open Question #4) because the leading comment block is load-bearing context — it explains *why* the omissions are there so a future contributor reading the file does not 'helpfully' add a matrix or Codecov upload that would violate CONTEXT user pushback. The actual YAML logic is ~27 lines." + - "Node 22 chosen (not 20) per RESEARCH § Environment Availability: 'Node 22 ideal for native crypto.hash; Node ≥ 20 required for recursive readdir; the validator uses readdir without recursive but Node 22 is the modern baseline.' Single-version (no matrix) per CONTEXT user pushback against ceremony." + - "ubuntu-latest only (no Windows / macOS matrix). PIPE-04 visual regression testing is Phase 8; cross-OS coverage of the *idle game itself* belongs there, not here. Plan 01–06 deliverables are all platform-agnostic (TypeScript, Node, npm)." + - "Triggers limited to `push` to main and `pull_request` to main. No tag-based release triggers (no releases until Phase 2 ships Season 1 per ROADMAP). No schedule triggers (no cron/canary needs in Phase 1)." + - "timeout-minutes: 10 chosen as a sensible ceiling: local `npm run ci` runs in ~5s (lint) + ~2.5s (test) + ~0.1s (validator) + ~0.7s (build) = well under 10s for the script proper; with `npm ci` install (~30–60s on fresh CI) the realistic full run is ~1–2min. 10min ceiling catches stuck runs without false-positives on slow GitHub runners." + - "Workflow does NOT depend on Plan 05 Task 2 (north-star images). The validator passes with 0 assets (`[provenance] all 0 assets carry valid provenance.`); when human curation lands the images, the validator will continue to pass (each new asset will carry a sidecar by definition of the curation gate). This means Phase 1's CI is shippable *now* even with Plan 05 partial." + +requirements-completed: [PIPE-06] + +# Metrics +duration: 2min +completed: 2026-05-09 +--- + +# Phase 1 Plan 07: CI Workflow Summary + +**Single-job `.github/workflows/ci.yml` (49 lines) runs `npm ci` + `npm run ci` on push to main and PR to main; Node 22, ubuntu-latest, actions/setup-node@v4 with `cache: 'npm'`, 10-minute timeout. Local `npm run ci` exits 0 (lint clean, 53 tests pass across 12 files, validator green, build green). PIPE-06 structurally enforced; every Phase 1 automated check now runs on every commit going forward.** + +## Performance + +- **Plan duration:** ~2 min (single-task plan; the YAML structure was specified verbatim in the plan) +- **Local `npm run ci` runtime (immediately before commit):** + - lint: <1s (clean, no warnings, --max-warnings=0) + - test: 2.37s (53 tests / 12 files, all passing) + - validate:assets: <0.5s (0 assets, all valid) + - build: 0.66s (tsc -b + vite build) + - **Total: ~5s** (well under the 30s feedback-latency target from VALIDATION.md) +- **Expected CI runtime on GitHub:** ~1–2 min (dominated by `npm ci` install on fresh runner; the test/lint/build steps remain ~5s) + +## What Was Built + +### `.github/workflows/ci.yml` (49 lines) + +The full file: + +```yaml +# Phase 1 — minimum-viable CI per RESEARCH Open Question #4 + CONTEXT user pushback +# against ceremonial workflows (.planning/phases/01-foundations-and-doctrine/01-CONTEXT.md). +# +# On every push to main and every pull request: +# - npm ci (lockfile-strict install — refuses on package.json drift) +# - npm run ci (lint + test + validate-assets + build, defined in package.json) +# +# This single job satisfies PIPE-06: Vitest tests run on every CI build. +# Phase 2+ economy tests flow through the same `npm run ci` chain — no workflow change +# is needed when more tests are added. +# +# Deliberately omitted (per CONTEXT user pushback against ceremony): +# - OS matrix (Linux only is fine; PIPE-04 visual regression testing is Phase 8) +# - Node-version matrix (one supported version is enough for solo-dev) +# - Test reporters / Codecov uploads (no coverage requirement in Phase 1) +# - Release automation (no releases until Phase 2 ships Season 1) +# - Notification integrations (the project owner reads GitHub directly) + +name: ci + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + ci: + name: lint + test + validate-assets + build + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node 22 + uses: actions/setup-node@v4 + with: + node-version: '22' + # Per RESEARCH CI Pitfall A: cache ~/.npm based on package-lock.json, + # NEVER cache node_modules/ directly (transitive deps go stale). + cache: 'npm' + + - name: Install dependencies (lockfile-strict) + run: npm ci + + - name: Run CI suite + run: npm run ci +``` + +### Acceptance Criteria — All 11 Pass + +| # | Criterion | Result | +|---|-----------|--------| +| 1 | `.github/workflows/ci.yml` exists | OK | +| 2 | Workflow runs `npm run ci` | OK | +| 3 | Uses `actions/setup-node@v4` with `cache: 'npm'` | OK | +| 4 | Does NOT cache `node_modules/` directly (RESEARCH CI Pitfall A) | OK | +| 5 | Uses Node 22 | OK | +| 6 | Runs `npm ci` (lockfile-strict) before `npm run ci` (line 46 < line 49) | OK | +| 7 | Triggers on push to main AND pull_request to main (`branches: [main]` count = 2) | OK | +| 8 | Has sensible `timeout-minutes` (10) | OK | +| 9 | Locally `npm run ci` exits 0 (proves workflow will be green) | OK | +| 10 | Contains comments explaining what was deliberately omitted | OK | +| 11 | Single-job, single-matrix-entry, no third-party actions beyond checkout + setup-node | OK | + +## Deviations from Plan + +**None — plan executed exactly as written.** + +The plan documented the YAML verbatim and the file was authored to match. Pre-flight `npm run ci` was green; post-write acceptance checks all passed; no Rule 1/2/3 fixes needed. + +## Authentication Gates + +None. CI workflow files require no auth to author or commit; GitHub validates the YAML on push (will happen on the user's next push, not gated on this plan). + +## Phase 1 Closure — Structural Enforcement Map + +With `.github/workflows/ci.yml` landed, every Phase 1 success criterion is now enforced on every commit: + +| Success Criterion | Enforcement | Plan Source | +|-------------------|-------------|-------------| +| 1. Game scaffold builds (CORE-01) | `npm run build` (smoke) | Plan 01 + Plan 04 | +| 2. Round-trip save test passes (CORE-04..09) | `npm test` (12 test files / 53 tests / save layer covers checksum, envelope, migrations, db, snapshots, persist, round-trip) | Plan 03 | +| 3a. CI fails if `src/sim/` imports `src/render/`/`src/ui/` (CORE-10) | `npm run lint` (boundaries plugin) | Plan 02 | +| 3b. CI fails if `/content/**` violates Zod schema (PIPE-01) | `npm test` (loader.test.ts) + `npm run build` (Vite content pipeline build-time) | Plan 04 | +| 3c. CI fails if any AI asset is missing provenance (PIPE-03, AEST-08, AEST-09) | `npm run validate:assets` + `npm test` (validate-assets.test.ts) | Plan 05 (Task 1 done; Task 2 awaits curation — validator passes with 0 assets which is valid) | +| 4. Anti-FOMO + Season 7 end-state docs exist (PIPE-05, UX-13) | `npm test` (doctrine.test.ts — 8 assertions across 2 docs) | Plan 06 | +| 5. North-star reference set + curation gate (AEST-08, AEST-09) | Validator + sidecar gate landed; 10–20 images await human curation (Plan 05 Task 2 — checkpoint:human-verify) | Plan 05 (partial) | +| (Cross-cutting) PIPE-06: Vitest runs on every CI build | `.github/workflows/ci.yml` runs `npm run ci` on push + PR | This plan | + +## Phase 1 Open Item Tracking + +- **Plan 05 Task 2 (north-star images):** Awaits human curation per the checkpoint. The CI workflow ships green *today* because the validator passes with 0 assets (`[provenance] all 0 assets carry valid provenance.`). When the user curates and commits the 10–20 images, each will carry a valid sidecar by definition of the curation gate, and the validator will continue to pass — no changes to `ci.yml` needed. + +## Phase 2 Handoff Notes + +When Phase 2 lands: + +1. **Adding economy tests:** Drop new `*.test.ts` files anywhere in the repo's existing `vitest` include glob (`src/**/*.test.ts`, `scripts/**/*.test.ts`). They will run automatically as part of `npm test` → `npm run ci` → CI workflow. **No workflow file change needed.** + +2. **Adding Playwright e2e (PIPE-07):** Two changes: + - In `package.json`: extend `scripts.ci` to include `&& npm run e2e` (or chain it however Phase 2 prefers). + - In `.github/workflows/ci.yml`: add a new step *before* `Run CI suite`: + ```yaml + - name: Install Playwright browsers + run: npx playwright install --with-deps chromium + ``` + This is the canonical pattern for Playwright on GitHub Actions ubuntu-latest. No matrix needed for Phase 2; visual regression matrix is Phase 8. + +3. **Phase 8 visual regression testing (PIPE-04):** Likely warrants a *separate* workflow file (e.g., `.github/workflows/visual-regression.yml`) — different cost profile (multi-OS matrix, snapshot uploads, possibly nightly schedule). Do NOT bolt it onto `ci.yml`; keep `ci.yml` as the fast PR-blocking gate. + +## Threat Model — T-01-08 Mitigation Confirmed + +The plan's threat model called out T-01-08 (npm install supply-chain compromise via transitive dep) with disposition **mitigate**. The mitigation is in place: + +- `package-lock.json` is committed (Plan 01). +- `.github/workflows/ci.yml` uses `npm ci` (not `npm install`), which refuses to run if `package.json` and `package-lock.json` drift. +- This is the standard solo-dev supply-chain mitigation per RESEARCH § Security Domain. +- `npm audit` as a CI step deferred to Phase 8 launch polish if surface area grows (deliberately deferred to keep Phase 1 minimum-viable per CONTEXT user pushback). + +## Threat Flags + +None. The workflow file introduces no new network endpoints, auth paths, file access patterns, or schema changes at trust boundaries. It only invokes existing `npm` commands that were already in scope. + +## Self-Check: PASSED + +- File exists: FOUND `.github/workflows/ci.yml` +- Commit exists: FOUND `609d582` (`ci(01-07): minimum-viable GitHub Actions workflow running npm run ci on push + PR (PIPE-06)`) +- All 11 acceptance criteria from PLAN green (see "Acceptance Criteria" table above) +- Pre-flight `npm run ci` exit 0 (lint clean / 53 tests pass / validator OK / build OK) +- No deletions in commit +- No unintended untracked files (only pre-existing `.claude/` local config) diff --git a/.planning/phases/01-foundations-and-doctrine/01-VALIDATION.md b/.planning/phases/01-foundations-and-doctrine/01-VALIDATION.md index 110f274..ea21d86 100644 --- a/.planning/phases/01-foundations-and-doctrine/01-VALIDATION.md +++ b/.planning/phases/01-foundations-and-doctrine/01-VALIDATION.md @@ -1,11 +1,12 @@ --- phase: 1 slug: foundations-and-doctrine -status: planned +status: executed (12 of 13 tasks green; 01-05-T2 partial — awaiting human curation of north-star images) nyquist_compliant: true -wave_0_complete: pending-execution +wave_0_complete: yes (all Wave 0 test infrastructure landed across Plans 01–06; CI workflow Plan 07 enforces the suite) created: 2026-05-08 -updated: 2026-05-08 (populated by /gsd-plan-phase) +updated: 2026-05-09 (per-task table populated by Plan 07 executor) +approval: approved --- # Phase 1 — Validation Strategy @@ -42,20 +43,20 @@ updated: 2026-05-08 (populated by /gsd-plan-phase) | Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status | |---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------| -| 01-01-T1 | 01 | 1 | CORE-01 | — | Scaffold builds | smoke | `npm run build` | post-execution | ⬜ pending | -| 01-01-T2 | 01 | 1 | (infra) | — | Vitest + Playwright wired | smoke | `npm test && npx playwright --version` | post-execution | ⬜ pending | -| 01-02-T1 | 02 | 2 | CORE-10 | — | ESLint flat config + boundaries plugin in place | static-analysis | `npm run lint` | post-execution | ⬜ pending | -| 01-02-T2 | 02 | 2 | CORE-10 | — | Boundary rule fires on `sim → render` import | unit (lint) | `npx vitest run src/sim/__test_violation__/lint-firewall.test.ts` | post-execution | ⬜ pending | -| 01-03-T1 | 03 | 2 | CORE-06, CORE-07 | T-01-01 | CRC-32 envelope + canonical JSON; v0→v1 synthetic migration | unit | `npx vitest run src/save/checksum.test.ts src/save/envelope.test.ts src/save/migrations.test.ts` | post-execution | ⬜ pending | -| 01-03-T2 | 03 | 2 | CORE-04, CORE-05, CORE-08 | T-01-01 | idb DB + LocalStorageDBAdapter fallback (CORE-04) + last-3 snapshot retention + persist API | unit | `npx vitest run src/save/db.test.ts src/save/snapshots.test.ts src/save/persist.test.ts` | post-execution | ⬜ pending | -| 01-03-T3 | 03 | 2 | CORE-09, CORE-04 | T-01-02 | Base64 codec with 50MB DoS cap + full round-trip | unit + integration | `npx vitest run src/save/round-trip.test.ts && npm run build` | post-execution | ⬜ pending | -| 01-04-T1 | 04 | 2 | PIPE-01, STRY-09 | — | Vite-native loader + Zod schemas + demo fragment | smoke | `npm run build && npm run compile:ink` | post-execution | ⬜ pending | -| 01-04-T2 | 04 | 2 | PIPE-01 | — | Schema violation throws (build fails on bad content) | unit | `npx vitest run src/content/loader.test.ts` | post-execution | ⬜ pending | -| 01-05-T1 | 05 | 2 | PIPE-03, AEST-08, AEST-09 | T-01-06, T-01-07 | Validator script + sidecar schema + refused-sample fixture (test fixture isolated under os.tmpdir()) | integration | `node scripts/validate-assets.mjs && npx vitest run scripts/validate-assets.test.ts` | post-execution | ⬜ pending | -| 01-05-T2 | 05 | 2 | AEST-08, AEST-09 | T-01-06 | 10–20 north-star reference images committed with sidecars | manual + smoke | `node scripts/validate-assets.mjs` (count assertion) | post-execution | ⬜ pending (checkpoint) | -| 01-06-T1 | 06 | 2 | PIPE-05, UX-13 | — | anti-FOMO doctrine consolidates 4 source documents (file exists with required H2 sections) | smoke | `test -f .planning/anti-fomo-doctrine.md && grep -q '## Banned Mechanics' .planning/anti-fomo-doctrine.md` | post-execution | ⬜ pending | -| 01-06-T2 | 06 | 2 | PIPE-05, STRY-09 | — | Season 7 end-state doctrine principle-level + doc-lint test | doc-lint | `npx vitest run scripts/doctrine.test.ts` | post-execution | ⬜ pending | -| 01-07-T1 | 07 | 3 | PIPE-06 | T-01-08 | GitHub Actions workflow runs `npm run ci` on push + PR | smoke (CI) | `npm run ci` (locally) + workflow runs on next push | post-execution | ⬜ pending | +| 01-01-T1 | 01 | 1 | CORE-01 | — | Scaffold builds | smoke | `npm run build` | ✓ committed | ✅ green | +| 01-01-T2 | 01 | 1 | (infra) | — | Vitest + Playwright wired | smoke | `npm test && npx playwright --version` | ✓ committed | ✅ green | +| 01-02-T1 | 02 | 2 | CORE-10 | — | ESLint flat config + boundaries plugin in place | static-analysis | `npm run lint` | ✓ committed | ✅ green | +| 01-02-T2 | 02 | 2 | CORE-10 | — | Boundary rule fires on `sim → render` import | unit (lint) | `npx vitest run src/sim/__test_violation__/lint-firewall.test.ts` | ✓ committed | ✅ green | +| 01-03-T1 | 03 | 2 | CORE-06, CORE-07 | T-01-01 | CRC-32 envelope + canonical JSON; v0→v1 synthetic migration | unit | `npx vitest run src/save/checksum.test.ts src/save/envelope.test.ts src/save/migrations.test.ts` | ✓ committed | ✅ green | +| 01-03-T2 | 03 | 2 | CORE-04, CORE-05, CORE-08 | T-01-01 | idb DB + LocalStorageDBAdapter fallback (CORE-04) + last-3 snapshot retention + persist API | unit | `npx vitest run src/save/db.test.ts src/save/snapshots.test.ts src/save/persist.test.ts` | ✓ committed | ✅ green | +| 01-03-T3 | 03 | 2 | CORE-09, CORE-04 | T-01-02 | Base64 codec with 50MB DoS cap + full round-trip | unit + integration | `npx vitest run src/save/round-trip.test.ts && npm run build` | ✓ committed | ✅ green | +| 01-04-T1 | 04 | 2 | PIPE-01, STRY-09 | — | Vite-native loader + Zod schemas + demo fragment | smoke | `npm run build && npm run compile:ink` | ✓ committed | ✅ green | +| 01-04-T2 | 04 | 2 | PIPE-01 | — | Schema violation throws (build fails on bad content) | unit | `npx vitest run src/content/loader.test.ts` | ✓ committed | ✅ green | +| 01-05-T1 | 05 | 2 | PIPE-03, AEST-08, AEST-09 | T-01-06, T-01-07 | Validator script + sidecar schema + refused-sample fixture (test fixture isolated under os.tmpdir()) | integration | `node scripts/validate-assets.mjs && npx vitest run scripts/validate-assets.test.ts` | ✓ committed | ✅ green | +| 01-05-T2 | 05 | 2 | AEST-08, AEST-09 | T-01-06 | 10–20 north-star reference images committed with sidecars | manual + smoke | `node scripts/validate-assets.mjs` (count assertion) | ⚠ partial | ⬜ pending (checkpoint:human-verify — awaiting human curation; validator passes with 0 assets, will continue passing once images land with sidecars) | +| 01-06-T1 | 06 | 2 | PIPE-05, UX-13 | — | anti-FOMO doctrine consolidates 4 source documents (file exists with required H2 sections) | smoke | `test -f .planning/anti-fomo-doctrine.md && grep -q '## Banned Mechanics' .planning/anti-fomo-doctrine.md` | ✓ committed | ✅ green | +| 01-06-T2 | 06 | 2 | PIPE-05, STRY-09 | — | Season 7 end-state doctrine principle-level + doc-lint test | doc-lint | `npx vitest run scripts/doctrine.test.ts` | ✓ committed | ✅ green | +| 01-07-T1 | 07 | 3 | PIPE-06 | T-01-08 | GitHub Actions workflow runs `npm run ci` on push + PR | smoke (CI) | `npm run ci` (locally) + workflow runs on next push | ✓ committed | ✅ green (local `npm run ci` exits 0 immediately before commit; GitHub-side workflow validation occurs on next push to main) | *Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*