Four agents were dispatched without worktree isolation and all edited the same working tree: one git status held one agent's effect.rs, another's harness/build.sh and a third's scripts/node-test.sh. Any commit would have swept up three units' half-finished work. The brief had carried that rule before and lost it, which is what a retyped brief does. It is now a skill: worktree isolation first, partition by crate rather than ticket count, the base commit by name, the baseline, the never-write list, the injection discipline, pr-watch --expect, and attribution. Two doctrines: every_wave_agent_gets_its_own_worktree records the tell and the per-agent recovery (copy only what an agent can PROVE it touched -- two units can legitimately both be in improvise-protocol); the_orchestrator_delegates_substantial_work records the user's rule and the non-obvious half of it, that orchestrator work lands in the shared primary tree and collides with agents who own that ground. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
4.2 KiB
name, description
| name | description |
|---|---|
| wave | Dispatch parallel agents to work through open beads and shepherd each to a merged PR. Use when an orchestrator is running a wave, partitioning the backlog, or writing a brief for a work-unit agent. |
Running a wave
An orchestrator chunks the open backlog, fans agents out, reviews what comes
back, and merges. AGENTS.md has the history; this is the operating procedure.
Every agent gets its own worktree. No exceptions.
Dispatch with isolation: "worktree". Without it every agent edits the same
working tree: one git status shows four agents' half-finished files, any commit
sweeps up the others' work, and any git checkout destroys it. This has happened
here. If you discover it mid-wave, stop every agent, have each create a worktree
and copy across only files it can prove it touched, then git checkout --
those files in the primary tree.
In the worktree: direnv allow, or bd reports a version mismatch rather than
failing cleanly. direnv status prints Found RC allowed 0, and 0 means
allowed — it reads like the opposite.
Partitioning
By crate or directory, never by ticket count. Tickets that share a file go
to one agent, to be done sequentially — four widget migrations all touching
src/draw.rs are a guaranteed conflict split four ways. Group first, then count.
Tell each agent what ground is not theirs, and to report rather than guess when
it must cross. Two agents adding a workspace member will still collide in
Cargo.toml/Cargo.lock; keep both sides.
What every brief must carry
- The expected base commit, by name. Worktrees do not reliably branch from HEAD — one was created three merges behind and only noticed because it was told to check.
- The baseline, so "N passing" is checkable rather than asserted: Rust test count, harness counts, node counts.
- Its ground, and the ground that is not.
- Never write
.beads/**,prolog-sessions/kb.pl,context/repo-map.md. Agents read them freely and report proposed text; the orchestrator applies it. - The commit trailers and PR footer, spelled out.
- Do not push to
main, do not merge. The orchestrator merges. - What to report: branch and head SHA, PR number, what changed per ticket, what could not be verified and why, proposed repo-map/kb text, and what it learned that the ticket did not predict — consistently the most valuable part, and omitted unless asked for explicitly.
Method to require, because this repo's defect is a test that passes
- Failing test first, then the fix.
- Every guard proved by injecting the fault it names and watching it fail by name. An injection that does not compile reads as a clean run, so require a positive signal the build ran.
cargo test --workspaceis fail-fast;--no-fail-fastfor any claim about blast radius.- A textually clean merge can delete tests with no conflict marker, and
cargo checkwill not notice. After any merge that moves a test module, diff test names — a count is masked by the other side's additions.
Shepherding
- Wait on checks with
scripts/pr-watch <pr> --expect <sha>. Never hand-roll a poll; see thepr-watchskill for the three ways they report green while wrong. - Review before merging. Copilot's quota may be exhausted and its request is a silent no-op; an absent review and an unrequested one both read as "pending". Dispatch an adversarial reviewer and give it the head SHA, the base, and a test-merge, so it reviews the tree that will exist.
- A re-review is of the delta, at a named SHA. A review of a superseded commit reads as a pass.
- Merge on GitHub, then
git fetch gh && git merge --ff-only gh/main. - Anything posted to GitHub goes out under the owner's account: open every comment with a line saying a Claude agent wrote it.
Between waves
Run the code-review skill on the merged range. The characteristic find here is not a wrong line, it is a test that passes while the thing it names is broken — a vacuous fold test, a one-category fixture, a helper that fabricates what the code under test needs. Ask the reviewer to inject the fault and watch the check fail.