ltl-accumulator-verified/verification/selftest-harness.sh

120 lines
6 KiB
Bash
Raw Normal View History

verification: pin the harness, audit drivers and policy files (P1-c) This repository has the estate's strongest gates, which makes them the most valuable to switch off. Until now every one of them was executed by scripts that nothing pinned. Phase 0c requires every harness file to match HARNESS.sha256 — 15 files: check.sh, lean-guard, inventory_gate.sh, run_bare.sh, all three self-tests, both audit drivers (Proofs/Inventory.lean, Proofs/AxiomCheck.lean), the policy tables (inventory-allowlist.txt, AUDIT-MANIFEST.txt), the toolchain pin, the fidelity harness and its Python transcription, and the extracted model. WHICH files must be pinned is policy and lives in check.sh, never in the map being consulted: the required set is derived from the filesystem (the executable bit, plus gen/**.lean, plus an explicit list for the rest), so deleting a pin entry is a set mismatch rather than a silent un-pinning. gen/LTLAcc/HashExternal.lean was previously bound by nothing at all — it was compiled and trusted. It is now pinned, and the derivation is by set, so a new model file fails closed. selftest_audit.sh case 9 is split rather than relabelled. Phase 0c now catches an unpinned rogue gen module BEFORE the dead-file gate runs, so asserting only the new diagnostic would have quietly retired the dead-file gate from the test suite. 9a asserts the harness-set mismatch on the unpinned file; 9b pins it — an author who added it deliberately — and asserts Phase 2 still dies with DEAD FILE (gen). Ten cases now, all defeated. KNOWN-GAPS and the trusted base record the circularity plainly: an author who edits a script and refreshes its pin in one commit passes every phase. The pin removes the silent path, not the possibility. Review at the pinned commit remains the consumer's protection. Verified green after the fix: button (75s), harness self-test, binding self-test, and the ten-case audit self-test. ATTESTATION GREEN (Lean + fidelity), all fidelity case counts identical to the pre-change run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 18:13:21 +00:00
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# selftest-harness.sh — adversarial self-test for check.sh Phase 0c.
#
# Phase 0c pins the scripts and policy files the button itself runs on. The
# attack it exists to stop is the cheapest one in the estate: don't touch the
# proofs at all, edit the checker. Round-5 review of the companion SLH-DSA
# repository stubbed the compiler wrapper alone and got ALL GREEN in 3.6
# seconds over deliberately destroyed proofs.
#
# Cases, each asserting a SPECIFIC diagnostic:
# 0 positive control: untouched tree passes
# 1 a pinned harness file edited by one byte → does not match its pin
# 2 a NEW executable appears, unpinned → set mismatch
# 3 an entry DELETED from HARNESS.sha256 → set mismatch, NOT a
# silent un-pin (this is the shape of the defect SLH-DSA round-6 found:
# dropping a key un-pinned two files with no diagnostic at all)
# 4 HARNESS.sha256 itself removed → fail-closed
#
# Phase 0c is lifted out of check.sh at run time, so the tested logic IS the
# shipping logic. Cheap: no Lean, runs in about a second.
# ─────────────────────────────────────────────────────────────────────────────
set -uo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
FAILURES=0
STASH="$(mktemp -d)"
NEWEXE="$HERE/zz-selftest-helper.sh"
cleanup() {
[ -f "$STASH/HARNESS.sha256" ] && cp "$STASH/HARNESS.sha256" "$HERE/HARNESS.sha256"
[ -f "$STASH/victim" ] && cp "$STASH/victim" "$HERE/$VICTIM"
rm -f "$NEWEXE"
rm -rf "$STASH"
}
trap cleanup EXIT INT TERM
cp "$HERE/HARNESS.sha256" "$STASH/HARNESS.sha256"
# Lift Phase 0c. The two repo families end the phase differently, so accept
# either terminator rather than hardcoding one and silently lifting nothing.
verification: guard the accumulator's two lifts (port lift-guard, assert on the payload) The four forks ship lift-guard.sh and call it from eight files each. This repository had no lift-guard.sh at all and called it zero times, while lifting Phase 0c (selftest-harness.sh) and Phase 3d (selftest_statements.sh). Its lifts got a line-count sanity check and nothing else — no analysis of which variables the payload READS against which the driver DEFINES, and after yesterday's fix no errexit check either. It was the one place that class could still recur. A SECOND defect surfaced while porting, and it is the more interesting one. Both lifts assembled the driver inline, with no payload file anywhere: { echo 'set -euo pipefail'; echo "HERE=..."; sed -n '...' check.sh } > DRIVER if [ "$(wc -l < "$DRIVER")" -lt 40 ]; then ... refuse ... so the size check measured the CONCATENATED DRIVER — bindings included. A lift that recovered almost nothing still cleared the threshold on the strength of the lines the test itself prepended. That is exactly the defect round-7 lift-guard-payload-assert reported and that the forks closed with the words "all six lift sites now assert on payload.sh". Six counted the forks. These two were never in the count, so a finding recorded as closed was measuring the wrong population — the same error this estate keeps finding in new costumes. Both sites now write payload.sh / payload3d.sh and assert on those. lift-guard.sh is byte-identical to the forks' (4f61c113). It is executable, so this repository's own self-deriving Phase 0c rule required a pin before it would run at all: required set == pinned set, verified. WIRING PROVEN RATHER THAN ASSUMED. With lift-guard.sh stubbed to exit 1, each self-test halts AT the guard, naming its phase, before a single attack case runs. Guard restored, pins re-verified. Certified: button + all three self-tests GREEN (check.sh 86s, selftest_audit 258s, selftest-harness 1s, selftest_statements 34s). The other five repositories are unchanged from the tree round-15 certified 50/50 and were not re-run; this commit does not claim they were. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 11:39:19 +00:00
# The payload is written to its OWN file before the driver is assembled, for two
# reasons that both bit this repository. The size sanity check below has to
# measure what was LIFTED; measured on the concatenated driver it counts the
# prepended bindings too, so a lift that recovered almost nothing still clears
# the threshold (round-7 lift-guard-payload-assert, closed in the four forks
# with "all six lift sites" — six counted the forks, and these two accumulator
# lifts were never in that count). And lift-guard needs payload and driver
# separately to tell what the phase READS from what the driver DEFINES.
verification: pin the harness, audit drivers and policy files (P1-c) This repository has the estate's strongest gates, which makes them the most valuable to switch off. Until now every one of them was executed by scripts that nothing pinned. Phase 0c requires every harness file to match HARNESS.sha256 — 15 files: check.sh, lean-guard, inventory_gate.sh, run_bare.sh, all three self-tests, both audit drivers (Proofs/Inventory.lean, Proofs/AxiomCheck.lean), the policy tables (inventory-allowlist.txt, AUDIT-MANIFEST.txt), the toolchain pin, the fidelity harness and its Python transcription, and the extracted model. WHICH files must be pinned is policy and lives in check.sh, never in the map being consulted: the required set is derived from the filesystem (the executable bit, plus gen/**.lean, plus an explicit list for the rest), so deleting a pin entry is a set mismatch rather than a silent un-pinning. gen/LTLAcc/HashExternal.lean was previously bound by nothing at all — it was compiled and trusted. It is now pinned, and the derivation is by set, so a new model file fails closed. selftest_audit.sh case 9 is split rather than relabelled. Phase 0c now catches an unpinned rogue gen module BEFORE the dead-file gate runs, so asserting only the new diagnostic would have quietly retired the dead-file gate from the test suite. 9a asserts the harness-set mismatch on the unpinned file; 9b pins it — an author who added it deliberately — and asserts Phase 2 still dies with DEAD FILE (gen). Ten cases now, all defeated. KNOWN-GAPS and the trusted base record the circularity plainly: an author who edits a script and refreshes its pin in one commit passes every phase. The pin removes the silent path, not the possibility. Review at the pinned commit remains the consumer's protection. Verified green after the fix: button (75s), harness self-test, binding self-test, and the ten-case audit self-test. ATTESTATION GREEN (Lean + fidelity), all fidelity case counts identical to the pre-change run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 18:13:21 +00:00
DRIVER="$STASH/phase0c.sh"
verification: guard the accumulator's two lifts (port lift-guard, assert on the payload) The four forks ship lift-guard.sh and call it from eight files each. This repository had no lift-guard.sh at all and called it zero times, while lifting Phase 0c (selftest-harness.sh) and Phase 3d (selftest_statements.sh). Its lifts got a line-count sanity check and nothing else — no analysis of which variables the payload READS against which the driver DEFINES, and after yesterday's fix no errexit check either. It was the one place that class could still recur. A SECOND defect surfaced while porting, and it is the more interesting one. Both lifts assembled the driver inline, with no payload file anywhere: { echo 'set -euo pipefail'; echo "HERE=..."; sed -n '...' check.sh } > DRIVER if [ "$(wc -l < "$DRIVER")" -lt 40 ]; then ... refuse ... so the size check measured the CONCATENATED DRIVER — bindings included. A lift that recovered almost nothing still cleared the threshold on the strength of the lines the test itself prepended. That is exactly the defect round-7 lift-guard-payload-assert reported and that the forks closed with the words "all six lift sites now assert on payload.sh". Six counted the forks. These two were never in the count, so a finding recorded as closed was measuring the wrong population — the same error this estate keeps finding in new costumes. Both sites now write payload.sh / payload3d.sh and assert on those. lift-guard.sh is byte-identical to the forks' (4f61c113). It is executable, so this repository's own self-deriving Phase 0c rule required a pin before it would run at all: required set == pinned set, verified. WIRING PROVEN RATHER THAN ASSUMED. With lift-guard.sh stubbed to exit 1, each self-test halts AT the guard, naming its phase, before a single attack case runs. Guard restored, pins re-verified. Certified: button + all three self-tests GREEN (check.sh 86s, selftest_audit 258s, selftest-harness 1s, selftest_statements 34s). The other five repositories are unchanged from the tree round-15 certified 50/50 and were not re-run; this commit does not claim they were. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 11:39:19 +00:00
PAYLOAD="$STASH/payload.sh"
awk '/^# ── Phase 0c/{f=1} f{print} /^# ── Phase 1|^echo "=== Phase 1/{if(f && !/Phase 0c/) exit}' "$HERE/check.sh" \
| sed '/^# ── Phase 1/d; /^echo "=== Phase 1/d' > "$PAYLOAD"
verification: pin the harness, audit drivers and policy files (P1-c) This repository has the estate's strongest gates, which makes them the most valuable to switch off. Until now every one of them was executed by scripts that nothing pinned. Phase 0c requires every harness file to match HARNESS.sha256 — 15 files: check.sh, lean-guard, inventory_gate.sh, run_bare.sh, all three self-tests, both audit drivers (Proofs/Inventory.lean, Proofs/AxiomCheck.lean), the policy tables (inventory-allowlist.txt, AUDIT-MANIFEST.txt), the toolchain pin, the fidelity harness and its Python transcription, and the extracted model. WHICH files must be pinned is policy and lives in check.sh, never in the map being consulted: the required set is derived from the filesystem (the executable bit, plus gen/**.lean, plus an explicit list for the rest), so deleting a pin entry is a set mismatch rather than a silent un-pinning. gen/LTLAcc/HashExternal.lean was previously bound by nothing at all — it was compiled and trusted. It is now pinned, and the derivation is by set, so a new model file fails closed. selftest_audit.sh case 9 is split rather than relabelled. Phase 0c now catches an unpinned rogue gen module BEFORE the dead-file gate runs, so asserting only the new diagnostic would have quietly retired the dead-file gate from the test suite. 9a asserts the harness-set mismatch on the unpinned file; 9b pins it — an author who added it deliberately — and asserts Phase 2 still dies with DEAD FILE (gen). Ten cases now, all defeated. KNOWN-GAPS and the trusted base record the circularity plainly: an author who edits a script and refreshes its pin in one commit passes every phase. The pin removes the silent path, not the possibility. Review at the pinned commit remains the consumer's protection. Verified green after the fix: button (75s), harness self-test, binding self-test, and the ten-case audit self-test. ATTESTATION GREEN (Lean + fidelity), all fidelity case counts identical to the pre-change run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 18:13:21 +00:00
{
verification: lifted phases run under the buttons shell options, enforced in lift-guard A lift is evidence about the shipping gate only if it executes the way the shipping gate executes. Every button here runs `set -euo pipefail`. Eighteen lift sites prefixed their driver with `set -uo pipefail` and no -e — four per fork (selftest-harness, selftest-scalar-statements, selftest-statements twice) and both accumulator lifts — while sixteen other sites got it right. The estate did it both ways, which is what made this a defect and not a convention. Without -e a failing command does not abort: execution continues and the driver returns the LAST command status. A lifted phase can therefore reach a verdict the shipping phase would never reach while the self-test reports the gate "works". selftest_statements.sh:27 claims the tested logic IS the shipping logic; in this respect it was not. NO VERDICT CHANGED. Every self-test that passed before passes now, at the same timings, so -e was not masking a false green at these commits. The defect was fidelity and the claim is no larger than that. The durable part is not the 18 edits. lift-guard.sh already inspects every driver, so it now REFUSES any lift whose driver does not enable errexit and prints the drivers actual shell options. Negative-tested four ways: no -e rejects, `set -euo` passes, bare `set -e` passes, no set line at all rejects. Byte-identical across the four forks. The nineteenth lift someone writes fails closed rather than silently testing a more permissive shell. Certified by the round-15 sweep: 50/50 GREEN, six repositories, both buttons and every self-test, exit 0. Registered and NOT fixed here: ltl-accumulator-verified has no lift-guard.sh at all and calls it zero times, so its two lifts remain unguarded — the one place this class can still recur silently. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 10:58:29 +00:00
echo 'set -euo pipefail' # -e matches the button; see lift-drivers-drop-errexit
verification: pin the harness, audit drivers and policy files (P1-c) This repository has the estate's strongest gates, which makes them the most valuable to switch off. Until now every one of them was executed by scripts that nothing pinned. Phase 0c requires every harness file to match HARNESS.sha256 — 15 files: check.sh, lean-guard, inventory_gate.sh, run_bare.sh, all three self-tests, both audit drivers (Proofs/Inventory.lean, Proofs/AxiomCheck.lean), the policy tables (inventory-allowlist.txt, AUDIT-MANIFEST.txt), the toolchain pin, the fidelity harness and its Python transcription, and the extracted model. WHICH files must be pinned is policy and lives in check.sh, never in the map being consulted: the required set is derived from the filesystem (the executable bit, plus gen/**.lean, plus an explicit list for the rest), so deleting a pin entry is a set mismatch rather than a silent un-pinning. gen/LTLAcc/HashExternal.lean was previously bound by nothing at all — it was compiled and trusted. It is now pinned, and the derivation is by set, so a new model file fails closed. selftest_audit.sh case 9 is split rather than relabelled. Phase 0c now catches an unpinned rogue gen module BEFORE the dead-file gate runs, so asserting only the new diagnostic would have quietly retired the dead-file gate from the test suite. 9a asserts the harness-set mismatch on the unpinned file; 9b pins it — an author who added it deliberately — and asserts Phase 2 still dies with DEAD FILE (gen). Ten cases now, all defeated. KNOWN-GAPS and the trusted base record the circularity plainly: an author who edits a script and refreshes its pin in one commit passes every phase. The pin removes the silent path, not the possibility. Review at the pinned commit remains the consumer's protection. Verified green after the fix: button (75s), harness self-test, binding self-test, and the ten-case audit self-test. ATTESTATION GREEN (Lean + fidelity), all fidelity case counts identical to the pre-change run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 18:13:21 +00:00
echo "HERE=\"$HERE\""
verification: guard the accumulator's two lifts (port lift-guard, assert on the payload) The four forks ship lift-guard.sh and call it from eight files each. This repository had no lift-guard.sh at all and called it zero times, while lifting Phase 0c (selftest-harness.sh) and Phase 3d (selftest_statements.sh). Its lifts got a line-count sanity check and nothing else — no analysis of which variables the payload READS against which the driver DEFINES, and after yesterday's fix no errexit check either. It was the one place that class could still recur. A SECOND defect surfaced while porting, and it is the more interesting one. Both lifts assembled the driver inline, with no payload file anywhere: { echo 'set -euo pipefail'; echo "HERE=..."; sed -n '...' check.sh } > DRIVER if [ "$(wc -l < "$DRIVER")" -lt 40 ]; then ... refuse ... so the size check measured the CONCATENATED DRIVER — bindings included. A lift that recovered almost nothing still cleared the threshold on the strength of the lines the test itself prepended. That is exactly the defect round-7 lift-guard-payload-assert reported and that the forks closed with the words "all six lift sites now assert on payload.sh". Six counted the forks. These two were never in the count, so a finding recorded as closed was measuring the wrong population — the same error this estate keeps finding in new costumes. Both sites now write payload.sh / payload3d.sh and assert on those. lift-guard.sh is byte-identical to the forks' (4f61c113). It is executable, so this repository's own self-deriving Phase 0c rule required a pin before it would run at all: required set == pinned set, verified. WIRING PROVEN RATHER THAN ASSUMED. With lift-guard.sh stubbed to exit 1, each self-test halts AT the guard, naming its phase, before a single attack case runs. Guard restored, pins re-verified. Certified: button + all three self-tests GREEN (check.sh 86s, selftest_audit 258s, selftest-harness 1s, selftest_statements 34s). The other five repositories are unchanged from the tree round-15 certified 50/50 and were not re-run; this commit does not claim they were. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 11:39:19 +00:00
cat "$PAYLOAD"
verification: pin the harness, audit drivers and policy files (P1-c) This repository has the estate's strongest gates, which makes them the most valuable to switch off. Until now every one of them was executed by scripts that nothing pinned. Phase 0c requires every harness file to match HARNESS.sha256 — 15 files: check.sh, lean-guard, inventory_gate.sh, run_bare.sh, all three self-tests, both audit drivers (Proofs/Inventory.lean, Proofs/AxiomCheck.lean), the policy tables (inventory-allowlist.txt, AUDIT-MANIFEST.txt), the toolchain pin, the fidelity harness and its Python transcription, and the extracted model. WHICH files must be pinned is policy and lives in check.sh, never in the map being consulted: the required set is derived from the filesystem (the executable bit, plus gen/**.lean, plus an explicit list for the rest), so deleting a pin entry is a set mismatch rather than a silent un-pinning. gen/LTLAcc/HashExternal.lean was previously bound by nothing at all — it was compiled and trusted. It is now pinned, and the derivation is by set, so a new model file fails closed. selftest_audit.sh case 9 is split rather than relabelled. Phase 0c now catches an unpinned rogue gen module BEFORE the dead-file gate runs, so asserting only the new diagnostic would have quietly retired the dead-file gate from the test suite. 9a asserts the harness-set mismatch on the unpinned file; 9b pins it — an author who added it deliberately — and asserts Phase 2 still dies with DEAD FILE (gen). Ten cases now, all defeated. KNOWN-GAPS and the trusted base record the circularity plainly: an author who edits a script and refreshes its pin in one commit passes every phase. The pin removes the silent path, not the possibility. Review at the pinned commit remains the consumer's protection. Verified green after the fix: button (75s), harness self-test, binding self-test, and the ten-case audit self-test. ATTESTATION GREEN (Lean + fidelity), all fidelity case counts identical to the pre-change run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 18:13:21 +00:00
} > "$DRIVER"
verification: guard the accumulator's two lifts (port lift-guard, assert on the payload) The four forks ship lift-guard.sh and call it from eight files each. This repository had no lift-guard.sh at all and called it zero times, while lifting Phase 0c (selftest-harness.sh) and Phase 3d (selftest_statements.sh). Its lifts got a line-count sanity check and nothing else — no analysis of which variables the payload READS against which the driver DEFINES, and after yesterday's fix no errexit check either. It was the one place that class could still recur. A SECOND defect surfaced while porting, and it is the more interesting one. Both lifts assembled the driver inline, with no payload file anywhere: { echo 'set -euo pipefail'; echo "HERE=..."; sed -n '...' check.sh } > DRIVER if [ "$(wc -l < "$DRIVER")" -lt 40 ]; then ... refuse ... so the size check measured the CONCATENATED DRIVER — bindings included. A lift that recovered almost nothing still cleared the threshold on the strength of the lines the test itself prepended. That is exactly the defect round-7 lift-guard-payload-assert reported and that the forks closed with the words "all six lift sites now assert on payload.sh". Six counted the forks. These two were never in the count, so a finding recorded as closed was measuring the wrong population — the same error this estate keeps finding in new costumes. Both sites now write payload.sh / payload3d.sh and assert on those. lift-guard.sh is byte-identical to the forks' (4f61c113). It is executable, so this repository's own self-deriving Phase 0c rule required a pin before it would run at all: required set == pinned set, verified. WIRING PROVEN RATHER THAN ASSUMED. With lift-guard.sh stubbed to exit 1, each self-test halts AT the guard, naming its phase, before a single attack case runs. Guard restored, pins re-verified. Certified: button + all three self-tests GREEN (check.sh 86s, selftest_audit 258s, selftest-harness 1s, selftest_statements 34s). The other five repositories are unchanged from the tree round-15 certified 50/50 and were not re-run; this commit does not claim they were. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 11:39:19 +00:00
if [ "$(grep -c . "$PAYLOAD")" -lt 20 ]; then
verification: pin the harness, audit drivers and policy files (P1-c) This repository has the estate's strongest gates, which makes them the most valuable to switch off. Until now every one of them was executed by scripts that nothing pinned. Phase 0c requires every harness file to match HARNESS.sha256 — 15 files: check.sh, lean-guard, inventory_gate.sh, run_bare.sh, all three self-tests, both audit drivers (Proofs/Inventory.lean, Proofs/AxiomCheck.lean), the policy tables (inventory-allowlist.txt, AUDIT-MANIFEST.txt), the toolchain pin, the fidelity harness and its Python transcription, and the extracted model. WHICH files must be pinned is policy and lives in check.sh, never in the map being consulted: the required set is derived from the filesystem (the executable bit, plus gen/**.lean, plus an explicit list for the rest), so deleting a pin entry is a set mismatch rather than a silent un-pinning. gen/LTLAcc/HashExternal.lean was previously bound by nothing at all — it was compiled and trusted. It is now pinned, and the derivation is by set, so a new model file fails closed. selftest_audit.sh case 9 is split rather than relabelled. Phase 0c now catches an unpinned rogue gen module BEFORE the dead-file gate runs, so asserting only the new diagnostic would have quietly retired the dead-file gate from the test suite. 9a asserts the harness-set mismatch on the unpinned file; 9b pins it — an author who added it deliberately — and asserts Phase 2 still dies with DEAD FILE (gen). Ten cases now, all defeated. KNOWN-GAPS and the trusted base record the circularity plainly: an author who edits a script and refreshes its pin in one commit passes every phase. The pin removes the silent path, not the possibility. Review at the pinned commit remains the consumer's protection. Verified green after the fix: button (75s), harness self-test, binding self-test, and the ten-case audit self-test. ATTESTATION GREEN (Lean + fidelity), all fidelity case counts identical to the pre-change run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 18:13:21 +00:00
echo "FATAL: could not lift Phase 0c out of check.sh — the phase markers moved."
echo "This self-test must attack the shipping gate; refusing to run against nothing."
exit 1
fi
verification: guard the accumulator's two lifts (port lift-guard, assert on the payload) The four forks ship lift-guard.sh and call it from eight files each. This repository had no lift-guard.sh at all and called it zero times, while lifting Phase 0c (selftest-harness.sh) and Phase 3d (selftest_statements.sh). Its lifts got a line-count sanity check and nothing else — no analysis of which variables the payload READS against which the driver DEFINES, and after yesterday's fix no errexit check either. It was the one place that class could still recur. A SECOND defect surfaced while porting, and it is the more interesting one. Both lifts assembled the driver inline, with no payload file anywhere: { echo 'set -euo pipefail'; echo "HERE=..."; sed -n '...' check.sh } > DRIVER if [ "$(wc -l < "$DRIVER")" -lt 40 ]; then ... refuse ... so the size check measured the CONCATENATED DRIVER — bindings included. A lift that recovered almost nothing still cleared the threshold on the strength of the lines the test itself prepended. That is exactly the defect round-7 lift-guard-payload-assert reported and that the forks closed with the words "all six lift sites now assert on payload.sh". Six counted the forks. These two were never in the count, so a finding recorded as closed was measuring the wrong population — the same error this estate keeps finding in new costumes. Both sites now write payload.sh / payload3d.sh and assert on those. lift-guard.sh is byte-identical to the forks' (4f61c113). It is executable, so this repository's own self-deriving Phase 0c rule required a pin before it would run at all: required set == pinned set, verified. WIRING PROVEN RATHER THAN ASSUMED. With lift-guard.sh stubbed to exit 1, each self-test halts AT the guard, naming its phase, before a single attack case runs. Guard restored, pins re-verified. Certified: button + all three self-tests GREEN (check.sh 86s, selftest_audit 258s, selftest-harness 1s, selftest_statements 34s). The other five repositories are unchanged from the tree round-15 certified 50/50 and were not re-run; this commit does not claim they were. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 11:39:19 +00:00
"$HERE/lift-guard.sh" "$PAYLOAD" "$DRIVER" "check.sh Phase 0c" || exit 1
verification: pin the harness, audit drivers and policy files (P1-c) This repository has the estate's strongest gates, which makes them the most valuable to switch off. Until now every one of them was executed by scripts that nothing pinned. Phase 0c requires every harness file to match HARNESS.sha256 — 15 files: check.sh, lean-guard, inventory_gate.sh, run_bare.sh, all three self-tests, both audit drivers (Proofs/Inventory.lean, Proofs/AxiomCheck.lean), the policy tables (inventory-allowlist.txt, AUDIT-MANIFEST.txt), the toolchain pin, the fidelity harness and its Python transcription, and the extracted model. WHICH files must be pinned is policy and lives in check.sh, never in the map being consulted: the required set is derived from the filesystem (the executable bit, plus gen/**.lean, plus an explicit list for the rest), so deleting a pin entry is a set mismatch rather than a silent un-pinning. gen/LTLAcc/HashExternal.lean was previously bound by nothing at all — it was compiled and trusted. It is now pinned, and the derivation is by set, so a new model file fails closed. selftest_audit.sh case 9 is split rather than relabelled. Phase 0c now catches an unpinned rogue gen module BEFORE the dead-file gate runs, so asserting only the new diagnostic would have quietly retired the dead-file gate from the test suite. 9a asserts the harness-set mismatch on the unpinned file; 9b pins it — an author who added it deliberately — and asserts Phase 2 still dies with DEAD FILE (gen). Ten cases now, all defeated. KNOWN-GAPS and the trusted base record the circularity plainly: an author who edits a script and refreshes its pin in one commit passes every phase. The pin removes the silent path, not the possibility. Review at the pinned commit remains the consumer's protection. Verified green after the fix: button (75s), harness self-test, binding self-test, and the ten-case audit self-test. ATTESTATION GREEN (Lean + fidelity), all fidelity case counts identical to the pre-change run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 18:13:21 +00:00
expect() { # expect <label> <want-rc> <want-substring>
local label="$1" want_rc="$2" want_txt="$3" out rc
out=$(bash "$DRIVER" 2>&1); rc=$?
if [ "$rc" -ne "$want_rc" ]; then
echo "$label: exit $rc, expected $want_rc"; echo "$out" | sed 's/^/ /'
FAILURES=$((FAILURES+1)); return
fi
if ! grep -qF "$want_txt" <<<"$out"; then
echo "$label: exit code right, diagnostic wrong (rejected for the wrong reason)"
echo " wanted: $want_txt"; echo "$out" | sed 's/^/ /'
FAILURES=$((FAILURES+1)); return
fi
echo "$label"
}
echo "=== selftest-harness: attacking check.sh Phase 0c ==="
# ── 0. positive control ────────────────────────────────────────────────────
expect "case 0 control: untouched harness passes" 0 "match their pins"
# ── 1. edit a pinned file. lean-guard is the pointed choice: it is the memory
# cap protecting this machine, and stubbing it is the demonstrated
# 3.6-second path to a false green.
VICTIM=lean-guard
cp "$HERE/$VICTIM" "$STASH/victim"
printf '\n# selftest\n' >> "$HERE/$VICTIM"
expect "case 1: edited lean-guard caught" 1 "does not match its pin"
cp "$STASH/victim" "$HERE/$VICTIM"
# ── 2. a new executable the button could shell out to ──────────────────────
printf '#!/bin/sh\necho "unpinned"\n' > "$NEWEXE"; chmod +x "$NEWEXE"
expect "case 2: new unpinned executable caught" 1 "does not match HARNESS.sha256"
rm -f "$NEWEXE"
# ── 3. delete a pin entry: the set must be derived from the filesystem, not
# read out of the map being consulted, or this is a silent un-pin.
grep -v " ${VICTIM}\$" "$STASH/HARNESS.sha256" > "$HERE/HARNESS.sha256"
expect "case 3: deleted pin entry is a failure, not a silent un-pin" 1 "does not match HARNESS.sha256"
cp "$STASH/HARNESS.sha256" "$HERE/HARNESS.sha256"
# ── 4. absence must not pass for cleanliness ───────────────────────────────
rm -f "$HERE/HARNESS.sha256"
expect "case 4: missing pin file is fail-closed" 1 "the harness is unpinned"
cp "$STASH/HARNESS.sha256" "$HERE/HARNESS.sha256"
# ── 5. restored ────────────────────────────────────────────────────────────
expect "case 5: restored to green" 0 "match their pins"
echo ""
if [ "$FAILURES" -eq 0 ]; then
echo "SELFTEST PASSED — Phase 0c rejects harness tampering for the stated reason."
exit 0
fi
echo "SELFTEST FAILED: $FAILURES case(s) did not behave as claimed."
exit 1