How the orchestrator runs tasks end-to-end.
Full Development Cycle
Issue → Branch + Worktree → Agent works → Push → PR → Review Agent → Merge → Cleanup- Issue — created via
orchestrator task add,gh_pull, orjobs_tick - Branch + Worktree — orchestrator creates via
gh issue develop+git worktree add - Agent works — runs inside worktree, edits files, commits changes
- Push — orchestrator pushes the branch after agent finishes
- PR — agent creates with
gh pr create --base mainandCloses #N - Review — opposite agent reviews the PR via
gh pr review(approve / request changes / reject) - Fix + Reply — fix review findings, reply to each comment, resolve threads
- Merge — squash merge with conventional commit prefix (
feat:/fix:) - Release — CI auto-tags, generates changelog, creates GitHub release, updates Homebrew
- Cleanup — (TODO) orchestrator detects merged PR, removes worktree + local branch
Task Lifecycle
new → routed → in_progress → done → in_review → (merged externally)
→ blocked
→ needs_review- new: task created (via
add,gh_pull, orjobs_tick) - routed: LLM router assigned agent, model, profile, skills
- in_progress: agent is running
- done: agent completed successfully (no open PR)
- in_review: agent completed and a PR is open (review agent fires if enabled)
- blocked: agent hit a blocker or crashed
- needs_review: agent needs human help, or review agent requested changes
Poll Loop
serve.sh ticks every 10s:
poll.sh— findsnew/routedtasks, runs them in parallel (up toPOLL_JOBS=4)poll.sh— detects stuckin_progresstasks (no lock held, stale >30min), resets tonewpoll.sh— checks blocked parents: if all children aredone, unblocks parentjobs_tick.sh— checks cron schedules, creates tasks for due jobsgh_sync.sh— pulls issues from GitHub, pushes task updates back (every 60s)
Worktrees
The orchestrator creates worktrees before launching agents. Agents do NOT create worktrees themselves.
Worktree path: ~/.orchestrator/worktrees/<project>/gh-task-<issue>-<slug>
Steps:
gh issue develop <issue> --base main --name <branch>— registers branch with GitHubgit branch <branch> main— creates branch from maingit worktree add ~/.orchestrator/worktrees/<project>/<branch> <branch>— creates worktree- Agent runs inside the worktree directory (
PROJECT_DIRis set to worktree)
After agent finishes:
- Orchestrator pushes the branch (
git push -u origin <branch>) if there are unpushed commits - Agent should NOT run
git pushitself
Agent Invocation
run_task.sh runs the agent:
claude -p \
--model <model> \
--permission-mode acceptEdits \
--allowedTools "Write" \
--disallowedTools "Bash(rm *)" \
--output-format json \
--append-system-prompt <system_prompt> \
<agent_message>Agent Output
{
"status": "done|in_progress|blocked|needs_review",
"summary": "what was done",
"reason": "why blocked/needs_review (empty if done)",
"accomplished": ["list of completed items"],
"remaining": ["list of remaining items"],
"blockers": ["list of blockers"],
"files_changed": ["list of modified files"],
"needs_help": false,
"delegations": [{"title": "...", "body": "...", "labels": [], "suggested_agent": "codex"}]
}Review Agent
After agent completion, if a PR is open and enable_review_agent is true:
- Status overridden to
in_review - Opposite agent selected (codex wrote → claude reviews)
- PR diff fetched via
gh pr diff - Review agent evaluates and returns
approve,request_changes, orreject - Real GitHub PR review posted via
gh pr review
See the Review Agent page for full details.
Stuck Task Recovery
poll.sh detects stuck tasks:
- No agent assigned — task stuck
in_progresswithout an agent → set toneeds_review - Dead agent — task has agent but no lock file and
updated_atolder thanstuck_timeout(default 30min) → reset tonew
Max Attempts
Default: 10 attempts per task (configurable via config.yml). After max attempts, task goes to blocked with error. Retry loop detection: if the same error repeats 3 times, task goes to needs_review instead of retrying.