mcpField
T
triage-prs

triage-prs

github.com/jamiepine开发58.9k70 次安装3 周前更新
代码仓库

关于 triage-prs

triage-prs 是用于整理开放 GitHub PR 并推进合并的技能,通过可续接的计划记录进度。它面向准备发布的维护者,提供隔离审查、分类处理和后续跟踪流程。

主要功能

  1. 01收集开放 PR 的元数据
  2. 02按合并优先级分类 PR
  3. 03在分流文档中跟踪进度
  4. 04审查、变基并压缩合并 PR
  5. 05处理已被取代及部分 PR
  6. 06记录后续修复和贡献者署名

适用场景

  1. 01准备合并积压 PR 的版本发布
  2. 02恢复中断的 PR 分流会话
  3. 03区分低风险合并与需深入审查的改动
  4. 04从部分被取代的 PR 中应用选定改动

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jamiepine/voicebox --skill triage-prs

安装后在 Claude Code 中输入/triage-prs确认已加载。

详细介绍

PR 分类处理

目标

在一次专注的工作会话中,将积压的开放 PR 转化为一批已合并的成果。先制定一份可跟踪、可恢复的计划(<VERSION>_PR_TRIAGE.md),然后执行它——在需要时进行 rebase,按隔离安全的批次合并,应用合并后的后续操作,并关闭已被取代或部分适用的 PR,同时向其作者致谢。

本技能与 draft-release-notes 和 release-bump 搭配使用:先进行分类处理,然后针对新的 main 起草发布说明,最后发布版本。

何时使用

  • 在次要或主要版本发布之前,当已积累 10 个以上开放 PR 时
  • 当你希望在不丢失落地内容脉络的情况下解除合并阻塞时
  • 当你清楚自己无法亲自深入审查每个 PR,但需要快速落地关键子集时

前提条件

  • 已针对仓库完成身份验证的 gh 命令行
  • 用于 PR 审查的专用 worktree(避免用贡献者分支的检出污染 main)
  • 明确目标版本——分类处理文档以它命名(例如 0.4.0_PR_TRIAGE.md)

工作流

1. 设置隔离的 PR 审查 worktree
git worktree list  # check for stale ones first
git worktree prune
git worktree add ../voicebox-pr-review -b pr-review-<VERSION> main

将主 worktree 保留用于发布准备工作(变更日志草稿、直接提交到 main 的后续操作)。将审查 worktree 保留用于 gh pr checkout——每次检出都会将 HEAD 移动到贡献者分支,而你并不希望在主 worktree 中这样做。

2. 收集每个开放 PR 的元数据
gh pr list --state open --limit 50 --json \
  number,title,author,isDraft,mergeable,mergeStateStatus,files,additions,deletions,reviewDecision,statusCheckRollup,maintainerCanModify \
  --jq '.[] | {num: .number, title, author: .author.login, mergeable, state: .mergeStateStatus, canModify: .maintainerCanModify, changes: "+\(.additions)/-\(.deletions)", files: [.files[].path]}'

对于每个 PR,你需要:

  • 规模(+additions/-deletions)
  • 可合并状态(CLEAN、UNSTABLE、DIRTY = 冲突、UNKNOWN = GitHub 仍在计算)
  • 是否允许维护者编辑该分支(如果你代表作者进行 rebase,稍后需要此项)
  • 涉及的文件路径(有助于发现 PR 之间的重叠)

UNKNOWN 在推送到 main 之后很常见——直接尝试合并看看即可。

3. 分类为不同层级

将每个 PR 归入且仅归入一个类别:

第 1 层——合并: 规模小、可合并、修复真实 bug、CI 干净、审查成本低。单行修改、依赖放宽、针对性安全加固。这些是轻松取胜的部分。

第 2 层——候选,待审查: 中等规模(50-200 行)、涉及更多表面区域、看起来合理但需要更仔细阅读。符合产品方向的新用户可见功能。

取代: 该修复或功能已被某个已合并的内容覆盖。关闭并附上指向取代它的 PR 的评论。仔细检查——“标题相似”不是证据;比较实际 diff。

推迟到下一版本: 大型功能、脏冲突、草稿 PR、任何以会引入风险的方式触及发布流水线的内容。不要在快速冲刺中合并这些——它们需要专门的关注。

4. 编写分类处理文档

在 PR 审查 worktree 根目录创建 <VERSION>_PR_TRIAGE.md。结构如下:

# <Repo> <VERSION> — PR Triage

Working doc for tracking which open PRs land in <VERSION>. Delete after release cut.

Last updated: <DATE>

## Progress

**Tier 1: 0 / N merged**
**Tier 2: 0 / M handled**
**Supersede triage: pending**

---

## Merge for <VERSION> — critical bug fixes

| PR | Status | Size | What it fixes | Why must-have |
|---|---|---|---|---|
| [#123](url) | [ ] | +5/-0 | ... | ... |

## Strong candidate — needs a quick review

| PR | Status | Size | Summary |
|---|---|---|---|

## Close as superseded

| PR | Status | Reason |
|---|---|---|

## Defer to <NEXT_VERSION>

- [#xxx](url) ... — reason

---

## Order of attack

1. Close superseded PRs (one-liner comments)
2. Merge tier-1 in dependency-free batches — check file paths don't overlap
3. Review tier-2 individually
4. Rerun `draft-release-notes` to pick up everything
5. Run `release-bump`

Progress 标头是最重要的部分——它是你的记分板,让你在会话被中断时能够干净地恢复。

5. 按 PR 逐个执行循环

对于 tier-1 / tier-2 列表中的每个 PR:

a. 在 review worktree 中检出:

cd ../voicebox-pr-review
git checkout pr-review-<VERSION>  # reset to neutral base
gh pr checkout <N>

b. 读取实际的提交,而不是 main..HEAD:

git show HEAD                    # the PR's actual changes
git show --stat HEAD             # files touched + line counts

不要通过 git diff main..HEAD 来审查,如果该 PR 分支比 main 旧。该 diff 会把PR 分叉之后落到 main 上的每一个提交都算作 -(删除)行。一个 3 行的 PR 看起来可能像 700 行的回退。这是最容易误判 PR 的方式。

c. 评估关注点: 正确性、范围、与已合并工作的交互、版本兼容性(例如不能使用需要某个我们尚未固定版本的依赖项的 API)。

d. 如果分支落后于 main,则 rebase:

git fetch origin main
git rebase origin/main

这在 squash 合并之前是必不可少的。GitHub 的 squash 计算的是 diff(PR-head, merge-base) —— 在一个过时的分支上,该 diff 会包含回退中间每一个提交。Rebase 会把 merge-base 向前移动,使 squash 干净。

e. 如果允许维护者编辑,把 rebase 结果推回贡献者的 fork:

git remote add <author> https://github.com/<author>/<repo>.git
git fetch <author> <branch>              # get their ref first
git push <author> HEAD:<branch> --force-with-lease

这能让 GitHub 的 PR UI 与 rebase 后的状态保持同步,并使从 GitHub 侧的合并干净。

f. 合并:

gh pr merge <N> --squash

g. 更新 triage 文档 —— 把复选框改为 ✅ merged <sha>(使用来自 gh pr view <N> --json mergeCommit --jq '.mergeCommit.oid[0:7]' 的短 SHA)。更新 Progress 标题。

6. 批量处理小修复

变更行数 ≤5、CI 干净、文件路径不重叠且意图明显正确(例如放宽一行依赖、添加环境变量、修复 import 路径)的 PR,可以在一个循环中合并,无需逐 PR 的审查仪式:

for pr in 425 384 416 429; do
  echo "=== Merging PR $pr ==="
  gh pr merge $pr --squash
done

之后验证每一个都干净落地:

for pr in 425 384 416 429; do
  gh pr view $pr --json state,mergeCommit --jq "{pr: $pr, state, sha: .mergeCommit.oid[0:7]}"
done
7. 合并后的后续跟进

有时一个 PR 尽管存在已知的小问题(例如不完整的 dtype 映射、过时的 sentinel 清理)仍值得合并。不要阻塞合并;紧接着以普通分支 + PR 的方式应用后续跟进:

cd <main-worktree>
git pull --ff-only origin main
git checkout -b fix/<short-name>
# edit...
git commit -m "fix(<area>): <one-liner>"
git push -u origin fix/<short-name>
gh pr create --title "..." --body "Follow-up to #<N>. ..."

在 triage 文档中记录两个 SHA(✅ merged <pr-sha> + follow-up <pr>)。

直接提交到 main 的例外: 仅在明确、有限定范围的策略下(例如"release speedrun")。不要默认采用。

8. 取代:以指向功劳的评论关闭
gh pr close <N> --comment "Closing — superseded by merged #<M> which landed <brief description>. Thanks!"

先检查 diff —— 仅"标题相似"是不够的。如果该 PR 被部分取代(诊断正确,但只有一半的改动仍然需要),则改为部分应用。

9. 部分应用模式

当一个 PR 同时捆绑了有价值和有问题的改动时:

cd <main-worktree>
git pull --ff-only origin main

# Cherry-pick specific files from the PR branch
git checkout <pr-commit-sha> -- <file1> <file2>

# Review the staged changes, adjust as needed
git diff --cached

# Apply any surgical edits to files you don't want to bulk-replace
# (e.g. the PR's file predates a recent main commit you need to preserve)

# Commit with a trailer crediting the original author
git commit -m "$(cat <<'EOF'
<subject>

<body explaining what was kept vs dropped>

Co-Authored-By: <author> <[email protected]>
EOF
)"
git push ...  # branch + PR, unless under the direct-to-main exception

然后用评论关闭该 PR,说明应用了什么、舍弃了什么,并引用提交 SHA。

10. 保持文档最新

每一次合并、每一次关闭、每一次后续跟进 → 更新 <VERSION>_PR_TRIAGE.md。该文档就是你的会话日志。如果你被打断并在明天继续,该文档是"我进行到哪里了"的唯一事实来源。

11. 当 triage 完成时
  • 文档中的每个 PR 都有终态(✅ merged / ✅ closed / deferred)
  • Progress 标题为每个 tier 显示 N/N
  • 下一个要运行的 skill 是 draft-release-notes(针对新的 main 重新生成 [Unreleased]),然后是 release-bump

你可以在 release 发布后删除 triage 文档,或将其保留在版本历史中作为记录。

注意事项

  • 在过期的分支上,main..HEAD 会骗人。 它会把 main 自分支分叉以来新增的所有内容显示为删除。务必通过 git show HEAD 查看 PR 的实际提交。
  • 对未 rebase 的分支进行 squash 合并会回退中间的改动。 squash 计算的是 diff(PR-head, merge-base)。rebase 会把 merge-base 向前移动。
  • mergeable=UNKNOWN 是暂时状态——GitHub 正在推送后重新计算。直接尝试合并即可。
  • 路由顺序很重要(FastAPI 及类似框架): DELETE /history/failed 必须注册在 DELETE /history/{id} 之前,否则带参数的路径会把 "failed" 当作 ID 消费掉。
  • Apple 的 -weak_framework 会覆盖同一框架的 -framework,与顺序无关——当某个依赖硬链接了可选内容时,通过 cargo:rustc-link-arg=-Wl,-weak_framework,Name 使用它。
  • 依赖版本下限会限制你能应用的内容。 在接受像 torch_dtype= → dtype= 这样的 kwarg 重命名之前,先检查最低版本 pin 是否支持它。有时正确的做法是只 cherry-pick PR 的一半。
  • cpal::Stream 及类似的 !Send 音频类型无法跨越 await 点或 spawn_blocking。有时一个"不理想但正确"的同步等待是现有条件下最好的修复;标记它但不要阻塞。
  • PyTorch nightly 构建不适合发布——非确定性,且可能在两次运行之间发生回归。如果某个 PR 建议切换到 nightly 来修复 GPU 问题,优先选择 TORCH_CUDA_ARCH_LIST=...+PTX 或等待稳定版支持。

规范命令参考

# Bulk PR metadata
gh pr list --state open --limit 50 --json number,title,author,mergeable,mergeStateStatus,additions,deletions,maintainerCanModify,files

# Detailed single-PR view
gh pr view <N> --json body,author,headRefName,baseRefName,mergeable,maintainerCanModify,files,statusCheckRollup

# The actual commit, not the branch-vs-main diff
git show HEAD
git show --stat HEAD
gh pr diff <N>

# Rebase contributor branch onto current main
git fetch origin main && git rebase origin/main

# Push rebase back to contributor fork (maintainerCanModify=true required)
git remote add <author> https://github.com/<author>/<repo>.git
git fetch <author> <branch>
git push <author> HEAD:<branch> --force-with-lease

# Merge
gh pr merge <N> --squash

# Confirm merge SHA for triage doc
gh pr view <N> --json state,mergeCommit --jq '{state, sha: .mergeCommit.oid[0:7]}'

# Close superseded
gh pr close <N> --comment "Closing — superseded by merged #<M>. Thanks!"

备注

  • 绝不通过 main..HEAD 审查过期分支。 这是本技能中最重要的一条。
  • triage 文档就是会话状态。 丢了文档,就丢了会话。每次操作后都要更新它。
  • 即使只部分应用,也要署名贡献者。 使用 Co-Authored-By: trailer,并关闭那些链接到已应用提交的评论。
  • 不要让完美成为交付的敌人。 一个从"损坏"变成"可用但带有已知小问题"的修复是严格的改进。标记该问题,创建后续任务,合并该修复。

评论

支持 Markdown