Skip to content

mutantkit 1.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 09 Oct 13:38
· 2 commits to main since this release
e297bd1

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 result flaky; a control that
    could not be established makes it infrastructureFailure. 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 becomes infrastructureFailure and says so
    in assertionKillAttribution; trust counts these under killEvidence.
  • 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, --evidence an evidence archive, --json emits
    verifyRunResult. Checks that cannot be verified are "not verifiable", never
    passed, and a run with any of them ends in PARTIAL rather than
    Fully verified.
  • mutantkit trust now re-verifies the report instead of believing its
    integrity self-report, and fails closed: trustworthy means every required
    check was re-verified. --json gains trustStatus (trustworthy,
    mismatch, notFullyVerified) and a verification object.
  • Opt-in evidence archive. With evidence.archive: true a run writes the raw
    observations behind each result to .mutantkit/evidence/<run-id>/
    (owner-only permissions; evidence.keep: N prunes older archives). With it,
    verify-run and trust also 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-parser sample
    (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, with retestKilledMutants: 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.json written by v1.1.x still loads. trust and verify-run
    treat its results as produced by an older verifier ("report was produced by
    an older verifier"); trust exits 5 for it. Re-run to obtain a verifiable
    report.
  • report.json gains optional fields: evidenceArchive, and per-result
    evidence.assertionKillAttribution, confirmationChain and
    assertionKillConfirmation.control. mutantkit.yml gains an optional
    evidence block (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

  • trustworthy is stricter. In trust --json, trustworthy: true now means
    the stored integrity passed, no check failed and every required check was
    verified. A report that v1.1.x called trustworthy can now be false
    because the plan could not be found (pass --plan, or keep plan.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.
  • trust has a new exit code, 5 (notFullyVerified): nothing failed, but a
    required check could not be verified. Exit 2 still means a check failed.
    A report from an older verifier can never be trustworthy and exits 5.
    Scripts that treat any non-zero exit as failure need no change; scripts that
    expect trust to exit 0 for such reports will now fail.
  • verify-run is new. It exits 0 for both a full and a partial
    verification (read complete in --json), 2 on a mismatch and 1 when
    its inputs cannot be read.
  • retestKilledMutants stays off by default. Two measured limits of turning
    it on: with tests.parallel: false SwiftPM writes no per-test breakdown, so
    retest-confirmed kills end up flaky (enable tests.parallel with 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 to flaky (safe:
    a kill is lost, never invented). In the swift-argument-parser sample, 19
    or 20 of 21 kills were confirmed per run and the others became flaky.
  • Kill attribution can turn a kill that v1.1.x counted into
    infrastructureFailure when its failing test lies outside the run's test
    selection. It is visible (assertionKillAttribution.disposition: outsideSelection, killEvidence in trust) and is not scored.
  • execution.sharedModuleCache is not expected to speed anything up on
    Xcode 27; doctor and execution-profile now 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 (5 from trust) is not breaking in itself,
    because the exit-code table defines each code separately and trust was
    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
    trust must be updated.
  • trustworthy meaning "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 what trust already
    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-27 runner 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 schemata with 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-run reports PARTIAL (and still exits 0) 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