Research / Formal and PL core

P02 · full · draft

Mechanized Soundness of Derived LIFO Teardown, WAL Discharge and No-Residue

partial full Formal and PL core

State of the work. Lean theorems for teardown, WAL discharge and no-residue and a differential oracle against the Python runtime are on main; roll-forward, failure during teardown and cascading abort are not modelled, and no mutation study of the oracle exists.

This is a draft, not peer reviewed. Repository references link to revl at commit 45bec431f.

Pitch

A Lean development, tied to the shipped Python runtime and recovery code by a differential oracle that runs them, shows, for the modelled fragment, that derived teardown replays exactly the right entries in the right order per verdict, that a failed body is reverted from a write-ahead log, and that what an abort leaves behind is exactly what the runtime reports.

Abstract

Languages that derive cleanup order from structure, rather than letting authors write it, owe their users a precise statement of what the derived teardown does under each outcome. We give one for revl, whose per-activation stack holds three entry kinds (bracket, transactional, compensation) and is unwound in two phases under a verdict (commit, abort, or the operator halt). In Lean 4 we prove, with no sorry and no project axioms (the CI axioms gate checks this; it was not re-run for this write-up), that (G7) the set of entries replayed, their order, and the phase split are determined by kind and verdict, with replay, discharge and strand forming an exact partition; that (A8) a body that fails after taking witnessed steps has its world restored by replaying its write-ahead log, that the commit marker is the roll-back-or-roll-forward decision (a specification-agreement statement by the file's own account), and that an undeclared inverse is never applied twice across a crash cut; and that (R4) the world after an abort equals the starting world plus exactly the residue the runtime reports. The models are small on purpose, so the proofs are tied to the implementation by a differential oracle that drives the shipped runtime over an enumerated scenario corpus (267 teardown scenarios, 1620 WAL scenarios) and fails the build if the corpus stops distinguishing LIFO from FIFO or phase 2 from phase 1. The oracle found one real divergence, where the model claimed a clean re-issue and the code refuses and reports residue (60 of 1620 scenarios). We also report what is not proved: failure of an inverse during teardown, the roll-forward residue surface, escrow and cascading abort.

Problem and claim

revl derives teardown: the author writes each effect beside its inverse, and the runtime unwinds the stack. That is only worth something if one can say exactly what the unwinding does. The design doc has to answer questions a naive "LIFO" does not: a transactional entry is discharged, not replayed, on a clean commit; a compensation is deferred to a second phase on abort; an operator halt replays and discharges nothing. An earlier version of the Lean model had one entry kind and replayed everything, and was found to contradict the runtime (formal/RevL/Theorems/G7_LifoComplete.lean:5-24). The statements had to be made relative to kind and verdict.

The claim is a mechanized account of three things: which entries run and in what order (G7), that failure reverts and the commit marker decides recovery across a crash (A8), and that abort leaves no residue except what is reported (R4). The limits are part of the claim: the models cover a small fragment and say so, and the status file lists the rest as unproved.

The paper also carries a methodological claim that is checkable: a proof about a model of a runtime is only useful if the model is run against the runtime. The oracle part is what separates this from proving a spec.

Contributions

  1. G7: a mechanized statement that, per entry kind and verdict, replay, discharge and strand are an exact partition; completeness and soundness of the replayed set; the LIFO equation; the two-phase split (compensations drain after the proof pass); LIFO within each phase; and the halted verdict, which replays nothing, discharges nothing and strands everything, with a total inventory of a halt cut into completed, ambiguous (at most one) and unattempted (formal/RevL/Theorems/G7_LifoComplete.lean:46-392; formal/RevL/Semantics.lean:125-135).
  2. A8: revert_on_failure over a small-step semantics in which the log is the trace; crash_cut_converges, the commit-decision theorem and approved_decides_the_crash_window; fence_before_apply_at_every_cut and at_most_once_across_crash for undeclared inverses (formal/RevL/Theorems/A8_WalDischarge.lean:103, :207, :224, :240, :256, :271).
  3. R4: residue_is_exactly_what_remains (the post-abort world is the starting world plus the reported residue), its corollary abort_leaves_no_residue when no emission occurred, and residue_necessary, which shows the side condition cannot be dropped (formal/RevL/Theorems/R4_NoResidue.lean:75, :98, :174).
  4. Supporting rules: A2 (no acquisition after a provision), A5 (compensation accompanies an emission), and capability ceilings, each with its own theorem file (formal/RevL/Theorems/A2_NoAcquisitionAfterProvision.lean, formal/RevL/Theorems/A5_CompensationAccompaniesEmission.lean, formal/RevL/Theorems/CapCeilings.lean).
  5. A differential oracle that runs backends/python/runtime.py and src/revl/recovery.py over enumerated scenario corpora and diffs observed dispositions against the model's predictions, with a coverage ratchet that fails the gate if the corpus stops biting (formal/harness/diff_corpus.py:4876-4960; formal/STATUS.md, rows G7, A8, R4).
  6. An honesty ledger: per guarantee, whether it is full, partial or absent, the kind of gap (modelling limit or unbuilt work), and which statements are contentless or specification-agreement only (formal/STATUS.md:44-72; formal/RevL/Theorems/A8_WalDischarge.lean:32-48).

Evidence on main

ClaimWhereStatusNote
G7 replay table per kind and verdictformal/RevL/Theorems/G7_LifoComplete.lean:46 (replay_table, by decide)shippedHeader explains the pre-fix model was wrong (lines 5-24)
Completeness and soundness of the replayed setformal/RevL/Theorems/G7_LifoComplete.lean:59, :85shipped
LIFO equation, two-phase split, LIFO per phaseformal/RevL/Theorems/G7_LifoComplete.lean:170, :184, :204, :209shipped
Commit discharges transactional and compensation; commit replays only bracketsformal/RevL/Theorems/G7_LifoComplete.lean:109, :119, :127shippedNon-vacuity witnesses at lines 426-484
Halted verdict: replays nothing, discharges nothing, strands allformal/RevL/Theorems/G7_LifoComplete.lean:233, :251, :262; formal/RevL/Semantics.lean:125-135shippedsettles_iff_not_halted (line 293) shows the settles hypothesis excludes exactly halted
Halt inventory is total, ambiguity at most oneformal/RevL/Theorems/G7_LifoComplete.lean:373, :383, :392shipped
Disposition trichotomyformal/RevL/Semantics.lean:134shipped
A8 revert on failureformal/RevL/Theorems/A8_WalDischarge.lean:103; witness at 412-415shippedFragment of five body forms; the witnessed step collapses a real window (formal/RevL/Lemmas/WalLemmas.lean:701; R4 header)
Crash cut convergence and commit decisionformal/RevL/Theorems/A8_WalDischarge.lean:207, :224, :240partial: 207 carries real content; 224 and 240 are specification agreementThe header says 224 and 240 are specification-agreement statements and not deep results
At most once across a crashformal/RevL/Theorems/A8_WalDischarge.lean:256, :271, :295, :308shippedDurability (fsync) is "a floor, not a theorem" (formal/STATUS.md:2209; formal/RevL/Theorems/A8_WalDischarge.lean:86-89)
outcome_trichotomyformal/RevL/Theorems/A8_WalDischarge.lean:170shipped but definitionalThe file says so (header, "What each theorem is worth")
R4 exact residue equation and corollaryformal/RevL/Theorems/R4_NoResidue.lean:75, :98, :119, :130shippedScope is the abort path only
R4 side condition is necessaryformal/RevL/Theorems/R4_NoResidue.lean:174, :188, :199shippedConcrete runs txnLog and emitLog
No sorry in the three filesgrep -c sorry on the G7, A8, R4, A2, A5 and G4 theorem files returned 0; gate: formal/scripts/axioms_gate.py, formal/CheckAxioms.leanshippedThe gate runs in CI job formal (.github/workflows/ci.yml:2521-2540), which skips pull_request events; formal/CheckAxioms.lean prints the G7, A8 and R4 theorems
Differential oracle runs the real runtime and recoveryformal/harness/diff_corpus.py:4876 (teardown_coverage); formal/STATUS.md G7/A8 rowsshippedStatus file, G7 row: "RUNS backends/python/runtime.py"; A8 row: it writes each scenario as a real JSON-Lines WAL and runs src/revl/recovery.py
Oracle found a model/implementation divergenceformal/STATUS.md:1675-1686; test tests/test_idempotent_inverse_309.py (test_undeclared_boundary_inverse_applies_once_then_fenced)shipped60 of 1620 scenarios disagreed before the fix
Roll-forward residue, cascading abort, escrow, failure of an inverse during teardownformal/STATUS.md G7, A8, R4 rows ("Still deliberately not modelled", "Unbuilt work")not modelledSee limits
A3 and T1-T3formal/STATUS.md A3 and T1/T2/T3 rows: no theoremnot proved"Out of scope by kind"

Numbers that exist

Paper outline

  1. Introduction: derived teardown needs a precise contract; what contradicted the first model.
  2. The teardown contract: three entry kinds, two phases, three verdicts (docs/design/teardown-contract.md:42-100).
  3. G7 in Lean: model, five statements, the halt, and why settles costs exactly one verdict.
  4. The WAL and A8: small-step semantics, revert on failure, the decision marker, at-most-once across crash cuts.
  5. R4: the exact residue equation and why the side condition is necessary.
  6. From model to implementation: the differential oracle, coverage ratchets, the divergence it found.
  7. The honesty ledger: what is full, partial, contentless or unproved, and which gaps are modelling limits versus unbuilt work.
  8. Evaluation: a mutation study of the oracle, proof effort.
  9. Related work and conclusion.

Threats to validity and limits

Fact-check

Claims in this draft were checked against revl main at commit 45bec431f: 17 checked, 11 corrected.

Cite this draft

@misc{revlp02,
  author       = {Thomas Moussajee},
  title        = {Mechanized Soundness of Derived LIFO Teardown, WAL Discharge and No-Residue},
  year         = {2026},
  howpublished = {\url{https://inso1337.github.io/revl/research/P02.html}},
  note         = {Research draft, not peer reviewed. Written against revl commit 45bec431f. Licensed CC BY 4.0.}
}

Text licensed CC BY 4.0, author Thomas Moussajee.

← All research drafts