MCP HubMCP Hub
SKILL·026F3C

run-copilot-review-loop

pjt222
업데이트됨 11 days ago
1 조회
26
3
26
GitHub에서 보기
기타aiapidata

정보

이 스킬은 GitHub Copilot PR 리뷰 루프를 자동화합니다. 별도의 커밋으로 발견된 문제를 수정하고, 수정된 SHA로 응답하며, 스레드를 해결하고, 재검토를 폴링합니다. GraphQL 변형 처리, 봇 전용 식별자 처리, 리뷰 결과의 정확한 해석을 수행합니다. 병합 전에 감사 가능한 기록을 남기며 봇 리뷰 스레드를 효율적으로 종료하는 데 사용하세요.

빠른 설치

Claude Code

추천
기본
npx skills add pjt222/agent-almanac -a claude-code
플러그인 명령대체
/plugin add https://github.com/pjt222/agent-almanac
Git 클론대체
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/run-copilot-review-loop

Claude Code에서 이 명령을 복사하여 붙여넣어 스킬을 설치하세요

문서

Run the Copilot Review Loop

Drive a GitHub Copilot PR review to a clean pass through a deterministic loop: fix → reply → resolve → re-request → poll. Each finding gets its own commit, each thread gets a reply citing the fix sha, and the loop terminates on a verified fresh re-review — not on the stale one that was already there. The same loop works for any bot reviewer with a stable slug.

When to Use

  • Copilot has left review comments on your PR and you want to drive them to a clean pass without babysitting the PR page
  • Bot review threads must be closed out before merge with an auditable fix → reply → resolve trail
  • You need to confirm a re-review landed on the new HEAD (the reviews list still contains the old review, so "a Copilot review exists" proves nothing)
  • Adapting the same mechanics to another bot reviewer that exposes review threads and a reviewer slug

Inputs

  • Required: A PR with an open bot review (PR number, or inferred from the current branch via gh pr view --json number)
  • Required: Authenticated gh CLI with access to the repository (the loop relies on the existing auth — no extra credentials)
  • Optional: Reviewer slug (default: copilot-pull-request-reviewer[bot])
  • Optional: Poll budget (default: ~20 iterations x 25 s ≈ 8 minutes)

Replace OWNER, REPO, and PR in the commands below with the repository owner, name, and PR number. See references/EXAMPLES.md for inferring all three from the current branch.

Procedure

Step 1: Locate the PR and Baseline the Bot's Latest Review

Capture the submitted_at of the bot's most recent review before you change anything. This baseline is what later distinguishes a fresh re-review from the stale review that triggered this loop.

# Infer the PR number from the current branch
gh pr view --json number --jq '.number'

# Baseline: latest Copilot review timestamp (may be null if none yet)
BASE=$(gh api repos/OWNER/REPO/pulls/PR/reviews \
  --jq '[.[]|select(.user.login=="copilot-pull-request-reviewer[bot]")]|last|.submitted_at')
echo "baseline: $BASE"

Expected: PR number resolved; BASE holds an ISO-8601 timestamp (or null when the bot has not reviewed yet — then any future review counts as new).

On failure: gh pr view errors when the current branch has no PR — pass the number explicitly. If the reviews list contains no bot entries at all, Copilot review may not be enabled on the repository; request it once (Step 6) before running the loop.

Step 2: List Open Review Threads with Both IDs

Every review thread carries two distinct identifiers, and they are never interchangeable:

  • the thread node-id (PRRT_...) — consumed by the GraphQL resolveReviewThread mutation (Step 5)
  • the comment databaseId (numeric) — consumed by the REST replies endpoint (Step 4)
gh api graphql -f query='query { repository(owner:"OWNER",name:"REPO"){
  pullRequest(number:PR){ reviewThreads(first:40){ nodes {
    id isResolved comments(first:1){ nodes { databaseId path line } } } } } } }' \
| jq -r '.data.repository.pullRequest.reviewThreads.nodes[]
         | select(.isResolved==false)
         | "\(.comments.nodes[0].databaseId) \(.id) \(.comments.nodes[0].path)"'

Expected: One line per unresolved thread: <databaseId> <PRRT_nodeId> <path>. Empty output means no open threads — skip to Step 8 to read the verdict.

On failure: GraphQL errors about owner/name/number mean the OWNER/REPO/PR placeholders were not replaced (note: number:PR takes a bare integer, not a quoted string). If the PR has more than 40 threads, raise first:40 or paginate.

Step 3: Fix Each Finding — One Commit per Finding

Read each finding and fix it in its own commit, so each thread reply in Step 4 can cite an exact sha. Record the thread → sha mapping as you go.

# Read the finding body (single-comment GET takes no PR number, unlike the Step 4 replies POST)
gh api repos/OWNER/REPO/pulls/comments/<databaseId> --jq '.body'

# ...make the change, then commit it alone...
git add <files>
git commit -m "fix: <what the finding asked for>"
git rev-parse --short HEAD   # record this sha for the thread's reply

Make the claim honest everywhere. When a finding cites the PR description (or a README, a doc comment, a changelog line), fixing only the code leaves the overstated claim standing. Edit every place the claim appears — for the PR description:

gh pr edit PR --body-file <corrected-body.md>

Expected: git log shows one commit per finding, and you hold a mapping of <databaseId>/<PRRT_nodeId> → fix sha. Any claim a finding cited is corrected at every location, not just in code.

On failure: If you disagree with a finding, make no commit — reply in Step 4 with your reasoning instead, then resolve. If one change genuinely closes two threads, cite the same sha in both replies rather than splitting a coherent commit.

Step 4: Reply to Each Thread with the Fix Sha

Reply via REST using the thread's first comment's databaseId (the numeric id from Step 2 — not the PRRT_... node-id):

gh api --method POST "repos/OWNER/REPO/pulls/PR/comments/<databaseId>/replies" -f body="Fixed in <sha> — <what changed>."

Expected: HTTP 201; the reply appears under the thread on the PR page. The sha link resolves once the branch is pushed (Step 6).

On failure: A 404 here almost always means the wrong ID type — a PRRT_... node-id was used where the numeric comment databaseId belongs. Re-read the Step 2 output: first column replies, second column resolves.

Step 5: Resolve Each Thread

Resolve via GraphQL using the thread node-id (PRRT_...):

gh api graphql -f query='mutation { resolveReviewThread(input:{threadId:"<PRRT_nodeId>"}){ thread { isResolved } } }'

Expected: Response contains "isResolved": true for each thread.

On failure: Could not resolve to a node with the global id means a numeric databaseId was passed where the PRRT_... node-id belongs. If a thread is already resolved, note that the bot auto-resolves threads on push — if you pushed before this step, re-run the Step 2 query and only mutate threads still reported isResolved==false.

Step 6: Push the Fixes and Re-Request the Review

Push first, then re-request — the bot reviews whatever HEAD it sees at request time:

git push

gh api --method POST repos/OWNER/REPO/pulls/PR/requested_reviewers -f "reviewers[]=copilot-pull-request-reviewer[bot]"

Note the two forms of the same identity: the POST takes the literal slug copilot-pull-request-reviewer[bot], but the pending entry then appears in requested_reviewers under the user form Copilot, while submitted reviews carry user.login == "copilot-pull-request-reviewer[bot]".

Expected: Push accepted; the PR's requested_reviewers now lists Copilot. Pushing may auto-resolve remaining open threads — that is normal bot behavior, not an error.

On failure: A 422 means the slug is misspelled or Copilot code review is not enabled for the repository. If you re-requested before pushing, the bot reviewed the stale HEAD — push, then POST the re-request again.

Step 7: Poll for the Async Re-Review

The re-review is asynchronous (typically 30 s to a few minutes). Poll against the Step 1 baseline; exit when a newer bot review lands, or when the bot drops out of requested_reviewers (it finished without posting new comments):

for i in $(seq 1 20); do   # 20 x 25s ≈ 8 min budget
  sleep 25
  LATEST=$(gh api repos/OWNER/REPO/pulls/PR/reviews \
    --jq '[.[]|select(.user.login=="copilot-pull-request-reviewer[bot]")]|last|.submitted_at')
  if [ "$LATEST" != "$BASE" ] && [ "$LATEST" != "null" ]; then
    echo "re-review landed: $LATEST"; break
  fi
  REQUESTED=$(gh api repos/OWNER/REPO/pulls/PR \
    --jq '[.requested_reviewers[].login] | any(. == "Copilot")')
  if [ "$REQUESTED" = "false" ]; then
    echo "Copilot left requested_reviewers — finished, no new comments"; break
  fi
done

Expected: The loop exits within a few minutes on one of the two conditions. Without a pre-change baseline the check is meaningless — the old review already satisfies "a Copilot review exists".

On failure: On timeout, check the PR page — the request may have been dropped; re-request (Step 6) and poll again. Keep the sleep at ~20-30 s; hammering the API tighter gains nothing and burns rate limit. See references/EXAMPLES.md for a poll variant with exit codes and finding printout.

Step 8: Read the Verdict and Decide

gh api repos/OWNER/REPO/pulls/PR/reviews \
  --jq '[.[]|select(.user.login=="copilot-pull-request-reviewer[bot]")]|last|{state,submitted_at,body}'

Interpret the result against how the bot actually reports:

  • COMMENTED is the bot's terminal state. Copilot does not return APPROVED or CHANGES_REQUESTED; a COMMENTED review is not a rejection.
  • Boilerplate is not a finding. A review body announcing "0 new comments" and/or the standing "human review recommended" style banner is fixed bot messaging — it does not block the PR.
  • Clean pass = the fresh review introduced zero new comments and the Step 2 thread query returns no unresolved threads.
  • New threads = re-enter the loop at Step 2 with the new findings.

Expected: An unambiguous verdict: clean pass (stop) or a concrete list of new threads (iterate).

On failure: When the prose is ambiguous, do not parse it — count unresolved threads with the Step 2 query. The thread count is ground truth; the review body is commentary.

Validation

  • Step 2 GraphQL query returns zero unresolved threads
  • git log shows one commit per addressed finding
  • Every thread carries a reply citing the fix commit sha (or won't-fix reasoning)
  • PR description (and any other cited location) corrected where a finding referenced it
  • Latest bot review submitted_at is newer than the Step 1 baseline, or the bot is no longer in requested_reviewers
  • Final verdict read via Step 8 and interpreted as a clean pass, not merely assumed from COMMENTED

Common Pitfalls

  • ID-type confusion: The single most common failure. The REST replies endpoint 404s when fed a PRRT_... thread node-id; the resolveReviewThread mutation errors when fed a numeric comment databaseId. Reply with the databaseId, resolve with the node-id.
  • Reading COMMENTED as a failing verdict: Copilot never approves; COMMENTED plus a "human review recommended" banner is its normal clean output. Treating it as a blocking finding stalls the merge on boilerplate.
  • Polling without a baseline: The reviews list still contains the pre-fix review, so a poll that merely checks "does a Copilot review exist" succeeds instantly against stale data and reports a false clean pass. Baseline submitted_at before re-requesting.
  • Re-requesting before pushing: The bot reviews the HEAD it sees at request time. Re-request first and it re-reviews the unfixed code — the same findings come straight back.
  • Squashing all fixes into one commit: Replies can no longer cite a per-finding sha, and the audit trail from finding to fix dissolves. One commit per finding.
  • Fixing the code but not the claim: A finding that cites the PR description is only half-fixed by a code change — edit the description too, or the dishonest claim survives and gets re-flagged.
  • Fighting the auto-resolve: The bot auto-resolves threads on push. Threads vanishing after git push is expected; re-check isResolved before mutating instead of treating it as data loss.

Related Skills

  • create-pull-request - opens and manages the PR this loop drives to a clean pass
  • review-pull-request - the human/agent-driven review counterpart to this bot loop
  • verify-web-app-runtime - runtime-verify the fix actually works before replying "Fixed in <sha>"
  • Copilot Review Loop guide - narrative walkthrough, provenance, and when the loop pays off

GitHub 저장소

pjt222/agent-almanac
경로: i18n/ja/skills/run-copilot-review-loop
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams
FAQ

자주 묻는 질문

run-copilot-review-loop Skill이란 무엇인가요?

run-copilot-review-loop은(는) pjt222이(가) 만든 Claude Skill입니다. Skill은 Claude가 필요할 때 불러오는 지침과 리소스를 묶어 추가 프롬프트 없이 run-copilot-review-loop 관련 작업을 수행할 수 있게 합니다.

run-copilot-review-loop은(는) 어떻게 설치하나요?

이 페이지의 설치 명령을 사용하세요. run-copilot-review-loop을(를) Claude Code 플러그인으로 추가하거나 저장소를 skills 디렉터리에 복제한 다음 Claude를 다시 시작해 Skill을 불러옵니다.

run-copilot-review-loop은(는) 어떤 카테고리에 속하나요?

run-copilot-review-loop은(는) 기타 카테고리에 속합니다.

run-copilot-review-loop은(는) 무료로 사용할 수 있나요?

네. run-copilot-review-loop은(는) AIMCP에 등록되어 있으며 무료로 설치할 수 있습니다.

연관 스킬

llamaguard
기타

LlamaGuard는 폭력 및 혐오 발언 등 6가지 안전 범주에서 LLM 입력과 출력을 조정하기 위한 Meta의 70-80억 파라미터 모델입니다. 94-95% 정확도를 제공하며 vLLM, Hugging Face 또는 Amazon SageMaker를 사용해 배포할 수 있습니다. 이 기술을 사용하여 AI 애플리케이션에 콘텐츠 필터링 및 안전 가드레일을 손쉽게 통합하세요.

스킬 보기
cost-optimization
기타

이 Claude Skill은 리소스 적정화, 태깅 전략, 지출 분석을 통해 개발자들이 클라우드 비용을 최적화할 수 있도록 지원합니다. AWS, Azure, GCP에서 클라우드 비용을 절감하고 비용 거버넌스를 구현하기 위한 프레임워크를 제공합니다. 인프라 비용을 분석하거나, 리소스를 적정화하거나, 예산 제약을 충족해야 할 때 사용하세요.

스킬 보기
sports-betting-analyzer
기타

이 Claude Skill은 스프레드, 오버/언더, 프로프 베트를 포함한 스포츠 베팅 시장을 분석합니다. 역사적 추이와 상황별 통계를 검토하여 가치 베트를 발견하고, 교육적 목적으로 실행 가능한 권장 사항이 담긴 구조화된 마크다운 결과를 제공합니다. 개발자는 이 기능을 스포츠 베팅 분석 도구에 활용할 수 있으며, 단순히 엔터테인먼트/교육 목적으로만 설계되었음을 유의해야 합니다.

스킬 보기
quantizing-models-bitsandbytes
기타

이 스킬은 bitsandbytes를 사용하여 LLM을 8비트 또는 4비트 정밀도로 양자화하며, 최소한의 정확도 손실로 50-75%의 메모리 감소를 달성합니다. 제한된 GPU 메모리에서 더 큰 모델을 실행하거나 추론을 가속화하는 데 이상적이며, INT8, NF4, FP4와 같은 형식을 지원합니다. 이 스킬은 HuggingFace Transformers와 통합되어 QLoRA 학습 및 8비트 옵티마이저를 가능하게 합니다.

스킬 보기