Task states
Every task is in exactly one of ten states. You move a task with two commands; the background poller moves it the rest of the way by watching CI, reviews and QA. This page lists every state and every rule behind the transitions.
The map#
pablo task:start, then /pablo-commit-and-pr). Thin arrows are detected by the poller. Yellow states bring work back to you, with an agent's analysis. A merge closes the task from any state.There's no todo state on purpose: a ticket nobody has started has no task, it only exists in your tracker.
Every state#
| State | Entered when | On entering |
|---|---|---|
🔨 in-progress | pablo task:start | launch task-analyst and the project's startup script (each only once per task) |
⏸️ waiting | pablo task:waiting | remember the previous state |
📝 draft | /pablo-commit-and-pr | — |
🔴 ci-red | poller: a check failed | launch ci-analyst |
ready-to-review | poller: CI is green | mark the pull request ready on GitHub, then move straight to waiting-review |
👀 waiting-review | right after ready-to-review | — (the task waits for reviewers) |
✅ approved | poller: the review is approved | move straight to needs-testing, unless the project has no QA step: then it stays here until merged |
🧪 needs-testing | right after approved | record the time, as the baseline for QA signals |
🔁 request-changes | poller: changes requested or a comment review | launch pr-feedback; when it finishes, put the pull request back in draft |
🚨 testing-failed | poller: QA's failure signal | launch task-feedback; when it finishes, put the pull request back in draft |
ready-to-review only lasts an instant; if you ever catch it in a listing it shows as 👀 waiting-review.
Into draft: /pablo-commit-and-pr#
The one and only way work enters (or re-enters) draft, allowed from in-progress, ci-red, request-changes, testing-failed, waiting-review and approved. It commits, pushes, opens the pull request as a draft if needed, then sets the state. A raw git push is never detected and never changes a state. How to use it: Ship your work.
What the poller watches#
The poller only checks what makes sense for each state:
| State | Checks |
|---|---|
draft | CI red, CI green |
ci-red | CI green |
waiting-review | CI red, reviews |
approved | CI red |
needs-testing | QA failure signal |
| any state | merge (even waiting) |
CI#
- Red moves
draft(orwaiting-review) toci-red. Green movesdraftorci-redto review. - Pending is not a signal: the task just stays where it is.
- No checks at all counts as green, otherwise a project without CI could never leave draft.
- Checks whose name matches
ci.ignore_checksare left out. - If CI turns red during review (after a sync push, for example), the task goes to
ci-redand comes back the usual way. The pull request never left “ready” on GitHub, so reviews given before the blip still count.
Reviews#
From waiting-review, the poller reads the pull request's reviews and decides between approved and request-changes:
- Your own reviews never count. Replying to a comment on your own pull request creates a review in your name; it shouldn't send you back to draft.
- Bots are ignored, unless listed in
review.bot_whitelist. - Only reviews after GitHub's last “ready for review” event count. An approval from a previous round doesn't leak into this one. (GitHub's summary verdict is not used: it has no timestamp.)
- The latest review of each reviewer wins.
- Any “changes requested” or plain comment review beats every approval. If someone took the time to write, you read it before QA.
QA failure signal#
From needs-testing, the task moves to testing-failed when the project's testing.failure_signal fires: a label added to the pull request (GitHub), or the issue reaching a status (Jira, Linear). It must be a new event, newer than both the task's entry into needs-testing and the last signal already handled. An old label never triggers, and a label that stays never triggers twice. PABLO never removes the label or touches the ticket.
Known gaps, on purpose#
CI turning red during needs-testing, or during approved for projects without QA, doesn't move the task. A broken CI shows up at merge time anyway.
Projects without QA#
With testing.enabled: false, an approved review leaves the task in ✅ approved until the merge closes it. Entering needs-testing is refused, including with pablo task:state or when resuming a paused task.
Pausing and manual moves#
pablo task:waitingsaves the state and pauses. Resuming restores the state and runs its usual actions (agents that only run once don't run again). Resuming intoneeds-testingkeeps the original baseline, so QA signals that arrived during the pause are handled, not lost. Not allowed fromrequest-changesortesting-failed.pablo task:state <state>forces a state and runs the same actions as the automatic transition;--no-triggeronly records it (except forwaiting, which always remembers the previous state).pablo task:attach <state>adopts an existing worktree: it only writes the record, launches nothing and flips nothing. Analytics see the state as entered at attach time.
How to use them: Managing tasks.
Launches that never start#
Agent launches are fire-and-forget, so they never block a command. If no agent session appears for an agent-launching state (in-progress, ci-red, request-changes, testing-failed) within a short window, which happens when Orca hangs on a brand-new worktree, the poller fires the launches again, up to a few attempts, startup script included. In in-progress it also sets the Orca workspace name to the issue key. Then the normal checks run, so a ci-red task that turned green still moves on. You can always force it with pablo task:relaunch.