Every dafny-replay kernel is generic: it works with any domain that satisfies a small set of proof obligations. Before the kernel can guarantee anything — that undo cannot corrupt state, that rejected requests leave the server unchanged, that cards are never duplicated — your domain must prove that its initial state is valid and that every transition preserves validity. Discharging those two obligations is all it takes to unlock the full set of kernel theorems for your domain.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/metareflection/dafny-replay/llms.txt
Use this file to discover all available pages before exploring further.
The two core obligations
TheReplay.dfy kernel requires concrete domains to prove exactly two lemmas.
R1 — Initial state satisfies the invariant:
Normalize function is the domain’s safety valve. When an action would violate Inv — such as decrementing a counter below zero — Normalize clamps the result back into the valid region. This lets Apply be a total function that never needs to reject or fail; Normalize makes the result well-formed unconditionally.
The precondition
requires Inv(m) in StepPreservesInv is not circular. It says: if the current state is valid, then the next state (after normalization) is also valid. R1 seeds the induction, and R2 carries it through every reachable state.What these obligations unlock
Once R1 and R2 are proved, the Replay kernel’s theorems follow automatically for your domain:- (RK1) For every reachable history
h,Inv(Present(h))holds. - (RK2)
Do,Undo, andRedoall preserveInvon the present state.
The three-module pattern
Every dafny-replay application uses three Dafny modules in a single.dfy file.
MyAppDomain refines Domain
Provide the concrete types (
Model, Action), the invariant (Inv), the transition function (Apply), and the normalization function (Normalize). Prove the two domain obligations here.MyAppKernel refines Kernel
A single import line. The kernel’s
Do, Undo, Redo, and all related lemmas are inherited from Replay.dfy and apply to your domain automatically.Worked example: the Counter domain
The Counter is the minimal domain in the repository. The model is an integer, the invariant is non-negativity, andNormalize clamps negative results to zero.
0 >= 0 is trivially true, and if m < 0 then 0 else m >= 0 holds for all integers. For more complex domains (such as Kanban’s WIP limit and partition invariants), lemma bodies contain explicit case splits and helper lemmas, but the obligations themselves remain the same two shapes.
The kernel module
Kernel abstract module in Replay.dfy provides Do, Undo, Redo, Preview, CommitFrom, and all their invariant lemmas. Refining it with CounterDomain instantiates all of them for integers.
AppCore
AppCore is the contract that dafny2js reads. Every function here becomes a named entry point in the generated app.js.
Verifying the domain
Run Dafny verification before compiling to JavaScript:Additional obligations for other kernels
The Replay kernel requires the minimal two obligations. More powerful kernels require additional proofs.Authority kernel
For server-authoritative state, the domain replacesApply/Normalize with a TryStep function that returns a Result:
- (A1)
Inv(Init()) - (A2)
Inv(m) ∧ TryStep(m, a) = Ok(m′) ⇒ Inv(m′)
Inv, independent of what clients send.
Multi-Collaboration kernel
Multi-Collaboration shares A1 and A2 and adds three more:- (MC3a) A total
Rebasefunction for rebasing client operations - (MC3b) A
Candidatesfunction andExplainspredicate defining the domain’s intent envelope - (MC3c)
CandidatesComplete— a proof that the intent envelope covers all valid candidate actions
dafny2js tool
Generate a JavaScript API wrapper from your verified Dafny modules.
Guarantees reference
Full statement of what is proved for each kernel, including integration boundaries.