首页
/ awesome-python PR 评审自动化:review-prs 技能的五步 Agent 工作流解析

awesome-python PR 评审自动化:review-prs 技能的五步 Agent 工作流解析

2026-09-04 09:04:05作者:伍希望

awesome-python 是一个刻意做成"精选清单"(shortlist)而非"目录"(catalog)的开源项目:每个用例(Use Case)只保留最显然的 3 个选择和至多 2 个挑战者,条目上限硬性卡在 5 个。这意味着绝大多数 PR 会被拒绝,而评审流程必须同时做到机械化(格式、重复、活跃度)与编辑化(是否配得上这个 slot)。本仓库在 .claude/skills/review-prs/SKILL.md 中把整套 PR 评审流程沉淀为一个 Claude Code 技能(Skill):给定 PR 队列,Agent 按 Fetch → Screen → Judge → Act → Report 五个步骤,把开放队列中的每个 PR 收敛到三种终态之一——合并(merged)、关闭(closed)或明确搁置(parked/kept open)。读完后你能掌握:如何把"规则文档 + Agent 工作流"解耦设计成一个可复用的维护型 Agent 技能,以及其中每一步的 gh 命令、委托调用和人工确认点是怎么落地的。

技能定位:规则与工作流的解耦

技能文件采用标准的 SKILL.md 结构,YAML frontmatter 定义了三个字段:

  • namereview-prs,技能标识;
  • description:说明触发条件——维护者要求"评审 PR、处理 PR 队列、或判断某个特定 PR 是否该合并"时激活,并明确了工作流骨架:"从 diff 筛查 → 委托 audit-the-list 做准入判断 → 在 GitHub 上合并或关闭";
  • argument-hint[PR numbers],即技能可接收具体 PR 编号作为参数,不传则处理整个队列。

文档开头一句话点出了整个设计的核心原则:

规则住在 CONTRIBUTING.md(Quality Requirements、Admission、Review Process、Automatic Rejection)里——这个技能是应用这些规则的工作流,不是规则的第二份拷贝。

这是一种典型的"单一事实源"设计:准入规则只维护在 CONTRIBUTING.md 中,技能文件只描述执行过程,避免规则在两个地方漂移。这也与 CLAUDE.md 的入口规则呼应——"每次增删条目(包括直接提交,不只是 PR 评审)都要应用 CONTRIBUTING.md 的规则"。

理解这个工作流之前,需要先理解它所执行的那套规则,这也是后续每一步筛查和判断的依据。

前置知识:工作流依赖的规则底座

CONTRIBUTING.md 定义了三块核心规则,review-prs 的每个步骤都在消费它们:

质量要求(Quality Requirements)——所有提交必须同时满足五条:

  1. Serves Python Developers:Python 开发者在 Python 工作中实际使用它。实现语言和打包方式无关——uv 和 ty 是 Rust 写的,agent 技能包是 markdown,都属于清单范围;一个没人用于 Python 工作的纯 Python 项目则不属于。
  2. Active:最近 12 个月内有提交;
  3. Stable:生产可用,非 alpha/beta/experimental;
  4. Documented:有清晰的 README,含示例和用例;
  5. Established:仓库至少存在 1 个月。

准入规则(Admission)——定义"用例"与容量上限:

  • **Use Case(用例)**是清单结构定义的:每个 Subcategory(子分类)是一个用例;没有子分类的 Section 整体是一个用例。结构变更(新 section、新 subcategory、拆分过大的用例)只能由维护者执行——条目 PR 永远不能创建它所需要的子分类
  • 每个用例至多 3 个 Obvious Choices(资深开发者脱口而出的选择)+ 2 个 Challengers(尚非显然但可信的继任者,准入需要采纳趋势证据而非单纯人气);硬性上限 5 个条目/用例
  • Displacement(置换):用例满员后唯一的进入方式——PR 必须点名它要替换的条目,并论证新项目做得更糟的那位的活儿更好。一进一出;
  • Evidence(证据):准入由维护者编辑判断拍板,主要参考 PyPI 下载量而非 GitHub star;维护者判断最终生效。

自动拒绝规则(Automatic Rejection)——以下情况 PR 会被直接关闭:

  • 一个 PR 添加多个项目;
  • 用例已满员且 PR 没有 Displacement 论证;
  • PR 自建 section/subcategory 并填充它;
  • 同一组织/作者跨一或多个 PR 的协调式自我推广;
  • 与现有条目或近期已关闭 PR 重复;
  • PR 描述为空或占位;
  • 分类不当;项目已归档/废弃(12 个月以上无提交);
  • 无文档或用例不清晰;仓库存在不足 1 个月。

这套规则的由来背景可以参见 docs/adr/0001-shortlist-not-catalog.md:清单从"三车道模型"(Industry Standard / Rising Star / Hidden Gem)改造为"明显选项精选清单",术语体系(Use Case、Obvious Choice、Challenger、Displacement、Split 等)定义在 CONTEXT.md 中。

步骤一 Fetch:拉取队列与 diff

技能的参数指定具体 PR 时只处理这些 PR;否则取整个队列:

gh pr list --repo vinta/awesome-python --limit 10 \
  --json number,title,author,url,body,files,mergeable,mergeStateStatus

字段选择很讲究:mergeablemergeStateStatus 直接决定后续走哪条合并路径(见步骤四),files 用于判断 PR 性质,body 用于空描述检查。随后并行拉取所有 diff:

gh pr diff <number> --repo vinta/awesome-python

拉到 diff 后要做的第一件事是分拣(sort the batch),规则是:

  • 新增条目的 PR 继续走流程;
  • 其他一切(typo 修复、website 改动、文档改动)超出技能范围——不动它们,只报告到 "needs human"(需人工处理)清单。

这里有一个刻意的设计:needs-human 的 PR 每次运行都会再次冒出来(resurface),直到有人类动手处理。"Done when every PR is sorted and has its diff"——完成标准是每个 PR 都已分拣且都有 diff。

步骤二 Screen:无判断力的机械筛查

筛查阶段应用 Automatic Rejection 规则中那些 diff 和 PR 元数据能直接回答、不需要编辑判断的部分。其中一条规则需要额外查询——"近期已关闭的重复 PR":

gh pr list --repo vinta/awesome-python --state closed \
  --search "<project name>" --limit 10

即按项目名搜索最近关闭的 PR,命中则按"重复"关闭。

被筛掉的 PR 直接跳到步骤四,作为一次 close 处理,理由就是它违反的那条规则

对每个存活 PR,技能还要求把目标用例对照当前 README 重新解析一遍,理由很实际:diff 的上下文行显示的是 PR 写作时的基线代码,而从提交到评审,README 可能已经变了——PR 作者写入时用例没满,评审时可能已经满员。这里有一个衔接设计:存在合并冲突的 PR 被标记后带入 Merge 分支,由步骤四就地吸收解决,而不是在筛查阶段就丢弃。

完成标准:每个存活 PR 都能说出自己的目标用例(section — subcategory)。

步骤三 Judge:按用例分组并委托准入判断

机械筛查无法回答"这个项目配不配得上这个 slot",这一步把工作委托给另一个技能。

首先按目标用例分组:为同一用例提出条目的多个 PR 竞争的是同一批 slot,所以它们必须一起评审(ride one invocation),避免各自判断时互相 unaware。

对每个分组,以如下形状的参数调用 audit-the-list 技能(定义见 .claude/skills/audit-the-list/SKILL.md):

"Judge proposed entries <names, each with its PR number> for the <section — subcategory> use case. Evidence and Verdicts steps only; report the verdicts back. No preview page, no README changes, no commits."

注意参数中的三重约束:

  1. 只执行 audit-the-list 的 Evidence 和 Verdicts 两个阶段(拉取下载量、仓库状态、PyPI 元数据等证据,然后逐条给裁决);
  2. 不要预览页面、不改 README、不提交——因为 PR 评审场景下裁决对象是"拟议条目"而非现有 README 内容;
  3. 把裁决报告回来。

每个 PR 的裁决是 merge 或 close,必须基于拉取到的证据。当用例已满员时,一个 merge 裁决必须点名被挤出的条目。还有一种第三种结果:没有当前用例能容纳的条目是"结构问题"——它带着证据被带入 Act 阶段,由维护者决定:新建子分类并合并、关闭、还是继续挂着。

完成标准:每个存活 PR 都持有带理由的裁决。

步骤四 Act:关闭与合并两条执行臂

裁决由维护者逐条确认后执行,分为两条臂:

Close 臂:带草案评论的人工确认

对每个要关闭的 PR,技能通过 AskUserQuestion 呈现起草好的关闭评论——评论写明理由并链接 CONTRIBUTING.md。交互细节有两点值得注意:

  • 每次调用最多批量 4 个 PR,并维护一个"哪些裁决已问过"的清单;
  • 维护者的回答经常是自定义文本,而那段文本本身就是决定(可能改评论措辞,也可能改变裁决)。

AskUserQuestion 提供三个选项:用这条评论关闭 / 不带评论关闭 / 保持开放。确认后的命令:

gh pr close <number> --repo vinta/awesome-python --comment "<comment>"
# 或无评论直接关闭
gh pr close <number> --repo vinta/awesome-python

Merge 臂:干净合并与本地冲突解决

无冲突的 PR 直接:

gh pr merge <number> --repo vinta/awesome-python --merge

有冲突的 PR 走本地合并,保留贡献者署名(GitHub 仍会标记 PR 为已合并):

git fetch origin pull/<number>/head
git merge FETCH_HEAD   # 使用标准信息 "Merge pull request #<number> from <owner>/<headRef>"

解决冲突的原则是把条目放到正确的位置——这本身就是一次编辑判断,而非机械解冲突。

无论哪条路径,push 前都要按 CONTRIBUTING 规则对账(reconcile)目标 section,然后跑测试并提交:

  • 移除裁决中被挤出的条目;
  • 修正新条目的显示名(应为 PyPI 包名,便于 pip install 直接复制)和 Entry Ordering 位置(obvious choices 在前按 PyPI 月下载量降序,challengers 在后;stdlib 模块在用例内最前;无下载信号的条目在其层级内按字母序垫底——位置即标记,条目文本里没有 tier 标记);
  • 运行 make test(对应 Makefile 中的 uv run pytest website/tests/ -v);
  • 提交。

这里有一条明确的责任划分:"add-only diff 却需要挤出旧条目"是正常情况——移除是评审这一步的职责,不是贡献者的职责。 贡献者只提交自己的条目,评审侧负责一进一出中的"出一"。

步骤五 Report:终态核对与汇报

最后产出一张汇总表:PR 编号、裁决、已执行的动作,外加 needs-human 清单。完成标准是一条封闭性检查:

每个拉取到的 PR 都恰好结束于一种状态——已合并(且 section 已对账)、已关闭、或保持开放(kept open、needs-human、或结构问题待决)。

"kept open 的 PR 会在下一次运行时再次冒出来——这正是它的目的。"技能不追求一次性清空队列,而追求每个 PR 状态可追踪:被搁置的 PR 是显式状态而非遗漏。

设计要点:这个工作流做对了什么

从技能文件与配套规则文档的结构看,这套设计有几个可迁移到任何"维护型 Agent 技能"的要点:

  1. 规则与过程解耦:SKILL.md 只写"做什么、按什么顺序、何时委托、何时停下来问人";"什么算合格、什么算重复"全部指向 CONTRIBUTING.md。改规则不需要改技能,技能升级也不会产生第二份规则拷贝。
  2. 机械判断与编辑判断分层:Screen 阶段只做元数据可回答的检查(空描述、重复、多条目 PR),Judge 阶段才引入需要证据拉取的编辑判断,且通过委托复用 audit-the-list 技能已有的证据管线(ClickPy 下载量扫描、gh api 仓库状态、PyPI 元数据校验)而不是重写一遍。
  3. 委托时收紧作用域:调用 audit-the-list 的参数明确限定"Evidence and Verdicts steps only",并用三个否定句封住副作用(no preview page, no README changes, no commits)——跨技能调用时显式裁剪对方流程,避免审计技能默认的"维护者预览 + 提交"路径被误触发。
  4. 人工是裁决点而非橡皮图章:Close 臂的评论由人确认且人的自定义文本即决定;Merge 臂的冲突解决、结构问题(新建子分类)都留给人;维护者的裁决"最终生效"(与 audit-the-list 中"their verdicts are final"一致)。
  5. 幂等的失败重放:needs-human 与 kept-open 的 PR 每轮重跑都会重新出现,队列永远可重入——Agent 运行中断或人类拖延都不导致 PR 丢失。

相关文件与运行方式

这个技能是 .claude/skills/ 下三个技能之一,围绕同一套规则文档协作:

文件 职责
.claude/skills/review-prs/SKILL.md 本文主题:PR 队列的评审工作流
.claude/skills/audit-the-list/SKILL.md 对 README 现有条目做周期性审计(被 review-prs 委托做证据与裁决)
.claude/skills/preview-verdicts/SKILL.md 生成维护者交互式 keep/drop 预览页(review-prs 场景下明确不调用它)

配套的事实源:CONTRIBUTING.md(规则)、CONTEXT.md(术语表)、CLAUDE.mdAGENTS.md(保持同步的 Agent 入口规则)、docs/adr/0001-shortlist-not-catalog.md(精选清单定位的决策记录)。

运行前提:仓库内已安装 Claude Code(技能通过 .claude/skills/ 目录自动发现),并已配置 gh CLI(含 PR 读写权限)与 git。技能在维护者要求"review PRs / process the PR queue / 判断某 PR 是否该合并"时触发,可传 PR 编号参数指定范围。仓库本地测试入口为 make test(等价于 uv run pytest website/tests/ -v),合并路径在 push 前依赖它通过。

需要说明的适用边界:本文描述的是仓库当前 .claude/skills/review-prs/SKILL.md 的内容;技能中的 --repo vinta/awesome-python 是上游仓库标识,fork 使用时应替换为对应仓库;技能本身不改动 README.md 的条目规则——若准入规则(上限数值、tier 定义等)调整,以 CONTRIBUTING.md 为准,技能流程无需变更。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
docsdocs
暂无描述
Markdown
889
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341