首页
/ oh-my-openagent 的 PR 验证策略:三道门禁(CI / 5-Agent 评审 / Cubic)与合并恢复流程

oh-my-openagent 的 PR 验证策略:三道门禁(CI / 5-Agent 评审 / Cubic)与合并恢复流程

2026-09-04 20:18:46作者:史锋燃Gardner

本文以仓库中 verification-strategy.md 为核心,讲解 omo/lazycodex(oh-my-openagent)在 work-with-pr 技能框架下针对具体修复 PR(atlas hook 在 boulder.json 缺少 worktree_path 时崩溃)设计的三阶段验证策略:CI 门禁、5-Agent 并行评审门禁与 Cubic 自动审查门禁。读完后你将掌握一套可复用的“提交前本地预检 + 无上限验证循环 + 失败路由”工程化验证方法,并能对照仓库真实源码(boulder-state 存储层、atlas 空闲事件钩子、ci.yml)验证每个检查项的实际落点。

一、背景:验证策略服务的 PR 与三层门禁总览

该验证策略是为一个聚焦的小修复 PR 制定的:fix(atlas): prevent crash when boulder.json missing worktree_path。根因是 readBoulderState()JSON.parse() 的原始输出直接断言为 BoulderState,当 boulder.json"worktree_path": null(手动编辑、外部工具或状态损坏导致)时,运行时类型为 null,违反了 TypeScript 声明的 string | undefined 契约。

对应产物文档见同目录的 code-changes.mdpr-description.md。验证策略把整个验证流程拆为三道门禁(Gate A/B/C),任何一道失败都会把流程打回“修复—提交—推送”循环,直到全部通过才允许合并:

门禁 名称 验证内容 通过信号
Gate A CI 测试(拆分执行)、Typecheck、Build gh pr checks 全绿
Gate B review-work 5 个并行 Agent 评审 5 个 Agent 全部 PASS
Gate C Cubic cubic-dev-ai[bot] 自动代码审查 "No issues found"

注意一个事实边界:当前仓库主干的 work-with-pr SKILL.md 定义的是 CI + Cubic 两道门禁(且该技能规定用 merge commit 而非 squash);而本文档所在的 work-with-pr-workspace 迭代评估(eval-2)把 Gate B 扩展为 5-Agent 评审(review-work),并在合并阶段使用 --squash。两者是同一技能体系在不同评估场景下的编排变体,使用时需区分。

二、Gate A:CI 门禁

CI 实际执行的检查项(对照 ci.yml

文档列出 CI 从 ci.yml 派生的三类检查:

  1. Tests(拆分执行):mock 密集型测试单独隔离运行 + 批量测试;
  2. Typecheckbun run typechecktsc --noEmit);
  3. Buildbun run build(ESM + 声明文件 + schema)。

对照仓库真实的 ci.yml 可以确认这一结构:test job 确实把测试拆成了“主批量”与“隔离批量”两次 bun test 调用——主批量运行 bun test packages/omo-opencode packages/memory-core,另一组则单独运行 Windows 特有测试、chaos-bench、安装器版本测试等长尾用例;typecheck job 独立执行 bun run typecheck,并覆盖 script 与各 package 的检查。也就是说,文档中“mock-heavy tests in isolation + batch tests”的说法与 CI 配置中“隔离运行 + 批量运行”的拆分方式相互印证。

提交前的本地预检(Pre-push local validation)

在推送前,先在本地运行与 CI 完全相同的检查步骤,尽早拦截失败:

# 先跑针对性测试(快速反馈)
bun test src/features/boulder-state/storage.test.ts
bun test src/hooks/atlas/index.test.ts

# 完整测试套件
bun test

# 类型检查
bun run typecheck

# 构建
bun run build

需要结合仓库现状补充一个关键事实:文档中写的 src/... 前缀是该评估当时 monorepo 布局下的路径;从当前仓库结构看,boulder-state 存储与 atlas 钩子已按 monorepo 规范拆包——readBoulderState 的真实实现位于 read-state.ts,由 storage.ts@oh-my-opencode/boulder-state 包统一 re-export;测试文件现位于 storage.test.tsatlas 钩子位于 idle-event.ts。因此本地预检命令在当前仓库应写为:

bun test packages/omo-opencode/src/features/boulder-state/storage.test.ts
bun test packages/omo-opencode/src/hooks/atlas
bun run typecheck
bun run build

这正是“先针对性测试、后全量”策略的意义:CI 一次往返约 3–5 分钟,本地按包过滤的测试能在几秒内给出反馈。

Gate A 失败处理

  • 测试失败:阅读测试输出 → 修复代码 → 创建新 commit(绝不 amend 已推送的 commit)→ push;
  • Typecheck 失败:对变更文件运行 lsp_diagnostics → 修复类型错误 → commit → push;
  • Build 失败:检查构建输出中的缺失导出或循环依赖 → 修复 → commit → push。

每完成一轮“修复—提交—推送”,都要执行 gh pr checks --watch 重新进入 Gate A。

三、Gate B:review-work 五 Agent 并行评审

5 个并行 Agent 的分工

  1. Oracle(目标/约束核对):检查修复是否对题——worktree_path 崩溃是否真正解决、有无范围蔓延(scope creep);
  2. Oracle(代码质量):验证代码遵循既有模式——工厂模式、given/when/then 测试风格、单文件 < 200 LOC、不使用 catch-all 文件;
  3. Oracle(安全):确认没有引入新安全问题——JSON 解析注入、worktree_path 的路径穿越;
  4. QA Agent(动手执行):实际运行测试、对变更文件跑 lsp_diagnostics、验证修复在真实场景下生效;
  5. 上下文挖掘 Agent:检索 GitHub issues、git 历史、相关 PR,确认与项目上下文对齐。

本 PR 的预期审查焦点

这是整个策略中最具可操作性的部分——把抽象门禁落到本 PR 的具体问题上:

  • Oracle(目标)readBoulderState 中的消毒(sanitization)是否真正阻止了崩溃?typeof 守卫是必要还是冗余?
  • Oracle(质量):新测试是否遵循 given/when/then 模式?是否复用了既有测试的 mock 搭建方式?
  • Oracle(安全)worktree_path 的值是否会在未消毒的情况下参与路径操作?(文档给出的结论:,该值只出现在模板字符串中。)
  • QA:运行 bun test src/hooks/atlas/index.test.ts——在修复前,worktree_path 为 null 的测试用例是否确实触发 bug?

对照当前源码可以核验“只用于模板字符串”这一安全结论:idle-event.tsworktreePath: boulderState.worktree_path 只是作为参数传给 injectContinuation()(同目录 idle-continuation.ts),并未直接进入 fs/path 操作,与文档判断一致。

Gate B 失败处理

  • 每个 Oracle 输出 PASS/FAIL 结论并附具体问题清单
  • 若 FAIL:阅读具体问题 → 在 worktree 内修复 → commit → push → 重跑 review-work;
  • 5 个 Agent 必须全部 PASS 才算该门禁通过。

四、Gate C:Cubic 自动审查

Cubic 检查什么

cubic-dev-ai[bot] 是分析 PR diff 的自动代码审查机器人,关注点包括:类型安全问题、缺失的错误处理、测试覆盖缺口、反模式。

预期结果

对这个小而聚焦的修复(文档口径:storage.tsidle-event.tsindex.test.ts 三个文件 + 1 个测试文件),预期结果是 “No issues found”。

Gate C 失败处理

  • 若 Cubic 提出问题:先评估是真问题还是误报
  • 真问题:修复 → commit → push;
  • 误报:在 PR 中留言解释该模式是有意为之;
  • push 后等待 Cubic 重新审查。

五、验证通过后的合并与冲突恢复

合并与 worktree 清理

三道门禁全部通过后:

gh pr merge --squash --delete-branch
git worktree remove ../omo-wt/fix-atlas-worktree-path-crash

合并失败(冲突)时的恢复路径

cd ../omo-wt/fix-atlas-worktree-path-crash
git fetch origin dev
git rebase origin/dev
# 如有冲突则逐一解决
git push --force-with-lease
# 从 Gate A 重新进入验证循环

这里 --force-with-lease 相对 --force 更安全:若远端分支被他人推进过,push 会被拒绝,避免覆盖他人提交。而“rebase 后必须从 Gate A 重新走完整验证”体现了该策略的核心不变量:任何代码变动都触发全量再验证,而不是只补跑失败的那一步。

六、源码纵深:被验证的修复在仓库中的实际形态

为让上述策略可被逐条核验,最后对照仓库真实实现说明修复的落点:

  1. readBoulderState 的消毒管道。当前实现位于 read-state.ts:函数对 boulder.json 做存在性检查与 JSON.parse,随后调用 normalizeState(parsed) 统一修正字段(session_ids 过滤非字符串项并归一化、session_origins 强制为对象、task_sessions 兜底为空对象),最后才执行 parsed as BoulderState 断言。文档要求“worktree_path 必须为 string | undefined,绝不接受 null”的策略,正是这条 normalize-then-cast 管道的典型应用——先消毒再断言,而不是裸 cast。BoulderState 接口中 worktree_path?: string 的声明可参见 boulder-state 包的 AGENTS.md 中的字段注释(git worktree root)。
  2. 防御性 typeof 守卫的调用点idle-event.ts 通过 scheduleRetry(约第 139、150 行两处)与直接 injectContinuation 调用(约第 164–172 行,worktreePath: boulderState.worktree_path 处)把 worktree 路径传递给续写注入链,与 code-changes.md 中“两处调用点加守卫”的描述吻合。
  3. 回归测试锚点storage.test.ts 中已存在使用 worktree_path 的用例(缺失 worktree 的异常路径测试等),index.test.ts 则覆盖 session.idle 处理器——QA Agent “修复前该用例必须红、修复后必须绿”的要求可以直接落在这两个文件上验证。

七、可复用的策略要点小结

把该文档从单一 PR 场景抽象出来,得到一条通用的 PR 验证方法论:

  • 三道门禁,失败即回流:CI(最便宜、最快)→ 多 Agent 评审(最深入)→ 外部自动审查机器人(最异步);任一失败都回到“读日志 → 定点修复 → 原子 commit → push → 从 Gate A 重进”的循环,不设迭代上限;
  • 提交前先本地复刻 CI:先跑变更相关的窄测试,再跑全量、typecheck、build,用秒级反馈换掉分钟级 CI 往返;
  • 门禁问题清单要具体到代码行:如“typeof 守卫是否必要”“worktree_path 是否参与路径操作”,而不是泛泛的“检查质量”;
  • 测试必须能自证 bug:关键回归测试应满足“修复前触发、修复后通过”的双重可验证性;
  • 合并后必清理 worktree,失败不删 worktree:保留现场供人工接管;冲突恢复统一走 fetch → rebase → --force-with-lease → 全量重验。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
981
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384