- 1. Tier S — Foundational gaps
- 2. Tier A — Single-PR proofs (each tractable in <1 day)
- 2.1. A-1. Idris2
?equivSymProofand?equivTransProof - 2.2. A-2. Idris2
?writeFileReversibleProof - 2.3. A-3. Idris2
?operationIndependenceProof - 2.4. A-4. Idris2
?cnoWriteSameContentProof - 2.5. A-5. Idris2
?appendOnlyAuditLogProof - 2.6. A-6. Glob expansion termination + complexity
- 2.7. A-7. Arithmetic expansion correctness vs POSIX
arith.h - 2.8. A-8. Short-circuit evaluation for
&&/|| - 2.9. A-9. Pipe associativity
- 2.10. A-10. Redirection
>vs>>distinction - 2.11. A-11. Quote-context preservation
- 2.12. A-12. Path traversal containment
- 2.1. A-1. Idris2
- 3. Tier B — Multi-day proofs
- 3.1. B-1. POSIX 2024 conformance proofs
- 3.2. B-2. Subshell
(…)syntax + scoping - 3.3. B-3. Word splitting under quote-context
- 3.4. B-4. Pipeline data-flow correctness
- 3.5. B-5. Job control state machine
- 3.6. B-6. Symlink resolution loop detection
- 3.7. B-7. Audit log HMAC signing + verification
- 3.8. B-8. MCP protocol response conformance
- 4. Tier C — Marginal but still valuable
- 4.1. C-1. Reverse-direction reversibility for file content writes
- 4.2. C-2. Empty-sequence and singleton-sequence base cases
- 4.3. C-3. CNO algebra: associativity under sequence concatenation
- 4.4. C-4.
parent_pathidempotence at root - 4.5. C-5.
well_formedis preserved by every reversible operation - 4.6. C-6.
path_prefixlattice laws - 4.7. C-7.
default_permsis the identity in the perm monoid - 4.8. C-8. Idempotent operations:
mkdir p (mkdir p fs)should fail under preconditions - 4.9. C-9. Operation transposition: when do two ops commute?
- 4.10. C-10.
apply_sequenceis a fold
- 5. Tier D — Meta / process / tooling
- 6. Methodology notes
- 7. Open questions
- 8. Changelog
This is the companion to PROOF-NARRATIVE.adoc. The narrative documents
what is proven; this document catalogues every valuable proof not yet
attempted, including marginal ones — per the directive on 2026-06-01
("identify every single proof that would be valuable to do, even
marginal stuff").
The entries are ordered by tractability × value, not alphabetically. Each entry includes: the statement, why it matters, the lift relative to existing infrastructure, and any precondition gates.
These items underpin the credibility of the rest of the verification. Closing any of them moves the bar materially.
| Field | Value |
|---|---|
Statement (informal) |
The Rust function |
Why |
|
Lift |
Large. Requires choosing an extraction target (Lean 4 → C via |
Gates |
None — orthogonal to other proofs. Could land incrementally per op. |
First tractable slice |
|
| Field | Value |
|---|---|
Statement |
|
Why |
Eliminates the only |
Lift |
Small. ~30 lines of Coq. The strengthened precondition propagates trivially through |
Gates |
None. |
Risk |
Strengthening |
| Field | Value |
|---|---|
Statement |
If a transaction is interrupted (SIGKILL, power loss) between |
Why |
|
Lift |
Large. Requires modelling the WAL/undo log explicitly. Today there is no formal model of the undo log; the Rust implementation uses |
Gates |
Need to model |
First tractable slice |
Prove: after SIGKILL between two |
| Field | Value |
|---|---|
Statement |
For two |
Why |
Today’s model is single-process. Real shells share a filesystem with other shells, daemons, and the kernel. Without a concurrency proof, all guarantees are "single-shell" guarantees. |
Lift |
Very large. Requires a concurrent semantics (e.g. |
Gates |
Need to choose a concurrency framework. Iris in Coq is the strongest match. |
First tractable slice |
Prove serializability for two non-overlapping-path operations. Trivial under per-path locks. |
Model.idr:182 and Model.idr:190. Pure equivalence-relation laws. Direct
import of Idris2’s Equivalence interface. ~10 lines each.
Operations.idr:186. Port the Lean 4 canonical proof
(FileContentOperations.lean::writeFileReversible). The proof structure
maps 1:1; only the syntax differs.
Operations.idr:201. Direct mirror of Coq’s mkdir_preserves_other_paths.
Pure case split on path equality.
Operations.idr:226. Connect to the is_CNO_sequence named consequence
in proofs/coq/filesystem_composition.v:279.
RMO.idr:231. Structural: append always extends the log; never shortens. Pure induction on list length.
| Statement | expand_glob(pattern, base_dir) terminates in time `O( |
|---|---|
pattern |
× |
files_in_base_dir |
)`. |
File |
|
Why |
Glob expansion is a frequent attack surface for DoS in shells. A complexity bound is a real security property. |
Lift |
Property test ( |
| Statement | For any $expr, vsh::arith::eval(expr) returns the same value as the POSIX-defined arith semantics for expr. |
|---|---|
File |
|
Why |
A shell bug in arithmetic expansion can silently corrupt scripts. Current cover is ~50 unit tests. |
Lift |
Define a Lean 4 model of POSIX arith semantics; prove equivalence to Rust by inspection of operator table. |
| Statement | For cmd1 && cmd2: if cmd1 exits non-zero, cmd2 is not executed. Left-to-right parsing: `a && b |
|---|---|
c` parses as `(a && b) |
|
c`. |
|
File |
|
Why |
Critical to script semantics. The 2026-02-12 fix is a real bug closed; a proof prevents regression. |
Lift |
Pratt-style precedence test (one new test file under |
| Statement | cmd1 | cmd2 | cmd3 has the same observable effect as cmd1 | (cmd2 | cmd3) and as (cmd1 | cmd2) | cmd3. Pipe composition is associative under stream equality. |
|---|---|
File |
|
Why |
The Unix pipe identity. Trivial-looking; rarely actually proven. |
Lift |
Property test; then a Lean 4 lemma if desired. |
| Statement | cmd > file truncates file to the output of cmd. cmd >> file appends. Specifically: (cmd1 > file; cmd2 >> file) = file contains output(cmd2) appended to output(cmd1). |
|---|---|
File |
|
Why |
Same "real bug, prove the fix" pattern as A-8. Short-circuit evaluation for |
Lift |
One property test asserting the file contents post-condition. |
| Statement | "a $var b" preserves spaces; 'a $var b' preserves dollar; \$var produces literal $var. The quote-context invariant. |
|---|---|
File |
|
Why |
The single largest source of shell parser bugs across all shells. |
Lift |
Pratt-style test matrix covering all (quote-type × content-type) combinations. |
| Statement | For vsh::resolve_path(p) with sandbox root /sandbox/: the resolved path is always a descendant of /sandbox/, regardless of .. components in p. |
|---|---|
File |
|
Why |
Security-critical. The 2026-02-12 fix is a real CVE-class bug closed. A proof prevents regression. |
Lift |
Property test with random |
| Statement | For each POSIX 2024 feature the shell claims (M1-M11 in docs/POSIX_COMPLIANCE.md), prove the implemented behaviour matches the POSIX 2024 specification. |
|---|---|
Why |
POSIX-conformance claims today are based on test pass/fail. A spec-level proof is a different kind of evidence. |
Lift |
Per feature, ~2 days. M1-M9 are complete (per CLAUDE.md); M10-M11 partial. |
Gates |
None. |
| Statement | (cmd) creates a new shell context; variables set inside do not leak to the parent. |
|---|---|
Why |
Missing today per CLAUDE.md "What Does NOT Work". Adding the proof first forces the implementation to be correct. |
Lift |
Medium. Requires a scope-stack in the model. |
| Statement | For cmd $var: if $var is unquoted, the value of $var is word-split on $IFS characters. If quoted ("$var"), no splitting occurs. |
|---|---|
Why |
Missing today per CLAUDE.md "Immediate Priorities". The classic POSIX shell trap. |
Lift |
Medium. Requires threading quote-context through the parser AST. |
| Statement | For cmd1 | cmd2: every byte that cmd1 writes to stdout is read by cmd2 from stdin, in order, with no loss or reordering. |
|---|---|
Why |
The fundamental Unix pipeline guarantee. Easy to state, surprisingly hard to prove without a stream model. |
Lift |
Medium. Requires a stream/queue model in the proof assistant. |
| Statement | The job state machine (Running → Stopped → Running |
|---|---|
|
File |
|
Why |
Job control is a known source of subtle bugs. |
Lift |
| Statement | resolve_symlink_chain terminates even when the chain is cyclic. Returns ELOOP if a cycle is detected within MAXSYMLINKS steps. |
|---|---|
File |
|
Why |
Real POSIX systems have a |
Lift |
Medium. Cycle detection in directed graphs; standard literature. |
| Statement | audit_log_append(entry) produces a log entry whose HMAC-SHA256 signature is verifiable iff the entry was added through the official API. |
|---|---|
File |
|
Why |
Audit log is GDPR/compliance critical. The append-only property is half the story; tamper-detection via HMAC is the other half. |
Lift |
Small implementation, medium proof. The proof is about the HMAC key not being compromised, which is an external assumption. |
| Statement | Every MCP tool handler in impl/mcp/src/Server.res returns a JSON response that satisfies the MCP protocol schema. |
|---|---|
File |
|
Why |
An MCP tool that returns non-conforming JSON silently breaks the protocol; clients get garbage. |
Lift |
Medium. Define the MCP schema in ReScript types + ensure |
writeFileReversible proves forward direction. The reverse (write back
the original content recovers the previous) is implied but not stated
as a named theorem.
operation_sequence_reversible proves the inductive case. The base
cases (empty list, single op) deserve their own theorems for clarity in
proof traces.
is_CNO_sequence says reversing an op-and-its-inverse is a no-op. The
algebra of CNOs — that CNO sequences compose to CNO sequences — is
not stated.
parent_path root_path = root_path. Useful as a corollary; never
stated.
The Coq layer proves mkdir_preserves_well_formed (2026-04-12). The
analogous theorems for rmdir, create_file, delete_file are
implicit but not stated.
path_prefix is a partial order on paths. The lattice laws
(reflexivity, antisymmetry, transitivity, least-upper-bound for the
shared prefix) are useful corollaries.
If we frame Permissions as a monoid under "intersect" (most-restrictive),
default_perms = (true,true,true) is the identity. Pure category-theory
lemma; useful for the chmod proofs.
The forward proof requires ¬ path_exists. So mkdir p (mkdir p fs)
is undefined under the model. State this explicitly via a negative
theorem.
For op1 at p1 and op2 at p2 with p1 ≠ p2, apply_op op2 ∘ apply_op op1 = apply_op op1 ∘ apply_op op2.
Implied by the preserves_other_paths family but never stated as a single transposition law.
Add a CI job that runs Print Assumptions <every_theorem>. for every
Coq theorem and grep-fails if any assumption other than
Coq.Logic.FunctionalExtensionality appears.
This is the load-bearing CI rule for the proof layer. Without it,
silent drift (a re-introduced admit. or Axiom) is not caught.
Add a CI job that fails the build if any new ?holename appears in
proofs/idris2/src/*/.idr.
Today the same theorem has slightly different names per system
(mkdir_rmdir_reversible in Coq, mkdir_rmdir_reversible in Lean,
mkdir-rmdir-reversible in Agda, mkdirRmdirReversible in Idris2).
Standardise to one name per cross-system convention; mechanise the
check.
Generate the per-system theorem-count table in PROOF-NARRATIVE.adoc
from the actual source files, not by hand. Avoids the kind of drift
that left PROOF-NEEDS.md two months stale.
-
Why "even marginal" matters. A small theorem (e.g. C-4.
parent_pathidempotence at root) costs minutes to state and seconds to check, but it documents an invariant that future code might silently break. The cumulative effect of catalogued marginalia is a much harder system to regress. -
Witness-count is the metric, not theorem-count. A theorem with one witness is fragile; a theorem with five is robust. The cross-system matrix in
PROOF-NARRATIVE.adoc#witness-matrixreads as the audit trail for "how confident are we, really?". -
Assumptions are theorems too. Anything
admit-ted,postulate-d,Axiom-defined, or left as?holeis a registered assumption. Treat it as a theorem-shaped IOU. ThePrint Assumptionsdiscipline (D-1. Print Assumptions guard in CI) is what makes this enforceable. -
Empirical vs mechanised proofs are different evidence. Pratt-style precedence tests (A-8. Short-circuit evaluation for
&&/||, A-11. Quote-context preservation) andproptest-style property tests are evidence; they are not proofs. The narrative explicitly tags which is which.
-
Should the Idris2 layer (23 holes) be promoted to a load-bearing status equal to the Coq/Lean 4 layer, or kept as an ABI-stub tier? Per the estate memory
[Zig=APIs+FFIs, Idris2=ABIs], the Idris2 layer is the canonical ABI expression — closing the holes is high priority but the timing is open. -
For the Lean→Rust mechanised refinement (F-1. Lean → Rust mechanised refinement), is the target Lean 4 → C extraction or Lean 4 → OCaml? Choice affects the refinement framework.
-
The crash-consistency proof (F-3. Crash-consistency for begin/commit/rollback) requires modelling the undo log. Is the model (a)
Filesystem × UndoLog, (b)Filesystemwith an embedded log per node, or (c) a separateLogStatethat pairs with the filesystem? Choice affects every downstream theorem.