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
$ARGUMENTS
(or current branch's PR) from blocked to mergeable: no conflicts, CI green, reviews addressed.
将PR
$ARGUMENTS
(或当前分支的PR)从阻塞状态转为可合并状态:无冲突、CI通过、评审意见已处理。

Dependency 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 -n
    ,
    per_page
  • If no useful signal in 20s: abort, narrow, rerun
  • Use
    ~/.claude/scripts/safe-read.sh
    for large local files
  • 先展示统计/元数据,再显示细节
  • 绝不输出无限制的日志/评论
  • 添加明确的限制参数:
    --limit
    head -n
    tail -n
    per_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 != CONFLICTING
Rebase 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
    git-mastery/references/conflict-resolution.md
    for strategies.
  • 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 --continue

Run project's test/typecheck commands

运行项目的测试/类型检查命令

undefined
undefined

3. Fix CI

3. 修复CI

Skip if: all checks passing.
Push current state and invoke
/fix-ci
:
bash
git push --force-with-lease
Then run the
/fix-ci
skill. Wait for checks to go green.
If
/fix-ci
introduces changes that create new conflicts: return to Phase 2 (max 2 full-pipeline retries).
跳过条件:所有检查均通过。
推送当前状态并调用
/fix-ci
bash
git push --force-with-lease
然后运行
/fix-ci
工具。等待检查变为通过状态。
如果
/fix-ci
引入的变更导致新的冲突:返回至第2阶段(最多允许2次完整流程重试)。

4. 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"...HEAD
For 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
    /
    console.error
    ), debug output on stdout in production
  • 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
针对每个变更的文件,检查以下内容:
  • 死代码:未使用的变量(尤其是前缀为
    _
    的参数,通常表示“已知未使用”)、不可达的分支、结果从未被读取的
    useMemo
    /
    useCallback
  • 逻辑错误:首次迭代就终止的循环、始终为真/假的条件、差一错误
  • 冗余计算:结果被丢弃的昂贵操作、重复工作(例如在CI中两次运行同一测试套件)
  • 错误的日志级别:在stderr输出成功信息(
    console.warn
    /
    console.error
    )、生产环境中在stdout输出调试信息
  • 语义不匹配:函数名称与行为不符、注释与代码矛盾
修复所有发现的问题。修复后运行类型检查和测试。提交后再进入下一阶段。
此阶段可以捕获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
reviewDecision
alone or prior "PR Unblocked" summary comments.
bash
OWNER="$(gh repo view --json owner --jq .owner.login)"
REPO="$(gh repo view --json name --jq .name)"
跳过条件:以下三项均为零:未解决的评审线程、未回复的评审评论、未处理的机器人问题评论。使用以下查询——绝不只依赖
reviewDecision
或之前的“PR已解锁”总结评论。
bash
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')"
undefined
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')"
undefined

5a. Bot issue comments (MANDATORY)

5a. 机器人问题评论(强制要求)

Why this exists: Some bot reviewers (Claude, CodeRabbit, etc.) post review feedback as issue comments (
/issues/$PR/comments
), not pull request review comments (
/pulls/$PR/comments
). These are a completely different API endpoint and are invisible to the GraphQL
reviewThreads
query. Missing them means missing actionable review feedback.
bash
undefined
原因:部分机器人评审工具(如Claude、CodeRabbit等)会将评审反馈作为Issue评论
/issues/$PR/comments
)发布,而非PR评审评论(
/pulls/$PR/comments
)。这些评论属于完全不同的API端点,在GraphQL的
reviewThreads
查询中不可见。遗漏这些评论意味着遗漏了可操作的评审反馈。
bash
undefined

Fetch 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}]')"

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 finding
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}]')"

筛选出包含可操作评审反馈的评论(代码建议、错误发现、安全问题)。忽略以下内容:
- 状态/总结评论(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:
  1. Read the FULL comment body — no truncation. Use the GitHub API without
    .body[:N]
    limits.
  2. Read the current file at the referenced line to verify the fix is actually present.
  3. 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已解锁”总结或声称反馈已处理的内容。 对于每一条开放的评审评论:
  1. 阅读完整的评论内容——不要截断。使用GitHub API时不要添加
    .body[:N]
    限制。
  2. 阅读评论引用行的当前文件内容,验证修复是否实际存在。
  3. 直接在评论线程中回复,提供确认修复的具体提交SHA和行号。无论总结评论如何声称,未回复的开放线程都视为未处理。
bash
undefined

Fetch 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}'

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}'

针对每条PR作者未回复的评论:
- 如果**代码中已修复**:回复提交SHA和当前行引用以确认修复
- 如果**需要修复**:修复后回复提交SHA
- 如果**推迟处理**:回复后续Issue编号
- 如果**拒绝采纳**:回复公开的理由

机器人反馈(CodeRabbit、Cerberus、Gemini、Codex)与人类反馈的处理方式相同。

Execution

执行步骤

  1. Invoke
    /respond
    — Categorize all feedback (critical / in-scope / follow-up / declined). Post transparent assessment to PR. Reviewer feedback CAN be declined with public reasoning.
  2. Invoke
    /address-review
    — TDD fixes for critical and in-scope items. GitHub issues for follow-up items.
  3. Reply to every open thread — use
    gh api repos/$OWNER/$REPO/pulls/$PR/comments/$ID/replies -f body='...'
    so the thread shows addressed.
  4. 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
  1. 调用
    /respond
    ——对所有反馈进行分类(关键/范围内/后续处理/拒绝采纳)。在PR中发布透明的评估结果。可以公开理由拒绝采纳评审反馈。
  2. 调用
    /address-review
    ——针对关键和范围内的项使用TDD方式修复。为后续处理的项创建GitHub Issue。
  3. 回复所有开放线程——使用
    gh api repos/$OWNER/$REPO/pulls/$PR/comments/$ID/replies -f body='...'
    ,使线程显示为已处理。
  4. 通过GraphQL解决每个线程——仅回复并不代表线程已解决。未过时的评论即使在修复代码并回复后,仍会作为开放问题显示给评审者。必须显式解决它们:
bash
undefined

Get 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-lease
Watch checks. If a phase-4 or phase-5 fix broke CI, invoke
/fix-ci
again (count toward 2-retry max).
If 2 full retries exhausted: stop, summarize state, ask user.
bash
git push --force-with-lease
监控检查状态。如果第4或第5阶段的修复导致CI失败,再次调用
/fix-ci
(计入2次重试上限)。
如果已耗尽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
undefined

Get 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 `![before](url)` / `![after](url)`.

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变更。使用`![before](url)` / `![after](url)`格式。

仅当所有修复均为纯内部变更(无行为变更的冲突解决、无可见输出差异的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 )"
undefined

Retry 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
    .body[:N]
    when fetching review comments. The actionable detail is often at the end of long comments.
  • Replying without resolving — a reply on a thread does NOT resolve it. Non-outdated threads with replies still show as open conversations. Use
    resolveReviewThread
    GraphQL mutation after replying.
  • 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 (
    /issues/$PR/comments
    ), not PR review comments (
    /pulls/$PR/comments
    ). These are different API endpoints. You MUST check all three: GraphQL reviewThreads, REST PR comments, AND REST issue comments.
  • 机械地选择“ours”或“theirs”解决冲突
  • 未进行本地验证就推送代码
  • 默默忽略评审反馈
  • 不理解失败原因就重试CI
  • 修复本应拒绝的评审评论
  • 信任之前的“PR已解锁”或总结评论——始终独立验证每条评论与当前代码的匹配情况。之前会话中声称“已修复”的内容毫无意义,除非你亲自查看文件。
  • 留下未直接回复的评审线程——即使代码已修复,未回复的开放线程仍视为未处理。评审者无法知道你已检查过。
  • 截断评论内容——获取评审评论时绝不使用
    .body[:N]
    限制。可操作的细节通常在长评论的末尾。
  • 仅回复而不解决线程——在线程中回复并不代表线程已解决。未过时的线程即使有回复,仍会显示为开放对话。回复后必须使用
    resolveReviewThread
    GraphQL mutation来解决线程。
  • 绝不降低质量标准以通过CI——覆盖率阈值、代码检查规则、类型严格性、安全检查。如果某个检查失败,编写测试/代码以满足要求。降低标准不是修复。这是绝对的、不可协商的规则。
  • 因CI通过而跳过自评审——CI只能捕获语法和测试失败。死代码、冗余计算、错误的日志级别和语义不匹配都能通过CI。在宣布PR解锁前,必须亲自评审代码差异。
  • 仅检查评审线程和PR评论——机器人评审工具(Claude、CodeRabbit等)通常会将反馈作为Issue评论(
    /issues/$PR/comments
    )发布,而非PR评审评论(
    /pulls/$PR/comments
    )。这些是不同的API端点。必须检查所有三类内容:GraphQL reviewThreads、REST PR评论、REST Issue评论。

Output

输出

Summary: blockers found, phases executed, conflicts resolved, CI fixes applied, reviews addressed/deferred/declined, final check status.
总结:发现的阻塞问题、执行的阶段、已解决的冲突、已应用的CI修复、已处理/推迟/拒绝的评审意见、最终检查状态。