Skip to content

Commit 476aa32

Browse files
hyperpolymathclaude
andcommitted
proofs: honest prover gate — absent prover = fail, z3 expect-checked, Print Assumptions gated, Agda 4/4 --safe (4b–4d)
Four defects made the gate able to say green without checking: - verify-all-provers.sh printed "skipped" for an absent Isabelle or Mizar and still said ALL-PROVERS-GREEN (four of six provers); a listed Agda module that was missing on disk was silently skipped too. - proofs/z3/verify.sh ran `z3 cno_properties.smt2` — a file that does not exist — and CI wrapped it in `|| true`; the only live z3 check was an exit code, which is 0 for sat AND unsat. - Nothing ran Print Assumptions anywhere, so "closed under the global context" was prose. - CI type-checked 2 of the 4 Agda modules and EchoBridgeCNO.agda carried no --safe pragma of its own. Changes: - proofs/verify-all-provers.sh: Isabelle/Mizar absent -> fail=1; missing Agda module -> fail; EchoBridgeScaffold added; z3 via the expect-checker. - proofs/z3/verify.sh: generic expect-checker — every (check-sat) must carry `; expect sat|unsat` and z3's verdicts must match in order; fails on unknown, (error, missing annotation, no files, z3 rc != 0. - proofs/coq/audit/Assumptions.v + proofs/coq/check-assumptions.sh: the 17 theorems PROOF-STATUS names must print Closed under the global context; --control proves the gate rejects landauer_limit_positive (kB_positive). - proofs/tests/gate-selftest.sh: 14 cases (stubbed toolchains + real-z3 mutants), each negative asserting its reason string. - proofs/agda/EchoBridgeCNO.agda: {-# OPTIONS --safe --without-K #-}. - .github/workflows/proofs.yml: coq job runs the gate + control; agda job checks 4 modules; z3 job runs the checker without `|| true` plus the self-test. - Justfile: build-agda 4 modules; verify-z3 no skip-as-pass; verify-coq runs the gate; new verify-gate-selftest in verify-all. - PROOF-STATUS.adoc: Agda section matches CI; assumptions claim is the measured 17/17-closed fact; census (109/182 closed) tracked in #171. Measured locally (2026-09-23): self-test 14/14; reverting the Isabelle fix flunks exactly case B; blinding the z3 comparison flunks exactly E/G/K/N; assumptions gate 17/17 closed, control rejects naming kB_positive, vacuous and renamed audit files fail; agda 2.6.4.3 --safe --without-K passes all 4 modules; actionlint clean; actions.lock coverage complete. Refs #171. Phase 4b–4d of the residual-evidence-types ultraplan. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYY8Gp4v4x2J7iSNn1vZ57
1 parent dd87b48 commit 476aa32

9 files changed

Lines changed: 303 additions & 65 deletions

File tree

‎.github/workflows/proofs.yml‎

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ jobs:
5656
coq_makefile -f _CoqProject -o Makefile.all
5757
make -f Makefile.all -j"$(nproc)"
5858
echo "✓ Coq: 14/14 theories compiled (CNO + OND)"
59+
- name: Print Assumptions gate (17 named theorems closed) + control
60+
working-directory: proofs/coq
61+
run: |
62+
bash check-assumptions.sh
63+
bash check-assumptions.sh --control
5964
6065
agda:
6166
name: Agda — CNO + OND
@@ -79,13 +84,15 @@ jobs:
7984
mkdir -p "$HOME/.agda"
8085
echo "$HOME/agda-stdlib/standard-library.agda-lib" > "$HOME/.agda/libraries"
8186
echo "standard-library" > "$HOME/.agda/defaults"
82-
- name: Type-check CNO + OND (--safe --without-K)
87+
- name: Type-check CNO + OND + EchoBridge (4 modules, --safe --without-K)
8388
working-directory: proofs/agda
8489
run: |
8590
agda --version
8691
agda --safe --without-K CNO.agda
8792
agda --safe --without-K OND.agda
88-
echo "✓ Agda: CNO + OND type-check"
93+
agda --safe --without-K EchoBridgeScaffold.agda
94+
agda --safe --without-K EchoBridgeCNO.agda
95+
echo "✓ Agda: CNO + OND + EchoBridgeScaffold + EchoBridgeCNO type-check"
8996
9097
z3:
9198
name: Z3 — CNO + OND bounded checks
@@ -97,9 +104,10 @@ jobs:
97104
- name: Run Z3 checks
98105
run: |
99106
z3 --version
100-
sh proofs/z3/verify.sh || true
101-
z3 proofs/z3/ond/OND_checks.smt2
102-
echo "✓ Z3: OND bounded instances checked"
107+
bash proofs/z3/verify.sh
108+
echo "✓ Z3: every (check-sat) verdict matched its ; expect annotation"
109+
- name: Gate self-test (stub provers + z3 mutants must turn the gate red)
110+
run: bash proofs/tests/gate-selftest.sh
103111

104112
lean:
105113
name: Lean — core CNO (6 modules + axiom audit)

‎Justfile‎

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ build-lean:
3939
@echo "Building Lean 4 proofs..."
4040
cd proofs/lean4 && lake build
4141

42-
# Build Agda proofs (CNO + OND, --safe --without-K)
42+
# Build Agda proofs (CNO + OND + EchoBridge, 4 modules, --safe --without-K)
4343
build-agda:
4444
@echo "Building Agda proofs..."
45-
cd proofs/agda && agda --safe --without-K CNO.agda && agda --safe --without-K OND.agda
45+
cd proofs/agda && agda --safe --without-K CNO.agda && agda --safe --without-K OND.agda && agda --safe --without-K EchoBridgeScaffold.agda && agda --safe --without-K EchoBridgeCNO.agda
4646

4747
# Build Isabelle/HOL proofs (CNO + OND session)
4848
build-isabelle:
@@ -78,21 +78,21 @@ verify:
7878
@proofs/verify-all-provers.sh
7979

8080
# Verify all proofs (per-prover targets; `just verify` is the canonical one-shot)
81-
verify-all: verify-coq verify-z3 verify-lean verify-agda verify-isabelle verify-mizar verify-idris
81+
verify-all: verify-coq verify-z3 verify-lean verify-agda verify-isabelle verify-mizar verify-idris verify-gate-selftest
8282
@echo "✓ All verifications complete"
8383

84-
# Verify Coq proofs
84+
# Verify Coq proofs: build, then the Print Assumptions gate and its control
8585
verify-coq: build-coq
86-
@echo "✓ Coq proofs verified"
86+
bash proofs/coq/check-assumptions.sh
87+
bash proofs/coq/check-assumptions.sh --control
88+
@echo "✓ Coq proofs verified (17 named theorems closed under the global context)"
8789

88-
# Verify Z3 SMT properties (CNO checks + OND bounded instances)
90+
# Verify Z3 SMT properties: every (check-sat) verdict must match its `; expect` annotation (no skip-as-pass)
8991
verify-z3:
9092
@echo "Verifying Z3 SMT properties..."
91-
@if command -v z3 >/dev/null 2>&1; then \
92-
sh proofs/z3/verify.sh && z3 proofs/z3/ond/OND_checks.smt2 && echo "✓ Z3 verification complete"; \
93-
else \
94-
echo "⚠ z3 not found, skipping Z3 verification"; \
95-
fi
93+
@command -v z3 >/dev/null 2>&1 || { echo "✗ z3 not found (required, not skipped)"; exit 1; }
94+
bash proofs/z3/verify.sh
95+
@echo "✓ Z3 verification complete"
9696

9797
# Verify Lean 4 proofs
9898
verify-lean:
@@ -116,6 +116,10 @@ verify-isabelle: build-isabelle
116116
verify-mizar: build-mizar
117117
@echo "✓ Mizar proofs verified"
118118

119+
# Self-test the prover gate: stubbed toolchains + z3 mutants must turn it red
120+
verify-gate-selftest:
121+
bash proofs/tests/gate-selftest.sh
122+
119123
# Verify the Idris 2 ABI package
120124
verify-idris: build-idris
121125
@echo "✓ Idris ABI verified"

‎PROOF-STATUS.adoc‎

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ All six provers are installed and were *reproduced in this environment*. A singl
1717
gate, `proofs/verify-all-provers.sh`, builds every prover and prints
1818
`ALL-PROVERS-GREEN`: *Coq, Agda, Lean 4 (+Mathlib), Z3, Isabelle/HOL, Mizar*,
1919
plus the *Idris 2* ABI. Both the CNO and OND pillars are covered.
20+
An absent prover is a *failure*, never a skip (since 2026-09-23 — before that Isabelle
21+
and Mizar printed "skipped" and the gate could say GREEN on four of six), and Z3
22+
verdicts are compared with the `; expect sat|unsat` annotation on every `(check-sat)`
23+
(`proofs/z3/verify.sh`). `proofs/tests/gate-selftest.sh` proves both gates turn red for
24+
each absent or failing prover and for each verdict mutant (14 cases, run in CI).
2025
====
2126

2227
== Coq — VERIFIED (this environment)
@@ -82,9 +87,14 @@ of these, each documented in-file with its blocker:
8287
`nat -> C` single-qubit model; faithful discharge is a separate formalisation.
8388

8489
These are the analogue of the OND-6 research fork: openly labelled, not silently
85-
assumed. `Print Assumptions` on every headline theorem shows only Coq stdlib axioms
86-
(`ClassicalDedekindReals.*`, `functional_extensionality*`) plus, where relevant, the
87-
explicitly-tagged postulate above — never a hidden project axiom.
90+
assumed. `Print Assumptions` on each of the 17 theorems this document names in backticks
91+
prints `Closed under the global context` — no stdlib axiom and no project axiom (measured
92+
2026-09-23, Coq 8.18). That is CI-gated: `proofs/coq/audit/Assumptions.v` lists the 17 and
93+
`proofs/coq/check-assumptions.sh` (Coq job of `proofs.yml`) fails on any `Axioms:` block or a
94+
missing line; its `--control` mode proves the gate bites by requiring that
95+
`landauer_limit_positive`, which rests on `kB_positive`, is rejected. The wider tree is not
96+
closed — 109 of 182 top-level theorems are; the other 73 rest on stdlib classical axioms
97+
and/or the tagged parameters — see #171 for the census and the tag-grammar work.
8898

8999
=== Reversibility <-> CNO bridge (2026-07-16, the theorem MAA cites)
90100

@@ -151,8 +161,11 @@ capstone) remains open by design — see `docs/OND-ROADMAP.adoc`.
151161

152162
== Agda — VERIFIED (this environment)
153163

154-
* `agda` 2.6.3, `--safe --without-K`: `CNO.agda`, `OND.agda`, `EchoBridgeCNO.agda`
155-
type-check. The EchoBridge modules take **funext as an explicit hypothesis**
164+
* `agda` 2.6.3 (CI) / 2.6.4.3 (local), `--safe --without-K`: `CNO.agda`, `OND.agda`,
165+
`EchoBridgeScaffold.agda`, `EchoBridgeCNO.agda` type-check; every file carries the
166+
`{-# OPTIONS --safe --without-K #-}` pragma and CI (`proofs.yml`) checks all four. Until
167+
2026-09-23 CI checked only the first two and `EchoBridgeCNO.agda` had no pragma of its
168+
own. The EchoBridge modules take **funext as an explicit hypothesis**
156169
(not a global `postulate`); `OND.agda` uses zero postulates.
157170

158171
== Lean 4 — VERIFIED (this environment)
@@ -225,3 +238,7 @@ capstone) remains open by design — see `docs/OND-ROADMAP.adoc`.
225238
* Remaining axioms are exactly: (a) tagged physical postulates (the honest metal
226239
boundary), and (b) the class-A items listed above (true, provable in principle,
227240
openly labelled). No headline theorem depends on a hidden project axiom.
241+
* Measured 2026-09-23: the 17 named theorems are closed under the global context
242+
(CI-gated); of all 182 top-level theorems, 109 are closed and 73 rest on stdlib
243+
classical axioms and/or the tagged parameters. The "exactly" in the bullet above is
244+
not yet machine-checked — the tag grammar is unified under #171.

‎proofs/agda/EchoBridgeCNO.agda‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# OPTIONS --safe --without-K #-}
2+
13
-- Concrete Echo/CNO instantiation against CNO.Program and CNO.eval.
24
--
35
-- Primary bridge: use CNO.state-eq directly as the relation in EchoRel.

‎proofs/coq/audit/Assumptions.v‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
(* SPDX-License-Identifier: MPL-2.0 *)
2+
(* Print Assumptions audit over the theorems PROOF-STATUS.adoc names.
3+
4+
NOT listed in _CoqProject: proofs/coq/check-assumptions.sh compiles this file
5+
after the theories are built and FAILS unless every line below prints
6+
"Closed under the global context" (no stdlib axiom, no project axiom).
7+
Add a line here whenever PROOF-STATUS starts naming a theorem; the checker
8+
counts the "Print Assumptions" lines, so a theorem cannot be dropped silently.
9+
Measured 2026-09-23: 17/17 closed (Coq 8.18). *)
10+
Require CNO.CNO.
11+
Require CNO.FilesystemCNO.
12+
Require CNO.LambdaCNO.
13+
Require CNO.OND.
14+
Print Assumptions CNO.CNO.cno_equiv_seq_empty_of_reverses.
15+
Print Assumptions CNO.FilesystemCNO.create_unlink_inverse.
16+
Print Assumptions CNO.LambdaCNO.eta_equivalence.
17+
Print Assumptions CNO.CNO.eval_app.
18+
Print Assumptions CNO.CNO.eval_deterministic.
19+
Print Assumptions CNO.FilesystemCNO.mkdir_idempotent.
20+
Print Assumptions CNO.FilesystemCNO.mkdir_not_identity.
21+
Print Assumptions CNO.FilesystemCNO.mkdir_rmdir_inverse.
22+
Print Assumptions CNO.FilesystemCNO.rename_inverse.
23+
Print Assumptions CNO.CNO.reverses_seq_computes_identity.
24+
Print Assumptions CNO.CNO.reversible_bridge_backward_upto.
25+
Print Assumptions CNO.CNO.reversible_bridge_forward.
26+
Print Assumptions CNO.CNO.reversible_iff_exists_reverses.
27+
Print Assumptions CNO.OND.skip_program_is_core_CNO.
28+
Print Assumptions CNO.FilesystemCNO.snapshot_restore_identity.
29+
Print Assumptions CNO.FilesystemCNO.transaction_cno.
30+
Print Assumptions CNO.OND.writer_program_not_core_CNO.

‎proofs/coq/check-assumptions.sh‎

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: MPL-2.0
3+
# Absolute Zero — Print Assumptions gate for the Coq pillar.
4+
#
5+
# Compiles audit/Assumptions.v (or the file given as $1) against the built
6+
# theories, using the -R roots from _CoqProject, and FAILS unless every
7+
# `Print Assumptions` line answers "Closed under the global context":
8+
# - any "Axioms:" block -> FAIL (the block is printed);
9+
# - closed-count != line-count -> FAIL (a theorem silently missing);
10+
# - coqc exit != 0 -> FAIL (a renamed/removed theorem);
11+
# - a file with no Print Assumptions lines -> FAIL (vacuous gate).
12+
# `--control` proves the gate bites: it audits CNO.StatMech.landauer_limit_positive,
13+
# which rests on the tagged axiom PhysicsConstants.kB_positive, and requires
14+
# the gate to REJECT it naming that axiom.
15+
# Run after `coq_makefile -f _CoqProject -o Makefile.all && make -f Makefile.all`.
16+
set -uo pipefail
17+
HERE="$(cd "$(dirname "$0")" && pwd)"
18+
19+
command -v coqc >/dev/null || { echo "ASSUMPTIONS-CHECK FAILED: coqc not on PATH"; exit 1; }
20+
RFLAGS=()
21+
while read -r flag dir ns; do
22+
[ "$flag" = "-R" ] && RFLAGS+=("-R" "$HERE/$dir" "$ns")
23+
done < "$HERE/_CoqProject"
24+
[ "${#RFLAGS[@]}" -gt 0 ] || { echo "ASSUMPTIONS-CHECK FAILED: no -R roots in _CoqProject"; exit 1; }
25+
26+
# check_file <file.v>: 0 iff every Print Assumptions line is closed.
27+
check_file() {
28+
local file=$1 base dir out rc expected closed axioms
29+
base="$(basename "${file%.v}")"; dir="$(dirname "$file")"
30+
expected=$(grep -c '^Print Assumptions' "$file")
31+
if [ "$expected" -eq 0 ]; then
32+
echo "ASSUMPTIONS-CHECK FAILED: $file has no 'Print Assumptions' lines (vacuous)"; return 1
33+
fi
34+
out="$(coqc "${RFLAGS[@]}" "$file" 2>&1)"; rc=$?
35+
rm -f "$dir/$base.vo" "$dir/$base.vos" "$dir/$base.vok" "$dir/$base.glob" "$dir/.$base.aux"
36+
printf '%s\n' "$out"
37+
if [ "$rc" -ne 0 ]; then echo "ASSUMPTIONS-CHECK FAILED: coqc exit $rc on $file"; return 1; fi
38+
closed=$(printf '%s\n' "$out" | grep -c '^Closed under the global context')
39+
axioms=$(printf '%s\n' "$out" | grep -c '^Axioms:')
40+
if [ "$axioms" -ne 0 ] || [ "$closed" -ne "$expected" ]; then
41+
echo "ASSUMPTIONS-CHECK FAILED: $file — expected $expected closed, got closed=$closed axiom-blocks=$axioms"
42+
return 1
43+
fi
44+
echo "ASSUMPTIONS-CHECK OK: $expected/$expected theorems closed under the global context ($file)"
45+
}
46+
47+
if [ "${1:-}" = "--control" ]; then
48+
tmp="$(mktemp -d "${TMPDIR:-/tmp}/az-assumptions-control.XXXXXX")"
49+
trap 'rm -rf "$tmp"' EXIT
50+
printf 'Require CNO.StatMech.\nPrint Assumptions CNO.StatMech.landauer_limit_positive.\n' > "$tmp/Control.v"
51+
if check_file "$tmp/Control.v" > "$tmp/control.log" 2>&1; then
52+
echo "ASSUMPTIONS-CONTROL FAILED: landauer_limit_positive (rests on kB_positive) PASSED the gate"
53+
cat "$tmp/control.log"; exit 1
54+
fi
55+
if ! grep -q 'kB_positive' "$tmp/control.log"; then
56+
echo "ASSUMPTIONS-CONTROL FAILED: the rejection did not name PhysicsConstants.kB_positive"
57+
cat "$tmp/control.log"; exit 1
58+
fi
59+
echo "ASSUMPTIONS-CONTROL OK: landauer_limit_positive rejected, naming kB_positive (the gate bites)"
60+
exit 0
61+
fi
62+
63+
check_file "${1:-$HERE/audit/Assumptions.v}"

‎proofs/tests/gate-selftest.sh‎

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: MPL-2.0
3+
# Absolute Zero — self-test for the prover gate.
4+
#
5+
# Proves that proofs/verify-all-provers.sh and proofs/z3/verify.sh turn RED when
6+
# they should, using a stub toolchain on a private PATH (no real prover needed),
7+
# plus two mutants under a REAL z3 (required on PATH). Every negative case must
8+
# fail with the expected reason string, not merely a non-zero exit — a parse
9+
# error would otherwise pass as a kill.
10+
# HOME is overridden because the gate prepends $HOME/.local/bin:$HOME/.elan/bin.
11+
set -uo pipefail
12+
HERE="$(cd "$(dirname "$0")" && pwd)"
13+
PROOFS="$(cd "$HERE/.." && pwd)"
14+
GATE="$PROOFS/verify-all-provers.sh"
15+
Z3CHECK="$PROOFS/z3/verify.sh"
16+
REAL_SMT2="$PROOFS/z3/ond/OND_checks.smt2"
17+
SCRATCH="$(mktemp -d "${TMPDIR:-/tmp}/az-gate-selftest.XXXXXX")"
18+
trap 'rm -rf "$SCRATCH"' EXIT
19+
STUB="$SCRATCH/bin"; mkdir -p "$STUB" "$SCRATCH/home"
20+
cases=0; fails=0
21+
pass() { cases=$((cases+1)); echo "PASS: $1"; }
22+
flunk() { cases=$((cases+1)); fails=$((fails+1)); echo "FAIL: $1"; }
23+
24+
for s in "$GATE" "$Z3CHECK"; do bash -n "$s" || { echo "FAIL: $s does not parse"; exit 1; }; done
25+
26+
mkstub() { printf '#!/bin/sh\n%s\n' "${2:-exit 0}" > "$STUB/$1"; chmod +x "$STUB/$1"; }
27+
for t in coqc coq_makefile make agda lake isabelle accom verifier idris2; do mkstub "$t"; done
28+
z3_stub() { mkstub z3 "case \"\${1:-}\" in --version) echo \"Z3 version stub\";; *) printf '$1';; esac"; }
29+
z3_stub 'sat\nunsat\nsat\n'
30+
for s in "$STUB"/*; do sh -n "$s" || { echo "FAIL: stub $s does not parse"; exit 1; }; done
31+
32+
OUT=""; RC=0
33+
run_gate() { OUT="$(HOME="$SCRATCH/home" PATH="$STUB:/usr/bin:/bin" MIZFILES="${MIZ-$SCRATCH/miz}" bash "$GATE" 2>&1)"; RC=$?; }
34+
# expect <label> <exit-wanted> <must-contain> <must-not-contain>
35+
expect() {
36+
local label=$1 want=$2 must=$3 mustnot=$4
37+
if [ "$RC" -ne "$want" ]; then flunk "$label — exit $RC, wanted $want"; printf '%s\n' "$OUT" | tail -6 | sed 's/^/ /'; return; fi
38+
if [ -n "$must" ] && ! printf '%s\n' "$OUT" | grep -qF -- "$must"; then flunk "$label — output lacks '$must'"; printf '%s\n' "$OUT" | tail -6 | sed 's/^/ /'; return; fi
39+
if [ -n "$mustnot" ] && printf '%s\n' "$OUT" | grep -qF -- "$mustnot"; then flunk "$label — output contains '$mustnot'"; return; fi
40+
pass "$label"
41+
}
42+
43+
# A. positive control: every stub present and green
44+
run_gate; expect "A all provers present -> ALL-PROVERS-GREEN" 0 "ALL-PROVERS-GREEN" "SOME PROVERS FAILED"
45+
# B. isabelle absent must FAIL (pre-2026-09-23: printed 'skipped', stayed green)
46+
mv "$STUB/isabelle" "$SCRATCH/isabelle.off"; run_gate
47+
expect "B isabelle absent -> fail" 1 "isabelle missing" "ALL-PROVERS-GREEN"
48+
mv "$SCRATCH/isabelle.off" "$STUB/isabelle"
49+
# C. mizar verifier absent must FAIL
50+
mv "$STUB/verifier" "$SCRATCH/verifier.off"; run_gate
51+
expect "C mizar verifier absent -> fail" 1 "mizar verifier / MIZFILES missing" "ALL-PROVERS-GREEN"
52+
mv "$SCRATCH/verifier.off" "$STUB/verifier"
53+
# D. MIZFILES unset must FAIL
54+
MIZ="" run_gate; expect "D MIZFILES unset -> fail" 1 "mizar verifier / MIZFILES missing" "ALL-PROVERS-GREEN"
55+
# E. z3 verdict drift (second verdict sat instead of unsat) must FAIL
56+
z3_stub 'sat\nsat\nsat\n'; run_gate
57+
expect "E z3 verdict mismatch -> fail" 1 "verdicts differ from annotations" "ALL-PROVERS-GREEN"
58+
# F. z3 (error ...) line must FAIL even when the verdicts match
59+
z3_stub 'sat\n(error "boom")\nunsat\nsat\n'; run_gate
60+
expect "F z3 (error line -> fail" 1 "z3 reported an error" "ALL-PROVERS-GREEN"
61+
# G. z3 'unknown' must FAIL
62+
z3_stub 'sat\nunknown\nsat\n'; run_gate
63+
expect "G z3 unknown verdict -> fail" 1 "verdicts differ from annotations" "ALL-PROVERS-GREEN"
64+
z3_stub 'sat\nunsat\nsat\n'
65+
# H. a prover that runs but fails must FAIL
66+
mkstub idris2 'exit 3'; run_gate; expect "H idris2 exit 3 -> fail" 1 "IDRIS FAILED" "ALL-PROVERS-GREEN"; mkstub idris2
67+
# I. after the mutants, the positive control is green again (no state leaked)
68+
run_gate; expect "I positive control repeats green" 0 "ALL-PROVERS-GREEN" "SOME PROVERS FAILED"
69+
70+
# ---- the expect-checker under a REAL z3 ------------------------------------
71+
if ! command -v z3 >/dev/null; then flunk "J-M need a real z3 on PATH"; else
72+
# J. positive control: the committed file matches its annotations
73+
OUT="$(bash "$Z3CHECK" 2>&1)"; RC=$?; expect "J real z3, committed OND_checks.smt2 -> OK" 0 "Z3-CHECK OK" "Z3-CHECK FAILED"
74+
# K. expect-flipped mutant: 'expect unsat' -> 'expect sat' must FAIL
75+
mkdir -p "$SCRATCH/k"; sed 's/; expect unsat/; expect sat/' "$REAL_SMT2" > "$SCRATCH/k/mutant.smt2"
76+
grep -q '; expect unsat' "$SCRATCH/k/mutant.smt2" && flunk "K mutant not applied"
77+
OUT="$(bash "$Z3CHECK" "$SCRATCH/k" 2>&1)"; RC=$?; expect "K real z3, expect-flipped mutant -> fail" 1 "verdicts differ from annotations" "Z3-CHECK OK"
78+
# L. an unannotated (check-sat) must FAIL
79+
mkdir -p "$SCRATCH/l"; sed 's/; expect .*$//' "$REAL_SMT2" > "$SCRATCH/l/bare.smt2"
80+
OUT="$(bash "$Z3CHECK" "$SCRATCH/l" 2>&1)"; RC=$?; expect "L real z3, (check-sat) without expect -> fail" 1 "without an '; expect sat|unsat' annotation" "Z3-CHECK OK"
81+
# M. a root with no .smt2 must FAIL (vacuous)
82+
mkdir -p "$SCRATCH/m"; OUT="$(bash "$Z3CHECK" "$SCRATCH/m" 2>&1)"; RC=$?; expect "M no .smt2 files -> fail" 1 "no .smt2 files" "Z3-CHECK OK"
83+
# N. a file whose assertions are unsatisfiable where 'sat' is expected: z3 says unsat -> FAIL
84+
mkdir -p "$SCRATCH/n"; printf '(declare-const x Int)\n(assert (< x 0))\n(assert (> x 0))\n(check-sat) ; expect sat\n' > "$SCRATCH/n/contra.smt2"
85+
OUT="$(bash "$Z3CHECK" "$SCRATCH/n" 2>&1)"; RC=$?; expect "N real z3, contradictory assertions vs expect sat -> fail" 1 "verdicts differ from annotations" "Z3-CHECK OK"
86+
fi
87+
88+
echo
89+
if [ "$fails" -eq 0 ]; then echo "GATE-SELFTEST OK: $cases/$cases cases"; exit 0; fi
90+
echo "GATE-SELFTEST FAILED: $fails of $cases cases"; exit 1

0 commit comments

Comments
 (0)