关于PR评审自动化这块内容, 主要是对那个具有-five-prs-技能的五步Agent工作流进行一个解析。提供一个链接让你能免费去下载, 这个列表的内容是关于说你想要去做某一个叫做 X 的动作或者事项到底应该去使用哪一个工具, 并且把相应的工具给列出来。项目地址:它是个开源项目, 这个项目故意被做成了“精选清单”, 而不是那种普通的“目录”。在每个具体的用例里面, 只保留最明显的3个选择, 并且最多只留下2个挑战者, 条目的总数被硬性地卡在了5个。这意味着绝大多数的PR都会被拒绝掉。评审流程必须同时具备两个特点, 一个特点是机械化, 也就是要管管格式、检查有没有重复、看看活跃度够不够另一个特点是编辑化就是要仔细想想这个内容是否配得上这个位置。本仓库 把整套的评审流程给沉 成了一个代码技能。这个技能的存储位置是在那个文件里面的。那个文件的层级路径是 .//-prs/SKILL.md。 当给定一个拉取请求的那个队列的时候。那个智能代理就会按照特定的五个步骤来进行操作。这五个步骤的顺序分别是去获取。接下来是下一步的判断。然后是对应的采取行动。最终要把开放队列里面所有的拉取请求给收敛到三种最终的态之一。这三种最终的状态是说要合并或者是关闭, 又或者是明确地搁置并且保持开启的状态。读完之后, 你能够学会如何把规则文档和 Agent 工作流解耦开, 设计出一个可以复用、容易维护的 Agent 技能, 并且清楚每一步里具体的 git 命令是如何使用的, 委托调用是怎么实现的, 人工确认的具体点又是在哪里落地的。技能定位规则与工作流的解耦技能这个文件, 它是采用了那个叫做 *SKILL.md* 的标准结构, 这里面呢, 用 YAML 格式进行了定义, 具体定义了三个字段。文档的开篇处, 有一句话, 它把整个设计方案里所遵循的那些最基本的准则, 给直接地交代清楚了。这个技能其实就是去应用那些规则的, 它并不等同于规则本身做的一份复制品。这些规则是存放在以.md结尾的文件里的, 比如常见的几个相关文件都在这类文件中。所以呢, 它是利用这些规则的一个工作流程。这是一种被大家称为“单一事实源”的典型设计做法。准入规则仅仅只保留在 .md 文件里面, 而技能文件只是去描述具体的执行过程是怎么回事。这么做的话, 就可以避免规则出现在两个不同的地方, 然后发生不一致的情况。这种做法也与 .md 文件里面的入口规则相呼应。那个入场规则是说, 每一次进行条目的增加或者删除操作的时候, 不管你是直接提交上去的, 还是在 PR 评审环节做的, 都必须把 .md 里的规则应用上。要想弄明白这个工作流程, 先得搞清楚它是在按照那一套规则来做事, 这套规则也是后面每一个筛查环节以及判断操作的根据。前置知识工作流依赖的规则底座.md 文件定义了三块非常核心的规则, 而 -prs 工具里的每一个操作步骤都在对它们加以使用。质量要求是啥意思, 就是把那个提交过来的东西全都给摆出来, 而且还得同时去把那五个条条框框都全部遵守掉, 一个都不能少。开发者在实际工作中会用到它。实现语言以及打包方式都与具体内容没有关系。由 Rust 编写的 uv 以及 ty , 还有 agent 的技能包, 这些全都属于清单所划定的范围。而一个没有任何人用于日常工作的纯粹的某个项目, 则不在这个范围之内。在最近12个月之内存在提交的操作。属于生产环境可用的状态, 而不是alpha或者beta版本的软件。拥有清晰的文档内容, 其中包含示例和具体的用例情况。该仓库从创建至今至少已经存续满了1个自然月的时间。准入规则是, 也就是用来给“用例”以及容量上限做一个定义的。对于自动拒绝的规则部分, 以下是这样的情况, 如果出现了这些情况, 那么 PR 就会被直接地关闭:关于这套规则是从哪里来的, 你可以去看看 docs/adr/0001--not-.md 这个文件, 原来的情况是清单改用了所谓的明显选项精选清单, 原来的三车道模型被去掉了, 三车道模型里面包括了 Star 和 Gem, 还有一些其他的定义也在文档里面提到了, 比如使用场景还有各种分割什么的术语系统都在那个 md 文件里说清楚了。步骤一 Fetch拉取队列与 diff将技能的参数指定为具体的 PR 的时候, 系统就只对这些 PR 进行处理如果没有做这个特别的指定, 那就选取整个队列:gh pr list --repo vinta/awesome-python --limit 10 \ --json number,title,author,url,body,files,mergeable,mergeStateStatus字段的选择非常讲究, 和直接决定后续走哪一条合并路径有关见步骤四, files用于判断PR性质, body用于空描述检查, 随后并行拉取所有diff。gh pr diff --repo vinta/awesome-python当你把一个 diff 拉取下来之后, 你需要去做的那件事儿里的第一件, 就是要对一个批次进行分拣处理, 也就是要把那个批次的东西好好的排序一遍, 那么所遵循的这个规则是:这里有一个被刻意安排好的设计, 那就是needs-human这个PR每次运行的时候都会再次冒出来, 它会一直持续到这个状态, 直到有真正的人类过来动手处理为止, 那么什么是完成标准呢, 就是要做到每一个PR都已经被分拣处理过了, 并且每一个PR也都拥有各自的diff部分。步骤二 无判断力的机械筛查在筛查查这个阶段运用相关的规则, 那些通过差异比较数据以及拉取请求元数据就能直接给出答案、压根就不用经过人工编辑去判断的部分, 都会被直接使用, 不过这里边有一条特定的规则需要再多查一下资料才行, 也就是最近被关掉了的那些重复拉取请求的情况。gh pr list --repo vinta/awesome-python --state closed \ --search --limit 10通过把项目名作为条件, 先进行搜索, 这样就能找到那个最近才关闭的PR, 一旦发现这个情况吻合了, 就接着去执行操作, 用“重复”这个理由, 把它给关掉就可以了。对那些在筛选过程中被剔除的 PR, 系统会直接进入步骤四来进行关闭处理操作。这一处被关闭的具体原因就是因为它违反了相关的某一条规定。针对每一个存活的状态为 PR 的情况, 该技能还必须要求把那个目标用例对照着当前的情况重新解析一遍。这样做的理由是非常实际的。因为差异对比中的上下文行所展示的是在 PR 写作时所依据的基线代码。可是从完成提交到开始评审这段时间里内容可能已经发生改变。在 PR 作者写入的时候用例的数量或许还没有达到上限。但是在进行评审的时候用例的数量可能已经达到满员的状态了。这里有个衔接设计, 存在合并冲突的PR被标记之后带回Merge分支, 然后由步骤四就地吸收解决, 而不是在筛查阶段就直接丢弃。每个存活的 PR 都能够描述清楚其对应的目标用例—。步骤三 Judge按用例分组并委托准入判断机械式的筛选办法, 没办法给出一个明确的回答, 这个问题到底能不能成立, 或者这个项目是不是适合安排到这个指定的时间窗口里面去, 于是就把这个具体的判断工作, 交给了具备另外一项专业技能的那个负责环节, 由他们来进行处理。首先要按照目标用例来进行分组, 这是因为为同一个用户故事而提交的那些条目, 它们都在争夺相同数量的可用名额, 所以这些PR必须被放在一起进行审查, 这样做的目的是为了互相配合、避免彼此之间产生混乱。对每个分组以如下形状的参数调用audit-the-list技能定义见 .//audit-the-list/SKILL.md您可以根据具体的使用场景来进行判断, 并且只需提供相关的操作步骤即可, 不需要添加任何页面元素, 也不需要包含其他任何多余的内容。请留意在相关参数所设定的三重约束条件方面。只去执行那个叫 audit-the-list 的里面的拉取下载量、仓库状态还有 PyPI 元数据这些证据, 以及把这些东西逐条给裁决的两个阶段。不要去预览页面, 也不用对现有的那些内容做任何修改, 更加不提交任何东西。这是因为在 PR 这个评审场景下面, 大家最终要做裁决的目标是拟议进来的条目, 而不是已经存在的内容本身。最后要把整个裁决的过程和结果报告回去。每一个PR所收到的裁决必须是合并或者关闭, 而且必须根据拉取到的那些证据来做决定。一旦用例已经达到了满员的状态, 那么一个合并的裁决就必须明确指出是被哪一个条目给挤出去了的情况。还存在第三种结果的可能性, 就是并没有任何当前的用例能够容纳该条目, 这种状况被看作是结构问题这样的情况, 它会携带着相关的证据进入到Act的阶段里面去, 最后由维护者来拍板决定是新建子分类并进行合并, 还是直接选择关闭, 或是继续保留现状挂在那里。必须让每一个存活的程序, 手里都拿着带有理由说明的裁决证明。步骤四 Act关闭与合并两条执行臂这个裁决的内容, 是由维护人员来一个一个地检查清楚的, 然后才会去进行实施操作的, 并且它是有着两个部分的。Close 臂带草案评论的人工确认当需要关掉某一个 PR 的时候, 技能会展示已经起草好的一份关闭评论, 在这份评论内容里会把相关的理由写清楚, 并且附上 .md 文件的链接, 关于这个过程中涉及到的交互细节方面, 有两点内容是需要重点关注和注意的:请给出三个可供你选择的项, 分别是使用这一评论来进行关闭操作、在不附带任何评论的情形下完成关闭动作, 以及决定继续让它保持为开放状态, 随后请确认你想要执行的具体指令内容。gh pr close --repo vinta/awesome-python --comment # 或无评论直接关闭 gh pr close --repo vinta/awesome-pythonMerge 臂干净合并与本地冲突解决对于那些没有产生任何冲突的提交代码请求, 就直接进行操作:gh pr merge --repo vinta/awesome-python --merge如果存在冲突的 PR 的情况, 那么就需要去执行本地合并这个动作, 在此过程中必须要去保留那个贡献者的署名信息, 尽管这样做以后依然还是会把这个 PR 的状态标记为已经合并的样子。git fetch origin pull//head git merge FETCH_HEAD # 使用标准信息 Merge pull request # from /我们解决冲突所遵循的原则, 简单来说, 就是把对应的条目移动到它应该处于的那个位置之中。这一行为本身, 实际上是一次经过人类判断的编辑操作。它绝不是那种毫无生气的、按部就班地机械拆解冲突的方法。不管走的是哪一条路线, 在 push 之前的时候, 都必须得按照那些个规则去对一下目标这个东西到底是个什么状况, 然后呢, 再去运行一下测试程序, 最后再提交上去。此处存在一条清晰的责任界定, 其内容是说当处理只添加差异的情况却需要从旧条目中挤出数据时属于正常现象这一观点在逻辑上是成立的, 因为移除的操作责任归属于评审环节, 该工作并非贡献者的义务所在, 参与贡献的人员仅需提交自身相关的条目即可, 而评审方面则承担在整体流程的输入与输出循环中负责执行输出部分的任务。步骤五 终态核对与汇报最后产出了一张汇总表, 这张表里包括 PR 编号、裁决内容、以及已经执行完成的具体动作, 除此之外, 还需要额外附带一份 needs-human 清单, 其完成的验收标准是针对一条封闭性的指标进行检查:每一个被拉到本地的合并请求最终只能落进一个状态里, 这种状态要么是已经合并了并且也对账清楚了, 要么是被关掉了, 再不然就是还开着的, 具体又分成保持开放、需要人工处理或者结构问题还在等着定夺这几种情况。那些被保持打开状态的 PR, 会在下一次进行运行的时候又重新出现, 这本来就是要这样的效果。这种技能并不是一下子就把所有的东西都处理干净, 而是追求每一个 PR 的状态都是可以被追踪到的。像那种被放在一边暂时不管的 PR, 它其实是一种很明确的状态, 这就意味着并不是被人给遗漏掉了。设计要点这个工作流做对了什么咱们从那个技能文件还有配套出来的规则文档的结构方面来进行分析, 可以发现这套设计里面藏着几个关键点, 这些关键点是可以直接拿来用到任何所谓的维护型Agent技能里面的, 这是非常具备可迁移性的。把规则和过程分拆开: 在 SKILL.md 里头就只管写得清清楚楚, 说清楚到底要做什么、该遵循什么样的先后顺序、什么时候需要交给别人去办、或者到了什么节点得停下来去找人问清楚至于什么东西才算达到了合格的标准, 又或者什么情况算是有重复劳动, 这些要求全部指向那些 .md 文件。要是想要改规则, 就没必要再去碰技能这边, 这样当技能升级的时候, 也绝对不会产生出第二份规则的拷贝来。分层处理机械判断与编辑判断。在前面的阶段, 只进行那些能够通过元数据直接回答的检查工作。这些检查包括查看是否有空白的描述、是否存在数据重复情况以及是否出现多条目提交PR等问题。直到接下来的Judge阶段时, 才会引入需要拉取证据来进行判断的编辑内容。在这个环节之中, 会通过委托的方式去复用audit-the-list这一技能已经具备的证据收集管线。这个管线可以执行下载量的扫描任务、查询gh api仓库的状态信息以及对PyPI系统的元数据进行校验操作。整个过程并不需要重新编写一遍现有的功能逻辑。在发出委托请求的时候, 要把作用域给收窄一点。你要把调用 audit-the-list 这个功能的参数明确限定为 steps only。并且要用三个否定语句来封住副作用的产生。具体来说就是 no page, no, and no ——这是在跨技能调用对方功能的情况下的时候进行的显式裁剪操作。这样做的目的是为了不让对方原本的那个流程被随便乱动。目的是要避免那个审计技能的默认的“维护者预览 提交”, 这种路径被不小心给触发到这种情况的发生是我们要极力避免的。人工干预是做出决定的关键点, 而不是仅仅做一个盖章的动作。对于“Close”分支来说, 评论需要得到人的确认, 而且人自己写的自定义文本就直接起到了决定作用。而对于“Merge”分支而言, 处理冲突以及解决结构层面的问题, 比如新建子分类这些事项, 全都留给了人来处理。维护者所做出的裁决被视为最终生效, 这种情况和审计列表里提到的“他们的决定是最终的”这一说法是一致的。所谓幂等的失败重放, 就是指针对那些标注有 needs-human 标签以及 kept-open 标签的 PR, 在每一轮重新执行测试或者验证流程的时候, 它们都会再次被发现并且被列出来进行重复处理。这样的话, 相关的任务队列就始终具备了可以反复进入和处理的特性。即便是有负责自动运行的 Agent 在中间突然停了下来, 或者是等待人类介入的人拖延迟了时间, 也完全不会导致对应的 PR 出现遗漏或者找不到的情况。下面我们来具体看一看涉及到的那些关系比较密切的文件具体内容, 以及在实施操作过程中实际采用的运行方式细节。目前的情况是这样的, 就是咱们现在看到的这个技能嘛, 它实际上是下面这三个技能当中的一个, 而它们三个是共同围绕着一套规则文档来进行协作的。文件职责.//-prs/SKILL.md本文主题PR 队列的评审工作流.//audit-the-list/SKILL.md对 现有条目做周期性审计被 -prs 委托做证据与裁决.//-/SKILL.md生成用于维护者的交互式预览页面, 其中包含对 keep 和 drop 状态的操作功能, 需要指出的是, 在 -prs 这种场景下是明确规定不对其调用这一功能的。与这些文件配套的有规则文档, 它的文件扩展名是.md。还有术语表文档, 它的文件扩展名也是.md。有一个Agent入口规则的文档也需要保持同步, 该文件的扩展名同样是.md。最后是决策记录文档, 它被放在了docs文件夹中的adr子文件夹下, 这个文档是关于精选清单定位的, 其文件名是0001--not-.md, 文件的扩展名依然是.md。运行的大前提条件是, 在代码仓库里面已经装好了 Code 这个东西, 而且这个技能能够通过斜杠双点斜杠这种目录样式来实现自动的发现功能, 同时, 也必须要把 gh 命令行接口工具配置妥当了, 这个工具得具备读取请求和写出请求这样的权限才行, 除此之外, 还要配备好 git 这个版本控制工具。当项目的维护者说出具体的词语比如 PRs、the PR queue 、还是说要判断某一个特定请求是否应该被合并的时候, 这个技能就会立马触发作用。在执行过程当中, 你可以通过提交 PR 编号这样的参数, 把需要处理的具体范围给指定出来。仓库里用于本地测试的那个入口, 具体来说是make test这个命令它实际上就等价于uv run加/tests/再加上-v这两个参数组成的操作, 在往远处推送代码之前, 都得靠着把这个测试给通过, 这是合并代码路径所必需的依赖条件。需要说明的情况是, 这里涉及到的适用范围边界。本文讲述的是仓库里当前那个叫作.-/-prs/SKILL.md的文件里面的内容。在这个技能里面, - -repo vinta/-这个部分是用来表示上游的仓库标识。当你把这个技能用来进行fork操作的时候, 你应该把它替换成对应的仓库名称。这个技能本身不会对那个md文件的条目规则进行修改。假如说准入的规则发生了变化, 比如上限的数值还有tier的定义等等这些东西进行了调整的话, 那么就要以那个md文件作为依据。在这种情况下, 技能的流程不需要做任何变更。
阅读完成 · 觉得有帮助?