Skip to main content
When a process dies holding an effect key, nothing happens. No sweeper frees it, no timer fires, and the process that comes back does not scan or repair — it waits to be asked for an effect key, exactly as it did before it died. That is deliberate, and this page is why.

What a process may conclude

A process that finds a record reserved or executing may conclude exactly two things: what state the record is in, and whether its lease is still live. It may not conclude that the holder is gone. “The holder is dead” is not knowable from the store, and no column makes it knowable. The record carries an action id, which names an attempt and not a process. There is deliberately no holder host and no holder pid, because the first thing anyone writes against those columns is a reclaimer — if the holder is not alive, free the key — and that reclaimer is wrong on the day it matters, when a container that stopped answering a health check still has an open socket to a payment API. A field that invites a false inference is worse than no field.

What actually happens

An expired lease that is never contended stays executing in the table, and ctrlrun effects prints it as executing (lease expired). Reading is not a transition: listing effects, inspecting one, or opening the store moves nothing. The effect record’s resolved_by column holds cli:local for a person, not their username. CTRLRun does not authenticate the person at the terminal, so a name there would be a claim about somebody made from a value that somebody controls. cli:local says exactly what is known: somebody with the operator’s terminal. The EFFECT_RESOLVED event carries the same string in its resolver field, which is what lets you join the two, and the coarser human or reconcile in its own resolved_by.

A continuation held by a dead process

An elicitation holds a reservation open across a round trip. The row survives the process, and with a shared store a different process may finish it. One resumption is admitted and no more, because the token is consumed in the transaction that admits it. If the lease lapsed first, the resumption is refused and the effect becomes AMBIGUOUS by the ordinary path.

What this does not do

  • Nothing sweeps. No background thread, no timer, no cron, no reap command. The lapse is noticed lazily, by the next contender, and never by anything running on a schedule.
  • An expired lease frees nothing. It is a refusal, not a reclaim. The next attempt is refused and the record is now unknown.
  • A restart repairs nothing and reports nothing. Opening the store migrates it and reads nothing else.
  • No receipt records the resolution. A receipt is written when the action reaches a terminal state; a resolution happens afterwards, often days later and by somebody who was not the actor. Mutating the receipt would be an alteration the chain would correctly report. ctrlrun effects and ctrlrun inspect are where you find it.
Verified by T159AMBIGUOUS survives a restart and still refuses a blind retry, against every store — T160 for the expired lease that frees nothing and the reads that transition nothing, T161 for the two authorities and what each is recorded as, T162 for the process identity that is deliberately absent, T163 for the continuation held by a dead process, and T177d for the display that is not a transition. G5 in ctrlrun verify grades the blocked blind retry on your store’s backend, in a scratch store of its own.

Next