Two-workflow split per ADR-020:
.github/workflows/ci.yml (existing, extended):
- checkout now uses fetch-depth: 0 so coverage:diff can resolve
origin/<base-ref>...HEAD against the PR's base branch
- new step "Coverage — aggregate (L2)" runs after the test step
(with `if: always()` so the artifact still captures partial state
on test failures)
- new step "Coverage — diff (L1)" runs only on pull_request events,
diffing against origin/${{ github.base_ref }}
- artifact upload extended to include the aggregated
coverage/lcov.info and coverage/summary.json alongside the
per-package files
.github/workflows/coverage-snapshot.yml (new):
- dedicated workflow with `permissions: contents: write` so it can
commit the aggregated coverage/summary.json back to main after
each merge — the committed trend store (ADR-020 L2)
- runs full test + aggregate, then commits summary.json only if it
actually changed (commit body marked [skip ci] so the snapshot
doesn't recurse into itself)
- concurrency: coverage-snapshot ensures only one snapshot at a time
This closes the CI side of the coverage architecture. PRs now fail
fast when changed lines are uncovered, and main's trend history
accumulates automatically.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Runs typecheck + lint + boundaries + test (with coverage) + build
on every push to main and every PR. Postgres service for tests that
need DB. Playwright e2e and Storybook smoke tests gated on validate
job passing. Coverage uploaded as artifact (lcov format) for downstream
tools (Codecov, etc.) — wiring left to template users.
Spec: §6.11