Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e6edd21
docs(repo): plan the execution engine stream and its bench lane
systemfsoftware-maker Oct 9, 2026
943e781
docs(repo): apply supervisor ruling 1 to the bench lane plan
systemfsoftware-maker Oct 9, 2026
f571136
perf(repo): add the report-only bench lane with check and reporting p…
systemfsoftware-maker Oct 10, 2026
ab679b4
refactor(repo): simplify the bench lane
systemfsoftware-maker Oct 10, 2026
1c55418
Merge remote-tracking branch 'origin/main' into stryker/exec-bench-lane
systemfsoftware-maker Oct 10, 2026
9c919f5
chore(stryker-js-cli-contract): record the ReportingDuration export i…
systemfsoftware-maker Oct 10, 2026
58bf2b3
Merge remote-tracking branch 'origin/main' into stryker/exec-bench-lane
systemfsoftware-maker Oct 10, 2026
dbabbd5
fix(bench): apply the PR 1 review rulings
systemfsoftware-maker Oct 10, 2026
526deb7
Merge remote-tracking branch 'origin/main' into stryker/exec-bench-lane
systemfsoftware-maker Oct 10, 2026
dcdab0d
fix(stryker-e2e-core): construct the catalog failure classes with make
systemfsoftware-maker Oct 10, 2026
bb14611
fix(bench): fit every bench job and the workflow within ten minutes
systemfsoftware-maker Oct 10, 2026
714dae7
Merge remote-tracking branch 'origin/main' into stryker/exec-bench-lane
systemfsoftware-maker Oct 10, 2026
057976e
ci(bench): upload each run's stream and incremental report
systemfsoftware-maker Oct 10, 2026
9ab80e2
fix(stryker-js-typescript-checker): keep every equivalence emit under…
systemfsoftware-maker Oct 10, 2026
60c62e2
docs(plans): supersede the bench lane plan with the per-run restore d…
systemfsoftware-maker Oct 10, 2026
481b6aa
docs(solutions): record the equivalence emit that leaked .js into che…
systemfsoftware-maker Oct 10, 2026
d929a6b
Merge remote-tracking branch 'origin/main' into stryker/exec-bench-lane
systemfsoftware-maker Oct 10, 2026
a7ad3b6
fix(bench): stop a stalled setup at the job deadline with setup-timed…
systemfsoftware-maker Oct 10, 2026
69d348a
fix(bench): log each setup step's start and finish
systemfsoftware-maker Oct 10, 2026
04399fc
fix(bench): print a stalled setup command's output tail
systemfsoftware-maker Oct 10, 2026
fed0ada
fix(bench): install the enterprise fixture as of the side's lockfile …
systemfsoftware-maker Oct 10, 2026
27170d9
Merge remote-tracking branch 'origin/main' into stryker/exec-bench-lane
systemfsoftware-maker Oct 10, 2026
68efb39
Merge remote-tracking branch 'origin/main' into stryker/exec-bench-lane
systemfsoftware-maker Oct 10, 2026
4d1dcf4
feat(bench): record each run's workload digest and executed tests in …
systemfsoftware-maker Oct 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/check-phase-duration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"@systemfsoftware/stryker-js-cli-contract": minor
"@systemfsoftware/stryker-js": major
---

The verdict line's `phaseDurations` gains `check` and `reporting`. `check` is checker-busy wall-clock (the union of the intervals in which any checker was starting or checking); it overlaps the other phases, and a run with no checker configured reports `{ "_tag": "not-run" }` rather than zero. `reporting` runs from the end of mutant execution to the verdict, so `mutation-test` now stops where `reporting` starts, and the five sequential phases add up to the elapsed time.

Breaking:

- The stream emits a `phase` event for `reporting`, so `RunPhase` gains that value; exhaustive matches over `RunPhase` must handle it.
- `mutation-test` no longer includes reporting time.
- Verdict lines written before this release decode both new members as `{ "_tag": "not-recorded" }`.
7 changes: 7 additions & 0 deletions .changeset/tce-emit-stays-in-temp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@systemfsoftware/stryker-js-typescript-checker": patch
---

The checker's equivalent-mutant detection no longer writes `.js` files next to your TypeScript sources. When your tsconfig reaches other sources through `paths` aliases or package imports, earlier versions left a compiled `.js` beside each of those files after a run. On the next run those files could change which tests ran.

If an earlier version left stray `.js` files beside your `.ts` sources, delete them.
142 changes: 142 additions & 0 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: Bench

on:
pull_request:
paths-ignore:
- "**/*.md"
- "docs/**"

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
plan:
name: bench · one job per corpus entry
runs-on: ubuntu-latest
timeout-minutes: 1
outputs:
targets: ${{ steps.targets.outputs.targets }}
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
sparse-checkout: test/bench/corpus.json
sparse-checkout-cone-mode: false
- id: targets
name: Corpus entries
run: |
targets=$(jq -c '[.repo[].project, .enterprise.fixture] | map({ entry: ., slug: gsub("[^A-Za-z0-9._-]+"; "-") })' test/bench/corpus.json)
echo "targets=$targets" >> "$GITHUB_OUTPUT"

bench:
name: bench · ${{ matrix.target.entry }}
needs: plan
runs-on: ubuntu-latest
timeout-minutes: 9
strategy:
fail-fast: false
matrix:
target: ${{ fromJSON(needs.plan.outputs.targets) }}
env:
CI: "true"
steps:
- name: Bench deadline, 7.5 minutes after the job starts
run: echo "BENCH_DEADLINE_MS=$(($(date +%s%3N) + 450000))" >> "$GITHUB_ENV"

- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v7
with:
node-version: 24
cache: pnpm

- id: sides
name: Side A at the merge-base with the base branch
env:
BASE_REF: ${{ github.base_ref }}
run: |
git fetch --no-tags origin "+refs/heads/$BASE_REF:refs/remotes/origin/$BASE_REF"
base=$(git merge-base HEAD "origin/$BASE_REF")
side_a="$RUNNER_TEMP/bench-a"
git worktree add --detach "$side_a" "$base"
pin() { jq -c '.nodes["stryker-published"].locked' "$1/flake.lock"; }
{
echo "base=$base"
echo "a=$side_a"
echo "same-pin=$([ "$(pin "$side_a")" = "$(pin .)" ] && echo true || echo false)"
} >> "$GITHUB_OUTPUT"

- name: Released tarballs, side B
uses: ./.github/actions/released-tarballs
- if: steps.sides.outputs.same-pin != 'true'
uses: cachix/install-nix-action@v31

- name: Tarballs and install, both sides by one mechanism
env:
SIDE_A: ${{ steps.sides.outputs.a }}
SAME_PIN: ${{ steps.sides.outputs.same-pin }}
TIMINGS: ${{ runner.temp }}/bench-setup.tsv
run: |
started=$(date +%s%3N)
rm -rf "$SIDE_A/.sfs-deps"
if [ "$SAME_PIN" = true ]; then
cp -r .sfs-deps "$SIDE_A/.sfs-deps"
else
published=$(cd "$SIDE_A" && nix build --no-link --print-out-paths .#stryker-published)
mkdir "$SIDE_A/.sfs-deps"
cp "$published"/*.tgz "$SIDE_A/.sfs-deps/"
chmod u+w "$SIDE_A"/.sfs-deps/*.tgz
fi
printf 'side A: released tarballs\t%s\n' "$(($(date +%s%3N) - started))" >> "$TIMINGS"
install() {
local name=$1 root=$2 started
started=$(date +%s%3N)
(cd "$root" && pnpm install --frozen-lockfile)
printf 'side %s: pnpm install\t%s\n' "$name" "$(($(date +%s%3N) - started))" >> "$TIMINGS"
}
install A "$SIDE_A"
install B "$GITHUB_WORKSPACE"

- name: Turbo cache
uses: actions/cache@v6
with:
path: .turbo/cache
key: turbo-${{ runner.os }}-bench-${{ matrix.target.slug }}-${{ github.event.pull_request.head.sha }}
restore-keys: |
turbo-${{ runner.os }}-bench-${{ matrix.target.slug }}-
turbo-${{ runner.os }}-dist-

- name: Bench
env:
BENCH_ENTRY: ${{ matrix.target.entry }}
BENCH_SIDE_A: ${{ steps.sides.outputs.a }}
BENCH_SIDE_B: ${{ github.workspace }}
BENCH_BASE_SHA: ${{ steps.sides.outputs.base }}
BENCH_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
BENCH_SETUP_TIMINGS: ${{ runner.temp }}/bench-setup.tsv
run: pnpm --filter @systemfsoftware/stryker-bench bench

- name: Bench report artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v7
with:
name: bench-report-${{ matrix.target.slug }}
path: ${{ runner.temp }}/bench-report/bench-report.json
if-no-files-found: warn
retention-days: 30

- name: Bench run streams artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v7
with:
name: bench-runs-${{ matrix.target.slug }}
path: ${{ runner.temp }}/bench-runs/
if-no-files-found: warn
retention-days: 7
Loading
Loading