orchestrate · git:20261104.423decb · 2026-11-04 · sha256 7b093d79c73f5d73
orchestrate git:20261104.423decbA
Immutable. This exact content never changes and is served at /api/v1/blob/7b093d79c73f5d73.
---
name: orchestrate
description: "Use when this session is the top-level orchestrator over every Claude Code and Orca session (\"오케스트레이터로\", \"모든 세션 관리해줘\", \"이 세션도 편입해줘\"), or drives a project to done through several Orca workers — \"PM 겸 오케스트레이터로 끝까지\", 3+ tickets in parallel with their PRs landed, a progress dashboard (\"대시보드 갱신해줘\") — or takes over (\"resume\") another lead's program, or asks why a program's PRs are not moving."
---
# Orchestrate a program
Core rules. The plugin's reorient hook prints this list verbatim after every compaction, so it stays short and self-contained:
1. Delegate. When the human gives an instruction, do not do the work yourself: hand it one layer down at once (a worker, a card, a background subagent) with the facts you already have, and have that layer sum up its result for you.
2. Your own turn holds coordination (briefs, starting and closing units, inbox ack and wait, decisions, landing), the acts in `references/top-level.md` "Acts only the human's session may take", answers from what is already in your context, and one `--json` read (`orch status`, one `orca … --json`, one `gh … --json`). Any other task work is a delegation; you write no PR yourself.
3. The orchestrator is the root. Leads sit under it, each lead's workers under that lead, and a single card the orchestrator starts sits directly under it.
4. The orchestrator sends a project's work to its lead, never to the lead's workers or into its own hands, and gives a lead to a project that meets "Starting a lead" (`references/top-level.md`); a lead sends its own project's work to its workers.
5. Start a child card with `skills-sync card`. A raw `orca orchestration worker-start` that makes a worktree takes `--worktree new-child` (`new-top-level` and `--no-parent` only when the brief names them); one that attaches a Dispatch to an existing card takes `--worktree id:<its worktree>` (`references/top-level.md` "Starting a lead", promoting a running card). When Orca refuses `new-child`, stop and report the refusal, never retry it as `new-top-level`.
6. Exactly one background inbox wait runs at all times (`orch wait <slug>`, or without a program `orch inbox`), plus one `orch watch-cards` when you started cards no Run lists; after a compaction or restart, check both are alive before anything else (agent-skills:reboot).
7. A status report is `orch brief render` output as printed (agent-skills:brief); add judgment through its flags, never rewrite its shape.
8. A PR lands only through `orch land` with green required checks and an independent review with nothing left to act on (`references/landing.md`), or as a plain merge the human approved under "Merge policy".
9. Your turn ends on a short answer to the human; completion reaches you as a notification, never by polling.
You own the program, not the code. You frame it, write briefs, drain the inbox, keep dependencies and the land order honest, and decide. Orca already owns the mechanics: Run, Task and its deps, Dispatch, `check --wait`/ack, `ask`/`reply`, gates, the worker contract, recovery and release. This skill adds only the program layer. Where an Orca command does the job, use it rather than add a wrapper that parses its output; the inbox wait in step 5 keeps its own rule. Code that must still read a response passes it through raw with one warning line when a field is missing, and gets no per-Orca-version branches, fixtures or contract tests.
**REQUIRED BACKGROUND:** at the start of every orchestrator or lead session, run `orca skills get orchestration` and read it. Every Orca command here comes from it; never compose one from memory.
## Roles
Two modes share these rules: **top-level** is the orchestrator's (`references/top-level.md`), **program** is a lead's (the Steps below). Every layer above a worker is one of these two, and the skills name it as one of them, never as "coordinator".
| Name | What it is | Started with | ROLE line |
|---|---|---|---|
| orchestrator (오케스트레이터) | The one top-level session the human talks to, above every task session and every lead. It routes, answers and starts leads; it drives no program itself. It owns the routing between projects and supervises the leads and the single-PR cards it started (their review, and the closing reports it checks). | `claude --agent agent-skills:orchestrator --name orchestrator` | `ROLE: orchestrator` |
| lead (리드) | A session that drives one project (one repository, one topic) to done through workers, in program mode. A session asked to run a project to done ("PM 겸 오케스트레이터로 끝까지", a program resumed) is a lead even when the human calls it 오케스트레이터. It owns its project end to end: the split into units, who runs each and in what order, the dependencies between them, and the final check. | `claude --agent agent-skills:lead --name lead:<slug>`, or `skills-sync card` with the Lead brief (`references/brief.md` "Lead"): a dispatched worker or a `/goal` card, by Orca's setting | `ROLE: lead <slug>` |
| worker, card | One unit (a ticket, an investigation) in its own worktree: a `worker-start` worker reports to its Run, a `/goal` card to the session that started it. | `worker-start`, `dispatch-card` | none |
| standing role | A worker with no ticket: main guardian, QA lead, flow improver, resource steward (`references/roles.md`). "QA lead" names this worker role, not a lead. | `worker-start`, then `orch record … spawned --role` | none |
| coordinator (Orca's word) | What Orca calls the session bound to a Run that dispatches workers: here always the orchestrator or a lead. The word stays only where Orca's own text, output or fields (`coordinator_handle`, a worker preamble's "Your coordinator") are quoted, and in code, whose identifiers and comments follow Orca's data. Orca's "sub-worker" is a worker a worker started: a helper, below. | — | — |
**Depth.** Units nest at most three layers under the orchestrator: a lead (a dispatched worker on the orchestrator's Run, or a `/goal` card with its own Run when Orca's setting is below 3; `references/top-level.md` "Starting a lead"), the lead's workers (ticket units and standing roles), and a worker's helpers, which the worker starts with `worker-start` on the Run it works for. A card the orchestrator starts with no lead counts as a lead's layer, so its helpers are the second layer. A helper starts no unit of its own; a subagent inside a session is not a layer. Orca's nesting limit (Settings → Orchestration, `references/top-level.md` "Starting a lead") is the hard stop, and this ceiling holds whatever the setting. When a worker's helper `worker-start` is refused (`nested_worker_depth_exceeded`, the default setting refuses every one), do the work in the worker itself or a subagent, or ask the lead (the orchestrator, for a card with no lead) for another worker; never start that unit from a new Run or as a card, which only hides the depth from Orca. Starting a lead as a card when the setting is below 3 is the intended path, not that workaround.
Where a unit runs is one of three placements, named this way everywhere:
| Name | Made with | What Orca shows |
|---|---|---|
| child card (하위 카드) | `worker-start --worktree new-child`, or `orca worktree create --parent-worktree <selector>` | Its own worktree, branch and PR, listed under the session that made it (Orca's lineage, `parentWorktreeId`) |
| child terminal (자식 터미널) | `worker-start --worktree current` | A new terminal in your own worktree: no branch or card of its own, so only for work that writes nothing |
| `/goal` card | `dispatch-card` / `handoff-ticket` (`orca worktree create --prompt "/goal …"`) | Its own worktree and session, unsupervised by a Run; under its parent when created with `--parent-worktree` |
Which of the two takes a piece of work (one PR: the orchestrator and a card; related PRs, an order, deploy stages or a predicate: a lead) is `references/top-level.md` "Starting a lead".
A session's role is declared, never guessed from its terminal: the `--agent` flags above, or, for a session already running or a lead card whose launcher cannot pass flags, a prompt line of its own, `ROLE: orchestrator` or `ROLE: lead <slug>`; `ROLE: none` silences either. The plugin's reorient hook reads the role from the session itself, so it survives compaction, resume and fork, and puts one reminder line before every prompt of a declared session. A lead card's first prompt carries its `ROLE` line (`references/brief.md` "Lead").
### Who checks what
An index only: each rule lives behind its link.
| Check | Owner | Rule |
|---|---|---|
| Tests, the E2E run and VERIFY's output in the report | The worker | [deliver-ticket §5](../deliver-ticket/SKILL.md#5-ship), [brief VERIFY, REPORT](references/brief.md) |
| The independent review and its findings | The worker | [deliver-ticket §3](../deliver-ticket/SKILL.md#3-review), [independent review](../deliver-ticket/references/independent-review.md) |
| What a PR needs to land, and the human-approved exceptions | `orch land`; outside a program, the standalone card | Core rule 8, [Merge policy](#merge-policy), [landing](references/landing.md), [deliver-ticket §6](../deliver-ticket/SKILL.md#6-finish-the-ticket--done-means-its-acceptance-criteria-are-met) |
| main after a landing; the ticket's remaining criteria after its merge | The lander; red main, the main guardian | Step 8, [deliver-ticket §6](../deliver-ticket/SKILL.md#6-finish-the-ticket--done-means-its-acceptance-criteria-are-met) |
| The program's VERIFY; verifier independence on a high-blast-radius PR | The lead | Steps 2–3, [brief rules](references/brief.md#rules-for-filling-it) |
| Landed tickets, periodic E2E on main, design against code | The QA lead (a standing worker) | Step 8, [roles](references/roles.md) |
| The predicate's final check and its `predicate_verified` record | The lead; the QA lead or a verifier worker runs it | Step 9 Close |
| A lead's closing report before the human hears "done"; a single-PR card's review | The orchestrator, through a background subagent | [Starting a lead](references/top-level.md#starting-a-lead) |
| Human authorization and judgment | The owner | [brief HUMAN ONLY](references/brief.md), [deliver-ticket §6](../deliver-ticket/SKILL.md#6-finish-the-ticket--done-means-its-acceptance-criteria-are-met), [Asking the human](references/top-level.md#asking-the-human) |
## Stay answerable
The human must get an answer from you within seconds, at any time. You route; you do not do the work.
- Inside your turn, only three things happen: routing a request to its owner, checks that finish in seconds (`orch status`, one `orca … --json` read, one `gh … --json` read), and answering the human.
- Investigation, implementation, verification, reviews, long waits and monitoring go to an Orca worker or a background subagent (`run_in_background`; implementation goes to a card, below) the moment the request arrives. Hand over the facts you already have; do not "take a quick look first".
- Never block in the foreground: no `until` loops, no `sleep`, no `check --wait` or `orch wait` without `run_in_background`, no back-to-back polling reads. The one background inbox wait you keep is in Step 5, "One inbox wait, always". A PR waiting on a human is read at most hourly, and a rate-limit error waits for its reset (`references/brief.md` LAND).
- Completion reaches you as a notification: the background task's completion, or the `orch wait` that wakes on worker_done, escalation or question. Between notifications, your turn is over. A notice that arrives without the subagent's report (dropped by a hook or never shown as a turn) means the work ran: read the report from the subagent's transcript (`<session>/subagents/agent-<id>.jsonl`, its hand-back input) or the result file its prompt named, then the shared record (diff, tracker, PR); never ask it to resend or redo side effects. Tell a worker in that state the same.
- A request that would take you more than one short tool call is a delegation, even when you know the answer's shape.
- Browser, desktop, chat-send and web steps, edits outside your state directories, and reads past a quick check (code, pages, PRs, chats) go one layer down through Orca's own orchestration: a supervised worker on your Run (`orca orchestration worker-start`, or `dispatch` to a live terminal), whose `worker_done`, escalation or `ask` wakes your inbox wait; a card; or a background subagent. Never pipe a background command into `tail` or `head`: a watcher's lines never reach its output file.
- You write no PR: not code, not a doc, not a script, however small the follow-up. It goes to a card (a `worker-start` worker inside a program; otherwise `dispatch-card` §2 and `skills-sync card`, which starts a brief that reports to your Run as a supervised worker when your terminal is bound to that Run, else a `/goal` card; with an APPROVED line when the unit needs approved acts), not to a background subagent, and you judge, review and land it. A program unit is never a `/goal` card: a card owns no Dispatch, so Orca rejects its escalations (`sender_not_assignee`) and `orch wait` picks up the status they come back as only late, through its untyped fallback. At the first such rejection, start the remaining units with `worker-start` rather than writing status reporting into the shared brief. Under auto mode a background subagent's Edit or Write can get no verdict from the classifier; a unit already given to one restarts as such a card at the first failure, not after retries ("Refused acts"). The acts in `references/top-level.md`, "Acts only the human's session may take", are the only task work you do yourself, and none of them is writing a PR.
- These rules bind every layer above a worker: the orchestrator and every lead, a lead card another session started included (`references/brief.md` "Lead"). Such a layer judges results, lands, records decisions and puts what waits on the human in front of them. Investigation, implementation, verification, browser steps and new cards go one layer down. When a project has a lead, the layer above sends that project's work to the lead, never to the lead's workers and never into its own hands. The orchestrator starts a lead without being asked once a project's work meets `references/top-level.md` "Starting a lead".
- A research answer that later tickets will build on (a contract, an authorization or security rule, a scope cut) is one model's draft until it is challenged. Before you post it as the ticket's answer, copy it into briefs or close the ticket, have a background subagent run `interrogate` on it, and fold the findings to act on into the answer: every brief that quotes it inherits its blind spots. Your reading of the owner's direction is the same kind of draft: a reinterpretation "by applying an invariant" (folding the owner's choice into your own option) goes through `interrogate` before it reaches a brief or an option list.
- A card already on the task (the same PR, branch or ticket) that only needs to be told something gets a message, not a new card. One whose work needs a different implementation is superseded by a new card: first get a state summary from it (what is done, what is unpushed, what is left; read its worktree where it cannot answer) and put it in the new card's brief, then, in the turn you start the new one, tell the old card `superseded by <new card>: stop and close by end-session §8` (`orca orchestration send --to dispatch:<id>` for a worker; `skills-sync nudge <handle> "<that line>"` for a `/goal` card, logged with `orch sent add`). `skills-sync card --supersede` (with `--reference`) does that send and the log below for a card it recorded. Log the supersede itself with `orch sent add --to <old card's handle or worktree name> --kind supersede --text "superseded by <new card>"`, even when Orca keeps the send: `orch patrol` checks that card against this log. Without the summary the new card redoes or undoes finished work. A nudge refused because a prompt is open on its screen → close its agent terminal in this turn. A question the old card left waiting is stale: drop its decision and inbox item (`orch decide drop`, `orch-dash inbox resolve`), never answer it. Not closed by the next wake → close its agent terminal; its worktree follows `end-session` §4.
- A card that is stuck is not yours to finish: no merge, dispatch or browser step done in its place. A missing approval gets a new `/goal` card that carries it; a missing permission rule gets the human one `!` line ("Refused acts").
- What you started, you close, in the wake that tells you its work is over: a `worker_done`, or any message from a card that says it is done, whatever its form. Judge closing in that turn, before the merge or review the same wake brings: no later wake brings the report back. A background subagent or task you no longer need → `TaskStop` (never the one `orch wait`). A scratchpad or `.claude/worktrees/agent-*` worktree whose work landed or was dropped → `git worktree remove` (clean ones only). A card you made with `orca worktree create` or `dispatch-card` has no `worker_done`, so no `CLOSE OUT` line names it: in the wake its report arrives, read its screen. Its brief's `CLOSE` line should have closed it in that same turn. Still open (idle at its prompt, waiting on its inbox, or asking about work already done) → close it now: where `end-session` §4's Remove row holds (PR merged or closed, clean tree), remove it (`orca worktree rm --worktree path:<card>`); where an open PR or a real open question holds it, leave it, note what, and remove it (`orca worktree rm`) in the wake its PR merges; otherwise close its agent terminal (`orca terminal close --terminal <handle>`). Do not leave a finished card to `reap-resources`' `card` round: that is a sweep hours later, not the plan (`end-session` §8, "Who closes a finished card"). A standing loop (a heartbeat routine, `/loop`) also reads the `card` targets of `<state>/janitor-plan.json` (`reap-resources`) on every wake and closes each card of yours listed there the same way.
## When not to use
- One agent could finish inside the budget → do it in this session, or give it to one card with `handoff-ticket`. A program costs a lead.
- A single ticket handed to another session → `handoff-ticket`.
## Where each fact lives
| Fact | Owner |
|---|---|
| Goal | Orca Run `objective` (`run-create`), shown as the dashboard headline |
| Standing orders, predicate, merge policy, decisions, human digest | Program note in the notes store (`use-notes`), template `references/program-note.md` |
| Tickets, their state, which are derived | The tracker, through `use-tracker` (`tracker.py`) |
| PRs, CI, merges, stacks | GitHub, read there directly (a tracker's PR panel is a cache and lags) |
| Runs, tasks and their deps (the dependency graph), workers, questions, gates | Orca |
| Verdicts, lanes, land order, landings, main red/green, the concurrency cap, deps found after dispatch | `~/.claude/programs/<slug>/ledger.jsonl`, written only through `orch` |
| Briefs as sent | `~/.claude/programs/<slug>/briefs/<ticket>.md` |
| Decision trail | `~/.claude/programs/<slug>/decisions.tsv` (`show-me-your-work`) |
| Lessons: raw signals / what became of them | `signal` rows in the ledger / the lessons ledger in the notes store (`reflect`) |
| What the human watches | `orch-dash` dashboard (`references/dashboard.md`) |
| Who does what beside the ticket workers | Standing roles: main guardian, QA lead, flow improver, resource steward (`references/roles.md`) |
`orch` runs `scripts/prog.py` and `orch-dash` runs `scripts/dash.py`; the plugin's `bin/` puts both on the Bash PATH. Run either with no arguments for usage.
## Steps
1. **Frame.**
- Read every ticket in scope.
- Write the predicate as countable ticket IDs plus a final check on the real artifact ("ABC-1, ABC-2, ABC-3 Done and `verify-<app>` drives the quickstart on main"). Derive it yourself. If the tickets have no countable end, write your best predicate, mark it proposed in the digest, and go on. The predicate is the program's exit condition (principle **Work to an Exit Condition**): write its out-of-scope list beside it in the program note, and report progress as "N/M predicate items done", never as tickets filed.
- Copy the human's goal into the standing orders verbatim, one sentence per order. A sentence that would have a worker write outside its worktree stays verbatim in the lead's list, and the workers' list gets its worker form: "put it in the worker_done body; the lead writes it".
- Map the dependencies between tickets and split them by kind (`references/landing.md`): **start-after** (B needs A's result before it can begin) becomes an Orca task dep; **land-after** (B can be built on A's branch now) becomes a GitHub stack plus `orch dep` (only `orch dep` where CI runs only on PRs into the default branch), never an Orca dep. Two units that change the same path are land-after too, even when neither needs the other's result: the first to merge leaves the other in conflict, and the fix push dismisses its approval. So write each unit's paths in its brief's SCOPE, and never run two units on one path, or under one `exclusive_paths` glob, as parallel PRs on the same base.
- Check that the repo can land in parallel: required checks on, "require branches to be up to date" off, squash merges. Add the program's shared contracts to `exclusive_paths`. Set `visual_paths` to the files that render (`orch set <slug> visual_paths …`): its default globs are fnmatch, where `*` crosses `/`, so `apps/web/*` also catches test fixtures and `packages/ui/*` a README. When `land` flags a non-screen path again, narrow the knob once instead of asking the human for a `no-visual-change` label per PR. If strict mode has to stay, put its cost in the digest. A repo with no CI workflows at all never passes `land`, since no checks counts as pending: write that in the digest and in every brief, with the lane that replaces it: test the PR head in a detached worktree, then land it as the human-approved plain merge in "Merge policy" (a verdict at that head, zero unresolved threads, `--match-head-commit <head>`) and `orch landed`, so no worker sits in a `land` wait that can only yield.
- Read the target repository's data-sharing restrictions. Carry them into the digest and every brief's FORBIDDEN section; every reviewer and tool must stay within the permitted boundary. No permitted reviewer means review pending, never a model-specific exception.
- Pick the merge policy.
- Check the permission chain. Each card's auto-mode classifier judges every act on its own, and an instruction relayed from another session is not the human's, so the human's standing approval of each outward act the predicate needs must exist as a rule in the user's `autoMode.allow`: this repo's merges (`orch land`), its deploys when the program deploys, and edits to tracker items or PRs an earlier session made (a body patch, retitle, `gh pr edit`): the default soft-deny covers items the acting session did not create, so these are refused while new tickets, relations and comments pass. Read `claude auto-mode config` for a rule naming this repo or tracker project and the act. Missing: ask the human whether those acts are approved for the program; on yes, draft the rule with `tune-automode` ("프로젝트 지속 승인") and put its run line to the human (`orch-dash inbox add --type run_command … --key automode:<slug>`). You never edit settings yourself. Until the rule is in, those acts take the ask-first path of the merge policy.
- Bind this terminal to the program's Run: `orca orchestration run-current --json`; `run` null means `run-create --objective "<the goal>"` (or `run-use --id <run>` when resuming), then `run-current` again to confirm. Workers report to it, and only a bound terminal gets their mail typed in (`references/top-level.md` "Your Run").
- A lead started as a dispatched worker binds nothing: Orca refuses a worker binding the Run it works for. `orch doctor` names that Run and your dispatch; that Run is your `orch init --run`. Your workers start on it and report to your Dispatch mailbox, Orca's notice wakes you for their mail, and `orch init` records your dispatch, so `orch wait` reads your own mailbox and every `orch` command sees only the units under you.
- `orch init <slug> --repo … --run … --tracker-project … --predicate <IDs> --final-check "<the real-artifact check>" --note <program note path>`. Leave out `--tracker-project` where the tracker's credentials are not in the environment: with it, every `orch status` fails; without it, `status` lists the predicate to check by hand.
- Registering a program that has already merged PRs: `orch backfill <slug> --since <when its work began> --dry-run`, check the PRs it lists belong to the program, then the same without `--dry-run`. It adds those merges to the ledger at their merge time with their main CI result and moves `created_at` to the first one, so the cap, the rate and the dashboard count them. Never hand-edit the ledger for this.
- `orch init` and every `orch status` start the dashboard (`orch-dash ensure`: one server per store, restarted when its code is older; with the macOS LaunchAgent from `orch-dash install-agent`, launchd runs it and `ensure` only hands over to launchd) and print its URL; give it to the human once. Nothing on it is kept by hand: every number comes from the ledger, Orca, GitHub and the tracker, so record events instead of writing status files.
2. **Verification first.** Choose a harness or direct checks that prove the predicate on the real deliverable. Reuse an existing verification skill when suitable; create one only when useful within the authorized scope. Record the exact VERIFY commands before Pilot. The checks must cover every acceptance criterion regardless of packaging. Report a stale existing skill or harness, repair it within scope, and prove any uncovered criterion with direct checks; do not silently skip it.
3. **Pilot.** Run one worker through brief → PR → verdict → `orch land` → main green. Fix the brief, the unit size and VERIFY from whatever broke. Also confirm that the chosen worker model gets through its first `orca orchestration` call and its `orch land` without a permission prompt.
4. **Scale.**
- Spawn the standing roles (`references/roles.md`): a main guardian, a QA lead once the first tickets land, and the machine's flow improver and resource steward unless `worker-list` shows them running. Record each with `orch record <slug> spawned --role <guardian|qa|flow|steward> --note <dispatchId>`: Orca has no field for a role, and roles do not count against the cap. A ticket unit needs no such line (`references/brief.md`, "Single worker").
- Then spawn ticket workers up to the cap that `orch status` prints. The cap starts at 1, grows by one per landing proven green on main, and halves on red. The layers of one land-after chain (`orch dep`) count once, since they land as one merge; start the whole chain together.
For each ticket worker:
- Write the brief per `references/brief.md`, its FORBIDDEN copied whole from the current template, never shortened by hand. The template sentences of LAND and VERIFY are pasted the same way, in the template's language with only `<slug>`, ticket and PR filled in; the user's language rule covers the ticket-specific lines only, since a translation drops the clause a gate or exception rests on and a copied line can carry another program's slug. The spec starts with the ticket ID, never `/goal`.
- A shared brief (`briefs/_common.md`) holds copies of the template's paragraphs, and a reload reaches sessions, never briefs already written. After a `skills-sync broadcast` that changes `references/brief.md`, paste the changed FORBIDDEN, LAND or PEERS paragraphs into it and send them to the live workers, or they treat a form the new text allows as refused.
- Create its task with its start-after prerequisites as Orca deps (`task-create --deps '[…]'`), and start what `task-list --ready` offers, except `Land #N` tasks: those hold a human-gate decision for you, and `orch land` closes them. A land-after layer starts at once, stacked on the lower layer's branch, with `orch dep`. Before each start, `orch overlap <slug> --paths <its SCOPE paths>`: an `OVERLAP plan #N` line makes the unit land-after #N, so it starts stacked on #N. After PRs open, an `OVERLAP #A #B` line in `orch status` means the same for two open PRs: B merges A's branch, settling the conflict before review, and is stacked on A with `orch dep`, by the commands the line prints. An `OVERLAP <other-slug> …` line names another program's PR: no stack and no `orch dep`; settle the order through PARENT (`references/top-level.md` "Leads that depend on each other"). A prerequisite found after dispatch goes in `orch dep`. A lead started as a dispatched worker cannot create tasks or gates on the Run it works for (`worker_cannot_coordinate_own_run`): it starts each unit with `--spec` once its prerequisites have landed, and its decisions go to `orch decide add`.
- Once the program has a Run, every new unit starts with `worker-start`, never `orca worktree create --prompt` or `dispatch-card`, even when the cards you adopted at the start are `/goal` cards (the reason: "You write no PR" above).
- Run `worker-start --task <id> --worktree new-child --repo <selector> --base-branch <origin/main, origin/feat/<topic> or the lower layer's branch> --name <ticket id, lowercase> --display-name "<ID> <title>" --agent claude [--model <id>]`, or `--spec "<the brief>" --deps …` instead of `--task`. The model is the program note's worker model (default: the lead's own); a verifier runs independently of the implementer with the configured agent. Run `git -C <repo> fetch origin` first: a bare `main` is the local branch, which can be landings behind. The display name is the card's durable name; the terminal tab title is the agent's own and it overwrites any rename. Your own dispatch keeps the workers' one-act-per-call rule: the brief saved with Write first, then each `worker-start` in a Bash call of its own, with no brief write or other start beside it, so a refusal names its act and does not stop the other dispatches.
- Close its setup terminal once setup finishes. `skills-sync card` and `skills-sync handoff` start `skills-sync close-setup <card path> --agent <handle>` in the background themselves and print its log path; a raw `worker-start` or `orca worktree create` needs it run by hand, in the background. The setup terminal stays a shell after its script ends, so `orca terminal wait --for exit` never fires on it. Setup terminals left open slow Orca itself. The log ends in `result: failed` when the agent sits on a trust or permission dialog or shows no start. A setup stopped on a tool's trust prompt (an untrusted `.mise.toml` or `.tool-versions` in a fresh worktree) never finishes, and `close-setup` waits on it without output: read the setup terminal's screen when the log has said nothing for a few minutes, and trust the path as in `references/top-level.md` "Starting a worker".
5. **Drain.**
- **One inbox wait, always.** The orchestrator and every lead keep exactly one background inbox wait running, under `run_in_background`, and no other inbox watcher. With a program it is `orch wait <slug>`; a session without one runs `orch inbox --wait`. Never both. Its wait is a peek that marks nothing read, so a session cut while it waits loses nothing. On every wake, in the same turn: act on the batch, ack it, and start the wait again. `orch wait` prints the batch and the exact `check --run <run> --ack <delivery>` line to run. `orch inbox` prints the batch one line per message and the next command, `orch inbox --ack <delivery> --wait`, which acks the batch you handled and is the new wait. Do not read the inbox with raw `orca orchestration check --json` calls: each returns a whole JSON batch, and the peek, take and ack replies were the largest share of a top-level session's tool output. After a compaction, `claude --continue` or a restart, `agent-skills:reboot` checks this wait first; a sleep loop is not a substitute. Without it, reports wait for the next heartbeat; a second watcher beside it swallows the `CLOSE OUT` and `status` lines. `orch wait` wakes on worker_done, escalation, question or a worker stuck on a prompt, and acks batches that hold only heartbeats or Orca's refusals of what a released worker sent again.
- Process every message in the batch, decide each settled worker's next owner (reuse or release), then ack.
- On a worker's `worker_done`, in the same turn, reconcile its tickets (`use-tracker` "Reconcile": the `gh` read and the moves it supports, with the REPORT's evidence standing for `completed`; a criterion that needs checking again goes to a background subagent; the worklog and notes by `end-session` `references/record.md`, read now, and a body without its record line is asked for one) and act on the `CLOSE OUT` lines `orch wait` prints beside it: release the worker; remove a finished card nobody else uses (`orca worktree rm`; never this session's own worktree, which a `--worktree current` worker reports as its card, so no rm line comes for it; checks and when to pass `--run-hooks` in `end-session` §4) unless its next task starts there; keep a failed one only for its retry. `worker_done` arrives before the card tries to close itself, so a card still there after the release is a close in progress or refused: wait one inbox round for its status before the rm, and on `card left: worktree rm refused` put the card to the human and never remove it yourself (a refused act, `end-session` §7). `status` lists cards you missed as `LANDED-BUT-OPEN`, and its `next` line puts them before spawning; `wait` names the released ones too, since a worker you stopped sends no `worker_done`. Leftover cards made Orca itself slow.
- A worker closes its own session once it settles (`end-session` §7, named in every brief's REPORT); the lines below are the backstop for the ones that could not. Every return of `orch wait` also lists `SETTLED` workers nobody released (worker done or failed, no open PR, nothing unpushed): release each in that turn. A worker that `worker-release` already left `release_unknown` with its card gone is done, though later wakes keep listing it, a few at a time. To tell a new or unreleased worker from them, count `orca orchestration worker-list --run <run> --json` by `terminalState`; a filter that drops wait lines by kind hides the new ones too. A `KEEP` line names what still holds a worker; the card itself goes only after landing, as above. A `TAKEN OVER` line is a settled worker whose terminal was typed into, a `terminal send` nudge included: Orca never releases it, so run the self-check command the line carries; later wakes print only when it was asked. The session then closes itself with `end-session` or says what is left; where it has no `end-session`, close it yourself once it answers that nothing is (`orca terminal close --terminal <agentTerminalHandle>`). When the host's permission layer, not Orca, refuses `worker-release` (an auto-mode classifier has called it workload interference), stop releasing and follow "Refused acts" below (the rule: an autoMode allow for releasing this program's own workers). Do not reach the same end another way (`worker-stop`, closing its terminal, a subagent).
- A `STUCK` line is a live worker whose screen shows a select menu, a permission prompt or a wait for input. Nobody watches a worker's terminal, so its own question can hold the program; `orch wait` reads every live worker's screen each round and wakes early on a new one. Workers may ask this way; answering is your side. In that turn, yourself or through a subagent you dispatch with the line, read the question and its options on the screen and answer from what the program already decided: its briefs, standing orders and decision trail. Select the option by its number, or type the answer, with `orca terminal send` (the terminal then counts as taken over). For a permission prompt, first check its target with real output (the pid, the cwd, that the worktree exists), then pick the one-time yes; never "don't ask again", which edits permission settings. Put it to the human at once only when no decision covers it, a call that is theirs (`orch-dash inbox add --type decision`). Record each answer and each escalation with the `orch record … signal` the line carries, the answer or the escalation in its note.
- **Watch the cards' screens.** `orch wait` reads only its Run's workers. A `/goal` card (`dispatch-card`, a lead) is not one, and `orch inbox` reads no screen, so such a card can sit unseen on a confirmation or a question only a human can answer. The top-level, and any layer that started such cards, keeps one `orch watch-cards` under `run_in_background` beside its inbox wait. It reads no inbox, so it is not a second inbox watcher. It reads every agent terminal but your own (`$ORCA_TERMINAL_HANDLE`) and exits on a new finding: a lost login or a goal Claude Code stopped (`auth`), a select menu, a permission prompt, an interrupted turn, a full disk, an API retry loop, a `/goal` card silent for 30 minutes, a card once under `/goal` idle on an empty prompt without it for 15 minutes (`goal lost`), or low disk. Otherwise it exits `QUIET` after 55 minutes. In that wake act on each line, then start it again. It reports a finding once while it stays on screen and never answers one; the answer is yours, from the screen's content:
- A card you started: as a `STUCK` line above. A question about work already settled (merged already, or done by a newer card) gets that fact, or the card is closed as superseded.
- A card or worker in a project that has a lead: that lead (`references/top-level.md`, "Routing").
- Any other session you did not start: the inbox (`references/top-level.md`, "Sessions you did not start").
- Several cards retrying at once: a shared usage limit; wait for its reset.
- Low disk: `reap-resources`.
- A silent `/goal` card: read its screen, then nudge it or close it as finished.
- `auth` or `goal lost`: the card will not go on by itself; read its screen. A lost login: do not type `/login` into it (a re-login can reset the token store every session shares); start a new card on the same brief and close the old one as superseded. A usage-limit pause waits for its reset; a finished card that never closed is closed.
- A permission dialog raised by a lead's workflow agent or worker takes the lead's own terminal input, so the lead cannot answer it. The layer above reads the screens of the leads and workers it started on every wake and answers such a dialog the same way when the approved scope (APPROVED lines, standing orders) covers it; anything outside goes to the human. An agent that uses a write tool whose host asks it to load a policy skill before the first write gets, in its prompt, an instruction to load that skill before its first write, so the confirmation does not come back in every session.
- A `STALLED` line is a worker whose ticket is open while its session has stopped writing (a turn that ended on a review report, a notification that never started a turn). `orch wait` ends early on a new one, once per 30 minutes. Read its screen before waking it: a spinner, a running tool or upload, a background shell it waits on, or a browser hold it waits for is work, so leave it; nudge only when nothing moves. A worker you told to wait (the next QA round, another PR, the human) gets `orch record <slug> parked --ticket <id> --note <what wakes it>` in that turn, which keeps it off the `STALLED` lines, and `record admitted --ticket <id>` when that happens.
- A start that ended `outcome_unknown` with an empty composer: `worker-stop --dispatch <id>`, then `worker-start --retry-of <id> --task <task> --worktree <that card> --agent <agent> [--model <id>]` (a retry inherits neither placement nor model).
- Record a lesson signal when the process, not the product, went wrong: `orch record <slug> signal --kind <human_correction|brief_gap|stall|tooling> --evidence <message id, PR comment URL or transcript path:line> [--ticket T] --note "<one line>"`. A human correction of how the work runs, a worker question the brief should have answered, a stall the process caused, a skill or script that misbehaved. A refusal report is sorted first ("Refused acts"). Only record; the flow improver's rounds and Close analyze it. `land_failed`, `main_red` and failed verdicts are in the ledger already.
- `WATCH-CARDS DOWN` (from `orch inbox` or `orch wait`): the `orch watch-cards` this terminal ran has finished no round in two intervals; start it again now, `run_in_background`, no pipe. `PATROL <code> <id>` lines are `orch patrol` findings routed to you (the card's starter, else the orchestrator), repeated every 30 minutes until acked; each line names what it found (codes in `docs/automation.md`, "세션 순찰"), and an `E` line is a hint only. Patrol only records them; before acting, read the screen and Dispatch state again, then act as for `STALLED` or a superseded card, and run `orch patrol ack <id>`. A card a lead started goes to that lead, not to you.
- End every drain with `orch status`; its lines are how a drain ends. `status` also prints what only the dashboard's collector sees: `STALLED` workers (turn ended with the task open, no session activity since dispatch, one tool call running too long), `SPARE` slots with ready tasks, and `LEDGER GAP`s. Act on them like the other lines. `orch-dash note` records a risk or decision the dashboard should show.
- Under `/goal`, a running background task defers the Stop hook's goal check. If the hook re-prompts anyway with no new event, answer in one line with no tool call. If it fires back-to-back, the background wait is gone: check it and start it again ("One inbox wait, always"), never as a foreground wait.
- Once every open predicate item waits on the human or an outside event (a human-only check, a rare event in prod), register the decision as in "What reaches the human" with its default stated (park it as LATER and Close). A lead sends it once through its established channel to its PARENT, which routes it to the human. Restart an expired wait with no reply when there is no new event or changed decision. A changed blocker, new evidence or a direct user question still gets an update; deduplication applies only to unchanged waiting notices.
6. **Triage.** Workers report findings with a proposed class in `worker_done` and file nothing (`references/brief.md` FORBIDDEN). Classify each one yourself against the predicate:
- NOW: it blocks a named predicate item, or it is a reproduced correctness, security or data defect in code this program merged. File it in the follow-up format (`use-tracker`), then `orch record <slug> admitted --ticket X` naming the item or defect. An admitted ticket blocks Close like a predicate item: `orch status` lists it as open until it is done or canceled.
- LATER: one line on the program note's `보류` list with its revisit trigger. No new ticket. Work that will be done when a date or condition comes is not LATER: it is a to-do on the board (`orch board todo add`, `brief` skill). The trigger is an event a named role fires (the QA lead's next pass, the human's release decision, a ticket that flips a flag), never a condition nobody watches; when an existing ticket or PR performs the trigger, the revisit line goes on it too. A security, authorization or data-exposure suspicion that touches a program invariant gets a reproduction attempt first, and is LATER only when that attempt did not reproduce it (a reproduced one is NOW, above).
- DROP: one line in the digest with the reason. No ticket.
A follow-up someone else already filed (a reviewer, the human, a worker on an old brief) gets the same classes: NOW is `record admitted`, LATER is `record parked` plus its line on `보류`, DROP is canceled with the reason as a comment. At every digest, compare the admitted set with the last one; for each admission since, name the predicate item it serves, or move it to LATER.
7. **Land** (`references/landing.md`). Workers land their own PRs with `orch land`:
- Normal PRs land in parallel the moment they are ready.
- Migrations, CI files and other `exclusive_paths` land one at a time, on the latest base.
- Dependencies land first.
You keep it honest:
- start-after edges in Orca, land-after chains stacked with `orch dep`
- `STALE` PRs unstuck
- classes set (`record reprioritized`)
You land only under human-gate, after the Orca gate resolves, and for a PR whose review outlasted its worker. `orch wait` lists those every wake: `WAITING ON REVIEW` for each still short of ready, and `LAND #N` with its command once one is approved (and through the human gate under human-gate), `CLEAN`, green at its head, free of unresolved threads and not on hold. Hold one when the human or the ticket says to wait, or a `deliver-ticket` §6 "Ask first" case applies: `orch record <slug> parked --pr N --note <why>`, released by `record admitted --pr N`. Every land hold you tell workers about (a serialized window, a hold until a fix lands) is recorded this way for each PR it covers, so `land` refuses it; the message only says why. A hold sent only as a message misses a worker spawned after it and a background `land` loop that does not read its inbox. `MERGED OUTSIDE LAND #N` is a PR someone merged by hand: run the `orch landed` it carries instead, then finish its ticket the same way. Run that `orch land` in the background, then finish the ticket the way the worker's `deliver-ticket` §6 would: read main CI's log and any apply or deploy run the merge started, move the ticket (`use-tracker` "Reconcile"), and cancel a reminder sent for that review, or answer it with the merge where it cannot be cancelled. A land that refuses, or a §6 "Ask first" case, goes to the human as a decision.
8. **Verify main.**
- The lander watches its merge's main CI and records `main_green`.
- Red main belongs to the main guardian: flake check, freeze, hotfix or revert, notify (`references/roles.md`). While main is red, only `--class main-fix` lands.
- The QA lead verifies each landed ticket and audits design against code. It also runs the E2E suite on main every 5 landings, every 2 h, and before each gate PR.
- When the QA lead or a worker reports that `verify-<app>` could not drive a feature, or described it wrongly (`verify skill stale`), dispatch a worker to run `maintain-verification-skill` on that repo.
9. **Close.**
- When `status` says the tickets are done, run the predicate's final check on the real artifact: the QA lead drives `verify-<app>` on main, or, without a QA lead, a verifier worker runs the program's `final_check` on a fresh `origin/main` checkout (`git archive` into a scratch directory), never on a worker's tree. That verifier's brief is written like a ticket worker's (step 4).
- `orch record <slug> predicate_verified --note <evidence>`.
- Release the standing roles: `orca orchestration send --to dispatch:<the role's dispatchId from its spawned record> --subject release --body "program closing: send worker_done"`, then `worker-release` once its `worker_done` arrives (Orca releases only settled workers). Release any remaining workers and remove any worktree still left (checks and `--run-hooks` in `end-session` §4).
- The program ends only when `orca orchestration worker-list --run <run> --terminal-state reclaimable --json` returns no rows. That is Orca's own end condition: every settled worker has been released or retained. Release what it lists.
- The dashboard server is detached and serves every program, so it neither needs stopping nor defers the `/goal` stop check. `state.json` stays for later reading.
- Each check left for later (a `보류` line, a check deferred to a later scheduled run) gets an owner before Close: a scheduled check, a standing-loop item or a ticket, named in the digest. A digest line alone owns nothing.
- Run `measure-delivery`, save its output as `~/.claude/programs/<slug>/reflect/delivery.md` for `reflect` with the Write tool, and later sections with Edit, never a Bash heredoc (audit text quotes commands that secret-scanning hooks match), and audit the trail per `show-me-your-work`.
- Run `reflect` in program mode. It turns the signals and the ledger's failures into lessons in the lessons ledger, fills in whether earlier lessons held, and opens at most one draft PR against `agent-skills` for the lessons that recurred. Put its digest lines and the PR link in the digest; the human approves and merges. Run it even with no signals and no failures: it then only records that the applied lessons held, and the digest gets one line saying so.
- Neither step is skipped for a brief's MODEL CALLS line: `measure-delivery` only reads, and `reflect` is the model call Close exists for. The signals are yours to fold in here unless a flow improver you spawned is running; leaving them to one that does not exist drops them.
## How the human's words change the program
| The human says | Do, in the same turn |
|---|---|
| "I'll watch X myself, don't bother" (usage, a metric, a channel) | Delete X from the standing orders and from every judgment rule now, and never defer work on X's account again |
| "Can it go faster?" | Offer structural levers: parallelize the critical path, stack dependent chains, reorder the land order, narrow `exclusive_paths`, risk-tiered review depth, split CI jobs by role. Apply the approved ones at once. Not "work harder", and not serializing for safety (one CI at a time, one landing per N minutes) |
| Feedback about how the work flows, not about the product | Record a `signal --kind human_correction`, and send the feedback to the flow improver (`send --to dispatch:<its id>`) while you stay on the program. It folds feedback into the skills in batches, and asks you before changing this program's contract; after its "reload needed", run `skills-sync broadcast` |
| Feedback or a request about the product, one that arrives mid-turn included | Put it on the board before you send it on: in the `next` of the lead or card that will do it, recorded as `references/top-level.md` "Periodic report" says, or, when no session runs that work yet, `orch board doing add <title> --owner W --next E`. A message to a lead is not a record, and the board is where the human looks for it |
| "Make it better" about in-flight work | A new ticket with its own brief. Never append it to the running task |
| "Make a ticket for …" inside another question | Split it out and file it immediately, then answer the question |
| Doubts your report ("is that right?", "불안하다") | A read-only verifier agent re-checks it. Your self-report is not evidence |
| "Check" (점검) one section | Check the whole related scope. "Check and align" (점검하고 얼라인) is two tracked steps: findings, then the alignment changes, each reported done separately |
| "Why is #N not moving?" / priority doubts | `orch queue <slug>`: answer with its order and reasons, then fix the reason (stack, Orca dep, class, fix task) |
| "Update the dashboard and summarize" | It updates itself. Run `orch status` and summarize its numbers; if the dashboard looks stale, `orch-dash ensure` |
## Merge policy
- `autonomous` (default): workers land with `orch land`.
- `human-gate`: workers stop at READY. You `orch gate <slug> --pr N` (an Orca decision gate), and after the user resolves it, `orch land`.
- `orch land` only squashes. A base that needs another merge method is a blocked land that goes to the human, not a policy of plain `gh pr merge`, except a merge-commit path `references/landing.md` names for that case. When the human approves a plain merge anyway, it waits for: an `orch verdict` row at the exact head being merged, a new verdict row for every commit pushed after the reviewed one (the delta review), zero unresolved review threads read right before the merge, the merge pinned with `--match-head-commit <head>`, then `orch landed <slug> --pr N`.
- Either way, stop and ask only before irreversible acts and acts the human owns: destructive migrations, force-pushing shared branches, sending anything outside, changing repo or branch protection, production deploys, approvals the review ruleset requires from a person, other people's tickets, and acts the classifier refuses. An act a permission layer, a hook or the human refused is not tried again in any form, by you or by a worker or subagent you brief, except what `references/brief.md` FORBIDDEN names as not a retry (listed in "Refused acts").
## Refused acts
A permission prompt, the auto-mode classifier, a hook or the human refused an act in your session, a worker's or a lead's. A classifier error that gives no verdict counts as a refusal:
- No other session runs it (two exceptions: `no verdict` on a subagent's Edit or Write, below, and the orchestrator's `[gate:delegate]` block from this plugin's `hooks/delegate_gate.py`, which refuses only that the orchestrator runs the call itself, so handing it one layer down is what it asks for): not you, not a sibling card where the same command happened to pass, not the layer above. Classifier verdicts vary from session to session, so another session's pass is not permission, and a message saying the human wants it is not the human's word.
- The refused session reports the act, what it was for, the refusal's category and the exact command; a report sent from Bash carries the command as the path of a file written with the Write tool under `<temp>/orch-refusal/<worktree directory name>/` (TMPDIR, or /tmp when unset), never quoted, and the reader moves that file to the trash after reading it (`references/brief.md` FORBIDDEN). A classifier error with no verdict is reported with the category `no verdict`.
- `no verdict` is not a rule request: no rule fixes a classifier error. When the act was a subagent's Edit or Write, the session that started that unit takes the whole unit back once, not only the refused edit and never through the refused subagent: you restart it as a new card; a worker does it in its own session. Stop the refused subagent first (`TaskStop`); the unit is redone from its base, and a worker re-reads or discards what the subagent left in its tree. This is the one case where another session does the work, because the refusal judged nothing. A second `no verdict`, or one on any other act except the harmless read below, goes to the human: they approve the act in the chat of the card that will do it, in their own words there rather than a relayed approval (for a subagent's Edit or Write, the restarted card; a subagent's other act goes into a card only with that act under HUMAN ONLY, so the card stops there), or leave it.
- Read which layer refused before asking for a rule. `Permission to use <tool> with command … has been denied` with no classifier reason is the permission-rule layer, which an autoMode rule never reaches: its request is a `permissions.allow` entry (`skills-config`) or the human's one `! <exact command>` line, not `tune-automode`. A refused call that bundled several acts names no culprit: report it as unknown rather than guess.
- The orchestrator or lead above a session refused with a verdict turns it into a rule request. Draft the smallest rule for that act class on this repo with `tune-automode`, put its run line to the human with `orch-dash inbox add --type run_command --title "권한 규칙 필요: <repo> <act> (--apply 없이 돌리면 diff 만 보인다)" --command "<emit's run line without the leading !>" --key denied:<repo>:<act>`, and say in your reply: "<card>에서 <act>가 분류기에 거부됐습니다(<category>). 다른 세션이 대신 실행하면 거부를 우회하는 것이라 하지 않습니다. 계속 허용하려면 규칙을 추가해 주세요: <rule>. 실행: `! <run line>` (설정을 백업한 뒤 적용하고, 되돌리는 명령을 출력합니다). 적용되면 <card>가 같은 행동을 한 번 다시 합니다."
- Once the human has run it, or approved the act in the refused session's own chat (for a production sync only the rule counts: `references/top-level.md`), that session does the act once more, after you check the new rule sits in the layer that refused. A running session may need a restart before a new rule reaches it: close it through Orca (`orca terminal close`, not a typed `/exit`, which a nudge can turn into prompt text), confirm it is gone, then start the new one; two sessions never share a worktree. This is not a retry of the refusal: its cause is gone.
- A harmless read refused as something it does not do, or with no verdict, is the harmless-read case in FORBIDDEN. When a read refused as something it does not do comes back, request an `environment` or `allow` rule for it as above; a `no verdict` read that comes back goes to the human.
- Distinguish a post-execution hook error from a refusal using output and observed side effects. Never rerun an already executed act just to clear that error. Continue only independently authorized acts that do not rely on the failed check, with explicit paths; report the error and leave required verification pending. If execution or safety is uncertain, stop the affected act. A degraded scanner does not authorize bypassing it: the hold lists each remaining act that is safe without that scanner, its evidence and scope; put only that bounded list to the human as an option.
- Do not tell the refused session a form that would pass (the value on stdin instead of an argument, a wrapper script, a sibling session, Bash after Edit got no verdict): coaching the workaround is the workaround. A different command or method that proves the same item (another tool, a normalized diff, an earlier measurement) is such a form: do not name one. When a worker asks whether it may reword the text of a hook block that opened no protected file, or follow a `[gate:pressure]` or `[gate:sleep-loop]` block, the answer is the FORBIDDEN clause it already has, nothing more. Before answering a repeat escalation about the same check, read decisions.tsv and repeat the standing decision. A refused check is recorded as unverified (refused), and the work goes on without it.
- A change made around a refusal anyway (another tool, a script: a FORBIDDEN breach) does not land as it is. Refused with a verdict: the change is reverted and goes the rule-request way above. Refused with `no verdict`: a subagent's unit is redone from its base by the session that takes it back (above); a session's own edit is re-applied with Edit or Write, and re-read, only after the human approved it there. Either way the PR body says which edits were first made another way: tests can pass on such a change and miss what a re-read finds.
- Sort a refusal report before recording it as a signal. What the FORBIDDEN paragraph names as not a retry is not a breach and not a signal: the brief's own path, a redo after the human's rule or their approval in the refused session's own chat, the text-only reword, following a `[gate:pressure]` or `[gate:sleep-loop]` block's named wait (its command with `run_in_background: true`, or Monitor), step or form, the orchestrator handing a call `[gate:delegate]` denied one layer down (that gate refuses who runs it, not the act), the harmless read, the no-verdict restart. The same result reached another way (a filter, another tool, a helper script, "instead of retrying I used …") is a change made around the refusal, handled by the bullet above.
- A card that stops because the act was never in its first prompt's approval is a scope gap, not a rule gap. Do not send it "사용자 승인" by message (refused as relayed: a rename, a workflow dispatch, a merge), do not press its keys, do not do the act yourself, and do not ask the human to type it into the card. If the human already approved it, start a new `/goal` card whose APPROVED line carries it (`dispatch-card` §2); if not, ask once, and on yes start that card. This path is for an act no session has attempted yet. An act already refused in any session, a lead's or a worker's (a `[gate:delegate]` block refuses none), never gets a new card: it follows the rule request above, or the human approves it in their own words in the refused session's chat.
## What reaches the human
The dashboard, plus the digest line in the program note, batched.
Inside the scope the human approved (the standing orders, a brief's APPROVED line), you and the layers under you decide: take the recommended default, act, and report what was chosen. Restarting an app, a language or settings change, an upgrade, checking a recording are such decisions; asking about each buries the human in questions. So are a PR's screenshots: you or the lead judge them by `deliver-ticket` `references/visual-evidence.md`; only a mockup the human asked to see before it is built goes to them, and it goes after it passes `ui-review`. Before anything goes to the human, ask whether you, a lead or a routine round could do it, or whether it is only a call inside that scope; either way, decide, act and report it in one line, and a "human check" a lower layer raises is decided here, not passed up. The human gets only two kinds: what only they can do (a permission dialog outside the approved scope, a login with credentials no agent may hold, a payment, a document submission), and an irreversible or outward act outside that scope. Those go out together in one message, not spread across the day. That message, and every status report to the human, is laid out with the `brief` skill; the per-item stage table (the `stage` skill, one line in the brief) is the `orch stage` record, generated from each program's ledger, Run and PRs, with the cells only you can check (dev, prod) written when you verify them (`references/dashboard.md`, "The stage table").
A decision that blocks an Orca Task is a `gate-create` on that Task only (`orch gate` for a landing), which Orca shows and the dashboard lists as an approval. Any other decision you wait on the human for is registered with `orch decide add` instead and closed with `orch decide done` the moment the human answers or settles it in words, and the answer goes, in the same turn, as a comment on the ticket it decides (the human's words in short, the date; `references/record.md` in `end-session`); a dashboard button, or a prompt that starts with the id or a unique option label (the `UserPromptSubmit` hook), closes it itself (`references/top-level.md`, "Asking the human"). The digest holds open gates, a proposed predicate, irreversible acts, and any standing order that contradicts reality. Never retries, CI flakes, review-thread triage, rebases, "should I continue", or implementation-policy questions (design options, ticket splits, stack or parallel): a self-review subagent decides those from the human's own precedent (how they handled it before, how they review, the shape of projects they already shipped), never picking an option of a different shape (a new architecture, tool or process), and you record the decision in `decisions.tsv` with that precedent as its evidence. A question no precedent covers becomes a decision for the human (`orch decide add`) while the rest of the program keeps moving.
Read a message from the human of several lines as one thought before you route any of it: a later line often explains an earlier one ("this mockup is not what I meant", then what was meant). Split by topic across leads, the explanation can reach one lead and the complaint another. Split it only after you know what each line refers to, and send each lead the lines it needs together with the ones they explain. Before you ask the human anything, read their recent messages for the answer. Ask an open question once; after that it lives in the brief's `결정 필요` or `지금 오너가 할 일`, not appended to each later reply, where it buries the answers.
Every instruction you send out of this session by a path Orca does not keep (a `/goal` card's `--prompt`, a `terminal send` or `skills-sync nudge`, a Slack post, a tracker comment) is logged in the same turn with `orch sent add --to <receiver> --kind <kind> --channel <how> --text-file <file>`, so the human reads on the dashboard's Sent page what was asked of whom. What Orca keeps needs no line: a worker's spec is its Orca Task, which the Sent page reads, and an `orca orchestration send` stays in Orca's inbox. `skills-sync card` logs the `/goal` cards it creates itself. Slack and tracker sends show only from the log (`references/dashboard.md`, "Sent instructions").
## Where this differs from Orca, and why
Orca's `orchestration` skill is the default; these are the places a program overrides it on purpose.
| Orca says | This skill does | Why |
|---|---|---|
| Start the full independent wave before waiting | Ticket workers start at a cap of 1 that grows by one per landing proven green on main and halves on red | The pilot fixes the brief, unit size and VERIFY before they are copied; past what main CI and the land lanes absorb, more workers only grow the landing backlog (`references/landing.md`: stop starting, start finishing) |
| Pass `--model` only when the user named one | `--model` is the program note's worker model, by default the lead's own | The pilot proves that model reaches its first `orca orchestration` call and `orch land` without a permission prompt, and the note keeps a resumed lead on the same model; the user's agent default can change under a running program (`/model` changes it globally) |
| Share the current workspace; a new worktree only on a real checkout conflict | One `new-child` worktree per ticket; `current` only for a read-only helper | Each ticket is its own branch and PR landing in parallel, stacked or on `origin/main`; a shared checkout would mix their branches. `new-child` records your worktree as the card's Orca parent, so the sidebar shows the program's cards under you. `new-top-level` drops that lineage and is used only where the brief names it (its LINEAGE row, `references/brief.md`); when Orca refuses `new-child`, stop and report it rather than retry as `new-top-level` (core rule 5) |
| The lead's turn ends only on its report to the user | `orch wait` runs in the background and the turn ends while it waits | A program outlives any one turn: the wait wakes you on worker_done, escalation or question and acks heartbeat-only batches, and under `/goal` it defers the Stop hook's check. Orca's end condition still closes the program (Close) |
| `worker_done` body is three sentences | The brief's REPORT asks for the PR URL, merge commit, reviewers, the VERIFY output seen, the main-CI run and the findings with their proposed class | That body is the landing's evidence and the only channel for what a worker must not write outside its worktree; the lead records it |
| `terminal send` only for prompts that need no task state or inbox | One exception: after the content goes through `orchestration send --to dispatch:<id>`, or `orchestration reply --id <msg>` for a question (the reply is what closes it on the dashboard), a one-line `terminal send` nudge ("run your orchestration check") to a worker whose turn ended before its Dispatch settled (a settled one gets a new Dispatch, never a nudge) | `send` does not wake an idle agent; a worker sat 80 min on an answered blocker. The content stays in Orca's tracked mail; a worker without a terminal gets Orca's recovery instead. A nudged terminal counts as taken over: `worker-release` refuses it from then on, and it closes through the `TAKEN OVER` self-check |
## Traps seen in real runs
| Trap | Instead |
|---|---|
| A lead granting each merge | Workers land through `orch land`. The lead became the slowest lane |
| "Whoever is ready lands next" | Dependencies in Orca, and the land order for the exclusive lane. A dependency root starved for 5h behind newer PRs |
| One merge baton under strict up-to-date branches | A parallel normal lane with strict off. Every landing had pushed every other PR behind for another 30–40 min of CI |
| Landing a dependency chain one PR at a time (rebase + CI between each) | Stack it; the top's `land` merges the chain in one `merge-async` |
| Workers idling for hours "waiting for the merge slot" with nothing to do | `land --wait-minutes` in the background. `status` STALE lines and backlog hours make the wait visible and actionable |
| A worker calling `gh api … merge-async` itself and the classifier refusing it as "Merge Without Review" | Merges happen only inside `orch land`, which is the review gate and the allowed command |
| Reverting every red main by reflex, or the lead debugging it | The main guardian: flake check first, then hotfix or revert by the rule in `references/roles.md` |
| Cards named by Orca's automatic title, one unrelated to the ticket | `--display-name "<ID> <title>"` on every start; a terminal rename does not stick |
| A `worker-start` spec starting with `/goal` | Start the spec with the ticket ID; Orca already delivers it as the worker's task. A card from `orca worktree create` is the opposite: `/goal` plus its brief (`dispatch-card` §2) |
| Waiting with `sleep`, a hand-built watcher, or invented `orca … events/status` | The one inbox wait (Drain), and `orch watch-cards` for the screens of cards no Run lists. One empty wait is a checkpoint; after three, run `worker-list --run` |
| Nudge-only turns ("You have N orchestration messages") burning lead turns | End such a turn with no tool call; real work arrives through `orch wait` |
| A worker shows `live` but has done nothing for many minutes | It may be sitting on a permission prompt (`status` lists `idle-waiting`): `worker-read --dispatch <id> --source terminal`. Answer it inside the approved scope as for a `STUCK` line; outside it, put it in the digest for the human. Waiting output does not prove the agent stopped, so do not stop or retry it |
| A worker that sent a blocker as a status and ended its turn sat 80 min after your `send` answered it | A question (a worker's `ask`, a `/goal` card's `--type question`) is answered with `orca orchestration reply --id <msg>`; a worker waiting in `ask` gets it at once and needs no nudge. Anything else, and a reply to a card whose turn ended: `send` does not wake an idle agent. Send the answer with `orca orchestration send --to dispatch:<id>` (to a card, the reply is that send) so Orca tracks it, then, only for an attempt that has not settled (a settled one gets a new Dispatch), nudge the terminal with one line, `orca terminal send --terminal <agentTerminalHandle> --text "run your orchestration check" --enter`, and read the terminal until the turn starts (text left in its input box needs Enter alone, `--text '' --enter`, not the text again); that terminal later closes through its `TAKEN OVER` self-check, not `worker-release`. Never put the content itself in `terminal send`: Orca keeps no record of it. A worker with no terminal (terminal verbs refuse its handle) follows Orca's recovery instead: a transcript (`worker-read --source transcript`) whose last turn sent no `worker_done` is Orca's proof it stopped, so read `orca skills get orchestration --reference references/recovery-and-cleanup.md` and choose `worker-stop` or `worker-abandon` |
| A `worker-start`, `task-create`, `gate-create` or `send` whose result never came back (a timeout, a dropped connection) run again, starting a second worker | Its error names `orchestrationRequestId`: `orca orchestration request-show --request <id> --json`. `completed` replays its outcome with `--retry-request <id>` on the same command; `pending` waits while the original command still runs, else replays the same way; `absent` is no proof it did nothing, so read `worker-list`, `task-list` or `gate-list` before running it again |
| Status reports that contradict each other, or a scope you no longer see whole, patched one symptom at a time | Stop and rebuild the picture first: a recap (`recall`) or a re-check by a verifier, then decide. A worker whose report is inconsistent is sent back to recap, not given a patch for the one line |
| A handoff prompt that retypes the rules | The note is the handoff; the prompt is only the lines in "Resume (handoff)" |
| Follow-ups spawned the moment they are filed | Park them; `status` shows derived tickets per predicate item |
| Parallel CI jobs named `1/3 2/3 3/3` | Name jobs by what they check (typecheck, lint, unit, db, api…) |
| Several cards running docker compose stacks and image builds at once; the machine and the Orca UI crawled | Heavy local runs go through `orch heavy`, 2 machine-wide slots (`landing.heavy_slots`) |
| Finished setup terminals and landed cards left open (50 terminals; 8 cards after one compaction dropped the step) | `skills-sync close-setup` on every new card; act on the `CLOSE OUT` lines in the turn a worker reports done, and on the `SETTLED` and `TAKEN OVER` lines every wake prints |
| A worker that finished but had no capability token to send `worker_done` stays `active`, and no sweep line names it | Ask it the `TAKEN OVER` self-check; its answer is its REPORT, and you close it out |
| A shared state file overwritten in place and left empty | Append-only ledger; anything else is written to a temp file and renamed |
| Typing `/model` into a worker terminal | Pass `--model` to `worker-start`; `/model` changes the global setting |
| Asked to save tokens, switching the cards to a cheaper model | Cut the work instead: close cards that only wait (keep the worktree and PR, start again when the trigger lands), skip optional re-reviews and subagent calls, shorten reports, pause when nothing is left to build. A card's model or effort changes only when the human names it |
| A check needs a secret the worker's session did not inherit from the environment | The worker writes a script that reads the value from the environment and prints only the result, never the value; the lead reads it, runs it in its own terminal and sends the output back. Only for a value that is missing: a check a guard refused follows "Refused acts" |
| A worker that has run for hours keeps hitting model API 5xx errors or timeouts; its context is too large, and `/compact` is as heavy | Replace it, do not retry it in place: the layer above reads its worktree (branch, commits, what is unpushed), writes a fresh brief with what is done and what is left, starts a new worker on that card, and releases the old one |
## Resume (handoff)
The new lead's whole prompt is two lines, `/goal orchestrate resume <slug>` and `ROLE: lead <slug>`; the second binds the program to that session for the reorient hook. A session started with `claude --agent agent-skills:lead --name lead:<slug>` needs only the first. On resume:
1. Read the program note.
2. `orca orchestration run-use --id <run>`.
3. Make `program.json` match the note: `orch set <slug> merge_policy|ceiling|deadline|predicate|exclusive_paths …` for any difference. The note wins.
4. `orch status`.
5. Stop any inbox watcher the program ran before (a Monitor, a script), start the one `orch wait`, and continue at Drain.
After a restart of the session, Orca or the machine, or an automatic compaction, run `agent-skills:reboot` before anything else.
Whenever the note's policy, ceiling, deadline, predicate or exclusive paths change mid-run, mirror them with `orch set` in the same turn. Workers report to the Run inbox, not to a session name, so nothing needs re-pointing. The old lead ends only after the new one has printed `status`.