Light orchestration — gate every hand-off and merge worktree branches sequentially
You now have several workers grinding through the money refactor, each walled off in its own worktree, each producing a branch — money/parse, money/store, money/report. The fan-out got the work done in parallel. What it didn’t do is bring it back together. That’s this lesson, and it’s deliberately the thinnest layer in the chapter: orchestration here is not a workflow engine, it’s three habits — gate every hand-off, decide the merge before you scatter, and bring the branches home one at a time through a gate. Get those right and the parallelism you built pays off without a half-finished branch quietly poisoning main.
Orchestration is the aggregation step, made real
Section titled “Orchestration is the aggregation step, made real”Back in the fan-out lesson the rule was: write the aggregation first — be able to say in one sentence how the slices come back together before you spawn anything. Orchestration is that sentence turned into an actual procedure. For the recategorisation it was cheap — “concatenate the change-logs, sum the per-category counts” — because the workers only produced data. The money refactor is harder, because the workers produced code, and code doesn’t reduce by concatenation. It reduces by merge, and merges can conflict, and a passing test on one branch tells you nothing about the other three. So the aggregation step grows teeth: a review gate on each branch and a sequential merge, not a free-for-all.
You can run this orchestration from your main Codex thread — it stays the coordinator, dispatching workers and reading back their summaries — or you can describe the whole reduce step to the agent and have it drive. The capability is “Codex coordinates a set of subagents and synthesises their returns”; Unverified: the exact spawn or orchestration flags Codex exposes for this, which shift between releases — describe the procedure in prose to the agent, or pin it to the official Codex reference, rather than scripting a flag you haven’t confirmed. The plain git commands below are the durable, verifiable part; lean on those.
Gate each hand-off with a read-only reviewer
Section titled “Gate each hand-off with a read-only reviewer”The cheapest way for parallel work to go wrong is for a worker to think it’s done when it isn’t — tests green on a path it didn’t exercise, an amount left as a float in a corner it didn’t touch. The fix is a separate set of eyes before any branch is allowed to merge: a read-only reviewer.
This is where the approvals & sandbox two-axis model earns its keep one more time. A reviewer is a subagent run under --sandbox read-only — it can read every file on the branch and run the tests, but it cannot edit, cannot push, cannot touch the network. Its only output is a verdict:
> Review the money/parse branch as read-only. Confirm every amount is parsed to integer cents per AGENTS.md, that no float path survived, and that the money tests pass. Return PASS or FAIL with the specific files and line ranges behind a FAIL. Do not edit anything.Two things make this a gate and not a rubber stamp. First, the reviewer is a different context from the worker that wrote the code — it didn’t talk itself into the change, so it’s not invested in it passing. Second, it’s read-only by construction, so a reviewer can never “helpfully” fix what it found and merge its own opinion in; a FAIL goes back to the writing worker, the gate stays a gate. You run one reviewer per branch, and a branch that comes back FAIL does not advance to the merge — it goes back for another pass first.
Merge sequentially, with a gate between each
Section titled “Merge sequentially, with a gate between each”It’s tempting, once three branches all come back PASS, to merge all three at once. Don’t. Parallel editing was safe because worktrees isolated the files; parallel merging is not, because every merge after the first lands on a main the previous merge already changed. Bring them home one at a time, and re-test between each — a sequential gated merge:
# start cleangit switch maingit pull --ff-only
# branch 1: merge, then prove main still passes before going ongit merge --no-ff money/parsepytest # the gate — green or you stop here and fix
# only if that gate passed, branch 2git merge --no-ff money/storepytest
# and finally branch 3git merge --no-ff money/reportpytestThe pytest line between each merge is the whole point. Branch two might pass in isolation and still break once branch one’s changes are underneath it — two independently-correct money refactors can disagree about a shared helper. Testing after every merge means that when something breaks, you know exactly which merge broke it, because only one thing changed. Merge all three at once and a red suite tells you only that one of three is wrong, which is the diagnostic position you went to all this trouble to avoid.
If a merge conflicts, that’s not a failure of the orchestration — it’s the orchestration doing its job, surfacing the one place two slices genuinely overlapped. Resolve it in your main thread (or hand the conflict to a worker with the conflicting hunks as its brief), re-run the gate, then continue down the list.
Clean up, then step back
Section titled “Clean up, then step back”Once a branch is merged and the suite is green, its worktree has done its job. Tear it down the way the worktrees lesson set up — git worktree remove per merged slice, git worktree prune to clear any registrations whose directories are gone — so the next fan-out starts from a clean board rather than inheriting a yard full of stale trees.
Step back and look at the shape you just ran, because it’s the same shape every time, regardless of the task:
- Decide the reduce step first — how do the branches come back together, in one sentence.
- Fan out independent, heavy slices into isolated worktrees.
- Gate each hand-off with a read-only reviewer that returns a verdict, not an edit.
- Merge sequentially, re-testing between each, so a break names its own cause.
- Tear down the worktrees so the next run starts clean.
That’s light orchestration: no engine, no framework, just a coordinator thread, a review gate, and git used carefully. It scales from three branches to thirty without changing — only the queue gets longer.
Hand-off to Chapter 7
Section titled “Hand-off to Chapter 7”Notice what you just did by hand: scoped a reviewer’s brief, ran a fixed sequence of git merges with a test gate between each, cleaned up the trees. You’ll do the same dance the next time budgetcli needs a parallel refactor, and the time after that. A procedure you repeat with the same steps every time is exactly the thing you should stop re-explaining and start packaging — write it down once so the agent runs it for you instead of waiting on you to narrate it.
And the running scenario has a procedure begging for that treatment: every bank’s CSV export is shaped differently, and importing a new one is the same sequence of moves each time. That’s the next chapter — Skills: turning a procedure you keep narrating into one the agent invokes itself.