关于 triage-pr
triage-pr 是用于将 GitHub PR 从草稿和 CI 失败推进到可供合并状态的技能,分阶段处理 CI 与代码审查反馈。适合需要按配置修复 PR 范围内问题、等待审查并报告阻塞项的团队。
主要功能
- 01检查失败的 GitHub Actions
- 02在 PR 范围内修复 CI 问题
- 03等待配置的审查机器人反馈
- 04核实并处理审查意见
- 05支持仅 CI、试运行和自动应用模式
适用场景
- 01排查草稿 PR 的失败检查
- 02等待 PR 就绪后的机器人审查
- 03在限制轮数内处理审查反馈
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rheged-studio/ agent-skills --skill triage-pr安装后在 Claude Code 中输入/triage-pr确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
config.example.jsonpackage.jsonREADME.mdreferences/follow-up-routing.mdphase-b-envelope.mdphase-b-unattended.mdreview-discipline.mdscripts/respond-threads.mjsreview-threads.mjs详细介绍
triage-pr
分两个阶段,将一个 草稿状态且 CI 失败 的拉取请求推进到 可合并 状态,并根据 PR 的草稿状态选择阶段:
- 阶段 A——PR 处于草稿状态时: 检查失败的检查项,拉取 GitHub Actions 日志,并且只在 PR 范围内修复失败项。持续循环,直到 CI 通过或报告阻碍因素。阶段 A 无人值守运行——除硬性阻碍因素外,无需人工把关。
- 阶段 B——PR 已准备好接受评审后: 等待已配置的评审者,按“先验证,再提出处理方案”(步骤 9)处理评审意见,然后根据
humanEnvelope/--auto-apply遵循references/phase-b-envelope.md或references/phase-b-unattended.md。受maxReviewRounds限制。
从 send-it 0.8.0 起,/send-it 会打开或更新 拉取请求,然后在最后一步调用此技能(步骤 11,A-1151):它会等待至少一项检查注册,然后将任务移交给此处——原样转发 --dry-run、--ci-only、--no-promote 和 --auto-apply。默认的 /send-it 运行必须完成这次移交才算完成(A-1645)。当 humanEnvelope 为 true 时,进入阶段 B 的 send-it 流程仅会在此技能的人工审核关口暂停;当其为 false 时,流程会在步骤 13 的报告处结束(A-2014)。当 send-it 已打开 PR,或有意跳过 send-it 时,仍完全支持直接运行 /triage-pr,以便在流程中途重新进入;但这并非 send-it 流程通常的结束方式。
草稿→就绪状态的转换由单个选项控制——config.json 中的 promoteOnGreen——并且启用的配置本身就是授权:当 promoteOnGreen 为 true(默认值)时,授权转换的人工许可已通过仓库配置取得,因此阶段 A 的 CI 确认完全通过后,技能会将 PR 切换为就绪状态并继续进入阶段 B,无需停下来另行寻求批准(就绪状态转换是启用 AI 评审的关口;参见步骤 6)。转换仍受保护——必须确认 CI 通过,且不存在未解决的人工评审讨论串,同时不存在未解决的基线漂移。设置 promoteOnGreen: false(或传入 --no-promote)即可选择退出,并在 CI 通过时停止;明确的用户提示——或 --promote / --no-promote 标志——会覆盖本次运行的配置。合并到 main 始终不会自动执行;这仍是人工操作。有关阶段 B 所采用的完整评审意见接收和验证规则,请参阅 references/review-discipline.md。
配置
此文件旁的 config.json 中包含各项配置。运行开始时读取该文件,并在整个过程中使用其中的值。编辑复制的 config.json,使其与所用仓库的评审机器人以及(可选)Linear 工作区相匹配。
前十项控制 CI + 评审 循环:
| 键 | 含义 | 默认值 |
|---|---|---|
reviewBots | 将其评论和讨论串视为一等 AI 评审反馈的 GitHub 登录名。根据 author.login 匹配;会规范化 [bot] 后缀,因此 claude 和 claude[bot] 都能匹配(GraphQL API 返回不带后缀的形式)。请根据你的安装情况进行编辑——各仓库的评审机器人登录名可能不同。默认特意排除 github-actions:它发布的是 CI 状态和发布 PR 评论,而非代码评审,否则 Phase B 会将其作为发现项处理;只有当你的安装确实通过 Actions 机器人发布评审类评论时,才将其添加。 | ["claude", "coderabbitai"] |
reviewBotChecks | 将 reviewBots 登录名映射到该机器人每次评审所发布的提交状态或检查运行。值可以是检查名称字符串(例如 {"coderabbitai": "CodeRabbit"}),也可以是用于指定发布者的 { "name": "…", "producer": "…" }。name 键会匹配状态 context、检查运行名称、检查运行名称开头的 <key> / … 片段,或 <workflow> / <check>。设置 producer 后,状态的 creator.login 或检查套件的 app.slug 也必须匹配(不区分大小写;会规范化 [bot] 后缀)。只有当该状态或检查在当前头部提交上已终结,且时间晚于 ready 状态切换时,映射的机器人才能视为已完成(步骤 7)——草稿期间的“Review skipped”成功不计入,而已取消或跳过的运行表示“不会报告”,而非“缺失”。未映射的机器人则根据 ready 状态切换后、当前头部上的评审或评论活动来判断。若仓库调用 estate 的 reusable-claude-code-review.yml,rheged-skills-setup 会将 claude 映射到 { "name": "claude-review", "producer": "github-actions" }(调用方作业 ID)。 | {} |
maxCiRounds | 停止并报告阻塞项前,Phase A 的最大重新监视迭代次数。此设置限制草稿期间的修复并监视循环,避免其无限运行。Phase B 不会消耗此次数。 | 5 |
maxReviewRounds | Phase B 的最大重新评审轮数:每次应用推送后,从步骤 12 返回步骤 7(无人值守时重新规划,humanEnvelope 为 true 时重新生成处置方案),包括对此次推送重新监视 CI。达到上限后,停止并将未处理的发现项报告为阻塞项。 | 2 |
replyOnAccept | 接受某项发现时,是否在解决讨论串前发布一条说明事实、引用修复提交的线程回复(审计记录)。设为 false 时,会静默解决已接受的讨论串,适用于不喜欢机器人回复干扰的维护者——对于拒绝的发现项,无论如何都会附上理由回复。 | true |
promoteOnGreen | 控制从草稿切换为 ready 的唯一选项。设为 true 时,Phase A 结束后,如果草稿 PR 的所有必需检查都确实通过,则运行 gh pr ready <pr>,将其切换为可供评审的状态(启用 AI 评审的门槛),然后继续进入 Phase B,而不是在检查通过后停止。默认开启,启用此配置_即表示_人类作者已授权切换:确认检查通过后直接继续,无需另行征求批准。设为 false(或传入 --no-promote)即可选择退出,并在检查通过后停止。除非检查通过已得到_证实_(步骤 6 中观察到的汇总结果,而非“尚无失败”),不存在未解决的人类评审讨论串,且 mergeStateStatus 显示不存在未解决的基础分支偏移(BEHIND / DIRTY),否则不会执行升为 ready 的操作。明确的用户提示——或 --promote / --no-promote——会覆盖本次运行的此设置;--ci-only 和 --dry-run 从不执行升为 ready 的操作。 | true |
deferNonBlocking | 设为 true(默认值)时,只有依据 references/review-discipline.md 中的影响程度标准判定为高影响的有效范围内发现项,才会建议接受;否则建议列为后续处理(与范围外发现项采用相同路径)。设为 false 可恢复处置方案路径中仅按范围判断的行为(每项有效的范围内发现项都建议接受;只有范围外发现项会列为后续处理)。无人值守路径始终应用该标准。 | true |
humanEnvelope | 设为 false(默认值)时,加载 references/phase-b-unattended.md;设为 true 时,加载 references/phase-b-envelope.md。deferNonBlocking 仅适用于处置方案路径。--auto-apply 会在单次运行中强制使用无人值守模式。旧版 CLI 别名 defer / defer-pending 仍然有效。明确的用户提示会覆盖本次运行的配置。 | false |
reviewIdleMinutes | 混合评审的静默判定窗口:至少一个已配置的机器人已在当前头部提交上报告(且没有映射机器人的检查仍在等待)后,如果获取器的 activityFingerprint 在此分钟数内未发生变化,则视为评审已完成。 | 10 |
reviewWaitMaxMinutes | 切换为 ready 后(或在 PR 已处于 ready 状态时进入 Phase B 后)的混合等待硬性上限。如果到期时仍有机器人未报告,则在处置方案生成前运行慢速机器人微型门控(继续 / 延长等待 / 中止)。 | 20 |
| 后续跟进捕获(Linear)的键和路由配置位于 | ||
references/follow-up-routing.md。 |
Phase B 仅对已配置的 reviewBots 执行操作。人类的审查评论会显示在最终报告中,但绝不会自动执行操作、回复或解决——这些都留给人类处理。
使用模式
自动模式 — 检测当前分支的 PR 及其阶段,然后运行:
triage-pr
指定 PR — 按编号或 URL 操作特定 PR:
triage-pr 123
仅运行 CI — 运行 Phase A 后停止,即使 PR 已准备就绪也不例外:
triage-pr --ci-only
试运行 — 报告失败的检查和未解决的问题,并提出修复方案, 但不做任何更改(不提交、不推送、不回复讨论串):
triage-pr --dry-run
检查通过后转为就绪 — Phase A 检查全部通过后,将草稿切换为就绪状态(然后
继续进入 Phase B)。默认已启用此操作(promoteOnGreen: true);
如果配置将 promoteOnGreen: false,则 --promote 会强制本次运行执行此操作,而
--no-promote 会强制在检查通过后停止:
triage-pr --promote
自动应用 Phase B — 强制本次运行走无人值守路径(发表评论计划 + 执行操作;不询问是/否;不显示仅限 Linear 的提示)。覆盖 humanEnvelope: true:
triage-pr --auto-apply
等待耗时较长的操作
Phase A 的 CI 监控和 Phase B 的审查等待通常需要 10–30 分钟。 等待时应使用主机能够持续运行的方式,并保持安静:
- Claude Code。 前台命令最长运行时间为 10 分钟,且裸
sleep会被阻止,因此绝不要串联前台sleep,也不要依赖一次长时间的前台--watch。 将等待作为后台命令运行(run_in_background):命令退出时,执行框架会重新调用你。对于 CI 监控,在后台运行gh pr checks <pr> --watch --required。对于 Step 7 轮询,在后台 运行一个有界的 shell 循环,每 60 秒重新运行一次抓取器,满足稳定条件或达到最长等待时间后 退出(也可以使用 Monitor 工具,并在相同条件下运行 until 循环)。重新调用时重新读取结果; 不要通过反复进行短暂的前台调用来轮询。 - Cursor。 每次等待都作为一个有界的 shell 命令运行,并确保在
终端超时前结束(例如
timeout 540 gh pr checks <pr> --watch --required,或运行最长约 9 分钟的循环),然后重复运行,直到满足 条件或预算用尽。 - 任一主机。 不要发送“仍在等待”之类的中途消息;如果等待结束时 条件仍未满足(超时、预算用尽),则在下一个自然停止点报告。
流程
Step 1 — 定位 PR 并检测阶段
gh pr view <pr> --json number,isDraft,state,headRefName,baseRefName,mergeable,mergeStateStatus,statusCheckRollup
- 根据参数解析 PR;如果未提供参数,则根据当前分支解析。如果
gh pr view未找到 PR,停止并告知用户先使用/send-it创建 PR。 isDraft == true→ Phase A。CI 检查通过后,步骤 6 会执行转为就绪操作(默认 启用promoteOnGreen),将已通过全部检查的草稿切换为就绪状态,随后继续进入 Phase B。禁用此操作时(--no-promote/promoteOnGreen: false), 则报告结果并停止——AI 审查尚未运行,是否切换状态由人类决定。isDraft == false→ Phase A(确认/清理 CI),然后进入 Phase B。- 记录
baseRefName,用于漂移检查;记录mergeStateStatus,用于冲突检测。
第 2 步 — 阶段 A:检查失败的检查项
gh api repos/<owner>/<repo>/rules/branches/<base> \
--jq '.[] | select(.type=="required_status_checks") | .parameters.required_status_checks[].context'
gh pr checks <pr> --required
绿色仅表示必需检查项通过。 合并门槛是基分支的必需状态检查项,因此 CI 只根据这些检查项判定。查看分支规则中的必需上下文(上面的第一条命令;如果规则列表为空,则对旧版分支保护重复执行 gh api repos/<owner>/<repo>/branches/<base>/protection/required_status_checks --jq '.contexts[]')。只有当所有必需上下文都出现在最新提交上,并且已结束且成功(成功或已跳过)时,CI 才算绿色。gh pr checks <pr> --required(退出码:0 表示通过、8 表示待处理、1 表示失败)可以快速查看状态,但它只能看到已经注册的必需检查项:门控任务(例如“Detect Changes”步骤)可能还要稍后才会创建其余检查项,“推送后立即显示没有必需检查项报告”也是同样的情况。因此,汇总中缺失的必需上下文属于待处理,绝不算绿色。
非必需检查项——影子 CI 通道(例如 Buildkite 镜像)、AI 审核工作流(例如已取消的 claude-review),以及其他建议性状态——都只是参考信息:在第 13 步的报告中列出失败项,但绝不修复它们,绝不让它们阻止晋级,也绝不为它们消耗一个 maxCiRounds 轮次。只有当仓库确实没有必需检查项(两次查询结果都为空)时,才回退到完整汇总,但排除 reviewBotChecks 上下文,并在报告中说明这一点。
对于每个失败的必需 Actions 检查项,从该检查项的 detailsUrl(位于 statusCheckRollup 中)解析其运行 ID,并读取失败步骤的日志:
gh run view <run-id> --log-failed
记录实际失败的命令和错误行,而不只是检查项名称。你要诊断根本原因,而不是根据标签匹配问题。
第 3 步 — 阶段 A:对每项失败进行分类(范围内、上游问题或受门控)
git fetch origin <base>
git diff --name-only origin/<base>...HEAD # files this PR actually touches
- 范围内 — 失败涉及此 PR 差异中的文件,或者是可在分支最新提交上复现的 lint/测试/构建失败。修复它(第 4 步)——除非唯一的补救方式是更改 lint/格式化/静态分析配置,或添加忽略或禁用指令;这种情况下,无论失败与此 PR 的关联有多明确,都应优先归入下文的Lint 范围受门控。
- 上游问题/基线漂移 — 无论此差异如何,该任务在
origin/<base>上也会失败,或者mergeStateStatus == BEHIND,或者错误涉及 PR 从未修改的文件。补救方式是变基或合并基分支(第 5 步),而不是编辑失败的代码。 - Lint 范围受门控 — 唯一可行的补救方式是更改 lint/格式化/静态分析配置,或添加新的忽略/禁用指令。这是开发者的决定,因此不属于处理范围,你不能擅自更改。记录一项受门控事项——文件、你原本会进行的更改、没有可用代码修复方案的原因,以及首选替代方案(修复违规代码,或在共享配置包中提出规则更改)——然后继续本轮的其余工作,并在下一个自然的停顿点(第 6 步/第 13 步)汇报。完整范围列表见
references/review-discipline.md。 - 只能通过放宽门槛才能“修复”的失败绝不属于处理范围——这是重要规则中的硬性禁令;上述受门控类别则是需由人工决定的灰色地带。
步骤 4 — 阶段 A:逐一修复范围内的失败
- 在 PR 的范围内,采用能解决根本原因的最小修复。
- 修复代码,绝不修补 lint 表面问题。 对于 lint/格式/静态分析失败,优先顺序为:(1)修复有问题的代码;(2)如果规则本身确实有误,应修改共享配置包
(
@rheged-studio/eslint-config、@rheged-studio/markdownlint-config等), 并向开发者提出,而不是在这里提交;(3)只有获得开发者批准,才能使用本地配置覆盖或忽略/禁用指令。你绝不能自行采取(2)或(3)——应将其归类为受限事项(步骤 3),然后继续处理。 例外: 如果 PR 自身的差异中已经包含由开发者编写的 lint 配置或忽略项变更,你可以修复其中确实存在的错误(例如导致 lint 任务失败的语法或架构错误),但绝不能放宽规则或扩大忽略范围。 - 在本地重新运行具体的失败命令,并读取其退出代码后,才能声称问题已修复(例如
pnpm lint、npx --yes [email protected] validate ./skills/<name>、失败的测试)。固定版本,确保本地检查与 CI 完全一致,避免版本被悄然替换。先有证据,再做声明——绝不能仅凭“应该”或“可能”就断言已修复。 - 使用 Conventional Commit 格式的主题提交,然后推送。一次修复 → 一次验证 → 再处理下一项。
步骤 5 — 阶段 A:处理基准分支变更
仅当步骤 3 将失败归类为上游变更/分支落后时:
git fetch origin <base>
git merge origin/<base> # or rebase, per the repo's convention
- 合并干净 → 推送并重新监控(步骤 6)。
- 存在冲突 → 转到下文的合并冲突。
步骤 6 — 阶段 A:持续重新监控 CI,直到全部通过或预算耗尽
gh pr checks <pr> --watch --required
使用等待长时间运行的操作中的主机模式运行监控——它可能会超出前台命令的时限。
- 每次推送后,都要等待必需检查完成。仍为红色 → 回到步骤 2,除非所有剩余的红色检查都是步骤 3 中的门控项;此时应立即结束阶段 A(见下文的门控退出规则)。
- 不得提前宣告“完成”。 在
gh pr checks --watch --required(或等效的新鲜必需检查汇总)退出且每项必需检查都已进入终态(成功或失败)之前,不要告诉用户运行已完成、检查全绿或已准备好供其处理。仍在运行或为红色的非必需检查不影响此要求。排队中、待处理或进行中的检查都不属于终态——“尚无失败”、空汇总或待处理与通过混杂,都不能证明检查全绿,也不能作为完成信号(每次宣告运行结束时,都要遵守下方推广门控的同等要求)。监视退出后要重新检查: 同一提交上启动的第二次工作流运行(再次推送,或edited/ready_for_review事件)可能会取消第一次运行;--watch可能会在两次运行之间,或在门控作业创建剩余必需检查之前,以状态码0退出。宣告全绿之前,要重新应用步骤 2 的判定:该提交上的每项必需检查都已出现且成功;若某项必需检查因其运行被取消并被后续运行取代而显示失败,则不算失败——等待取代它的运行完成。 - 监视期间保持安静。 优先静默等待或在后台监视,不要用打断其他工作的“仍在等待”之类消息频繁更新。仅在自然停顿点通知用户:人工处理项(步骤 10——需要审批的可执行处置方案)、步骤 13 报告(循环收敛时)、本步骤中记录的阶段 A 提前停止(禁用推广 / 推广门控未通过 / 仍有门控的 lint 表面项 /
--ci-only/--dry-run)、慢速机器人微型门控(步骤 7),或需要作出决定的硬阻塞项 /maxCiRounds或maxReviewRounds耗尽。人工处理项本身就是可执行事项——不要把 A-1178 的“不要引起注意”规则当成跳过它的理由。 - 门控的 lint 表面项会终止循环。 如果所有剩余的红色检查都是步骤 3 中的门控项,应立即停止——不要耗尽
maxCiRounds,反复监视一个你已决定不修复的失败项。逐项报告门控项(文件、你原本会做的修改、首选替代方案),将其作为阶段 A 提前停止的事项,并把决定权交给开发者。CI 未全绿,因此下方的推广门控也无法通过;要明确指出这些门控项是未能推广的具体原因。 - 循环次数受
maxCiRounds限制。达到上限后停止,并将剩余失败项报告为阻塞项,不要无限循环。 - 检查全绿且已准备好 → 继续阶段 B。
- 检查全绿且为草稿、推广已禁用(
--no-promote/promoteOnGreen: false)→ 报告检查全绿并停止。 - 检查全绿且为草稿、推广已启用(默认,或使用
--promote)→ 翻转状态前运行推广门控。以下三项必须全部满足:- 已证明全绿——全绿状态必须来自_本步骤_监视到的必需检查结果(步骤 2 的判定:该提交上的每项必需检查都已出现且成功;不能处于待处理状态,也不能只是“尚无失败”); 遵守阶段 A 已执行的退出码规则,绝不能为了翻转状态而粉饰成全绿。红色的非必需检查不会导致此门控失败。
- 没有未解决的人工讨论线程——运行
node scripts/review-threads.mjs <pr> --bots "<config.reviewBots joined by commas>"并要求humanThreads为空。(草稿的unresolvedThreads本来就是空的——AI 审查尚未运行——因此此门控专门针对审查草稿的人工用户。) - 没有未解决的基准分支偏移——翻转状态前立即重新获取最新的
mergeStateStatus(gh pr view <pr> --json mergeStateStatus),而不是使用步骤 1 的快照:阶段 A 期间的推送可能已改变该状态。要求其不是BEHIND/DIRTY(阶段 A 的步骤 5 会解决范围内的偏移;若问题仍存在,不要推广——将其报告为阻塞项)。 三项全部通过 → 执行gh pr ready <pr>,报告状态变更,然后继续执行阶段 B (步骤 7)。标记为就绪后以及阶段 B 中的推送都会重新触发 CI 和 AI 审查;阶段 A 受maxCiRounds限制,阶段 B 受maxReviewRounds限制。任何门禁未通过 → 不要标记为就绪;报告通过的检查以及未提升状态的具体原因,然后停止。在--dry-run模式下,报告将会提升状态(或说明原因),但不做任何状态变更。在--ci-only模式下,绝不提升状态——无论相关开关设置如何,只要通过检查就停止。
步骤 7 — 阶段 B:混合等待 AI 审查者
留在同一会话中。标记为就绪后(或进入阶段 B 时 PR 已处于就绪状态),轮询获取器,直到审查结果稳定——或者达到硬上限,触发慢速机器人微型门禁。按步骤 8 中的方法解析技能目录。
node scripts/review-threads.mjs <pr> --bots "<config.reviewBots joined by commas>" --bot-checks '<config.reviewBotChecks as JSON>'
所有稳定性字段都以当前头部提交(headRefOid)为范围,并且只统计标记为就绪后(readyAt)的活动。PR 处于草稿状态时发布的内容均不计入——尤其是 CodeRabbit 在草稿期间的演练和它的“Review skipped: draft pull request”状态;针对已被取代的头部提交发布的内容也不计入。
botStatus— 每个已配置的机器人对应一条记录:state为reported、pending、skipped或missing,并包含via(check或activity)和evidence。- 在
reviewBotChecks中配置了映射的机器人(via: check),如果其状态或检查运行在头部提交上已终止成功,且时间晚于标记为就绪的时间,则为reported;如果该运行处于排队或进行中,则为pending;如果运行已取消、跳过、中立、失败,或描述中包含“Review skipped”,则为skipped(它不会报告结果——绝不要等待它);如果尚无此类运行,则为missing。 - 未配置映射的机器人(
via: activity),如果在标记为就绪后且针对头部提交执行了以下任一操作,则为reported:提交审查、在审查讨论串中发表评论,或创建或就地编辑已完成的摘要——包括带有粘性标记的摘要,或 claude-code-action 的跟踪评论(当其内容变为“Claude finished @…'s task”时)(一次干净的 Claude 审查不会留下其他内容)。- 只有确认信息——即既不含粘性标记,也不含上述完成标头的评论,例如“Claude Code is working…”——不计入。
- 在
botsReported/botsSkipped/botsMissing— 按状态对botStatus分组;botsMissing包含pending和missing。activityFingerprint— 头部、未关闭的机器人讨论串或机器人摘要(包括就地编辑)发生变化时,该值也会变化。
满足以下任一条件即视为稳定:
- 全部稳定 —
botsMissing为空(每个reviewBots条目均为reported或skipped),或 - 空闲 — 至少一个机器人为
reported,没有映射的机器人处于pending(待处理的检查意味着审查仍在运行),且activityFingerprint在reviewIdleMinutes内未发生变化,或 - 最长等待时间 — 阶段 B 等待开始后经过了
reviewWaitMaxMinutes。
使用等待长时间运行的操作中的主机模式安静地轮询(例如每 60 秒一次);等待期间不要联系用户,除非触发慢速机器人门禁。在步骤 13 的报告中列出 skipped 机器人,确保被取消的审查清晰可见,而非无声略过。
慢速机器人微型门禁——仅当 humanEnvelope 为 true 且最长等待时间已到、botsMissing 非空时触发。无人值守时(humanEnvelope: false / --auto-apply),跳过此门禁:带着当前发现继续执行步骤 8,并在步骤 13 中列出缺失的机器人。在 humanEnvelope 路径下,列出已完成与仍待处理的机器人,并在此会话中使用与步骤 10 相同的双主机结构化提问模式询问一次:
- 将超时情况放入聊天消息中(已报告的机器人与尚未响应的机器人)。
- 如有可用的结构化提问工具,优先使用:
- **Cursor
AskQuestion:**选项为 Proceed / Wait / Abort。 - Claude Code
AskUserQuestion:header示例:Review wait(≤12 个字符); 选项为 Proceed / Wait / Abort(描述:使用目前的发现继续 / 延长等待时间 / 停止且不创建信封)。
- **Cursor
- 备用方案(两种工具都不可用):使用文字说明
Review wait timed out after <N> minutes.
Reported: claude
Still outstanding: coderabbitai
Proceed with what we have / wait longer / abort? [proceed|wait|abort]
- Proceed → 使用目前的发现继续执行步骤 8(在信封报告中注明缺失的机器人)。
- Wait → 重置最大等待计时器(或再延长
reviewWaitMaxMinutes),并返回轮询循环。 - Abort → 停止;保持线程不变;不创建处置信封。
在此关卡得到答复(或通过标题/空闲状态确认评审已结束)之前,不要打开处置信封。
步骤 8 — 阶段 B:获取未解决的评审反馈
运行随附的获取脚本(路径相对于此技能自身目录):
node scripts/review-threads.mjs <pr> --bots "<config.reviewBots joined by commas>"
此获取脚本为只读。写入操作由 respond-threads.mjs 执行(步骤 11)。
它会输出简洁的 JSON,包括:
unresolvedThreads— 由已配置的reviewBot提出的内联评审线程(isResolved == false),精简为{threadId, path, line, isOutdated, author, url, comments}。GitHub 提供链接时,url为第一个评审评论的永久链接(在步骤 10 的详情块中使用)。这是需要处理的集合。deferredThreads— 已带有我们非解决型待跟进标记的机器人线程(来自之前的处理轮次)。在步骤 9 中不要重新分类;重新发现待处理捕获时,将其加入信封的跟进集合。otherBotThreads— 由不在reviewBots中的 GitHub 机器人账号(如代码检查工具或监控应用)提出的未解决线程。在步骤 9 中像处理评审机器人发现的问题一样核实并处置(接受 / 拒绝 / 跟进 / 已过时),以免遗漏,但这些内容仅供参考:它们不会阻止晋升,不会触发无人值守情况下的人类线程停止,也不会延迟步骤 13。humanThreads— 由人类提出的未解决线程。在报告中列出;不要自动处理。aiSummaryComments— 每个评审机器人的标题摘要(固定问题评论和/或评审提交正文)。每个机器人最多一条。botStatus、botsReported/botsSkipped/botsMissing、activityFingerprint、headRefOid、readyAt— 用于确认结束状态的辅助信息(步骤 7)。
已解决的线程会被过滤掉。若 unresolvedThreads 为空、otherBotThreads 为空、没有 AI 摘要,且没有 deferredThreads,则报告“没有可处理的 AI 评审反馈”,并跳至步骤 13。如果只剩下 deferredThreads,且 humanEnvelope: true,则将其并入信封计划;如果是无人值守模式(humanEnvelope: false / --auto-apply),则前往步骤 11 进行 Linear 捕获——不要提示仅处理 Linear 的内容。
步骤 9 — 阶段 B:先验证,再提出处置方案
对每项可执行的发现应用 READ → UNDERSTAND → VERIFY → EVALUATE —
unresolvedThreads、摘要条目,以及 otherBotThreads(完整规则见
references/review-discipline.md)。在计划中将
otherBotThreads 条目标记为信息项;其处置方式与其他条目相同,但未解决的条目不会阻止本次运行。
暂勿 IMPLEMENT、创建 Linear 问题或解决讨论串——仅制定带编号的处置计划:
对每项发现记录:
- 来源机器人 + 路径:行号(或问题级摘要条目)
- 有则记录讨论串 / 评论的永久链接(成形后的讨论串中的
url,或摘要条目的问题评论 / 评审 URL)——没有可靠链接时省略,不要编造 - 简短概述发现(1–3 句——无需打开 GitHub 即足以做出判断)
- 验证概要(是否属实?是否在范围内?影响是否重大?)
- 拟议处置:
accept|decline|follow-up|outdated|gated - 对于
accept:具体的修复概要 - 对于
decline:技术理由 - 对于
follow-up:Linear 标题草稿 + 理由,以及下方路由步骤中的目标位置行 (→ file under …) - 对于
outdated:遵循references/review-discipline.md(验证问题已消失,而非仅被移走) - 对于
gated:受影响的范围 + 首选替代方案——先分类,再评估影响; 完整的 lint 范围规则见references/review-discipline.md
使用 references/review-discipline.md
中的标准分类影响(在 envelope 路径中,deferNonBlocking: false 会将每项有效且在范围内的发现都提议为 accept)。
当计划中包含后续事项(或无人值守的 [gated] 条目)时,只读解析目标位置,遵循
references/follow-up-routing.md。
根据 humanEnvelope 分支:
true→ 遵循references/phase-b-envelope.md(步骤 10 门控,然后步骤 11 应用)。false/--auto-apply→ 遵循references/phase-b-unattended.md(发布计划, 然后步骤 11 应用)。
步骤 10 — 阶段 B:人工确认信封
当 humanEnvelope 为 true 时,执行
references/phase-b-envelope.md 中的步骤 10。当其为 false 或
--auto-apply 时,跳过——无人值守流程从上方的步骤 9 开始。
步骤 11 — 阶段 B:应用处置方案
按照 references/phase-b-envelope.md 或
references/phase-b-unattended.md,执行已批准的计划(envelope)或已发布的计划(无人值守)。按照 references/follow-up-routing.md 创建 Linear 后续事项。
node scripts/respond-threads.mjs thread --thread <PRRT_id> --decision accept --sha <sha> --bots "<config.reviewBots joined by commas>"
node scripts/respond-threads.mjs thread --thread <PRRT_id> --decision decline --reason "<technical reasoning>" --bots "<config.reviewBots joined by commas>"
node scripts/respond-threads.mjs thread --thread <PRRT_id> --decision follow-up-pending --bots "<config.reviewBots joined by commas>"
node scripts/respond-threads.mjs thread --thread <PRRT_id> --decision follow-up --reference <issue-id> --bots "<config.reviewBots joined by commas>"
respond-threads.mjs 只会处理作者属于 --bots 的讨论串。对于 otherBotThreads 条目,将该讨论串的作者追加到 --bots(--bots "<config.reviewBots>,<thread author>")。
步骤 12 — 阶段 B:问题级确认 + 重新封装
应用已批准的计划后,用一条汇总评论确认摘要中的重点发现:
node scripts/respond-threads.mjs summary --pr <pr> --findings '[{"title":"…","status":"accepted","reference":"<sha>"}]'
然后重新获取(步骤 8)。阶段 B 中的任何推送都会改变 head——记录新的
headRefOid,重置步骤 7 的等待计时,并返回步骤 7,之后才能判定没有新发现。如果出现新的机器人发现,继续执行步骤 7 → 步骤 9,并遵循路径文件的步骤 12 部分(重新封装或重新制定计划)。受 maxReviewRounds 限制。如果 CI 最终为绿色、机器人已针对当前 head 完成审查,且没有新的机器人发现,则继续执行步骤 13。
步骤 13 — 报告
这是完整运行结束时的完成提醒。只有在所有必需检查都已终结,或遇到硬性阻塞、预算耗尽、信封被拒绝或中止后,才发出提醒;检查仍在等待时绝不发出。Phase A 的提前停止应在步骤 6 退出时报告。
总结:
- 已修复的检查,以及每项检查所针对的失败命令。
- 信封结果(已批准/已拒绝)或已发布的无人值守计划;任何慢速机器人的决定(仅限信封路径)或缺失的机器人(无人值守);状态最终为
skipped的机器人(已取消或已跳过的审查运行),并列出其证据。 otherBotThreads(非审查机器人)的处理结果,另行列出,仅供参考。- 已接受并修复的发现(注明解决该问题的提交)。
- 已拒绝的发现,并逐项说明给出的技术理由。
- 等待开发者决定的受门控 lint 范围事项——逐项列出文件、原本会进行的更改、没有可用代码修复方案的原因,以及首选替代方案(修复代码,或在共享配置包中提出)。此列表中的事项均未应用。
- 已创建的后续问题(逐项注明其 Linear ID/URL、
follow-up标签,以及目标位置——继承的项目和里程碑、仅继承的项目,或兜底项目加仓库里程碑),或未跟踪的后续候选事项。 - 已在合并评论中确认的问题级发现。
- 已执行的基准合并/变基。
- 剩余阻塞项(若
maxCiRounds或maxReviewRounds已耗尽)。 - 最终 CI 状态,并提供步骤 2 测试的最新证据——列出头部提交上的每个必需上下文及其终结状态;之后另行列出任何标红的非必需检查,仅供参考。
- 任何人工审查评论,供人工处理。
- PR 的草稿/就绪状态:若触发了晋升,报告状态切换(草稿 → 就绪),并说明之后运行了 Phase B;否则提醒状态未变——若已启用晋升但被某个门控条件阻止,则说明具体原因。
合并冲突
- 只有在解决方式明确且属于 PR 范围内时才解决(例如双方修改了不同的代码块,或此分支的意图明显优先)。
- 若意图不明确,则中止并询问人工:双方修改了同一逻辑内容、冲突涉及 PR 范围之外的文件,或解决冲突需要产品决策。运行
git merge --abort并报告冲突文件。 - 绝不要为了让代码编译而通过删除另一方的工作来解决冲突。
重要规则
- 绝不粉饰。 绝不编辑
.github/workflows/*、禁用或放宽 lint 规则、删除或跳过测试,或放宽 CI 阈值来让检查通过。修复代码,或将失败报告为阻塞项。 - Lint 检查范围由开发者决定。 将其归类为 受门控(Step 3 / Step 9);未经明确的 envelope 批准,绝不应用。完整政策和检查范围列表见:
references/review-discipline.md。 - 只处理范围内的问题。 仅修复本 PR 的差异所涉及的问题;不要修复无关的仓库问题。
- 先验证,再实施。 未先针对代码库验证之前,绝不应用审查建议。
- 仅处理 AI 机器人。 处理已配置的
reviewBots,并将otherBotThreads作为信息性、非阻塞发现;指出人工评论,但留给人工处理。 - 不阿谀奉承。 以技术理由拒绝,不要恭维。
- 先有证据,再作断言。 未重新运行验证命令并读取其退出代码前,绝不声称 CI 全绿或修复有效。CI 全绿意味着所有必需上下文都已出现,并且在最新提交上成功(Step 2)。只要仍有必需检查尚未进入终态(排队 / 待处理 / 进行中),就绝不声称运行已完成、已处理完毕或可供关注——“尚无失败”不等于全绿,也不等于完成。只在自然的停止点提醒人工:人工 envelope(Step 10,当
humanEnvelope为true时)、Step 13、文档规定的 Step 6 Phase-A 提前停止条件(promotion 已禁用 / gate 失败 / 仍有受门控的 lint 检查项 /--ci-only/--dry-run)、慢速机器人的微型 gate,或硬性阻塞项 / 预算耗尽时——绝不要在监控过程中间发送“仍在等待”的提醒。 - 两条 Phase B 路径。 加载
references/phase-b-envelope.md或references/phase-b-unattended.md;不要应用这些文件之外的处置方式。 - Draft → ready 受保护,且默认开启。
promoteOnGreen是切换状态的唯一控制项;启用的配置即为授权:开启时(默认值),skill 会在 Phase A 已验证全绿、没有未解决的人工讨论串且没有未解决的基准分支漂移后,才切换 PR 状态,然后继续进入 Phase B,无需另行征求人工批准。设置promoteOnGreen: false/ 传入--no-promote可在全绿时停止;显式的用户提示或--promote/--no-promote会在本次运行中覆盖配置。绝不为了切换状态而粉饰结果;--ci-only绝不会执行 promotion。合并仍由人工操作。 - 循环次数有上限。 Phase A 达到
maxCiRounds或 Phase B 达到maxReviewRounds后停止并升级处理。
错误处理
gh auth status失败 → 停止,并告知用户运行gh auth login。- 当前分支没有 PR → 停止,并提示“先用
/send-it创建一个”。 gh run view --log-failed不可用(日志已过期或运行记录已清除)→ 按名称报告失败的检查,不要猜测原因;不要捏造修复方案。- 审查讨论串抓取器以非零状态退出(速率限制、权限或 GraphQL 错误)→ 报告该问题,并回退到
gh pr view <pr> --json reviews,comments。绝不要把“无法抓取”当成“没有发现”。 - 过时的讨论串 → 按照
references/review-discipline.md处理(--decision outdated)。 respond-threads.mjs以非零状态退出(回复或解决讨论串的操作因权限失败)→ 回退到手动使用gh api graphql回复并说明理由,而不是中止;标记约定仍然适用,以便后续运行跳过该项。- 汇总评论的
summaryupsert 找不到之前的评论(REST 分页上限约为 100 条)→ 它会发布新评论;这没有问题,只需避免手动删除标记,以便下一次运行能够找到并编辑该评论。
参数
$ARGUMENTS