Skip to content
Русский

Running approved plans under the conductor

tools/conductor/ runs approved plans to a merged main with nobody at the keyboard. It works in up to two worktree lanes, and each plan gets separate headless claude -p sessions: its implementer runs, then a review that also closes the plan, then a fast-forward of main and removal of the lane (ADR-0205). It never pushes. Anything it cannot decide — a human phase, a red gate, a review still failing after two fix rounds, a spend cap — parks the plan and moves on to the next one.

Terminal window
node tools/conductor/conductor.mjs check # local.json, the CLI version, the queue
node tools/conductor/conductor.mjs run # both lanes, until the queue is merged or parked
node tools/conductor/conductor.mjs status # what each lane is doing, and every park

Before the first run:

  • Spend caps. Write tools/conductor/local.json with your per-step caps. It is gitignored, and the conductor refuses to start without it.
  • The main checkout. Keep it clean while a run is live: a fast-forward refuses a dirty one.

What changes for a plan it runs:

  • The approval is the go. The plan’s Status: approved is the only approval it needs.
  • The review is a separate process. A fresh session, handed the plan and the lane and nothing an implementer wrote, performs the close review.
  • The review is committed. It lands in the plan’s ## Close review section.

Every other seam stays exactly as the skills describe it.

Watch it from the terminal that started it. run prints one line per milestone as it happens: a step starting and ending with its duration, spend and turn count, each commit that lands in the worktree, each phase whose log row flips to done, each test and gate command with its counts and lock wait, the 5-hour and 7-day usage readings, and every command a permission rule denied. The same lines go to tools/conductor/state/live.log, under one header per run, for a run you did not watch.

Next morning, read tools/conductor/digest.md. It is the current state in two sections and nothing else (ADR-0214). Needs you comes first and is the whole worklist: each park with its age, the worktree it holds — or the branch resume reopens it from, when you have already removed that worktree — the usage reading its session ended on and its resume command; each lane stopped at the worktree cap; each lane still on disk after a merge; and every merge’s still-open findings with their file:line. A park the repository itself shows as finished closes that section under Already settled, clear the record, counted apart from the live ones, so a plan you closed by hand is never repeated at you as work. Now follows: per lane, the plan, the step and how long it has been in it, and what it has spent. A first section that says it found nothing means nothing is waiting on you.

What last night produced is one command away: node tools/conductor/conductor.mjs digest --history writes digest-history.md beside it, newest run first, each run with its own closed plans, its failures and its Totals — the usage windows at run start and run end, and gate minutes split into the full workspace suite and everything else, with the count of suite runs skipped because the conductor had already seen that exact tree pass (ADR-0207). Nothing writes that file until you ask for it, and a closed plan’s own committed ## Close review carries its review either way.

The operator guide — every command, what to do about each kind of park, and how to verify a new CLI version — is tools/conductor/README.md. Its tests need no network and spend nothing:

Terminal window
node --test "tools/conductor/test/*.test.mjs"

Built from f4f807a at version 0.178.0. This site tracks main and is not versioned per release.