#!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # selftest_statements.sh — adversarial self-test of check.sh Phase 3d. # # WHY A SECOND SELF-TEST. selftest_audit.sh attacks the coverage gate, which # pins every constant's NAME, KIND and AXIOM CONE, both directions. That gate # is strong and none of its nine attacks defeat it. It is also blind to what a # declaration SAYS, and this script demonstrates that with a real, compiling # edit rather than an argument: # # `LTLAcc.pinAccept` is a specification definition. Wrapping one branch of # its body in `id (…)` is definitionally equal, so every downstream proof # still compiles; the name, the kind, the type and the axiom cone are all # unchanged. The inventory gate reports 222 constants, environment == # allowlist, GREEN. Only the statement digest sees it. # # That edit is deliberately harmless. The point is that the ONLY thing # standing between it and a genuinely vacuous redefinition is the digest. # # Cases: # 0 positive control: pristine tree passes Phase 3d # 1 defeq body edit: old gate PASSES (asserted), Phase 3d FAILS (asserted) # 2 committed AUDIT-MANIFEST.txt hand-edited → COMMITTED BLOCK STALE # 3 statement block truncated → BLOCK TRUNCATED # 4 a constant inventoried but carrying no statement → COVERAGE GAP # # Phase 3d is lifted out of check.sh at run time, so the tested logic IS the # shipping logic. Run AFTER a green check.sh. All Lean work via lean-guard. # ───────────────────────────────────────────────────────────────────────────── set -uo pipefail AENEAS_ENV="${AENEAS_ENV:-$HOME/aeneas-toolchain/env.sh}" [ -f "$AENEAS_ENV" ] || { echo "FATAL: Aeneas environment not found: $AENEAS_ENV"; exit 1; } source "$AENEAS_ENV" SRC="$(cd "$(dirname "$0")" && pwd)" AENEAS_LEAN="$AENEAS_HOME/backends/lean" CORES="${LEAN_MAX_CORES:-0-3}" FAILURES=0 WORK=$(mktemp -d /tmp/acc-stmt-selftest-XXXX) trap 'rm -rf "$WORK"' EXIT echo "=== statement-binding self-test (scratch: $WORK) ===" cp -a "$SRC" "$WORK/verification" T="$WORK/verification" cp "$T/Proofs/PinStore.lean" "$T/PinStore.pristine" cp "$T/AUDIT-MANIFEST.txt" "$T/MANIFEST.pristine" # Phase 3d, lifted verbatim from the shipping button. HERE and INVLOG are the # two variables it reads from its surroundings. # Payload to its own file before the driver is assembled: the size check must # measure what was LIFTED, not the lift plus its bindings, and lift-guard needs # the two apart to separate what the phase READS from what the driver DEFINES. DRIVER="$T/phase3d.sh" PAYLOAD="$T/payload3d.sh" sed -n '/^# -- Phase 3d/,/^# -- Phase 4/p' "$SRC/check.sh" | sed '$d' > "$PAYLOAD" { echo 'set -euo pipefail' # -e matches the button; see lift-drivers-drop-errexit echo "HERE=\"$T\"" echo 'INVLOG="$1"' cat "$PAYLOAD" } > "$DRIVER" if [ "$(wc -l < "$PAYLOAD")" -lt 40 ]; then echo "FATAL: could not lift Phase 3d 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 # Guarded by the SHIPPING guard in $SRC, not the copy inside the scratch tree: # a test that vets itself with its own copy of the instrument proves less. "$SRC/lift-guard.sh" "$PAYLOAD" "$DRIVER" "check.sh Phase 3d" || exit 1 # Recompile the edited leaf module + the inventory into $T/inv.out. build_inventory() { cd "$AENEAS_LEAN" lake env bash -c " set -euo pipefail cd '$T' && export LEAN_PATH=\"\$LEAN_PATH:$T/gen:$T\" LEAN_TIMEOUT=600 LEAN_MAX_CORES=$CORES '$T/lean-guard' Proofs/PinStore.lean >/dev/null 2>&1 LEAN_TIMEOUT=600 LEAN_MAX_CORES=$CORES '$T/lean-guard' Proofs/Inventory.lean " > "$T/inv.out" 2>&1 local rc=$? cd "$T" return $rc } expect() { # expect