Task Schema
Tasks are stored in a unified SQLite database (~/.orch/orch.db). Both internal tasks (cron jobs, mentions) and external tasks (GitHub Issues) share the same schema and lifecycle. External tasks are also synced to GitHub Issues via labels and comments.
Key fields:
| Field | Description |
|---|---|
id | Internal store ID (auto-increment) |
external_id | GitHub issue number (if external) |
repo | Repository slug (owner/repo) |
title, body, labels | Task description and metadata |
status | new, routed, in_progress, done, in_review, blocked, needs_review |
agent | Executor (codex, claude, opencode, kimi, minimax) |
model | Model chosen by the router |
complexity | Router-assigned complexity (simple, medium, complex) |
summary, reason | What was done / why blocked |
attempts, last_error | Retry tracking |
branch, worktree | Git worktree path and branch name |
pr_number | Associated PR number |
input_tokens, output_tokens | Token usage |
input_cost_usd, output_cost_usd, total_cost_usd | Cost tracking |
origin | Source: github, internal, mention, job |
source, source_id | For dedup (e.g., mention ID, job ID) |
Task Lifecycle
new → routed → in_progress → needs_review → in_review → done (merged)
→ done (no PR)
→ blocked- new — task created (via
task add,gh pull, orjobs tick) - routed — LLM router assigned agent, model, profile, skills
- in_progress — agent is running
- done — PR merged (or agent completed with no code changes)
- in_review — review agent is actively running on the PR
- blocked — agent hit a blocker or crashed and requires human intervention (rare)
- needs_review — agent needs human help, or review agent requested changes. After repeated failures the engine moves tasks to
needs_reviewand removes any forcedagent:*label so an owner can reassign.
Delegation & Decomposition
Complex tasks can be decomposed into subtasks:
- Router sets
decompose: truefor complex multi-system tasks - Agent receives a planning prompt instead of an execution prompt
- Agent returns
delegations— a list of child tasks - Parent task is blocked until all children are
done - When children finish, parent is unblocked and re-run (rejoin)
Force decomposition manually:
orch task plan "Complex feature" "Detailed description"
# or add the "plan" label
orch task add "title" "body" "plan"The orchestrator will:
- Create child tasks with
parent_idset - Block the parent until children are done
- Re-run the parent via
pollorrejoin
Concurrency
- The engine dispatches tasks concurrently using a
tokio::sync::Semaphore(configurable concurrency limit) - SQLite WAL mode allows concurrent reads; writes are serialized by SQLite
- The
needs_reviewtoin_reviewstatus transition serves as an atomic guard against duplicate review agent spawns - Worktree cleanup runs in a background task so it does not block routing or dispatch