--- phase: 01 plan: 07 type: execute wave: 3 depends_on: [01-01, 01-02, 01-03, 01-04, 01-05, 01-06] files_modified: - .github/workflows/ci.yml autonomous: true requirements: [PIPE-06] must_haves: truths: - "A GitHub Actions workflow at `.github/workflows/ci.yml` runs `npm ci` (lockfile-strict install) then `npm run ci` (lint + test + validate-assets + build) on every push to main and every pull request" - "The workflow uses Node 22.x (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)" - "The workflow uses `actions/setup-node@v4` with `cache: 'npm'` (per RESEARCH § CI Pitfall A — never cache `node_modules/` directly)" - "The workflow runs successfully on the post-Plan-06 codebase, verifying that PIPE-06's contract (Vitest covers all save migrations and runs on every CI build) is enforced as the CI job" artifacts: - path: .github/workflows/ci.yml provides: "Minimum-viable CI workflow per RESEARCH Open Question #4 (~20-line) — single job, single matrix entry, npm ci + npm run ci" contains: "npm run ci" key_links: - from: .github/workflows/ci.yml to: package.json scripts.ci via: "Workflow runs `npm run ci` which is `npm run lint && npm run test && npm run validate:assets && npm run build`" pattern: "npm run ci" --- Ship the minimum-viable CI workflow per RESEARCH Open Question #4: a single GitHub Actions YAML at `.github/workflows/ci.yml` that on every push to `main` and every pull request runs `npm ci` (lockfile-strict install) followed by `npm run ci` (lint + test + validate-assets + build). This wires Plans 02–06's automated checks into a single CI job. Per CONTEXT user pushback against ceremonial workflows: NO matrix builds across OSes, NO matrix builds across Node versions, NO test reporters, NO release automation, NO Codecov uploads — just one job that goes green or red. PIPE-06's contract — "Project ships unit tests (Vitest) covering all save migrations and core economy formulas, run on every CI build" — is satisfied because Plan 03 authored the migration tests and `npm run ci` runs them. Phase 1 has no economy formulas yet (Phase 2 deliverable), so PIPE-06 in Phase 1 is "the CI runs Vitest on every PR/push." Phase 2+ will add economy tests that flow through this same workflow. Purpose: This is the structural enforcement of PIPE-06 and the closing arc of Phase 1 — Plans 01–06 all ship their own automated checks; this plan ensures those checks actually run on every commit going forward. Output: One YAML file. Wave 3 by definition because it can only land after Plans 02 (lint), 03 (test), 04 (build), 05 (validate-assets), 06 (doc-lint) are all green — running before any of those would fail. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.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 @.planning/phases/01-foundations-and-doctrine/01-01-SUMMARY.md @.planning/phases/01-foundations-and-doctrine/01-02-SUMMARY.md @.planning/phases/01-foundations-and-doctrine/01-03-SUMMARY.md @.planning/phases/01-foundations-and-doctrine/01-04-SUMMARY.md @.planning/phases/01-foundations-and-doctrine/01-05-SUMMARY.md @.planning/phases/01-foundations-and-doctrine/01-06-SUMMARY.md @CLAUDE.md Task 1: Author `.github/workflows/ci.yml` (~25 lines per RESEARCH Open Question #4) .github/workflows/ci.yml - .planning/phases/01-foundations-and-doctrine/01-RESEARCH.md § "Open Questions #4" (20-line minimum-viable `.github/workflows/ci.yml` recommendation), § "Common Pitfalls (CI / Tooling Specific)" CI Pitfall A (use `actions/setup-node@v4` with `cache: 'npm'`, never cache `node_modules/`), CI Pitfall B (`--passWithNoTests=false` already on `npm run test` from Plan 01), CI Pitfall C (`--max-warnings 0` already on `npm run lint` from Plan 01) - .planning/phases/01-foundations-and-doctrine/01-RESEARCH.md § "Environment Availability" (Node 22.x ideal) - .planning/phases/01-foundations-and-doctrine/01-CONTEXT.md user pushback: solo dev, minimum-viable, no ceremonial workflows - package.json (verify `npm run ci` script exists from Plan 01 and chains lint+test+validate:assets+build) - All 6 prior SUMMARY files (verify each plan's artifacts are committed and tests are green BEFORE writing this workflow — this plan must NOT land if any prior plan's tests fail) **Step 0 — Sanity check that all upstream plans landed green.** Run locally: ```bash npm run ci ``` This MUST exit 0 before this plan's workflow lands. If it does not, the failing plan needs revision before this plan proceeds. **Step 1 — Create the directory:** ```bash mkdir -p .github/workflows ``` **Step 2 — Write `.github/workflows/ci.yml`** using the Write tool: ```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 ``` **Concrete shape per RESEARCH Open Question #4:** ~25 lines (slightly over the 20-line target because the comment block is load-bearing context for future maintainers). This is single-job, single-matrix-entry, no third-party actions beyond `actions/checkout@v4` + `actions/setup-node@v4`. **Step 3 — Validate the YAML locally** (without pushing): ```bash # If `actionlint` is not installed: skip; the workflow will be validated by GitHub on push. actionlint .github/workflows/ci.yml 2>/dev/null || echo "actionlint not installed; will validate on push" ``` **Step 4 — Local sanity check that `npm run ci` exits 0** (it should, since Plan 06 was green; this is the second time we run it just to be sure): ```bash npm run ci ``` Confirm exit code 0 with output containing: - `[lint]` or ESLint pass message - `[test]` or Vitest pass message (some N tests passed) - `[provenance] all assets carry valid provenance.` - `[build]` or Vite build success message **Step 5 — Commit `ci(01-07): minimum-viable GitHub Actions workflow running npm run ci on push + PR (PIPE-06)`.** **Step 6 (optional, only if the user has set up the GitHub remote):** push the branch and verify the workflow runs green on GitHub. Per CONTEXT user pushback, do NOT block this plan on the push — local `npm run ci` green is sufficient evidence that the workflow will run green when the user next pushes. test -f .github/workflows/ci.yml && grep -q "npm run ci" .github/workflows/ci.yml && grep -q "actions/setup-node@v4" .github/workflows/ci.yml && grep -q "cache: 'npm'" .github/workflows/ci.yml && npm run ci - `.github/workflows/ci.yml` exists — verify with `test -f .github/workflows/ci.yml`. - The workflow runs `npm run ci` — verify with `grep -q "npm run ci" .github/workflows/ci.yml`. - The workflow uses `actions/setup-node@v4` with `cache: 'npm'` — verify with `grep -q "actions/setup-node@v4" .github/workflows/ci.yml && grep -q "cache: 'npm'" .github/workflows/ci.yml`. - The workflow does NOT cache `node_modules/` directly (RESEARCH CI Pitfall A) — verify with `! grep -E "cache: 'node_modules" .github/workflows/ci.yml`. - The workflow uses Node 22 — verify with `grep -E "node-version: '22'" .github/workflows/ci.yml`. - The workflow runs `npm ci` (lockfile-strict) before `npm run ci` — verify with `grep -E "run: npm ci" .github/workflows/ci.yml` and that the `npm ci` step appears before the `npm run ci` step (`grep -n` line numbers ascending). - The workflow triggers on `push` to `main` AND `pull_request` to `main` — verify with `grep -E "branches: \\[main\\]" .github/workflows/ci.yml | wc -l` returns 2 (one for push, one for pull_request). - The workflow has a sensible `timeout-minutes` (10 is the recommended ceiling for Phase 1's ~30s runtime) — verify with `grep -q "timeout-minutes:" .github/workflows/ci.yml`. - Locally `npm run ci` exits 0 — proves the workflow will be green on push. - The workflow contains comments explaining what was deliberately omitted (no matrix, no codecov, no release automation) per CONTEXT user pushback — verify with `grep -qE "Deliberately omitted|matrix" .github/workflows/ci.yml`. `.github/workflows/ci.yml` authored as a minimum-viable single-job workflow running `npm ci` + `npm run ci` on push to main and PR; uses `actions/setup-node@v4` with npm caching per RESEARCH CI Pitfall A; Node 22; ~25 lines + load-bearing comments; locally `npm run ci` exits 0 proving the workflow will be green; commit landed. | Threat ID | Category | Component | Disposition | Mitigation Plan | |-----------|----------|-----------|-------------|-----------------| | T-01-08 | Tampering | npm install supply-chain (a transitive dep gets compromised) | mitigate | `package-lock.json` is committed (Plan 01); `npm ci` in this workflow refuses if lockfile and `package.json` drift; per RESEARCH § Security Domain, this is the standard mitigation for solo-dev supply-chain risk in Phase 1. Phase 8 launch polish may add `npm audit` as a CI step if surface area grows. | - Local `npm run ci` exits 0 (the workflow is a thin shell around the same script that runs locally). - `.github/workflows/ci.yml` is well-formed YAML (validated by GitHub on push). - All Phase-1 success criteria are now structurally enforced on every commit going forward: - CORE-10 firewall via `npm run lint` (Plan 02) - CORE-04 through CORE-09 via `npm test` (Plan 03 + Plan 06's doctrine.test.ts) - PIPE-01 via `npm run build` + `npm test` (Plan 04 loader.test.ts) - PIPE-03 + AEST-08 + AEST-09 via `npm run validate:assets` + `npm test` (Plan 05) - PIPE-05 via `npm test` (Plan 06 doctrine.test.ts) - PIPE-06 via this workflow (Vitest runs on every CI build) - CORE-01 via `npm run build` (smoke; Phase 2 PIPE-07 adds Playwright load-time spec) - `.github/workflows/ci.yml` runs `npm ci && npm run ci` on push to main and PR. - All Plan 01–06 automated checks now run on every commit. - PIPE-06's "Vitest tests run on every CI build" is structurally satisfied. - Phase 2 inherits the same workflow without modification — adding economy tests just adds them to `npm test`. After completion, create `.planning/phases/01-foundations-and-doctrine/01-07-SUMMARY.md` documenting: - The exact workflow shape (~25 lines). - Node version chosen (22). - Confirmation that local `npm run ci` exits 0 immediately before this plan's commit. - Note for 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 to run 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`. - Note for Phase 8: visual regression testing (PIPE-04) will likely require a separate workflow file (matrix runs against multiple OSes) since it's a different cost profile from this single-job lint/test workflow. Then update `.planning/phases/01-foundations-and-doctrine/01-VALIDATION.md` per-task table (the skeleton populated as plans were written): for each Plan 01–07 task, fill in one row mapping Task ID → Plan → Wave → Requirement → Test Type → Automated Command → File Exists → Status. Set `nyquist_compliant: true` in the frontmatter and approval to "approved" once all rows are filled.