orchestrating-parallel-work · git:20260913.256c175 · 2026-09-13 · sha256 9652ab890c8b5503

orchestrating-parallel-work git:20260913.256c175A

Immutable. This exact content is served forever at /api/v1/blob/9652ab890c8b5503.

---
name: orchestrating-parallel-work
description: How to run several subagents against one repository without losing their work or misreporting it — taking a worktree's diff against the base that worktree actually had, closing a task with the verb instead of hand-editing two files, never reaching for a tree-wide destructive git command, and checking a claim about work in flight before saying it out loud. Use this skill whenever you are about to spawn subagents in worktrees, take work back out of one, say what an agent is doing or has done, mark a task or phase finished, clean up after a failed apply, or write a brief that tells an agent what the code holds. It applies to the ordinary hand-off, not only the messy one: every failure it guards against was made by an orchestrator who knew the rule and did not check at the moment.
---

# Orchestrating parallel work

Running several agents against one repository is mostly bookkeeping, and the bookkeeping
fails in a small number of ways that all look like carelessness and are not. Each rule
below was written after the failure happened here, in a run where the orchestrator knew
the rule already. Knowing is not the problem. The moment of action is.

So every rule names the command that checks it. A rule you cannot check at the moment you
act is a rule you will follow when you are calm and skip when you are three agents deep.

## Before you say what an agent is doing

**A claim about work in flight is checked before it is spoken.** `ListAgents` says what is
running; `git status` in the worktree says what has been written. Both are cheap.

This exists because an orchestrator here reported a task as running when no agent had been
spawned for it — the task and its worktree had been created, the launch was intended, and
the intention got written down as a fact. The worktree was clean and the agent list was
empty; either check would have caught it in seconds.

The transcript size is not the signal. It does not grow while an agent works. The worktree
does.

## Taking work out of a worktree

**Diff against the base the worktree actually had, which is its own HEAD** — never against
a branch name, because the branch has moved since the agent started:

```bash
git -C <worktree> diff "$(git -C <worktree> rev-parse HEAD)"
```

An orchestrator here took `git diff main` from a worktree whose `main` had advanced by
three commits, and applying that patch silently reverted a sibling task's test cases.
Nothing failed. It was caught because a case count dropped by five, and only because
someone looked.

**After applying, run the suites the patch touched and compare the case counts with what
the agent reported.** A count that dropped means the patch reverted something. That
comparison is the whole check; a clean `git apply` proves only that the hunks matched.

When a repo ships a tool for this, use the tool — composing the git yourself is where the
mistake lives.

## When an apply goes wrong

**Undo by naming paths, never by resetting the tree.**

```bash
git checkout -- <the paths you applied>     # yes
git reset --hard                            # no
```

`reset --hard` here destroyed three things at once that had nothing to do with the bad
apply: a skill revision that was waiting to be committed, the manifest index, and a
phase's completion marks that existed in no other file. All of it was recoverable only
because the commits happened to carry the same facts in their subjects.

The general shape: a destructive command scoped to the tree takes everything uncommitted
with it, and what is uncommitted is by definition the work you have not yet proven. If a
guard refuses one of these, read what it says was at risk rather than reaching for a
bigger hammer.

**Commit as soon as a piece is verified.** Work that is finished and uncommitted is work
one careless command away from gone. This is not tidiness; it is the only thing that made
the loss above recoverable.

## State that lives in two places lives in neither

**Use the verb. Never hand-edit the same fact into two files.**

The completion marks lost above had been hand-written into a phase shard and an index.
When the index was reverted, the shard turned out never to have carried them — so the
record of finished work survived only in commit subjects. A verb writes one record, under
the lock, with a journal row, and cannot write half of it.

If there is no verb for what you are doing, that absence is the finding. Say so and record
it; do not quietly hand-edit around it. A missing verb is exactly why the hand edit felt
necessary, and the next orchestrator will feel the same way.

## Writing a brief

**A brief is a claim surface, so it answers the same questions a comment does.** Read
`before-you-claim` — in particular, whatever you tell an agent about what the code holds
is a claim about behaviour, and it is checked the same way: name the file and line, or do
not assert it.

An orchestrator here told an agent that an evidence row carried a field, because a task
that would have added it had been planned. It had never been created. The agent read the
code, found the field absent, and wrote what the record could actually support — but an
agent that trusted the brief would have documented a mechanism that does not exist, and
the brief would have been the source.

**Give the agent the failure, not just the goal.** A brief that carries what was driven —
the payload, the verdict, the line number — produces work you can check. A brief that
carries only an instruction produces work you have to re-derive.

**Name the allow case.** For anything that refuses, says no, or filters, the brief should
name what must stay quiet as explicitly as what must be caught. Agents reliably build the
deny half and leave the allow half to luck, and the allow half is what decides whether the
thing survives its first week.

## Judging what comes back

**The agent locates and implements; the verdict is yours, and it comes from running.** A
report that a suite is green is a claim about a suite. Run the thing the change is about,
in the shape the field reported it, and compare.

Expect your own probe to be wrong before the code is. In one run here three probes were
wrong in a row — a fixture that could not reach the branch under test, a shape that
collapsed two cases into one, an argument that silenced the output being measured. Each
time the first instinct was that the implementation had failed. If a probe reports
something surprising, suspect the probe first; it is newer than the code.

**A mutation that survives is information, not a nuisance.** It usually means the case is
asserting something other than what it claims, or that another condition already covers
the one you are testing. Both are worth knowing before the work is trusted.

## Keeping the queue full

**Report alongside the work, never instead of it.** A finished phase is a moment to start
the next one, not to stop and write. An orchestrator here treated "report at the boundary"
as "pause at the boundary" and left both slots idle while composing a summary.

**Fill the freed slot before doing anything else with a result.** Applying, verifying and
committing a returned patch takes several minutes; a slot left empty for those minutes is
time nothing is being built.

## The shape of a good hand-off

One task, one worktree, one brief that carries the driven evidence, the allow case named,
and the verification commands stated with the exit codes you expect. Then: take the diff
against the worktree's own HEAD, apply, run the suites, compare the counts, drive the
behaviour yourself, commit while it is fresh.