feat(core): recover incremental results after a crash - #6212
Draft
davidshq wants to merge 9 commits into
Draft
Conversation
Persist completed mutants in a pending journal next to incrementalFile so the next --incremental run can reuse them after SIGKILL, OOM, or an uncaught exception, not only after a signal.
Freeze the WAL before compacting so in-flight results cannot vanish, skip plan-time appends, and document hard-kill / concurrent-run limits.
- Re-add a synchronous process.on('exit') path so backups are restored when
termination is not a handled signal (e.g. process.exit), without dropping
async signal handlers used for partial incremental reports.
If pending promotion fails, begin() staged by wiping .prev/.next and could delete the only on-disk journal. Stage in the other directory until the new pending pair is durable, and cover both failure paths in unit tests.
davidshq
marked this pull request as draft
September 7, 2026 14:27
- `pnpm run clean` recreates `dist`, breaking the hard links pnpm's injected deps rely on, so the e2e tests silently run the old build. - Check before running, and point at `pnpm install --frozen-lockfile`.
- `sync-dependencies-meta-injected` has no matching dependency, and `local-release` was added by accident earlier on this branch.
… file - Incremental runs build the report twice, so a missing source or test file warned twice. - Track what has been warned. Also share the extension-to-language map with the incremental journal instead of keeping a second copy. - copyDir now calls mkdirSync(recursive) unconditionally instead of checking existsSync first.
- Append `.pending` rather than replacing the extension: `incrementalFile: "x.pending"` used to map onto the report itself, and `a.json`/`a.html` shared one WAL. - Drop promoteToPending. load() now only records which of `.prev`/`.next` holds the WAL, and begin() stages into the other, closing the window where the only copy could be deleted before the rename landed. - Also normalize path options to posix before matching them as ignore globs, so `reports\foo.json` is ignored on Windows.
…as stale - Only set syncHandlersRan when all sync handlers succeed so --inPlace restore can retry on exit. - Treat injected e2e copies as stale when a copied file has no readable source counterpart.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--incrementalresults after a crash. Persist completed mutants in a new pending journal next toincrementalFileso the next run can reuse them after SIGKILL, OOM, or an uncaught exception—not only after a handled signal (extends feat(core): save partial incremental report on unexpected exit #5986). Onmaster, interrupted runs only flush a partial report toincrementalFileon Ctrl+C-style interrupts; there was no pending journal.stryker initgitignorereports/stryker-incremental.*(report + pending artifacts).--inPlacefile backups on unexpected process exit (includingprocess.exit) without dropping async signal handlers used for partial incremental reports.Replaces #6211 (that PR was based on the 9.6.x-era
incremental-recoverybranch). The 9.6.x work remains available on the fork asincremental-recoveryfor anyone who wants it.Test plan
IncrementalJournal, unexpected-exit handler, sandbox restore, and mutation-test report helperincremental-interrupt(crash mid-run, then recover on next incremental run)incrementalstill passes--incremental, kill the process mid-run, confirm pending journal exists and next run reuses results--inPlacerun interrupted viaprocess.exitrestores original files