Skip to content

v3.1.0 — the instruments that could not report what they were built to find

Choose a tag to compare

@WingedGuardian WingedGuardian released this 09 Sep 05:57
· 1076 commits to master since this release

⚠ Read this first if you installed a pre-release build

If you ever ran an installer from this repo with --over-existing, check
.claude/backups/ before anything else.
An upgrade deleted the destination's
recovery store silently, at exit 0. The prune list is dual-purpose — paths in it are
skipped on the way in and rm -rf'd from the destination on the way out — and the
entry added to stop the source machine's backups travelling inherited that second,
destructive meaning. On the machine where it was found, that directory held 982
files, 60 MB and 33 named known-good snapshots
. Fixed in this release.

Three installer criticals, all introduced by this arc

  • --dry-run performed a REAL install whenever the toolkit was already at the
    destination — both installers, both methods, printing === install complete ===. A
    new "nothing to change" fast path returned above the dry-run gate, so the guard was
    correct, present, and unreachable.
  • The source machine's secrets travelled. x4-paths.env.bak-* and .tmp* hold
    X4_NEXUS_KEY by construction and were copied to the destination.
  • --method global rewrote the user's own files inside shipped skill directories,
    with the only backup deleted on the success path.

Also: the recovery command both installers printed from a refused install (x4lock.py unlock) exits 2 — it needs a path or --all. The remedy failed at the moment you were
least able to tell a broken instruction from a broken tool.

The theme: five gates with no floor under their verdict

Every one reported success over a population it never examined — All properties hold
over three checks that never ran, No per-mod regression over an empty
intersection, a completion sentinel over an empty directory, a header-only artifact
from an empty input, and a three-channel audit whose third channel was uncounted. Each
is now a refusal or an rc 3.

The generalisation: a count incremented before the step it is meant to measure
cannot report that step failing.

mutation_probe could not run at all — it shared a 120s timeout with the targeted
runs while the suite had grown to 665s, so it returned its non-answer and refused. It
was the one gate of 29 left unrun, and it was found only because the runner prints
NOT ATTEMPTED and makes its buckets sum to the roster.

Other measured fixes

  • An empty root list was digested as a world, so an artifact that enumerated zero
    mods
    reported FRESH.
  • A malformed document made x4stats print "candidate introduces/changes no wares" at
    rc 0 — walking around the guard this arc added against exactly that sentence.
  • Nine tests that could not fail, four of them holding an already-fixed defect in place.
  • x4effective dump printed an incomplete tree as a clean one; it now discloses dropped
    overlays and returns 3.

Verification

Suite 1702 passed / 14 skipped / 0 failed · verify-cold 1651 / 65, COLD RUN CLEAN with the roots asserted unresolved · 160 hook probes · gates 28 of 29
attempted, 28 passed
· mutation_probe run alone, 48/48 killed, 0 survivors ·
all four derived artifacts agreeing on both fingerprint axes.

Full detail, with the measurements and the denominators, is in CHANGELOG.md.