Generated from
cat-harness/skills/sdlc/sdlc-core/coordinate.md— do not edit here.
/coordinate — multi-agent / multi-PR coordination
When several Claude branches are converging on the same long-term goal (e.g. “reach the precision target”, “close all violators of a rule”, “infrastructure overhaul”), each agent has only its own context. Without coordination they will:
- duplicate work (two agents both implementing the same helper),
- silently diverge (one renames a symbol, another keeps the old name, the merge conflicts),
- miss cherry-picks (one agent already wrote the template the others need),
- accept inconsistent findings without flagging them to the author,
- accept review-tool feedback without checking it against the actual artifact / sibling change proposal’s — pull request’s (PR’s) — framing (e.g. accepting an off-by-one “fix” that contradicts a definition another PR is also using),
- miss new sibling PRs that opened mid-session (new branches landing
on
mainwith overlapping scope).
/coordinate is the protocol that prevents this. None of the agents
has all the answers; they look to the author for clarification on
inconsistencies, and they cherry-pick from each other.
Workflow rule reminder (from AGENTS.md §Branch + PR workflow)
This skill assumes you’ve already created a branch + opened a PR for the work tranche being coordinated. Per AGENTS.md (STRICT, supersedes default “no auto-PR” guidance for this repo): always create a branch and open a PR at the start of every work tranche — ASAP, and never ask the user “want me to open the PR?” Branch + PR creation is pre-authorized; the only git action needing explicit permission is the merge. Commit early, commit often. Small structured commits cherry-pick cleanly; big mixed commits do not. Exception: integration-watcher batch audit-job sweeps may use a single bulk commit.
When to invoke
- Start of a session where the user mentioned other branches/PRs
by name (e.g. “coordinate with
claude/fooandclaude/bar”). - Whenever you start a new substantive task in a multi-PR effort — before making code changes, post intent on the relevant PRs.
- When you finish a substantive task — post progress + concrete cherry-pickable artefacts (file paths, function names, templates, fixtures).
- Periodic triage between substantive commits (§7) — even with no external trigger, sibling PRs may have landed commits or comments that change your scope. Run a quick triage every ~3–5 commits or when you finish a task and pick up the next one.
- When
mainlands new commits during your session — if any touch the same files, blocks, or scripts you are editing, treat as a sibling PR for §3 classification purposes. - When a code-review comment lands on your own PR (gemini-code- assist, copilot-pull-request-reviewer, codex, or human reviewers) — see §5 Responding to review comments.
- When you encounter a finding that contradicts another PR’s framing — write the disagreement up explicitly, post it to both PRs, and tag the author for resolution.
- A COLLISION — coordinate. A merge conflict caused by a sibling’s landed work is not merely a thing to resolve; it is the signal that two sessions are editing one subject. Resolve it AND coordinate. Owner, 2026-09-21: “collision=coordinate”.
- A POTENTIAL collision, seen in the beans — coordinate. Before
you start a topic, and at each triage, scan for an
in-progressbean whose scope overlaps yours. That is the cheapest collision to find, because it is the one found BEFORE either of you has written anything. Owner, same day: “potential collision by looking at beans = coordinate”. How to read a sibling’s state out of the store, and the boundary of that inference, isbean-coordination§”Where a sibling session is visible from” — not restated here. - When you START any new unit of work — before the first edit. A new story, epic, feature or task bean, an issue, CRDM Phase 6, a workplan tranche, or a handover pickup runs the collision review in §”Starting new work” below, scaled to its blast radius, and records it in the workplan bean. Owner, 2026-10-02 (#1885).
Inputs
- The current PR number (your branch).
- A list of sibling branch names or PR numbers (the user gives this,
or list the open PRs labelled
in-flightwith the list change proposals forge-operation Tool). - The shared goal in 1–2 sentences.
Where each section lives
This skill was 732 lines and the Protocol was 478 of them — an agent reads the
whole thing before acting, and at that length it skims. The Protocol now sits
beside this file. Nothing was deleted and no step was renumbered, because
other skills cite coordinate §0a and coordinate.md §8a and those citations
have to keep resolving.
| section | where |
|---|---|
| workflow rule, when to invoke, inputs | here — read before you start |
| Protocol §1–§11 — the eleven coordination steps | coordinate/protocol.md |
| output, anti-patterns, §11 STATUS.md, §12 same-goal coordination, related skills | here |
Coordinating: read this file for whether and when, then protocol.md for how.
Output
After invocation, you should have:
- Read every sibling PR’s body and changed-files list.
- Posted at most one coordination comment per sibling PR (intent + asks), unless you’ve made progress that warrants a separate progress comment.
- Triaged every open review-tool thread on your own PR (§5) and posted a single consolidated status comment.
- Run a §7 periodic triage every 3–5 of your own commits, capturing new sibling-PR comments + commits + CI status in one table.
- Run §8a (
git fetch origin main) at each triage cycle and react to any main-landed changes that touch your scope. - Run §8b (newly-opened PRs / branches) at each triage cycle and prompt the author when a new sibling overlaps your scope keywords.
- Identified the next concrete, non-overlapping task on your own workplan and started on it.
- (Optional) Created or updated
docs/coordination/<goal-slug>.mdwith the current state. - Escalated any inconsistencies via §6 with
@<author>tagging.
Anti-patterns
- ❌ Post a coordination comment that just summarises your own PR. Sibling agents already read your PR body.
- ❌ Pick the same task as a sibling without posting first. Even if their PR has been quiet, the human author may have given them a verbal lead.
- ❌ “Resolve” an inconsistency by rewriting your finding. Escalate to the author.
- ❌ Accept a review-tool fix without verifying it against the artifact and sibling-PR conventions. Bot suggestions can flip conventions silently.
- ❌ Reply per-thread on a 6-comment review pass. Use one
consolidated status comment + per-thread
accept/reject-with-reasonflags. - ❌ Skip §7 triage between commits because “I would have heard if something landed” — you wouldn’t. Sibling agents work in parallel and rarely interrupt each other. Run the triage anyway.
- ❌ Silently merge / cherry-pick from
mainwithout §8a classification. Main commits can also be inconsistent findings. - ❌ Add a newly-opened PR to your scope without prompting the author (§8b). The author may want it independent.
- ❌ Long prose. Coordination comments are tables, file pointers, and one-line asks.
§11 STATUS.md + master ledger pattern
A repeated flip-flop episode (a claim asserted and retracted across several sessions) motivates a more structured coordination layer that overlays this skill:
- Root
STATUS.md— single dashboard listing every goal + pointer to its master ledger + active PRs. - Master ledger per goal —
docs/coordination/<goal>.mdholds the durable narrative: current canonical status, open tasks, flip-flop history, sessions log. - Per-goal queue — the
beansqueue (beans/); each open task is one entry.
When /coordinate runs, it now ALSO:
- Reads STATUS.md to find which goal(s) the current PR touches.
- Reads the goal’s master ledger to identify the current canonical status — overrides recent commit claims if the ledger records a retraction.
- Reads the queue to find sibling tasks in flight.
- References the ledger session log when posting intent comments on sibling PRs, so the comment is grounded in the durable record, not just session memory.
See session-intent for the session-start / session-end
ledger + queue update protocol — /coordinate is the sibling-PR
arm; /session-intent is the durable-state arm. They are run
together at session start.
§12 Multi-agent same-goal coordination
Multiple agents MAY work the same goal in parallel. Per author directive: agents coordinate with the user on goals, not with each other on task-level locks.
Model:
- Goal = product (author’s directive). User-level concern.
- Queue = per-goal item list (the
beansqueue). - Tasks are NOT exclusively claimed. Two agents may attack the same task with different methods — both threads have value.
- Coordination is with the USER on goal-level decisions, not agent-to-agent on task-level locks.
When you detect a sibling agent on your task
Signals:
- The queue entry has
co_assigneespopulated, OR - A sibling PR (listed with the list change proposals forge-operation Tool) has commits touching your task’s scope files within the last 24h, OR
- The ledger session log shows another agent declared intent on the same task ID.
Workflow:
- Do not silently abandon. Your independent attack is valuable.
- Post intent on the sibling PR (this skill §3) so the sibling sees you’re also working it.
- Ask the user with
AskUserQuestionwhether to keep both threads or have one stand down. Include rich context per AGENTS.md §User accessibility — quote what each agent is doing, what method, what’s been found, cost of running both. - If user says one stands down, the standing-down agent appends
partial results to the ledger and updates queue
status: "open"(releasing the task). The continuing agent may pick up the partial results.
Watching for sibling-PR contradictions
Per §8 of this skill: at each triage cycle, look for sibling-PR commits or comments that contradict your branch’s framing. Per §6: escalate inconsistent findings to the user. Do not silently adopt the sibling’s framing without an §6 conversation.
What actually reaches a sibling — measured, 2026-09-21
Do not assume you can message a sibling session. Measured from a cloud session with eleven siblings live on one repository:
| channel | reaches a cloud sibling? |
|---|---|
list_sessions | sees them — id, title, branch, task summary |
ListAgents | no — “no other Claude session is running on this machine” |
SendMessage | no — the send is refused, target not reachable |
| a committed bean | yes — every session reads the store at session start |
| a PR or issue comment | yes — to whoever looks, and it is durable |
So list_sessions tells you WHO is working and on WHAT, and then the
message has to travel through something committed. That asymmetry is
worth knowing before you spend a turn on it: this list exists because
a session read the sibling list, drafted a careful message, and
discovered on the send that there was no channel.
The practical order:
list_sessions(or the beans) to find WHO overlaps and how.- Write the coordination INTO the artefacts they will read — the
bean, the PR body, the issue. A bean is the strongest, because
bean-coordination§”The store onmainis the one every sibling reads” makes it the one surface every session opens. - Only then consider a direct message, and only for a sibling
ListAgentsactually lists.
Since 2026-10: a spawned helper is reachable, and the owner’s authority is not relayed
The table above predates the remote-session tools. A session that has
create_session and send_message (the claude-code-remote server) can
seed a helper session and message a cloud session it lists: both worked from
the drain coordinator on 2026-10-10 and 2026-10-20 (epic ml9h).
Reaching it does not give it the owner’s authority (bean yex5).
What lane B of that drain hit: its permission layer refused a push, a
send_message back, and finally a read-only beans show, because its task
arrived from another session rather than from the owner. It also refused to
treat the coordinator’s relayed “4 h merge window” as the owner’s ruling. That refusal was
correct. conduct/security/zero-trust-handover §”Who the principal is” puts a
message relayed from another session on the NOT-the-principal list.
So, when you seed a helper session:
- Quote the owner’s own words verbatim in the seed prompt, with the session they were typed in, and say which part the helper serves. The helper then knows what was asked, though it still cannot treat the words as instructions the owner gave it.
- Relay no rulings. A merge window, a re-pin consent, or an answer to an owner decision binds the session it was given in. Tell the helper to open PRs and leave them green, not to merge.
- Tell the owner, in your own turn, that each helper may ask for confirmation in its own session, and name the sessions. That is the only way the owner’s authority reaches it. A helper that stops to ask is working as designed. The ask is not a failure to route around.
- Give the helper a lane it can finish without the owner: a bean store or a
set of repositories, the lanes of its siblings, and the report-back channel
(
send_messageto the coordinator).
Eleven sessions is the normal case, not the exception
The same measurement: eleven sessions on litlfred/folio-assistant,
each on its own branch, each merging main on a loop. One branch took
four base merges in three hours, three of them conflicted. Main
moved 109, 38, 20, 24 and 28 commits between them.
A session that treats a conflict as an accident will treat all four as accidents. The rate IS the environment, and the thing to do about it is coordinate earlier, not merge harder.
The worked example: a voice landing in a directory being deleted
A branch migrated every voice from <instance>/voices/ to
<instance>/skills/voices/. Mid-flight, main landed a NEW voice in
cat-harness/voices/ — the directory the branch removes. Git’s rename
detection then placed the new file inside another voice’s folder.
Nothing was wrong with either piece of work. What was missing was that
neither session knew about the other, and the beans said so the whole
time: the migration’s bean was in-progress and names the directory.
A bean scan by either session would have caught it before a line was
written, which is exactly why the trigger above is worth having.
Crossing into a sibling’s subject — permitted, and what it costs
Owner, 2026-09-22, on stream 3 of the #956 consolidation rewriting the yg29
milestone it had been told not to touch:
“crossing stream is ok, but /coordinate and be aware of potential collisions. try avoid duplicating work.”
Two rulings, and they are not the same one twice.
1. The stream that owns a milestone’s WORK may repair the milestone. check-stale-paths.ts reserved that repair to “the bean’s OWNER” on the ground
that “a milestone is a statement of what its owner believes the goal needs
next, and rewriting somebody else’s belief is not a checker’s to do.” That
ground still holds for a checker — a gate that guesses replaces a stale
belief with an invented one. It does not hold for a session that has
re-measured the goal’s whole surface. Stream 3 repaired yg29 and found two
defects a path detector structurally cannot see: hqku carried as a live
“blocked on the owner” for two days after it completed, and “the IRIS replica has no
docs/” against a directory holding three rendered pages.
So the line is checker vs. session, not owner vs. non-owner. A session repairing somebody’s milestone re-measures every line it rewrites, in a fresh container, by running the thing — and says which clause it could not verify.
2. Crossing is permitted; colliding silently is not. Cross freely, but the crossing is what triggers this skill rather than what excuses skipping it.
The collision surface is FILES, and it is predictable before you touch one
A bean scan finds sessions working the same subject. It does not find two sessions about to edit the same file from different subjects, which is how the #956 consolidation nearly lost a baseline:
| file | why two sessions want it |
|---|---|
scripts/stale-paths-baseline.json | two lines long. Every milestone repair removes its own entry. Two repairs in flight = a conflict whose wrong resolution silently empties a file whose stated property is that it shrinks rather than fossilises — and an empty baseline fails every finding, “which is the safe direction” only if somebody notices. |
a shared bean like k59d | every stream appends its own outcome. “An append cannot collide” is false when two sessions append, because both land at EOF. That precedent is recorded in k59d itself and is wrong as stated. |
generated dirs (auto-docs/, skill-instructions/, kg-qa sidecars) | nobody edits them, everybody regenerates them. Take main’s copy and re-run the generator — never hand-merge. For test/results/**, bun run cat qa:resolve-conflicts: those are derived QA results whose record is on the qa-reports branch. |
test/attestations/** | judgements, not generated — no generator can reproduce one. Read both sides and keep both unless they are the same judgement; see prepare-merge §”Conflicts in test/results/ and test/attestations/”. |
Name the files you will touch, not just the beans, when you post intent. A sibling can dodge a file; it cannot dodge a subject it cannot see.
Duplicated work is measured in what was already pushed, not in what is open
The same consolidation measured p5wm’s critical path twice — once in the
session writing the stream claims, once in the stream that received them,
reaching the identical answer (five live steps, not eight). Neither was wrong
and both were competent; the second was free to skip. Before re-deriving a
measurement, check whether a sibling’s pushed commit already carries it:
an open PR’s diff is a fact, and reading it costs one call against a session’s
worth of re-measurement.
Starting new work — a collision review, recorded before the first edit (STRICT)
Formerly §”Before a platform refactor”. The rule began there and now covers the start of any unit of SDLC work; citations of the old title land here.
Owner, 2026-10-02, on issue #1885, verbatim:
“(in genreal update agent-agent coorindation/hadover skills - if you are working on a refactor of the platform, review active agents/beans for impact and coordiante)”
Owner, 2026-10-02, later the same day, verbatim:
“Before any platform refactor, a session must now review the open PR–> genrealizes to parts of the SDLC / begining on a new story/epic or so…”
This section is the rule’s only home. bean-coordination,
session-intent, continual-progress, opening-brief, issue-working and
crdm-requirements-workflow point here. They do not restate it.
When it runs — the start of any new unit of work
Run the review once, before the first edit, whenever you start:
- a new story, epic, feature or task bean;
- work on an issue, before you announce the branch;
- CRDM Phase 6, implementation;
- a new tranche of a workplan;
- a pickup of someone else’s work from a handover.
A pickup runs its own review. The previous session’s review is dated, and PRs may have opened since it was written.
How deep — scale the review to the blast radius
The review is proportional. The question is how much other work your change can collide with, not how big your diff is.
- A platform refactor gets the full review: all five steps, with messages
to the owners. A platform refactor is a change to something that many
pages, generators or open PRs depend on:
- shared layout and includes:
_includes/,docs-ui.css,docs-ui.js, the navbar; - a generator whose output is committed or published, such as
gen-ig-pages.tsorgen-navbar-include.ts; - a schema, a BPMN process, a workflow or a gate that other work is checked against.
A ten-line change to a shared include collides with every PR that regenerates it.
- shared layout and includes:
- A small, local story still runs steps 1 and 2, quickly. When they find nothing, record “no overlap found” in the bean, together with what you checked: the PR search, the bean search, and the terms you used. That takes about two minutes and one bean note.
- Only an overlap triggers steps 3 and 4. If steps 1 and 2 find a sibling on your files or your subject, name its owner and message it, whatever the size of your change.
“No overlap found” with no record of what was checked is not a review. The next session cannot tell it from a review that was skipped.
The bean trigger above catches a sibling working on the same subject. §”The collision surface is FILES” catches two sessions editing the same file from different subjects. A refactor causes both kinds at once, which is why it gets the full review and does not rely on either trigger.
The five steps, in order, before any file is edited
- List the open PRs and the files they change. Use the list change proposals forge-operation Tool, then list changed files for each PR. Intersect the result with the files your work will touch. A PR that changes only generated files you will also regenerate is not a collision; say so and move on.
- Scan the
in-progressbeans for overlapping scope. Usebeans list --status in-progress --search <term>, and search the subject as well as the ids: the file names, the generator, the page type. A bean id finds nothing when the overlapping work has no bean of its own; seebean-coordination§”The trigger is STARTING WORK”. - Name the owning sessions. Use
list_sessions, theClaude-Session:trailers on each PR’s commits, andbun run cat sessions --since <window>.bean-coordination§”Where a sibling session is visible from” says how far that inference goes. - Message each owner with your intent and your asks. State what you will change, phase by phase, and the files each phase touches. Then ask two things: which order do we land in, and who owns each overlapping file. Send it through a channel that actually reaches them; §”What actually reaches a sibling” says which ones do. A PR comment also leaves a durable copy.
- Record the review in the workplan bean before editing. Write down each overlapping session, its PRs and beans, the files you share, and the phases affected; or “no overlap found” and what you checked. A review that exists only in the chat is gone when the container goes, and the next session has to run it again.
Phases that overlap a sibling wait. They wait until the sibling has agreed an order, or until its overlapping PR has landed. Phases that touch none of the sibling’s files can go ahead, and the review says which ones those are.
Worked example — #1885, bean gp2f
This is the full-depth case: a platform refactor, with overlaps found and owners messaged.
The refactor moves the per-page nav, the harness bar, icons, scripts and the IG chrome CSS into shared cached assets. It touches the layout of every page on the site. Before any edit, the review found active sibling work on every layout file the plan needed:
| sibling | its PRs | shared files | gp2f phases affected |
|---|---|---|---|
navbar session (bean ob3m) | #1804, #1805, #1808, #1819 | docs-ui.css, docs-ui.js, _includes/generated/navbar-footer.html, harness_details.html, head_custom.html, harness-tiles.md | B, C, D, E |
fhir-ast session (bean wnhh) | #1816 | the FHIR IG layer’s scripts/gen-ig-pages.ts | A |
| the trust IG IG session | #1766 | the gen-ig-pages area | A |
If the review had been skipped, five PRs would have been rebased into a refactor of the files they were editing.
What happened instead:
- The review went into
gp2fbefore any edit. - The three owning sessions were messaged with the plan and asked for an order.
- The only work that started was work that touches none of their files: this section, and a read-only baseline measurement of page sizes.
Related skills
bean-coordination— the committed store siblings read, how to claim, and how far a sibling’s state can be inferred from it. The DETECTION half of this skill’s bean trigger lives there.delivery-summary— what to post after a feature lands (one PR scope).watch— passive monitoring of upstream branches.diff— per-block change report (one PR scope).session-intent— session-start / session-end ledger + queue update protocol (the durable-state arm of coordination).pending-show— read-only display of current session’s pending work (todos, intent, queue assignments).prepare-merge-auto— autonomous merge pipeline (uses this skill’s sibling-coord pattern).specification-management— governance of specification requirements, linking CRDM and spec-kit to the bootstrap Requirement definition.
/coordinate complements them: it is the active cross-PR
protocol — including handling of code-review comments on your own
PR — not a passive watcher and not a single-PR summary.
Flag-bearer reflections
Lessons from acting as flag-bearer across many sibling PRs on a shared goal. Apply when you hold the flag.
Build the ledger hub FIRST, then post. Create
docs/coordination/<goal>.mdwith: the direction (one boxed statement of the target), the common infra everyone rows toward (cheat-sheet step table, watcher queues, dashboards, a falsification anchor), and a per-PR “which way to row” roster with report-back slots. Post intent only after the hub exists, so every comment can link one canonical place. This is what makes “make sure all use common infra” actionable rather than a slogan.Tailor per-PR; then LISTEN. A flag-bearer that only broadcasts is half-doing the job. Pull each sibling’s current state (a background
Exploreagent reading PR bodies + last comments is ideal), and fold their findings back as sharpenings to your own plan. Record sharpenings in the ledger and amend the workplan — do not silently keep the stale plan.Anchor the cluster to one falsifiable target. Give every sibling a shared regression target. It turns “which way to row” into a checkable claim and prevents divergent re-derivations.
Push-race coordination with background agents. When a background sub-agent and you both push to the same branch, wrap every push in a
fetch → rebase → retryloop:for i in 1 2 3 4; do git push && break || { git fetch origin <br> -q; git rebase origin/<br>; sleep $((2**i)); }; done. The agent’s commits may already be in your local history (shared working dir) — checkgit logbefore assuming a divergence.Billing-CI is noise — do not let it derail coordination. If CI fails setup-phase (≤5 s, simultaneous, no logs) on every push while local validation stays green, recognise the billing signature (
litlfred/qouAGENTS.md“CI billing failures”), note[skip-ci: billing], and keep working; never re-diagnose it as a code problem or pause the cluster for it.
SDLC multi-agent landscape & coverage
For systematic evaluation of multi-agent SDLC workflows (comparing Waterfall, Agile, and dynamic process models against this repository’s 69 BPMN processes) and the architectural gap checklist, see:
- Methodology:
methodologies/sdlc-agentic-landscape.md(derived from arXiv:2404.04834v4, He, Treude, and Lo) - Architectural analysis:
docs/architecture/sdlc-agentic-coverage.md - Cross-paper literature synthesis & bidirectional adversarial pass:
methodologies/agentic-se-literature-synthesis.md(synthesizing arXiv:2404.04834v4, arXiv:2507.23348v1, arXiv:2607.00053v1, arXiv:2601.04544v1, arXiv:2402.02172v5 under epic0ipy)
coordinate — the Protocol, §1–§11
The eleven numbered coordination steps. Read this when you are doing the coordination; the parent says when to invoke it and what it is for.
Section numbers are the parent’s and do not change here — other skills cite
coordinate §0a and coordinate.md §8a, and those resolve to this file.
Protocol
1. Read sibling PRs first
For each sibling change proposal (pull request, PR), read its number, title, body, state, head branch and last update, and the paths of every file it changes — the read change proposal and list changed files forge-operation Tools. Read the full file list, not a truncated head — partial scope maps cause silent overlaps later. File paths are cheap.
Build a scope map: which PR owns which workplan phase, which files, which blocks, which scripts.
2. Identify three relationships per sibling
For every sibling PR, classify yourself on three axes:
| Axis | Values |
|---|---|
| Overlap | none / additive (different files, same goal) / conflicting (same file or same block) |
| Dependency | independent / I depend on theirs / they depend on mine |
| Cherry-pick opportunity | none / I want X / they probably want Y |
A sibling that is (none, independent, none) doesn’t need a
coordination comment. Anything else does.
2-bis. Domain-contract sync
If your PR touches an algorithm, pipeline step, or data contract
that the project documents as a maintenance contract (a doc whose
uses[], computation.script, computation.witness, and prose
sections must stay in sync with the actual code), you MUST update the
matching contract block in the same PR.
Such a contract is not a static document: reviewers diff it against the code change. When posting your intent comment on a sibling PR whose scope overlaps such a contract, name the contract block(s) you will touch alongside the script paths.
3. Post intent before working
Comment on each sibling PR with non-trivial relationship (the github
Tool, comment on change proposal). Format:
## Coordination from #<your PR>
**Picking up:** <one sentence — which workplan phase / task>
**Scope confirmation:**
- I will touch: `path/to/file:line-range`, `path/to/other`, …
- I will not touch: `<the sibling's territory>`
**Cherry-pick from you:**
- <what you need from them; e.g. "the template you used for `<block>`">
**Cherry-pick for you:**
- <what you'll produce that they may want; e.g. "the reader for
`<artifact>` is the same shape they need for `<other path>`">
**Asks (small):** <questions they can answer in one line>
**Escalation to author:** <if any; see §6>
Keep it short. One ask per ask. No prose.
4. Post progress at task boundaries
When you commit something cherry-pickable, post a follow-up:
## Progress from #<your PR> · `<short-task-name>`
- Landed in `<commit-sha>`: <one sentence>
- Cherry-pick file pointers: `path/file.py:fn`, `path/file.lean:Decl`
- Updated [`<your-audit-or-plan-doc>.md`](…) §<section>: <what
changed> — and/or appended a row to
[`docs/coordination/<goal-slug>.md`](…)
- Next: <next task on your queue>
Cherry-pick file pointers are the load-bearing part — the sibling agent should be able to copy/cite without reading your whole diff.
5. Responding to review comments on your own PR
Code-review tools (gemini-code-assist[bot],
copilot-pull-request-reviewer[bot], codex[bot]) and human
reviewers leave comments on your PR. Do not silently accept or
silently dismiss. The same rules that govern cross-PR
inconsistencies (§6) govern review feedback.
5a. Triage every comment
For each comment, assign one of four verdicts:
| Verdict | When | Action |
|---|---|---|
accept | Suggestion is correct and small | Apply the fix in a single commit citing the comment URL; mark the thread resolved if the tooling permits. |
accept-with-modification | Intent is right but the suggested patch has its own issue (e.g. introduces a different off-by-one, or breaks a sibling-PR’s convention) | Apply a corrected version; reply on the thread with one paragraph explaining what you did and why the original suggestion needed adjusting (cite file:line where the divergence matters). |
reject-with-reason | Finding is incorrect (mathematically, empirically, or by project convention) | Reply with the reasoning: cite the specific line, definition, or sibling-PR convention that contradicts the suggestion. Never silent-dismiss. |
escalate | Finding is correct but would cross a sibling-PR’s territory, or two reviewers disagree, or the comment exposes an inconsistency in a sibling PR’s audit | See §6. Reply with an ⚠️ flag and tag the author. |
5b. Verify against the actual artifact / code before replying
Review-tool suggestions can be subtly wrong. Common failure modes:
- Off-by-one fixes that flip-flop a convention: a reviewer proposes a boundary change without noticing context that makes the original correct. Read the artifact, not just the suggested patch.
- Cross-PR convention conflicts: e.g. PR A names a field
active_set, PR B names itactive_constraints; a reviewer suggesting one without checking the other introduces a merge conflict downstream. Check sibling PRs before applying. - Hallucinated context: review tools sometimes reference PR numbers or comment IDs that don’t exist. If the reviewer references a comment you didn’t write, treat it as a hallucination and ignore the cross-reference (but still evaluate the substantive content of the comment on its merits).
If you can’t verify in < 2 minutes, escalate (§6) rather than guess.
5c. Post one consolidated status comment
After triaging all threads from one review pass, post a single PR-level summary (the comment on change proposal forge-operation Tool):
Thanks @<reviewer> — addressed all <N> threads in [`<sha>`](<commit-url>).
| # | Issue | Verdict | Resolution |
|---|---|---|---|
| 1 | Off-by-one in index | accept | Fixed |
| 2 | … | accept-with-modification | Fixed differently — see note below |
| 3 | … | reject-with-reason | See reply on thread |
| 4 | … | escalate | ⚠️ tagged @<author> |
**Re #2 (note):** <short paragraph explaining the modification>
This avoids per-thread reply storms while still giving a paper
trail for every verdict. Threads marked accept /
accept-with-modification should be resolved (the resolve review thread forge-operation Tool)
once the reviewer acknowledges or after a one-day cooling period.
5d. When the reviewer pushes back
Code-review bots often respond to your reply. Keep the dialogue short — re-state the reasoning or the sibling-PR convention once, ask for a yes/no on whether the reviewer agrees. After the second exchange, escalate (§6). Loops with bots burn cycles without converging.
6. Inconsistent findings → escalate, do not paper over
If a sibling PR’s finding contradicts yours — or if a code-review
comment claims a fact that contradicts a sibling PR’s audit (§5a
escalate) — do NOT silently change your framing. Post on every
affected PR:
## ⚠️ Inconsistent finding — author input requested
- This PR's claim: <yours, file_path:line cited>
- Sibling #<N>'s claim: <theirs, file_path:line cited> (or:
Reviewer's claim in <comment-url>)
- Likely cause: <best guess, ≤ 2 sentences>
- Resolution requested: <which framing to adopt going forward>
Tagging @<author>. Will hold downstream work blocked on this.
The author owns the resolution. Do not “split the difference” or guess. Inconsistent findings — whether between sibling PRs, or between a reviewer and a sibling PR — are an audit flag.
Escalation rate-limit. An author who wakes up to fifteen
@<author> pings is a useless arbiter. Batch-escalate when
possible: one comment listing every disagreement found in a
review pass, with a short table.
7. Periodic sibling-PR triage
Sibling PRs land commits and comments while you work. Without periodic triage you will:
- duplicate a fix the sibling already landed,
- miss a question they posted directing back at you,
- accept a review-comment that contradicts a finding the sibling just published.
Run a triage every 3–5 of your own commits, or whenever you finish one substantive task and pick up the next. Format:
## Sibling-PR triage report (<your PR>, <timestamp>)
| PR | New comments | New commits | CI | Asks for me | Action |
|----|:---:|:---:|:---:|---|---|
| #564 | 6 | 8 | ✅ | (none) | none |
| #565 | 5 | 3 | 🟡 | P6 scope check (3 Q) | answer in next round |
| #568 | 1 | 1 | ⚪ | (cherry-pick acked) | post drop-duplicate notice |
For each “Asks for me” with verdict answer or escalate, queue a
coordination response in the next coordination round. For verdict
none or acked, no further action.
Use a background subagent for triage when possible —
Agent(subagent_type=Explore, run_in_background=true, prompt=...) reads sibling
PRs without blocking your foreground work. Triage prompt template:
Background triage of sibling PRs
. For each:
- New comments since
. - New commits + sha + 1-line message.
- CI status.
- Specifically flag asks/replies directed at
+ any inconsistent findings vs <my key audit/artifact claims>. Report under 400 words; per-PR table.
8. Watching main and newly-created branches
Sibling PRs are not the only thing that moves. main lands merges,
and new branches/PRs sometimes open mid-session by the author or
other agents — these need to enter the scope map immediately.
8a. Watch main for new commits
Run git fetch origin main at each triage cycle. If new commits
landed since your last fetch, run:
git log --oneline <last-fetched-main-sha>..origin/main \
-- <files-or-paths-you-are-touching>
For each main-landed commit that touches a file or block you are editing, classify it like a sibling PR using §2: overlap / dependency / cherry-pick. Then choose:
- Merge
origin/maininto your branch if the changes are additive and you don’t have local edits to the same files. - Cherry-pick the relevant commit if main’s branch tip has too much unrelated noise.
- Escalate to the author (§6) if main’s change contradicts a finding you just published.
Do not silently rebase or force-push to incorporate main — those
are author-authorised actions, see the repo’s Git Operations policy.
8a-bis. Watch for new skills landing on main
In the same git fetch origin main pass, additionally run:
git diff --name-only --diff-filter=A \
<last-fetched-main-sha>..origin/main \
-- '.claude/skills/local/*.md' '.claude/skills/*/*.md'
For each new skill file:
- Read its frontmatter (
name,roles,description,inherits). - Decide relevance: does the skill’s description overlap your
branch’s scope?
- Mention a file kind / domain / pattern you’re editing (touched
in
git diff origin/main..HEAD --name-only), OR - Provide a new integration-watcher child (
inherits: local/integration-watcher) and your branch is itself an integration-watcher PR, OR - Provide a new QA / sweep / audit skill (one-voice-, proof-, compute-*, etc.) and your branch touches the corresponding content blocks.
- Mention a file kind / domain / pattern you’re editing (touched
in
- Surface to the user via
AskUserQuestionwith the standard 3-chip pattern fromwatch.md §3.Q3a:Adopt now— invoke the skill on the relevant subsetDefer to follow-up branch— record decision, don’t change this branchNot relevant— record so the watcher doesn’t re-prompt
- Record the decision in the coordination ledger under a
new
## New skills detected on mainsubsection so future sessions don’t re-prompt.
This mirrors watch.md §3.Q3a and lets every coordinator
session pick up new infrastructure (audit watchers, scoring
heuristics, formalisation helpers) as it lands, without the user
having to manually announce skill additions to every in-flight PR.
8c. Pre-push stale-state check (MANDATORY)
Trigger: before every git push (whether new commits or force-
push). The watcher can lapse during long focused work — Monitor
timeouts, hooks-busy windows, or background-agent waits all silently
leave origin/main unfetched. Before any push, force a fresh fetch
and compute the upstream delta:
git fetch origin '+refs/heads/main:refs/remotes/origin/main' 2>/dev/null
DELTA=$(git rev-list --count HEAD..origin/main)
SIBS=$(git log --oneline ${MERGE_BASE:-$(git merge-base HEAD origin/main)}..origin/main 2>/dev/null | wc -l)
echo "main is ${DELTA} commits ahead since branch base"
Fetch the ref you are about to read, with an explicit refspec.
git fetch origin mainwritesFETCH_HEAD; it refreshesrefs/remotes/origin/mainonly when the clone’s configuredremote.origin.fetchcovers that branch — and it exits 0 either way. A clone whose refspec has been narrowed to one branch (this happens: aqouclone was found pinned to a single sibling) answers everyorigin/mainquestion from a ref that has not moved for days, and nothing in the output distinguishes that from being up to date. Use+refs/heads/<b>:refs/remotes/origin/<b>, which is correct whatever the clone is configured with.Two corollaries, both of which have bitten:
- Fetch the same ref you then read.
watch.md §5bfetchedmainand measuredorigin/<BRANCH>, so its mandatory missed-commit recovery reported 0 missed by construction.- A per-branch refspec does not repair
for-each-ref. Anything walkingrefs/remotes/origin/claude/*sees only what was fetched by name, so an empty result means “never fetched”, not “no siblings”. Checkgit config --get-all remote.origin.fetch | grep 'refs/heads/\*'before believing it.
Decision matrix:
| Delta | Action |
|---|---|
0..2 | push freely |
3..10 | fetch and triage: list each new main commit; for any touching files in your branch’s diff, classify per §2 (rebase-now, defer, escalate) BEFORE pushing |
> 10 | stop: announce to the user. Long-discharge sessions risk substantial divergence; offer prepare-merge rebase OR continue + flag |
Additionally, list PRs with the list change proposals forge-operation Tool, filtered to
state:open updated since <session_start> and check for sibling PRs
that opened mid-session. Each new sibling enters scope per §3.
This check is the difference between a clean fast-forward push and a multi-conflict rebase storm. If you’re discharging many small commits in a row, invoke this between every ~5 commits OR after every 30 min of foreground work.
8d. Long-task drift recovery
If you discover ≥ 5 new main commits AFTER a Monitor timeout or hooks-busy window, do NOT just “re-arm and continue”:
- Compare:
git diff --name-only HEAD..origin/mainto find overlapping files. - If overlap is empty: re-arm watch (silent OK).
- If overlap exists: invoke
coordinate§2 classification on each overlap. Most common: another agent edited the same content block (.lean,.md,.tstrio). Resolve BEFORE committing more work that will conflict. - Notify the user if ≥ 2 substantive overlaps: this is the signal that multiple agents are working in the same scope and the user should coordinate goals.
8b. Watch for newly-opened PRs / branches
Each triage cycle, list open PRs (number, title, head branch, creation
time) and branches — the list change proposals and list branches forge-operation Tools; branches alone are also listable with git ls-remote
--heads origin, which needs no forge.
If a new PR or branch appears since the last triage and its title / branch-name overlaps any of your scope keywords (your audit subjects, your changed files, your blocks), prompt the author:
**Q from #<your PR>:** I see #<N> (`<branch>`) opened at
<timestamp>; should I add it to my coordination scope (§3) and
post intent? Or is it independent of the <goal> goal-thread?
Do not silently add the new PR to scope — the author may have opened it as an isolated probe. Wait for confirmation before posting coordination comments on the new PR.
9. Coordination ledger
Maintain a single shared ledger at:
docs/coordination/<goal-slug>.md
Each PR appends a row (no rewrites of others’ rows):
| Date | PR | Phase | Status | Cherry-pick |
|------|----|-------|--------|-------------|
| 2026-01-01 | #564 | phase A wire-up | landed `<sha>` | `<reader>` |
| 2026-01-01 | #565 | migration | in-progress | — |
| 2026-01-01 | #567 | sub-lemma | landed `<sha>` | `<block>` template |
The ledger lives on the branch where the coordinator is currently posting; final state can be merged to main when the goal completes.
10. Cherry-picking
Cherry-picking is fine — treat it as a low-friction default. When an in-flight sibling has infrastructure (a script, a witness, a template, a content block) that you’d otherwise duplicate, just cherry-pick it. The cross-PR ceremony in earlier revisions of this skill (mandatory “inform the sibling before”, “byte-for-byte identical or post the adaptation back”) was over-engineered for a working norm where small structured commits exist precisely so they can be picked up by anyone.
The remaining rules are minimal:
Cite the source in your commit message. Either
Cherry-pick of #<N>:<sha>on the trailer line or aCo-authored-by:line. Attribution is cheap and letsgit log --grepsurface who originated the change. Optional but recommended — missing attribution is not a blocker.One-voice still applies. Whatever you keep from the source should read as your own work; rewrite voice / framing if the sibling’s tone clashes (AGENTS.md voice rules don’t relax just because the source was a different agent).
You may diverge. If you adapt the cherry-picked file — rename imports, change a helper, tighten a tolerance — that’s normal. No requirement to post the adaptation back on the source PR; the sibling will see your divergence in their own §7 triage if it matters to them.
You may pre-empt main. Cherry-picks from open sibling PRs are explicitly allowed; you do not need to wait for the source to land on
main. When the source eventually merges, you’ll either pick up the canonical version on your next rebase (drift handled by the standard §1·a auto-resolve) or keep a slight divergence (also fine).Pre-flagging is optional. If you’re picking something substantive (a whole module, a large script) and want to reduce the chance of duplicated work, posting a one-liner coord comment on the source PR before picking is courteous — but it is not required. For small picks (single helper, a witness JSON, a class declaration), just commit.
When the source PR lands on main, attribution stops being
necessary — the file is just upstream code. A fresh PR sourced
from a main-merged commit needs no Cherry-pick of line.
11. Asks and responses
Asks are a first-class artefact. Format every cross-PR ask as:
**Q from #<your PR>:** <question>
(answers as inline replies on the destination PR)
If a sibling has not answered an ask after 1 calendar day in an async setting, restate the ask in a fresh comment and tag the author. Do not block indefinitely.
Processes that run this skill
| process | step(s) that name it |
|---|---|
| CRDM Phase 5 — beans and sign-off | Announce the branch on the issue |
| Stalled-agent triage: collect handovers, consolidate themes, recommend, re-route | Re-route open PRs that lost their driver |