What to watch, and what to do about it
Set the alert on the first row and the last. The middle rows are for the dashboard.
Getting it somewhere you can see it
Every executed action leaves a portable JSON receipt, and receipts are the export. Withpip install "ctrlrun[otel]" you get one OpenTelemetry span per action and one span event per
step, and argument values stay out of it unless you ask for them. There is no ctrlrun dashboard
and there will not be one.
Routine
- Back up the store. It holds every in-flight effect key, every approval and the receipt chain. Restoring a database from before an action ran is how a duplicate execution becomes possible again.
- Verify the chain after a restore, and after any maintenance that wrote to the database directly.
- Take the backup before the first new process starts on a deploy, because migrations run at open and there is no way back.
- Size the lease to your slowest executor, not to your average one. It defaults to five minutes and is meant to be raised. A lease shorter than the work it covers turns healthy slow actions into unknown outcomes.
- A reporting role still needs
CREATEon the schema. Opening the store migrates it, so a read-only role cannot run--verify-chain— it is refused before a receipt is read, naming the missing privilege. Read-only is for your own queries against the tables, not for the CLI. - Anchor on an interval you choose, and say what it is.
ctrlrun anchor --provider ...records the chain’s head outside the database, which is what makes a truncation detectable at all: the head that would catch one is otherwise a row in the same database. The window you are exposed to is(last anchored seq, current head], so the interval is the claim, and it is the number to quote rather than any sentence about tamper-evidence. See anchoring. - Prune with a window, not with a
DELETE.ctrlrun pruneremoves a prefix and leaves a checkpoint the reader seeds from; deleting receipts yourself is detected as a break, by design. It refuses rather than warns, and there is no--force. See retention.
What this does not do
- There is nothing to run. No agent, no sidecar, no scheduler. Every command above is a
one-shot read of the store, and the two that write —
anchorandprune— run when your scheduler runs them. Nothing sweeps, nothing reaps, and no hold expires: a hold that lapsed on a timer would release evidence on a schedule nobody reviewed, so a person places it and a person ends it. - It does not retry for you. A proven non-execution leaves the key retryable — the next attempt is admitted rather than refused — and nothing performs that attempt but your code. Every other outcome refuses one.
- It does not resolve unknown outcomes for you. A person or a reconcile hook does, and only where the hook’s answer points.
- It is not an audit product. Receipts are evidence you can export; what you do with them is outside this project.
T160 and T177d — an expired lease frees nothing, and displaying it changes
nothing — T161 for the two authorities that can move an unknown outcome and what each is
recorded as, T545c for the hold that no timer lifts, and T177c for the CLI surface these
commands come from, asserted against the command list so a new one cannot appear unnoticed.
Next
- Recovery after a crash: why nothing sweeps.
- Anchoring and retention: the two things this milestone gives an operator to schedule.
- Reconcile automatically: the hook that answers without a person.
- Get started · Why.