关于 gh-fix
gh-fix 是用于自主处理 GitHub Issue 的 Agent 技能,涵盖验证、实现、拉取请求、CI 和合并。它在独立克隆中工作,可恢复现有拉取请求,并在缺少合并授权时暂缓合并。
主要功能
- 01验证并解读 GitHub Issue
- 02恢复符合条件的未关闭拉取请求
- 03将多项任务拆分为子 Issue
- 04在独立克隆中实现修复
- 05跟进 CI 并合并或暂缓拉取请求
适用场景
- 01自动完成获准合并的 Issue 修复
- 02在中断后继续处理已有工作
- 03将可独立完成的任务拆成子 Issue
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ lsegal/ glorp --skill gh-fix安装后在 Claude Code 中输入/gh-fix确认已加载。
附带文件agents/openai.yaml
详细介绍
通过合并修复 GitHub 问题
将 /gh-fix OWNER/REPO#ISSUENUMBER 视为授权你实现、发布、持续修复并合并该问题的修复方案。调用时可以附加 identity:/glorp:<ID>,以标识派发该任务的 Glorp 实例。自主工作,直至 PR 合并、问题不再授权合并,或出现需要用户介入的真正外部阻碍。绝不要更改用户现有的检出;所有更改都必须在单独的克隆中进行。
验证请求
- 必须提供且仅提供一个正整数 GitHub issue 编号;可选地在前面加上
#。此工作流在任何提及该 issue 的地方(分支、提交、PR 正文、评论和后续跟进)都必须使用 GitHub 风格的#NNN引用。绝不能用环境中其他跟踪系统的标识符(例如ABCD-123)代替 issue 编号,即使该标识符出现在 issue、提交或其他上下文中也不行。还可选地接受一个末尾参数identity:/glorp:<ID>,并在处理评论时保留该身份。如果存在身份参数,还可在其后接受可选的末尾指示and do not merge,将其作为本次运行的禁止合并指示。如果存在身份参数以及禁止合并指示,还可在它们之后接受进一步的可选末尾指示and no changelog,将其作为本次运行的不添加变更日志指示:跳过“修复实现”中的第 4 步,且不添加变更日志条目,无论 issue 或仓库规范原本有何要求。 - 确定 GitHub 仓库。优先使用命令本身直接给出的
OWNER/REPO(/gh-fix OWNER/REPO#N,glorp 始终会以此形式分派)——这是权威形式,无需进一步检测。如果命令是以裸形式/gh-fix N调用,则查找调用中的其他位置是否有Repository: OWNER/REPO行,或用户是否以其他方式明确说明了OWNER/REPO,并使用该信息。只要以上任一形式提供了仓库,就绝不能运行git remote -v、gh repo view或任何其他仓库检测命令。仅当调用中的任何位置都未提供仓库时,才回退到当前检出分支的 GitHub 远程仓库以推断OWNER/REPO;只有这样仍无法确定仓库时,才询问用户。 - 必须具备
git、gh,且gh会话已通过身份验证并拥有仓库和工作流访问权限。如果 issue 存在,但无法满足此项或任何其他环境要求,则停止,不得创建拉取请求或以其他方式修改仓库——但必须按照下方规则在该 issue 上发布一条评论,说明未实现修复的原因。 - 阅读 issue 标题、正文、标签、评论、状态和关联上下文。提供了身份时,还要按时间顺序以线程对话的形式阅读所有 issue 评论和关联的拉取请求对话:issue 正文构成初始请求,之后的评论可以修改、澄清或覆盖该上下文。包含对所提供身份的精确提及
@/glorp:<ID>的评论是直接发给本 Agent 的指示,不得忽略;提及其他身份的内容不是本次运行的指示。如果 issue 不存在,则停止;无需发布评论。如果 issue 不可执行,或已关闭,则停止,不得创建拉取请求或以其他方式修改仓库——但必须按照下方规则在该 issue 上发布一条评论,说明未实现修复的原因。 - 在编写任何代码之前,确定该 issue 是否不予合并授权,并记录此决定。以下任一情况均视为禁止合并指示:标签表明暂缓合并(
donotmerge、do-not-merge、do not merge、no-merge、hold、needs-review),匹配时不区分大小写,并忽略空格、连字符和下划线;或 issue 正文或评论中的任何措辞——包括发给本次运行的@/glorp:<ID>指示——要求不要合并该修复、保持开启状态,或在合并前停止。按时间顺序阅读对话:较新的评论可以提出或解除暂缓指示,因此以最近的表述为准。存在该指示时,记录其确切标签,或引用其来源措辞,并在整个运行过程中遵循:直至将拉取请求标记为就绪(含该步骤在内)的所有操作仍须照常进行,并以“禁止合并时暂缓拉取请求”代替合并。 - 阅读仓库说明,包括适用的
AGENTS.md、贡献指南、分支和 PR 规则、CI 配置以及变更日志规范。 放弃前务必评论并跟踪后续工作。 无论何种原因,只要此技能在为该 issue 创建 pull request 之前停止运行——例如 issue 无效或无法执行、缺少环境要求、存在无法消除的歧义、工具反复失败,或在此工作流的任何更早阶段遇到其他阻碍——结束运行前都必须在该 issue 上发布且仅发布一条评论,说明尝试过什么以及为何未实施修复,除非用户明确要求改为执行后续工作。在“将多部分 issue 拆分为子 issue”下创建的跟踪 issue 不属于阻碍,且不受此规则约束:首次拆分时评论一次;之后每次运行若没有新的内容可说,则不再评论。即使从未创建草稿 pull request,也必须遵守此规则。pull request 创建后,之后遇到的阻碍应根据“推动 CI 完成”在 pull request 上报告,而不是在 issue 上发表新评论。在上述任一情况下停止前,都要创建或关联所有可执行的后续 issue,并按“创建后续 issue”中的要求分派。这能让原因和下一步具体工作都显示在 GitHub 上,而不只是写在发给调用者的最终报告中。
恢复现有工作(可重入模式)
在遭到中断(Ctrl+C、会话崩溃、之后启动新会话)或由调用者从先前运行中移交后,/gh-fix N 必须能够安全地再次运行。创建任何新内容前:
- 确定
N指向的是 issue 还是已打开的 pull request。如果N是 pull request,则从其正文中的Closes #<ISSUENUMBER>行找到它关闭的 issue,将其视为源 issue,并推动该 PR 本身直至完成,而不是另开一个。 - 如果
N是 issue,则查找关闭该 issue 的 pull request,并将分支命名约定fix/issue-N-*和 PR 正文中的Closes #N作为匹配信号。绝不要复用 CLOSED pull request,无论它是否已合并——只有 OPEN pull request 才可以恢复,且不论匹配的是哪个信号。如果存在匹配的 open pull request,则恢复该 PR 和分支,而不是创建新草稿;否则,就按未找到处理,即使有已关闭的 PR 匹配也一样。 - issue 或 PR 的归属(判断是否可以安全接手,还是仍由其他 Agent 认领)由调用者在此技能启动前确定,而非由此技能确定。不要阅读或发布 PR 或 issue 评论来协商归属。
- 恢复工作时,克隆现有分支(而非默认分支),以保留其提交历史、检查点和任何未完成的实现。阅读 PR 正文,以了解已完成和已测试的内容,以及剩余工作。
- 克隆后,像从新建分支开始一样,继续执行此工作流的其余部分:持续创建检查点,直到确实准备就绪前都保持 PR 为草稿,并推动 CI 直至完成。如果先前的工作仍然有效,不要从头重新开始实现。
将包含多个部分的问题拆分为子问题
如果一个问题明确描述了多个可分离的工作内容,它就是一个跟踪问题,而不是一个工作单元。请在克隆任何内容之前做出一次判断,并且绝不要重复拆分同一个问题。
- 先阅读问题已有的子问题。 如果问题已经有一个或多个子问题,就说明它已被拆分。绝不要为它创建更多子问题,也绝不要为它创建拉取请求:对于此类问题,
/gh-fix唯一要做的事就是判断它是否可以关闭。阅读每个子问题的状态。如果所有子问题都已关闭,且父问题自身正文中没有尚未实现的内容,就通过评论列出已完成的子问题,然后关闭父问题。如果仍有任何子问题处于打开状态,则在结束运行时报告哪些子问题仍未关闭,且不要发布评论——如果运行没有新内容可说,就应保持问题不变,以免重复调度时累积相同的评论。无论哪种情况,都应在此处结束运行,不要克隆、创建分支或拉取请求。 - 绝不要拆分已有进行中工作的 问题。 如果“恢复现有工作”匹配到该问题的一个打开的拉取请求,就恢复该拉取请求,并完全跳过本节。
- 只有当问题本身明确说明了多个不同且可分离的任务时,才拆分。 务必非常谨慎。一个问题中的任务通常在开始时无法确定是否可分离,而错误拆分的代价高于不拆分。只有当每个部分都说明了自己的交付成果,并且无需其他部分就可以独立实现、测试和合并时,才进行拆分:“实现修复并更新文档网站”是两个任务。以下情况不要拆分:多个部分只是用不同说法描述同一项更改;某个部分无法在没有另一部分的情况下验证甚至实现;或者拆分依据是你自己的推断,而非问题本身的措辞:“实现此功能并修复相关的查找错误”通常是一个任务,因为只有实现该功能后才会触及此错误。如有疑问,就不要拆分——将该问题作为一项修复来实现,并按原样继续此工作流的其余部分。按照“创建后续问题”中的定义,仅需手动处理的部分永远不算可分离任务:绝不要为其创建子问题,也不要将它计入拆分。
- 如果确实需要拆分,请在同一仓库中为每个部分分别创建一个问题,并使用 GitHub 的子问题 API,通过父问题和新问题的 GitHub 问题 ID 将其关联到原始问题。不要只创建 Markdown 清单或简单提及。为每个子问题设置明确聚焦的标题,并提供足够的背景和验收标准,使其无需重新阅读父问题也能执行。混合手动检查与自动化工作的部分,应仅针对其中的自动化工作创建子问题。
- 按照“创建后续问题”的规则为每个新子问题准确分配:根据子问题本身选择标签,只保留仍然适用的标签,继承父问题的里程碑和受指派人,复制父问题的项目归属并将状态设为
Todo,其他方面则遵循.glorp.json中的分配规则。这样下一个 Agent 时段就能接手该子问题。创建、关联或分配子问题失败时,应将其视为需要采取行动的错误并重试。 - 创建子问题后,父问题就是一个跟踪或元问题。关闭它不需要拉取请求、代码或变更日志条目,并且不得占用 Agent 时段。只发布一条评论,列出已创建的子问题,并说明待所有子问题完成后将关闭父问题;对于仅需手动处理的部分,也要在同一条评论中列入
Manual verification清单,然后结束运行,不要克隆、创建分支或打开拉取请求,以便下一个 Agent 时段可以接手某个子问题。
处理开放的阻塞问题
如果仓库支持 GitHub 堆叠拉取请求(gh-stack),被另一个未关闭议题阻塞的议题无需等待该议题。请在验证期间、克隆之前确定这一点,并记录下来,供本次运行后续步骤使用。恢复未关闭的拉取请求时,请跳过本节;其基础分支已记录该请求是否为堆叠式。
- 收集此 issue 的未解决阻塞项:
gh api repos/<OWNER>/<REPO>/issues/<ISSUENUMBER>/dependencies/blocked_by中的每个未解决 issue,以及 issue 正文中Depends on #<N>行所提及的每个未解决 issue。 - 使用
gh api repos/<OWNER>/<REPO>/stacks?per_page=1检测仓库是否启用了堆叠式拉取请求。请求成功表示已启用;404 Not Found表示未启用。 - 仅当已启用堆叠式拉取请求、恰好有一个未解决阻塞项,且该阻塞项有一个会关闭它的未解决拉取请求时,才进行堆叠。记录该阻塞项拉取请求的编号和 head 分支,作为堆叠基准。其他情况下都不要堆叠:按照本工作流其余部分的说明,从默认分支构建。
- 如果扩展尚未安装,则使用
gh extension install github/gh-stack安装。如果无法安装,仍按下文说明堆叠分支和拉取请求,但跳过gh stack命令,并在拉取请求正文中说明无法关联堆叠。 - 从阻塞项的 head 分支创建新分支,而不是从默认分支创建;并将草稿拉取请求的目标分支设为该分支,而不是默认分支。草稿拉取请求的其他设置保持不变。
- 使用
gh stack link在 GitHub 上将拉取请求关联为堆叠。如果阻塞项的拉取请求已属于某个堆叠(gh api repos/<OWNER>/<REPO>/stacks?pull_request=<BLOCKERPR>),则按从底到顶的顺序传入该堆叠中的拉取请求,后接此拉取请求;否则传入<BLOCKERPR> <PRNUMBER>。在拉取请求正文中提及阻塞项的拉取请求。 - 阻塞项的分支属于另一次运行。绝不要提交到该分支、对其进行变基、推送或合并,也绝不要使用
gh stack merge合并整个堆叠。同样也不能使用gh stack sync和gh stack push,因为它们会推送堆叠中的每个分支。 - 每次推送前以及等待 CI 期间,都要检查上游是否有变更:获取并比较阻塞项的 head 分支与此分支的基准。如果阻塞项已有更新或已合并,则从此分支运行
gh stack rebase --upstack更新此分支(阻塞项已合并时,它会自动切换为--onto);解决任何冲突,重新运行受影响的检查,并仅推送此分支:git push --force-with-lease=<BRANCH>:<PREVIOUSREMOTESHA> origin <BRANCH>。在gh stack变基后,通过租约保护推送此运行自己的分支,是唯一允许强制推送的例外。没有扩展时,则将阻塞项的分支合并到此分支,并正常推送。 - 阻塞项的拉取请求合并后,确认此拉取请求的目标分支现已是默认分支;如果 GitHub 没有自动调整,则使用
gh pr edit <PRNUMBER> --base <DEFAULTBRANCH>修改目标分支,然后照常在新 head 上运行 CI。如果阻塞项的拉取请求在未合并的情况下关闭,则使用gh stack unstack取消堆叠,按相同方式将此分支变基到默认分支,修改拉取请求的目标分支,并在拉取请求中报告已关闭的阻塞项。 - 如果堆叠式拉取请求的目标分支不是默认分支,绝不要合并它。一旦拉取请求已标记为就绪且 CI 通过,而阻塞项的拉取请求仍处于打开状态,就结束本次运行,不要等待阻塞项合并:在拉取请求上发布一条评论,说明它已就绪并暂时停放在阻塞项的拉取请求上;将停放的拉取请求作为结果报告,而不是报告为失败或阻塞项。不要创建后续 issue,也不要关闭此 issue。glorp 派发运行时,glorp 会将其停放、释放其 Agent 槽位,并在阻塞项不再处于打开状态时再次派发该 issue。后续运行会继续处理此拉取请求,遵循第 9 步,运行 CI,并继续执行“合并并验证”。如果 CI 通过时阻塞项已经合并,则在本次运行中遵循第 9 步,而不是结束运行。
创建隔离克隆和分支
- 确定规范的
OWNER/REPO、克隆 URL 和默认分支。 - 在切换目录之前,记录调用目录中是否包含
.glorp.json。保留此信息,以便后续路由使用,因为状态文件通常会被忽略,不会出现在隔离克隆中。 - 在当前检出目录之外创建一个名称唯一的同级目录或临时目录,例如
<repo>-gh-fix-<N>。绝不要重复使用或修改用户当前的工作树,也不要用 worktree 代替独立克隆。 - 正常克隆仓库。如果按上述章节恢复工作,则克隆并检出已有分支,并验证其 HEAD 与远程一致;否则,验证克隆的默认分支 HEAD 与远程一致。
- 验证克隆后立即输出
GLORP_CHECKOUT_DIRECTORY=<absolute clone path>,作为一行原样的纯文本进度信息,不添加 Markdown 格式。这使调用方能够显示并保存实际的隔离检出路径。如果恢复工作时重新生成了缺失的检出目录,则再次输出此行。 - 如果不是从已有分支恢复工作,则从当前远程默认分支创建新分支;如果“基于未解决的阻塞问题堆叠”决定进行堆叠,则从阻塞项的头分支创建新分支。优先使用
fix/issue-<N>-<short-slug>,除非仓库说明要求采用其他命名方案。 - 创建本工作流使用的每个克隆目录后,立即注册清理操作。退出前删除这些目录,包括正常完成、发生错误或出现 panic 时。不要删除用户已有的检出目录或无关目录。
清理必须无条件执行:每创建一个克隆目录,就立即使用延迟执行/finally 风格的清理保护机制;清理出错时,应明确显示错误,同时保留原始失败信息(如有)。
打开草稿拉取请求
创建分支后立即推送并打开草稿拉取请求,以便在整个开发过程中展示进度。如果按上述“恢复已有工作”章节恢复已有草稿 PR,则完全跳过本节——该 PR 已经打开。
- 创建一个空的初始提交,例如
Start work on issue #<ISSUENUMBER> [skip ci],然后推送新分支并设置上游跟踪。[skip ci]标记可避免 CI 在与默认分支内容相同的树上运行;只有此提交和“实现修复”中描述的检查点提交可以带有此标记。绝不要强制推送。 - 针对当前默认分支,或在堆叠时针对阻塞项的头分支,打开一个简洁标题描述预期修复内容的草稿 PR。
- 编写真实的 Markdown 正文,总结问题和计划开展的工作。将完整的多行 Markdown 写入文件或通过标准输入传递,并使用
gh pr create --body-file(或等效的gh pr edit --body-file)提交;绝不要在--body参数中使用字面量\n转义序列表示段落换行。单独占一行写入Closes #<ISSUENUMBER>,以便草稿 PR 关联原始问题,并在合并时将其关闭;然后读回已创建的 PR 正文,确认其中包含实际换行,而不是字面量\n文本。 - 正文末尾添加
**Agents:**页脚行,注明当前负责处理该问题的 Agent CLI 和模型(例如**Agents:** claude-code (claude-sonnet-5)),并根据自身运行时上下文确定。这是下文所述的贡献 Agent 页脚。 - 记录 PR 编号和 URL,然后确认头分支和基础分支正确。
维护贡献 Agent 页脚
每次编写或替换 PR 正文(创建草稿、更新检查点以及标记为可审查)时,都要保留 **Agents:** 页脚,而不是覆盖它:
- 先读取当前 PR 正文,并找到其中的
**Agents:**行(如果有)。 - 根据运行时上下文确定你当前使用的 Agent CLI 和模型。
- 如果缺少页脚,只添加你自己的条目。如果页脚已列出一个或多个 Agent/模型条目,则保留所有不重复的现有条目,并且仅在尚未包含你自己的条目时追加该条目;条目以逗号分隔,并按出现顺序排列(例如
**Agents:** codex (gpt-5), claude-code (claude-sonnet-5))。 - 这样,页脚就会累积所有处理过该问题的 Agent 和模型;当其他 Agent 或模型中途接手草稿时,这一点很重要。
实现修复
- 在可行的情况下,复现或以其他方式验证所报告的行为。
- 检查相关代码和历史记录,然后根据仓库惯例实现最小且完整的修复。
- 如果仓库有适用的测试框架,添加或更新有针对性的测试,确保没有此修复时测试会失败。
- 不区分大小写地查找现有变更日志,包括项目特定的路径和名称。在当前未发布部分下添加简洁、面向用户的说明,并遵循其格式。如果项目没有变更日志,不要新建;完全跳过此步骤,并在 PR 正文中说明项目没有变更日志,因此未添加条目。仅为用户可见的变更添加变更日志条目;不要添加仅涉及内部变更的说明。若修复的是另一条尚未发布的变更日志条目,不要添加条目。如果生效了禁止添加变更日志的指令,则完全跳过此步骤,不添加任何变更日志条目:此类指令包括验证给出的
and no changelog分派建议,或问题正文及其评论中的任何措辞(包括发给本次运行的@/glorp:<ID>指令),只要要求此次修复跳过、不修改或忽略变更日志。请在 PR 正文中说明有意跳过变更日志的原因。 - 开发期间,只要工作树有变更,每隔五分钟至少创建并推送一次检查点提交。提交说明可使用
Checkpoint issue #<ISSUENUMBER> progress [skip ci]这样的格式;保留[skip ci]标记,以免未完成的工作触发 CI 运行;不要等实现或测试完成后才向草稿 PR 发布下一个检查点。如果没有变更,则跳过空提交,并在下一个开发间隔后再次检查。绝不包含机密、生成的构建产物或无关变更。 - 先运行有针对性的测试,再运行仓库要求的更广泛检查。修复由此次变更导致的失败。不要将已知有问题的修复标记为可供审查。
- 检查状态和完整差异。只包含该问题、其测试和变更日志说明所需的文件。
捕获 UI 屏幕截图和屏幕录制
实现完成后,且仅在完成后,判断是否有任何更改的文件会影响用户界面。如果有:
- 捕获屏幕截图,展示具有代表性的最终状态中的已完成 UI 更改。如果更改涉及动画、交互或状态转换,则捕获屏幕录制来演示其行为,以替代或补充屏幕截图。对于动画,规划一系列操作,完整体验所有功能,包括错误处理等次要用例。
- 对于基于浏览器的界面,运行 UI 并使用可用的浏览器工具(例如 CDP 或浏览器自动化)捕获屏幕截图或屏幕录制。
- 对于基于终端的界面,如果没有视觉效果、动画或状态变化,则将输出复制为文本。
- 对于所有其他非浏览器界面,使用可用的本地应用或平台捕获工具。如果未安装合适的捕获工具,请安装 Loom 并用它创建屏幕录制。
- 捕获原生窗口时(任何浏览器之外的捕获,例如桌面应用或平台捕获工具),将屏幕截图或录制裁剪至相关窗口的边界。除非应用在捕获时确实处于全屏状态,否则绝不要保留全屏或全显示分辨率的捕获。
- 上传每张屏幕截图或每段屏幕录制,然后将返回的 URL 直接以 Markdown 格式嵌入拉取请求正文中(例如,
)。不要将 UI 屏幕截图或屏幕录制添加到仓库资源中,也不要将它们提交到分支。
GitHub 没有用于将文件附加到议题、拉取请求或评论的公开文档 API,但 Web UI 用于拖放的同一端点支持通过 bearer token 以非交互方式上传。直接使用该端点上传:
REPO_ID=$(gh api repos/<OWNER>/<REPO> --jq .id)
curl -sf -X POST "https://uploads.github.com/user-attachments/assets?name=<FILENAME>&content_type=<MIME_TYPE>&repository_id=$REPO_ID" \
-H "Authorization: Bearer $(gh auth token)" \
-H "Accept: application/json" \
--data-binary @<LOCAL_FILE_PATH>
响应是包含 url 字段的 JSON(https://github.com/user-attachments/assets/<uuid>);将该 URL 嵌入拉取请求正文中。此端点未公开文档且非官方,因此如果出现失败或意外响应,请将其视为以下捕获错误之一,而不要无限重试。
只有在已完成的差异完全不影响任何 UI 代码时,才跳过本节。 如果尝试捕获或上传结果时遇到 2 个或更多错误,则跳过并在 PR 中说明。
提交并推送
本地检查通过后,创建最终实现提交,绝不要标记为 [skip ci],并使用简洁的祈使句作为主题行,将关闭关键词单独放在正文一行。如果最新检查点已包含所有最终更改,则创建一个空提交,以确保已检查的实现有明确的收尾提交:
Fix <concise issue summary>
Closes #<ISSUENUMBER>
例如,git commit -m "Fix parser handling of empty input" -m "Closes #123" 会在单独的正文行中创建所需内容。使用准确的目标议题编号,并按示例将 Closes 首字母大写。
如果提交消息的任何位置(包括主题行)包含跳过标记,GitHub 就会跳过该提交的 CI;而压缩合并会将 PR 标题和正文复制到默认分支上的提交中。绝不要在最终实现提交、CI 修复提交、PR 标题或 PR 正文中写入 GitHub 可识别的字面跳过标记([skip ci]、[ci skip]、[no ci]、[skip actions]、[actions skip] 或 skip-checks: true 尾注),即使更改与这些标记有关也不例外。请改用文字描述该标记,例如“跳过 CI 标记”。
最终推送前,确认分支包含预期代码、测试和变更日志说明;最终实现提交包含独立一行 Closes #<ISSUENUMBER>,且不含跳过标记;工作树干净;并且本地检查已通过。正常推送。绝不要强制推送。
将拉取请求标记为可审查
- 更新草稿 PR 的标题和正文,说明已完成的修复,包括根本原因、变更内容、对用户的影响、变更日志条目、测试,以及任何必需的 UI 截图或屏幕录制。将
Closes #<ISSUENUMBER>保留在单独一行,并按照上述说明更新**Agents:**页脚,不要删除或覆盖它。标题和正文中不得包含「Commit and push」下列出的任何字面跳过标记。 - 确认头部分支、基准分支和变更文件范围正确。堆叠式拉取请求的变更文件只能包含此问题的变更,并且这些变更应基于阻塞问题的分支。
- 只有在实现、本地检查、最终推送以及任何必需的 UI 截图或屏幕录制均完成后,才将草稿 PR 标记为可供审查。
推进 CI 直至完成
继续操作,直到所有必需的检查都成功完成:
- 在判定成功前,确认预期的检查套件已为 PR 注册。创建 PR 后,检查列表暂时为空并不代表构建通过;请等待已配置或必需的检查出现,或者确认该代码库确实没有适用的 CI。
- 持续监控 PR 检查,不要只查看一次状态快照。优先使用
gh pr checks <PR> --watch --interval 10;使用产品提供的循环等待机制,让用户在耗时较长的构建期间定期收到进度更新。当以非交互方式运行(例如 glorp 分派此工作流时),请在前台阻塞等待监控完成,切勿在后台任务、监控器或计划唤醒仍在等待时结束本轮:本轮结束时进程会退出,从而中断等待。 - GitHub Actions 检查失败时,使用
gh pr checks、gh run view和作业日志 API(如有必要)检查确切的运行记录和失败作业日志。在更改代码前,记录检查名称、运行 URL、失败的命令以及有用的错误上下文。 - 对于外部检查,请打开检查 URL,并使用服务提供方提供的日志或工具。如果无法访问日志,请报告访问受阻的情况,不要猜测。
- 对每项失败进行分类:
- 如果失败由 PR 引起,请在实际可行时于本地复现,实施最小且正确的修复,运行相关本地检查,不使用「Commit and push」下列出的任何跳过标记提交修复,并正常推送。
- 如果存在合并冲突,请从最新的默认分支更新分支,不要强制推送,解决冲突,重新运行受影响的检查,然后提交并推送。对于堆叠式拉取请求,请按照「Stack on an open blocking issue」中的说明从阻塞问题的分支更新。
- 如果明显是临时基础设施故障或不稳定测试导致失败,请重跑失败的作业一次;若问题再次出现,则进行调查。
- 如果明显是与 PR 无关且持续存在的失败,请收集诊断详情;只有在安全的情况下,才尝试修复范围内的问题。否则,请在确实受外部因素阻塞时停止。
- 每次推送或重跑后,都要监控新头部 SHA 的检查状态,直至检查完成。忽略早期 SHA 的过时结果。
- 对仍可处理的 CI 失败,重复诊断、修复、本地验证、提交、推送和监控步骤,直至全部解决。不要仅为获得通过结果而削弱断言、跳过测试、降低覆盖率或更改 CI。
合并被暂缓时保留拉取请求
当验证记录了禁止合并的指令时,本次运行会以一个已准备就绪但尚未合并的拉取请求结束。在此之前,一切照常进行:修复、测试、更新日志说明、最终推送、将拉取请求标记为可供审查,以及等待 CI 完成。只有合并和后续问题不会进行。
- 不要合并拉取请求,不要删除分支,也不要关闭发起的议题。绝不能因为 CI 结果为绿色或修复看起来已完成,就绕过暂缓指令进行合并。
- 在本次运行自身输出所示的位置记录该决定:注明暂缓合并的标签,或引用暂缓合并的原文,并说明拉取请求是有意保持开放、留待人工合并的。
- 在拉取请求上恰好发布一条评论,报告完成状态。说明工单状态为 Ready,概述修复、测试和 CI 结果,并说明合并已暂缓,同时注明相关标签或引用暂缓合并的指令。
- 对于暂缓合并的运行,不要创建、复用或转交任何后续问题——“创建后续问题”不适用,因为尚未合并的工作在审查过程中仍可能发生变化。相反,应在同一条拉取请求评论中以
Follow-ups (not filed)为标题,列出所有原本会成为后续问题的事项;如果有等同的现有开放议题,应链接该议题,而不要新建任何内容,以便负责合并的人创建这些问题。按照“创建后续问题”中的说明对这些事项分类:纯人工处理的事项不要放入Follow-ups (not filed),而应在同一条评论中用单独的Manual verification标题列出,并附上设置步骤和精确的检查内容。 - 发布该评论后结束本次运行,并将暂缓合并报告为最终结果,而不是失败或阻塞。
合并并验证
如果议题禁止合并授权,请完全跳过本节;改为遵循“合并被暂缓时保留拉取请求”。
- 合并前,获取最新的 PR 状态,并确认发起的议题和 PR 均仍处于开放状态。如果其中任何一个已关闭,则不要合并:议题已关闭意味着停止工作;未合并便关闭的 PR 表示本次尝试已被拒绝,不能重新打开或复用。然后确认其基准分支为默认分支(堆叠式拉取请求需等待阻塞它的 PR 先合并),至少有一次 CI 运行实际针对头部 SHA 注册,且该 SHA 上的每项必需检查均成功;确认 PR 可合并、没有必需审查或未解决的讨论阻碍合并、必需的 UI 截图或屏幕录制已提供,并且头部 SHA 就是通过 CI 的那个提交。如果头部 SHA 的检查列表始终为空,则不算通过:如果仓库配置了 CI,请检查头部提交消息以及 PR 标题和正文中是否有跳过标记,移除该标记并推送一个新提交,以便 CI 在合并前运行。
- 使用仓库要求或惯用的合并方式。当仓库允许多种方式时,优先级如下:压缩合并,然后合并提交,最后变基。在压缩合并时,使用 PR 的标题和正文作为压缩提交消息,不要覆盖它——正文已包含独立一行的
Closes #<ISSUENUMBER>。如果只允许合并提交或只允许变基,则改用该方式,并无论采用哪种方式都保留独立的关闭引用。 - 如果仓库政策允许,在成功合并后删除远程议题分支。
- 验证 PR 已合并、合并提交可从远程默认分支访问,并且 GitHub 已关闭议题
#<ISSUENUMBER>。允许 GitHub 有短暂的处理延迟,但未经检查不得声称议题已关闭。
创建后续问题
检查两个终止节点是否存在未解决的后续工作:在停止失败或停滞的运行前立即检查,无论是否已有拉取请求;以及拉取请求合并后检查。阅读源议题、任何拉取请求的正文和评论,以及当前对话,找出所有明确提及的阻塞项、待办事项或已知问题。运行即将停止时,不要等到合并后再检查。本节不适用于按“合并被阻止时保留拉取请求”结束的运行:保留的拉取请求不会创建任何后续议题,而是在其完成状态评论中报告相同事项。
创建议题前,先对每项进行分类。 如果某项只能由人工检查是否符合验收条件,则该项属于仅限人工处理:运行第三方 GUI 应用或主机、使用实体或外围硬件、使用真实设备或账户,或做出仓库无法测试的主观或视觉判断。绝不要将仅限人工处理的事项创建为议题:glorp 会将其分派给无法完成工作的 Agent 插槽,导致积压列表中充满没有 Agent 能够关闭的议题。
- 将仅限人工处理的事项作为一条评论发布,并附上
Manual verification检查清单。有拉取请求时,发布在拉取请求上;运行停止且没有拉取请求时,发布在源议题上;运行在拉取请求创建前就停止时,将检查清单并入该运行已发布的单条说明性评论中,不要另发第二条评论。逐项列出设置步骤和确切的检查内容,并说明 CI 无法覆盖这些检查。若先前的运行已发布相同且未更改的检查清单,则不要重复发布。 - 如果某项同时包含人工检查和可自动化工作(例如脚本、测试框架、文档或打包),只将可自动化部分创建为后续议题,并将人工检查留在评论中。
- 以下步骤仅适用于不属于仅限人工处理的事项,或此类事项中不属于仅限人工处理的部分。
- 将每个不同且可执行的事项分别在同一仓库中创建为一个 issue。不要为已完成的工作、模糊的观察或已有等效未关闭 issue 的事项创建 issue;应链接到现有 issue。
- 为每个新 issue 设置明确聚焦的标题,并提供足够的背景信息和验收标准,使其无需重新阅读拉取请求也能采取行动。
- 将每个新 issue 与其源 issue 关联;如果存在发现阻塞事项或剩余工作的拉取请求,也要与该拉取请求关联。支持时,优先使用仓库或项目关系元数据。否则,在 issue 正文中加入
Addresses #<ISSUENUMBER>;存在拉取请求时,再加上and #<PRNUMBER>。 - 如果源 issue 存在尚未解决的 issue 依赖项,且后续 issue 要处理该依赖项,则将后续 issue 设为相关阻塞 issue 的子 issue。读取依赖关系和新 issue 的 GitHub issue ID,然后使用 GitHub 的子 issue API;不要只在 Markdown 中提及阻塞项。如果存在多个阻塞项,只将后续 issue 关联到它所处理的特定阻塞项;如果关系不明确,应请求指示,不要猜测。对复用的等效未关闭 issue 也应用相同的关系,除非它已经是该阻塞 issue 的子 issue。
- 每个新后续 issue 的标签都应根据后续 issue 本身确定,而不是照搬源 issue 的标签集合。先读取仓库可用的标签(
gh label list),再为其添加与后续工作类型相对应的仓库标签:缺陷使用仓库中表示 bug 的标签(bug、bugreport、defect),新工作使用表示功能的标签(enhancement、feature、Feature)。标签名称必须与仓库实际定义的名称匹配,大小写不敏感,绝不可编造仓库未定义的标签;如果仓库没有对应标签,则不添加类型标签,也不要用近似标签替代。 - 只有源 issue 的标签对后续 issue 仍然准确时才予以继承。描述后续 issue 与源 issue 共有属性的标签——例如领域、组件、发布列车、优先级、
milestone123式分组——应予以继承。描述源 issue 本身、可能与后续 issue 矛盾的标签则不应继承:包括类型标签(例如,后续 issue 是功能请求时,源 issue 上的bug标签)以及分流或工作流状态标签(needs-triage、duplicate、wontfix、good first issue)。继承的标签绝不能覆盖上述为后续 issue 选择的类型标签;两者不一致时,应保留后续 issue 自身的类型标签,并舍弃源 issue 的类型标签。 - 将源 issue 的里程碑和指派人原样继承到每个新后续 issue。创建后续 issue 时,与上述决定的标签一并设置(
gh issue create --label ... --milestone ... --assignee ...);或者创建后立即通过gh issue edit添加。仅跳过仓库无法接受的值——不存在的标签、已关闭或缺失的里程碑、无法指派的用户——并说明跳过了哪个值,不要因此省略整个步骤。不要编造源 issue 未指定的里程碑或指派人。 - 检查源 issue 的项目条目。如果它属于一个或多个 GitHub Projects,则将每个新后续 issue 加入相同的项目,并将每个新条目的 Status 设为该项目的
Todo选项。匹配Todo时不区分大小写,但不得擅自选择其他状态。即使运行失败或停滞,也必须先完成此项目路由,再停止;合并后同样如此。 - 如果源 issue 不属于任何项目,且调用目录中存在
.glorp.json,则除了继承的指派人外,还应将每个新后续 issue 指派给已认证用户,以便 Glorp 能够调度它:使用gh issue edit <NEWISSUENUMBER> --repo <OWNER/REPO> --add-assignee @me。使用克隆前记录的文件是否存在这一信息;不要假设被忽略的状态文件会存在于隔离检出目录中。不要将已认证用户添加到项目关联的后续 issue 中;这类 issue 仍应继承源 issue 的指派人。 - 对复用的等效未关闭 issue,也应应用相同的项目状态或指派人路由,除非它已经正确路由,或其当前项目状态表明工作已经开始或完成。只有在复用的 issue 在相应字段上没有任何自身值时,才添加上述决定的标签以及继承的里程碑和指派人,避免覆盖或移除其现有分流信息。
- 记录所有新建或复用的后续 issue 的 URL,以便在最终报告中提供。如果没有符合条件的事项,明确记录无需创建后续 issue。单独记录需要人工验证的事项,并提供列出这些事项的评论 URL。
- 创建 issue、建立源关联或必要的子 issue 关系、为后续 issue 添加标签或复制源 issue 的里程碑或指派人、指派所需用户、复制项目成员关系或设置
Todo状态时若发生失败,应视为可执行错误并重试。不要在失败或停滞时结束运行;所需的后续 issue 工作尚未完成时,不得报告工作流已合并并完成。
报告结果
先说明合并结果。提供 issue 和 PR 的 URL、分支名称、最终提交或合并 SHA、克隆路径、变更日志文件、本地测试、已完成的 CI 检查、后续 issue 的 URL 或确认不需要后续 issue、手动验证项目及其评论 URL(与后续 issue 分开列出),或确认没有手动验证项目。提供 UI 截图或屏幕录制,或确认不适用。确认 PR 已合并且 issue 已关闭。如果确实受阻,请指出确切的失败步骤、相关 URL 或日志详情、剩余要求,以及为此创建或沿用的所有后续 issue;保留隔离的克隆和分支以便继续。如果运行因暂缓合并而以搁置 PR 结束,则不要先报告合并结果:先说明 PR 已就绪但尚未合并,指出相关标签或引用暂缓合并的原文措辞,提供完成状态评论的 URL,并将其中报告的后续事项列为未创建 issue,而不是 issue URL。如果运行因将堆叠 PR 暂停在尚未解决的阻塞项上而结束,则先说明这一点:报告 PR 已就绪但尚未合并,指出它在等待哪个阻塞 PR,并提供暂停评论的 URL。如果运行因该 issue 是跟踪 issue 而结束,请说明未创建 PR,列出已创建或已存在的子 issue 及其 URL 和状态,并说明父 issue 已关闭还是仍在等待未关闭的子 issue。如果工作流在验证期间停止且未创建 PR,请说明未创建 PR,引用停止原因,列出所有创建或沿用的后续 issue,并提供发布在该 issue 上的说明评论 URL(如果该 issue 不存在,则确认无需发布评论)。
清理克隆
删除隔离的克隆目录和任何临时文件。如果工作流受阻或失败,请保留克隆以供进一步调查,并向用户报告其位置。