Repository navigation
Highlights
Trust v2: a kill is now credited only when the evidence shows it.
- Structured kill confirmation. With
execution.retestKilledMutants: true,
a confirmed assertion kill records what was confirmed: the second run of the
identical mutant, the tests that failed, and a baseline control (the same
tests run against the unmutated build). A kill is counted only when the
control passes. A failing control makes the resultflaky; a control that
could not be established makes itinfrastructureFailure. The control run is
shared by kills with the same test selection. - Kill attribution. An assertion kill is credited only to tests inside the
run's test selection, matched by full test identifier. A kill whose failing
test lies outside the selection becomesinfrastructureFailureand says so
inassertionKillAttribution;trustcounts these underkillEvidence. mutantkit verify-run <report>: re-verifies a finished report from what it
contains. Tier A checks plan identity, source anchors, per-result
provenance, and recomputes the integrity block and the score.--plan
supplies the plan,--evidencean evidence archive,--jsonemits
verifyRunResult. Checks that cannot be verified are "not verifiable", never
passed, and a run with any of them ends inPARTIALrather than
Fully verified.mutantkit trustnow re-verifies the report instead of believing its
integrity self-report, and fails closed:trustworthymeans every required
check was re-verified.--jsongainstrustStatus(trustworthy,
mismatch,notFullyVerified) and averificationobject.- Opt-in evidence archive. With
evidence.archive: truea run writes the raw
observations behind each result to.mutantkit/evidence/<run-id>/
(owner-only permissions;evidence.keep: Nprunes older archives). With it,
verify-runandtrustalso run Tier B: results are re-judged from the raw
observations under the confirmation policy the run recorded. Tier B is a
consistency check, not a signature. - Retesting kills is measured: on a 30-mutant
swift-argument-parsersample
(isolated, warm coverage cache,tests.parallel: true) it added about 237
to 245 s to a 562 to 571 s run (+42 to +43 percent), 21 kills and 20
baseline-control runs (about 6 s per extra run). Its default is
unchanged (see below).
Xcode 27 support:
- MutantKit builds from source on Xcode 27 (Swift 6.4).
- SwiftPM's new products layout (
.build/out/Products/<Configuration>) is
handled by the confirmation retest and its baseline control. Before this
change, withretestKilledMutants: true, every SwiftPM kill on Xcode 27
degraded instead of being confirmed. - The Swift Testing event stream parser accepts the verdict-less
testEnded
events newer helpers emit, only when the rest of the stream proves the
verdict; otherwise the stream is still treated as unsupported. - Xcode 27.0 is the CI-enforced baseline and Xcode 26.6 a reduced
CI-enforced compatibility lane: see
Apple support matrix. On Xcode 27.0
(27A266a) the full unit suite and all 22 acceptance fixtures of the CI
matrix passed on the release commit; on Xcode 26.5 the unit suite and the
SwiftPM, Xcode project, batch testing and cache and checkpoint acceptance
classes passed. - Test harness and fixtures: the application fixtures adopt the scene
lifecycle the iOS 27 SDK requires, and acceptance destinations resolve to a
simulator the machine has. No user-facing behaviour changes.
Upgrade impact
- Caches and checkpoints from v1.1.x are not reused. The verifier version
(12 in v1.1.x, 16 now) is part of what a cached result must match, so an
older cached result is a miss and the mutant is run again; it is never an
error and never served as if current. A resumed checkpoint is re-judged
from its raw observations under the current rules. Old files under
.mutantkit/can be deleted. Expect the first run after upgrading to
re-evaluate mutants. - A
report.jsonwritten by v1.1.x still loads.trustandverify-run
treat its results as produced by an older verifier ("report was produced by
an older verifier");trustexits 5 for it. Re-run to obtain a verifiable
report. report.jsongains optional fields:evidenceArchive, and per-result
evidence.assertionKillAttribution,confirmationChainand
assertionKillConfirmation.control.mutantkit.ymlgains an optional
evidenceblock (archive,keep). Schema versions are unchanged
(still 1) and the mutation ID derivation is unchanged.- Xcode 27: see "Known issues". Everything else about running on Xcode 26.6
is unchanged. - Minimum requirements are unchanged: macOS 14+, Apple Silicon, Swift 6.0+
(swift-tools-version:6.0).
Compatibility changes
trustworthyis stricter. Intrust --json,trustworthy: truenow means
the stored integrity passed, no check failed and every required check was
verified. A report that v1.1.x called trustworthy can now befalse
because the plan could not be found (pass--plan, or keepplan.json
next to the report or in the project root) or because its results come from
an older verifier. The key keeps its name and type.trusthas a new exit code,5(notFullyVerified): nothing failed, but a
required check could not be verified. Exit2still means a check failed.
A report from an older verifier can never betrustworthyand exits5.
Scripts that treat any non-zero exit as failure need no change; scripts that
expecttrustto exit 0 for such reports will now fail.verify-runis new. It exits0for both a full and a partial
verification (readcompletein--json),2on a mismatch and1when
its inputs cannot be read.retestKilledMutantsstays off by default. Two measured limits of turning
it on: withtests.parallel: falseSwiftPM writes no per-test breakdown, so
retest-confirmed kills end upflaky(enabletests.parallelwith it); and
the unmutated control runs in a clone of the built products, so a test that
reaches a built binary by a path relative to the original products
directory fails there and a genuine kill can be demoted toflaky(safe:
a kill is lost, never invented). In theswift-argument-parsersample, 19
or 20 of 21 kills were confirmed per run and the others becameflaky.- Kill attribution can turn a kill that v1.1.x counted into
infrastructureFailurewhen its failing test lies outside the run's test
selection. It is visible (assertionKillAttribution.disposition: outsideSelection,killEvidenceintrust) and is not scored. execution.sharedModuleCacheis not expected to speed anything up on
Xcode 27;doctorandexecution-profilenow say so.
Breaking changes
No flag, configuration key, schema version or JSON key has been removed, and
no JSON shape changed incompatibly. Two documented behaviours are tightened,
and each can turn a CI step that passed on v1.1.x into one that fails:
- A newly possible exit code (
5fromtrust) is not breaking in itself,
because the exit-code table defines each code separately andtrustwas
already documented to fail when a report cannot be trusted; but because it
fires on reports that v1.1.x passed, a script that requires exit 0 from
trustmust be updated. trustworthymeaning "every required check re-verified" is a semantic
tightening of an existing key, which we treat as a breaking behaviour change
for anyone who gates on it. It is fail-closed (it can only withhold trust,
never grant it) and brings the key in line with whattrustalready
promised.
We still ship this as a minor release: it removes nothing, both tightenings
are fail-closed corrections of a documented promise, and they lead this
document so they are not missed. A project that applies strict semantic
versioning to documented output meanings could reasonably call it a major
change.
Known issues
- CI runs on GitHub's preview
xcode-27runner image. Jobs can queue longer
than on a generally available image, and an image update can fail a run
without a change in this repository. CodeQL still runs on Xcode 26.6, and
the Xcode 26.6 compatibility lane covers only the unit tests, the SwiftPM
package, local path dependency and Xcode project (isolated) fixtures. - SwiftPM
schematawith two or more test targets on Xcode 27: every chunk
forfeits schemata and runs isolated (reported in
fallbackReasonCounts["buildReceiptUnavailable"]). Results stay correct;
there is no schemata speedup. Packages with one test target are not
affected. - Dead-stripping on Swift 6.4 removes code nothing references, so a mutant in
it can build to a product identical to the baseline. It is reported as
infrastructureFailure("build product identical to baseline"), not as a
survivor, and is not scored. verify-runreports PARTIAL (and still exits0) when a report records an
evidence archive that cannot be found: Tier B is not performed and the
checks that need raw observations stay not verifiable. Keep the archive
next to the project, or pass--evidence.
What's Changed
- Pin the documented release to v1.1.1 by @juntaki in #87
- Trust v2 and Xcode 27 support by @juntaki in #91
- Bump SonarSource/sonarqube-scan-action from 8.2.2 to 8.3.0 in the github-actions group across 1 directory by @dependabot[bot] in #89
Full Changelog: v1.1.1...v1.2.0