Skip to content
C.W.K.
Stream
Lesson 03 of 04 · published

Replay, Not Memory

~11 min · replay, recovery, state-machine, idempotency

Level 0Cold Iron
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Replay, Not Memory

Anvil's trail is append-only, total, and self-sufficient in anvil-db. Every state transition, artifact version, judgment, tie-break, dissent, and reveal is durable before it is shown. The SQLite run, seat, and submission views are projections of that record, not permission for an operator to patch history after a crash.

Recovery begins by reading durable state and store references. A submission archived before failure remains submitted; a stored ballot remains ruled; a phase advance that never committed remains unapplied. Completed model or harness work is not rerun merely because a process restarted.

On the sealed rail, raw and scrubbed artifact copies live with the trail, while cwkPippa conversation IDs are only back-references. Rebuilding an Anvil run never depends on rereading another product's conversation store. Open Run store trees and reports likewise remain in anvil-db; yards are valuable process archaeology but not rebuild dependencies.

If durable facts and a cached display disagree, the trail wins. Recovery appends any replacement, withdrawal, or resumed action as new fact rather than rewriting earlier events.

Rebuild from durable facts; never recreate history from operator memory. Store and trail define the contest after every restart.

Code

Recovery rule — finished work is never redone·python
def rebuild(trail):
    """No screen repair. Fold the events in order and the state falls out."""
    state = {"submissions": {}, "ballots": [], "phase": 0}
    for ev in trail:
        kind = ev["event"]
        if kind == "submission_archived":
            state["submissions"][ev["seat"]] = ev["sha"]
        elif kind == "ballot_stored":
            state["ballots"].append(ev["pick"])
        elif kind == "phase_committed":       # only committed moves count
            state["phase"] = ev["phase"]
    return state


trail = [
    {"event": "submission_archived", "seat": "A", "sha": "aa11"},
    {"event": "ballot_stored", "pick": "A"},
    {"event": "phase_advance_attempted", "phase": 2},   # never committed
]

before = rebuild(trail)
after = rebuild(trail)          # replay any number of times — idempotent
assert before == after
assert before["phase"] == 0     # the uncommitted advance did not apply
print(before)

External links

Exercise

A service crashes after one submission archives but before the next phase opens. List the durable facts, the action that must not repeat, and the next lawful event.
Hint
Archive-before-judge makes the first submission a settled fact.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.