Skip to content

ci: shard the pull request mutation gate, and skip it where nothing it tests changed - #467

Merged
ExtraToast merged 2 commits into
mainfrom
ci/464-shard-pr-mutation
Oct 16, 2026
Merged

ExtraToast merged 2 commits into
mainfrom
ci/464-shard-pr-mutation

Conversation

@ExtraToast

Copy link
Copy Markdown
Contributor

Summary

The pull request's mutation gate now runs as six parallel shards and one merging job, and a pull request that changes nothing the gate reads runs no shard at all.

  • Shards by top-level statement. scripts/mutation-shard.ts hands each shard a disjoint share of every module's top-level statements as --mutate line ranges, weighed by runtime syntax nodes (which track per-statement mutant counts at r = 0.96). Stryker mutates only a node a range holds whole, and every node sits inside one top-level statement, so every mutant lands in exactly one shard. Each file is spread over every shard, so a change that re-tests one module re-tests it in parallel. The weekly full run uses the same split.
  • One merged report. In incremental mode every shard's report also carries the other shards' mutants over from main's baseline. scripts/mutation-merge.ts keeps each mutant only from the shard whose range holds it, merges the test lists, decides the score against the break threshold, and names every survivor. On a push to main that merged report is the mutation-incremental baseline.
  • Skip where nothing changed. scripts/mutation-scope.ts compares the merge commit with its first parent. A release (version fields only), docs or emf/ change runs no shard, and Mutation passes on main's result. src/, test/, the Stryker and Vitest configuration, tsconfig.json, .nvmrc, the setup action, ci.yml, the gate's own scripts, and any dependency change still run it. A push to main always runs.
  • Wiring. Pipeline Complete needs only Mutation, which never skips and fails when the scope job or any shard did not succeed. RULE-075 and test/pipeline-wiring.test.ts hold that; ADR 0063, RULE-064, docs/architecture.md, REQ-063 and REQ-064 say what the gate now is.

To know:

  • One statement is the floor. INVARIANTS in src/check/union.ts (about 353 of the file's 648 mutants) cannot be split without dropping the mutant of every node that spans the cut. A change that re-tests every mutant of union.ts waits on that statement, about half of today's time rather than a third; a change spread like feat: deliver the database credential an edge derives, as itself or to the environment #462's (2,374 mutants re-tested) should take about a sixth plus setup. This run is the first real timing.
  • mutation-survivors.ts now reads every shard's part of one file: with range shards, two weekly reports can each hold part of a file, and the old merge by file name kept only one.

Closes #464

Verification

  • npm run verify passes, and actionlint is clean.
  • Six real Stryker shards on main commit 4ec2ea2, against that commit's own baseline, then merged: 7,798 mutants, none missing or extra, no status changed, 1,125 tests. Fed back to Stryker as the baseline, it reuses exactly as main's own report does.
  • The scope check over main's last twelve commits skips the three releases and the docs and emf/ commits, and runs every commit that touches src/ or test/.

…t tests changed

The pull request's mutation run is now six parallel shards, each mutating a
disjoint share of every module's top-level statements, run incrementally
against the last green report on main. A merging job takes each mutant from
the shard whose range holds it, decides the score, names every survivor, and
on main uploads the merged report as the next baseline. A pull request that
changes no module, test, gate configuration or dependency runs no shard.

The weekly full run uses the same statement-level split.

Closes #464
@ExtraToast ExtraToast added type: feature New user-facing or operator-facing capability. area: tooling Reusable workflows, Gradle, templates, Renovate, and API tooling. component: ci Continuous integration workflow or check behavior. priority: P1 High; important and should be handled in the current iteration. labels Oct 16, 2026
@ExtraToast ExtraToast self-assigned this Oct 16, 2026
@github-actions

Copy link
Copy Markdown

Shape

bucket files additions deletions
tests 6 +745 -61
decision records 1 +36 -4
documentation 3 +19 -10
tooling 5 +622 -97
CI 2 +124 -20

Coverage

Baseline: main @ 4ff3638.

metric this branch main diff
statements 99.66% 99.57% +0.09
branches 98.14% 98.43% -0.29
functions 100.00% 100.00% 0.00
lines 99.62% 99.53% +0.09

Lines this pull request changed: 173/174 covered (99.43%).

@ExtraToast
ExtraToast merged commit 21339e4 into main Oct 16, 2026
30 checks passed
@ExtraToast
ExtraToast deleted the ci/464-shard-pr-mutation branch October 16, 2026 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: tooling Reusable workflows, Gradle, templates, Renovate, and API tooling. component: ci Continuous integration workflow or check behavior. priority: P1 High; important and should be handled in the current iteration. type: feature New user-facing or operator-facing capability.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shard the pull request mutation gate, and skip it where nothing it tests changed

1 participant