Skip to content

The Daemon

Dumb Scheduler, Not a Feature Host

The Animus daemon is a scheduler. It consumes SubjectDispatch envelopes, manages subprocess capacity, spawns workflow-runner processes, and emits execution facts. It does not contain AI logic, task policy, or business rules.

This deliberate simplicity keeps the daemon generic. Advanced behavior lives in YAML workflows executed by workflow-runner.


The Tick Loop

The daemon operates on a periodic tick (default: every 5 seconds). Each tick follows the same sequence:

Step by step

  1. Load dispatch queue -- Read queued SubjectDispatch values, ordered by priority and requested_at.
  2. Check capacity -- Determine how many new workflows can be started given the current slot usage and headroom configuration.
  3. Dequeue -- Pop the highest-priority dispatch that fits within capacity.
  4. Spawn -- Start a workflow-runner subprocess, passing the workflow_ref, subject identity, and input. Built-in task subjects get a managed worktree; plugin-owned task subjects run from project_root unless the plugin provides its own checkout strategy.
  5. Poll -- Check all active workflow-runner subprocesses for completion, telemetry, or failure.
  6. Emit facts -- Publish execution facts (workflow started, phase completed, workflow succeeded/failed) for projectors to consume.

Capacity Management

The daemon controls concurrency through three mechanisms:

ControlDescription
Max concurrent workflowsHard limit on how many workflow-runner subprocesses can run simultaneously.
Slot headroomReserve slots so the system is never fully saturated. Allows high-priority work to preempt.
Priority orderingDispatches are dequeued in priority order. Within the same priority, earlier requested_at wins.

The daemon tracks active subjects to prevent duplicate dispatches for the same subject.


What the Daemon Knows vs. Does Not Know

Knows about

  • Subjects -- generic SubjectRef identity (kind, id, optional metadata).
  • Dispatch envelopes -- SubjectDispatch with workflow_ref, priority, trigger source.
  • Slots and headroom -- How many workflows are running, how many can start.
  • Subprocess lifecycle -- PID tracking, health checks, orphan detection on restart.
  • Runner telemetry -- Phase progress, resource usage, timing.
  • Workflow execution events -- Started, phase completed, succeeded, failed.

Does NOT know about

  • Task status policy (backlog, ready, blocked transitions).
  • Backlog promotion rules.
  • Retry policy (handled by workflow-runner's rework loop).
  • Requirement state transitions.
  • AI logic, prompts, or model selection.
  • Git workflow policy (branching, merging, PR creation).

These responsibilities belong to workflow-runner, projectors, or MCP tool surfaces.


Execution Facts and Projectors

When a workflow completes (or fails), the daemon emits execution facts. Projectors subscribe to these facts and update domain state accordingly.

The daemon emits facts; it never interprets them. This separation means adding a new projector (e.g. a Slack notifier) does not require changing the daemon.


Starting and Stopping

bash
animus daemon start --autonomous    # Start daemon in background (forks child process)
animus daemon status                # Check daemon health and active workflows
animus daemon pause                 # Pause dispatch (running workflows continue)
animus daemon resume                # Resume dispatch
animus daemon stop                  # Graceful shutdown

When started with --autonomous, the daemon forks a child process. Structured runtime events are written through the active log storage backend and mirrored locally at ~/.animus/<repo-scope>/logs/events.jsonl. Use animus daemon stream for live events and animus logs tail for recent persisted entries.

Failure Recovery

  • Daemon crashes -- On next startup, orphan recovery detects and cleans up stale subprocesses, but newly-started workflows get a 90-second grace window before they can be treated as orphaned.
  • workflow-runner crashes -- The daemon detects the process exit and emits a failure fact.
  • Phase fails inside a workflow -- Handled by workflow-runner's rework loop, not by the daemon.

Released under the Elastic License 2.0 (ELv2).