Skip to main content
Every task in dotbot’s queue has a status field that tracks where it sits in its lifecycle. The state machine is a closed transition table: the runtime is the only writer, anything not in the table is rejected, and the full history of state changes is recorded in the activity log. Understanding the states helps you interpret the dashboard, write conditional workflow steps, and debug stuck tasks.

Full state machine

Tasks live in a directory that matches their current status. For example, a task in the in-progress state has its JSON file under .bot/workspace/tasks/, in the directory for that status.

State descriptions

todo

The task has been created and is waiting to be picked up. Tasks in todo are ordered by priority (lower number runs first). A task-runner claims the next available todo task for the active workflow.

in-progress

A task-runner is executing the task in a single provider session. The agent explores the codebase, writes code in the task’s isolated worktree, runs tests, and prepares commits. dotbot claims the task directly into this state — there is no separate analysis step beforehand.
If a process crashes during execution, the task may be left in in-progress with no active process. The runtime resets orphaned in-progress tasks back to todo on startup, and dotbot doctor reports stale locks and orphaned worktrees so you can clean them up.

done

The task is complete. Code changes have been committed with a [task:XXXXXXXX] tag and squash-merged to the main branch, and the worktree and task branch have been cleaned up. Reaching done runs the verification gates first — secret scanning, framework integrity, and commit-info checks — then closes the provider session.

needs-input

The agent encountered a question it cannot answer from the codebase alone. The task is paused and the question is routed to a stakeholder via Teams, Email, or Jira. A task-scoped handoff is written so the next attempt on the same task resumes with the answer in context. Once answered, the task returns to todo to be picked up again.
The question_timeout_hours setting controls how long dotbot waits for an answer before flagging the task as overdue. Overdue questions appear on the Overview tab in the dashboard.

needs-review

The implementation is finished but the task is parked for a human to approve before it merges. A task moves here instead of done when its extensions.review.required flag is set. A reviewer then approves or rejects it. See Human review flow below.

failed

The task hit a terminal error. dotbot archives the diagnostic state and emits a notification. A failed task can be requeued to todo for a retry.

skipped

The task was intentionally skipped — for example an optional task whose condition evaluated to false, or work determined to be unnecessary. Skipped tasks do not block downstream tasks that depend on them via depends_on. A skip can record a machine-readable skip_reason such as condition-not-met or not-applicable.

cancelled

The task was cancelled. This is terminal with no recovery path.

The transition table

The runtime enforces a closed transition table. Any move that is not listed is rejected with an invalid-transition error.

Human review flow

When a task carries extensions.review.required, the agent calls task_mark_needs_review instead of completing the task. This moves the task from in-progress to needs-review and captures the pending commit so the reviewer sees exactly what would merge. A human then submits a decision with task_submit_review:
  • Approve — the task worktree is merged and the task transitions to done after the verification gates pass.
  • Reject — the worktree is discarded, the reviewer’s feedback is appended to extensions.review.feedback, and the task returns to todo for rework with the feedback guiding the next attempt.

Task priority ordering

Tasks within the same workflow run in ascending priority order. Tasks with the same priority may run concurrently when multiple slots are available. Priority is set in workflow.json and can also be patched directly on the task JSON file.

MCP tools that drive transitions

Task state changes go through MCP tools exposed by the dotbot runtime. The agent calls these during autonomous execution, and you can call them yourself from your AI tool’s MCP interface.
task_set_status replaces the older one-tool-per-transition family. A single status field now drives every move, with the transition table deciding whether the move is legal.