检查代码变更的测试情况及对现有功能的影响,按仓库模板创建PR,并继续处理评审请求、反馈意见和CI检查。
- 按指定模板创建PR
- 检查现有功能与新功能的测试
- 本地验证受限时请求机器人评审
收集PR审查意见,推进代码修改、提交、回复及讨论串解决,同时持续检查CI失败、合并冲突和新增评论,跟进直至审查事项处理完成。
Address PR review comments and loop until CI green and all comments resolved. TRIGGER when user asks to address comments, fix PR feedback, respond to reviewers, or babysit/monitor a PR.
实测评分 未实测
查看安装方法读取PR审查意见,从代码修改推进到回复及解决已处理的讨论串。逐页检查行内评论、审查正文和PR对话,收集尚未处理的意见。修改提交并推送后,会附上对应提交的链接回复。对于误报,会解释无需修改的理由。
适合经过多轮审查,或同时收到人工和机器人意见的PR。也会检查CI自动检查失败和合并冲突,并结合新增评论反复推进处理,跟进到审查事项完成。
使用GitHub CLI的gh和Git。流程包含推送修改、在GitHub发布回复以及解决讨论串。格式整理和测试以AutoGPT开发环境为前提。CI通过后还会继续检查,对已请求的机器人审查最多等待60分钟。提供的资料仅包含部分内容,此处介绍限于能够确认的范围。
本介绍由 AI(OpenAI Codex)根据公开的 SKILL.md 撰写。准确的规格请查看下方原文。
AI 根据 SKILL.md 的内容检查了需要注意的操作和使用前提。评分只依据实际运行的结果(实测对比)。
不计入评分。 由 AI(OpenAI Codex)于 2026年10月23日 评估。仅供参考,安装前请同时查看原文。
安装前可以查看交给 AI 代理的指令内容。
gh pr list --head $(git branch --show-current) --repo Significant-Gravitas/AutoGPT
gh pr view {N}
Understand the Why / What / How before addressing comments — you need context to make good fixes:
gh pr view {N} --json body --jq '.body'
If GraphQL is rate-limited,
gh pr viewfails. See GitHub rate limits for REST fallbacks.
Only relevant if the PR has no review yet. If the fetch steps below turn up no reviews and no inline threads, there is nothing to address yet — that is not the same as being done. You can summon the repo's review bot yourself:
gh pr comment {N} --body "/review"
This is an option, not a required step. Skip it whenever the PR already has reviews (bot or human) — those are what you are here to address. See the open-pr skill's "Review workflow" step for the same trigger in the PR-creation flow.
autogpt-pr-reviewer[bot] typically responds within ~30 minutes. Poll for it rather than sleeping — the loop in Polling for CI + new comments already re-checks every source every 30 seconds, so run that loop and react the moment the review lands. Note the id and created_at of the /review comment you posted; Waiting on a requested review needs them for the exit condition.
⚠️ WARNING — PAGINATE ALL PAGES BEFORE ADDRESSING ANYTHING
reviewThreads(first: 100)returns at most 100 threads per page AND returns threads oldest-first. On a PR with many review cycles (e.g. 373 threads), the oldest 100–200 threads are from past cycles and are all already resolved. Filtering client-side withselect(.isResolved == false)on page 1 therefore yields 0 results — even though pages 2–4 contain many unresolved threads from recent review cycles.This is the most common failure mode: agent fetches page 1, sees 0 unresolved after filtering, stops pagination, reports "done" — while hundreds of unresolved threads sit on later pages.
One observed PR had 142 total threads: page 1 returned 0 unresolved (all old/resolved), while pages 2–3 had 111 unresolved. Another with 373 threads across 4 pages also had page 1 entirely resolved.
The rule: ALWAYS paginate to
hasNextPage == falseregardless of the per-page unresolved count. Never stop early because a page returns 0 unresolved.
Step 1 — Fetch total count and sanity-check the newest threads:
# Get total count and the newest 100 threads (last: 100 returns newest-first)
gh api graphql -f query='
{
repository(owner: "Significant-Gravitas", name: "AutoGPT") {
pullRequest(number: {N}) {
reviewThreads { totalCount }
newest: reviewThreads(last: 100) {
nodes { isResolved }
}
}
}
}' | jq '{ total: .data.repository.pullRequest.reviewThreads.totalCount, newest_unresolved: [.data.repository.pullRequest.newest.nodes[] | select(.isResolved == false)] | length }'
If total > 100, you have multiple pages — you must paginate all of them regardless of what newest_unresolved shows. The last: 100 check is a sanity signal only; the full loop below is mandatory.
Step 2 — Collect all unresolved thread IDs across all pages:
# Accumulate all unresolved threads — loop until hasNextPage == false
CURSOR=""
ALL_THREADS="[]"
while true; do
AFTER=${CURSOR:+", after: \"$CURSOR\""}
PAGE=$(gh api graphql -f query="
{
repository(owner: \"Significant-Gravitas\", name: \"AutoGPT\") {
pullRequest(number: {N}) {
reviewThreads(first: 100${AFTER}) {
pageInfo { hasNextPage endCursor }
nodes {
id
isResolved
path
line
comments(last: 1) {
nodes { databaseId body author { login } }
}
}
}
}
}
}")
# Append unresolved nodes from this page
PAGE_THREADS=$(echo "$PAGE" | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)]')
ALL_THREADS=$(echo "$ALL_THREADS $PAGE_THREADS" | jq -s 'add')
HAS_NEXT=$(echo "$PAGE" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage')
CURSOR=$(echo "$PAGE" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor')
[ "$HAS_NEXT" = "false" ] && break
done
# Reverse so newest threads (last pages) are addressed first — GitHub returns oldest-first
# and the most recent review cycle's comments are the ones blocking approval.
ALL_THREADS=$(echo "$ALL_THREADS" | jq 'reverse')
echo "Total unresolved threads: $(echo "$ALL_THREADS" | jq 'length')"
echo "$ALL_THREADS" | jq '[.[] | {id, path, line, body: .comments.nodes[0].body[:200]}]'
Step 3 — Address every thread in ALL_THREADS, then resolve.
Only after this loop completes (all pages fetched, count confirmed) should you begin making fixes.
Why reverse? GraphQL returns threads oldest-first and exposes no
orderByoption. A PR with 373 threads has ~4 pages; threads from the latest review cycle land on the last pages. Processing in reverse ensures the newest, most blocking comments are addressed first — the earlier pages mostly contain outdated threads from prior cycles.
Filter to unresolved threads only — skip any thread where isResolved: true. comments(last: 1) returns the most recent comment in the thread — act on that; it reflects the reviewer's final ask. Use the thread id (Relay global ID) to track threads across polls.
If GraphQL is rate-limited, see GitHub rate limits for the REST fallback (flat comment list — no thread grouping or
isResolved).
gh api repos/Significant-Gravitas/AutoGPT/pulls/{N}/reviews --paginate
Already REST — unaffected by GraphQL rate limits or outages. Continue polling reviews normally even when GraphQL is exhausted.
CRITICAL — always --paginate. Reviews default to 30 per page. PRs can have 80–170+ reviews (mostly empty resolution events). Without pagination you miss reviews past position 30 — including autogpt-pr-reviewer[bot]'s structured review which is typically posted after several CI runs and sits well beyond the first page.
Two things to extract:
CHANGES_REQUESTED or APPROVED reviews.Where each reviewer posts:
autogpt-pr-reviewer[bot] — posts detailed structured reviews ("Blockers", "Should Fix", "Nice to Have") as top-level reviews. Not present on every PR. Address ALL items.sentry[bot] — posts bug predictions as inline threads. Fix real bugs, explain false positives.coderabbitai[bot] — posts summaries as top-level reviews AND actionable items as inline threads. Address actionable items.gh api repos/Significant-Gravitas/AutoGPT/issues/{N}/comments --paginate
Already REST — unaffected by GraphQL rate limits.
Mostly contains: bot summaries (coderabbitai[bot]), CI/conflict detection (github-actions[bot]), and author status updates. Scan for non-empty messages from non-bot human reviewers that aren't the PR author — those are the ones that need a response.
Slash-command trigger comments are never actionable items — skip them. A comment whose entire body is a slash command (/review being the common one) exists to summon the review bot; it is not a request directed at you. Do not reply to it, do not treat it as feedback, and do not count it as a "new comment" that restarts the loop. The non-author filter above happens to hide the usual case where the PR author posted it, but that is incidental — a maintainer can post /review on someone else's PR, and it must still be skipped. The actionable content is the review it produces, which arrives as a top-level review and/or inline threads, not as a conversation comment.
CRITICAL: The only valid sequence is fix → commit → push → reply → resolve. Never resolve a thread without a real code commit.
Resolving a thread via resolveReviewThread without an actual fix is the most common failure mode — it makes unresolved counts drop without any real change, producing a false "done" signal. If the issue was genuinely a false positive (no code change needed), reply explaining why and then resolve. Otherwise:
Address comments one at a time: fix → commit → push → inline reply → resolve.
Use a markdown commit link so GitHub renders it as a clickable reference. Always get the full SHA with git rev-parse HEAD after committing — never copy a SHA from a previous commit or hardcode one:
FULL_SHA=$(git rev-parse HEAD)
gh api repos/Significant-Gravitas/AutoGPT/pulls/{N}/comments/{ID}/replies \
-f body="🤖 Fixed in [${FULL_SHA:0:9}](https://github.com/Significant-Gravitas/AutoGPT/commit/${FULL_SHA}): <description>"
| Comment type | How to reply |
|---|---|
Inline review (pulls/{N}/comments) | gh api repos/Significant-Gravitas/AutoGPT/pulls/{N}/comments/{ID}/replies -f body="🤖 Fixed in [abc1234](https://github.com/Significant-Gravitas/AutoGPT/commit/FULL_SHA): <description>" |
Conversation (issues/{N}/comments) | gh api repos/Significant-Gravitas/AutoGPT/issues/{N}/comments -f body="🤖 Fixed in [abc1234](https://github.com/Significant-Gravitas/AutoGPT/commit/FULL_SHA): <description>" |
Only two situations justify calling resolveReviewThread:
sdk_cwd is pre-validated by _make_sdk_cwd() which applies normpath + prefix assertion before reaching this point").Anti-patterns that look resolved but aren't — never do these:
"Accepted, tracked as follow-up" — a deferral, not a fix. The concern is still open. Do not resolve."Acknowledged" or "Same as above" — these are acknowledgements, not fixes. Do not resolve."Fixed in abc1234" where abc1234 is a commit that doesn't actually change the flagged line/logic — dishonest. Verify git show abc1234 -- path/to/file changes the right thing before posting.When in doubt: if a code change is needed, make it. A deferred issue means the thread stays open until the follow-up PR is merged.
Codecov patch target is 80% on changed lines. Checks are informational (not blocking) but should be green.
Backend (from autogpt_platform/backend/):
poetry run pytest -s -vv --cov=backend --cov-branch --cov-report term-missing
Frontend (from autogpt_platform/frontend/):
pnpm vitest run --coverage
git diff --name-only $(gh pr view --json baseRefName --jq '.baseRefName')...HEADhelpers.ts/helpers.py and test those (highest ROI). Colocate tests as *_test.py (backend) or __tests__/*.test.ts (frontend).After fixing, format the changed code:
autogpt_platform/backend/): poetry run formatautogpt_platform/frontend/): pnpm format && pnpm lint && pnpm typesIf API routes changed, regenerate the frontend client:
cd autogpt_platform/backend && poetry run rest &
REST_PID=$!
trap "kill $REST_PID 2>/dev/null" EXIT
WAIT=0; until curl -sf http://localhost:8006/health > /dev/null 2>&1; do sleep 1; WAIT=$((WAIT+1)); [ $WAIT -ge 60 ] && echo "Timed out" && exit 1; done
cd ../frontend && pnpm generate:api:force
kill $REST_PID 2>/dev/null; trap - EXIT
Never manually edit files in src/app/api/__generated__/.
Then commit and push immediately — never batch commits without pushing. Each fix should be visible on GitHub right away so CI can start and reviewers can see progress.
Never push empty commits (git commit --allow-empty) to re-trigger CI or bot checks. When a check fails, investigate the root cause (unchecked PR checklist, unaddressed review comments, code issues) and fix those directly. Empty commits add noise to git history.
For backend commits in worktrees: poetry run git commit (pre-commit hooks).
Codecov enforces patch coverage on new/changed lines — new code you write must be tested. Before pushing, verify you haven't left new lines uncovered:
cd autogpt_platform/backend
poetry run pytest --cov=. --cov-report=term-missing {path/to/changed/module}
Look for lines marked miss — those are uncovered. Add tests for any new code you wrote as part of addressing comments.
Rules:
address comments → format → commit → push
→ wait for CI (while addressing new comments) → fix failures → push
→ re-check comments after CI settles
→ repeat until: all comments addressed AND CI green AND no new comments arriving
After pushing, poll for both CI status and new comments in a single loop. Do not use gh pr checks --watch — it blocks the tool and prevents reacting to new comments while CI is running.
Note:
gh pr checks --watch --fail-fastis tempting but it blocks the entire Bash tool call, meaning the agent cannot check for or address new comments until CI fully completes. Always poll manually instead.
Polling loop — repeat every 30 seconds:
gh pr checks {N} --repo Significant-Gravitas/AutoGPT --json bucket,name,link
Parse the results: if every check has bucket of "pass" or "skipping", CI is green. If any has "fail", CI has failed. Otherwise CI is still pending.
gh pr view {N} --repo Significant-Gravitas/AutoGPT --json mergeable --jq '.mergeable'
If the result is "CONFLICTING", the PR has a merge conflict — see "Resolving merge conflicts" below. If "UNKNOWN", GitHub is still computing mergeability — wait and re-check next poll.
Check for new/changed comments (all three sources):
Inline threads — re-run the GraphQL query from "Fetch comments". For each unresolved thread, record {thread_id, last_comment_databaseId} as your baseline. On each poll, action is needed if:
id appears that wasn't in the baseline (new thread), ORlast_comment_databaseId has changed (new reply on existing thread)Conversation comments:
# Exclude slash-command triggers here, not just when reading — otherwise a
# `/review` (yours or a maintainer's) counts as a "new comment" and forces
# an address round over a comment with nothing to address.
gh api repos/Significant-Gravitas/AutoGPT/issues/{N}/comments --paginate --slurp \
| jq '[.[][] | select((.body // "") | test("^\\s*/[a-z-]+\\s*$") | not)]'
Compare total count and newest id against baseline. Filter to non-empty, non-bot, non-author-update messages.
Top-level reviews:
gh api repos/Significant-Gravitas/AutoGPT/pulls/{N}/reviews --paginate
Watch for new non-empty reviews (CHANGES_REQUESTED or COMMENTED with body). Compare total count and newest id against baseline.
React in this precedence order (first match wins):
| What happened | Action |
|---|---|
| Merge conflict detected | See "Resolving merge conflicts" below. |
Mergeability is UNKNOWN | GitHub is still computing mergeability. Sleep 30 seconds, then restart polling from the top. |
| New comments detected | Address them (fix → commit → push → reply). After pushing, re-fetch all comments to update your baseline, then restart this polling loop from the top (new commits invalidate CI status). |
| CI failed (bucket == "fail") | Get failed check links: gh pr checks {N} --repo Significant-Gravitas/AutoGPT --json bucket,link --jq '.[] | select(.bucket == "fail") | .link'. Extract run ID from link (format: .../actions/runs/<run-id>/job/...), read logs with gh run view <run-id> --repo Significant-Gravitas/AutoGPT --log-failed. Fix → commit → push → restart polling. |
CI green + no new comments, but a requested /review is unanswered | The bot is still working — quiet polls are exactly what that looks like. Keep polling; do not count these as the quiet polls below. See "Waiting on a requested review". |
| CI green + no new comments | Do not exit immediately. Bots (coderabbitai, sentry) often post reviews shortly after CI settles. Continue polling for 2 more cycles (60s) after CI goes green. Only exit after 2 consecutive green+quiet polls. |
| CI pending + no new comments | Sleep 30 seconds, then poll again. |
The loop ends when: CI fully green + all comments addressed + 2 consecutive polls with no new comments after CI settled + no requested-but-unanswered /review (see below).
If a /review comment was posted on this PR and the bot has not answered it yet, the "2 consecutive green+quiet polls" exit is premature — a pending bot review looks identical to a quiet PR. Keep polling until one of these is true:
autogpt-pr-reviewer[bot], whichever is later — an inline-only reply is still an answer, and counting only top-level reviews leaves the gate waiting after its threads have already been addressed. Once it lands, treat it as "New comments detected" and address it normally./review comment's created_at. Then exit per the normal rule and tell the user the requested review never arrived. Never hang indefinitely on a bot.Recompute both timestamps from the API on every poll rather than tracking elapsed time in a loop variable — a counter that some branch forgets to increment is how this gate becomes an infinite wait.
# `--slurp` cannot be combined with `--jq`; pipe to standalone jq instead.
REQUESTED_AT=$(gh api "repos/Significant-Gravitas/AutoGPT/issues/{N}/comments" --paginate --slurp \
| jq -r '[.[][] | select((.body // "") | test("^\\s*/review\\s*$"))] | max_by(.created_at) | .created_at // empty')
REVIEWED_AT=$(gh api "repos/Significant-Gravitas/AutoGPT/pulls/{N}/reviews" --paginate --slurp \
| jq -r '[.[][] | select(.user.login == "autogpt-pr-reviewer[bot]")] | max_by(.submitted_at) | .submitted_at // empty')
COMMENTED_AT=$(gh api "repos/Significant-Gravitas/AutoGPT/pulls/{N}/comments" --paginate --slurp \
| jq -r '[.[][] | select(.user.login == "autogpt-pr-reviewer[bot]")] | max_by(.created_at) | .created_at // empty')
ANSWERED_AT=$(printf '%s\n%s\n' "$REVIEWED_AT" "$COMMENTED_AT" | grep -v '^$' | sort | tail -1)
# Pending iff a request exists and no answer is strictly newer than it.
# Start every poll from `false`: a stale `true` from the previous poll would
# otherwise keep the gate waiting after the answer has already landed.
# `[ a \< b ]` is not portable (fails under zsh), so compare via sort.
pending=false
NEWEST=$(printf '%s\n%s\n' "$REQUESTED_AT" "$ANSWERED_AT" | grep -v '^$' | sort | tail -1)
if [ -n "$REQUESTED_AT" ] && { [ -z "$ANSWERED_AT" ] || [ "$NEWEST" = "$REQUESTED_AT" ]; }; then
pending=true
fi
A /review posted before this session still counts. Budget is 60 minutes
from REQUESTED_AT: an observed reply on this repo took 46 minutes, so 45
would have abandoned a review that was about to land. Enforce it in the same
poll so the loop cannot wait forever:
# Only meaningful when a request exists: GNU date reads an empty string as
# "now", BSD date errors, and either way there is nothing to time out.
if [ -n "$REQUESTED_AT" ]; then
WAITED=$(( $(date +%s) - $(date -u -j -f "%Y-%m-%dT%H:%M:%SZ" "$REQUESTED_AT" +%s 2>/dev/null || date -u -d "$REQUESTED_AT" +%s) ))
[ "$WAITED" -ge 3600 ] && pending=false # budget spent — stop waiting
fi
Do not post another /review while one is unanswered — check this same
condition before triggering, or each round queues a duplicate request.
gh pr view {N} --repo Significant-Gravitas/AutoGPT --json baseRefName --jq '.baseRefName'
git remote -v # find the remote pointing to Significant-Gravitas/AutoGPT (typically 'upstream' in forks, 'origin' for direct contributors)
git pull {base-remote} {base-branch} --no-rebase
if grep -R -n -E '^(<<<<<<<|=======|>>>>>>>)' <conflicted-files>; then
echo "Unresolved conflict markers found — resolve before proceeding."
exit 1
fi
git add <conflicted-files>
git commit -m "Resolve merge conflicts with {base-branch}"
git push
Three distinct rate limits exist — they have different causes, error shapes, and recovery times:
| Error | HTTP code | Cause | Recovery |
|---|---|---|---|
{"code":"abuse"} | 403 | Secondary rate limit — too many write operations (comments, mutations) in a short window | Wait 2–3 minutes. 60s is often not enough. |
{"message":"API rate limit exceeded"} | 429 | Primary REST rate limit — 5000 calls/hr per user | Wait until X-RateLimit-Reset header timestamp |
GraphQL: API rate limit already exceeded for user ID ... | 403 on stderr, gh exits 1 | GraphQL-specific per-user limit — distinct from REST's 5000/hr and from the abuse secondary limit. Trips faster than REST because point costs per query. | Wait until the GraphQL window resets (typically ~1 hour from the first call in the window). REST still works — use fallbacks below. |
Prevention: Add sleep 3 between individual thread reply API calls. When posting >20 replies, increase to sleep 5.
The gh CLI surfaces the GraphQL limit on stderr with the exact string GraphQL: API rate limit already exceeded for user ID <id> and exits 1 — any gh api graphql ... or gh pr view ... call fails. Check current quota and reset time via the REST endpoint that reports GraphQL quota (this call is REST and still works whether GraphQL is rate-limited OR fully down):
gh api rate_limit --jq '.resources.graphql' # { "limit": 5000, "used": 5000, "remaining": 0, "reset": 1729...}
# Human-readable reset:
gh api rate_limit --jq '.resources.graphql.reset' | xargs -I{} date -r {}
Retry when remaining > 0. If you need to proceed sooner, sleep 2–5 min and probe again — the limit is per user, not per machine, so other concurrent agents under the same token also consume it.
When GraphQL is unavailable (rate-limited or outage):
gh pr checks), and the gh api rate_limit probe./pulls/{N}/comments REST, which drops thread grouping, isResolved, and Relay thread IDs. You still get comment bodies and the databaseId as id, enough to read and reply.gh pr view, the resolveReviewThread mutation, and any new gh api graphql queries — wait for the quota to reset.PR metadata reads — gh pr view uses GraphQL under the hood; use the REST pulls endpoint instead, which returns the full PR object:
gh api repos/Significant-Gravitas/AutoGPT/pulls/{N} --jq '.body' # == --json body
gh api repos/Significant-Gravitas/AutoGPT/pulls/{N} --jq '.base.ref' # == --json baseRefName
gh api repos/Significant-Gravitas/AutoGPT/pulls/{N} --jq '.mergeable' # == --json mergeable
Note: REST mergeable returns true|false|null; GraphQL returns MERGEABLE|CONFLICTING|UNKNOWN. The null case maps to UNKNOWN — treat it the same (still computing; poll again).
Inline comments (flat list) — no thread grouping or isResolved, but enough to read and reply:
gh api repos/Significant-Gravitas/AutoGPT/pulls/{N}/comments --paginate \
| jq '[.[] | {id, path, line, user: .user.login, body: .body[:200], in_reply_to_id}]'
Use this degraded mode to make progress on the fix → reply loop, then return to GraphQL for resolveReviewThread once the rate limit resets.
Replies — already REST-native (/pulls/{N}/comments/{ID}/replies); no change needed, use the same command as the main flow.
resolveReviewThread — no REST equivalent; GitHub does not expose a REST endpoint for thread resolution. Queue the thread IDs needing resolution, wait for the GraphQL limit to reset, then run the resolve mutations in a batch (with sleep 3 between calls, per the secondary-limit guidance).
sleep 3 between each callNever batch all replies in a tight loop — always space them out.
When a PR has more than 10 unresolved threads, addressing one commit per thread is slow. Use this strategy instead:
ALL_THREADS by path — threads in the same file can share a single commit.git commit → git push → reply to all those threads with the same SHA → resolve them all.This reduces N commits to (number of files touched), which is usually 3–5 instead of 15–30.
For truly independent thread groups (different files, no shared logic), you can post replies in parallel using background subshells — but always space out API writes:
# Post replies to a batch of threads concurrently, 3s apart
(
sleep 3
gh api repos/Significant-Gravitas/AutoGPT/pulls/{N}/comments/{ID1}/replies \
-f body="🤖 Fixed in [${FULL_SHA:0:9}](https://github.com/Significant-Gravitas/AutoGPT/commit/${FULL_SHA}): ..."
) &
(
sleep 6
gh api repos/Significant-Gravitas/AutoGPT/pulls/{N}/comments/{ID2}/replies \
-f body="🤖 Fixed in [${FULL_SHA:0:9}](https://github.com/Significant-Gravitas/AutoGPT/commit/${FULL_SHA}): ..."
) &
wait # wait for all background replies before resolving
Then resolve sequentially (GraphQL mutations):
for THREAD_ID in "$THREAD1" "$THREAD2" "$THREAD3"; do
gh api graphql -f query="mutation { resolveReviewThread(input: {threadId: \"${THREAD_ID}\"}) { thread { isResolved } } }"
sleep 3
done
Always sleep 3s between individual API writes — GitHub's secondary rate limit (403) triggers on bursts of >20 writes. Increase to sleep 5 when posting more than 20 replies in a batch.
Use resolveReviewThread only after the commit is pushed and the reply is posted:
gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: "THREAD_ID"}) { thread { isResolved } } }'
Never call this mutation before committing the fix. The orchestrator will verify actual unresolved counts via GraphQL after you output ORCHESTRATOR:DONE — false resolutions will be caught and you will be re-briefed.
resolveReviewThreadis GraphQL-only — no REST equivalent. If GraphQL is rate-limited, see GitHub rate limits for the queue-and-retry flow.
Before claiming "0 unresolved threads", always query GitHub directly — don't rely on your own bookkeeping. Paginate all pages — a single first: 100 query misses threads beyond page 1:
# Step 1: get total thread count
gh api graphql -f query='
{
repository(owner: "Significant-Gravitas", name: "AutoGPT") {
pullRequest(number: {N}) {
reviewThreads { totalCount }
}
}
}' | jq '.data.repository.pullRequest.reviewThreads.totalCount'
# Step 2: paginate all pages, count truly unresolved
CURSOR=""; UNRESOLVED=0
while true; do
AFTER=${CURSOR:+", after: \"$CURSOR\""}
PAGE=$(gh api graphql -f query="
{
repository(owner: \"Significant-Gravitas\", name: \"AutoGPT\") {
pullRequest(number: {N}) {
reviewThreads(first: 100${AFTER}) {
pageInfo { hasNextPage endCursor }
nodes { isResolved }
}
}
}
}")
UNRESOLVED=$(( UNRESOLVED + $(echo "$PAGE" | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved==false)] | length') ))
HAS_NEXT=$(echo "$PAGE" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage')
CURSOR=$(echo "$PAGE" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor')
[ "$HAS_NEXT" = "false" ] && break
done
echo "Unresolved threads: $UNRESOLVED"
Only output ORCHESTRATOR:DONE after this loop reports 0.
还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
检查代码变更的测试情况及对现有功能的影响,按仓库模板创建PR,并继续处理评审请求、反馈意见和CI检查。
在独立工作目录中运行多个Claude Code,统一分配开发任务、监控进度、协助恢复停止的会话,并检查PR测试及评审反馈的处理情况。
利用Sentry测量数据比较变更前后或不同环境的速度与失败率,考虑统计波动,判定加速、减速、未检测到变化或数据不足,并输出比较结果。
反复审查和修复PR,检查未解决的讨论、评论回复、自动检查及合并冲突,并等待延迟到达的评论,将PR整理到可以合并的状态。
审查拉取请求的目的和代码差异,检查正确性、安全性、设计及测试,避免重复已有评论,并将标注严重程度的问题发布到对应代码行。
在运行中的系统上通过浏览器和API验证PR或分支变更,对照界面、接口及存储数据的变化,并附上操作前后截图报告结果。