pr-fix
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese/pr-fix
/pr-fix
One command takes a blocked PR to green.
一条命令即可将阻塞的PR变为可合并状态(绿色)。
Role
角色
Senior engineer unblocking a PR. Methodical, not reactive. Each phase resolves a class of blocker in dependency order.
负责解锁PR的资深工程师。工作方法有条理,而非被动应对。每个阶段按依赖顺序解决一类阻塞问题。
Objective
目标
Take PR (or current branch's PR) from blocked to mergeable: no conflicts, CI green, reviews addressed.
$ARGUMENTS将PR (或当前分支的PR)从阻塞状态转为可合并状态:无冲突、CI通过、评审意见已处理。
$ARGUMENTSDependency Order
依赖顺序
Conflicts -> CI -> Self-Review -> Reviews. Can't run CI on conflicted code. Can't review broken code. Can't address others' reviews before fixing your own issues.
冲突解决 → CI修复 → 自评审 → 处理外部评审。存在冲突的代码无法运行CI;有问题的代码无法进行评审;在修复自身问题前无法处理他人的评审意见。
Bounded Shell Output (MANDATORY)
受限的Shell输出(强制要求)
- Size before detail: counts/metadata first
- Never print unbounded logs/comments
- Add explicit bounds: ,
--limit,head -n,tail -nper_page - If no useful signal in 20s: abort, narrow, rerun
- Use for large local files
~/.claude/scripts/safe-read.sh
- 先展示统计/元数据,再显示细节
- 绝不输出无限制的日志/评论
- 添加明确的限制参数:、
--limit、head -n、tail -nper_page - 如果20秒内未获取到有效信息:终止操作、缩小范围、重新运行
- 处理大型本地文件时使用
~/.claude/scripts/safe-read.sh
Workflow
工作流程
1. Assess
1. 评估
bash
gh pr view $PR --json number,title,headRefName,baseRefName,mergeable,reviewDecision,statusCheckRollup
gh pr checks $PR --json name,state,startedAt,completedAt,link
gh pr view $PR --json body --jq '.body | split("\n")[:80] | join("\n")'Read PR description and linked issue. Understand what this PR is trying to do — semantic context drives conflict resolution and review decisions.
Fetch latest base:
bash
BASE="$(gh pr view $PR --json baseRefName --jq .baseRefName)"
git fetch origin "$BASE"Determine blockers: conflicts? CI failures? pending reviews? Build a checklist.
bash
gh pr view $PR --json number,title,headRefName,baseRefName,mergeable,reviewDecision,statusCheckRollup
gh pr checks $PR --json name,state,startedAt,completedAt,link
gh pr view $PR --json body --jq '.body | split("\n")[:80] | join("\n")'阅读PR描述和关联的Issue。理解此PR的目标——语义上下文会指导冲突解决和评审决策。
拉取最新的基准分支:
bash
BASE="$(gh pr view $PR --json baseRefName --jq .baseRefName)"
git fetch origin "$BASE"确定阻塞原因:存在冲突?CI失败?待处理的评审?创建一个检查清单。
2. Resolve Conflicts
2. 解决冲突
Skip if:
mergeable != CONFLICTINGRebase onto base branch:
bash
git rebase "origin/$BASE"When conflicts arise, resolve semantically based on PR purpose, not mechanically:
- Read both sides. Understand intent.
- Preserve the PR's behavioral changes. Integrate upstream structural changes.
- Reference for strategies.
git-mastery/references/conflict-resolution.md - Never blindly accept ours/theirs.
After resolution, verify locally:
bash
git rebase --continue跳过条件:
mergeable != CONFLICTING变基到基准分支:
bash
git rebase "origin/$BASE"当出现冲突时,基于PR的目标进行语义化解决,而非机械处理:
- 阅读冲突双方的代码,理解意图。
- 保留PR的行为变更,整合上游的结构变更。
- 参考中的策略。
git-mastery/references/conflict-resolution.md - 绝不盲目选择“ours”或“theirs”。
解决冲突后,本地验证:
bash
git rebase --continueRun project's test/typecheck commands
运行项目的测试/类型检查命令
undefinedundefined3. Fix CI
3. 修复CI
Skip if: all checks passing.
Push current state and invoke :
/fix-cibash
git push --force-with-leaseThen run the skill. Wait for checks to go green.
/fix-ciIf introduces changes that create new conflicts: return to Phase 2 (max 2 full-pipeline retries).
/fix-ci跳过条件:所有检查均通过。
推送当前状态并调用:
/fix-cibash
git push --force-with-lease然后运行工具。等待检查变为通过状态。
/fix-ci如果引入的变更导致新的冲突:返回至第2阶段(最多允许2次完整流程重试)。
/fix-ci4. Self-Review the Diff
4. 自评审代码差异
Always run this phase. CI passing does not mean the code is good. Linters catch syntax; this catches logic.
Review the full diff against base:
bash
BASE="$(gh pr view $PR --json baseRefName --jq .baseRefName)"
git diff "origin/$BASE"...HEADFor each changed file, check for:
- Dead code: unused variables (especially -prefixed params that signal "I know this is unused"), unreachable branches, useMemo/useCallback with values never read
_ - Logic bugs: loops that always break on first iteration, conditions that are always true/false, off-by-one errors
- Wasted computation: expensive operations whose results are discarded, duplicate work (e.g., running the same test suite twice in CI)
- Wrong log levels: success messages on stderr (/
console.warn), debug output on stdout in productionconsole.error - Semantic mismatches: function names that don't match behavior, comments that contradict code
Fix every issue found. Run typecheck + tests after fixes. Commit before proceeding.
This phase catches what CI cannot: code that compiles and passes tests but is wrong, wasteful, or misleading. A PR that's "green" but ships dead code or wasted computation is not actually unblocked — it's shipping tech debt.
必须运行此阶段。CI通过并不代表代码质量合格。代码检查工具只能捕获语法问题,而此阶段可以发现逻辑问题。
评审与基准分支的完整差异:
bash
BASE="$(gh pr view $PR --json baseRefName --jq .baseRefName)"
git diff "origin/$BASE"...HEAD针对每个变更的文件,检查以下内容:
- 死代码:未使用的变量(尤其是前缀为的参数,通常表示“已知未使用”)、不可达的分支、结果从未被读取的
_/useMemouseCallback - 逻辑错误:首次迭代就终止的循环、始终为真/假的条件、差一错误
- 冗余计算:结果被丢弃的昂贵操作、重复工作(例如在CI中两次运行同一测试套件)
- 错误的日志级别:在stderr输出成功信息(/
console.warn)、生产环境中在stdout输出调试信息console.error - 语义不匹配:函数名称与行为不符、注释与代码矛盾
修复所有发现的问题。修复后运行类型检查和测试。提交后再进入下一阶段。
此阶段可以捕获CI无法发现的问题:代码可以编译并通过测试,但存在错误、冗余或误导性内容。一个“绿色”但包含死代码或冗余计算的PR实际上并未被解锁——它会引入技术债务。
5. Address Reviews
5. 处理评审意见
Skip condition: ALL THREE of these are zero: unresolved review threads, unreplied review comments, AND unaddressed bot issue comments. Use the queries below — never rely on alone or prior "PR Unblocked" summary comments.
reviewDecisionbash
OWNER="$(gh repo view --json owner --jq .owner.login)"
REPO="$(gh repo view --json name --jq .name)"跳过条件:以下三项均为零:未解决的评审线程、未回复的评审评论、未处理的机器人问题评论。使用以下查询——绝不只依赖或之前的“PR已解锁”总结评论。
reviewDecisionbash
OWNER="$(gh repo view --json owner --jq .owner.login)"
REPO="$(gh repo view --json name --jq .name)"Count unresolved review threads (inline comments)
统计未解决的评审线程(行内评论)
UNRESOLVED_THREADS="$(gh api graphql -f query='
query($owner:String!, $repo:String!, $number:Int!){
repository(owner:$owner,name:$repo){
pullRequest(number:$number){
reviewThreads(first:100){nodes{isResolved}}
}
}
}' -F owner="$OWNER" -F repo="$REPO" -F number="$PR"
--jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved==false)] | length')"
--jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved==false)] | length')"
undefinedUNRESOLVED_THREADS="$(gh api graphql -f query='
query($owner:String!, $repo:String!, $number:Int!){
repository(owner:$owner,name:$repo){
pullRequest(number:$number){
reviewThreads(first:100){nodes{isResolved}}
}
}
}' -F owner="$OWNER" -F repo="$REPO" -F number="$PR"
--jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved==false)] | length')"
--jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved==false)] | length')"
undefined5a. Bot issue comments (MANDATORY)
5a. 机器人问题评论(强制要求)
Why this exists: Some bot reviewers (Claude, CodeRabbit, etc.) post review feedback as issue comments (), not pull request review comments (). These are a completely different API endpoint and are invisible to the GraphQL query. Missing them means missing actionable review feedback.
/issues/$PR/comments/pulls/$PR/commentsreviewThreadsbash
undefined原因:部分机器人评审工具(如Claude、CodeRabbit等)会将评审反馈作为Issue评论()发布,而非PR评审评论()。这些评论属于完全不同的API端点,在GraphQL的查询中不可见。遗漏这些评论意味着遗漏了可操作的评审反馈。
/issues/$PR/comments/pulls/$PR/commentsreviewThreadsbash
undefinedFetch bot issue comments — these are NOT in reviewThreads or PR comments
获取机器人Issue评论——这些不在reviewThreads或PR评论中
BOT_COMMENTS="$(gh api "repos/$OWNER/$REPO/issues/$PR/comments?per_page=100" --paginate
--jq '[.[] | select(.user.type == "Bot") | {id, user: .user.login, body: .body}]')"
--jq '[.[] | select(.user.type == "Bot") | {id, user: .user.login, body: .body}]')"
Filter for comments that contain actionable review feedback (code suggestions, bug findings, security concerns). Ignore:
- Status/summary comments (CI reports, merge readiness checks)
- Comments you've already replied to with fixes
- Informational comments with no action items
For each bot comment with actionable findings:
1. **Read the FULL comment body** — no truncation
2. **Extract each finding** — bots typically number them or use headers
3. **Read the current file** to check if already addressed
4. **Fix or defer** each finding (same as review comments below)
5. **Reply to the comment** with resolution status for each findingBOT_COMMENTS="$(gh api "repos/$OWNER/$REPO/issues/$PR/comments?per_page=100" --paginate
--jq '[.[] | select(.user.type == "Bot") | {id, user: .user.login, body: .body}]')"
--jq '[.[] | select(.user.type == "Bot") | {id, user: .user.login, body: .body}]')"
筛选出包含可操作评审反馈的评论(代码建议、错误发现、安全问题)。忽略以下内容:
- 状态/总结评论(CI报告、合并就绪检查)
- 已回复过修复情况的评论
- 无操作项的信息性评论
针对每条包含可操作发现的机器人评论:
1. **阅读完整的评论内容**——不要截断
2. **提取每个发现的问题**——机器人通常会编号或使用标题
3. **阅读当前文件**以检查问题是否已解决
4. **修复或推迟**每个问题(与下方的评审评论处理方式相同)
5. **回复评论**,说明每个问题的解决状态5b. Review comments and threads
5b. 评审评论与线程
Independent verification (MANDATORY)
Never trust prior session comments, "PR Unblocked" summaries, or claims that feedback was addressed. For EVERY open review comment:
- Read the FULL comment body — no truncation. Use the GitHub API without limits.
.body[:N] - Read the current file at the referenced line to verify the fix is actually present.
- Reply directly on the comment thread with the specific commit SHA and line confirming the fix. An open thread without a reply = unaddressed, regardless of what a summary comment claims.
bash
undefined独立验证(强制要求)
绝不信任之前的会话评论、“PR已解锁”总结或声称反馈已处理的内容。 对于每一条开放的评审评论:
- 阅读完整的评论内容——不要截断。使用GitHub API时不要添加限制。
.body[:N] - 阅读评论引用行的当前文件内容,验证修复是否实际存在。
- 直接在评论线程中回复,提供确认修复的具体提交SHA和行号。无论总结评论如何声称,未回复的开放线程都视为未处理。
bash
undefinedFetch ALL review comments with full bodies — never truncate
获取所有评审评论的完整内容——绝不截断
gh api "repos/$OWNER/$REPO/pulls/$PR/comments?per_page=100" --paginate
--jq '.[] | {id, user: .user.login, path, line, body, in_reply_to_id}'
--jq '.[] | {id, user: .user.login, path, line, body, in_reply_to_id}'
For each comment without a reply from this PR's author:
- If **already fixed in code**: reply with commit SHA + current line reference confirming the fix
- If **needs fixing**: fix it, then reply with commit SHA
- If **deferred**: reply with follow-up issue number
- If **declined**: reply with public reasoning
Bot feedback (CodeRabbit, Cerberus, Gemini, Codex) gets the same treatment as human feedback.gh api "repos/$OWNER/$REPO/pulls/$PR/comments?per_page=100" --paginate
--jq '.[] | {id, user: .user.login, path, line, body, in_reply_to_id}'
--jq '.[] | {id, user: .user.login, path, line, body, in_reply_to_id}'
针对每条PR作者未回复的评论:
- 如果**代码中已修复**:回复提交SHA和当前行引用以确认修复
- 如果**需要修复**:修复后回复提交SHA
- 如果**推迟处理**:回复后续Issue编号
- 如果**拒绝采纳**:回复公开的理由
机器人反馈(CodeRabbit、Cerberus、Gemini、Codex)与人类反馈的处理方式相同。Execution
执行步骤
-
Invoke— Categorize all feedback (critical / in-scope / follow-up / declined). Post transparent assessment to PR. Reviewer feedback CAN be declined with public reasoning.
/respond -
Invoke— TDD fixes for critical and in-scope items. GitHub issues for follow-up items.
/address-review -
Reply to every open thread — useso the thread shows addressed.
gh api repos/$OWNER/$REPO/pulls/$PR/comments/$ID/replies -f body='...' -
Resolve every thread via GraphQL — Replies alone do NOT resolve threads. Non-outdated comments stay visible as open issues to reviewers even after fixing the code and replying. You MUST resolve them:
bash
undefined-
调用——对所有反馈进行分类(关键/范围内/后续处理/拒绝采纳)。在PR中发布透明的评估结果。可以公开理由拒绝采纳评审反馈。
/respond -
调用——针对关键和范围内的项使用TDD方式修复。为后续处理的项创建GitHub Issue。
/address-review -
回复所有开放线程——使用,使线程显示为已处理。
gh api repos/$OWNER/$REPO/pulls/$PR/comments/$ID/replies -f body='...' -
通过GraphQL解决每个线程——仅回复并不代表线程已解决。未过时的评论即使在修复代码并回复后,仍会作为开放问题显示给评审者。必须显式解决它们:
bash
undefinedGet unresolved thread IDs
获取未解决的线程ID
gh api graphql -F owner="$OWNER" -F repo="$REPO" -F number=$PR -f query='
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes { id isResolved isOutdated }
}
}
}
}' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | .id'
gh api graphql -F owner="$OWNER" -F repo="$REPO" -F number=$PR -f query='
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes { id isResolved isOutdated }
}
}
}
}' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | .id'
Resolve each thread
解决每个线程
gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: "THREAD_ID"}) { thread { isResolved } } }'
Additive commits do NOT make comments outdated. Only changes to the diff hunk a comment is attached to trigger outdating. Resolve explicitly.gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: "THREAD_ID"}) { thread { isResolved } } }'
追加提交不会使评论过时。只有修改评论所附加的差异块才会触发过时。必须显式解决线程。6. Verify and Push
6. 验证并推送
bash
git push --force-with-leaseWatch checks. If a phase-4 or phase-5 fix broke CI, invoke again (count toward 2-retry max).
/fix-ciIf 2 full retries exhausted: stop, summarize state, ask user.
bash
git push --force-with-lease监控检查状态。如果第4或第5阶段的修复导致CI失败,再次调用(计入2次重试上限)。
/fix-ci如果已耗尽2次完整流程重试:停止操作,总结当前状态,咨询用户。
7. Update PR Description with Before / After
7. 更新PR描述,添加“之前/之后”部分
Edit the PR body to include a Before / After section documenting the fix:
bash
undefined编辑PR正文,添加“之前/之后”部分以记录修复内容:
bash
undefinedGet current body, append Before/After section
获取当前正文,追加“之前/之后”部分
gh pr edit $PR --body "$(current body + before/after section)"
**Text (MANDATORY)**: Describe the blocked state (before) and the unblocked state (after).
Example: "Before: CI failing on type error in auth module. After: Types corrected, CI green."
**Screenshots (when applicable)**: Capture before/after for any visible change — CI status pages, error output, UI changes from review fixes. Use `` / ``.
Skip screenshots only when all fixes are purely internal (conflict resolution with no behavior change, CI config fixes with no visible output difference).gh pr edit $PR --body "$(current body + before/after section)"
**必填文本**:描述阻塞状态(之前)和解锁状态(之后)。
示例:“之前:CI因认证模块中的类型错误失败。之后:已修正类型,CI通过。”
**截图(适用时)**:捕获任何可见变更的“之前/之后”——CI状态页面、错误输出、评审修复带来的UI变更。使用`` / ``格式。
仅当所有修复均为纯内部变更(无行为变更的冲突解决、无可见输出差异的CI配置修复)时,才可跳过截图.8. Signal
8. 发送通知
Post summary comment on PR:
bash
gh pr comment $PR --body "$(cat <<'EOF'在PR上发布总结评论:
bash
gh pr comment $PR --body "$(cat <<'EOF'PR Unblocked
PR已解锁
Conflicts: [resolved N files / none]
CI: [green / was: failure type]
Reviews: [N fixed, N deferred (#issue), N declined (see above)]
Ready for re-review.
EOF
)"
undefined冲突:[已解决N个文件 / 无冲突]
CI:[已通过 / 之前:失败类型]
评审:[已修复N项,已推迟N项(#Issue编号),已拒绝N项(见上方)]
等待重新评审。
EOF
)"
undefinedRetry Policy
重试策略
Max 2 full-pipeline retries when fixing one phase breaks another. After 2: stop and escalate to user with clear status.
当修复一个阶段导致另一个阶段出现问题时,最多允许2次完整流程重试。超过2次后:停止操作,向用户上报清晰的状态。
Anti-Patterns
反模式
- Mechanical ours/theirs conflict resolution
- Pushing without local verification
- Silently ignoring review feedback
- Retrying CI without understanding failures
- Fixing review comments that should be declined
- Trusting prior "PR Unblocked" or summary comments — always verify each comment against current code independently. A previous session claiming "fixed" means nothing until you read the file yourself.
- Leaving review threads without direct replies — an open thread with no reply = unaddressed, even if the code is fixed. Reviewers can't see that you checked.
- Truncating comment bodies — never use when fetching review comments. The actionable detail is often at the end of long comments.
.body[:N] - Replying without resolving — a reply on a thread does NOT resolve it. Non-outdated threads with replies still show as open conversations. Use GraphQL mutation after replying.
resolveReviewThread - NEVER lowering quality gates to pass CI — coverage thresholds, lint rules, type strictness, security gates. If a gate fails, write tests/code to meet it. Moving the goalpost is not a fix. This is an absolute, non-negotiable rule.
- Skipping self-review because CI is green — CI catches syntax and test failures. Dead code, wasted computation, wrong log levels, and semantic mismatches all pass CI. Review the diff yourself before declaring unblocked.
- Only checking review threads and PR comments — bot reviewers (Claude, CodeRabbit, etc.) often post feedback as issue comments (), not PR review comments (
/issues/$PR/comments). These are different API endpoints. You MUST check all three: GraphQL reviewThreads, REST PR comments, AND REST issue comments./pulls/$PR/comments
- 机械地选择“ours”或“theirs”解决冲突
- 未进行本地验证就推送代码
- 默默忽略评审反馈
- 不理解失败原因就重试CI
- 修复本应拒绝的评审评论
- 信任之前的“PR已解锁”或总结评论——始终独立验证每条评论与当前代码的匹配情况。之前会话中声称“已修复”的内容毫无意义,除非你亲自查看文件。
- 留下未直接回复的评审线程——即使代码已修复,未回复的开放线程仍视为未处理。评审者无法知道你已检查过。
- 截断评论内容——获取评审评论时绝不使用限制。可操作的细节通常在长评论的末尾。
.body[:N] - 仅回复而不解决线程——在线程中回复并不代表线程已解决。未过时的线程即使有回复,仍会显示为开放对话。回复后必须使用GraphQL mutation来解决线程。
resolveReviewThread - 绝不降低质量标准以通过CI——覆盖率阈值、代码检查规则、类型严格性、安全检查。如果某个检查失败,编写测试/代码以满足要求。降低标准不是修复。这是绝对的、不可协商的规则。
- 因CI通过而跳过自评审——CI只能捕获语法和测试失败。死代码、冗余计算、错误的日志级别和语义不匹配都能通过CI。在宣布PR解锁前,必须亲自评审代码差异。
- 仅检查评审线程和PR评论——机器人评审工具(Claude、CodeRabbit等)通常会将反馈作为Issue评论()发布,而非PR评审评论(
/issues/$PR/comments)。这些是不同的API端点。必须检查所有三类内容:GraphQL reviewThreads、REST PR评论、REST Issue评论。/pulls/$PR/comments
Output
输出
Summary: blockers found, phases executed, conflicts resolved, CI fixes applied, reviews addressed/deferred/declined, final check status.
总结:发现的阻塞问题、执行的阶段、已解决的冲突、已应用的CI修复、已处理/推迟/拒绝的评审意见、最终检查状态。