Files
josh 8ace3db7b4 docs(01-07): complete ci-workflow plan + Phase 1 closure metadata
- 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)
2026-05-09 00:00:23 -04:00

221 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 (1020 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 0106 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 (~3060s on fresh CI) the realistic full run is ~12min. 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:** ~12 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; 1020 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 1020 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)