Mutation

Parity gate

vary mutate-parity defends performance-oriented bytecode backends (redefine, hot-swap) against the reference fresh-loader backend. Any time the two backends classify the same mutant differently (one killed, the other survived), the parity run fails loudly so the discrepancy is caught before the performance backend can become a default.

For the backends themselves, see Strict mode → Bytecode backends.

Why

The fresh-loader backend is the correctness source of truth. It constructs a brand-new classloader for every mutant, which is slow but gives each mutant a clean execution environment. Other backends are strictly performance optimisations: every kill-vs-survive classification must match what the reference backend would have produced. The parity gate is the continuous defence of that invariant.

CLI

vary mutate-parity <source> [-t <tests>] [--candidate redefine|hot-swap]
vary mutate-parity <directory> --corpus [--candidate redefine]

Single-file mode:

vary mutate-parity src/utils.vary -t tests/test_utils.vary

Pinned-corpus mode (CI):

vary mutate-parity programs/frugal --corpus
FlagDefaultPurpose
-t, --testsautoTest file/directory (single-file mode)
--candidateredefineCandidate backend: redefine or hot-swap
--corpusoffWalk a project directory as a pinned corpus
--jsonoffEcho the parity report to stdout

Output

Human-readable text (default) and mutation-reports/parity-report.json are emitted in both modes. With --json, the JSON is also printed to stdout.

Each mismatch carries:

FieldMeaning
mutantIdStable mutation ID (same across backends)
location<class>#<method><descriptor>@<instructionIndex>
referenceOutcome / candidateOutcomekilled or survived under each backend
candidateSwapOutcomeredefine, hotswap, fallback:*, or fresh-loader
referenceKilledBy / candidateKilledByTests that failed under each backend

A non-empty mismatches array exits the CLI non-zero.

Default backend

fresh-loader remains the default --backend on vary mutate. The redefine backend will not become the default until the parity gate is stable on the pinned corpus. Until that happens, the parity gate is the only CI signal that the redefine backend is trustworthy.

CI

The nightly nightly-reference-parity job runs parity on a pinned corpus:

vary mutate-parity programs/frugal --corpus --json

A non-zero exit causes the nightly run to fail. The mutation-reports/parity-report.json artifact is uploaded for triage.

What's not a mismatch

CaseWhyTreatment
Mutant errors in either backendEngine failure, not a classification claimExcluded from the comparison
Mutant was generated by only one backendRare, since both use the same generatorSkipped

If the candidate backend has no Instrumentation handle available (no -javaagent: and self-attach failed), every mutant routes through fresh-loader fallback. The parity report still runs to completion; classifications then agree by construction.

← Incremental inference
Survivor tail →