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>
14 KiB
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 |
|
|
true |
|
|
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.
<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> |
<success_criteria>
.github/workflows/ci.ymlrunsnpm ci && npm run cion 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. </success_criteria>
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.