Skip to content

A task's life ​

A task starts when a card reaches Ready on the board. It ends when a person has approved the exact change and GitHub has merged it. In between, the agent writes code, the platform checks it, and nobody can skip a step: each move is checked against what is on record.

The path, in plain words ​

  1. Ready. A card on the board is Ready. Intake reads the board every 30 seconds by default, checks the repository's pins (image, harness, governance profile) and creates a task. A pin that is missing or wrong stops intake before any task exists.
  2. Preflight. Before agents work on a repository, a trusted runner proves its environment works at the exact base commit and forelead.env. The result is signed evidence. A failed attempt leaves the task waiting until the cause is fixed.
  3. Claimed. A runner claims the job. The claim is a lease that lasts 30 seconds and is renewed while the runner is alive.
  4. Agent session (running). The agent works in the sandbox. It can only write inside the task's allowed paths. A write outside them blocks the task and the issue says which path.
  5. Gates. The runner runs the declared gates on the agent's committed tree, in a fresh copy, and signs the results.
  6. Publish. The control plane publishes a signed commit and opens the pull request. The published tree must be identical to the tree that passed the gates.
  7. Review. A shadow review comments on the PR. Reviewers can send the work back for a fix round.
  8. Signature. A person signs merge:approved on the exact head commit. A signature on an older head does not count.
  9. Merge queue. If the base branch has a GitHub merge queue, the App queues the PR pinned to the signed head. Otherwise it merges directly.
  10. Merged, then done.

When things go wrong ​

  • Fix rounds. A blocking review sends the PR back to gates with a new task version. The default is 2 rounds; a repository can set 0 to 5 in reviewFix.rounds (0 means the default). A still-blocking review after the last round blocks the task.
  • Publish retries. If GitHub is unavailable when the signed publish runs, it is noted and retried. After 3 failures (counted from the latest claim, fix retry or refresh) the task is blocked and the agent's work is kept.
  • Base moves. If main moves while the gates run, the runner rebases onto the new base and gates again inside the same lease. After 3 moves (MaxBaseMoves) the task is blocked with "main moved 3 times while the gates ran"; the work is kept and can be retried.
  • Lost lease or crashed runner. The job is re-queued and the next claim continues the saved session. Code and research tasks get 3 claims; a task already in gates or published gets 5 resume attempts.
  • Clocks. Silence for 15 minutes re-queues the job. A total budget of 120 minutes running or 60 in gates blocks the task. Waiting on a decision board pauses both.
  • Cancels. cancelled is final and stays on record. A failed task can only move to cancelled, by a system or administrator retirement.
  • Blocked is a pause a person can resolve. It resumes to the state it came from.

Technical notes ​

  • The state machine is internal/lifecycle: states waiting, ready, claimed, running, gates, published, in_review, merged, done, blocked, failed, cancelled. A move to published needs signed gate evidence; a move to merged also needs a human merge approval. Every transition is appended to task_transitions and never rewritten.
  • Attempt limits are maxAgentAttempts, maxPlanningAttempts, maxResumeAttempts and maxRefreshAttempts in cmd/controlplane/agent_claim.go; publish retries use maxPublishFailures (cmd/controlplane/agent_publish_retry.go); base moves use records.MaxBaseMoves (internal/records/tasks.go, enforced in cmd/controlplane/agent_base_moved.go).
  • With a merge queue the App posts a forelead/merge-approved status on each queue entry and calls enqueuePullRequest with expectedHeadOid. A PR whose status is withdrawn is taken out with dequeuePullRequest (decision 0043, see the README).
  • The full set of failure behaviours, each with its test, is in Task failure contract. Clocks are in Task clocks.

Sources ​