Rebut
풀 리퀘스트의 AI 코드 리뷰 댓글을 엄격하게 분류하고 답변합니다. 각 지적을 실제 코드와 대조하여 확인하고, 실제 버그는 수정하며, 거짓 양성은 증거를 들어 반박하고, 각 스레드에 자동 분류임을 표시하여 답변을 게시합니다. 사람이 'Resolve' 버튼을 클릭하는 것은 그대로 둡니다.
이 스킬은 사람 리뷰의 대응물이지, 복사본이 아닙니다. CodeRabbit이나 Gemini Code Assist와 같은 AI 리뷰어는 훨씬 더 많은 지적을 게시하고, 실제 버그와 거짓 양성을 혼합하며, 저장소를 인식하지 못합니다. 로컬 설정, 규칙, 도구를 알지 못하므로, 저장소에 올바른 패턴을 버그로 확신 있게 표시합니다. 봇의 심각도가 정확성을 의미하지는 않습니다: CRITICAL이 거짓 양성일 수도 있고, 사소한 지적이 실제 버그를 숨길 수도 있습니다.
AI 리뷰어가 별도의 분류를 받는 이유
- 저장소를 인식하지 못함. 봇은 로컬 설정(린터, 포매터, 타입 체커 설정 등)이나 내부 규칙을 로드하지 않습니다. 따라서 자체 도구가 요구하는 패턴을 플래그로 표시합니다. 실제 사례(ESLint 저장소): 리뷰어가
meta.defaultOptions를 CRITICAL "오류"로 표시했지만, 저장소의require-meta-default-options린트 규칙이 이를 강제합니다. 제안을 적용했다면 빌드가 깨졌을 것입니다. 맹목적 적용은 맹목적 무시만큼 위험합니다. - 높은 거짓 양성 비율. 많은 지적이 추측성 또는 스타일 전용입니다. 일부는 사람이 놓친 실제 버그입니다. 임무는 이를 느낌이 아닌 증거로 분리하는 것입니다.
- 확신에 찬 오류. 심각도 레이블은 휴리스틱입니다.
CRITICAL을 사소한 지적과 동일하게 확인하십시오.
리뷰어가 사람인 경우
파이프라인은 모든 리뷰어(봇 또는 사람)에 대해 동일합니다: 현재 코드와 대조하여 확인 → 증거와 함께 수정 또는 반박 → 귀속 라인 아래 스레드에 답변 → 적용 범위 증명. 사람 기여자나 리뷰어도 분류 루프의 일부입니다: 사람이 변경을 요청하면 수정하고 답변하며, 사람 게이트가 병합 시 읽는 것과 동일한 엄격함과 동일한 감사 추적을 따릅니다. 어조만 바뀝니다. 왜냐하면 사람은 저장소를 알고, 더 적고 더 신호가 높은 지적을 게시하며, 무뚝뚝한 반박이 위협이 될 수 있는 얼굴이 있기 때문입니다. 따라서 리뷰어가 사람인 경우:
- 봇 프레이밍을 버리십시오. 그들의 리뷰를 저장소를 인식하지 못하는, 거짓 양성이 많은 노이즈로 취급하지 마십시오; 일반적으로 그렇지 않습니다.
- 협력하고, 무뚝뚝하게 반박하지 마십시오. 확인한 후, 옳은 것은 수정하고 잘못된 것은 기술적 추론으로 반박하십시오. 수행적 동의나 동료에게 향한 무뚝뚝한 "거짓 양성"은 절대 하지 마십시오; 기술적으로 추론된 어조로 이유를 명시하십시오.
- 귀속 라인과 함께 직접 답변을 게시하십시오. 봇 스레드와 동일하게 사람 스레드를 자율적으로 분류합니다: 귀속 라인으로 열린 분류 계정을 통해 게시하여, 독자가 유지 관리자의 자체 피어 리뷰가 아닌 자동화된 분류를 볼 수 있도록 합니다. 댓글을 유지 관리자로부터 분리하는 라인은 바로 사람 스레드에 자동 게시를 안전하게 만드는 요소입니다. 적용 범위는 사람 스레드도 포함합니다(5.5단계). 따라서 답변되지 않은 사람 지적은 라운드를 계속 열어 둡니다.
아래 단계는 봇과 사람 모두에게 적용됩니다; 귀속 마커와 자동 답변은 둘 다에 사용됩니다. 유일한 리뷰어별 적응은 위의 어조입니다.
사전 점검
"${CLAUDE_SKILL_DIR}/scripts/preflight.sh"
preflight.sh는 gh가 인증되었고 저장소에 GitHub 리모트가 있는지 확인합니다. 필수 조건이 누락된 경우 stderr에 수정 방법을 인쇄하고 0이 아닌 종료 코드를 반환합니다; 이를 중계하고 중지하십시오. PR을 식별하십시오: [pr-number] 인수, 또는 현재 브랜치의 PR(gh pr view --json number).
1단계: 모든 지적 수집
"${CLAUDE_SKILL_DIR}/scripts/gather-review.sh" <pr>
gather-review.sh는 각 리뷰의 작성자, 상태, 본문을 포함하는 REVIEWS 블록과 각 인라인 댓글의 작성자, path:line, id=<id>, 본문을 포함하는 COMMENTS 블록을 gh의 내장 --jq를 통해 인쇄하므로, 어떤 것도 만들어지거나 누락되지 않습니다. 각 지적을 작성자, path:line, 답변에 필요한 댓글 id, 본문과 함께 나열하십시오. 최상위 리뷰 요약과 모든 인라인 댓글을 포함하십시오. 하나도 놓치지 마십시오. 각 스레드의 작성자를 봇(수집된 출력에 표시된 [bot] 로그인 접미사로 인식 가능) 또는 사람으로 태그하십시오: 둘 다 4-6단계를 따르며, 사람 스레드는 위의 "리뷰어가 사람인 경우"에 설명된 어조 조정을 추가로 적용합니다.
분류하기 전에 라운드가 안정될 때까지 기다리십시오. 리뷰어는 비동기적으로 실행됩니다: 두 번째 봇은 첫 번째 봇보다 몇 분 늦게 도착하는 경우가 많습니다. 따라서 PR이 업데이트되는 즉시 gather를 실행하면 지금까지 게시된 리뷰어만 포착됩니다. 첫 번째 gather 후, gh pr checks <pr> --watch || true로 라운드를 안정시키십시오: PR의 검사가 완료될 때까지 차단되며, 대화형 및 헤드리스 환경에서 동일하게 작동하며, 비동기 리뷰어가 게시하는 창입니다(|| true는 검사가 없는 PR의 0이 아닌 종료를 실패로 읽지 않도록 합니다). 그런 다음 gather-review.sh를 다시 실행하십시오. 새로운 지적이 나타나면 라운드가 아직 도착 중인 것이므로, 다시 watch하고 gather하십시오. (PR에 검사가 없으면 --watch는 즉시 반환됩니다. 리뷰 전용 봇은 검사 실행을 전혀 등록하지 않을 수 있으므로, 두 경우 모두 잠시 멈추고 검사 상태에 관계없이 다시 gather하십시오. 아래의 라운드 간 자동화는 이 안정화 후에 게시하는 리뷰어에 대한 실제 백스톱입니다.) 다시 gather해도 새로운 것이 없을 때만 분류를 시작하십시오. 이는 여러 리뷰어 라운드를 리뷰어 A의 지적에서 시작하여 리뷰어 B가 아직 게시 중인 동안 시작하는 대신(전체 두 번째 패스를 강제함) 하나의 분류 패스로 처리합니다. 이 경계는 영원히 기다리는 것을 방지합니다. 마지막 섹션의 라운드 간 자동화는 스킬이 종료된 후 게시하는 리뷰어에 대한 내구성 있는 해결책입니다.
2단계: 각 지적 확인 (이 스킬의 핵심)
각 지적에 대해 현재 코드(봇의 프레이밍이 아님)에 대해 두 가지 질문에 답하십시오:
- 문제가 재현됩니까?
${CLAUDE_SKILL_DIR}/references/debugging.md에 설명된 대로 재현하십시오: 해당 라인의 파일을 열고, 로직을 추적하고, 봇이 설명하는 입력을 구성하고, 실제 동작을 확인하십시오. 버그라면 입증 가능해야 합니다. - 제안이 이 저장소에 대해 올바릅니까? 저장소가 정의하는 관련 게이트(린터, 타입 체커, 테스트 등 존재하는 것)를 실행하십시오. 문서화된 규칙을 확인하십시오. 봇은 통과하지만 저장소 게이트는 실패하는 수정은 여기서 잘못된 것입니다.
한 번에 하나씩 변경하고 재확인하십시오. 일괄 처리하지 마십시오.
3단계: 분류
| 평결 | 의미 | 조치 |
|---|---|---|
| FIX | 실제, 재현됨 | 수정 (4단계) |
| REFUTE | 이 저장소에 대한 거짓 양성 | 반증하는 증거와 함께 답변 |
| INTENTIONAL | 봇이 볼 수 없는 의도적 선택 | 의도를 설명하는 답변 |
| MINOR | 표면적, 게이트 통과에 영향 없음 | 기록; 유지 관리자의 기준에 따라 수정 또는 건너뜀 |
4단계: 유효한 지적 수정
- 지적 범위에 국한된 최소 변경. 버그의 경우, 먼저 실패하는 테스트를 작성하고, 실패를 확인한 후, 수정하고, 통과를 확인하십시오.
- 저장소의 전체 게이트를 실행하십시오. 빨간 게이트는 수정을 차단합니다.
- 전체 라운드를 하나의 커밋에 담아 푸시하고, 지적당 하나씩 푸시하지 마십시오. 2단계에서와 같이 각 지적을 하나씩 확인하고 수정하되, 모든 수정 사항을 스테이징하고 함께 커밋한 후, 한 번에 푸시하십시오. PR을 소유하고 답변을 게시하는 유지 관리자 계정으로 푸시하십시오. 지적당 푸시는 하나의 리뷰 사이클을 여러 개로 만듭니다: 각 푸시는 CI를 다시 실행하고 모든 봇을 다시 트리거하므로, 5개의 수정 사항은 5번의 CI 실행과 5번의 재리뷰 웨이브가 됩니다. 라운드당 하나의 커밋은 1번의 CI 실행과 1번의 재리뷰 웨이브입니다. 해당 단일 SHA를 포착하십시오. 5단계의 모든 수정 답변에서 이를 인용하십시오. 원격 브랜치가 이동하여(릴리스 봇의 범프 또는 PR "Update branch" 병합이 라운드 중에 커밋을 추가함) 푸시가 비-빨리감기로 거부되면 중지하지 말고 복구하십시오:
git fetch후git rebase origin/<branch>, 게이트를 다시 실행하고, 다시 푸시하십시오. 절대--force를 사용하지 마십시오. 리베이스는 커밋을 다시 작성하므로, 새로운 SHA를 다시 포착하고 5단계 답변에서 리베이스 전의 오래된 SHA 대신 인용하십시오.
5단계: 각 스레드에 답변
원래 댓글에 답변하여 인라인으로 스레드되도록 하고, 최상위 PR 댓글은 절대 사용하지 마십시오.
모든 답변을 동일한 귀속 라인으로 시작하십시오. 예외 없이 모든 스레드에 적용합니다. 유지 관리자의 gh 토큰을 통해 게시하므로, GitHub는 유지 관리자의 아바타를 표시하고 독자는 유지 관리자가 작성했다고 가정합니다. 귀속 라인은 에이전트를 지명하고 댓글을 유지 관리자로부터 분리하므로, 자동화된 분류가 유지 관리자의 개인 리뷰로 오인되지 않습니다:
🤖 Automated triage by Claude Code, posted through the maintainer's account, not a personal review.
저장소에 봇 또는 머신 계정이 있는 경우 해당 ID로 게시하여 작성자 자체가 비개인적이도록 하십시오. 귀속 라인은 개인 토큰에 대한 폴백입니다.
본문을 파일에 작성하십시오. 귀속 라인은 본문을 여러 줄로 만들어 인라인 -f body="..." 인용을 깨뜨립니다. 수정 답변 예시:
> 🤖 Automated triage by Claude Code, posted through the maintainer's account, not a personal review.
**rebut** fixed in <sha>: <변경 사항에 대한 한 줄 설명>.
반박은 증거를 명시합니다:
> 🤖 Automated triage by Claude Code, posted through the maintainer's account, not a personal review.
**rebut** not changing this: <구체적인 이유, 예: 저장소 린트 규칙이 요구함; 게이트 통과>.
각 답변을 post-reply.sh로 한 번에 하나씩 게시하십시오:
"${CLAUDE_SKILL_DIR}/scripts/post-reply.sh" <pr> <comment_id> /tmp/reply.md
post-reply.sh는 GitHub의 보조 속도 제한 아래에서 게시 속도를 조절한 다음, API 응답에서 생성된 답변 ID를 읽어 유지되었는지 확인하고, 게시가 제한될 때 백오프와 함께 재시도합니다. 성공 시 답변 ID를 인쇄하고 0으로 종료합니다. 종료 코드 1은 답변이 게시되지 않았음을 의미합니다(계속하지 말고 수정 후 재실행). 종료 코드 2는 잘못된 인수입니다. 루프에서 원시 gh api .../replies 호출을 직접 작성하지 마십시오: 연속 게시는 속도 제한을 유발하고 사라집니다. 이 스크립트가 방지하는 정확한 실패입니다. 하나의 지적, 하나의 post-reply.sh 호출, 순차적으로.
답변만 하고, 절대 Resolve하지 마십시오. API를 통해 답변을 게시하십시오. "Resolve conversation"을 클릭하지 마십시오. 초록색 Resolve 버튼은 사람 리뷰어의 것입니다. 사람 리뷰어는 이 스킬의 작업을 확인하는 방법으로 사용합니다: 각 스레드를 읽고, 답변이 있는지 확인하고, 요약 댓글이 있는지 확인한 후에만 Resolve합니다. 스킬이 Resolve하면 사람은 자신 또는 에이전트가 스레드를 닫았는지 알 수 없으며, 이는 정확히 사람이 재확인하거나 분류를 다시 실행하게 만드는 혼란입니다. 이 스킬의 전체 출력은 답변과 하나의 요약 댓글입니다. Resolve 버튼은 사람의 것입니다.
빈 스레드를 남기지 마십시오. 1단계에서 수집된 모든 지적은 답변을 받습니다: SHA가 포함된 FIX, 또는 이유가 포함된 REFUTE / INTENTIONAL / MINOR. 봇이든 사람이든 응답이 없는 지적은 분류되지 않은 작업과 구별할 수 없습니다. 리뷰어는 스킬이 실행되었는지 알 수 없으므로 다시 호출하고 라운드가 반복됩니다. 침묵은 절대 평결이 아닙니다. 지적에 동의하지 않더라도 명시된 이유가 필요하며, 빈 스레드는 절대 안 됩니다.
5.5단계: 적용 범위 확인, CI 재확인, 수정 푸시가 유발한 라운드 포착
요약하기 전에:
-
적용 범위 확인 (항상). 게시 후 PR을 다시 조회하여 모든 지적(봇 또는 사람)이 분류 계정의 답변을 받았는지 확인하십시오:
"${CLAUDE_SKILL_DIR}/scripts/verify-coverage.sh" <pr>지적당 한 행(
answered/MISSING)을 인쇄한 후answered N / M을 인쇄합니다. 종료 코드 0은 모든 지적에 답변이 있음을 의미합니다(라운드가 커버됨). 종료 코드 1은 각MISSING지적을 나열하므로,post-reply.sh로 다시 게시하고answered N / N을 보고할 때까지 다시 실행하십시오. 종료 코드 2는 읽기/인수 오류로, 적용 범위가 아니므로 이를 표면화하십시오. 이는 평결에 관계없이 실행됩니다. 수정 사항이 푸시되지 않은 모든 REFUTE 라운드를 포함하여, 드롭된 반박 답변은 드롭된 수정 답변만큼 보이지 않습니다. 지적이MISSING인 동안에는 6단계로 진행하지 마십시오. -
CI 재확인. 검사가 여전히 안정화 중인 경우
gh pr checks <pr> --watch로 기다린 후,"${CLAUDE_SKILL_DIR}/scripts/ci-status.sh" <pr>로 분류하십시오:ci: green(종료 코드 0)은 통과.ci: failing(종료 코드 1)은 차단되므로 디버그.ci: none(종료 코드 3)은 CI가 구성되지 않았음을 의미하며, 이는 실패가 아니므로, 기록하고 계속 진행합니다. implement 스킬이 처리하는 것과 정확히 동일합니다.ci: pending(종료 코드 4)은--watch를 다시 실행한 후 다시 프로브하십시오. 읽기 오류(종료 코드 2)는 "green"이 아니므로 표면화하십시오. 직접 눈으로 초록색을 확인하십시오. 스크립트의 증거 없이 단언하지 마십시오. 모든 지적이 REFUTE 또는 INTENTIONAL이어서 4단계에서 변경된 사항이 없으면 새로운 푸시가 없으므로, 이 CI 재확인과 아래의 라운드 포착은 다시 트리거할 것이 없습니다. 위의 적용 범위 확인은 여전히 실행됩니다. -
새로운 라운드 포착. 수정 푸시가 ...