From da92bfe8202145a2f9771d6b5959455300017506 Mon Sep 17 00:00:00 2001 From: kristofferR Date: Fri, 3 Jul 2026 18:57:37 +0200 Subject: [PATCH 1/3] docs: run crq loop under a persistent task runner in agent harnesses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A crq loop wait can exceed an hour when the queue is deep or the account is rate-limited, and agent harnesses commonly kill plain background shell jobs between turns — the wait gets orphaned and looks like a hang. Document the pattern: run the loop under the harness's persistent long-running-task primitive (Claude Code: Monitor with persistent:true), redirect the findings JSON to a file, and emit a final CRQ_EXIT: line as the completion event. Also note that a killed runner loses nothing — the PR stays enqueued and re-running crq loop re-attaches idempotently. Claude-Session: https://claude.ai/code/session_01BgW8cjUycHYKDZWaiRSLXY --- llms.txt | 7 +++++++ skills/coderabbit-queue/SKILL.md | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/llms.txt b/llms.txt index 10c9cd5..bda762f 100644 --- a/llms.txt +++ b/llms.txt @@ -76,6 +76,13 @@ non-outdated review threads), so no manual cross-review audit is needed. Long waits are not hangs. During queue/rate-limit waits, missing required-bot reviews, and network/GitHub outages, crq logs progress to stderr; stdout stays reserved for the final JSON. +Keep the loop alive: harnesses often kill plain background shell jobs between agent turns, which +orphans the wait. Run `crq loop` under the harness's persistent long-running-task primitive (in +Claude Code: the Monitor tool with `persistent: true`, e.g. +`crq loop OWNER/REPO PR > crq-feedback.json; echo "CRQ_EXIT:$?"` so the exit line is the completion +event). If a runner is killed anyway, the PR stays enqueued — re-running the same `crq loop` is +idempotent and re-attaches to the wait. Never replace the runner with a `crq status` polling loop. + Agent communication rule: do not relay every stderr progress line or send repeated "still waiting" updates. Tell the user once when a long `crq loop` wait begins, then stay quiet until the state changes (fired, feedback wait, findings, convergence, timeout, rate-limit/window change, network diff --git a/skills/coderabbit-queue/SKILL.md b/skills/coderabbit-queue/SKILL.md index c525a56..678e8d2 100644 --- a/skills/coderabbit-queue/SKILL.md +++ b/skills/coderabbit-queue/SKILL.md @@ -67,6 +67,29 @@ Long waits are expected when the queue is blocked, GitHub is rate-limited, a req reviewed yet, or the network is down. crq logs progress to stderr; do not kill it just because stdout is quiet. +## Keeping the Loop Alive in an Agent Harness + +A single `crq loop` call can wait an hour or more when the queue is deep or the account is +rate-limited. Agent harnesses commonly kill plain background shell jobs between turns, which +silently orphans the wait. Run `crq loop` under the harness's *persistent* long-running-task +primitive instead of a fire-and-forget background shell. In Claude Code that is the Monitor tool +with `persistent: true`, redirecting the findings JSON to a file and emitting one final event line: + +``` +Monitor({ + command: 'crq loop OWNER/REPO PR > /path/to/crq-feedback.json; echo "CRQ_EXIT:$?"', + description: 'crq review loop on OWNER/REPO#PR', + persistent: true, +}) +``` + +The `CRQ_EXIT:` line is the completion event (map it to the exit codes above); crq's stderr +progress stays in the task's output file for diagnosis without generating event noise. + +If a loop runner is killed anyway, nothing is lost: the PR stays enqueued. Re-running the same +`crq loop` command is safe and re-attaches to the wait — enqueueing is idempotent. Do not +substitute a hand-rolled `crq status` polling loop for the runner. + User-facing updates must be sparse during those waits. Do not narrate every stderr progress line or send repeated "still waiting" messages. Say once that `crq loop` is waiting, then update only when the state changes (review fired, feedback wait started, findings arrived, convergence, timeout, From 9c0cba7047528e5ecb0decc4355dccd7caea266e Mon Sep 17 00:00:00 2001 From: kristofferR Date: Fri, 3 Jul 2026 22:47:50 +0200 Subject: [PATCH 2/3] Disable errexit before emitting CRQ_EXIT in loop runner docs The documented Monitor command relies on echoing crq loop's exit code as the completion event, but crq loop intentionally exits non-zero for actionable outcomes (10 = findings, 2 = timeout). Under an inherited set -e the shell dies before the echo and the event never arrives. Claude-Session: https://claude.ai/code/session_01W4RViwpNDBmT2fs3qhQNx7 --- llms.txt | 6 ++++-- skills/coderabbit-queue/SKILL.md | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/llms.txt b/llms.txt index bda762f..d284de3 100644 --- a/llms.txt +++ b/llms.txt @@ -79,8 +79,10 @@ network/GitHub outages, crq logs progress to stderr; stdout stays reserved for t Keep the loop alive: harnesses often kill plain background shell jobs between agent turns, which orphans the wait. Run `crq loop` under the harness's persistent long-running-task primitive (in Claude Code: the Monitor tool with `persistent: true`, e.g. -`crq loop OWNER/REPO PR > crq-feedback.json; echo "CRQ_EXIT:$?"` so the exit line is the completion -event). If a runner is killed anyway, the PR stays enqueued — re-running the same `crq loop` is +`set +e; crq loop OWNER/REPO PR > crq-feedback.json; echo "CRQ_EXIT:$?"` so the exit line is the +completion event — the `set +e` keeps an errexit shell from dying on the meaningful non-zero exits +(10 = findings, 2 = timeout) before it can echo). If a runner is killed anyway, the PR stays +enqueued — re-running the same `crq loop` is idempotent and re-attaches to the wait. Never replace the runner with a `crq status` polling loop. Agent communication rule: do not relay every stderr progress line or send repeated "still waiting" diff --git a/skills/coderabbit-queue/SKILL.md b/skills/coderabbit-queue/SKILL.md index 678e8d2..9cdcf27 100644 --- a/skills/coderabbit-queue/SKILL.md +++ b/skills/coderabbit-queue/SKILL.md @@ -77,12 +77,16 @@ with `persistent: true`, redirecting the findings JSON to a file and emitting on ``` Monitor({ - command: 'crq loop OWNER/REPO PR > /path/to/crq-feedback.json; echo "CRQ_EXIT:$?"', + command: 'set +e; crq loop OWNER/REPO PR > /path/to/crq-feedback.json; echo "CRQ_EXIT:$?"', description: 'crq review loop on OWNER/REPO#PR', persistent: true, }) ``` +The `set +e` matters: `crq loop` reports actionable outcomes as non-zero exits (10 = findings, +2 = timeout), and a shell with errexit inherited would exit before the `echo` — the completion +event would never arrive even though `crq-feedback.json` was written. + The `CRQ_EXIT:` line is the completion event (map it to the exit codes above); crq's stderr progress stays in the task's output file for diagnosis without generating event noise. From 8408260337dd755332c3914a886ba97b14647f68 Mon Sep 17 00:00:00 2001 From: kristofferR Date: Sat, 4 Jul 2026 10:26:15 +0200 Subject: [PATCH 3/3] Add language tag to the Monitor example fence Claude-Session: https://claude.ai/code/session_01W4RViwpNDBmT2fs3qhQNx7 --- skills/coderabbit-queue/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/coderabbit-queue/SKILL.md b/skills/coderabbit-queue/SKILL.md index 9cdcf27..a26019b 100644 --- a/skills/coderabbit-queue/SKILL.md +++ b/skills/coderabbit-queue/SKILL.md @@ -75,7 +75,7 @@ silently orphans the wait. Run `crq loop` under the harness's *persistent* long- primitive instead of a fire-and-forget background shell. In Claude Code that is the Monitor tool with `persistent: true`, redirecting the findings JSON to a file and emitting one final event line: -``` +```js Monitor({ command: 'set +e; crq loop OWNER/REPO PR > /path/to/crq-feedback.json; echo "CRQ_EXIT:$?"', description: 'crq review loop on OWNER/REPO#PR',