Parent program: #854
Foundation: #816
Outcome
Turn the existing internal automation structs and control actions into a stable, independently testable coven.automations.v1 protocol that Cave, the SDK, Psyche adapters, runtimes, and future implementations can consume without importing Coven internals or reproducing lifecycle semantics by hand.
The protocol must describe one canonical truth for definitions, occurrences, runs, attempts, authority bindings, receipts, commands, events, and failures.
Current gap
The landed foundation has a valid v1 Rust definition and useful coven.automations.* actions, but the public contract is still inferred from implementation:
- routine definitions are schedule + prompt records;
- JSON payloads are assembled inside the control action router;
- domain failures may be returned inside a successful/accepted outer response;
- there is no canonical revision/adoption model for mutating requests;
- there is no versioned event/changefeed envelope or independent replay reducer;
- occurrence, run, attempt, cancellation, recovery, and receipt semantics are not yet published as one state machine;
- clients cannot negotiate supported fields/actions or distinguish additive evolution from incompatible meaning changes.
Required normative objects
Publish schemas and corresponding Rust types for at least:
AutomationDefinition
- stable
automationId;
- monotonic
revision and definition integrity digest;
schemaVersion / contract profile;
- display metadata;
- lifecycle state (
draft | paused | active | disabled | invalid or ratified equivalent);
- one versioned
Trigger union;
- zero or more versioned
Condition values;
- one versioned
Action union;
- familiar binding policy;
- authority/approval policy references;
- runtime capability requirements;
- timeout, retry, concurrency/overlap, misfire, retention, and delivery policies;
- creator principal and creation/update provenance;
- effective/activation timestamps;
- explicit extension bag rules, if any.
For v1, ScheduleTrigger and FamiliarInvocationAction may be the only executable variants. The union must permit future variants without redefining v1 fields.
AutomationOccurrence
- stable
occurrenceId;
- automation ID + exact definition revision;
- trigger identity and canonical occurrence key;
- scheduled/observed/eligible timestamps;
- fence token/generation;
- state and state reason;
- misfire disposition;
- claim/lease metadata;
- active run reference, if any;
- cancellation/recovery metadata;
- timestamps and event sequence boundaries.
AutomationRun
- stable
runId and occurrence correlation;
- exact familiar identity binding;
- exact principal/authority/approval binding;
- exact runtime descriptor/capabilities;
- state, reason, start/finish times;
- current attempt and terminal disposition;
- delivery/result/artifact references;
- receipt reference.
AutomationAttempt
- stable
attemptId and monotonic attempt number;
- request/adoption key;
- dispatch fence;
- worker/runtime correlation;
- retry classification;
- heartbeat/lease observations;
- output/event cursors;
- terminal or ambiguous disposition.
AutomationReceipt
- immutable versioned receipt body;
- definition, occurrence, run, attempt, identity, authority, approval, runtime, delivery, and result digests;
- exercised capabilities and side-effect class;
- timestamps and producer identity;
- partial failures and recovery disposition;
- integrity/authentication field;
- retention/privacy classification.
Command and error envelopes
At minimum:
- create, revise, activate, pause, disable, delete/tombstone;
- run now;
- cancel occurrence/run/attempt;
- retry/recover with explicit prior disposition;
- list/get/history/health;
- subscribe/read events;
- legacy import.
Every mutating command must include a stable request/adoption key, expected revision where applicable, authenticated origin/principal context, and explicit intent. Define typed error codes and HTTP/control-action status mapping. A rejected or failed domain operation must not be wrapped as accepted: true merely because routing succeeded.
Event/changefeed envelope
Each durable event must include:
- schema/profile version;
- automation/occurrence/run/attempt identifiers as applicable;
- monotonically increasing sequence within its authoritative stream;
- globally unique event ID;
- observed and recorded timestamps;
- producer identity;
- idempotency key / causation / correlation;
- user-safe summary;
- structured payload;
- privacy/retention class;
- integrity field where required.
Define replay, pagination, cursor expiry, duplicate delivery, out-of-order rejection, and compaction/snapshot behavior.
Required lifecycle semantics
Ratify explicit state machines; do not permit arbitrary client-authored transitions.
Illustrative occurrence lifecycle:
planned -> eligible -> claimed -> dispatching -> running
-> succeeded | failed | cancelled | timed_out | recovery_required
planned/eligible -> skipped | superseded | cancelled
claimed/running with expired evidence -> recovering -> failed | recovery_required
Illustrative attempt lifecycle:
adopted -> dispatching -> started -> observing
-> succeeded | failed | cancelled | timed_out | ambiguous
Required invariants:
- command adoption commits before consequential side effects;
- one occurrence fence cannot own two accepted runs;
- one attempt cannot bind two runtime sessions;
- terminal states do not regress;
- absence of runtime evidence cannot become success;
- cancellation is a request until acknowledged/reconciled;
- retry creates a new attempt and never rewrites the prior attempt;
- ambiguous mutating work is not automatically retried;
- definition revision changes never rewrite historical occurrences/runs;
- deleting a definition tombstones it without erasing required history.
Compatibility and evolution
- Publish JSON Schema or an equivalently portable normative format.
- Define required/optional fields and unknown-field behavior.
- Add negative capability negotiation for unsupported trigger/action/policy variants.
- Separate contract version from implementation/release version.
- Establish additive compatibility rules and explicit incompatible-version refusal.
- Provide canonical JSON normalization where digests/signatures depend on bytes.
- Publish golden valid, invalid, downgrade, unknown-field, and replay vectors.
- Add a machine-readable compatibility matrix.
Implementation boundaries
crates/coven-cli/src/automations/** may implement the contract but must not be its only specification.
- Control actions and any HTTP routes delegate to the same command handlers and return the same typed outcomes.
- Cave, SDK, and Psyche consume generated or pinned contract artifacts rather than hand-maintained parallel types.
- This issue does not move schedule authority into Psyche or authority semantics into Cave.
Verification
- Schema validation and Rust round-trip tests.
- State-machine property tests proving invariant preservation.
- Request-adoption replay/conflict tests.
- Duplicate/out-of-order event replay tests.
- Expected-revision conflict tests.
- Typed transport/domain error mapping tests.
- Golden vectors runnable outside the Coven crate.
- Packed/released artifact tests rather than source-relative imports.
- Cross-repository canaries against SDK and Cave pinned to exact immutable artifacts.
Acceptance criteria
Non-goals
- Implementing every future trigger or action variant.
- Turning the protocol into a general-purpose workflow language.
- Letting clients author run state.
- Defining familiar identity or authority semantics independently of their canonical layers.
Bead packet
Create one P0 Bead mapped exactly to this issue. It depends on the #816 foundation and blocks scheduler certification, SDK mutation support, Cave v1 oversight, and the final #854 release gate. Evidence must include schema artifacts, vectors, exact test commands/results, compatibility canaries, migration proof, and unresolved semantic decisions.
Parent program: #854
Foundation: #816
Outcome
Turn the existing internal automation structs and control actions into a stable, independently testable
coven.automations.v1protocol that Cave, the SDK, Psyche adapters, runtimes, and future implementations can consume without importing Coven internals or reproducing lifecycle semantics by hand.The protocol must describe one canonical truth for definitions, occurrences, runs, attempts, authority bindings, receipts, commands, events, and failures.
Current gap
The landed foundation has a valid v1 Rust definition and useful
coven.automations.*actions, but the public contract is still inferred from implementation:Required normative objects
Publish schemas and corresponding Rust types for at least:
AutomationDefinitionautomationId;revisionand definition integrity digest;schemaVersion/ contract profile;draft | paused | active | disabled | invalidor ratified equivalent);Triggerunion;Conditionvalues;Actionunion;For v1,
ScheduleTriggerandFamiliarInvocationActionmay be the only executable variants. The union must permit future variants without redefining v1 fields.AutomationOccurrenceoccurrenceId;AutomationRunrunIdand occurrence correlation;AutomationAttemptattemptIdand monotonic attempt number;AutomationReceiptCommand and error envelopes
At minimum:
Every mutating command must include a stable request/adoption key, expected revision where applicable, authenticated origin/principal context, and explicit intent. Define typed error codes and HTTP/control-action status mapping. A rejected or failed domain operation must not be wrapped as
accepted: truemerely because routing succeeded.Event/changefeed envelope
Each durable event must include:
Define replay, pagination, cursor expiry, duplicate delivery, out-of-order rejection, and compaction/snapshot behavior.
Required lifecycle semantics
Ratify explicit state machines; do not permit arbitrary client-authored transitions.
Illustrative occurrence lifecycle:
Illustrative attempt lifecycle:
Required invariants:
Compatibility and evolution
Implementation boundaries
crates/coven-cli/src/automations/**may implement the contract but must not be its only specification.Verification
Acceptance criteria
Non-goals
Bead packet
Create one P0 Bead mapped exactly to this issue. It depends on the #816 foundation and blocks scheduler certification, SDK mutation support, Cave v1 oversight, and the final #854 release gate. Evidence must include schema artifacts, vectors, exact test commands/results, compatibility canaries, migration proof, and unresolved semantic decisions.