Skip to content

feat: changed-file mutation gate as a second required PR check (D-027) - #12

Merged
nzneit merged 19 commits into
mainfrom
mutation-pr-gate
Aug 5, 2026
Merged

feat: changed-file mutation gate as a second required PR check (D-027)#12
nzneit merged 19 commits into
mainfrom
mutation-pr-gate

Conversation

@nzneit

@nzneit nzneit commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Implements docs/superpowers/specs/2026-08-04-mutation-pr-gate-design.md: scripts/mutation-gate.mjs + .github/workflows/mutation.yml (the portable two-file unit), changed-file mode gating on zero undetected mutants, loud-skip over the size threshold with mutate-force/mutate-skip label overrides, incremental mode for adopters, report artifact on failure. Rehearsed end to end on a scratch PR (red on a planted survivor, green after the kill, both labels, skip-size, sticky comment upsert, artifact); concurrency and threshold set from the measured rate (D-027).

The rehearsal also surfaced two gate-blocking stryker.conf.json issues (fixed: tsconfigFile sentinel no-op for the TS7 crash, bun.timeout for the dry run) and one post-D-011 drift survivor at engine/index.ts:311 (killed; full engine recertified clean) — see D-027.

nzneit added 19 commits August 4, 2026 21:22
Task 10 rehearsal (scratch PR #11, closed without merging): concurrency 1
hit the 15-minute job timeout at a 409-line mutate set with no report
produced; concurrency 4 completed the same set cleanly in 7.7 min at
27.5 mutants/min, with no coverage-correlation warnings in the log.
Concurrency 4 ships via MUTATION_GATE_EXTRA_ARGS. Derived sustainable
threshold (27.5 * 12 / 0.5, rounded) is 700 lines, within 2x of the
existing 800 default, so thresholdLines stays unchanged.

Also carries back two stryker.conf.json fixes the rehearsal found
necessary for the gate to run in CI at all (not rehearsal-specific,
so they belong here rather than staying scratch-only):
- tsconfigFile pointed at a nonexistent path, sidestepping a crash in
  Stryker 9.6.1's TSConfigPreprocessor (ts.parseConfigFileTextToJson,
  removed from TypeScript 7's module surface per D-022) that fired on
  every invocation regardless of which files were mutated
- bun.timeout raised to 120s so the dry run's full-suite pass (~68-90s
  observed in CI) survives the runner plugin's own internal process
  timeout, which otherwise killed it well before Stryker's own
  dryRunTimeoutMinutes ever applied
@nzneit
nzneit merged commit d20b749 into main Aug 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant