Liking cljdoc? Tell your friends :D

Formal-verification map — the invariant–model–proof correspondence

Navigation: ↑ Persistence architecture · Durability & recovery · Concurrency model · Formal-verification tree

The durability and concurrency claims made throughout this corpus are not asserted — they are machine-checked. This page is the correspondence index: for each persistence invariant, it names the TLA⁺ model that model-checks it and the Rocq proof that establishes it, and links the doc that relies on it. It does not restate the proofs; the authoritative source is formal-verification/ and its VERIFICATION_RESULTS.md.

The two-pronged strategy

Verification divides the obligation space cleanly between two tools, tied to the running Rust by an executable correspondence harness:

The map is drawn as two companion figures — one per prong — so each fits the prose column; both prongs tie to the same implementation-under-test and correspondence harness.

Proof-artifact map, part ① of ② — the TLA+/TLC model-checking prong. Prong ① (blue) exhaustively explores bounded concurrency and crash interleavings: representative specs LockFreeARTrieLinearizability, CrashRecovery, DurabilityFrontier, and EvictionWalkEBR establish the properties linearizability, no-lost-writes, and crash-recovery completeness with zero TLC violations. The prong models the concurrency and crashes of the Rust implementation under test (grey, src/persistent_artrie — overlay, WAL, arena), and an amber correspondence harness (scripts/verify-formal-correspondence.sh) feeds SANY+TLC into the TLA prong and trace tests into the implementation, tying the models to the code alongside the Rocq make and the unsafe-inventory gate. The Rocq theorem-proving prong is the companion figure proof-artifact-map-2. Proof-artifact map, part ② of ② — the Rocq theorem-proving prong. Prong ② (green) proves properties for all inputs: representative specs MapRefinement, ARTrieSpec, DictionaryLawSpec, and EpochReclamationSpec establish functional correctness, map-ADT refinement, and no-use-after-free (gated EBR), all Qed-closed with zero Admitted/Axiom/Parameter. The prong proves the function of the same Rust implementation under test (grey, src/persistent_artrie — overlay, WAL, arena), and the amber correspondence harness (scripts/verify-formal-correspondence.sh) drives the Rocq make. The TLA+/TLC model-checking prong is the companion figure proof-artifact-map.
ProngToolEstablishesScope
① Model checkingTLA⁺ / TLCtemporal safety + liveness under concurrency and crashesbounded instances, all interleavings
② Theorem provingRocq / Coqfunctional correctness + abstract-data-type (ADT) refinementall inputs, machine-checked Qed.

Aggregate: 72 Rocq .v files, 1,348 propositions (1,027 Theorem + 313 Lemma + 8 Corollary), 0 Admitted / 0 Axiom / 0 Parameter; 57 TLA⁺ modules, 69 .cfg TLC configs, all SANY-clean (SANY = the TLA⁺ syntactic analyzer). Many models ship a paired _Unsafe.cfg negative control that must violate the named invariant, proving the checker has teeth. The correspondence harness gives every TLC invocation a distinct on-disk state directory. A negative control succeeds only when TLC returns status 12 and the diagnostic names the required invariant (or, for the liveness control, status 13 and a temporal-property violation). Parser failures, resource failures, timeouts, and state-directory collisions therefore fail the gate instead of masquerading as successful negative controls.

Correspondence by concern

Lock-free overlay (CAS, values, removal)

InvariantTLA⁺ modelRocq proofDoc
Root-CAS linearizability (duplicate-insert, insert-vs-contains)LockFreeARTrieLinearizability.tlaSpec/ARTrieSpec.v, Proofs/MapRefinement.vlock-free-overlay
Indexed-overlay counter accumulation + vocab index uniquenessLockFreeIndexedOverlay.tlaSpec/LockFreeCounterMergeSpec.vlock-free-overlay
Arbitrary-V value-CAS + remove-CAS correctnessLockFreeOverlayValueCas.tla, LockFreeOverlayRemoveCas.tla (+ _Unsafe)Spec/ARTrieSpec.vlock-free-overlay
Counter-merge no-lost-update, order-independentLockFreeCounterMergeAtomicity.tlaSpec/LockFreeCounterMergeSpec.vlock-free-overlay

Durability, watermark & checkpoint

InvariantTLA⁺ modelRocq proofDoc
acknowledged $\implies$ durable; checkpoint_lsn = committed prefix; no truncation lossLockFreeDurableCheckpoint.tla (+ _Unsafe), SharedPersistentConcurrency.tlaSpec/PublicDurabilityPolicySpec.v, Spec/PersistentWalAtomicitySpec.vdurability-and-recovery
Checkpoint snapshot $\subseteq$ visible; publication serialized by CKConcurrentCheckpointPublication.tla, ConcurrentCheckpointSerialization.tla (+ _Unsafe NoTornDescriptor)Spec/PersistentCheckpointRetentionSpec.v, Spec/PersistentDirtyCheckpointSpec.vdurability-and-recovery
Durable checkpoint under evictionLockFreeDurableCheckpointEviction.tla (+ _Unsafe)Spec/PersistentDirtyCheckpointSpec.vdurability-and-recovery

Recovery & crash-safety

InvariantTLA⁺ modelRocq proofDoc
Reopen replay reproduces exactly the visible state; drop uncommittedLockFreeOverlayDurableReplay.tla (+ _Unsafe), CrashRecovery.tlaSpec/PersistentRecoveryPlannerSpec.v, Spec/PersistentRecoveryReplayCompletenessSpec.vdurability-and-recovery
Epoch accounting + recoveryEpochCheckpoint.tla, EpochCheckpointRecovery.tlaSpec/PersistentWalSegmentLifecycleSpec.vdurability-and-recovery
End-to-end refinement across checkpoint/compaction/crash/vocabSpec/PersistentEndToEndTraceSpec.vdurability-and-recovery

Concurrency & the F4 lock hierarchy

InvariantTLA⁺ modelRocq / testDoc
Shared-handle linearizability (byte + char + vocab), reads observe completed visible stateSharedPersistentConcurrency.tla, ConcurrentVocabLinearizability.tlaSpec/SharedPersistentConcurrencySpec.vconcurrency-model
F4 deadlock-freedom (CK > merge_lock > EC, drop-before-join)tests/persistent_lockfree_f4_lock_hierarchy_loom.rs, tests/vocab_lockfree_f4_lock_hierarchy_loom.rsconcurrency-model

Eviction & epoch reclamation

InvariantTLA⁺ modelRocq proofDoc
Eviction-CAS overwrite-race + stale-image safety (serial_disk_ptr stamp)OverlayEvictionCas.tla, OverlayEvictionStale.tla (+ _Unsafe each)eviction, concurrency-model
Eviction-walk epoch reclamation + registry publishEvictionWalkEBR.tla, EvictionRegistryPublication.tlaSpec/PersistentCharEpochReclamationSpec.veviction
Version-GC reader-guard reclaim safetyVersionLifecycle.tlaconcurrency-model

WAL, storage & group commit

InvariantTLA⁺ modelRocq proofDoc
WAL-before-mutation ordering, fail-closed on WAL errorWAL.tla, WAL_FileSystem.tlaSpec/PersistentWalAtomicitySpec.v, Spec/PersistentVocabWalAtomicitySpec.vwal-format
Fail-closed write/sync durability boundaryStorageSyscallOutcome.tladurability-and-recovery
Backend contracts (mmap block storage, io_uring SQE/CQE + fixed-buffer ownership)MmapBlockStorage.tla, IoUringSqeCqeLifecycle.tla, IoUringFixedBufferOwnership.tlastorage-backends
Buffer-page lease exclusion; raw-child-pointer ownershipBufferPageLease.tla, PointerOwnership.tlastorage-backends
Group-commit frontier: no early ack; ordered FIFO / returned-LSNDurabilityFrontier.tla, AsyncWalGroupCommit.tlagroup-commit
Vocab reopen bijection ownershipVocabPersistenceOwnership.tlaSpec/PersistentVocabCheckpointSpec.vfamilies

ABI resource layer (vt.dictionary.v1 producer)

The language-binding boundary joined the correspondence program in wave W2 of the family ABI plan. Its registry is formal-verification/ABI_INVARIANTS.tsv (checked by scripts/check-abi-invariants.py inside this gate), and its artifacts follow the same spec ↔ test convention as every concern above:

ModelChecksExecutable mirror
formal-verification/tla+/AbiProducerSnapshot.tla (+_Unsafe.cfg negative control)immutable-capture law, fresh-capture visibility, content-preserving maintenance publishes [LDICT-SNAP-1..3]tests/ffi_snapshot_law.rs, tests/ffi_crud_model_correspondence.rs, torn-capture regression in tests/ffi_concurrent_snapshot_stress.rs
formal-verification/rocq/Spec/AbiTraversalSnapshotSpec.vABI-local node-id arena laws: stable, append-only, unambiguous, write-once memoization, well-formedness preservation [LDICT-ARENA-1..5]src/bindings.rs node-id unit tests
formal-verification/rocq/Spec/AbiPagingProducerSpec.vpaging bounds, out_total stability, lossless page decomposition [LDICT-PAGE-1..2]tests/ffi_resource_paging_proptest.rs
formal-verification/rocq/Spec/AbiStatusMappingSpec.vstatus-table bijections and the deliberate project/interop divergence (raw-integer reuse provably misroutes) [LDICT-STAT-1..2]tests/ffi_status_matrix.rs

Lifecycle (retain/release) is deliberately NOT re-modeled here: the protocol is owned by the interop lifecycle model in the liblevenshtein-rust repo (docs/verification/tla/AbiResourceLifecycle.tla, invariants VT-LIFE-1..6); this repo realizes it and pins the realization with the abi-owned-resource-release-once unsafe-contract row plus the balance and cross-thread teardown tests [LDICT-LIFE-1..2].

The negative-control methodology

A model that only checks the safe configuration proves nothing if its invariant is vacuous. Most durability/eviction models therefore ship an _Unsafe.cfg that deliberately breaks the mechanism (e.g. a frontier-bounded reclaim instead of the watermark, or eviction without the stamp) and asserts the checker finds the violation. The pair "safe cfg passes $\land$ _Unsafe cfg fails" is what makes the safe result meaningful — a falsifiable experiment in the scientific sense.

The CI correspondence gate

The two prongs are tied to the running code by scripts/verify-formal-correspondence.sh: it runs the Rust trace-correspondence tests (the code's observable trace matches the spec), the Rocq make (asserting 0 Admitted/Axiom/Parameter), TLA⁺ SANY parsing (and, under RUN_TLC, model checking), and the unsafe-inventory gate (every unsafe block in src/ must be reconciled row-for-row against formal-verification/UNSAFE_INVENTORY.tsv

  • UNSAFE_CONTRACTS.tsv, by set-equality). A drifted proof, a new unreconciled unsafe, or a stale count fails CI.

Running it locally

# Rocq proofs (resource-limited, per CLAUDE.md guidance):
systemd-run --user --scope -p MemoryMax=32G -p CPUQuota=1800% \
  make -C formal-verification/rocq -j1

# TLA+ model checking (bounded):
RUN_TLC=1 scripts/verify-formal-correspondence.sh

See also

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close