关于 finish-pr
Finish PR 是一项技能,用于将当前分支关联的拉取请求推进到明确的就绪状态。它指导开发者处理冲突、CI、评审意见和 PR Agent 检查,同时保留由评审者决定线程是否解决的权限。
主要功能
- 01检查仓库说明和拉取请求状态
- 02优先处理合并冲突
- 03以独立提交处理评审意见
- 04发布前检查 CI 和 PR Agent 状态
适用场景
- 01使分支上的拉取请求达到完成评审的条件
- 02处理尚未解决的行内评审意见
- 03推送或回复前等待自动评审完成
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pinguapps/ skills --skill finish-pr安装后在 Claude Code 中输入/finish-pr确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlscripts/get-unresolved-pr-threads.ps1reply-to-review-thread.ps1wait-for-pr-review.ps1tests/reply-to-review-thread.tests.ps1wait-for-pr-review.tests.ps1详细介绍
完成 PR
将当前分支关联的拉取请求处理到真正就绪的状态。
需要 Git 2.38+、已通过身份验证并可访问此仓库的 GitHub CLI(gh),以及用于捆绑辅助脚本的 PowerShell 7(pwsh)。
完成标准
仅当当前 PR HEAD 满足以下所有条件时,才算完成:
- GitHub 和本地合并探测均显示不存在合并冲突。
- 没有 CI 检查失败。待处理的检查可能仍在运行,但在必需检查仍处于待处理状态时,绝不能将 PR 描述为已完全就绪。
- 每个尚未解决的审查讨论串都处于以下某种状态:
- 最新的未处理反馈已采取相应措施,且 Agent 已回复处理结果;或
- 最新的相关评论是 Agent 的回复,之后没有审查者回复,因此该讨论串正在等待审查,无需重复处理。
- 本次运行创建的回复没有任何一条仍保留在待处理的 GitHub 审查中。
- 本次运行没有更改任何审查讨论串的解决状态。
- 如果此仓库正在运行 PR Agent,则当前精确 HEAD 必须具有已成功完成的
PR Agent检查运行记录,或状态为success的PR Agent提交状态,且没有活跃的 PR Agent 审查信号。检测方法和状态语义请参阅下方的 PR Agent 部分。
尚未解决的讨论串不一定意味着工作未完成。审查者负责决定是否解决讨论串;对话顺序决定当前是否需要 Agent 采取行动。
PR Agent
PR Agent 是一个可能正在运行、也可能未运行的可自托管审查工具。检测其名为 PR Agent 的检查运行,或其上下文为 PR Agent 的旧版提交状态(可通过其 CHECK_NAME 配置);这些状态会发布在它审查的每个 PR 头部上。
- 检测:如果当前 HEAD 或该拉取请求的任意更早提交上存在
PR Agent检查运行或提交状态,就认为 PR Agent 正在运行。如果整个 PR 中都不存在这两者,则它未在运行——绝不要等待它,不要发布任何内容来触发它,并跳过以下所有 PR Agent 规则。 - 状态含义:排队中/进行中的检查运行和旧版
pending表示正在运行。已完成的failure表示存在发现;已完成的success或旧版success表示批准了该确切 HEAD。neutral、已取消、超时、已跳过或其他非成功/非发现结论,以及旧版error,都表示未完成,绝不代表已批准。应检查服务错误和重试状态,而不是为了迎合基础设施故障而更改代码。若此前有活动记录,但当前头部没有信号,则等待自动审查。如果多个信号并存,任何最新活动信号都会阻止发布;只有所有最新信号都成功,才算批准。 - 反馈识别:当前 PR Agent 评论来自其 GitHub App;旧版本使用所有者的登录名。通过隐藏的 `` 标记或 PR Agent 徽章识别审查者消息,绝不要仅凭作者登录名判断。即使登录名与你相同,捆绑的监视器也会包含带标记的审查反馈。
- 线程处理:对 PR Agent 采用与其他所有审查者完全相同的处理方式——认同并修复(一个针对性提交,然后在该线程中回复提交 SHA 和验证结果),或提供具体证据进行反驳。绝不要解决 PR Agent 线程:由它负责解决,并会在它根据已推送的 HEAD 验证修复或接受有理有据的拒绝后自动解决线程。
- 解决记录:区分已验证的修复、误报、预期行为和已接受的权衡。已修复的缺陷可能会重新引入;拒绝只在其有来源依据的前提仍然成立时有效。如果 PR Agent 再次反驳,只有在有新证据时才继续讨论;否则让线程保持未解决,等待它回复。
- 已被取代的审查:首次审查会覆盖整个 PR;后续自动审查会检查自上次已完成的祖先提交以来的更改,以及验证发现所需的上下文。重写历史或存在不兼容的已保存工作时,可能需要完整审查。推送会取代正在进行的审查。通过下方的自动审查门控来保留正在运行的审查;默认不要请求额外的全 PR 审查。
操作规则
- 将对话历史作为首要任务上下文。此技能通常在实现完成后调用,因此在评判 PR 反馈之前,先还原用户意图、此前的决定、权衡、验证结果、已知限制以及当前设计的原因。
- 阅读所有适用的
AGENTS.md,以及 PR 涉及的仓库原生要求和设计文档。根据仓库和 PR 查找这些内容;切勿假设特定的任务目录、分支命名方案、语言、构建系统或托管平台。 - 将尚未解决的评审讨论串视为权威的行内反馈列表。还要检查 PR 级别的评审和问题评论,查找独立且可执行的反馈。
- 保留与任务无关的工作区更改。只提交本次运行所做的更改。
- 先解决冲突,再处理失败的检查,最后处理评审反馈。后续证据可能需要重新审视较早阶段。
- 优先采用正确且改动最小的方案。针对行为问题或容易回归的问题,添加有针对性的测试。
- 确认缺陷后,搜索有变更的实现和 PR 中直接相关的代码,查找由已证实原因引发的其他实例。在同一反馈单元的提交中修复已验证的实例;适用时,测试此类共同故障。将与 PR 无关的既有缺陷留在范围之外;这是有针对性的因果排查,而非清理整个仓库。
- 对于处置结果需要产生更改的每个需采取行动的 PR 反馈单元,恰好创建一个有针对性且不压缩的提交:每个评审讨论串或独立的 PR 级反馈项各一个提交。即使多个单元彼此相关,也绝不将它们合并为一个提交。若有充分理由表示异议,则需要回复,但不创建提交。
- 除非用户明确要求单独执行,否则绝不变基、强制推送、在 GitHub 上合并拉取请求、关闭、批准或将 PR 标记为可供评审。冲突解决流程可以将最新的基分支提交合并到 PR 分支。
- 绝不解决或重新打开评审讨论串。不得调用
resolveReviewThread、unresolveReviewThread或等效操作。 - 逐条直接回复评审讨论串。绝不并发发送回复。
- 每次推送或评论 PR 之前(包括讨论串回复、异议、确认、提醒以及推送后的延迟回复),都必须先通过下文的自动化评审门槛。
- 推送后,针对 PR Agent 和所有其他来源的新反馈,继续自主处理,直至达到下文规定的收敛上限。
- 让 PR 自动化机制主动发起评审。默认不要联系任何评审者(自动化或人工),请求其评审或回复。对于 PR Agent 和 Copilot 以外的评审者,只有在回复是完成 PR 的必要条件、当前没有正在进行的评审,且该评审者已沉默至少 25 分钟(自动化评审者)或一个工作日(人工评审者)时,才发送一条简短提醒。跨本技能的多次运行,以 PR 创建时间或 Agent 最近一次回复时间为起点,计算人工评审者的等待时间;否则应将等待时间报告为阻碍因素。绝不通过 GitHub 控件、评审者指派或重新指派、评论、CLI 命令、API 调用或任何等效方式提醒 Copilot,也不得手动请求或触发 Copilot 评审或重新评审。
pinguapps-pr-agent会在创建时接手所有 Copilot 讨论串;对其反馈采取行动,并在修复或有理有据地拒绝后回复一次,然后将验证及后续跟进留给该机器人。 - 绝不发布用于触发 PR Agent 的评论或备用评论。PR Agent 运行时会自动发现 PR 和推送;使用其检查运行或旧版提交状态及行内讨论串作为最终信号。
自动审核门禁
此门禁仅适用于 PR Agent。其他审核者和无关的 CI 检查不会通过此门禁阻止推送或评论;现有 CI 和反馈要求仍然适用。
每次推送或发布 PR 评论前,立即刷新已发布的 PR head、其 PR Agent 检查运行记录以及任何旧版 PR Agent 提交状态。使用 gh pr checks 检查所有检查,包括可选检查;必要时使用分页的检查运行记录和提交状态 API 结果,确认准确的 head、提供方或最新状态。仅当 PR Agent 未在此 PR 上运行时,才跳过门禁。检测到 PR Agent 时,缺少当前 head 的信号并不能证明审核已完成;请等待其自动审核。
捆绑的 scripts/wait-for-pr-review.ps1 -Inspect -PrNumber <number> -Repository <host/owner/repo> 会生成一份经过最新 head 验证的快照,并为检查运行记录和旧版状态提供一个 prAgentStatus 分类:pending、success、failure、incomplete 或 absent。它会对两个 API 的结果进行分页,并为每个 App 选择最新的同名运行记录。读取或身份验证失败应视为未知并阻止操作,绝不能视为不存在。即使当前信号缺失,仍须进行历史检测。门禁和备用监视器应使用此分类,而不是自行重新构建不兼容的状态规则。
- 只要 PR Agent 最新的当前 head 审核检查运行记录中有任何一项尚未
completed,包括已排队或正在运行的记录,或者其最新的当前 head 旧版状态为pending,PR Agent 就处于活动状态。 - PR Agent 处于活动状态期间,所有修复、提交和回复草稿都必须保留在本地。绝不推送或发布任何 PR 评论,无论评论对象是谁,也无论评论是否提及某个提交。处理其他已完成审核的审核者所提供的反馈;PR Agent 的反馈则暂缓处理,直到其审核完成。
- PR Agent 完成后,重新获取反馈,处理新完成的反馈,并在发布该批内容前重复反馈审查。完成的审核可能包含问题或失败;此门禁要求审核已结束,而非获得批准。完成标准仍要求最终结果干净。
- 在推送前以及每条按顺序发布的评论前,都要重新检查门禁。先前的空闲快照、已捕获的基线、监视器结果或成功推送,都不能授权下一次变更。推送可能立即启动新一轮审核;保留暂缓的回复,直到 PR Agent 完成,然后重新读取相关讨论串,避免重复回复或回复已被取代的内容。
- 如果在现有的 25 分钟等待时间或整体收敛时限内无法确认审核已完成,则停止操作,保留本地提交和排队的回复,并报告阻碍因素。超时绝不允许绕过门禁。
1. 确定状态和意图
-
定位仓库根目录并阅读适用的说明。
-
检查:
git status --short git rev-parse --abbrev-ref HEAD git rev-parse HEAD gh --version gh auth status gh pr view --json number,title,url,body,author,headRefName,headRefOid,headRepository,headRepositoryOwner,isCrossRepository,baseRefName,baseRefOid,mergeable,mergeStateStatus,reviews,comments -
记录起始 SHA 以及所有已有的变更路径,并区分已暂存、未暂存和未跟踪的变更。绝不要将本次运行开始前已有的变更纳入提交。 反馈或 CI 修复不得触及任何在开始前已有已暂存、未暂存或未跟踪变更的路径。编辑此类路径前先停下并询问用户;部分暂存再使用
git commit --only无法保留同一文件内区块的隔离。 -
如果当前分支没有 PR,请检查
gh pr status。仅当映射明确且本地变更安全时,才切换或检出 PR;否则询问用户。 -
按以下优先顺序还原预期变更:
- 用户的明确指示和本次对话;
- 适用的仓库说明;
- PR 标题、正文、提交和差异;
- 关联的问题、规范或设计文档;
- 周边代码、测试和惯例。
-
在评估冲突、CI 或反馈之前,检查完整的 PR 差异。
-
根据上述规则,通过当前及更早的 PR 提交检测 PR Agent。将其针对精确 HEAD 的检查运行或旧版状态视为处理/完成边界,并从审查讨论串读取其发现。
-
确定已认证的 GitHub 查看者登录名。将来自该登录名的评论,或根据对话/PR 历史可明确确认属于其他 Agent 登录名的评论,视为 Agent 回复。
-
根据 PR 元数据分别确定基础仓库和头仓库:
- 从 PR URL 推导基础仓库;
- 使用
headRepository.nameWithOwner确定头仓库; - 优先使用与这些确切仓库匹配的现有已配置远程;
- 否则使用 GitHub 提供的克隆 URL,并配置 Git 使用已认证的
gh凭据助手; - 保留确切的
headRefName。
$pr = gh pr view --json number,url,headRefName,headRefOid,headRepository,headRepositoryOwner | ConvertFrom-Json $prNumber = [int]$pr.number $prUri = [uri]$pr.url $pathSegments = $prUri.AbsolutePath.Trim("/").Split("/") $githubHostname = $prUri.Authority $baseRepositoryName = "$($pathSegments[0])/$($pathSegments[1])" $baseRepository = "$githubHostname/$baseRepositoryName" $baseMetadata = gh api --hostname $githubHostname "repos/$baseRepositoryName" | ConvertFrom-Json $headMetadata = gh api --hostname $githubHostname "repos/$($pr.headRepository.nameWithOwner)" | ConvertFrom-Json gh auth setup-git --hostname $githubHostname $baseFetchUrl = [string]$baseMetadata.clone_url $headPushUrl = [string]$headMetadata.clone_urlGitHub 的
clone_url会保留服务器权限部分,包括非默认端口;而gh auth setup-git会使 HTTPS Git 操作使用已认证的 CLI 身份。也可以使用已验证且匹配的 SSH/已配置远程。如果身份验证、仓库身份或头仓库不可用或不明确,请停止。绝不要假定origin指向基于 fork 的 PR 的任一方。 -
进行任何更改之前,将检出内容与确切的 PR 头对齐:
git fetch $headPushUrl $pr.headRefName
$remoteHeadSha = (git rev-parse FETCH_HEAD).Trim()
$lastObservedPrHeadSha = $remoteHeadSha
$localHeadSha = (git rev-parse HEAD).Trim()
git merge-base --is-ancestor $remoteHeadSha $localHeadSha
$localContainsRemoteHead = $LASTEXITCODE -eq 0
if ($localContainsRemoteHead -and $localHeadSha -ne $remoteHeadSha) {
$initialLocalAheadCommits = git log --oneline "$remoteHeadSha..$localHeadSha"
# Validate and record every commit against the recovered user intent and full PR diff.
# Stop for confirmation if any commit is unrelated, unfinished, or ambiguous.
}
if (-not $localContainsRemoteHead) {
git merge-base --is-ancestor $localHeadSha $remoteHeadSha
$canFastForward = $LASTEXITCODE -eq 0 -and -not (git status --porcelain)
if (-not $canFastForward) {
throw "Local HEAD is stale or diverged from the PR head; stop before mutation."
}
git merge --ff-only $remoteHeadSha
}
只有在本地 HEAD 与已获取的 PR 头匹配、已安全地快进到该提交,或所有最初本地领先的提交都已根据对话和仓库证据明确确认为预期 PR 工作时,才继续。将这些提交记录为预先存在的推送范围;有任何不确定之处,都应停止并请求确认。绝不要悄悄发布本地领先的提交。
11. 在仓库外创建一个唯一的状态目录,并在整个运行期间保留该目录:
$runStateDirectory = Join-Path ([IO.Path]::GetTempPath()) (
"finish-pr-{0}-{1}" -f $prNumber, [guid]::NewGuid().ToString("N")
)
New-Item -ItemType Directory -Path $runStateDirectory | Out-Null
将本次运行的所有基线、快照和监视器状态文件都存放在此目录中,以免并行运行相互覆盖。
2. 解决合并冲突
在 CI 检查或反馈之前运行:
-
刷新 PR/基础分支元数据,并执行不会修改内容的本地探测:
$pr = gh pr view $prNumber --repo $baseRepository --json number,url,baseRefName,baseRefOid,headRefName,headRefOid,headRepository,headRepositoryOwner,mergeable,mergeStateStatus | ConvertFrom-Json git fetch $baseFetchUrl $pr.baseRefName $baseCommit = (git rev-parse FETCH_HEAD).Trim() git merge-tree --write-tree --messages HEAD $baseCommit -
如果 GitHub 报告
CONFLICTING、DIRTY或UNKNOWN,或者探测报告存在冲突,请在本地调查。 -
如果存在冲突,请在合并前检查初始工作区基线。正常合并要求暂存区干净:如果仍有任何预先存在的已暂存更改,请在修改前停止,并告知用户提交或暂存这些更改,或请求明确许可,以便隔离并恢复暂存区。未经许可,不要对用户的工作使用
--autostash。如果暂存区干净,且无关的本地更改不受影响,请将最新的基础分支合并到 PR 分支:
git merge --no-ff $baseCommit -
根据恢复出的任务意图、仓库要求、相邻代码和测试解决每个冲突。不要机械地偏向任一方。
-
运行针对性验证,仅暂存冲突解决内容,并提交。记录冲突摘要、提交 SHA 和运行的检查。
-
如果合并没有冲突,保留 Git 创建的合并提交,但不要额外创建空提交。
3. 修复 CI 失败
-
检查所有检查项:
gh pr checks $prNumber --repo $baseRepository --json bucket,completedAt,description,event,link,name,startedAt,state,workflow gh pr checks $prNumber --repo $baseRepository --required --json bucket,completedAt,description,event,link,name,startedAt,state,workflow使用第二条查询区分必需检查和可选检查。将“未报告必需检查”视为空的必需检查集合,而不是失败。
-
对于每项失败,在编辑前获取实际日志:
gh run list --repo $baseRepository --branch $pr.headRefName --commit $pr.headRefOid --json databaseId,name,workflowName,status,conclusion,url,headSha,event,createdAt -L 50 gh run view <run-id> --repo $baseRepository --json name,status,conclusion,jobs,url gh run view <run-id> --repo $baseRepository --log-failed -
对于非 Actions 检查,检查提供方链接或可用的检查详情。
-
修复根本原因,而不只是表面症状。从最明确的上游失败着手,因为一项失败可能导致其他失败。
-
运行最接近的本地等效检查,检查初始工作区基线,并且只暂存该修复。使用精确的路径规格提交,确保预先存在的已暂存更改不会纳入 CI 提交:
git commit --only -m "fix(ci): address <failed check>" -- <exact-ci-fix-paths>如果 CI 修复路径中存在预先已暂存、未暂存或未跟踪的更改,请在编辑前停止。记录检查项、原因、SHA 和验证结果。
-
如果失败由外部因素、偶发问题、权限问题导致,或无法通过修改仓库修复,请收集证据。仅在安全且条件允许时重试;不要为了应对无关失败而修改代码。
4. 获取并分类反馈
解析已加载技能的目录,然后通过绝对路径使用其附带的辅助工具;不要假定该技能位于目标仓库内。
在仓库外记录每个讨论串的只读解析基线:
$threadBaseline = Join-Path $runStateDirectory "thread-resolution.json"
$threadSnapshot = Join-Path $runStateDirectory "unresolved-threads.json"
pwsh <skill-directory>/scripts/get-unresolved-pr-threads.ps1 -PrNumber $prNumber -Repository $baseRepository -Hostname $githubHostname -All |
Set-Content -Encoding utf8 $threadBaseline
pwsh <skill-directory>/scripts/get-unresolved-pr-threads.ps1 -PrNumber $prNumber -Repository $baseRepository -Hostname $githubHostname |
Set-Content -Encoding utf8 $threadSnapshot
对于每个尚未解决的讨论串,按时间顺序读取所有分页评论并进行分类。无论作者登录名是什么,凡是带有隐藏 `` 标记或 PR Agent 徽章的评论,都归类为审核者反馈。然后对讨论串进行分类:
- **Copilot 交接:**如果讨论串由 Copilot 创建,则处理其反馈,并回复一次,说明修复内容或有理有据地拒绝。
pinguapps-pr-agent会验证回复并处理后续跟进。切勿请求 Copilot 审核或向其发送提醒。 - **等待审核者:**最新的相关评论是 Agent 在已提交审核中的回复(
pullRequestReview.state != PENDING且submittedAt非空),并且之后无人回复。无需操作。不要发送提醒、重复修复内容或重复回复。PR Agent 的消息也视为审核者消息,适用此规则:PR Agent 回复(验证结果、反驳或解决说明)后,讨论串正在等待你采取行动,或已由你解决。 - **需要处理:**Agent 最近一次已提交回复之后出现了审核者反馈;Agent 从未回复;或 Agent 最近一次回复仅存在于待提交审核中。此对话顺序规则也适用于 PR Agent:如果一个尚未解决的讨论串已在等待它回复,则无需重复修复或回复。对于新产生的待处理反馈,应赞同并通过一个专注的提交修复,或提供依据进行反驳,让 PR Agent 重新评估。
- **已被取代/无需处理:**后续对话明确撤回、回答或取代了该意见。仅当讨论串仍需要 Agent 确认时才回复;避免重复已有的 Agent 回复。如果 PR Agent 在刚解决的讨论串中留下“已验证……正在解决此讨论串”的说明,则无需回复。
对于需要处理的讨论串,识别每一项不同的反馈。应结合用户意图、对话历史、仓库规则、关联要求、PR 范围、当前代码、惯例和测试来判断。讨论串是提交边界:将同一讨论串所需的所有工作合并为该讨论串的一个提交,但绝不要包含其他讨论串的工作。
使用相同规则对可执行的 PR 级审核正文和 issue 评论进行分类。每一项独立反馈都是单独的提交边界;绝不要将其与审核讨论串或其他独立项目合并。由于它们没有审核讨论串 ID,请通过反馈 ID 和永久链接进行追踪。
- 如果反馈指出了真实缺陷、遗漏的要求、被破坏的不变量、缺失的测试、误导性行为或范围内的可维护性问题,则予以认可。
- 如果反馈与要求、既定意图、仓库不变量冲突,或会导致更差/超出范围的设计,则予以反驳。
- 如果无法确定,且证据支持,则进行小范围的正确性修复。否则,说明存在的不确定性以及未作更改的原因。
不要跳过过时但尚未解决的讨论串;应判断其反馈是否仍适用于当前代码。
5. 修复并回复
对于自动化审查门控允许处理的每个需要采取行动的审查线程或独立反馈项:
-
针对该线程中的每个可操作事项,做出最小且完整的修复,并编写有针对性的测试。
-
运行范围最小且有意义的验证。
-
检查并仅暂存该事项涉及的文件:
git status --short git diff git add <paths> git diff --cached保持其他路径中无关的已暂存更改处于暂存状态。若某个修复路径存在预先暂存、未暂存或未跟踪的更改,则在编辑该路径前停止;绝不要依赖先部分暂存、再使用
git commit --only来隔离同一文件中的更改。 -
如果处理结果产生了更改,则在处理下一个事项前,恰好为该反馈单元创建一个提交:
git commit --only -m "fix(pr): address <thread summary>" -- <exact-thread-fix-paths>不要修改、压缩或合并反馈提交。如果较早单元的更改已完全满足后续已同意处理的单元,且没有剩余的独立文件更改,则为后续单元使用
--allow-empty创建一个明确的可追溯提交,而不是合并它们的提交历史。对于有充分理由的异议,不要创建提交。 -
对于审查线程反馈,在评估反馈并创建任何相关提交后,直接在该线程中回复,但须遵守自动化审查门控和下方的提交延迟要求。若任一条件阻止发布回复,则在本地起草并排队:
$body = @" Agreed. I fixed this in commit <sha> by <specific change>. Verification: <command and result>. "@ pwsh <skill-directory>/scripts/reply-to-review-thread.ps1 -ThreadId "<thread-id>" -Hostname $githubHostname -Body $body对于独立反馈,发布 PR 级别的回复,并链接到确切的反馈永久链接:
$body = @" Regarding [this feedback](<feedback-permalink>): agreed. I fixed this in commit <sha> by <specific change>. Verification: <command and result>. "@ gh pr comment $prNumber --repo $baseRepository --body $body对于有充分理由的独立异议,也使用相同的 PR 级别回复方式,同时保留反馈永久链接,并采用下方的异议措辞。
对于有充分理由的异议:
I don't think this change is correct for this PR. Reason: <specific reason grounded in requirements, conversation, or code>. No code change made.如果任何 PR Agent 反馈处理结果创建的提交尚未推送,则将其线程回复或 PR 级别回复延迟到批量推送完成且自动化审查门控解除之后。PR Agent 无法验证仅存在于本地的 SHA;在它能看到提交之前回复,可能会导致误导性的后续反馈。异议不依赖提交,但仍须等待门控解除。所有回复均须按顺序逐条处理。
-
记录发生更改的处理结果中,一对一的反馈单元 ID → 提交 SHA 映射,以及每项处理结果、验证结果和返回的评论 ID。审查线程使用线程 ID,独立反馈项使用反馈 ID。有充分理由的异议记录为
no commit — disagreement。
回复辅助工具使用 GitHub 的单条评论回复端点,因此绝不会提交或修改共享的待提交审查。随后,它会验证 state != PENDING 且 submittedAt 不为 null。辅助工具失败属于阻塞问题;仅返回评论 URL 并不能证明回复已提交。
每批反馈处理后(包括仍有回复处于排队状态时):
- 使用
-All重新获取所有线程,以及 PR 级别的审查和议题评论。 - 验证本次运行创建的每条回复都属于已提交的审查。
- 验证已认证用户在该 PR 上没有待提交的审查,包括本次运行前创建的审查。
- 对基线中存在的每个线程 ID,将其
isResolved值与当前值进行比较。基线的解决状态必须保持不变;报告外部更改,且绝不将其改回。审查趋于一致期间,出现新的线程 ID 是预期情况:应将其归类为额外反馈,而不是视为解决状态变更。 - 如果批次处理中出现了新的需要采取行动的审查线程或独立反馈项,则对每个符合条件的事项分别创建一个提交并执行相应操作,然后重复审计。只有在自动化审查门控解除,且刷新后的反馈集均已处理完毕或正在等待审查者回复时,才可推送。已在本地处理完毕且回复已排队的事项,在推送前审计中视为已处理;但在提交延迟要求解除且门控通过后,仍必须发送这些回复;在回复发布前,这些事项不视为正在等待审查者回复。
6. 推送并与审查趋于一致
-
确认工作树中没有本次运行产生的未提交更改。不要在单个线程提交产生后立即推送;仅在所有正在运行的 PR Agent 审查完成且更新后的反馈审计无问题后,才批量推送所有未压缩的线程提交。
-
审查起始 SHA 之后的提交,以及调用时已在本地领先的每个经过验证的提交,然后在推送前获取确切的 PR 头:
git log --oneline <starting-sha>..HEAD git fetch $headPushUrl $pr.headRefName $remoteHeadSha = (git rev-parse FETCH_HEAD).Trim() $localHeadSha = (git rev-parse HEAD).Trim() $currentPrHeadSha = (gh pr view $prNumber --repo $baseRepository --json headRefOid --jq .headRefOid).Trim() $pushRequired = $localHeadSha -ne $remoteHeadSha git status --short --branch如果
$remoteHeadSha和$currentPrHeadSha不同,或者任一者与$lastObservedPrHeadSha不同,则停止。绝不要用意外的远程值覆盖$lastObservedPrHeadSha。使用$pushRequired(而非起始 SHA 提交范围)判断是否需要推送 PR 头;该范围仅用于报告上下文。 -
如果
$pushRequired,则递增$reviewRound,并在推送前立即记录审查基线:$reviewRound++ $reviewState = Join-Path $runStateDirectory ("review-round-{0}.json" -f $reviewRound) pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 ` -CaptureBaseline ` -StatePath $reviewState ` -PrNumber $prNumber ` -Repository $baseRepository ` -Hostname $githubHostname ` -PrAgentContext "PR Agent" -
推送前,针对已发布的头重新检查自动审查门槛。如果被阻止,请将这批提交保留在本地,等待审查完成,然后重复反馈审计和头检查,再重新记录基线。门槛解除后,不使用强制推送,并记录确切的 HEAD:
$reviewRequestedAt = [DateTimeOffset]::UtcNow git push $headPushUrl "HEAD:refs/heads/$($pr.headRefName)" $expectedHeadSha = git rev-parse HEAD $lastObservedPrHeadSha = $expectedHeadSha推送后保留排队的回复。每次回复前重新检查自动审查门槛;如果推送已启动 PR Agent 审查,则等待其完成。然后重新读取反馈,仅针对仍需处理的内容,串行发布回复,并附上当前可见的提交 SHA 和验证结果。确认线程回复已提交,并刷新反馈。对不同意见以及回复任何其他审查者,也应用相同的门槛。
-
推送后,如果 PR Agent 正在运行,则等待其针对确切 HEAD 给出结果:
- **PR Agent 检查运行或旧版状态:**如果环境提供 PR 监视器,则使用它,并在每次唤醒时继续进行确切头审计。否则使用下面打包的
-Wait命令;它会使用与-Inspect相同的分类方式处理这两种信号。若确切头的结果成功且没有新反馈,则可直接进行最终审计。 - **PR Agent 未运行:**刷新检查和反馈,然后进行最终审计。不要等待不存在的集成。
pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 ` -Wait ` -StatePath $reviewState ` -ExpectedHeadSha $expectedHeadSha ` -ReviewRequestedAt $reviewRequestedAt ` -TimeoutMinutes 25 ` -PollSeconds 20将其作为长时间运行的工具调用执行。运行期间,只使用环境的等待机制;除非用户中断,否则保持静默。监视器会避免将重复轮询带入模型上下文。
- **PR Agent 检查运行或旧版状态:**如果环境提供 PR 监视器,则使用它,并在每次唤醒时继续进行确切头审计。否则使用下面打包的
-
根据所选等待路径的结果,按以下情况处理。捆绑式监视器会像其他审查者一样,通过
newFeedback内联提供发现。其他审查仍在进行时,也可能收到反馈;使用自动审查门控机制判断哪些反馈符合处理条件,以及是否允许发布:feedback:获取所有反馈作为上下文,但只处理新产生且尚待处理的反馈(使用捆绑式监视器时为newFeedbackID)。其中可能包括内联讨论串(来自 PR Agent、Copilot 或其他审查者)、任何审查者针对 PR 的反馈,以及 PR Agent 在报告failure且未捕获到评论时生成的合成pragent_status项。如果新评论延续了旧的未解决讨论串,请阅读完整讨论串,只处理 Agent 最后一次回复之后的反馈。PR Agent 的发现遵循相同的认可并修复/提出异议规则;它会重新验证已推送的修复,并自动解决自己的讨论串。对于 Copilot 讨论串,只回复一次以说明处理决定,让pinguapps-pr-agent可以跟进;绝不要要求 Copilot 重新审查。approved:所有针对最新精确 HEAD 的 PR Agent 信号均成功。重新获取检查结果、PR 级反馈和讨论串;只有在完整的完成定义仍然满足时才结束。incomplete:审查结束,但未获批准,也没有给出发现结论。检查检查输出和重试状态;在现有限制范围内等待已安排的重试,或报告服务阻塞。不要将此情况转化为代码反馈或批准,也不要通过评论触发审查。timeout:检查必需的自动审查者是否在没有进行中的审查时,已沉默整整 25 分钟。对于人员,从创建 PR 或 Agent 最近一次回复起,必须已过一个工作日,包括跨续接运行的情况。只有当其回复对于完成 PR 至关重要时,才考虑操作规则中对符合条件的审查者规定的单次提醒例外;PR Agent 和 Copilot 不适用此例外。否则,将等待报告为阻塞,并且不要声称已具备就绪条件。head_changed:获取并检查新状态。如果其他参与者的推送使继续修改变得不安全,则停止。pr_closed:停止并报告 PR 状态。
-
对于新反馈,重复执行符合条件的修复 → 验证 → 提交 → 排队或门控串行回复 → 已完成的审查和刷新的审计 → 基线 → 门控推送 → 等待。只有在门控条件满足且提交延迟解除后,才发送仍需发送的排队回复;只有回复审计通过后才结束。
如果无需推送,请使用步骤 5 中相同的等待路径选择。如果门控条件解除且剩余的完成定义均满足,则针对当前精确 HEAD 的成功 PR Agent 检查或旧版状态已足够。若没有 PR Agent,则直接进行最终审计。否则,记录当前状态,只读等待其自动审查,并应用相同的超时规则,不要发布默认触发评论。
$expectedHeadSha = (git rev-parse HEAD).Trim()
$reviewRound++
$reviewState = Join-Path $runStateDirectory ("review-round-{0}.json" -f $reviewRound)
pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
-CaptureBaseline `
-StatePath $reviewState `
-PrNumber $prNumber `
-Repository $baseRepository `
-Hostname $githubHostname
如果环境中没有 PR 监视器,对于任一种信号类型,都运行以下等待命令:
pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
-Wait `
-StatePath $reviewState `
-ExpectedHeadSha $expectedHeadSha `
-ReviewRequestedAt ([DateTimeOffset]::MinValue) `
-TimeoutMinutes 25 `
-PollSeconds 20
监视器会验证预期的 PR 头部,并对当前检查运行和旧版状态进行分类,然后报告批准、发现或未完成的工作。审查完成前,新反馈可能会唤醒监视器;自动审查门控机制仍适用于每一次发布。API 错误会终止辅助程序,而不会假装集成不存在。
第三轮推送审查后,将剩余反馈归类为新回归、重复异议或此前遗漏的问题。检查当前处理方法或对要求的理解是否导致反复变动。只有在有具体且有证据支持的剩余工作计划时才继续;否则,报告阻塞,不要声称已获批准。此检查点不会要求再次进行完整审查,也不会重置计数器。遵守五轮推送审查或总计两小时的硬性上限。若结果已无问题、发生超时、PR 已关闭、HEAD 意外变动或出现真正的阻塞,则应提前停止。
最终审核与回复
如果审核修复改变了行为、决策、验证或恢复方式,请更新已保存 PR 的审核上下文。保留模板和无关的作者内容;发布此更新前,遵循相同的自动化审核门禁。记录当前 HEAD 的验证情况和重要缺口,不要重复手动测试交接内容。偶尔评估工作流时,应分别记录实际的人为干预和大致的主动投入分钟数,不要与 PR Agent 的模型成本混为一谈;等待经过的时间不属于人工投入。
重新获取信息,不要依赖缓存状态:
- PR HEAD、可合并性和基准分支;
- 最新基准提交,以及新执行的本地
git merge-tree --write-tree --messages HEAD <base-commit>冲突探测; - 所有检查;
- 使用
gh pr checks --required单独查询必需检查; - 针对确切 HEAD 的
PR Agent检查运行状态/结论,以及任何旧版提交状态(当 PR Agent 正在此仓库运行时); - PR 级别的审核和评论;
- 所有审核线程及回复提交状态;
- 本地/远程分支状态和工作树。
简要报告:
- PR 编号和 URL;
- 冲突和 CI 结果及对应提交;
- 线程数量:已处理、等待审核者回复和存在分歧;
- 修复、针对性验证和提交 SHA;
- 推送结果和审核轮次;
- 当前 HEAD 的最终
PR Agent结果:检查已完成且成功,或旧版状态为success(若拉取请求上两种信号都不存在,则为not running); - 待处理的审核回复:
0; - 审核线程解决状态变更:
0,并附基线审计结果; - 任何阻塞项或仍在等待的必需检查。