voyage/scripts
Kjell Tore Guttormsen 83d82f121d
fix(end-state): a behaviour probe must FELL a stub, not just name a test
The cosmetic close came back one level up. The probe reads the test file from
the same tree it measures, so a four-line file holding two EMPTY tests with the
two named names closed D-03 and D-04 on a tree where `lib/verification/` did
not exist at all - "defects 0 of 7, registry intact" (measured 2026-09-18).
First a two-line stub exporting the right symbols; then an empty test with the
right name. A name is always forgeable.

So the named test is now run twice. Once on the tree, as before - and once in a
sandbox where the module the condition declares in `stubs` is replaced by a
stub exporting the same names, all inert. If the test still passes there, it
binds the name and not the behaviour, and the condition THROWS: NOT FELLABLE,
counted open. A condition that declares no `stubs`, or names a module that is
not there, cannot fire either.

The sandbox is a symlink overlay: every entry of the tree is symlinked, and
only the test file and the stubbed module are materialised for real - Node
resolves an ESM import through the realpath, so a symlinked test file would
import the original module and never see the mutant. Nothing is ever written
inside the measured tree, and the only directory removed is the one this code
made under the system temp dir (pinned by a test).

M7 is now a permanent mutant beside M6, in two forms: the checkpoint's own
reproduction (unfixed tree + empty named tests) and the harder one (the real
module present, so the stub can be built and the empty test passes against it).
Both report `defects 2 of 7`. A positive control pins that D-03/D-04 still
CLOSE on the real tree, so "not closed" everywhere cannot read as a working
probe.

The frozen denominator moves a third time, deliberately, and its `why` no
longer claims authority it does not have: the second and third amendments were
maintenance decisions by the maintainer, not operator decisions, and the
tracked file now says exactly that.

Measured after:
  real tree      node scripts/end-state-gate.mjs -> defects 0 of 7, intact, exit 1
  M6 (stub)      8d1669e + current gate/registry/frozen + lib/cosmetic/stub.mjs -> 2 of 7
  M7 (empty)     8d1669e + current gate/registry/frozen + 3-line
                 tests/lib/criteria-runner.test.mjs with the two named tests -> 2 of 7
Red first: 4 of the new tests failed before the change. Suite 1154 (1152/0/2).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 02:56:22 +02:00
..
annotate.mjs chore: roll up in-progress changes across plugins 2026-05-16 21:02:23 +02:00
bakeoff-armA-merge.mjs feat(voyage): S10 part B — NW2 full bake-off (rich fixture) → verdict POSITIVE 2026-06-18 15:44:24 +02:00
bakeoff-fidelity.mjs feat(voyage): S10 part B — NW2 full bake-off (rich fixture) → verdict POSITIVE 2026-06-18 15:44:24 +02:00
end-state-gate.mjs fix(end-state): a behaviour probe must FELL a stub, not just name a test 2026-09-18 02:56:22 +02:00
end-state-registry.json fix(end-state): a behaviour probe must FELL a stub, not just name a test 2026-09-18 02:56:22 +02:00
gen-expected-prom.mjs feat(voyage): add lib/exporters/textfile-format.mjs — Prometheus text-format pure transform SC #12 2026-05-09 09:30:58 +02:00
q3-cache-prefix-experiment.mjs feat(voyage)!: bulk content rewrite ultra -> voyage/trek prose [skip-docs] 2026-05-05 15:08:20 +02:00
storm-measure.mjs fix(storm-measure): check BOTH halves of the activation SC, not just the count delta 2026-08-12 23:01:59 +02:00
synthesis-measure.mjs feat(voyage): S12 — NW3 synthesis-agent built + measured → declined per measurement [skip-docs] 2026-06-18 17:58:39 +02:00
trekreview-armB.workflow.mjs feat(voyage): S10 — NW2 part A (Workflow port + fidelity harness + smoke) 2026-06-18 14:40:19 +02:00