mirror of
https://github.com/saymrwulf/ltl-accumulator-verified.git
synced 2026-09-03 19:53:48 +00:00
Round-2 external reviews (GPT-5.6 + second Claude) converged on the coverage gate being evadable (H1/NEW-1); GPT additionally proved the kit's fidelity target could not run (H2) and the namespace-collision attack that defeats any source-regex fix. This round adopts GPT's required correction in full: - Proofs/Inventory.lean: declaration inventory read from the compiled Lean environment — every constant of every corpus module, fully qualified, unfiltered (compiler auxiliaries and _private mangles pinned too), with kind and axiom cone; own cone walker cross-checked in-process against core collectAxioms (hard error on divergence). - verification/inventory-allowlist.txt: all 218 constants pinned. - inventory_gate.sh: fail-closed diff both directions (UNCLASSIFIED / STALE), INV-COUNT truncation guard, exactly-one-axiom invariant. - check.sh Phase 3b rewritten around the gate + manifest⇔inventory drift checks + CONES⇔inventory cone cross-check (two independent computations must agree). EXCLUDE table gone (sha256/Bytes are ordinary audited entries now). - selftest_audit.sh: 9 adversarial cases against the production gate (attributed/indented/private/instance, namespace collision, smuggled axiom, deleted decl, unmanifested Proofs/ and gen/ modules) + positive control — all defeated (GPT release condition 2). - M1: recursive orphan-olean guard (caught a stray dev artifact on its first run), gen/ dead-file check, corpus-wide single-axiom pin. - L1/NEW-2: acceptIncl_sound drops the redundant hm (derived from hacc.1); cone unchanged. - M2/M3: STATEMENT-MAP counts 230,271/230,016; non-vacuity guard wording narrowed to what the guards actually certify. - README layer table: stale L4/pin-store rows fixed (missed by both round-2 reviewers AND the round-2 revision — found in self-review). - KNOWN-GAPS 12 (audit-gate lineage + residual limits), 13 (round-2 kit target not self-contained); gap 2 count fixed. - RESPONSE-TO-REVIEWERS.md: round-3 disposition of every finding. Kit round 3 additionally ships the complete stdlib-only import closure of pacta.transparency (content-addressed vs pacta 3d81d53), the clean-extraction fidelity transcript (exit 0, 230,271+230,016, zero mismatches), the ATTESTATION GREEN check.sh transcript, and the self-test transcript. The live LTL remains untouched (12 leaves, root bcd15f9d…); attestation stays blocked pending ePrint decision + author review + explicit operator order. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
52 lines
2.6 KiB
Bash
Executable file
52 lines
2.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# inventory_gate.sh — diff an observed environment inventory against the
|
|
# pinned allowlist. This is THE production coverage gate: check.sh Phase 3b
|
|
# calls it, and selftest_audit.sh exercises this exact script against
|
|
# injected evader declarations — the tested logic IS the shipping logic.
|
|
#
|
|
# Usage: inventory_gate.sh <observed-lean-output> <allowlist-file>
|
|
#
|
|
# Fail-closed in BOTH directions:
|
|
# UNCLASSIFIED — constant in the environment, absent from the allowlist
|
|
# (new/renamed decl, changed kind, or changed axiom cone)
|
|
# STALE — allowlist entry absent from the environment
|
|
# plus an output-integrity check: the INV-COUNT trailer emitted by
|
|
# Proofs/Inventory.lean must equal the number of INV lines actually seen,
|
|
# so a truncated or crashed run can never pass as an empty diff.
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
set -uo pipefail
|
|
export LC_ALL=C # byte-order collation: sort/comm must agree with Lean's String order
|
|
obs_file="$1"; allow_file="$2"
|
|
|
|
OBS=$(grep '^INV|' "$obs_file" | sort -u)
|
|
N_OBS=$(printf '%s' "$OBS" | grep -c '^INV|' || true)
|
|
TRAILER=$(grep '^INV-COUNT|' "$obs_file" | tail -1 | cut -d'|' -f2)
|
|
if [ -z "$TRAILER" ] || [ "$TRAILER" != "$N_OBS" ]; then
|
|
echo " INVENTORY TRUNCATED: trailer=${TRAILER:-absent}, observed $N_OBS lines"
|
|
exit 1
|
|
fi
|
|
|
|
ALLOW=$(grep '^INV|' "$allow_file" | sort -u)
|
|
FAILGATE=0
|
|
UNCLASS=$(comm -23 <(printf '%s\n' "$OBS") <(printf '%s\n' "$ALLOW"))
|
|
STALE=$(comm -13 <(printf '%s\n' "$OBS") <(printf '%s\n' "$ALLOW"))
|
|
if [ -n "$UNCLASS" ]; then
|
|
printf '%s\n' "$UNCLASS" | sed 's/^/ UNCLASSIFIED (in environment, not allowlisted): /'
|
|
FAILGATE=1
|
|
fi
|
|
if [ -n "$STALE" ]; then
|
|
printf '%s\n' "$STALE" | sed 's/^/ STALE (allowlisted, not in environment): /'
|
|
FAILGATE=1
|
|
fi
|
|
|
|
# The corpus admits exactly one axiom, and it is the sanctioned boundary.
|
|
AXLINES=$(printf '%s\n' "$OBS" | grep '|axiom|' || true)
|
|
if [ "$AXLINES" != "INV|LTLAcc.sha256|axiom|LTLAcc.sha256" ]; then
|
|
echo " AXIOM SURFACE DRIFT: expected exactly LTLAcc.sha256, observed:"
|
|
printf '%s\n' "${AXLINES:- (none)}" | sed 's/^/ /'
|
|
FAILGATE=1
|
|
fi
|
|
|
|
[ "$FAILGATE" = 0 ] && echo " inventory gate: $N_OBS constants, environment == allowlist, single sanctioned axiom"
|
|
exit "$FAILGATE"
|