Skip to content

Commit db2bd9e

Browse files
hyperpolymathclaude
andcommitted
ci(proof): comment-aware honesty-guard, replace brittle inline scan
scripts/honesty-guard.sh strips Idris line/doc/block comments (and is string-literal aware) before scanning for proof-escape smells: believe_me, really_believe_me, postulate, assert_total, assert_smaller, idris_crash, sorry, ?holes, partial. Reports file:line; exit 1 + count on any hit, exit 0 + "Clean." otherwise. Default scope src/, accepts file/dir args. Wires it into .github/workflows/proof-corpus.yml in place of the inline grep, which only filtered comments matched at line start (missed mid-line -- and {- -} blocks). Same Phase-1 corpus scope. Local invocation noted in VERIFICATION-STANCE.adoc. Verified: Clean on the corpus and all of src/; fault-injection confirms it catches a real believe_me and ?hole while ignoring the same tokens in --, |||, and {- -} comments. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent a8021db commit db2bd9e

3 files changed

Lines changed: 120 additions & 14 deletions

File tree

.github/workflows/proof-corpus.yml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,22 +57,22 @@ jobs:
5757
echo "$HOME/.idris2/bin" >> "$GITHUB_PATH"
5858
echo "IDRIS2_PREFIX=$HOME/.idris2" >> "$GITHUB_ENV"
5959
60-
- name: Proof-escape audit (no believe_me / postulate / assert_* / sorry)
60+
- name: Proof-escape audit (honesty guard)
6161
run: |
6262
set -euo pipefail
63-
# Strip line/block comments, then scan the corpus sources.
64-
files="src/core/Grammar.idr src/core/Schema.idr src/core/Decide.idr \
65-
src/core/Levels.idr src/core/Checker.idr \
66-
src/core/Composition.idr src/core/Epistemic.idr \
67-
src/interface/abi/Types.idr src/interface/abi/Layout.idr \
68-
src/interface/abi/LayoutProofs.idr \
69-
src/interface/WireDecode.idr src/interface/WireConformance.idr"
70-
if grep -nE '\b(believe_me|really_believe_me|assert_total|assert_smaller|idris_crash|postulate|sorry)\b' \
71-
$files | grep -vE ':\s*(--|\|\|\|)' ; then
72-
echo "::error::proof-escape symbol found in the Phase-1 corpus"
73-
exit 1
74-
fi
75-
echo "OK: zero proof-escape symbols outside comments"
63+
# Robust, comment-aware scan (line --, doc |||, nested {- -}, and
64+
# string-literal-aware): scripts/honesty-guard.sh. Scoped to the
65+
# Phase-1 corpus sources — the same module set vclut-core.ipkg builds
66+
# below. Exits 1 on any believe_me / really_believe_me / postulate /
67+
# assert_total / assert_smaller / idris_crash / sorry / ?hole /
68+
# partial appearing outside a comment.
69+
sh scripts/honesty-guard.sh \
70+
src/core/Grammar.idr src/core/Schema.idr src/core/Decide.idr \
71+
src/core/Levels.idr src/core/Checker.idr \
72+
src/core/Composition.idr src/core/Epistemic.idr \
73+
src/interface/abi/Types.idr src/interface/abi/Layout.idr \
74+
src/interface/abi/LayoutProofs.idr \
75+
src/interface/WireDecode.idr src/interface/WireConformance.idr
7676
7777
- name: Build the proof corpus
7878
run: |

scripts/honesty-guard.sh

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/bin/sh
2+
# SPDX-License-Identifier: MPL-2.0
3+
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
4+
#
5+
# honesty-guard.sh — advisory scan for fake-success "proof-escape" smells in
6+
# the Idris2 corpus. These symbols let a broken proof typecheck and claim a
7+
# green that it has not earned:
8+
#
9+
# believe_me / really_believe_me assert any type with zero proof content
10+
# postulate axiom with no proof
11+
# assert_total suppress the totality (coverage) checker
12+
# assert_smaller suppress the termination checker
13+
# idris_crash runtime abort masquerading as a value
14+
# sorry unfilled placeholder (Idris2 accepts it)
15+
# ?name unsolved metavariable / open hole
16+
# partial / %default partial disable coverage+termination checking
17+
#
18+
# The scan STRIPS Idris comments first — line (`--`), doc (`|||`), and nested
19+
# block (`{- -}`) — so a file that merely *names* one of these tokens in prose
20+
# (as src/interface/abi/LayoutProofs.idr does in its module docstring) is not a
21+
# false positive. String literals are comment-marker-aware so an in-string
22+
# `--` cannot hide following code. Line numbers are preserved for reporting.
23+
#
24+
# Usage: scripts/honesty-guard.sh [PATH ...] (PATH = file or dir; default: src)
25+
# Exit: 0 + "Clean." when no smell is found
26+
# 1 + "N smell(s) in M file(s)" and a file:line list otherwise
27+
#
28+
# Advisory by design: it is a diagnostic, not a substitute for the
29+
# totality-checked `idris2 --build` of verification/proofs/vclut-core.ipkg.
30+
31+
set -u
32+
33+
PATTERN='\b(believe_me|really_believe_me|assert_total|assert_smaller|idris_crash|postulate|sorry|partial)\b|\?[A-Za-z_]'
34+
35+
# ---- Idris comment stripper (preserves one output line per input line) ------
36+
awkprog=$(mktemp)
37+
filelist=$(mktemp)
38+
hits=$(mktemp)
39+
trap 'rm -f "$awkprog" "$filelist" "$hits"' EXIT INT TERM
40+
41+
cat > "$awkprog" <<'AWK'
42+
# Blank out Idris2 comments while keeping line count stable.
43+
# depth : nesting depth of {- -} block comments (persists across lines)
44+
# instr : inside a "..." string literal (reset per line; Idris strings
45+
# do not span lines except rare triple-quoted forms)
46+
BEGIN { depth = 0 }
47+
{
48+
line = $0; n = length(line); out = ""; i = 1; instr = 0
49+
while (i <= n) {
50+
c = substr(line, i, 1)
51+
two = substr(line, i, 2)
52+
if (depth > 0) { # inside a block comment
53+
if (two == "-}") { depth--; i += 2; continue }
54+
if (two == "{-") { depth++; i += 2; continue }
55+
i++; continue
56+
}
57+
if (instr) { # inside a string literal
58+
out = out c
59+
if (c == "\\") { i++; if (i <= n) out = out substr(line, i, 1); i++; continue }
60+
if (c == "\"") { instr = 0 }
61+
i++; continue
62+
}
63+
if (two == "{-") { depth++; i += 2; continue } # open block comment
64+
if (two == "--") { break } # line comment to EOL
65+
if (substr(line, i, 3) == "|||") { break } # doc comment to EOL
66+
if (c == "\"") { instr = 1; out = out c; i++; continue }
67+
out = out c
68+
i++
69+
}
70+
print out
71+
}
72+
AWK
73+
74+
# ---- collect target files ---------------------------------------------------
75+
[ "$#" -eq 0 ] && set -- src
76+
for arg in "$@"; do
77+
if [ -d "$arg" ]; then
78+
find "$arg" -type f -name '*.idr'
79+
elif [ -f "$arg" ]; then
80+
printf '%s\n' "$arg"
81+
else
82+
echo "honesty-guard: no such path: $arg" >&2
83+
fi
84+
done | sort -u > "$filelist"
85+
86+
# ---- scan -------------------------------------------------------------------
87+
while IFS= read -r f; do
88+
[ -n "$f" ] || continue
89+
awk -f "$awkprog" "$f" | grep -nE "$PATTERN" | sed "s|^|$f:|" >> "$hits"
90+
done < "$filelist"
91+
92+
# ---- report -----------------------------------------------------------------
93+
if [ -s "$hits" ]; then
94+
cat "$hits"
95+
n=$(wc -l < "$hits" | tr -d ' ')
96+
m=$(cut -d: -f1 "$hits" | sort -u | wc -l | tr -d ' ')
97+
echo "honesty-guard: $n smell(s) in $m file(s)"
98+
exit 1
99+
fi
100+
echo "honesty-guard: Clean."
101+
exit 0

verification/proofs/VERIFICATION-STANCE.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ and a fully-qualified `hasStringLit` (a bare lowercase occurrence in a
7676
*type* signature is silently auto-bound by Idris 2 as a fresh implicit,
7777
which had decoupled the predicate from its definition).
7878

79+
That same proof-escape scan runs locally (advisory-only) via `sh
80+
scripts/honesty-guard.sh [PATH…]` (default `src/`); it strips Idris line/doc/block
81+
comments before matching, so tokens merely *named* in prose are not flagged, and
82+
it exits non-zero on any escape symbol found outside a comment.
83+
7984
*New finding (Phase 1):* `src/interface/abi/Layout.idr` and
8085
`src/interface/abi/Foreign.idr` (`VclTotal.ABI.Layout/.Foreign`) do *not*
8186
compile under idris2 0.8.0 and contain *unsound* scaffolding (`paddingFor`

0 commit comments

Comments
 (0)