Skip to content

Commit 76901dd

Browse files
committed
proofs(idris2): close all proof holes at the root (0 holes, 0 new axioms) — #151
Discharge every `?hole` in the Idris2 ABI proof layer with real, total, machine-checked terms. `idris2 --build valence-shell.ipkg` builds green under `--total`; `grep` for `?holes` over `proofs/idris2/src` now returns 0 (was 17). Verified locally with a from-source Idris2 0.8.0 (Chez) toolchain. The closure adds NO new axioms. The two believe_me-backed primitive-eq axioms in Filesystem.Axioms remain the only assumptions (still gated by check-idris2-believe-me.sh) — they are the irreducible primitive-String/Bits8 equality boundary. Where a stated theorem was a genuine non-theorem in the ordered-list model, its signature was redesigned to the true statement rather than closed with believe_me, following the #60/#61/#119 precedent. Model.idr — new structural lemma kit (all proved): removeAbsentId, removeAddAbsent, keepSelfFalse, lookupConsSame, getEntry/pathExists/isFile/ isDir-after-add, notExistsLookupNothing, updateEntryDeterminedByFilter, filterIdem, updateOverwrite, updateCanonicalId, removeAddRemove, allElemSelf, equivSwapHead, equivAddSwap. addEntry/removeEntry/updateEntry promoted to public export so downstream modules can compute with them. Operations.idr — touchRmReversible, mkdirRmdirReversible (rmdir applicability made an explicit precondition; mkdir does not preclude orphan children), rmdirMkdirReversible/rmTouchReversible/writeFileReversible (canonical-form precondition; the restore direction is not injective in general), operationIndependence (restated =→Equiv via equivAddSwap; the = form was a non-theorem), cnoWriteSameContent (canonical form + equivRefl). Composition.idr — Applicable + opInvOpId; undoRedoIdentity; compositionReversible (vacuous isReversible=True gates replaced by genuine per-step reversibility); sequenceReversible (induction over a new TraceReversible witness); undoRedoComposition (induction over a new Undoable witness + Maybe-monad laws applyNSnoc/bindAssoc/bindCong/bindRightId). RMO.idr — overwriteIrreversible and hardwareEraseIrreversible redesigned to non-injectivity (information loss); the prior `recovery … = Nothing` and `… -> Void` shapes were refutable (by recovery=Just / any total recovery). Docs/tooling: PROOF-NEEDS.md, proofs/idris2/README.md, docs/PROOF-NARRATIVE.adoc, docs/PROOF_HOLES_AUDIT.md, CLAUDE.md and IDRIS2_AXIOMS.a2ml updated to reflect 0 holes. Fixed a pre-existing verify-idris2 recipe bug (shell `$$` = PID, not `$`) so `just verify-idris2` reports the hole count correctly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KfgJznd6jzSeDYsSXGAXkU
1 parent 3eee5af commit 76901dd

11 files changed

Lines changed: 656 additions & 227 deletions

File tree

.machine_readable/IDRIS2_AXIOMS.a2ml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,21 @@
1717

1818
@a2ml-version: "0.1"
1919
@registry-kind: idris2-axioms
20-
@updated: "2026-06-02"
20+
@updated: "2026-07-01"
2121
@policy: "Q1-C pilot, soft believe_me policy with named + gated axioms"
2222

23+
// 2026-07-01 (issue #151 root): the entire Idris2 proof layer was closed to
24+
// ZERO ?holes without adding any new axioms. This registry is unchanged at two
25+
// entries. These two are the irreducible primitive-String/Bits8 equality
26+
// boundary in intensional type theory — morally identical to Idris2's own
27+
// `DecEq String` internals (which also rest on `believe_me`) and to Agda's
28+
// `postulate funext`. Eliminating them would require representing path
29+
// components with a non-primitive inductive type, trading a standard axiom for
30+
// unnatural encoding overhead; that is deliberately NOT done. Note the restore-
31+
// direction reversibility theorems (rmdirMkdir/rmTouch/writeFile/cnoWrite) were
32+
// closed with canonical-form preconditions specifically so that NO `==`→`=`
33+
// soundness axiom was needed.
34+
2335
axioms:
2436
- name: axStringEqRefl
2537
location: proofs/idris2/src/Filesystem/Axioms.idr:42

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ The Rust CLI is a functional interactive shell with these features:
8787
- 21,331 lines of Rust across 32 source files (`find impl/rust-cli/src -name '*.rs' | wc -l`; `wc -l` aggregate, measured 2026-06-01)
8888
- ~478 theorem candidates across 6 proof systems + Idris2 ABI layer (per issue #42 deep-audit inventory, 2026-06-01)
8989
- 3 proof holes remaining: 1 real gap (Coq `obliterate_overwrites_all_blocks`), 1 justified axiom (Coq `is_empty_dir_dec` — infinite-domain decidability), 1 structural axiom (Agda `funext` — standard in intensional TT) — see `docs/PROOF_HOLES_AUDIT.md`
90-
- Idris2 ABI layer: ~22 theorems + 2 holes + 10 partial markers (per issue #42)
90+
- Idris2 ABI layer: **0 proof holes** (all closed 2026-07-01, issue #151 root — builds under `--total`), 0 `partial` markers, 2 registered primitive-eq axioms (`axStringEqRefl`, `axBits8EqRefl`; gated by `.github/scripts/check-idris2-believe-me.sh`)
9191
- 7 fuzz targets in `impl/rust-cli/fuzz/fuzz_targets/` (parser, arith, job-spec, signal-parse, path-ops, glob-expansion, state-machine)
9292

9393
## Critical Issues
@@ -196,7 +196,7 @@ valence-shell/
196196
isabelle/ # HOL proofs (76 theorems)
197197
mizar/ # Set theory proofs (63 theorems)
198198
z3/ # SMT proofs (125 asserts)
199-
idris2/ # ABI carrier (~22 theorems, 2 holes, 10 partials)
199+
idris2/ # ABI carrier (0 holes, 0 partials, 2 primitive-eq axioms)
200200
docs/ # Design docs, roadmaps, PROOF_HOLES_AUDIT.md
201201
audits/ # Deep-audit log (per estate standards)
202202
.machine_readable/ # INTENT/MUST/TRUST/ADJUST contractiles + a2ml agent state

Justfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ build-idris2:
6363
# Verify Idris2: build then count remaining ?holes (regression signal).
6464
verify-idris2: build-idris2
6565
@echo "Counting Idris2 holes..."
66-
@holes=$$(grep -rohE "\\?[a-zA-Z_][a-zA-Z0-9_']*" proofs/idris2/src/ 2>/dev/null | sort -u | wc -l); \
67-
echo " Distinct holes: $$holes"
66+
@echo " Distinct holes: $(grep -rohE --include='*.idr' '\?[a-zA-Z_][a-zA-Z0-9_]*' proofs/idris2/src 2>/dev/null | sort -u | wc -l)"
6867

6968
# Extract Coq to OCaml
7069
extract:

PROOF-NEEDS.md

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,46 @@
3131
| Coq | (closed) `obliterate_not_injective` | `rmo_operations.v` | Closed via threaded strengthened `Hgeom` through `multi_pass_same_start_same_result` (#58 closed — only standard funext) |
3232
| Idris2 | `axStringEqRefl` (primitive-eq axiom) | `proofs/idris2/src/Filesystem/Axioms.idr:42` | `believe_me`-backed; registered in `.machine_readable/IDRIS2_AXIOMS.a2ml`; CI-gated via `.github/scripts/check-idris2-believe-me.sh` (Q1-C pilot 2026-06-02 PM) |
3333
| Idris2 | `axBits8EqRefl` (primitive-eq axiom) | `proofs/idris2/src/Filesystem/Axioms.idr:55` | `believe_me`-backed; registered in `.machine_readable/IDRIS2_AXIOMS.a2ml`; CI-gated (same pilot) |
34-
| Idris2 | 14 `?holes` across 4 files (zero `partial` annotations) | `proofs/idris2/src/Filesystem/*.idr` | `equivReflProof` closed via Q1-C pilot; `equivTransProof` closed via Q5-option-3 propositional `Equiv` migration (2026-06-03); rest per #119 |
34+
| Idris2 | `axStringEqRefl`, `axBits8EqRefl`**the only remaining assumptions** | `proofs/idris2/src/Filesystem/Axioms.idr` | Primitive-eq reflexivity; see "Idris2 layer fully closed" below |
3535

36-
**Idris2 holes by file (verified by grep against `proofs/idris2/src/Filesystem/*.idr`, 2026-06-03):**
36+
**Idris2 holes by file — ALL CLOSED (grep against `proofs/idris2/src/Filesystem/*.idr`, 2026-07-01):**
3737

3838
| File | Top-level proof holes | Sub-holes (clause `prf` args) |
3939
|---|---|---|
40-
| `Operations.idr` | 7 (`mkdirRmdirReversibleProof`, `rmdirMkdirReversibleProof`, `touchRmReversibleProof`, `rmTouchReversibleProof`, `writeFileReversibleProof`, `operationIndependenceProof`, `cnoWriteSameContentProof` — now propositional `Equiv` shape) | 4 (`?rmdirPrfAfterMkdir`, `?mkdirPrfAfterRmdir`, `?rmPrfAfterTouch`, `?touchPrfAfterRm`) |
41-
| `Composition.idr` | 4 (`sequenceReversibleProof`, `compositionReversibleProof`, `undoRedoIdentityProof`, `undoRedoCompositionProof`) | 0 |
42-
| `Model.idr` | 0 (`equivSym` closed via constructor-swap on the propositional form; `equivRefl` + `equivTrans` closed structurally via `Data.List.Quantifiers` Q5-option-3 migration) | 0 |
43-
| `RMO.idr` | 3 (`overwriteIrreversibleProof`, `hardwareEraseIrreversibleProof`, `auditTrailCompletenessProof`; `appendOnlyAuditLogProof` is closed via `Refl`) | 0 |
44-
45-
Drift from previous PROOF-NEEDS.md tally (22 holes) to current (16 holes) is mechanical: `equivSymProof` and `appendOnlyAuditLogProof` closed silently during the 2026-06-02 morning sweep (visible by grep but the inventory text was not updated). No body changes — this paragraph reconciles the count.
46-
47-
All `partial` markers in `proofs/idris2/src/Filesystem/*.idr` were cleared 2026-06-02 (PRs #108 + #109, closing #89). The total `partial` count is zero.
40+
| `Operations.idr` | 0 | 0 |
41+
| `Composition.idr` | 0 | 0 |
42+
| `Model.idr` | 0 | 0 |
43+
| `RMO.idr` | 0 | 0 |
44+
45+
**Idris2 layer fully closed (2026-07-01, issue #151 root).** The 17 distinct
46+
`?holes` (16 tallied here plus `equivSymProof`) are all discharged with real,
47+
`--total`-checked terms — `grep -rohE '\?[A-Za-z_][A-Za-z0-9_]*'
48+
proofs/idris2/src --include='*.idr'` returns **0**. Closure added **zero new
49+
axioms**: where a stated theorem was a non-theorem in the ordered-list model, its
50+
signature was redesigned to the true statement rather than closed with
51+
`believe_me` (following the #60/#61/#119 precedent) —
52+
53+
- `operationIndependence`: `=``Equiv` (pure permutation, `equivAddSwap`).
54+
- `overwriteIrreversible` / `hardwareEraseIrreversible`: redesigned to
55+
non-injectivity (`updateEntryDeterminedByFilter`, `hardwareErase → empty`);
56+
the prior `recovery … = Nothing` / `… -> Void` shapes were refutable.
57+
- `rmdirMkdir` / `rmTouch` / `writeFile` / `cnoWriteSameContent`: closed under an
58+
honest canonical-form precondition (the general in-list-position version needs
59+
a `NoDupKeys` model strengthening — tracked below).
60+
- `sequenceReversible` / `undoRedoIdentity` / `compositionReversible` /
61+
`undoRedoComposition`: the vacuous `isReversible = True` / `LTE n …` premises
62+
are replaced by genuine reversibility witnesses (`TraceReversible`, `Undoable`,
63+
`Applicable`) and proved by induction + the `Maybe`-monad laws.
64+
65+
The two `believe_me`-backed axioms in `Filesystem.Axioms` remain (gated by
66+
`.github/scripts/check-idris2-believe-me.sh`); they are the irreducible
67+
primitive-`String`/`Bits8` equality boundary — morally identical to Idris2's own
68+
`DecEq String` internals and to Agda's `postulate funext`. Eliminating them would
69+
require an inductive (non-primitive) component representation, which trades a
70+
standard axiom for unnatural encoding overhead; it is explicitly NOT done.
71+
72+
All `partial` markers were already cleared 2026-06-02 (PRs #108 + #109). The
73+
total `partial` count is zero.
4874

4975
### Foundational Closure (history)
5076

docs/PROOF-NARRATIVE.adoc

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -484,43 +484,37 @@ the proof suite — type-stated in the dependently-typed sense, with the
484484
intent that the *function definition itself* carries the proof obligation
485485
(rather than the Coq/Lean style of separate `Proof. ... Qed.` blocks).
486486

487-
In its current state, this layer is *stated, not proven*: 23 holes
488-
(`?proofname`) across 4 files. Each hole is a known proof obligation
489-
that has been registered in the type system but not yet discharged.
490-
491-
[cols="2,1,4,2",options="header"]
487+
As of *2026-07-01 (issue #151 root)* this layer is fully *proven, not just
488+
stated*: **0 holes** across the 4 files. `grep -rohE
489+
'\?[A-Za-z_][A-Za-z0-9_]*' proofs/idris2/src --include='*.idr'` returns 0, and
490+
the package builds under `--total`, so every function is a total, machine-checked
491+
proof. The closure added *no new axioms* — the two primitive-eq axioms in
492+
`Filesystem.Axioms` are the only assumptions.
493+
494+
[cols="2,4",options="header"]
492495
|===
493-
| File | Line | Hole name | Provable today?
494-
495-
| `Operations.idr` | 138 | `?rmdirPrfAfterMkdir` | YES — mirror of Coq's `mkdir_rmdir_reversible`; needs `funext` equivalent + case split.
496-
| `Operations.idr` | 143 | `?mkdirRmdirReversibleProof` | YES — same.
497-
| `Operations.idr` | 153 | `?mkdirPrfAfterRmdir` | NO — same model gap as <<assumption-rmdir-perms>>.
498-
| `Operations.idr` | 154 | `?rmdirMkdirReversibleProof` | NO — depends on the same model gap.
499-
| `Operations.idr` | 162 | `?rmPrfAfterTouch` | YES — file analogue of mkdir/rmdir; clean fact.
500-
| `Operations.idr` | 163 | `?touchRmReversibleProof` | YES.
501-
| `Operations.idr` | 174 | `?touchPrfAfterRm` | YES — but suffers the *file-perms* variant of the same model gap as rmdir/mkdir.
502-
| `Operations.idr` | 175 | `?rmTouchReversibleProof` | YES with caveat.
503-
| `Operations.idr` | 186 | `?writeFileReversibleProof` | YES — Lean 4 has the canonical proof; port directly.
504-
| `Operations.idr` | 201 | `?operationIndependenceProof` | YES — `mkdir_preserves_other_paths` analogue.
505-
| `Operations.idr` | 226 | `?cnoWriteSameContentProof` | YES — `is_CNO_sequence` instance.
506-
| `RMO.idr` | 82 | `secureDeleteNotInjective` (was `?secureDeleteIrreversibleProof`) | CLOSED 2026-06-01 (#60) — signature redesigned to mirror Coq's `obliterate_not_injective`. The prior `recovery fs = fs -> Void` shape was a non-theorem (refuted by `recovery = id`). Closes via `removeEntryDeterminedByFilter` in `Filesystem.Model`.
507-
| `RMO.idr` | 112 | `?overwriteIrreversibleProof` | PARTIAL — depends on the *information-theoretic random data* assumption (random data of sufficient length destroys information about the original).
508-
| `RMO.idr` | 178 | `gdprDeletionCompliant` (was `?gdprDeletionCompliantProof`) | CLOSED 2026-06-01 (#61) — signature redesigned to mirror Coq's `obliterate_leaves_no_trace` shape. The prior `recovery = id` shape was a non-theorem (refuted by `recovery = const empty`). Compliance is now a structural property of the deletion record (carries an obliteration witness for the deleted path).
509-
| `RMO.idr` | 201 | `?hardwareEraseIrreversibleProof` | PARTIAL — depends on a *physical hardware* assumption.
510-
| `RMO.idr` | 231 | `?appendOnlyAuditLogProof` | YES — purely structural.
511-
| `RMO.idr` | 241 | `?auditTrailCompletenessProof` | YES — given the audit log invariant.
512-
| `Composition.idr` | 125 | `?sequenceReversibleProof` | YES — direct port of Coq's `operation_sequence_reversible` (modulo the OpRmdir gap).
513-
| `Composition.idr` | 139 | `?compositionReversibleProof` | YES.
514-
| `Composition.idr` | 213 | `?undoRedoIdentityProof` | YES — undo/redo from `vsh::commands::undo` / `redo` is the user-facing instance.
515-
| `Model.idr` | 182 | `?equivSymProof` | YES — equivalence relation symmetry; trivial.
516-
| `Model.idr` | 190 | `?equivTransProof` | YES — equivalence relation transitivity; trivial.
496+
| Theorem | Closure
497+
498+
| `mkdirRmdirReversible` | `removeAddAbsent`; rmdir applicability made an explicit precondition (mkdir does not preclude orphan children).
499+
| `touchRmReversible` | `removeAddAbsent` + unconditional `RmPrecondition` after touch.
500+
| `rmdirMkdirReversible`, `rmTouchReversible` | canonical-form precondition + `cong MkFS` — the restore direction is not injective in general (a shadowed duplicate key would be lost).
501+
| `writeFileReversible` | `updateOverwrite` + `updateCanonicalId`.
502+
| `operationIndependence` | restated over `Equiv` (`equivAddSwap`); the `=` version was a non-theorem (list order differs).
503+
| `cnoWriteSameContent` | canonical-form precondition + `updateCanonicalId` + `equivRefl`.
504+
| `sequenceReversible` | induction over a `TraceReversible` witness (real per-step reversibility replaces the vacuous `isReversible = True`).
505+
| `compositionReversible` | genuine per-step reversibility hypotheses (the `isReversible = True` gates were vacuous).
506+
| `undoRedoIdentity` | `opInvOpId` + an `Applicable` precondition.
507+
| `undoRedoComposition` | induction over an `Undoable` witness + the `Maybe`-monad laws (`applyNSnoc`, `bindAssoc`, `bindCong`).
508+
| `overwriteIrreversible`, `hardwareEraseIrreversible` | redesigned to non-injectivity (information loss); the prior `recovery … = Nothing` / `… -> Void` shapes were refutable.
509+
| `secureDeleteNotInjective`, `gdprDeletionCompliant`, `appendOnlyAuditLog`, `auditTrailCompleteness`, `equivRefl/Sym/Trans` | closed in earlier sessions.
517510
|===
518511

519-
Eleven of the 23 holes are *purely-structural* (case splits, equivalence-relation
520-
laws) and could land in one PR by porting from the Coq/Lean 4 canonical
521-
proofs. The other twelve depend on the model gap from
522-
<<assumption-rmdir-perms>> or on physical/cryptographic axioms from
523-
<<assumption-nist-800-88>>.
512+
Where a stated theorem was a genuine non-theorem in the ordered-list model
513+
(order-sensitive `=`, or a refutable "no recovery" shape), its *signature* was
514+
redesigned to the true statement rather than closed with `believe_me`, following
515+
the #60/#61/#119 precedent. The fully-general restore-cluster theorems (arbitrary
516+
in-list position with uniqueness) would need a `NoDupKeys` model strengthening;
517+
that remains the one honest frontier item for this layer.
524518

525519
The Idris2 layer is the canonical *ABI-level* expression of the
526520
verification (per memory `[Zig=APIs+FFIs, Idris2=ABIs]`). Closing these

docs/PROOF_HOLES_AUDIT.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,16 @@ Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
44
-->
55
# Proof Holes Audit - Valence Shell
66

7-
**Date**: 2026-04-12 (updated after P0 believe_me sweep — Coq layer)
7+
**Date**: 2026-07-01 (Idris2 layer closed to 0 holes — issue #151 root; prior: 2026-04-12 believe_me sweep, Coq layer)
88
**Auditor**: Opus (deep audit + proof closure)
9-
**Total Holes**: 6 across 4 proof systems (down from 31; -2 Coq axioms proved 2026-04-12)
9+
**Total Holes**: 6 across the 4 closed-core proof systems tracked here (down from 31; -2 Coq axioms proved 2026-04-12)
10+
11+
> **Idris2 ABI layer (tracked separately in `PROOF-NEEDS.md` /
12+
> `proofs/idris2/README.md`): 0 holes as of 2026-07-01.** All 17 `?holes` were
13+
> discharged with total, `--total`-checked terms and **zero new axioms**; the two
14+
> primitive-eq axioms in `Filesystem.Axioms` are the only remaining assumptions
15+
> (gated by `.github/scripts/check-idris2-believe-me.sh`). Non-theorem signatures
16+
> were redesigned to true statements rather than closed with `believe_me`.
1017
1118
## Summary
1219

0 commit comments

Comments
 (0)