Crash mid-refund, then recover without charging twice
Build run 1 event by event. KILL the process at the worst moment: right after the refund posts, before its result is journaled. Then branch. A NAIVE RESTART re-runs everything and double-charges. A DURABLE RESUME replays the journal: step 0 is memoized, step 1 is re-attempted but the idempotency key is already honored, so the ledger stays at one refund.
The world: one run run-7f3a, frozen timestamps 2026-07-05T10:00:NNZ by seq. Three durable artifacts must survive a crash: the journal (append-only events), the keystore (idempotency keys the provider honored), and the ledger (where money actually moved). State is the FOLD over the journal, never an in-memory variable.
This is a faithful REPLAY of the journal, not a live process. Resume re-runs the same script over the same log. The decision for step 1 is re-made (you will see a second llm_decided for idx 1), but the refund EFFECT is not, because the provider already honored the key.
The three durable artifacts
journal · append-only events (JSONL)0 events
ledger · the real side effect
ORD-3300$0.00
No money has moved yet.
keystore · provider's honored keys
empty — no idempotency key honored yet.
result
run status
Run not started.
Memoization handles the easy crash; the idempotency key handles the hard one. If the crash had landed after the tool_result was journaled, replay would just memoize the recorded result and skip the tool. But the kill lands BEFORE that write, so the journal has no result for step 1 and memoization alone would re-run it. The stable key ORD-3300:refund:180.00 is the only thing standing between resume and a second charge. This hardens Part 2's in-memory guard, which died with the process.
How we keep it honest: the journal here lives in a list and prints as JSONL; a real system appends to a file or SQLite so it outlives the process. The keystore models the payment provider's own idempotency, which is what makes effectively-once real in practice. Byte-reproducible replay holds only on this deterministic path; with a real LLM each decision is cached in the journal and replayed best-effort.