From 753a8a9a474f221049cd40fdf57899ca793028c3 Mon Sep 17 00:00:00 2001 From: Leon Lee Date: Fri, 6 Nov 2026 17:39:49 +0900 Subject: [PATCH 1/3] Tell a delegating author it owns the pair loop, and subagents not to run pair A subagent inherits the auto author's pair environment, so following "when you finish a task, send a request" it could open a thread in a checkout others are still editing, or in its own worktree where no auto session serves it. The instructions gain a Delegating work section: the parent owns requests, responses, retries and verdicts, tells subagents to return changes and validation results without running pair, keeps the checkout stable during each round, and reviews separate PRs one at a time. The finish-a-task triggers apply to the loop owner, the auto author prompt says the same, and README gains a Parallel work section. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012Y3kg5hjT2zSZM9qUEEinM --- README.md | 15 +++++++++++++++ prompts/pair.md | 38 +++++++++++++++++++++++++++++--------- src/auto.ts | 2 +- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 01e93ba..b5e53eb 100644 --- a/README.md +++ b/README.md @@ -339,6 +339,21 @@ the reviewer to complete. A brainstorm never escalates, and `pair history` lists Both agents MUST run pair 0.8.0 or later: an older pair rejects a brainstorm as a corrupt message instead of reviewing it as code. +### 5.3. Parallel work + +An author MAY split a task across subagents, but it alone runs the pair loop. Its instructions tell +it to have each subagent return its changes and validation results without running pair commands, +then integrate them into the session's worktree and request review of the combined change, keeping +the checkout stable while the reviewer runs. A subagent inherits the author's pair environment, so +without that rule it could open a thread of its own: in the shared checkout, against files others +are still editing, or in its own worktree, where no auto session serves the request. + +When the subagents' work belongs in separate PRs, the author reviews them one at a time: it checks +out each branch in the session's worktree and finishes that PR's review loop before the next. For +PRs reviewed in parallel, run one `pair start --worktree NAME` session per PR +([Worktrees](#6-worktrees)). Approval in each worktree doesn't cover a later merge of their work; +review the integrated result as well. + diff --git a/prompts/pair.md b/prompts/pair.md index d3318df..a83ae69 100644 --- a/prompts/pair.md +++ b/prompts/pair.md @@ -6,6 +6,26 @@ You are `{{AGENT}}`. Your partner `{{PARTNER}}` works on the same repo. In auto reviewer for each round. You talk only through the `pair` CLI. Always pass `--as {{AGENT}}`. +## Delegating work + +If you delegate implementation to subagents, you still own the pair loop: requests, responses, +retries and verdicts. In each delegated task, tell the subagent not to run pair commands and to +return its changes and validation results to you. Say so even when it works in a separate worktree, +where pair's instructions may be missing. Integrate the changes into this session's worktree, then +request review of the combined change. Before each request or response, make sure no task is still +writing to this checkout, and keep it stable while the reviewer runs; work in other worktrees may +continue. You may delegate fixes between review rounds, then integrate them before you respond. +If the delegated work belongs in separate PRs, review each one on its own: check out its branch in +this worktree, finish its review loop, then move to the next. Git refuses a branch still checked +out in another worktree; once its work is committed and no task is using it, remove that worktree +with `git worktree remove`, never by force. Or ask the user to run one `pair start --worktree` +session per PR. + +If you are a subagent implementing part of another author's task, return your changes and +validation results to that author. Don't run pair commands or start a reviewer, even if you inherit +`PAIR_AUTO_ROLE=author` or other pair variables. This doesn't change the rules for a managed +reviewer handling a pending round. + ## Auto mode At session start and after a clear or compaction, check `PAIR_AUTO_ROLE` in your shell before @@ -14,14 +34,14 @@ choosing the pair workflow below. In auto mode the launcher sets `PAIR_BIN` to its own CLI. Use `"$PAIR_BIN"` in place of `pair` in all command examples, so a login shell cannot select an older installation from PATH. -If `PAIR_AUTO_ROLE=author`, pair owns the reviewer. After finishing a task, send your request as -usual. `pair send request` and `pair send response` return the review inline: read it and continue -the fix/reject loop until approval or escalation, or in a brainstorm until it completes. In -interactive Claude Code, run these commands and managed retry waits with Bash's -`run_in_background: true`, end your turn, and read their output when the completion notification -arrives. Reviews can exceed the foreground Bash timeout. This -background command is active review work, not an idle wait loop. Do not register, call `pair_listen`, -or run idle waits. +If `PAIR_AUTO_ROLE=author`, pair owns the reviewer. If you own the pair loop, send your request +after finishing the task and integrating any delegated work. `pair send request` and +`pair send response` return the review inline: read it and continue the fix/reject loop until +approval or escalation, or in a brainstorm until it completes. In interactive Claude Code, run +these commands and managed retry waits with Bash's `run_in_background: true`, end your turn, and +read their output when the completion notification arrives. Reviews can exceed the foreground Bash +timeout. This background command is active review work, not an idle wait loop. Do not register, +call `pair_listen`, or run idle waits. If a managed review fails, the request stays on disk. Show the user the error as printed, and don't guess at a cause it doesn't name. Retry once with `pair wait --as {{AGENT}}`. If the same failure @@ -71,7 +91,7 @@ cancelled by you or the user), don't restart it. Tell the user what happened. ## Ask {{PARTNER}} for a review (you are the author) -When you finish a task: +When you own the pair loop and finish a task, including integrating any delegated work: 1. Send a request with what changed and why, what to focus on, and the files touched. ``` diff --git a/src/auto.ts b/src/auto.ts index 10f5424..3b02e51 100644 --- a/src/auto.ts +++ b/src/auto.ts @@ -784,7 +784,7 @@ export async function startAuto(options: AutoOptions): Promise { heartbeat = setInterval(() => sendGuardian({ type: "heartbeat" }), 1000); for (const name of ["SIGINT", "SIGTERM", "SIGHUP"] as const) process.on(name, signal); // No run-specific path: Claude records the system prompt and reuses it when the conversation is resumed in a later run. - const authorPrompt = `You are the interactive author in pair auto mode, with ${reviewer} as your automatically managed reviewer. The pair CLI is "$PAIR_BIN", which the launcher sets for each run; use it in place of pair in every example below. Follow the pair review rules. After completing a task, feed a Markdown summary, review focus and file list through stdin to pair send request --as ${options.author} -. Follow-up replies use pair send response --as ${options.author} - with the fix/reject explanations on stdin. In this mode both commands return the review inline: read it, verify each finding, fix or reject it, and send a response until approval or escalation. To brainstorm a design with ${reviewer} before a task, use pair send request --brainstorm: each contribution comes back inline the same way, and you answer with pair send response until ${reviewer} completes it. Do not register, call pair_listen, or start idle waits in auto mode. ${FAILED_REVIEW_RULE.replaceAll("{{AGENT}}", options.author)} For interactive Claude Code, run managed send and retry commands with run_in_background: true in the Bash tool, end your turn, and read their output on the completion notification. A reviewer can take longer than the foreground Bash timeout; backgrounding the active review command is different from idle polling. Do not start your own reviewer processes. Wait for the user's task.`; + const authorPrompt = `You are the interactive author in pair auto mode, with ${reviewer} as your automatically managed reviewer. The pair CLI is "$PAIR_BIN", which the launcher sets for each run; use it in place of pair in every example below. Follow the pair review rules. After completing a task, feed a Markdown summary, review focus and file list through stdin to pair send request --as ${options.author} -. Follow-up replies use pair send response --as ${options.author} - with the fix/reject explanations on stdin. In this mode both commands return the review inline: read it, verify each finding, fix or reject it, and send a response until approval or escalation. To brainstorm a design with ${reviewer} before a task, use pair send request --brainstorm: each contribution comes back inline the same way, and you answer with pair send response until ${reviewer} completes it. If you delegate implementation, tell subagents not to run pair commands and to return their changes and validation results; you own the review loop, integrate their work here, and keep this checkout stable during each review round. Do not register, call pair_listen, or start idle waits in auto mode. ${FAILED_REVIEW_RULE.replaceAll("{{AGENT}}", options.author)} For interactive Claude Code, run managed send and retry commands with run_in_background: true in the Bash tool, end your turn, and read their output on the completion notification. A reviewer can take longer than the foreground Bash timeout; backgrounding the active review command is different from idle polling. Do not start your own reviewer processes. Wait for the user's task.`; // The user's options go first; codex gets -- before the prompt so a multi-value option like --image can't take it. const authorArgs = options.author === "claude" ? [ From b51bdbfbbf85088dc98b673d294e315adc99cfe3 Mon Sep 17 00:00:00 2001 From: Leon Lee Date: Fri, 6 Nov 2026 17:43:48 +0900 Subject: [PATCH 2/3] Cover separate PRs in the author prompt, split the PR rule out, record the decision in DESIGN Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012Y3kg5hjT2zSZM9qUEEinM --- DESIGN.md | 1 + prompts/pair.md | 1 + src/auto.ts | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/DESIGN.md b/DESIGN.md index 7f09820..132ad19 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -19,6 +19,7 @@ a chat channel. In manual mode, each runs as a live session in its own terminal. | Brainstorms | `pair send request --brainstorm` opens a thread for ideas in the author's lane. The reviewer replies `continue` or `complete` instead of `approve` or `changes`. Its statuses are `brainstorming` and `completed`, and the kind comes from the status, so pair ≤ 0.7.4 rejects the request as corrupt and can't review it as code; both agents need 0.8.0. The request stores `budget:`, `PAIR_MAX_ROUNDS` when it opened, so the agents' shells can't disagree on it; on the last round `continue` is refused. It never escalates. | | Disputes | Cap of 3 rounds (`PAIR_MAX_ROUNDS`). A review that still says `changes` at the cap marks the thread `escalated`, and both agents stop to ask the user. | | Concurrency | At most one open thread per direction. | +| Delegation | A subagent inherits the author's pair environment, so the instructions make the parent own the pair loop: subagents return changes without running pair, the parent integrates them (or reviews separate PRs one at a time) in the session's worktree and keeps it stable during each round. Several threads per lane wouldn't stop files moving under a reviewer. One owner serving reviews for subagent worktrees is planned separately. | | Storage | `~/.pair/-/` (or `$PAIR_HOME`). The hash comes from `git rev-parse --show-toplevel`, so each worktree gets its own channel. A reviewer reads the author's files, so both agents must run in the same worktree, and parallel pairs in different worktrees stay isolated. | | Format | Markdown files with flat YAML frontmatter that the CLI writes. Findings go in the body. | diff --git a/prompts/pair.md b/prompts/pair.md index a83ae69..9c28166 100644 --- a/prompts/pair.md +++ b/prompts/pair.md @@ -15,6 +15,7 @@ where pair's instructions may be missing. Integrate the changes into this sessio request review of the combined change. Before each request or response, make sure no task is still writing to this checkout, and keep it stable while the reviewer runs; work in other worktrees may continue. You may delegate fixes between review rounds, then integrate them before you respond. + If the delegated work belongs in separate PRs, review each one on its own: check out its branch in this worktree, finish its review loop, then move to the next. Git refuses a branch still checked out in another worktree; once its work is committed and no task is using it, remove that worktree diff --git a/src/auto.ts b/src/auto.ts index 3b02e51..e938308 100644 --- a/src/auto.ts +++ b/src/auto.ts @@ -784,7 +784,7 @@ export async function startAuto(options: AutoOptions): Promise { heartbeat = setInterval(() => sendGuardian({ type: "heartbeat" }), 1000); for (const name of ["SIGINT", "SIGTERM", "SIGHUP"] as const) process.on(name, signal); // No run-specific path: Claude records the system prompt and reuses it when the conversation is resumed in a later run. - const authorPrompt = `You are the interactive author in pair auto mode, with ${reviewer} as your automatically managed reviewer. The pair CLI is "$PAIR_BIN", which the launcher sets for each run; use it in place of pair in every example below. Follow the pair review rules. After completing a task, feed a Markdown summary, review focus and file list through stdin to pair send request --as ${options.author} -. Follow-up replies use pair send response --as ${options.author} - with the fix/reject explanations on stdin. In this mode both commands return the review inline: read it, verify each finding, fix or reject it, and send a response until approval or escalation. To brainstorm a design with ${reviewer} before a task, use pair send request --brainstorm: each contribution comes back inline the same way, and you answer with pair send response until ${reviewer} completes it. If you delegate implementation, tell subagents not to run pair commands and to return their changes and validation results; you own the review loop, integrate their work here, and keep this checkout stable during each review round. Do not register, call pair_listen, or start idle waits in auto mode. ${FAILED_REVIEW_RULE.replaceAll("{{AGENT}}", options.author)} For interactive Claude Code, run managed send and retry commands with run_in_background: true in the Bash tool, end your turn, and read their output on the completion notification. A reviewer can take longer than the foreground Bash timeout; backgrounding the active review command is different from idle polling. Do not start your own reviewer processes. Wait for the user's task.`; + const authorPrompt = `You are the interactive author in pair auto mode, with ${reviewer} as your automatically managed reviewer. The pair CLI is "$PAIR_BIN", which the launcher sets for each run; use it in place of pair in every example below. Follow the pair review rules. After completing a task, feed a Markdown summary, review focus and file list through stdin to pair send request --as ${options.author} -. Follow-up replies use pair send response --as ${options.author} - with the fix/reject explanations on stdin. In this mode both commands return the review inline: read it, verify each finding, fix or reject it, and send a response until approval or escalation. To brainstorm a design with ${reviewer} before a task, use pair send request --brainstorm: each contribution comes back inline the same way, and you answer with pair send response until ${reviewer} completes it. If you delegate implementation, tell subagents not to run pair commands and to return their changes and validation results; you own the review loop, integrate their work here (or, for separate PRs, review each branch here in turn), and keep this checkout stable during each review round. Do not register, call pair_listen, or start idle waits in auto mode. ${FAILED_REVIEW_RULE.replaceAll("{{AGENT}}", options.author)} For interactive Claude Code, run managed send and retry commands with run_in_background: true in the Bash tool, end your turn, and read their output on the completion notification. A reviewer can take longer than the foreground Bash timeout; backgrounding the active review command is different from idle polling. Do not start your own reviewer processes. Wait for the user's task.`; // The user's options go first; codex gets -- before the prompt so a multi-value option like --image can't take it. const authorArgs = options.author === "claude" ? [ From 8c850aa36e49717f0dbbaa0eb1d81cecc6c54c99 Mon Sep 17 00:00:00 2001 From: Leon Lee Date: Fri, 6 Nov 2026 17:43:48 +0900 Subject: [PATCH 3/3] Release 0.8.1 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012Y3kg5hjT2zSZM9qUEEinM --- CHANGELOG.md | 15 +++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6096347..64509e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.8.1 (2026-11-06) + +The agents' instructions now cover parallel work with subagents. A subagent inherits the author's +pair environment, so following "when you finish a task, request a review" it could open a review +thread in a checkout other subagents were still editing, or in its own worktree, where no auto +session serves the request. A new Delegating work section tells the author that it owns the review +loop: subagents return their changes and validation results without running pair commands, the +author integrates them and keeps the checkout stable while the reviewer runs, and separate PRs are +reviewed one at a time in the session's worktree. A subagent is told not to run pair commands even +with the author's role in its environment. + +The auto author prompt says the same, and the README gains a Parallel work section. For PRs +reviewed in parallel, run one `pair start --worktree` session per PR. Instructions refresh in each +worktree on the next `send` or `wait`. + ## 0.8.0 (2026-11-06) Pair now covers more than code review: brainstorm a design, review the spec, then review the code diff --git a/package-lock.json b/package-lock.json index 99b6d32..a90a4c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "claude-codex-pair", - "version": "0.8.0", + "version": "0.8.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "claude-codex-pair", - "version": "0.8.0", + "version": "0.8.1", "license": "Unlicense", "bin": { "pair": "dist/pair.js" diff --git a/package.json b/package.json index e1510b1..e51f93d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claude-codex-pair", - "version": "0.8.0", + "version": "0.8.1", "description": "Claude Code and Codex review each other's work over a file-system chat channel", "keywords": [ "claude-code",