Skip to content

State Machines

Animus uses formal state machines to govern workflow and task lifecycle transitions. State machine definitions can be loaded from a JSON configuration file or use compiled-in defaults.

Workflow State Machine

The workflow state machine (crates/orchestrator-core/src/workflow/state_machine.rs) controls valid workflow transitions.

States

StateDescription
IdleWorkflow created but not yet started
RunningActively executing phases
PausedExecution suspended, can be resumed
CompletedAll phases finished successfully
FailedA phase failed and rework attempts are exhausted
CancelledManually cancelled
MergeConflictPost-success merge encountered a conflict

Events and Transitions

The table above is the operator-facing summary. The compiled engine machine in builtin_state_machines_document() (crates/orchestrator-core/src/state_machines/schema.rs) is finer-grained: Running expands into the working states EvaluateTransition, RunPhase, EvaluateGates, and ApplyTransition, plus a HumanEscalated state reached when the rework budget is exceeded.

PauseRequested and CancelRequested are accepted from every working state (only the relevant edges are drawn above to keep the diagram readable). Terminal states are Completed, Failed, and Cancelled.

Guard Conditions

Transitions can have guard conditions evaluated at runtime. The evaluate_guard() function receives a GuardContext and returns whether the transition is allowed. Guards enable conditional behavior like:

  • Only allow resume if the phase has rework attempts remaining
  • Only transition to completed if all phases have passed their gates

The WorkflowStateMachine struct (crates/orchestrator-core/src/workflow/state_machine.rs) wraps a CompiledWorkflowMachine and exposes apply(event), which delegates to the compiled machine with a permissive guard. The guard-aware transition logic — evaluate_guard() and the engine's apply() that accepts a guard closure — lives in crates/orchestrator-core/src/state_machines/engine.rs.

Task Status Transitions

Tasks follow a lifecycle managed by apply_task_status in crates/orchestrator-core/src/services/task_shared.rs.

Task Statuses

StatusDescription
BacklogInitial state, not yet ready for work
ReadyAvailable for dispatch
InProgressCurrently being worked on
BlockedCannot proceed (dependency, failure, etc.)
DoneSuccessfully completed
CancelledManually cancelled

Valid Transitions

When setting task status via set_status(), the validate parameter controls whether transition rules are enforced. The status application function also clears transient fields:

  • Moving to Ready clears paused, blocked_at, blocked_reason, and blocked_by
  • Moving to Blocked sets blocked_at and blocked_reason

Requirements Lifecycle

The requirements lifecycle machine (also from builtin_state_machines_document()) governs the PO/EM review flow for kind=requirement subjects, with rework_budget_available guarding the rejection edges.

Terminal states are Approved, Deprecated, Implemented, and Done. The PoFail and EmFail edges to NeedsRework are gated by rework_budget_available.

Phase Lifecycle

Individual workflow phases have their own status tracking:

StatusDescription
PendingPhase not yet reached in execution order
ReadyPhase is next in the execution queue
RunningAgent is actively working on this phase
SuccessPhase completed successfully
FailedPhase failed (may trigger rework)
SkippedPhase was skipped (gate condition or filter)

State Machine Configuration

State machines can be customized per project via state-machines.v1.json, stored in the project's scoped state directory.

The StateMachineMode enum controls which definition source is used:

ModeBehavior
BuiltinUse compiled-in Rust definitions only
JsonLoad from JSON file, fall back to builtin on parse errors
JsonStrictLoad from JSON file, fail on parse errors

Loading goes through load_state_machines_for_project() in crates/orchestrator-core/src/state_machines/mod.rs, which defaults to StateMachineMode::Json; callers can request Builtin or JsonStrict explicitly via load_state_machines_for_project_with_mode(). There is no environment variable that overrides the mode.

The LoadedStateMachines struct contains:

  • compiled -- The CompiledStateMachines with ready-to-use workflow and requirement lifecycle machines
  • warnings -- Any validation warnings from the JSON load
  • path -- The path the JSON file was loaded from

The state machines module (crates/orchestrator-core/src/state_machines/) includes:

  • schema.rs -- JSON schema definitions and builtin defaults
  • engine.rs -- Compiled machine evaluation, guard evaluation, transition application
  • validator.rs -- Validation of state machine documents against expected invariants

Released under the Elastic License 2.0 (ELv2).