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
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.
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 carriesextensions.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
doneafter the verification gates pass. - Reject — the worktree is discarded, the reviewer’s feedback is appended to
extensions.review.feedback, and the task returns totodofor rework with the feedback guiding the next attempt.
Task priority ordering
Tasks within the same workflow run in ascendingpriority 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.