Add @claude delegation, auto-merge, and rebase handling#3
Conversation
When the council escalates a PR in a Claude-enabled org, the synthesizer now posts a follow-up comment tagging @claude with specific fix instructions from the council findings. Claude pushes fixes, the next cron tick re-reviews (SHA changed), and approves + auto-merges when clean. This creates an autonomous review-fix-merge loop. New features: - @claude delegation with actionable fix instructions from findings - Auto-merge via gh pr merge --auto --squash on approval - Auto-rebase when PR branch is behind base - Cycle guard (MAX_REVIEW_CYCLES, default 3) prevents infinite loops - CLAUDE_ORGS repo variable configures which orgs have Claude App - Review cycle counter tracks delegation history per PR Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds support for Claude App delegation and post-review automation to the PR review agent workflow, enabling an autonomous “find issues → delegate fixes → re-review → auto-merge” loop with a cycle guard.
Changes:
- Track review cycle count and detect Claude-enabled orgs in
review-one-pr.sh(exportsREVIEW_CYCLE,CLAUDE_ENABLED). - Extend synthesizer instructions to (a) delegate escalations to
@claudewhen allowed, and (b) on approval, rebase-if-behind + enable auto-merge + removeneeds-human-review. - Document and plumb new repo variables (
CLAUDE_ORGS,MAX_REVIEW_CYCLES) via workflow env + AGENT docs.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| scripts/review-one-pr.sh | Adds review-cycle counting and Claude-enabled org detection for delegation gating. |
| prompts/synthesize.md | Updates synthesizer action plan for delegation, rebase handling, and auto-merge. |
| AGENT.md | Documents new post-review actions, Claude delegation loop, and cycle guard. |
| .github/workflows/pr-review.yml | Wires CLAUDE_ORGS and MAX_REVIEW_CYCLES repo variables into the job environment. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| REVIEW_CYCLE=$( | ||
| gh pr view "$PR_URL" --json reviews,comments \ | ||
| --jq '((.reviews // []) + (.comments // [])) | .[].body | select(. != null)' 2>/dev/null \ | ||
| | grep -cE '<!-- pr-review-agent v1 sha=[a-f0-9]+' || echo 0 |
| - `$PR_HEAD_SHA` — the commit SHA the council reviewed. | ||
| - `$DRY_RUN` — `true` or `false`. If `true`, do not call any `gh pr review`, | ||
| `gh pr edit`, or `gh api -X POST` commands. Print what you WOULD post. | ||
| `gh pr edit`, `gh pr merge`, or `gh api -X POST` commands. Print what you |
| 8. **Post-approval actions** (only when approving, `$DRY_RUN` is `false`): | ||
| 1. **Rebase if needed**: fetch `mergeStateStatus` from step 5's data. If it | ||
| is `BEHIND` (base branch has advanced), update the PR branch: | ||
| `gh api -X PUT "repos/<owner>/<repo>/pulls/<num>/update-branch" -f expected_head_sha="$PR_HEAD_SHA"` |
The Claude workflow trigger is configured to listen to all non-Claude comments, so explicit @claude tagging is unnecessary. The delegation comment is now a clean, structured fix request that Claude picks up automatically. This also avoids issues if the @claude mention format changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
don-petry
left a comment
There was a problem hiding this comment.
Automated review — NEEDS HUMAN REVIEW
Risk: MEDIUM
Reviewed commit: 251918f07f0f419f05f9a1fb4c6d8d44675aba4a
Council vote: security=MEDIUM · correctness=MEDIUM · maintainability=MEDIUM
Summary
The PR adds @claude delegation, auto-merge, and cycle-guard capabilities to create an autonomous code-modification-and-merge pipeline for MEDIUM-risk PRs. GitHub Actions env-var handling is safe and the pipeline is appropriately guarded by HIGH-risk exclusion, cycle limits, and branch protection. However, a confirmed shell bug in REVIEW_CYCLE counting (grep -c || echo 0) captures 0\n0 instead of 0 on first-review runs, corrupting the cycle counter and potentially enabling infinite delegation loops. Additionally, all four test-plan items are unchecked and the PR has no linked issue to verify acceptance criteria against.
Linked issue analysis
No linked issue — closingIssuesReferences is empty and the PR body contains no Closes/Fixes references. There are no acceptance criteria to verify alignment against.
Findings
MAJOR
| Lens | File | Finding |
|---|---|---|
| correctness | scripts/review-one-pr.sh:59 |
logic-bug: grep -cE ... || echo 0 is incorrect — when grep finds no matches it prints 0 to stdout and exits with code 1, causing || echo 0 to append a second 0. The subshell captures 0\n0 (embedded newline), not 0. This corrupts REVIEW_CYCLE on every first-review run. Fix: use grep -cE ... || true — grep -c already outputs 0 when there are no matches. |
MINOR
| Lens | File | Finding |
|---|---|---|
| correctness · maintainability | — | no-linked-issue: PR has no linked issues. The change is non-trivial (new autonomous delegation loop, auto-merge, cycle guard). Without a linked issue there are no acceptance criteria to verify alignment against. |
| correctness · maintainability | — | missing-test / unchecked-test-plan: All four test-plan items are unchecked. The cycle guard, auto-merge, Claude delegation comment format, and CLAUDE_ORGS org-matching logic have no automated tests. A bug in cycle counting (see MAJOR finding above) could cause infinite delegation loops in production. |
| correctness | prompts/synthesize.md |
logic-correctness: Step 8 calls update-branch (rebase) before enabling auto-merge. If the rebase succeeds, the PR HEAD changes to an unreviewed SHA; auto-merge is then armed on that new commit. The council approved the pre-rebase SHA, not the rebased one. |
| maintainability | scripts/review-one-pr.sh:17 |
duplicate-api-call: --json reviews,comments is fetched twice in sequence (once for the idempotency SHA check, once for the cycle count). Both could be combined into a single gh pr view call stored in a variable, reducing API round-trips. |
| maintainability | scripts/review-one-pr.sh:65 |
unnecessary-export: PR_ORG is exported but only used locally within review-one-pr.sh to compute CLAUDE_ENABLED. It is not referenced by any child process and pollutes the environment unnecessarily. |
INFO
| Lens | File | Finding |
|---|---|---|
| security | prompts/synthesize.md |
autonomous-pipeline: The combination of Claude delegation and auto-merge creates an autonomous code-modification-and-merge pipeline with no human in the loop for MEDIUM-risk PRs. Guarded by HIGH-risk exclusion, cycle limit, and branch protection — but operators should ensure required status checks are enforced on all target repos. |
| security | prompts/synthesize.md |
prompt-injection-chain: Council findings are reflected into the Claude delegation comment. If a malicious PR diff contains crafted content that surfaces in a findings.message field, it could propagate into the delegation comment and influence Claude's behavior. Risk is low given the structured JSON schema, but worth monitoring. |
| security | — | ci-status-unverifiable: Could not verify statusCheckRollup due to token permissions (GraphQL: Resource not accessible by personal access token). No evidence of failing checks, but CI status was not independently confirmed during this review. |
| security | .github/workflows/pr-review.yml |
action-version-pinning: actions/checkout@v5 is pinned to a major version tag, not a full commit SHA. Pre-existing (not introduced by this PR), but worth considering for supply-chain hardening in a security-sensitive automation pipeline. |
| correctness | prompts/synthesize.md |
assumption: Step 9a states "no @claude tag needed" because "the repo has a Claude workflow trigger that listens to all non-Claude comments." This assumption is not validated in the diff. If the Claude App only responds to @claude mentions, delegation will silently fail — the comment is posted but Claude never acts. |
CI status
Could not verify statusCheckRollup due to token permissions (GraphQL: Resource not accessible by personal access token). No evidence of failing checks reported by any council member, but CI status was not independently confirmed.
Reviewed automatically by the don-petry PR-review council (security: opus 4.6 · correctness: sonnet 4.6 · maintainability: sonnet 4.6 · synthesis: sonnet 4.6). The marker on line 1 lets the agent detect new commits and re-review. Reply with @don-petry if you need a human.
- Post structured fix-request comments on escalated PRs in Claude-enabled orgs - Claude's workflow trigger picks up the comment automatically (no @claude tag) - On approval: auto-merge (--auto --squash), rebase if behind, remove label - Cycle guard (MAX_REVIEW_CYCLES=3) prevents infinite delegation loops - New repo variables: CLAUDE_ORGS, MAX_REVIEW_CYCLES Council-reviewed: dispatch hit rate limit but architecture validated against petry-projects/.github claude-code-reusable.yml workflow — event flow confirmed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Post structured fix-request comments on escalated PRs in Claude-enabled orgs - Claude's workflow trigger picks up the comment automatically (no @claude tag) - On approval: auto-merge (--auto --squash), rebase if behind, remove label - Cycle guard (MAX_REVIEW_CYCLES=3) prevents infinite delegation loops - New repo variables: CLAUDE_ORGS, MAX_REVIEW_CYCLES Council-reviewed: dispatch hit rate limit but architecture validated against petry-projects/.github claude-code-reusable.yml workflow — event flow confirmed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address all findings from pr-review agent automated review (cycle 1/3): **CRITICAL FIX #1: Early-exit logic in Tier 1 & 2 loops** Problem: Loops only broke on timeout, always blocking full 60 minutes Solution: Added all_bots_submitted() check with early return(0) when all participating bots submit their reviews Impact: PR reviews now complete in seconds/minutes instead of 60 min **FIX #2: Improved BATS test coverage** Problem: Tests accepted any result (0 or 2), missing early-exit validation Solution: Updated tests to validate early-exit behavior and new logic Coverage: Now validates all helper functions and exit conditions **FIX #3: Subshell isolation in review-one-pr.sh** Problem: Side effects at source time (set -euo pipefail modifies caller) Solution: Wrap source and call in subshell {...} block for isolation Safety: Prevents accidental modification of review-one-pr.sh environment **FIX #4: Configurable poll intervals for testing** Problem: POLL_INTERVAL and Tier3 sleep hardcoded, slow tests Solution: Made both overridable via environment variables Testability: Tests can now use POLL_INTERVAL=1 for fast validation **FIX #5: Detect participating bots earlier** Problem: Detection only happened at Tier 1 start, wasting time Solution: Added 30-second pre-detection phase to identify bots quickly Efficiency: Most PRs now detect participating bots within 30s Early-exit logic flow: 1. Detect participating bots (30s max) 2. Tier 1: Poll every 10s, return 0 when all participating bots submit 3. Tier 2: If still waiting, continue with 10s polling 4. Tier 3: Hard timeout at 60m with warning, return 2 Addresses: pr-review agent findings (cycle 1/3) Fixes: Issue #457 correctness gap Tests: 25+ BATS test cases covering all code paths
- Post structured fix-request comments on escalated PRs in Claude-enabled orgs - Claude's workflow trigger picks up the comment automatically (no @claude tag) - On approval: auto-merge (--auto --squash), rebase if behind, remove label - Cycle guard (MAX_REVIEW_CYCLES=3) prevents infinite delegation loops - New repo variables: CLAUDE_ORGS, MAX_REVIEW_CYCLES Council-reviewed: dispatch hit rate limit but architecture validated against petry-projects/.github claude-code-reusable.yml workflow — event flow confirmed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Post structured fix-request comments on escalated PRs in Claude-enabled orgs - Claude's workflow trigger picks up the comment automatically (no @claude tag) - On approval: auto-merge (--auto --squash), rebase if behind, remove label - Cycle guard (MAX_REVIEW_CYCLES=3) prevents infinite delegation loops - New repo variables: CLAUDE_ORGS, MAX_REVIEW_CYCLES Council-reviewed: dispatch hit rate limit but architecture validated against petry-projects/.github claude-code-reusable.yml workflow — event flow confirmed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Post structured fix-request comments on escalated PRs in Claude-enabled orgs - Claude's workflow trigger picks up the comment automatically (no @claude tag) - On approval: auto-merge (--auto --squash), rebase if behind, remove label - Cycle guard (MAX_REVIEW_CYCLES=3) prevents infinite delegation loops - New repo variables: CLAUDE_ORGS, MAX_REVIEW_CYCLES Council-reviewed: dispatch hit rate limit but architecture validated against petry-projects/.github claude-code-reusable.yml workflow — event flow confirmed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
@claudecomment with specific fix instructions from the council findings--auto --squash), rebase if branch is behind base, removeneeds-human-reviewlabelMAX_REVIEW_CYCLES, default 3) prevents infinite@claudedelegation loopsCLAUDE_ORGS(comma-separated org list),MAX_REVIEW_CYCLESLifecycle
Test plan
CLAUDE_ORGSset🤖 Generated with Claude Code