16 KiB
Orch CLI
Purpose
orch is the leader-facing scheduler and control plane. It owns the run, task graph, dependencies, ready queue, dispatch decisions, retries, and reassignment logic.
orch does not replace inbox. It uses inbox as the durable transport and execution record.
In normal operation:
- leaders use
orch orchcreates and monitorsinboxthreads- workers continue using
inbox - a separate worker runtime or worker agent must still consume the assigned inbox thread after
dispatch
Responsibilities
orch is responsible for:
- creating a run for one user request or project
- defining tasks and dependencies
- calculating which tasks are ready
- dispatching ready tasks to workers
- tracking attempts and mapping them to inbox threads
- allocating attempt worktrees for code tasks
- surfacing blocked tasks to the leader
- sending answers back into the active inbox thread
- reconciling thread state into task state
- blocking until actionable events arrive for the leader
- retrying, reassigning, cancelling, or adding follow-up tasks
Non-Responsibilities
orch should not implement:
- worker claiming
- direct worker polling
- automatic worker-runtime launch
- raw message append storage
- low-level thread history management
Those belong to inbox.
Core Objects
run: one coordinated execution for a user requesttask: one schedulable unit of workdependency: an edge between tasksattempt: one execution try for a taskdispatch: the act of materializing a task into an inbox threadworkspace: the branch and worktree assigned to one code-writing attempt
Workspace Model
For code-writing tasks, orch should allocate one Git worktree per attempt.
Strict policy:
- dispatch from a concrete committed
base_ref - fail dispatch if strict mode is enabled and the leader is implicitly relying on uncommitted state
- create a fresh worktree for every retry
- do not let workers edit the user's primary checkout
See worktree-execution.md for the full execution model.
Task State Model
planned: task exists but is not yet eligible for dispatchready: dependencies are satisfied and it can be dispatcheddispatched: an inbox thread exists but the worker has not started yetrunning: the task has been claimed and is actively executingblocked: the active attempt needs clarification or an external dependencydone: task completed and passed its current acceptance gatefailed: task completed unsuccessfullycancelled: task was cancelled and should not continue
Suggested transitions:
planned -> readyready -> dispatcheddispatched -> runningrunning -> blockedblocked -> runningrunning -> donerunning -> failedfailed -> readythrough explicit retry* -> cancelledby leader action
Leader Workflow
The normal leader loop is:
- create a run
- add tasks
- add dependencies
- inspect
ready dispatchtasks- arrange or launch a separate worker runtime that consumes the assigned inbox threads
- use
statusfor the current operational view; it reconciles first and includes latest attempt and message context - inspect
blocked - answer blocked questions
- if nothing is actionable, call
wait - retry or reassign failures when needed
- finish when all required tasks are
done
The leader should block on orch wait, not on ad hoc sleep.
CLI Surface
The binary name is orch.
Global Flags
--db PATH--json
orch run init
Create a new run.
Suggested flags:
--run RUN_ID--goal TEXT--summary TEXT
Example:
orch run init --db .agents/coord.db --run blog_mvp_001 --goal "Build blog MVP" --summary "Public blog plus admin CRUD"
orch run show
Show run metadata and current aggregate status.
Suggested flags:
--run RUN_ID
orch task add
Add a task to a run.
Suggested flags:
--run RUN_ID--task TASK_ID--title TEXT--summary TEXT--default-to AGENT--acceptance-json STRING--priority low|normal|high
orch dep add
Add a dependency edge.
Suggested flags:
--run RUN_ID--task TASK_ID--depends-on TASK_ID
orch ready
List tasks ready for dispatch.
Suggested flags:
--run RUN_ID--limit N
orch dispatch
Dispatch a ready task to a worker by creating an inbox thread and the first task message.
Suggested flags:
--run RUN_ID--task TASK_ID--to AGENT--repo-path PATH--base-ref REF--workspace-root PATH--strict-worktree--body TEXT--body-file PATH
Behavior:
- creates a new attempt
- automatically enables strict worktree mode for code-like tasks inferred from task metadata when worktree flags are omitted
- resolves the source repository from
--repo-pathor the current working directory - resolves a committed base revision
- creates a branch and worktree for the attempt when the task writes code
- creates or links an
inboxthread - writes workspace metadata into attempt storage and task payload
- moves the task to
dispatched - does not start a worker runtime on its own
Strict-mode recommendation:
- if
--base-refis omitted and the repository is clean, default toHEAD - if
--base-refis omitted and the repository is dirty, fail dispatch - if
--base-refis provided, resolve it to a commit and use it exactly - if
--workspace-rootis omitted in worktree mode, default to.orch/worktreesunder the source repository
orch reconcile
Read inbox state and update run/task state.
Suggested flags:
--run RUN_ID
Behavior:
- maps inbox
claimedorin_progresstorunning - maps inbox
blockedtoblocked - maps inbox
donetodone - maps inbox
failedtofailed
orch blocked
List blocked tasks and their latest question.
Suggested flags:
--run RUN_ID
orch wait
Block until one or more run-scoped events become available.
This is the normal wait primitive for the interactive leader.
Suggested flags:
--run RUN_ID--for task_ready,task_blocked,task_done,task_failed--after-event EVENT_ID--timeout-seconds N
Behavior:
- blocks until a later matching event exists
- reconciles inbox state while polling so worker thread transitions can surface as
task_*events - returns a cursor for the next wait
- lets the leader wait for worker activity without manual sleep loops
orch answer
Answer the active blocked question for a task by writing into the mapped inbox thread.
Suggested flags:
--run RUN_ID--task TASK_ID--body TEXT--body-file PATH--payload-json STRING
orch retry
Explicitly retry a failed task.
Suggested flags:
--run RUN_ID--task TASK_ID--to AGENT--body TEXT--body-file PATH
Behavior:
- creates a new attempt
- links the retry to the prior failed attempt
- dispatches a new inbox thread or fresh task message
orch reassign
Move a blocked or failed task to another worker.
Suggested flags:
--run RUN_ID--task TASK_ID--to AGENT--reason TEXT
orch cancel
Cancel a task or an entire run.
Suggested flags:
--run RUN_ID--task TASK_ID--reason TEXT
orch cleanup
Remove completed or abandoned attempt worktrees that are no longer needed.
Suggested flags:
--run RUN_ID--task TASK_ID--attempt N--all-completed--force
orch status
Show task state summary for the run.
Suggested flags:
--run RUN_ID
Behavior:
- reconciles inbox thread state before returning the view
- returns run aggregate counts plus per-task detail
- includes the latest attempt for each task when one exists
- includes the latest thread message for each task when one exists
- includes the latest blocked question for blocked tasks so the leader can inspect the current issue without a separate
blockedcall in the common case
orch show
Show one task with dependencies, attempts, and inbox mapping.
Suggested flags:
--run RUN_ID--task TASK_ID
orch council start
Start a three-reviewer council workflow for one target.
Suggested flags:
--run RUN_ID--target TEXT--target-file PATH--repo-path PATH--task-id TASK_ID--target-type text|repo|mixed--mode brainstorm|review--output markdown|json|both--only-unanimous
Default behavior:
- fixed reviewer roles:
architecture-reviewer,implementation-reviewer,risk-reviewer - analysis only
--target-type mixed--output both- unanimous-only disabled unless requested
- reviewer count fixed at
3in v1
orch council wait
Block until the council has enough reviewer responses to continue.
Suggested flags:
--run RUN_ID--timeout-seconds N
orch council tally
Group similar reviewer suggestions and compute support counts.
Suggested flags:
--run RUN_ID--similarity strict|normal
Behavior:
- groups semantically similar reviewer proposals
- assigns
consensus,majority, orminority - persists grouped recommendations in
orchstorage
Default behavior:
--similarity normal
orch council report
Render the final grouped council output.
Suggested flags:
--run RUN_ID--show consensus|majority|minority|all|consensus,majority
Default behavior:
- show
consensus,majority - preserve
minorityin persisted storage even if omitted from the main report - support both markdown artifacts and JSON output
Relationship To Inbox
orch should be implemented as a control plane on top of inbox.
orch dispatchwrites the firsttaskmessage intoinboxorch dispatchalso writes worktree metadata for code tasks into the attempt record and inbox payload- workers claim and update status through
inbox orch reconcilereads thread state and converts it into task stateorch answerwrites an inboxanswermessage to the active thread
The leader should not need to hand-write inbox send during normal dispatch.
Higher-level workflows such as council review should also run on top of orch, not as a separate infrastructure layer. See council-review.md.
Waiting Model
The leader does not receive worker output as an in-memory push. Instead:
- workers write updates into
inbox inboxappends eventsorch reconcileconverts thread state into task stateorch waitblocks on the run-scoped event stream
This is still a single leader model. orch wait is just the leader's blocking read primitive.
JSON Contract
Every command should support --json.
Suggested success shape:
{
"ok": true,
"command": "dispatch",
"run_id": "blog_mvp_001",
"task": {
"task_id": "T4",
"status": "dispatched",
"assigned_to": "backend-worker"
},
"attempt": {
"attempt_no": 1,
"thread_id": "thr_987",
"base_ref": "main",
"base_commit": "abc1234",
"branch_name": "orch/blog_mvp_001/T4/attempt-1",
"worktree_path": ".orch/worktrees/blog_mvp_001/T4/attempt-1"
}
}
Suggested wait wake shape:
{
"ok": true,
"command": "wait",
"woke": true,
"next_event_id": 127,
"events": [
{
"event_id": 127,
"type": "task_blocked",
"run_id": "blog_mvp_001",
"task_id": "T5",
"thread_id": "thr_t5_attempt1",
"summary": "Editor choice undecided",
"payload": {
"question": "Should the admin editor use a rich text editor or plain textarea in MVP?"
}
}
]
}
Exit Codes
0: success10: no ready or matching tasks20: conflict30: invalid input or invalid state transition40: not found50: storage or internal error
SQLite Schema Draft
These tables should live in the same SQLite file as the inbox tables.
CREATE TABLE IF NOT EXISTS runs (
run_id TEXT PRIMARY KEY,
goal TEXT NOT NULL,
summary TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'active',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS tasks (
run_id TEXT NOT NULL,
task_id TEXT NOT NULL,
title TEXT NOT NULL,
summary TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL,
default_to TEXT,
priority TEXT NOT NULL DEFAULT 'normal',
acceptance_json TEXT NOT NULL DEFAULT '[]',
latest_attempt_no INTEGER,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
PRIMARY KEY (run_id, task_id),
FOREIGN KEY(run_id) REFERENCES runs(run_id)
);
CREATE TABLE IF NOT EXISTS task_dependencies (
run_id TEXT NOT NULL,
task_id TEXT NOT NULL,
depends_on_task_id TEXT NOT NULL,
PRIMARY KEY (run_id, task_id, depends_on_task_id)
);
CREATE TABLE IF NOT EXISTS task_attempts (
run_id TEXT NOT NULL,
task_id TEXT NOT NULL,
attempt_no INTEGER NOT NULL,
assigned_to TEXT NOT NULL,
thread_id TEXT NOT NULL,
base_ref TEXT,
base_commit TEXT,
branch_name TEXT,
worktree_path TEXT,
workspace_status TEXT,
result_commit TEXT,
status TEXT NOT NULL,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
PRIMARY KEY (run_id, task_id, attempt_no)
);
CREATE INDEX IF NOT EXISTS idx_tasks_run_status
ON tasks(run_id, status, priority, updated_at);
CREATE TABLE IF NOT EXISTS events (
event_id INTEGER PRIMARY KEY AUTOINCREMENT,
run_id TEXT NOT NULL,
task_id TEXT NOT NULL,
thread_id TEXT,
source TEXT NOT NULL,
event_type TEXT NOT NULL,
message_id TEXT,
summary TEXT NOT NULL DEFAULT '',
payload_json TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_events_run_event
ON events(run_id, event_id);
Embedded Skill Draft
The following block is a draft SKILL.md for the leader-facing orch skill.
```markdown
---
name: orch
description: Use this skill when the leader needs to plan and schedule work through the orch CLI. It is for creating runs, adding tasks and dependencies, finding ready work, dispatching tasks to workers, allocating task worktrees, reconciling inbox state, waiting for worker events, reviewing blocked tasks, answering them, retrying failures, reassigning work, and cleaning up attempt worktrees. Do not use this skill for worker-side claim or progress updates; use inbox for that.
---
# Orch
Use this skill when you are the leader and need to control the task graph through the `orch` CLI.
## When To Use
- you need to decompose a goal into tasks
- you need to record dependencies
- you need to know which tasks are ready
- you need to dispatch work to workers
- you need to allocate isolated worktrees for code-writing tasks
- you need to inspect blocked tasks and answer them
- you need to retry or reassign a failed task
## Rules
- Prefer `orch` over hand-written `inbox send` for normal leader operations.
- Reconcile inbox state before making new dispatch decisions.
- If nothing is actionable, use `orch wait` instead of manual sleep loops.
- For code tasks, dispatch from a committed base and allocate a fresh worktree per attempt.
- Keep tasks small enough to be checkable and to minimize clarification loops.
- Use `inbox` directly only for inspection or manual repair.
- Keep user-facing discussion in the leader.
## Typical Commands
```bash
orch run init --run blog_mvp_001 --goal "Build blog MVP" --summary "Public blog plus admin CRUD" --json
orch task add --run blog_mvp_001 --task T1 --title "Project skeleton" --summary "Initialize app structure and database wiring" --default-to foundation-worker --json
orch dep add --run blog_mvp_001 --task T2 --depends-on T1 --json
orch ready --run blog_mvp_001 --json
orch dispatch --run blog_mvp_001 --task T1 --to foundation-worker --base-ref main --workspace-root .orch/worktrees --strict-worktree --body-file tasks/t1.md --json
orch reconcile --run blog_mvp_001 --json
orch wait --run blog_mvp_001 --for task_blocked,task_done,task_failed --after-event 0 --timeout-seconds 900 --json
orch blocked --run blog_mvp_001 --json
orch answer --run blog_mvp_001 --task T2 --body "MVP supports draft and published only." --json
orch retry --run blog_mvp_001 --task T7a --to backend-worker --body "Retry after fixing the contract mismatch." --json
orch cleanup --run blog_mvp_001 --all-completed --json
```
```