Files
2026-05-27 23:29:53 +01:00

52 lines
3.8 KiB
Markdown

## 0. Pre-flight (non-negotiable)
- [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each)
- [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
- [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest.
## 1. Catalog and tooling setup
- [ ] 1.1 Add `@stryker-mutator/core` and `@stryker-mutator/vitest-runner` to root `package.json` `catalogs.testing` (no bare versions per `openspec/AGENTS.md` §1)
- [ ] 1.2 Run `bun install`; confirm lockfile updates cleanly
- [ ] 1.3 Add `test:mutation` task to root `turbo.json` with `dependsOn: ["test:coverage"]` so 100% line coverage is a precondition
- [ ] 1.4 Document the foundation-package set in `openspec/specs/testing/spec.md` once this change is folded; the same enumeration appears in the spec delta in this folder
## 2. Per-package Stryker configuration
- [ ] 2.1 Author a reusable `stryker.base.conf.cjs` template under `tooling/stryker/` (path TBD) that every package extends — testRunner: `vitest`, reporters: `html, json, clear-text`, mutate exclusions per design D4
- [ ] 2.2 For every `@suaveplan/*` package, create `stryker.conf.json` at the package root extending the base template, declaring `mutate: ["src/**/*.ts"]` and the package-specific exclusions
- [ ] 2.3 For every package, add a `test:mutation` script in `package.json` invoking Stryker against the package's `vitest.config.ts`
## 3. Threshold enforcement
- [ ] 3.1 Encode the foundation-package list in the base config via a tiered `thresholds` block (≥ 85% for foundation, ≥ 70% otherwise)
- [ ] 3.2 Wire a CI step that fails the build on `mutationScore` below the package's tier threshold
- [ ] 3.3 Wire the PR-scoped mutation run via `--mutate` filtered to files changed in the PR (resolved through `git diff --name-only origin/main...HEAD`)
## 4. Reporter and artefacts
- [ ] 4.1 Configure HTML + JSON reporters; archive both as CI artefacts per nightly run
- [ ] 4.2 Author a `scripts/report-mutants.ts` that reads the JSON report and emits a Markdown table (path, line, mutator, status) for the PR comment
- [ ] 4.3 Wire the PR-comment step to post the table via `gh pr comment` (or workflow equivalent)
## 5. Custom-mutator hook (extension point)
- [ ] 5.1 If a custom Stryker mutator or runner adapter is required (e.g. once a bun-test runner exists), package it as `@suaveplan/testing-mutation` under `packages/testing/`
- [ ] 5.2 Errors thrown by the adapter MUST extend `TestingError` with codes prefixed `TESTING.MUTATION.*` (e.g. `TESTING.MUTATION.RUNNER_FAILED`, `TESTING.MUTATION.CONFIG_INVALID`)
- [ ] 5.3 The adapter package itself MUST meet 100% Istanbul coverage and pass the same mutation-score tier it advertises
## 6. Spec delta and validation
- [ ] 6.1 `openspec validate enterprise-testing-mutation --type change` passes
- [ ] 6.2 Fold `specs/testing/spec.md` ADDED Requirements into `openspec/specs/testing/spec.md`
- [ ] 6.3 Move this change folder to `openspec/archive/<yyyy-mm-dd>-enterprise-testing-mutation/`
## 7. Rollout
- [ ] 7.1 Run baseline mutation analysis across every existing genesis package; record current scores
- [ ] 7.2 For each package below its tier threshold, file a triage issue listing surviving mutants by mutator class
- [ ] 7.3 Land assertion-strengthening fixes per package until every existing package meets its tier threshold
- [ ] 7.4 Flip the CI gate from advisory to enforcing once every package is green