Skip to content

Navigation Menu

Sign in
Sign up

feat(guard): mechanise self-test potency with a declared-mutant harness (#405) - #432

Merged
avrabe merged 1 commit into
main from
feat/self-test-potency-405
Aug 21, 2026
Merged

feat(guard): mechanise self-test potency with a declared-mutant harness (#405) #432
avrabe merged 1 commit into
main from
feat/self-test-potency-405

Conversation

@avrabe

@avrabe avrabe commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

What & why (#405)

REQ-GUARD-GATE-EVIDENCE-002 once asserted in prose that "each was mutation-tested to show its cases are load-bearing rather than merely green." That universal was false and was withdrawn (#405): an adversarial review applied one-line mutations to two of the six guard tools and their --self-tests stayed green —

  • check_verification_filters.py: filt in namefilt.split('::')[-1] in name (blind to the 16-of-60 filters carrying ::);
  • check_lean_sorries.py: deleting the below-floor ratchet-notice branch (no case read what it printed).

Both holes were later closed by hand, but nothing prevented them reopening — delete either case and the suite is green again, silently. This PR ships the standing mechanism the withdrawn prose claimed to have.

The harness

tools/check_self_test_potency.py. For each mutant in a declared table:

  1. read the tool source, assert the substitution applies exactly as declared (a drifted/absent/ambiguous old, or a no-op new == old, is a hard ERROR, never a silent verdict — the specific trap this repo has been bitten by);
  2. assert the tool's unmodified --self-test is green (a red baseline can't be potency-judged → ERROR);
  3. apply the mutation to a copy in a tempdir (the working tree is never touched), run its --self-test, and require it now fails (CAUGHT). A survivor reds the build.

Exit 0 = all caught, 1 = a survivor, 2 = a declaration/baseline fault. Stdlib-only.

Seeded with four mutants across the two tools #405 falsified, including the exact two it demonstrated (vf-colon-tail, ls-drop-below-floor). All four are CAUGHT on this tree.

Non-vacuity — executed, not asserted

  • Harness self-test (12 cases): the same mutation is run against a potent stub (→ CAUGHT) and a blind stub differing only by one boundary case (→ SURVIVED). Distinct inputs, distinct outputs — a harness whose verdict ignored the target suite could not tell them apart.
  • Against the real tools: removing each mutant's named catching case flips it to SURVIVED and reds the run. Confirmed for all four (vf-colon-tail, vf-none-lenient, ls-drop-below-floor, ls-drop-axiom) — so each is caught by a specific case, not an incidental SyntaxError.
  • Fail-closed error handling (absent old, no-op, ambiguous count, red baseline → ERROR) is pinned by cases.

Honest ceiling

Mutation testing shows the cases present are load-bearing; it cannot show a suite is complete. A green run means "the declared mutants are all caught", never "these suites cover the hazard". The table is an allow-list of two tools / four mutants; broadening it to the other guard tools is left to a successor (noted in the REQ).

Artifacts & wiring

Local verification

  • check_self_test_potency.py --self-test → 12/12; real run → 4/4 CAUGHT.
  • Mutant-removal experiment → each of the 4 flips to SURVIVED, harness exits 1; tree restored byte-identical.
  • rivet validatePASS; REQ/TEST appear, all cross-refs resolve (the field 'release'/'method'/'steps' INFO and missing: design-decision WARN are the repo-wide baseline, firing on every sibling REQ-GUARD-*).
  • check_evidence_steps (floor 78, unchanged), check_human_scoped, check_release_plane, check_required_contexts, and every guardrail --self-test: green.
  • A clean-room subagent independently re-derived the above.

🤖 Generated with Claude Code


Generated by Claude Code

...ss (#405)
Mechanises the claim REQ-GUARD-GATE-EVIDENCE-002 once made in prose and
withdrew as false (#405): that each guardrail's self-test cases are
load-bearing rather than merely green. That universal was falsified by two
one-line mutations whose suites stayed green; both holes were then closed by
hand, but nothing PREVENTED them reopening — deleting either case is silently
green again.
tools/check_self_test_potency.py is that standing mechanism. For each mutant in
a declared table it applies the textual substitution to the tool's source, runs
that tool's --self-test, and asserts it now FAILS (CAUGHT). A survivor reds the
build; a stale/no-op/ambiguous declaration, or a tool whose baseline suite is
not already green, ERRORs (exit 2) rather than being smoothed into a verdict —
the harness refuses to report a mutation it did not actually exercise. It runs
mutated COPIES in a tempdir, never touching the tree, stdlib-only.
Seeded with four mutants across the two tools #405 falsified, including the
exact two it demonstrated: vf-colon-tail (a filter matched by its `::` tail,
#404) and ls-drop-below-floor (the deleted ratchet notice). All four are CAUGHT
on this tree.
NON-VACUITY is executed, not asserted. The harness --self-test runs the SAME
mutation against a potent stub (CAUGHT) and a blind stub differing only in the
one boundary case (SURVIVED) — distinct inputs, distinct outputs. Against the
real tools, removing each mutant's named catching case flips it to SURVIVED and
reds the run; all four were confirmed case-caught this way.
Adds REQ-GUARD-SELFTEST-POTENCY-001 (implemented, v0.40.0, traces-to
REQ-GUARD-GATE-EVIDENCE-002) and TEST-GUARD-SELFTEST-POTENCY, which carries real
runnable steps and satisfies/verifies links (the good -001-era convention).
Wired as two steps in the rivet-validate job beside the sibling guardrail
self-tests.
HONEST CEILING: mutation testing shows the cases PRESENT are load-bearing, not
that a suite is complete; the table covers two tools / four mutants, with
broadening to the other guard tools left to a successor.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

Rivet verification gate

20/20 passed

count
Passed 20
Failed 0
Skipped (no steps) 0

Filter: (and (= type "feature") (or (has-tag "v093") (has-tag "v0100")))

Failed artifacts

(none)

Updated automatically by tools/post_verification_comment.py. Source of truth: artifacts/verification.yaml.

avrabe merged commit 47c24c8 into main Aug 21, 2026
21 checks passed
avrabe deleted the feat/self-test-potency-405 branch August 21, 2026 04:36
avrabe added a commit that referenced this pull request Aug 21, 2026
Version bump for v0.40.0. Feature landed in #432 — mechanises self-test
potency with a declared-mutant harness (closes #405). Cargo.toml / Cargo.lock
(23 workspace crates) / vscode-spar/package.json 0.39.0 -> 0.40.0;
REQ-GUARD-SELFTEST-POTENCY-001 promoted to verified (release v0.40.0).
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

2 participants

AltStyle によって変換されたページ (->オリジナル) /