Chair and workers

One Chair per project, elected by arrival. A second interactive Chair is refused, and workers may not spawn workers.

What it is#

Two roles, and only two.

Role How it is set May spawn workers?
chair The first interactive orch <agent> seat in a project, opened with an empty task Yes — dispatch_worker, task_add, task_run
worker Created by task_run or dispatch_worker, or any process with ORCH_ROLE=worker No — the attempt errors
        you, typing in the agent UI
                   |
                 Chair                (one per git project)
             /     |     \
        worker  worker  worker        (own orch/<session> worktree each)
             \     |     /
           msg_send / ask / verify_report
                   |
                 Chair

Election is by arrival, not by configuration. Open orch claude in a project and that seat is the Chair. Open a second interactive seat in the same project and orch refuses it:

project already has Chair session <id> (<name>) — one Chair per project; spawn workers with orch task run, or pass --force-chair

--force-chair exists for the case the message names: you really do want two live Chairs. Ghost seats left behind by a killed terminal are cleared automatically, so you should rarely need it.

Fan-out from a worker is denied on both transports, with the same string:

dispatch_worker denied: ORCH_ROLE=worker — only the Chair may spawn (use orch msg to the Chair)

Why it exists#

A worker that can spawn workers is a fork bomb with a credit card. More quietly: it is also an accountability hole — nobody is left holding the thread that decides when the task is done. One Chair per project keeps a single place where work is handed out, a single inbox for questions, and a single verdict at the end.

Reporting is not fan-out, and the rule is explicit about it: a worker may call verify_report, because saying what you did is not the same as handing out more work.

How it relates to the rest#

  • A worker that needs a decision raises a blocking ask instead of guessing or spawning someone to decide for it.
  • Each spawned worker gets an orch/<session> git worktree by default; orch worktree status, orch worktree promote <session> and orch worktree prune are its lifecycle. Promote is fail-closed on conflicts and never pushes.
  • A task can carry standing context and a list of acceptance_criteria; each criterion is rendered into the worker's prompt as an unchecked box and must come back through verify_report marked met or not. A worker that never reports leaves them all standing as unmet on the board — deliberately.
  • When clarify_before_spawn is on, spawning is gated on orch ledger check passing, unless the call sets force.

Nothing to run here#

You elect a Chair by opening a seat, and you spawn a worker by asking the Chair for one in chat. orch dispatch --prompt "…" exists for scripts and CI, not for daily use.