Files
TheLastGarden/.planning/phases/01-foundations-and-doctrine/01-07-ci-workflow-PLAN.md
T
josh 39563f6934 docs(01): plan phase 1 — 7 plans across 3 waves, verified after 1 revision
Wave 1: Plan 01 (scaffold + test infra)
Wave 2: Plans 02 (eslint firewall), 03 (save layer), 04 (content pipeline),
        05 (asset provenance — autonomous:false human-curate checkpoint),
        06 (doctrine docs)
Wave 3: Plan 07 (CI workflow)

All 16 Phase-1 REQ-IDs covered. Plan-checker found 4 blockers + 6 warnings
on first pass; revision iteration 1 landed all 10 fixes; iteration 2
returned VERIFICATION PASSED. Two orchestrator judgment calls during
revision: (1) implement CORE-04 localStorage fallback in Phase 1 (the
literal requirement and ROADMAP success criterion #2 both call for it),
(2) reclassify STRY-09 as vacuously satisfied in Phase 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 23:09:08 -04:00

14 KiB
Raw Blame History

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
01 07 execute 3
01-01
01-02
01-03
01-04
01-05
01-06
.github/workflows/ci.yml
true
PIPE-06
truths artifacts key_links
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
path provides contains
.github/workflows/ci.yml Minimum-viable CI workflow per RESEARCH Open Question #4 (~20-line) — single job, single matrix entry, npm ci + npm run ci npm run ci
from to via pattern
.github/workflows/ci.yml package.json scripts.ci Workflow runs `npm run ci` which is `npm run lint && npm run test && npm run validate:assets && npm run build` 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 0206'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 0106 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.

<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>

@.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 <N> 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_model>

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.
</threat_model>
- 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)

<success_criteria>

  • .github/workflows/ci.yml runs npm ci && npm run ci on push to main and PR.
  • All Plan 0106 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. </success_criteria>
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 0107 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.