internal/contributor-info/multi-batch-operations.md
Use this playbook when one coordinator is running multiple agent batches across machines, launch surfaces, or repositories. It sits above the per-lane workflow rules in AGENTS.md, PR Batch Skills Usage, and Agent Coordination Backend.
The goal is to make the live operating model reconstructable by a cold-start reader without asking the coordinator which machine, tool, or repository owns a lane.
Use this when a coordinator asks Codex, Claude, or conductor.build to join a batch from another machine or fresh checkout.
The coordinator should provide the batch objective, exact targets, stable
batch_id, lane names, agent ids, any depends_on refs, and whether the worker
should use this PR branch or main for the current workflow docs.
Authenticate GitHub and confirm access:
gh auth status
gh repo view shakacode/react_on_rails
gh repo view shakacode/agent-coordination
Check out the public repo branch that contains the active workflow docs,
normally main after the workflow docs land or the active PR branch while it
is still open.
Clone or update the private backend and put agent-coord on PATH:
gh repo clone shakacode/agent-coordination
cd agent-coordination
ruby -Itest test/agent_coord_test.rb
bin/agent-coord --help
bin/agent-coord bootstrap
export PATH="$HOME/.local/bin:$PATH"
hash -r 2>/dev/null || true
command -v agent-coord || which agent-coord
agent-coord doctor --json
agent-coord config show --json
agent-coord status --batch-id <batch-id> --json
The remaining snippets assume that PATH entry is present in the active
shell. In another shell, add the export first or replace each agent-coord
command below with "$HOME/.local/bin/agent-coord". The private bootstrap
also installs agent_coord as an underscore alias for launchers or prompts
that use that spelling.
If doctor --json fails, or targeted status exits non-zero (exit 2 means
degraded/UNKNOWN) or times out, report private state as UNKNOWN and use the
structured public claim comment fallback where dependency rules allow it. Do
not start a dependency-sensitive lane when the lane declares depends_on and
private status cannot be checked.
Before dependent lanes start, the coordinator creates or updates
batches/<batch-id>.json in the private backend so targeted batch status can
render blocked_on refs.
Each worker claims before creating a worktree, branch, or conductor session:
agent-coord claim \
--agent-id <agent-id> \
--repo shakacode/react_on_rails \
--target <issue-or-pr> \
--batch-id <batch-id> \
--branch <branch>
A refused claim after successful status exits with CLAIM_REFUSED / code 3
and is a hard stop. Report the holder, heartbeat liveness, and target instead
of creating competing work. Operational failures are UNKNOWN, not claim
overrides.
Each worker heartbeats at item start, branch/PR update, review pass, blocked state, resumed state, and done state:
agent-coord heartbeat \
--agent-id <agent-id> \
--repo shakacode/react_on_rails \
--target <issue-or-pr> \
--batch-id <batch-id> \
--branch <branch> \
--status in_progress
Before rebase, push, readiness, or closeout, rerun
agent-coord status --batch-id <batch-id> --json. If a lane shows non-empty
blocked_on, set the worker heartbeat to --status blocked, report the
blocked refs, and move to independent work.
Final handoff from the second machine must include the agent id, batch id,
branch/PR URL, validation run, current
agent-coord status --batch-id <batch-id> --json summary, blockers, and
UNKNOWN for anything not verified live.
The current coordination model uses these role names for multi-machine, multi-launcher operating windows. Keep specific hardware inventory, active inbox ids, and capacity counts in runtime registration or the private operations runbook; this public table is role vocabulary, not a durable list of machine names or an enforced scheduler policy:
| Role | Primary use | Notes |
|---|---|---|
| Mobile high-memory host | High-memory batch host | Useful for heavy local context, but treat power, network, and travel as availability risks. |
| Stable wired host | Stable batch host | Prefer for long-running desktop sessions and lanes that benefit from steady network/power. |
| Claude Desktop | Batch kickoff surface | Best for long-running multi-lane work when a configured high-capability lane owns the hardest items. |
| Codex Desktop | Batch kickoff surface | Best for long-running Codex batches, local validation, commits, and repo-aware finishing. |
| conductor.build | Single-PR focus and finishing | Best when one PR needs concentrated Claude plus Codex chats on the same PR. |
| shakacode/react_on_rails | Main gem/npm/Pro monorepo | Claims use this full repo name in the coordination backend. |
| shakacode/react_on_rails_rsc | RSC integration/adoption repo | Uses the same coordination backend, with claims namespaced by repo. |
Prefer no more concurrent batches than the registered capacity profiles expose as available lane slots. A manual override beyond profile-advertised capacity requires an explicit human decision with package and risk separation recorded in the batch handoff. Keep concurrent batch packages, branches, and risk surfaces intentionally disjoint:
Machine choice is an operational decision, not a policy label. Prefer the wired host when continuity matters more than local memory, and prefer the mobile host when mobility or local capacity is the better fit. If either machine is likely to disappear during a lane, route dependency-sensitive work elsewhere. If a coordinator exceeds registered capacity, record the package/risk separation in the batch handoff and downgrade any uncertain overlap to blocked or deferred work.
Use Claude Desktop and Codex Desktop to kick off batches because they are the right surfaces for long-running lane splits, local worktrees, validation loops, and coordinator handoffs.
Use conductor.build for one PR at a time. Its special value is focused finishing: Claude and Codex chats can work against the same PR context. A conductor session must take a normal coordination lease before editing or finishing that PR. Once the lease exists, batch workers must skip that PR unless the lease is released, dead, or explicitly transferred by the coordinator.
Do not let conductor become an invisible side channel. If conductor takes a PR,
record the claim in shakacode/agent-coordination with the same repo and target
identity that batch workers use, then refresh heartbeats while conductor owns
the lane. If agent-coord is not installed in the conductor environment, install
it with the private backend bootstrap first or use the structured public claim
comment fallback until the host is configured; do not treat an unbootstrapped
conductor session as a private claim override.
The private shakacode/agent-coordination repository is the coordination source of truth for concurrent batches. Public issue or PR claim comments are human hints and recovery aids only.
Use stable agent ids with the base format <machine-or-profile>-<batch>-<lane>,
for example mobile-batch2-lane1, desktop-highcap-lane1, or
desktop-conductor-lane1; if one batch runs multiple
simultaneously-heartbeating lanes on the same machine or profile, add a short
lane suffix after the batch id so each heartbeat remains distinguishable.
Existing registrations using the older <machine>-<tool>-<batch> format remain
valid while their old claim or heartbeat is live. A restarted worker must keep
using the old id until that claim is released or expired; re-key only for new
lanes or after the old claim is gone.
Use this lifecycle for every lane:
agent-coord doctor --json to
confirm backend health, then assign targets or a batch id before any status
read. Broad agent-coord status is audit-only.agent-coord claim for the repo and
issue/PR target before creating a branch, worktree, or conductor session.agent-coord heartbeat at every phase
transition: item start, branch update, PR update, review pass, blocked state,
resumed state, and done state.agent-coord status --batch-id <batch-id> --json before starting
dependency-sensitive work, rebasing, pushing, finishing, or reassigning a
target.If the private backend is unavailable, use the structured public claim comment fallback from pr-processing.md, but do not use a public comment to override a refused private claim.
The per-batch cap remains in PR Batch Skills Usage: 8 items when files or risk overlap, or 10 fully independent items. Treat that as a per-batch maximum, not a global multiplier based on a presumed lane count.
For whole-surface triage, derive the number of implementation groups from registered capacity profiles and enabled inboxes. The flow is:
agent-coord claims and heartbeats.The queue is not a lock. Workers still claim the repo target before editing, and the queue view must reconcile live claims, stale heartbeats, released claims, and done heartbeats before recommending the next item for an inbox.
Before launching multiple batches, route by package and risk:
react_on_rails/,
packages/react-on-rails/, react_on_rails_pro/, and an adopter repo such
as react_on_rails_rsc.react_on_rails_pro/ work to one batch unless the coordinator has
explicit disjoint file ownership and validation coverage for each lane.react_on_rails and
react_on_rails_rsc, either keep it in one coordinated batch or designate one
repo as the lead and make the other repo wait on a claim/status dependency.Cross-batch safety should reduce concurrency before it reduces review quality. If two batches want the same package, move one target, shrink one batch, or make one batch wait for the other lane's done heartbeat.
agent-coord status --repo shakacode/react_on_rails --target <issue-or-pr> --json
or agent-coord status --batch-id <batch-id> --json for the affected lane.agent-coord config show --json, the private backend README, and
CLI help for the current TTL and dead-threshold calculation.git status, current branch, and remote branch state before editing.Adopting repos join the same private shakacode/agent-coordination backend.
Claims and heartbeats are namespaced by full repo name, so
shakacode/react_on_rails#3973 and shakacode/react_on_rails_rsc#3973 are
different targets even if the issue numbers match.
Use one desktop project or worktree per repository for code edits. A coordinator
session may read shared agent-coord status across repositories, but editing,
validation, commits, and PR updates should happen from the checkout for the
target repo. Cross-repo work is coordinated through backend dependencies rather
than by treating one repo-scoped session as if it owned another repo's files.
Use one status table for the whole operating window. That lets a coordinator see
that a react_on_rails_rsc lane is waiting on a react_on_rails package
release, or that a conductor session has removed a PR from the shared pool.
When a cross-repo change needs sequencing, make the dependency explicit in the coordination state:
Before kickoff:
agent-coord status --repo <repo> --target <issue-or-pr> --json
for each exact target before routing, then
agent-coord status --batch-id <batch-id> --json for dependency lanes;<machine-or-profile>-<batch>-<lane>;During execution:
At closeout:
react_on_rails and react_on_rails_rsc status when work crossed
repositories;UNKNOWN for anything not verified live.