From e545cffc40db3421c7120d99b801d775566a98c8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 16:06:28 +0000 Subject: [PATCH 01/11] feat: add posttool-pr-created hook to remind agent to invoke pr-monitoring after gh pr create Agent-Logs-Url: https://github.com/GoCodeAlone/claude-superpowers/sessions/4b58f439-58b7-48be-9e21-fdb5c4975ac5 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- hooks/hooks.json | 10 +++ hooks/posttool-pr-created | 66 +++++++++++++++++++ .../finishing-a-development-branch/SKILL.md | 2 +- 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100755 hooks/posttool-pr-created diff --git a/hooks/hooks.json b/hooks/hooks.json index 219bb35..7e6fe57 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -34,6 +34,16 @@ "timeout": 10 } ] + }, + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": "'${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd' posttool-pr-created", + "timeout": 10 + } + ] } ], "UserPromptSubmit": [ diff --git a/hooks/posttool-pr-created b/hooks/posttool-pr-created new file mode 100755 index 0000000..a0135ba --- /dev/null +++ b/hooks/posttool-pr-created @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# hooks/posttool-pr-created +# PostToolUse hook: reminds the agent to invoke pr-monitoring after gh pr create. +# +# Fires whenever a Bash tool call contains "gh pr create". Extracts the PR +# URL from the tool response (if present) and injects an IMPORTANT reminder +# that pr-monitoring must be started immediately for the new PR. +# +# Why this exists: agents sometimes bypass the finishing-a-development-branch +# skill chain and run gh pr create directly. Without the skill chain the +# automatic "invoke pr-monitoring" step never fires, leaving CI failures and +# bot review comments unattended. This hook closes that gap by triggering +# the reminder mechanically — regardless of which code path created the PR. +# +# Global opt-out: set SUPERPOWERS_HOOKS_DISABLE=1 + +set -euo pipefail + +[ "${SUPERPOWERS_HOOKS_DISABLE:-}" = "1" ] && exit 0 + +# Require stdin (PostToolUse always sends a JSON payload). +[ -t 0 ] && exit 0 +command -v jq >/dev/null 2>&1 || exit 0 + +hook_input=$(cat || true) +[ -z "$hook_input" ] && exit 0 + +tool_name=$(printf '%s' "$hook_input" | jq -r '.tool_name // empty' 2>/dev/null || true) +[ "$tool_name" != "Bash" ] && exit 0 + +cmd=$(printf '%s' "$hook_input" | jq -r '.tool_input.command // empty' 2>/dev/null || true) +[ -z "$cmd" ] && exit 0 + +# Only act when the command created a PR (not a simple `gh pr list`, etc.). +printf '%s' "$cmd" | grep -q 'gh pr create' || exit 0 + +# Try to extract the PR URL from the tool response so the reminder is specific. +tool_response=$(printf '%s' "$hook_input" | jq -r '.tool_response // empty' 2>/dev/null || true) +pr_url=$(printf '%s' "$tool_response" \ + | grep -oE 'https://github\.com/[^[:space:]]+/pull/[0-9]+' \ + | head -1 || true) + +if [ -n "$pr_url" ]; then + pr_hint="for the PR you just created: ${pr_url}" +else + pr_hint="for the PR you just created" +fi + +# Escape a string for embedding inside a JSON string value. +escape_for_json() { + local s="$1" + s="${s//\\/\\\\}" + s="${s//\"/\\\"}" + s="${s//$'\n'/\\n}" + s="${s//$'\r'/\\r}" + s="${s//$'\t'/\\t}" + printf '%s' "$s" +} + +reminder="You just ran \`gh pr create\`. You MUST now invoke \`superpowers:pr-monitoring\` ${pr_hint}. Use a SINGLE monitoring agent that covers ALL PRs you have created in this session — do not spawn one agent per PR, as that risks rate-limiting. Draft PRs still trigger CI and receive bot reviews, so monitoring is required regardless of draft state. Do NOT declare the task complete until pr-monitoring has been started. See superpowers:pr-monitoring for usage." + +escaped=$(escape_for_json "$reminder") + +printf '{"additional_context":"%s"}\n' "$escaped" + +exit 0 diff --git a/skills/finishing-a-development-branch/SKILL.md b/skills/finishing-a-development-branch/SKILL.md index 2a3cec7..c70d8dd 100644 --- a/skills/finishing-a-development-branch/SKILL.md +++ b/skills/finishing-a-development-branch/SKILL.md @@ -61,7 +61,7 @@ When running in the autonomous pipeline (invoked from subagent-driven-developmen EOF )" ``` -5. **Invoke pr-monitoring** — spawn one background monitor per PR created +5. **Invoke pr-monitoring** — spawn a single background monitor that covers all PRs created in this session 6. **Report PR URLs** — output every PR link for the user (one per row in the manifest's PR Grouping table) **Do NOT:** From ac0c1e6838b33546534008c4cce73874855585d4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 16:07:00 +0000 Subject: [PATCH 02/11] style: break long reminder string into multi-line concatenation for readability Agent-Logs-Url: https://github.com/GoCodeAlone/claude-superpowers/sessions/4b58f439-58b7-48be-9e21-fdb5c4975ac5 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- hooks/posttool-pr-created | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hooks/posttool-pr-created b/hooks/posttool-pr-created index a0135ba..bbfc3c6 100755 --- a/hooks/posttool-pr-created +++ b/hooks/posttool-pr-created @@ -57,7 +57,15 @@ escape_for_json() { printf '%s' "$s" } -reminder="You just ran \`gh pr create\`. You MUST now invoke \`superpowers:pr-monitoring\` ${pr_hint}. Use a SINGLE monitoring agent that covers ALL PRs you have created in this session — do not spawn one agent per PR, as that risks rate-limiting. Draft PRs still trigger CI and receive bot reviews, so monitoring is required regardless of draft state. Do NOT declare the task complete until pr-monitoring has been started. See superpowers:pr-monitoring for usage." +reminder="" +reminder+="You just ran \`gh pr create\`. " +reminder+="You MUST now invoke \`superpowers:pr-monitoring\` ${pr_hint}. " +reminder+="Use a SINGLE monitoring agent that covers ALL PRs you have created in this session" +reminder+=" — do not spawn one agent per PR, as that risks rate-limiting. " +reminder+="Draft PRs still trigger CI and receive bot reviews, so monitoring is required regardless of draft state. " +reminder+="Do NOT declare the task complete until pr-monitoring has been started. " +reminder+="See superpowers:pr-monitoring for usage." +reminder+="" escaped=$(escape_for_json "$reminder") From 3288aee562b3999af51099bc6093ad7619f89836 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 16:08:43 +0000 Subject: [PATCH 03/11] feat: add pretool-pr-review-reminder hook to require Copilot reviewer on gh pr create Agent-Logs-Url: https://github.com/GoCodeAlone/claude-superpowers/sessions/4b58f439-58b7-48be-9e21-fdb5c4975ac5 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- hooks/hooks.json | 10 ++++++ hooks/pretool-pr-review-reminder | 55 ++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100755 hooks/pretool-pr-review-reminder diff --git a/hooks/hooks.json b/hooks/hooks.json index 7e6fe57..6b82988 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -22,6 +22,16 @@ "timeout": 15 } ] + }, + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": "'${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd' pretool-pr-review-reminder", + "timeout": 10 + } + ] } ], "PostToolUse": [ diff --git a/hooks/pretool-pr-review-reminder b/hooks/pretool-pr-review-reminder new file mode 100755 index 0000000..958aaf6 --- /dev/null +++ b/hooks/pretool-pr-review-reminder @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# hooks/pretool-pr-review-reminder +# PreToolUse hook: blocks gh pr create unless --reviewer Copilot is included. +# +# When an agent runs gh pr create without requesting Copilot as a reviewer the +# PR is created without automated code review. This hook intercepts the command +# before it runs and blocks it with a clear instruction to add the flag, so the +# agent retries with Copilot in the reviewer list. +# +# Copilot is specified as a reviewer with --reviewer Copilot (the exact handle +# GitHub uses for its built-in AI code-review feature). +# +# Global opt-out: set SUPERPOWERS_HOOKS_DISABLE=1 + +set -euo pipefail + +[ "${SUPERPOWERS_HOOKS_DISABLE:-}" = "1" ] && exit 0 + +# Require stdin (PreToolUse always sends a JSON payload). +[ -t 0 ] && exit 0 +command -v jq >/dev/null 2>&1 || exit 0 + +hook_input=$(cat || true) +[ -z "$hook_input" ] && exit 0 + +tool_name=$(printf '%s' "$hook_input" | jq -r '.tool_name // empty' 2>/dev/null || true) +[ "$tool_name" != "Bash" ] && exit 0 + +cmd=$(printf '%s' "$hook_input" | jq -r '.tool_input.command // empty' 2>/dev/null || true) +[ -z "$cmd" ] && exit 0 + +# Only act on PR creation commands. +printf '%s' "$cmd" | grep -q 'gh pr create' || exit 0 + +# Pass through if Copilot is already listed as a reviewer. +# Matches: --reviewer Copilot --reviewer=Copilot (case-insensitive on "copilot") +if printf '%s' "$cmd" | grep -qiE -- '--reviewer[[:space:]=][^[:space:]]*copilot'; then + exit 0 +fi + +block() { + local reason="$1" + printf '{"decision":"block","reason":%s}\n' \ + "$(printf '%s' "$reason" | jq -Rs .)" + exit 2 +} + +block "Add Copilot as a code reviewer before creating this PR. +Re-run the command with: --reviewer Copilot + +Example: + gh pr create --title \"...\" --body \"...\" --reviewer Copilot + +Copilot reviews run automatically on the PR diff and catch issues before +human reviewers see the PR. Do not skip this flag." From e428848ca825b4e1149eb3b19a69cdc4e9c18dbb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 16:10:32 +0000 Subject: [PATCH 04/11] feat: monitor resolves bot review threads after addressing them Agent-Logs-Url: https://github.com/GoCodeAlone/claude-superpowers/sessions/4b58f439-58b7-48be-9e21-fdb5c4975ac5 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- hooks/pretool-pr-review-reminder | 2 +- skills/pr-monitoring/SKILL.md | 52 +++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/hooks/pretool-pr-review-reminder b/hooks/pretool-pr-review-reminder index 958aaf6..9717f58 100755 --- a/hooks/pretool-pr-review-reminder +++ b/hooks/pretool-pr-review-reminder @@ -34,7 +34,7 @@ printf '%s' "$cmd" | grep -q 'gh pr create' || exit 0 # Pass through if Copilot is already listed as a reviewer. # Matches: --reviewer Copilot --reviewer=Copilot (case-insensitive on "copilot") -if printf '%s' "$cmd" | grep -qiE -- '--reviewer[[:space:]=][^[:space:]]*copilot'; then +if printf '%s' "$cmd" | grep -qiE -- '--reviewer[[:space:]=]copilot'; then exit 0 fi diff --git a/skills/pr-monitoring/SKILL.md b/skills/pr-monitoring/SKILL.md index fb17911..2752dd8 100644 --- a/skills/pr-monitoring/SKILL.md +++ b/skills/pr-monitoring/SKILL.md @@ -62,20 +62,62 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): ### 2. Check Review Comments + Use GraphQL to fetch review threads — this gives both the thread IDs needed + for resolution and the author login needed to detect bots: + + ```bash + gh api graphql -f query=' + query($owner: String!, $repo: String!, $number: Int!) { + repository(owner: $owner, name: $repo) { + pullRequest(number: $number) { + reviewThreads(first: 100) { + nodes { + id + isResolved + isOutdated + comments(first: 1) { + nodes { author { login } body } + } + } + } + } + } + } + ' -f owner= -f repo= -F number= + ``` + + Also fetch any "CHANGES_REQUESTED" reviews: + ```bash - gh api repos///pulls//comments --jq '.[] | select(.position != null) | {id, body, path, line: .original_line, user: .user.login}' - gh api repos///pulls//reviews --jq '.[] | select(.state == "CHANGES_REQUESTED") | {id, body, user: .user.login}' + gh api repos///pulls//reviews \ + --jq '.[] | select(.state == "CHANGES_REQUESTED") | {id, body, user: .user.login}' ``` - **If new unresolved comments found:** + **Bot detection:** treat a commenter as a bot if their login ends in `[bot]` + or matches a known review bot (e.g. `copilot`, `github-advanced-security`, + `datadog`, `codeclimate`, `sonarcloud`). Apply the same address-then-resolve + flow to bot comments as to human comments. + + **If new unresolved, non-outdated threads are found:** a. Read the comment carefully b. Implement the requested change c. Run tests to verify d. Commit and push e. Reply to the comment: "Addressed in " + f. **Resolve the thread** (required for all comments, especially bot comments): + ```bash + gh api graphql -f query=' + mutation($threadId: ID!) { + resolveReviewThread(input: {threadId: $threadId}) { + thread { isResolved } + } + } + ' -f threadId="" + ``` **Safety:** Max 3 revision rounds per review comment. After 3, reply: "I've attempted to address this feedback but may need clarification. Flagging for manual review." + Then resolve the thread so it does not block the exit condition. ### 3. Check Exit Conditions @@ -99,10 +141,10 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): Use your host's equivalent mechanism to periodically poll the following in a loop: - `gh pr checks ` — fix any failing CI checks -- `gh api repos///pulls//comments` — respond to inline review comments +- GraphQL `reviewThreads` query — fetch unresolved, non-outdated threads; address each one, reply "Addressed in ", then resolve the thread via the `resolveReviewThread` GraphQL mutation. Apply this to bot comments (any login ending in `[bot]`, or known bots such as `copilot`, `github-advanced-security`, `datadog`) the same as human comments. - `gh api repos///pulls//reviews` — handle any "CHANGES_REQUESTED" reviews -Continue until all checks pass, no unresolved inline comments remain, and no "changes requested" reviews are pending. +Continue until all checks pass, no unresolved inline threads remain, and no "changes requested" reviews are pending. When the PR has merged with green base-branch CI and a design + plan exist in `docs/plans/` for this branch, invoke `superpowers:post-merge-retrospective` to write a retro in `docs/retros/`. If the PR was closed without merge, skip the retro and exit cleanly. From 5148c823b7d073000c91be5e791b699124bc578a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 16:12:41 +0000 Subject: [PATCH 05/11] fix: handle comma-separated reviewer lists in pretool-pr-review-reminder regex Agent-Logs-Url: https://github.com/GoCodeAlone/claude-superpowers/sessions/4b58f439-58b7-48be-9e21-fdb5c4975ac5 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- hooks/pretool-pr-review-reminder | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hooks/pretool-pr-review-reminder b/hooks/pretool-pr-review-reminder index 9717f58..e0faa2e 100755 --- a/hooks/pretool-pr-review-reminder +++ b/hooks/pretool-pr-review-reminder @@ -33,8 +33,13 @@ cmd=$(printf '%s' "$hook_input" | jq -r '.tool_input.command // empty' 2>/dev/nu printf '%s' "$cmd" | grep -q 'gh pr create' || exit 0 # Pass through if Copilot is already listed as a reviewer. -# Matches: --reviewer Copilot --reviewer=Copilot (case-insensitive on "copilot") -if printf '%s' "$cmd" | grep -qiE -- '--reviewer[[:space:]=]copilot'; then +# Handles all gh reviewer syntaxes (case-insensitive on "copilot"): +# --reviewer Copilot +# --reviewer=Copilot +# --reviewer user1,Copilot (copilot after a comma-separated peer) +# --reviewer Copilot,user2 (copilot before a comma-separated peer) +# --reviewer user1 --reviewer Copilot (multiple flags; second flag matched) +if printf '%s' "$cmd" | grep -qiE -- '--reviewer[[:space:]=]([^[:space:]]*,)*copilot'; then exit 0 fi From 6db8aa58f6263dd02b987d202fe2e1554bb37aa0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 16:19:18 +0000 Subject: [PATCH 06/11] =?UTF-8?q?feat:=20tune=20pr-monitoring=20=E2=80=94?= =?UTF-8?q?=20worktrees,=2010-min=20poll,=2060-min=20cap,=20timeout=20rest?= =?UTF-8?q?art?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/GoCodeAlone/claude-superpowers/sessions/0819218d-f7ef-40c8-ae9a-7962ca512562 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- hooks/posttool-pr-created | 4 +- skills/pr-monitoring/SKILL.md | 148 ++++++++++++++++++++++++++-------- 2 files changed, 115 insertions(+), 37 deletions(-) diff --git a/hooks/posttool-pr-created b/hooks/posttool-pr-created index bbfc3c6..73137da 100755 --- a/hooks/posttool-pr-created +++ b/hooks/posttool-pr-created @@ -60,8 +60,8 @@ escape_for_json() { reminder="" reminder+="You just ran \`gh pr create\`. " reminder+="You MUST now invoke \`superpowers:pr-monitoring\` ${pr_hint}. " -reminder+="Use a SINGLE monitoring agent that covers ALL PRs you have created in this session" -reminder+=" — do not spawn one agent per PR, as that risks rate-limiting. " +reminder+="Prefer a SINGLE monitoring agent that covers ALL PRs you have created in this session " +reminder+="to avoid GitHub API rate limits — but you may use one agent per PR if the situation warrants it. " reminder+="Draft PRs still trigger CI and receive bot reviews, so monitoring is required regardless of draft state. " reminder+="Do NOT declare the task complete until pr-monitoring has been started. " reminder+="See superpowers:pr-monitoring for usage." diff --git a/skills/pr-monitoring/SKILL.md b/skills/pr-monitoring/SKILL.md index 2752dd8..7649f0b 100644 --- a/skills/pr-monitoring/SKILL.md +++ b/skills/pr-monitoring/SKILL.md @@ -7,7 +7,7 @@ description: Use after creating a PR to automatically monitor CI checks and revi ## Overview -Monitor a pull request for CI failures and review comments, automatically fixing issues and pushing updates. Runs as a background agent after autonomous PR creation. +Monitor a pull request (or a set of PRs) for CI failures and review comments, automatically fixing issues and pushing updates. Runs as a background agent after autonomous PR creation. **Core principle:** The PR is the final quality gate. Monitor it, fix what breaks, respond to feedback — all without human intervention. @@ -15,30 +15,59 @@ Monitor a pull request for CI failures and review comments, automatically fixing Invoked automatically by `finishing-a-development-branch` in autonomous mode after creating a PR. Can also be invoked manually for any open PR. +## Single Agent vs. One Agent per PR + +When multiple PRs were created in the same session, prefer launching **one monitor agent that covers all PRs** to reduce GitHub API request volume. You may launch one agent per PR instead if the PRs are on unrelated codebases, if you anticipate heavy parallel CI load, or if a previous shared monitor was rate-limited. Default to the single-agent approach and only deviate with a reason. + ## The Process -Run a `balanced`-tier agent that monitors the PR in a loop until all CI checks pass and no unresolved reviews remain. +Run a `balanced`-tier agent that monitors PRs in a loop for up to **60 minutes**, polling every **10 minutes**, until all CI checks pass and no unresolved reviews remain. Use the Agent tool to run the monitor in the background: ```` Agent tool (general-purpose, model: balanced, run_in_background: true): - description: "Monitor PR #N for CI and reviews" + description: "Monitor PR(s) for CI and reviews" prompt: | - You are monitoring PR # on and automatically fixing issues. + You are monitoring one or more pull requests and automatically fixing issues. ## Setup - PR URL: - Branch: - Base: - Design doc: - Plan doc: + PRs to monitor (repeat the loop below for each): + | PR # | URL | Branch | Base | Design doc | Plan doc | + |------|-----|--------|------|------------|----------| + | | | | | | | + + ## Worktree Setup + + Before starting the loop, ensure every branch has its own git worktree so + you never need to `git checkout` mid-session (which would discard in-flight + changes on the current branch): + + ```bash + # For each PR branch that doesn't already have a worktree: + git worktree add ../-monitor + ``` + + When working on a fix for PR #N, `cd` into that branch's worktree directory. + Always confirm which branch you are on with `git branch --show-current` before + making any edits, commits, or pushes. + + ## Session Limits + + - **Maximum session duration:** 60 minutes from when this agent starts. + - **Poll interval:** 10 minutes between full check cycles across all PRs. + - Track elapsed time; when fewer than 10 minutes remain, finish the current + cycle and then write the timeout status report (see step 3) before exiting. + + ## Monitor Loop + + Repeat until exit conditions are met or the 60-minute session limit is reached: - Repeat the Monitor Loop until exit conditions are met: + ### 1. Check CI Status (per PR) - ### 1. Check CI Status + For each PR: ```bash gh pr checks --json name,state,conclusion @@ -47,20 +76,25 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): **If any check fails:** a. Read the failure logs: `gh run view --log-failed` b. Identify the root cause - c. Fix the issue in the codebase - d. Run the relevant tests locally to verify - e. Commit and push: + c. `cd` into that PR's worktree directory and confirm the branch: + ```bash + cd ../-monitor + git branch --show-current # must equal + ``` + d. Fix the issue in the codebase + e. Run the relevant tests locally to verify + f. Commit and push: ```bash git add git commit -m "fix: address CI failure in " git push ``` - f. Wait 60s, re-check + g. Return to the next PR in the loop **Safety:** Max 5 fix attempts per unique CI failure. After 5, comment on the PR: "Unable to automatically resolve CI failure in after 5 attempts. Manual intervention needed." - ### 2. Check Review Comments + ### 2. Check Review Comments (per PR) Use GraphQL to fetch review threads — this gives both the thread IDs needed for resolution and the author login needed to detect bots: @@ -100,11 +134,16 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): **If new unresolved, non-outdated threads are found:** a. Read the comment carefully - b. Implement the requested change - c. Run tests to verify - d. Commit and push - e. Reply to the comment: "Addressed in " - f. **Resolve the thread** (required for all comments, especially bot comments): + b. `cd` into that PR's worktree directory and confirm the branch: + ```bash + cd ../-monitor + git branch --show-current # must equal + ``` + c. Implement the requested change + d. Run tests to verify + e. Commit and push + f. Reply to the comment: "Addressed in " + g. **Resolve the thread** (required for all comments, especially bot comments): ```bash gh api graphql -f query=' mutation($threadId: ID!) { @@ -121,32 +160,63 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): ### 3. Check Exit Conditions - Exit when ALL of: + A PR is **complete** when ALL of: - All CI checks passing (green) - No unresolved review comments - No pending "changes requested" reviews - On exit: - - If the PR is merged AND base-branch CI is green for the merge commit AND a design + plan exist in `docs/plans/` for this branch, invoke `superpowers:post-merge-retrospective` to produce a retro in `docs/retros/`. This is the autonomous closing-the-loop step. - - If the PR is closed without merge, skip the retrospective and exit cleanly. - - Report final status either way. + **On all PRs complete (clean exit):** + - For each PR that is merged AND whose base-branch CI is green for the merge + commit AND that has a design + plan in `docs/plans/` for its branch, invoke + `superpowers:post-merge-retrospective` to produce a retro in `docs/retros/`. + - Report final status. + + **On session timeout (60-minute limit reached):** + Write a status report to stdout in this format so the orchestrator can decide + whether to restart: + + ``` + PR-MONITOR TIMEOUT REPORT + Elapsed: ~60 min + PRs still needing attention: + - PR # : + PRs complete: + - PR # : all checks green, no open threads + Action required: restart superpowers:pr-monitoring for the PRs listed above. + ``` + + Then exit. The orchestrator (lead agent) will read this report via the + activity log and start a new monitor agent for the remaining PRs. - ### 4. Wait Between Checks + ### 4. Wait Between Cycles - Sleep 60 seconds between check cycles. Do not poll more frequently. + Sleep **10 minutes** (600 seconds) between full check cycles across all PRs. + Do not poll more frequently — this keeps GitHub API usage well within limits. ```` -Use your host's equivalent mechanism to periodically poll the following in a loop: -- `gh pr checks ` — fix any failing CI checks -- GraphQL `reviewThreads` query — fetch unresolved, non-outdated threads; address each one, reply "Addressed in ", then resolve the thread via the `resolveReviewThread` GraphQL mutation. Apply this to bot comments (any login ending in `[bot]`, or known bots such as `copilot`, `github-advanced-security`, `datadog`) the same as human comments. +Use your host's equivalent mechanism to periodically poll the following in a loop, +with a **10-minute** wait between full cycles and a **60-minute** total session cap: + +- `gh pr checks ` — fix any failing CI checks; use a separate worktree + per branch so you never switch branches mid-session +- GraphQL `reviewThreads` query — fetch unresolved, non-outdated threads; address + each one, reply "Addressed in ", then resolve the thread via the + `resolveReviewThread` GraphQL mutation. Apply this to bot comments (any login + ending in `[bot]`, or known bots such as `copilot`, `github-advanced-security`, + `datadog`) the same as human comments. - `gh api repos///pulls//reviews` — handle any "CHANGES_REQUESTED" reviews -Continue until all checks pass, no unresolved inline threads remain, and no "changes requested" reviews are pending. +When the 60-minute limit is reached before all PRs are clean, write a timeout +status report listing which PRs still need attention, then exit. The orchestrator +should start a new monitor for the remaining PRs. -When the PR has merged with green base-branch CI and a design + plan exist in `docs/plans/` for this branch, invoke `superpowers:post-merge-retrospective` to write a retro in `docs/retros/`. If the PR was closed without merge, skip the retro and exit cleanly. +When a PR has merged with green base-branch CI and a design + plan exist in +`docs/plans/` for its branch, invoke `superpowers:post-merge-retrospective` to +write a retro in `docs/retros/`. If the PR was closed without merge, skip the +retro and exit cleanly. @@ -156,10 +226,18 @@ When the PR has merged with green base-branch CI and a design + plan exist in `d | Limit | Value | On Exceed | |-------|-------|-----------| | CI fix attempts per failure | 5 | Comment on PR, stop fixing that check | -| Revision rounds per comment | 3 | Reply with escalation, stop revising | -| Total monitoring duration | 30 min | Exit with status report | +| Revision rounds per comment | 3 | Reply with escalation, resolve thread, move on | +| Total monitoring duration | 60 min | Write timeout status report; orchestrator restarts a new monitor | +| Poll interval | 10 min (600s) | — do not poll more frequently | | Push frequency | Max 1 per 60s | Queue fixes, batch push | +## Orchestrator Restart Guidance + +When the monitor agent times out (60 min), it writes a `PR-MONITOR TIMEOUT REPORT` +to its output. The orchestrator (lead agent) should watch for this via the activity +log, read the report, and start a new `superpowers:pr-monitoring` agent scoped to +only the PRs still listed as needing attention. Repeat until all PRs are clean. + ## Integration **Called by:** From 87794cb8ba56423336d2d790825ef83f76845649 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 16:20:28 +0000 Subject: [PATCH 07/11] fix: align single-vs-per-PR agent language across hook, pr-monitoring, and finishing-a-development-branch Agent-Logs-Url: https://github.com/GoCodeAlone/claude-superpowers/sessions/0819218d-f7ef-40c8-ae9a-7962ca512562 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- hooks/posttool-pr-created | 4 ++-- skills/finishing-a-development-branch/SKILL.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hooks/posttool-pr-created b/hooks/posttool-pr-created index 73137da..1925f59 100755 --- a/hooks/posttool-pr-created +++ b/hooks/posttool-pr-created @@ -60,8 +60,8 @@ escape_for_json() { reminder="" reminder+="You just ran \`gh pr create\`. " reminder+="You MUST now invoke \`superpowers:pr-monitoring\` ${pr_hint}. " -reminder+="Prefer a SINGLE monitoring agent that covers ALL PRs you have created in this session " -reminder+="to avoid GitHub API rate limits — but you may use one agent per PR if the situation warrants it. " +reminder+="Prefer a single monitoring agent covering all PRs in this session to avoid GitHub API rate limits. " +reminder+="One agent per PR is acceptable if the PRs are on unrelated codebases or a previous shared monitor was rate-limited. " reminder+="Draft PRs still trigger CI and receive bot reviews, so monitoring is required regardless of draft state. " reminder+="Do NOT declare the task complete until pr-monitoring has been started. " reminder+="See superpowers:pr-monitoring for usage." diff --git a/skills/finishing-a-development-branch/SKILL.md b/skills/finishing-a-development-branch/SKILL.md index c70d8dd..119448f 100644 --- a/skills/finishing-a-development-branch/SKILL.md +++ b/skills/finishing-a-development-branch/SKILL.md @@ -61,7 +61,7 @@ When running in the autonomous pipeline (invoked from subagent-driven-developmen EOF )" ``` -5. **Invoke pr-monitoring** — spawn a single background monitor that covers all PRs created in this session +5. **Invoke pr-monitoring** — spawn a background monitor for all PRs created in this session; prefer a single agent covering all PRs to avoid GitHub API rate limits, but one agent per PR is acceptable if the PRs are on unrelated codebases or a previous shared monitor was rate-limited 6. **Report PR URLs** — output every PR link for the user (one per row in the manifest's PR Grouping table) **Do NOT:** From 4d9ed30a43a6a8f204e467086b7e9f4cb4bcfbf3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 16:30:55 +0000 Subject: [PATCH 08/11] fix: quote @copilot as \"@copilot\" to prevent GitHub auto-linking in hook text Agent-Logs-Url: https://github.com/GoCodeAlone/claude-superpowers/sessions/7cdce8b4-93c0-40dc-a40f-9aba4ab5bb7d Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- hooks/pretool-pr-review-reminder | 56 +++++++++++++++----------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/hooks/pretool-pr-review-reminder b/hooks/pretool-pr-review-reminder index e0faa2e..822b3ed 100755 --- a/hooks/pretool-pr-review-reminder +++ b/hooks/pretool-pr-review-reminder @@ -1,14 +1,11 @@ #!/usr/bin/env bash # hooks/pretool-pr-review-reminder -# PreToolUse hook: blocks gh pr create unless --reviewer Copilot is included. +# PreToolUse hook: reminds the agent to add Copilot as a reviewer after creating a PR. # -# When an agent runs gh pr create without requesting Copilot as a reviewer the -# PR is created without automated code review. This hook intercepts the command -# before it runs and blocks it with a clear instruction to add the flag, so the -# agent retries with Copilot in the reviewer list. -# -# Copilot is specified as a reviewer with --reviewer Copilot (the exact handle -# GitHub uses for its built-in AI code-review feature). +# When an agent is about to run gh pr create, inject a reminder about: +# 1. gh CLI version requirement (v2.88+) +# 2. Adding Copilot as a reviewer via `gh pr edit --add-reviewer "@copilot"` +# immediately after the PR is created (not as a flag to gh pr create). # # Global opt-out: set SUPERPOWERS_HOOKS_DISABLE=1 @@ -32,29 +29,28 @@ cmd=$(printf '%s' "$hook_input" | jq -r '.tool_input.command // empty' 2>/dev/nu # Only act on PR creation commands. printf '%s' "$cmd" | grep -q 'gh pr create' || exit 0 -# Pass through if Copilot is already listed as a reviewer. -# Handles all gh reviewer syntaxes (case-insensitive on "copilot"): -# --reviewer Copilot -# --reviewer=Copilot -# --reviewer user1,Copilot (copilot after a comma-separated peer) -# --reviewer Copilot,user2 (copilot before a comma-separated peer) -# --reviewer user1 --reviewer Copilot (multiple flags; second flag matched) -if printf '%s' "$cmd" | grep -qiE -- '--reviewer[[:space:]=]([^[:space:]]*,)*copilot'; then - exit 0 -fi - -block() { - local reason="$1" - printf '{"decision":"block","reason":%s}\n' \ - "$(printf '%s' "$reason" | jq -Rs .)" - exit 2 +# Escape a string for embedding inside a JSON string value. +escape_for_json() { + local s="$1" + s="${s//\\/\\\\}" + s="${s//\"/\\\"}" + s="${s//$'\n'/\\n}" + s="${s//$'\r'/\\r}" + s="${s//$'\t'/\\t}" + printf '%s' "$s" } -block "Add Copilot as a code reviewer before creating this PR. -Re-run the command with: --reviewer Copilot +reminder="" +reminder+="Before and after running \`gh pr create\`:" +reminder+=" (1) Ensure \`gh\` is version 2.88 or higher (\`gh --version\`)." +reminder+=" If it is older, upgrade gh (e.g. \`gh upgrade\` or follow https://cli.github.com/manual/) or inform the user that a manual upgrade is needed." +reminder+=" (2) After the PR is created, add Copilot as a reviewer by running:" +reminder+=" \`gh pr edit --add-reviewer \"@copilot\"\`" +reminder+=" Do NOT use \`--reviewer Copilot\` as a flag to \`gh pr create\` — the correct method is \`gh pr edit --add-reviewer \"@copilot\"\` post-creation." +reminder+="" + +escaped=$(escape_for_json "$reminder") -Example: - gh pr create --title \"...\" --body \"...\" --reviewer Copilot +printf '{"additional_context":"%s"}\n' "$escaped" -Copilot reviews run automatically on the PR diff and catch issues before -human reviewers see the PR. Do not skip this flag." +exit 0 From 695dabfa7f5835baeaba0998eeb515e5a4f96bc9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 22:51:17 +0000 Subject: [PATCH 09/11] fix: address PR review comments on hooks and pr-monitoring skill Agent-Logs-Url: https://github.com/GoCodeAlone/claude-superpowers/sessions/14f51239-1ee9-4c89-8bf3-2353ea0d333a Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- hooks/posttool-pr-created | 12 +++++------ hooks/pretool-pr-review-reminder | 21 ++++++++++++------- skills/pr-monitoring/SKILL.md | 36 +++++++++++++++++++++++++------- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/hooks/posttool-pr-created b/hooks/posttool-pr-created index 1925f59..8879de7 100755 --- a/hooks/posttool-pr-created +++ b/hooks/posttool-pr-created @@ -34,17 +34,17 @@ cmd=$(printf '%s' "$hook_input" | jq -r '.tool_input.command // empty' 2>/dev/nu # Only act when the command created a PR (not a simple `gh pr list`, etc.). printf '%s' "$cmd" | grep -q 'gh pr create' || exit 0 -# Try to extract the PR URL from the tool response so the reminder is specific. +# Try to extract the PR URL from the tool response to confirm the PR was created. +# If no URL is found, gh pr create likely failed — do not inject the reminder. tool_response=$(printf '%s' "$hook_input" | jq -r '.tool_response // empty' 2>/dev/null || true) pr_url=$(printf '%s' "$tool_response" \ | grep -oE 'https://github\.com/[^[:space:]]+/pull/[0-9]+' \ | head -1 || true) -if [ -n "$pr_url" ]; then - pr_hint="for the PR you just created: ${pr_url}" -else - pr_hint="for the PR you just created" -fi +# Only remind when we can confirm a PR was successfully created. +[ -z "$pr_url" ] && exit 0 + +pr_hint="for the PR you just created: ${pr_url}" # Escape a string for embedding inside a JSON string value. escape_for_json() { diff --git a/hooks/pretool-pr-review-reminder b/hooks/pretool-pr-review-reminder index 822b3ed..aea6722 100755 --- a/hooks/pretool-pr-review-reminder +++ b/hooks/pretool-pr-review-reminder @@ -40,14 +40,19 @@ escape_for_json() { printf '%s' "$s" } -reminder="" -reminder+="Before and after running \`gh pr create\`:" -reminder+=" (1) Ensure \`gh\` is version 2.88 or higher (\`gh --version\`)." -reminder+=" If it is older, upgrade gh (e.g. \`gh upgrade\` or follow https://cli.github.com/manual/) or inform the user that a manual upgrade is needed." -reminder+=" (2) After the PR is created, add Copilot as a reviewer by running:" -reminder+=" \`gh pr edit --add-reviewer \"@copilot\"\`" -reminder+=" Do NOT use \`--reviewer Copilot\` as a flag to \`gh pr create\` — the correct method is \`gh pr edit --add-reviewer \"@copilot\"\` post-creation." -reminder+="" +reminder=$(cat <<'REMINDER' + +Before and after running `gh pr create`: +(1) Ensure `gh` is version 2.88 or higher (`gh --version`). + If it is older, upgrade gh (e.g. `gh upgrade` or follow https://cli.github.com/manual/) + or inform the user that a manual upgrade is needed. +(2) After the PR is created, add Copilot as a reviewer by running: + gh pr edit --add-reviewer "@copilot" + Do NOT use `--reviewer Copilot` as a flag to `gh pr create` — + the correct method is `gh pr edit --add-reviewer "@copilot"` post-creation. + +REMINDER +) escaped=$(escape_for_json "$reminder") diff --git a/skills/pr-monitoring/SKILL.md b/skills/pr-monitoring/SKILL.md index 7649f0b..40234e3 100644 --- a/skills/pr-monitoring/SKILL.md +++ b/skills/pr-monitoring/SKILL.md @@ -70,12 +70,19 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): For each PR: ```bash - gh pr checks --json name,state,conclusion + gh pr checks --json name,state,conclusion,detailsUrl ``` **If any check fails:** - a. Read the failure logs: `gh run view --log-failed` - b. Identify the root cause + a. Extract the run ID from the `detailsUrl` field of the failing check + (the URL has the form `.../runs//...`): + ```bash + gh pr checks --json name,state,conclusion,detailsUrl \ + | jq '.[] | select(.conclusion == "FAILURE") | .detailsUrl' + # run-id is the numeric segment after /runs/ in that URL + ``` + b. Read the failure logs: `gh run view --log-failed` + c. Identify the root cause c. `cd` into that PR's worktree directory and confirm the branch: ```bash cd ../-monitor @@ -97,7 +104,7 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): ### 2. Check Review Comments (per PR) Use GraphQL to fetch review threads — this gives both the thread IDs needed - for resolution and the author login needed to detect bots: + for resolution and the author login and comment IDs needed to reply in-thread: ```bash gh api graphql -f query=' @@ -110,7 +117,12 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): isResolved isOutdated comments(first: 1) { - nodes { author { login } body } + nodes { + databaseId + url + author { login } + body + } } } } @@ -120,6 +132,15 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): ' -f owner= -f repo= -F number= ``` + To reply to a review thread, use the REST API with the `databaseId` of the + first comment in the thread (the `in_reply_to_id` parameter): + ```bash + gh api repos///pulls//comments \ + --method POST \ + --field body="Addressed in " \ + --field in_reply_to_id= + ``` + Also fetch any "CHANGES_REQUESTED" reviews: ```bash @@ -156,7 +177,8 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): **Safety:** Max 3 revision rounds per review comment. After 3, reply: "I've attempted to address this feedback but may need clarification. Flagging for manual review." - Then resolve the thread so it does not block the exit condition. + Leave the thread **unresolved** — do NOT resolve it, as that would mask the outstanding concern. + It will be surfaced in the timeout status report as needing manual intervention. ### 3. Check Exit Conditions @@ -226,7 +248,7 @@ retro and exit cleanly. | Limit | Value | On Exceed | |-------|-------|-----------| | CI fix attempts per failure | 5 | Comment on PR, stop fixing that check | -| Revision rounds per comment | 3 | Reply with escalation, resolve thread, move on | +| Revision rounds per comment | 3 | Reply with escalation, leave thread unresolved, surface in timeout report | | Total monitoring duration | 60 min | Write timeout status report; orchestrator restarts a new monitor | | Poll interval | 10 min (600s) | — do not poll more frequently | | Push frequency | Max 1 per 60s | Queue fixes, batch push | From 3c7eed2a7f89acaa85ca445520e9135c03f2c3b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 22:52:15 +0000 Subject: [PATCH 10/11] fix: correct duplicate step label c. -> d. in CI failure workflow Agent-Logs-Url: https://github.com/GoCodeAlone/claude-superpowers/sessions/14f51239-1ee9-4c89-8bf3-2353ea0d333a Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- skills/pr-monitoring/SKILL.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/skills/pr-monitoring/SKILL.md b/skills/pr-monitoring/SKILL.md index 40234e3..e68b294 100644 --- a/skills/pr-monitoring/SKILL.md +++ b/skills/pr-monitoring/SKILL.md @@ -83,20 +83,20 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): ``` b. Read the failure logs: `gh run view --log-failed` c. Identify the root cause - c. `cd` into that PR's worktree directory and confirm the branch: + d. `cd` into that PR's worktree directory and confirm the branch: ```bash cd ../-monitor git branch --show-current # must equal ``` - d. Fix the issue in the codebase - e. Run the relevant tests locally to verify - f. Commit and push: + e. Fix the issue in the codebase + f. Run the relevant tests locally to verify + g. Commit and push: ```bash git add git commit -m "fix: address CI failure in " git push ``` - g. Return to the next PR in the loop + h. Return to the next PR in the loop **Safety:** Max 5 fix attempts per unique CI failure. After 5, comment on the PR: "Unable to automatically resolve CI failure in after 5 attempts. Manual intervention needed." From 074344ff9e7428a57bf2a05ec29e4586979c06b5 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Wed, 6 May 2026 15:56:15 -0400 Subject: [PATCH 11/11] fix: align PR monitoring review guidance --- hooks/pretool-pr-review-reminder | 6 +++--- skills/pr-monitoring/SKILL.md | 20 +++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/hooks/pretool-pr-review-reminder b/hooks/pretool-pr-review-reminder index aea6722..925676c 100755 --- a/hooks/pretool-pr-review-reminder +++ b/hooks/pretool-pr-review-reminder @@ -4,7 +4,7 @@ # # When an agent is about to run gh pr create, inject a reminder about: # 1. gh CLI version requirement (v2.88+) -# 2. Adding Copilot as a reviewer via `gh pr edit --add-reviewer "@copilot"` +# 2. Adding Copilot as a reviewer via `gh pr edit --add-reviewer copilot-pull-request-reviewer` # immediately after the PR is created (not as a flag to gh pr create). # # Global opt-out: set SUPERPOWERS_HOOKS_DISABLE=1 @@ -47,9 +47,9 @@ Before and after running `gh pr create`: If it is older, upgrade gh (e.g. `gh upgrade` or follow https://cli.github.com/manual/) or inform the user that a manual upgrade is needed. (2) After the PR is created, add Copilot as a reviewer by running: - gh pr edit --add-reviewer "@copilot" + gh pr edit --add-reviewer copilot-pull-request-reviewer Do NOT use `--reviewer Copilot` as a flag to `gh pr create` — - the correct method is `gh pr edit --add-reviewer "@copilot"` post-creation. + the correct method is `gh pr edit --add-reviewer copilot-pull-request-reviewer` post-creation. REMINDER ) diff --git a/skills/pr-monitoring/SKILL.md b/skills/pr-monitoring/SKILL.md index e68b294..aefa7db 100644 --- a/skills/pr-monitoring/SKILL.md +++ b/skills/pr-monitoring/SKILL.md @@ -133,12 +133,12 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): ``` To reply to a review thread, use the REST API with the `databaseId` of the - first comment in the thread (the `in_reply_to_id` parameter): + first comment in the thread (the `in_reply_to` parameter): ```bash gh api repos///pulls//comments \ --method POST \ --field body="Addressed in " \ - --field in_reply_to_id= + --field in_reply_to= ``` Also fetch any "CHANGES_REQUESTED" reviews: @@ -149,9 +149,9 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): ``` **Bot detection:** treat a commenter as a bot if their login ends in `[bot]` - or matches a known review bot (e.g. `copilot`, `github-advanced-security`, - `datadog`, `codeclimate`, `sonarcloud`). Apply the same address-then-resolve - flow to bot comments as to human comments. + or matches a known review bot (e.g. `copilot-pull-request-reviewer`, + `github-advanced-security`, `datadog`, `codeclimate`, `sonarcloud`). Apply + the same address-then-resolve flow to bot comments as to human comments. **If new unresolved, non-outdated threads are found:** a. Read the comment carefully @@ -164,7 +164,8 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): d. Run tests to verify e. Commit and push f. Reply to the comment: "Addressed in " - g. **Resolve the thread** (required for all comments, especially bot comments): + g. **Resolve the thread** after verification unless the max revision rounds + safety limit was exceeded (required for addressed comments, especially bot comments): ```bash gh api graphql -f query=' mutation($threadId: ID!) { @@ -184,7 +185,7 @@ Agent tool (general-purpose, model: balanced, run_in_background: true): A PR is **complete** when ALL of: - All CI checks passing (green) - - No unresolved review comments + - No unresolved, non-outdated review threads - No pending "changes requested" reviews **On all PRs complete (clean exit):** @@ -226,8 +227,9 @@ with a **10-minute** wait between full cycles and a **60-minute** total session per branch so you never switch branches mid-session - GraphQL `reviewThreads` query — fetch unresolved, non-outdated threads; address each one, reply "Addressed in ", then resolve the thread via the - `resolveReviewThread` GraphQL mutation. Apply this to bot comments (any login - ending in `[bot]`, or known bots such as `copilot`, `github-advanced-security`, + `resolveReviewThread` GraphQL mutation unless the 3 revision-round safety limit + was exceeded. Apply this to bot comments (any login ending in `[bot]`, or known + bots such as `copilot-pull-request-reviewer`, `github-advanced-security`, `datadog`) the same as human comments. - `gh api repos///pulls//reviews` — handle any "CHANGES_REQUESTED" reviews