oh-my-openagent 的 PR 验证策略:三道门禁(CI / 5-Agent 评审 / Cubic)与合并恢复流程
【免费下载链接】oh-my-openagentomo/lazycodex: The coding agent for tokenmaxxers;the one and only agent harness for complex codebases. For your Codex, for your OpenCode项目地址: https://gitcode.com/gh_mirrors/oh/oh-my-openagent
本文以仓库中 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.md 与 pr-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 派生的三类检查:
- Tests(拆分执行):mock 密集型测试单独隔离运行 + 批量测试;
- Typecheck:
bun run typecheck(tsc --noEmit); - Build:
bun run build(ESM + 声明文件 + schema)。
对照仓库真实的 ci.yml 可以确认这一结构:testjob 确实把测试拆成了“主批量”与“隔离批量”两次bun test调用——主批量运行bun test packages/omo-opencode packages/memory-core,另一组则单独运行 Windows 特有测试、chaos-bench、安装器版本测试等长尾用例;typecheckjob 独立执行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.ts,atlas钩子位于 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 的分工
- Oracle(目标/约束核对):检查修复是否对题——
worktree_path崩溃是否真正解决、有无范围蔓延(scope creep); - Oracle(代码质量):验证代码遵循既有模式——工厂模式、given/when/then 测试风格、单文件 < 200 LOC、不使用 catch-all 文件;
- Oracle(安全):确认没有引入新安全问题——JSON 解析注入、
worktree_path的路径穿越; - QA Agent(动手执行):实际运行测试、对变更文件跑
lsp_diagnostics、验证修复在真实场景下生效; - 上下文挖掘 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.ts 中worktreePath: 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.ts、idle-event.ts、index.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 重新走完整验证”体现了该策略的核心不变量:任何代码变动都触发全量再验证,而不是只补跑失败的那一步。
六、源码纵深:被验证的修复在仓库中的实际形态
为让上述策略可被逐条核验,最后对照仓库真实实现说明修复的落点:
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)。- 防御性
typeof守卫的调用点。idle-event.ts 通过scheduleRetry(约第 139、150 行两处)与直接injectContinuation调用(约第 164–172 行,worktreePath: boulderState.worktree_path处)把 worktree 路径传递给续写注入链,与 code-changes.md 中“两处调用点加守卫”的描述吻合。 - 回归测试锚点。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→ 全量重验。
【免费下载链接】oh-my-openagentomo/lazycodex: The coding agent for tokenmaxxers;the one and only agent harness for complex codebases. For your Codex, for your OpenCode项目地址: https://gitcode.com/gh_mirrors/oh/oh-my-openagent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考