Coven automations
Durable Coven-owned routine definitions, scheduling, execution, health, and run history.
18 min read
Coven automations are durable routine definitions owned by the Coven daemon and its local store. A routine binds a schedule to a validated runtime launch, optional familiar identity, project working directory, prompt, and delivery settings. The scheduler and run ledger live in Coven rather than in a harness home directory.
Automations are exposed through the coven.automations capability and the
versioned POST /api/v1/actions router. Always call
GET /api/v1/capabilities first and use only action ids advertised by the live
daemon. This page describes the current source contract; an older installed
daemon advertises fewer actions.
The coven.automations capability may include an optional variantNegotiation
object describing supported, experimental, and refused contract variants.
This is negotiation metadata; it does not authorize a refused variant. See
versioned definition commands.
Owner-local access
Send automation actions to the owner-local IPC endpoint: the Unix socket or
the Windows named pipe. If you run the optional loopback TCP listener, only
these diagnostic reads answer over it: coven.automations.health,
coven.automations.definition.health.v1,
coven.automations.scheduler.status.v1,
coven.automations.occurrence.list.v1, and
coven.automations.occurrence.history.v1. Every other coven.automations.*
action, including reads that return prompts, run logs, receipts, or event
checkpoints, returns HTTP 403 with error code AUTHORITY_REQUIRED before the
daemon opens its store. origin, intentId, and other caller-supplied
identity fields never grant access.
AUTHORITY_REQUIRED sets retryable: false. Refusal happens before reserving
an adoption key, replaying a saved result, emitting an action event, or
dispatching runtime work. A refused request does not consume the adoption key;
a later owner-local request can use that key, subject to normal validation.
Clients should stop and report the transport error. Have the owner explicitly configure a supported owner-local connection. Do not silently retry through a more privileged connection or expose the IPC endpoint through an unauthenticated bridge. Passing this transport check does not provide a trusted Runtime Authority adapter or enable a refused execution command or SDK mutation phase.
Capability discovery alone does not prove that an older installed daemon enforces this boundary. Check its build identity and release evidence before relying on TCP refusal.
Safety defaults
coven.automations.importcreates legacy routines asPAUSEDandcoven.automations.legacy.import.v1creates them as drafts; import never opts them into execution. See Automations migration.- Unsupported recurrence values fail validation rather than being approximated.
- Overlap policy is
forbidand misfire recovery islatestin the v1 definition shape. - A run without an explicit
cwdfails instead of guessing a project. - Scheduled and manual runs use the same validated session-launch path.
- The daemon runs a scheduler pass at startup, every 60 seconds, and right after most successful definition changes, cancellations, recoveries, retries, manual runs,
tick, orunquarantine. Disabling a definition, a richcommand.v1change, and imports wait for the next 60-second pass. It records occurrence and run state durably. See Automations scheduling. - One scheduler at a time claims and dispatches work for a
COVEN_HOME, fenced by$COVEN_HOME/automations-scheduler.lockand a generation stored in SQLite. Keep the lock file and the SQLite store on one local filesystem; network filesystems are not supported. outputTargetis refused until atomic delivery is certified.- An
authoritydeclaration is refused until the daemon advertises Runtime Authority. - A routine that exhausts its retry policy is quarantined: it stops planning and refuses manual runs until you call
coven.automations.unquarantine.
Review a definition before changing its status to ACTIVE. Provider credentials
remain owned by the selected runtime or harness and must not be embedded in the
automation definition or action envelope.
Action envelope
Automation arguments are top-level fields in the action request. origin and
intentId are optional correlation fields. On coven.automations.create,
.update, and .delete, intentId is also an idempotency key: repeating the
same request with the same intentId returns the first result, and a different
request with a reused intentId is rejected. Use a new intentId for each
intended change. coven.automations.run.cancel.v1,
coven.automations.occurrence.cancel.v1,
coven.automations.attempt.cancel.v1,
coven.automations.attempt.retry.v1,
coven.automations.occurrence.recover.v1, and
coven.automations.occurrence.runNow.v1 accept only their own fields, so leave
origin and intentId off those requests.
{
"action": "coven.automations.health",
"origin": "local-maintainer-tool",
"intentId": "inspect-daily-notes-1",
"id": "daily-notes"
}The router returns an event-shaped response when it recognized and routed the action:
{
"ok": true,
"accepted": true,
"action": "coven.automations.health",
"status": "completed",
"event": {
"kind": "automations.changed",
"action": "coven.automations.health",
"origin": "local-maintainer-tool",
"intentId": "inspect-daily-notes-1",
"payload": {
"health": {
"automationId": "daily-notes"
}
}
}
}A successful action returns ok: true, accepted: true, and
status: "completed". A failed action returns ok: false, accepted: false,
status: "rejected", and the cause in reason. Unversioned actions report
failures with HTTP 400. Versioned actions (ids ending in .v1) and the
owner-local check also return a typed error with code, httpStatus,
message, and retryable, and the HTTP status matches error.httpStatus:
for example VALIDATION_FAILED (400), AUTHORITY_REQUIRED (403),
NOT_FOUND (404), REVISION_CONFLICT and ADOPTION_REPLAY_MISMATCH
(409), CANCEL_PENDING (409), GONE_TOMBSTONED and CURSOR_EXPIRED (410), and
CAPABILITY_UNSUPPORTED, ILLEGAL_TRANSITION, RETRY_DISPOSITION_INVALID,
or AMBIGUOUS_RETRY_FORBIDDEN (422), and DEADLINE_EXCEEDED (504). Branch on
error.code, not reason. Malformed JSON and missing action ids return
400. An unknown coven.automations.* action over TCP is refused with 403
before action validation; other unknown action ids return 400.
accepted: true on coven.automations.run means Coven started or scheduled
the run, not that it finished; see Manual runs and health.
Supported actions
The daemon advertises 37 coven.automations.* action ids. Unversioned actions
and the definition, run, occurrence, health, and scheduler reads return their
data in event.payload. Versioned commands, event pages, and receipt reads
return it in a top-level result; a versioned command that commits also
returns an event.
Unversioned actions
| Action | Required fields | Result |
|---|---|---|
coven.automations.list | none | routines |
coven.automations.get | id | routine or null |
coven.automations.create | definition | created routine and timestamp |
coven.automations.update | definition | updated routine and timestamp |
coven.automations.delete | id | id and deleted |
coven.automations.tick | none | planning report; it plans due slots and wakes the scheduler but never claims or recovers work, so recovered is 0 and claimed is empty |
coven.automations.runs | id; optional limit | recent runs with their attempts and the latest attempt's cancellation; default limit 20 |
coven.automations.run | id | run id, status, session id, and error |
coven.automations.import | none | imported, skipped, and failure lists |
coven.automations.health | id | next due time, recent outcomes, lease, retry, quarantine, and staleness state |
coven.automations.unquarantine | id | automationId and released |
Versioned commands
| Action | Required fields | Result |
|---|---|---|
coven.automations.definition.create.v1 | definition, adoptionKey | outcome, revision, and the routine |
coven.automations.definition.revise.v1 | definition, adoptionKey, expectedRevision | outcome, revision, and the routine |
coven.automations.definition.activate.v1 | id, adoptionKey, expectedRevision; optional reason | paused to active as a new revision |
coven.automations.definition.pause.v1 | id, adoptionKey, expectedRevision; optional reason | active to paused as a new revision |
coven.automations.definition.disable.v1 | id, adoptionKey, expectedRevision; optional reason | disabled as a new revision |
coven.automations.definition.tombstone.v1 | id, adoptionKey, expectedRevision | tombstone revision; history is kept |
coven.automations.legacy.import.v1 | adoptionKey, source: "codex-automation-toml"; optional dryRun | imported, skipped, and failure lists |
coven.automations.run.cancel.v1 | adoptionKey, runId, attemptId, runtimeCorrelation.sessionId, scope: "run", reason, requestedBy.principalId | cancellation record |
coven.automations.occurrence.cancel.v1 | adoptionKey, occurrenceId; optional reason | the occurrence cancelled, or the run cancellation it started |
coven.automations.attempt.cancel.v1 | adoptionKey, attemptId; optional reason | the attempt cancelled, or the run cancellation it started |
coven.automations.attempt.retry.v1 | adoptionKey, runId, priorAttemptNumber, priorDisposition; optional note | the new attempt, with the occurrence planned |
coven.automations.occurrence.recover.v1 | adoptionKey, occurrenceId, evidenceDetermination; optional statement | the determination: the occurrence settled failed, or planned for a new attempt |
coven.automations.occurrence.runNow.v1 | adoptionKey, automationId; optional note, bypassEligibility | the manual occurrence and, once dispatched, its run |
coven.automations.command.v1 | envelope | a coven.automations.v1 command response |
Reads, history, and events
| Action | Required fields | Result |
|---|---|---|
coven.automations.definition.list.v1 | none; optional includeTombstoned | routines, revisionById, and tombstonedAtById |
coven.automations.definition.get.v1 | id | routine or null, revision, tombstonedAt, and the rich definition when one was authored through command.v1 |
coven.automations.definition.health.v1 | id | the same health as coven.automations.health; typed NOT_FOUND or GONE_TOMBSTONED |
coven.automations.run.history.v1 | automationId; optional occurrenceId, limit, cursor | runs newest first and a cursor |
coven.automations.run.get.v1 | id | one run with its attempts, or null |
coven.automations.occurrence.list.v1 | view; optional automationId, limit | occurrences |
coven.automations.occurrence.get.v1 | id | one occurrence with up to 20 runs, or null |
coven.automations.occurrence.history.v1 | automationId; optional limit, cursor | occurrences in every state, newest first, and a cursor |
coven.automations.scheduler.status.v1 | none | scheduler owner, generation, last pass, and queue counts |
coven.automations.receipt.get.v1 | id | receipt and verification |
coven.automations.events.read.v1 | stream; optional after or from, limit | an event page with nextAfter and a checkpoint |
coven.automations.events.subscribe.v1 | stream; optional after or checkpoint | up to 100 events and a new checkpoint |
view is due, eligible, claimed, running, or recovery_required.
due lists every planned slot whose time has arrived; eligible applies the
scheduler's own claim rules. History and occurrence reads accept limit from
1 to 100 (default 20). Pass the previous page's cursor.next as cursor
until cursor.hasMore is false. These reads never renew leases or change
state.
stream is an object with kind (automation, occurrence, run, or
feed) and id; use feed with id all for every automation event in commit
order. events.read.v1 takes an exclusive sequence in after or a UTC
timestamp in from, and limit from 1 to 1,000 (default 100). Checkpoints
expire after 24 hours and then return CURSOR_EXPIRED instead of rewinding.
Occurrence, run, and attempt state changes publish occurrence.transitioned,
run.transitioned, and attempt.transitioned events in the same transaction
as the change: occurrence events on the occurrence stream, run and attempt
events on the run stream. Creating a row publishes from: "none". History
from before these events existed is not backfilled, so a stream can begin
mid-lifecycle; treat its first prior state as unknown.
coven.automations.receipt.get.v1 returns the stored receipt with a
verification summary. Current builds cannot authenticate the receipt
producer, so verification.status is unverifiable; treat a receipt as
integrity-checked, not as proof of what ran.
Versioned definition commands
Versioned mutations take an adoptionKey: 8 to 200 characters, starting with
a letter or digit, then letters, digits, ., _, :, or -. Coven stores
the first outcome for each key in the same transaction as the change.
Repeating the exact request returns the stored result with
outcome: "replayed" and no second event. Reusing a key for a different
request returns ADOPTION_REPLAY_MISMATCH. Rejections are stored too, so use a
new key after you fix a rejected request.
Revise, activate, pause, disable, and tombstone also take expectedRevision.
Read the current value from coven.automations.definition.get.v1. A stale
value returns REVISION_CONFLICT with currentRevision and changes nothing.
{
"action": "coven.automations.definition.activate.v1",
"id": "daily-notes",
"adoptionKey": "activate-daily-notes-0001",
"expectedRevision": 1,
"reason": "Reviewed prompt, cwd, and schedule."
}- Activate moves a
pauseddefinition toactiveand re-validates it; pause movesactivetopaused. Any other starting state isILLEGAL_TRANSITION. - A disabled definition cannot be activated, revised, or updated.
- A draft from
legacy.import.v1, or an invalid definition, can only be revised tostatus: "PAUSED"before you activate it. create.v1andrevise.v1reject unknown definition fields, and refuse any variant that thevariantNegotiationobject on thecoven.automationscapability does not list as supported, such asoutputTarget, withCAPABILITY_UNSUPPORTEDnaming the variant.- After any versioned mutation,
coven.automations.updaterefuses the definition andcoven.automations.deletereturnsdeleted: falseand leaves it in place. Usedefinition.tombstone.v1instead. - Every versioned command in the
coven.automations.v1command envelope is implemented and advertised. A versioned action name the daemon does not advertise returnsCAPABILITY_UNSUPPORTED.
coven.automations.command.v1 accepts a coven.automations.v1 command
envelope in envelope and answers with a command response in result.
Envelope definition.create.v1 and definition.revise.v1 commands carry a
rich AutomationDefinition with its JCS integrity digest. Create must be
revision: 1 in lifecycleState: "draft"; revise must be
expectedRevision + 1. Coven runs the rich body through the same validation
and transactions as a routine body, keeps the rich form, and returns it as
definition from coven.automations.definition.get.v1. Delivery policies and
activation windows are refused with CAPABILITY_UNSUPPORTED rather than
dropped, and a rich request and a routine request never share an adoption key.
The envelope also refuses run.cancel.v1, occurrence.cancel.v1,
attempt.cancel.v1, attempt.retry.v1, and payload fields it does not
implement with
CAPABILITY_UNSUPPORTED; send cancellation as the flat action instead.
For a richly authored revision, definition lifecycle events, occurrence
list/history/get projections, coven.automations.run.get.v1, and Runtime
Authority execution bindings publish the recorded document's integrity
digest. The compatibility coven.automations.runs and
coven.automations.run.history.v1 projections do not expose a digest.
Receipts produced from those bindings carry the published digest.
Scheduling and dispatch continue to fence execution with the digest
of the projected routine JSON; these two digests serve different purposes.
Revisions without a rich document publish the routine digest. Historical rows
without a stored digest remain unattributed.
This behavior is present in source beginning with
eb3273e.
Existing events are immutable: v0.4.7 events retain their original routine
digest. Receipts from older execution bindings may also name the routine
digest of the same revision; the signed binding still determines the exact
value to verify.
Definition shape
A create or update request supplies a top-level definition object:
{
"action": "coven.automations.create",
"origin": "local-maintainer-tool",
"definition": {
"schemaVersion": 1,
"id": "daily-notes",
"name": "Daily notes",
"status": "PAUSED",
"rrule": "FREQ=DAILY;BYHOUR=9",
"timezone": "local",
"misfire": "latest",
"overlap": "forbid",
"timeoutMinutes": 30,
"runtime": "coven-code",
"familiarId": "charm",
"cwd": "/absolute/path/to/project",
"prompt": "Write the daily reflection.",
"tags": ["notes"]
}
}The v1 implementation validates:
schemaVersionis exactly1;idis 1–96 ASCII letters, digits,.,_, or-;nameis 1–160 characters;statusisACTIVEorPAUSED; reads can also returnDISABLEDaftercoven.automations.definition.disable.v1;rruleusesFREQ=DAILYorFREQ=WEEKLYwith supportedBYHOURvalues, andBYDAYonly for weekly rules; empty or repeated parts and repeated weekdays fail;timezoneisutcor an exact IANA zone name such asAmerica/New_York;localis accepted as input only, and Coven resolves it to the host's IANA zone before storing the definition or refuses the request (on Unix, aTZoverride must itself beutcor an IANA name);misfireislatestandoverlapisforbid;timeoutMinutesis 1–44,640;- optional
retrysetsmaxAttempts(1–10),backoffPolicy(none,fixed, orexponential),backoffSeconds(1–86,400, required forfixed), andretryableClassesfromtransient_dispatch,lease_expired, andruntime_unavailable; runtimeis non-empty and at most 64 characters;promptis non-empty;- optional
familiarIdis non-empty and at most 64 characters.
Optional fields also include model and tags. outputTarget fails
validation until atomic delivery is certified, and an authority block (a
Runtime Authority declaration) fails validation until the daemon advertises
Runtime Authority. In an IANA zone, a wall-clock
slot removed by a spring-forward change does not run, and a slot repeated by a
fall-back change runs once, at the earlier instant; see
Automations scheduling for the
recurrence subset, time zones, missed slots, retries, and timeouts with their
conformance cases. Treat all filesystem paths as host-local values. Do not copy a definition between hosts without reviewing
its cwd and timezone.
Manual runs and health
An immediate run uses:
{
"action": "coven.automations.run",
"id": "daily-notes"
}A successful dispatch returns a run id and session id with status running.
That status proves durable correlation and runtime ownership, not completion.
The automation run remains nonterminal until the correlated session ledger
contains authoritative terminal evidence. Launch acknowledgement, process
output, or a dropped client connection must not be reported as success. If a
running response also carries error, Coven kept runtime ownership but could
not confirm the launch; treat that run as unresolved.
If the launch fails before any process starts and the failure class is in the
routine's retry.retryableClasses, the response has status retry_scheduled,
a run id, no session id, and the launch error. The scheduler starts the next
attempt after its backoff.
A missing routine, missing cwd, quarantined routine, unsettled earlier run,
or launch refusal returns a rejected response: HTTP 400, accepted: false,
and the cause in reason. coven.automations.run does not check the
routine's status, so it also runs a paused routine;
coven.automations.occurrence.runNow.v1 requires an active one. A refused launch still leaves its run: an ordinary
run is held for an operator retry until its deadline
rather than failed. Deadline and restart recovery settle
conservatively: timeout handling requires strict process-tree containment, and
an interrupted run stays nonterminal until Coven can prove a terminal
disposition.
To run a routine now with replay protection, send
coven.automations.occurrence.runNow.v1 instead. It plans a manual occurrence,
claims it, and dispatches it through the same path as a scheduled one, so the
routine's timeout, overlap, and retry policies still apply:
{
"action": "coven.automations.occurrence.runNow.v1",
"adoptionKey": "run-now-daily-notes-0001",
"automationId": "daily-notes",
"note": "Rerun after fixing the notes template."
}The result has occurrenceId, automationId, and occurrenceState, plus
runId, status, and sessionId once a run exists, and echoes note
(at most 500 characters). Read status as for coven.automations.run. If the
launch is refused before a session starts, the result has no sessionId: the
status is retry_scheduled when an automatic retry applies, an ordinary run is
otherwise held for an operator retry (occurrenceState: "claimed", status: "running"), and any other refusal settles it failed. An
unexpected dispatch error is returned in error and settles the occurrence
failed. bypassEligibility is accepted but changes nothing in v1, which has
no eligibility conditions.
The occurrence id derives from the adoptionKey, and the claim commits before
the launch, so an exact replay returns the same occurrence and its run with
reason: "replayed previously adopted run" and never launches a second time.
Reusing the key for a different request returns ADOPTION_REPLAY_MISMATCH.
The command is refused with NOT_FOUND, GONE_TOMBSTONED for a tombstoned
routine, ILLEGAL_TRANSITION when the routine is not active or is
quarantined, VALIDATION_FAILED when it has no cwd, and OVERLAP_FORBIDDEN
(409) while it already has a nonterminal run.
Automatic retries cover only transient_dispatch, lease_expired, and
runtime_unavailable failures with evidence that no process started. Each
retry is a new attempt inside the same run and its original timeout. Backoff
none retries immediately, fixed waits backoffSeconds, and exponential
uses deterministic jitter capped at one day. When a routine exhausts
maxAttempts, Coven quarantines the routine until you call
coven.automations.unquarantine, and the run is held for an operator retry
like any other failed ordinary run.
Operator retry
When an attempt of an ordinary run fails and no automatic retry follows, Coven
holds the run running until its deadline instead of failing it. The failed
attempt stays failed, the run has no live session, the occurrence stays
claimed (failed before launch) or running (failed after start), and its
failure reason ends with held for an operator retry until the run's deadline.
If no retry is opened by the deadline, the run and occurrence settle failed
with the reason no operator retry was opened before the run's deadline.
Runtime Authority runs are not held.
To retry a held run, name its latest attempt and that attempt's disposition, so a retry never lands on an attempt you did not mean:
{
"action": "coven.automations.attempt.retry.v1",
"adoptionKey": "retry-daily-notes-0001",
"runId": "RUN_ID",
"priorAttemptNumber": 1,
"priorDisposition": "failed",
"note": "Fixed the missing template."
}The retry opens the next attempt in the same run, classified
operator_retry, and returns the occurrence to planned for the scheduler to
dispatch. The result has runId, occurrenceId, attemptId,
attemptNumber, priorDisposition, status: "planned", and retriedAt;
note is optional and at most 500 characters. It is refused with:
RETRY_DISPOSITION_INVALIDwhen the attempt number or disposition does not match the run's latest attempt;AMBIGUOUS_RETRY_FORBIDDENfor ambiguous work, which onlycoven.automations.occurrence.recover.v1resolves;ILLEGAL_TRANSITIONwhen the run is not held: it is settled, its latest attempt is still in flight, it has used all 10 attempts, or its routine is not active or is still quarantined (callcoven.automations.unquarantinefirst);CANCEL_PENDINGwhile a cancellation or stop is unresolved;DEADLINE_EXCEEDEDonce the run's deadline has passed;AUTHORITY_REQUIREDfor a Runtime Authority run.
An exact replay returns reason: "replayed previously adopted retry" and opens
nothing new, and reusing the key for anything else returns
ADOPTION_REPLAY_MISMATCH. To give up on a held run before its deadline, cancel
its occurrence with coven.automations.occurrence.cancel.v1: the run and
occurrence settle cancelled and the failed attempt stays failed.
attempt.cancel.v1 refuses the held attempt, because it has already settled.
Cancellation and recovery
To cancel a run, send coven.automations.run.cancel.v1 with the run id, the
current attempt id from the run's attempts, and its session id.
Cancellation stays a request until Coven confirms the session stopped; read
the run's cancellation record for its state.
To cancel by occurrence or attempt instead, without a session id, send
coven.automations.occurrence.cancel.v1 with occurrenceId or
coven.automations.attempt.cancel.v1 with attemptId, plus an adoptionKey
and an optional reason of at most 500 characters (default
"cancelled by the owner"):
- Work that has not been dispatched, an occurrence still
plannedorclaimedor an attempt stilladoptedand waiting for its retry, is cancelled at once. The occurrence settlescancelled, and so do a waiting attempt and its run, with no session to stop. The result hasoccurrenceId,status: "cancelled",reason, andcancelledAt, plusrunIdandattemptIdwhen a waiting attempt was cancelled. - Work that is dispatching or running is handed to
coven.automations.run.cancel.v1under a key derived from yours, and the result is that run cancellation. It can answerCANCEL_PENDING(409) while the session's stop is unconfirmed; retry whenretryableistrue.
attempt.cancel.v1 accepts only the current attempt of a running run. Both
commands refuse an occurrence in recovery_required (resolve it with
coven.automations.occurrence.recover.v1), work that has already settled
(except that occurrence.cancel.v1 releases a run held for an
operator retry),
and a waiting attempt whose run deadline has passed, with
ILLEGAL_TRANSITION; that last case first settles the attempt timed_out.
An exact replay returns reason: "replayed previously adopted cancellation"
and changes nothing, and reusing the key for anything else returns
ADOPTION_REPLAY_MISMATCH.
When Coven cannot settle an occurrence on its own, because a stop could not be
confirmed or a launch was abandoned, the occurrence waits in
recovery_required. Coven never retries ambiguous work by itself. List these
with coven.automations.occurrence.list.v1 and view: "recovery_required",
then resolve each one with coven.automations.occurrence.recover.v1 and one
evidenceDetermination:
failed_deterministicsettles the occurrence and its runfailed. The result hasstatus: "failed", andrunIdwhen there was a run.retry_with_new_attemptopens the next attempt in the same run, recording the earlier attempt as ambiguous, and plans the occurrence for dispatch. The result hasstatus: "planned",runId,attemptId, andattemptNumber. The latest attempt must beambiguous, the run must have attempts left (at most 10) and an open deadline, and the routine must be active.
{
"action": "coven.automations.occurrence.recover.v1",
"adoptionKey": "recover-daily-notes-0001",
"occurrenceId": "OCCURRENCE_ID",
"evidenceDetermination": "failed_deterministic",
"statement": "Checked the worktree; the run wrote nothing."
}statement is optional, 1 to 1,000 characters, and is recorded with the
determination. Both determinations are refused with ILLEGAL_TRANSITION while
the latest attempt's session is still created or running; cancel it first, so
a retry never runs beside it. A retry after the run's deadline returns
DEADLINE_EXCEEDED; settle it failed_deterministic instead. A Runtime
Authority run returns AUTHORITY_REQUIRED, because settling it needs
authority-evidenced receipts. The adoptionKey works as it does for the
versioned definition commands: an exact replay returns the first answer, with
reason: "replayed previously adopted recovery" and no second change, and
reusing the key for anything else returns ADOPTION_REPLAY_MISMATCH.
Health
Use coven.automations.health for the next due time, recent planning and run
timestamps, consecutive failure count, live lease owner/expiry, the current
retry attempt (currentAttempt, maxAttempts, retryNotBefore), quarantine
state (quarantinedAt, quarantineFailureClass, quarantineReason,
consecutiveExhaustions), and a staleness reason. nextDueAt is null while
a routine is quarantined. Use coven.automations.runs, or
coven.automations.run.history.v1 to page by cursor, for persisted run history
rather than inferring completion from process output.
See Automations lifecycle for the contract's state machines and how the daemon's recorded states relate to them, Automations scheduling for how schedules, retries, and timeouts resolve, Automations conformance for what the contract is tested against and the exact revisions it depends on, Automations migration for importing Codex automations, Coven local API for transport and trust rules, and Safety for the broader authority model.
Last updated on