A worker walks forward through an endless pipeline. Some steps are side-effecting — cross one and it fires into the world, permanently. The worker crashes on a random timer and resumes from the last committed checkpoint, not from the crash site — so any side-effecting step it had already crossed since that checkpoint fires again on the replay. A step that already carries a token getting a second one is a duplicate: the fail state. The only input is commit, on a cooldown, so the real skill is choosing which side effect is worth locking in before the next crash lands, not dodging crashes themselves.
Riffs on durable execution and why replay safety is really an idempotency problem: a workflow engine that resumes a crashed run from its last checkpoint has the same shape as this pipeline, and “did that email already send?” is the same question as “did that step already fire?”
Reuse
The mechanic lives in src/replay.js as a framework-free ES module:
createReplay(opts)— returns a state object; callupdate(dt)each frame andcommit()on input.commit()advances the checkpoint to the worker’s current step and is a no-op while on cooldown.opts:effectChance(odds a generated step is side-effecting),speed(steps/s),commitCooldown,crashIntervalBase/crashIntervalMin/crashDecay(crashes come faster over a run),maxDuplicates(0 disables the fail state),duration(0 = endless).- State exposes
pos(float progress along the pipeline),committedIndex,steps(grows lazily, each{ effect, emitted, duplicated }),lastEvent({ type: 'commit'|'crash'|'duplicate', index, at }, for a render flash),score(committed/duplicates/streak/bestStreak), andstatus('playing'|'finished', withreason'corrupted'|'time-up'). Rendering and input are entirely the caller’s job.
Port notes for DragonRuby: update() and commit() have no DOM
dependencies; the pipeline-to-screen scroll and token rendering belong to
the renderer, same split as the demo.
Gotchas
stepsis generated lazily and cached by index (ensureStep), so a step’seffectflag is decided once and stays fixed across replays — onlyemitted/duplicatedchange when it’s re-crossed.- A crash only resets
pos; it never touchessteps. The already-emitted tokens are the point — they represent side effects that actually happened and can’t be undone, which is exactly what makes re-crossing them a duplicate instead of a free do-over. commit()only counts effect steps ascommittedat the moment they’re locked in, not when they first fire — a step that fires and then gets duplicated before you commit past it never counts.- The demo bundles its own copy of the module (self-contained by contract).
If you touch
src/, re-copy it intodemo/.