- 01-07-ci-workflow-SUMMARY.md: structural enforcement map, Phase 2/8 handoff notes, threat T-01-08 mitigation confirmed - 01-VALIDATION.md: per-task table populated (12/13 green, 01-05-T2 partial — checkpoint:human-verify awaiting north-star image curation); status flipped to executed - ROADMAP.md: progress table marks Phase 1 as 7/7 with 01-05 partial annotation - STATE.md: position advanced to Plan 7 of 7 complete; performance trend; Plan 01-05 Task 2 explicitly tracked as the only outstanding deliverable; next action = human curation pass then /gsd-verify-work - REQUIREMENTS.md: PIPE-06 marked complete (CI workflow runs Vitest on every push/PR)
15 KiB
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
ciscript chaining lint + test + validate:assets + build; package-lock.json (committed); Node 22 baseline - phase: 01
plan: 02
provides:
npm run lintgreen (ESLint flat config + boundaries plugin, --max-warnings 0) - phase: 01
plan: 03
provides:
npm testgreen (save layer — checksum, envelope, migrations, db, snapshots, persist, round-trip) - phase: 01
plan: 04
provides:
npm testgreen (content loader) +npm run buildgreen (Vite-native content pipeline) - phase: 01
plan: 05
provides:
npm run validate:assetsexits 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 testgreen (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 cion 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 ciscript — the workflow file does NOT need to change. If Phase 2 wants Playwright on CI, addnpx playwright install --with-deps chromiumbefore thenpm run cistep and update theciscript 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
pushto main andpull_requestto 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 ciruns in ~5s (lint) + ~2.5s (test) + ~0.1s (validator) + ~0.7s (build) = well under 10s for the script proper; withnpm ciinstall (~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 ciruntime (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 ciinstall on fresh runner; the test/lint/build steps remain ~5s)
What Was Built
.github/workflows/ci.yml (49 lines)
The full file:
# 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 toci.ymlneeded.
Phase 2 Handoff Notes
When Phase 2 lands:
-
Adding economy tests: Drop new
*.test.tsfiles anywhere in the repo's existingvitestinclude glob (src/**/*.test.ts,scripts/**/*.test.ts). They will run automatically as part ofnpm test→npm run ci→ CI workflow. No workflow file change needed. -
Adding Playwright e2e (PIPE-07): Two changes:
- In
package.json: extendscripts.cito include&& npm run e2e(or chain it however Phase 2 prefers). - In
.github/workflows/ci.yml: add a new step beforeRun CI suite:This is the canonical pattern for Playwright on GitHub Actions ubuntu-latest. No matrix needed for Phase 2; visual regression matrix is Phase 8.- name: Install Playwright browsers run: npx playwright install --with-deps chromium
- In
-
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 ontoci.yml; keepci.ymlas 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.jsonis committed (Plan 01)..github/workflows/ci.ymlusesnpm ci(notnpm install), which refuses to run ifpackage.jsonandpackage-lock.jsondrift.- This is the standard solo-dev supply-chain mitigation per RESEARCH § Security Domain.
npm auditas 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 ciexit 0 (lint clean / 53 tests pass / validator OK / build OK) - No deletions in commit
- No unintended untracked files (only pre-existing
.claude/local config)