Launch Plan
2026/9/20 9:23:27 网站建设 项目流程

Launch Plan

【免费下载链接】oh-my-openagentOmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.项目地址: https://gitcode.com/gh_mirrors/oh/oh-my-openagent

TODOs

  • Top-level

Acceptance Criteria

  • Nested under acceptance criteria
  • Nested done

Final Checklist

  • Nested under final checklist
这份夹具刻意混合了多种元素:`## TODOs` 下有一个**列 0(column-0)的未勾选顶层条目**;`### Acceptance Criteria`(H3 子标题)下有两个**带缩进的嵌套复选框**(一未勾选一已勾选);`## Final Checklist` 下还有一个带缩进的嵌套复选框。它与同目录的 [plan-scaffold.md](https://link.gitcode.com/i/c03c938b65905b7678715d2b33411d21)、[plan-with-unchecked.md](https://link.gitcode.com/i/0d6b61cda1ec6e6d2cb6d6cbf0e6e023)、[plan-all-done.md](https://link.gitcode.com/i/821ccebbeb1d61246ff88241307e2724) 共同构成该组件的计划样本集,用来界定"延续钩子到底该统计什么"。 ## ulw-execute 延续钩子:为什么需要统计计划复选框 在 OmO 的 `ulw-execute` 技能([SKILL.md](https://link.gitcode.com/i/d14548773f3d76e3f593d4c99732bcca))中,Agent 按 launch plan 逐项推进任务。为了让多轮自动延续不依赖模型的记忆,组件 `codex-ulw-execute-continuation`([README.md](https://link.gitcode.com/i/1e8be3f4aa701b22d9bb15878b841a10))以 Codex Stop hook 的形式注册:每当一轮回复结束时,hook 读取钩子负载 `cwd` 下的 `.omo/boulder.json`,解析活跃工作项,检查活跃计划顶层清单,只要还有未勾选任务、或最终 review/debugging 关卡未完成,就输出: ```json {"decision":"block","reason":"<directive>"}

reason每次调用都会从 directive.md 加载并填入当前计划状态——包括剩余/总数复选框、下一个未完成任务等。Codex 收到block后会把reason注入下一轮,从而形成"计划未完成 → 自动延续 → 勾选一项 → 再评估"的循环。清单统计的准确性因此直接决定自动延续循环的启停:统计口径一旦出错,要么提前放行导致任务半途而废,要么永远阻塞在已完成计划上。

计数规则:只有哪些复选框算数

组件 README 的 "Counted plan checkboxes" 一节给出了官方口径:

  • 只有位于以下两个 section 下、且处于**第 0 列(无缩进)**的复选框才会被统计:
    • ## TODOs
    • ## Final Verification Wave
  • 嵌套在### Acceptance Criteria### Evidence### Definition of Done下的复选框一律忽略

这份规则同样写进了延续指令 directive.md 的第 2 条:

Pick the FIRST unchecked top-level checkbox in## TODOsor## Final Verification Wave. Ignore nested checkboxes under Acceptance Criteria / Evidence / Definition of Done.

也就是说,### Acceptance Criteria这类子标题下的细节清单是验收证据而非顶层任务,勾选它们不应驱动延续循环;只有## TODOs## Final Verification Wave中的顶层条目才是"活"的任务清单。这正是 plan-with-nested-checkboxes.md 这份夹具要表达的核心语义:嵌套复选框存在,但不应被计入。

解析器实现:plan-checklist.ts 逐层拆解

规则由 plan-checklist.ts 实现,核心入口是parsePlanChecklist(markdown)(L41-L78),返回{ completed, remaining, total, nextTaskLabel }。其关键正则如下:

常量正则(L10-L16)作用
TODO_HEADING_PATTERN^##[ \t]+TODOs(?:[ \t]+#+)?[ \t]*$(忽略大小写)识别## TODOs统计区,进入 todo 区
FINAL_VERIFICATION_HEADING_PATTERN^##[ \t]+Final Verification Wave(?:[ \t]+#+)?[ \t]*$(忽略大小写)识别## Final Verification Wave统计区
SECTION_BOUNDARY_HEADING_PATTERN^#{1,2}(?:[ \t]+|$)只有 H1/H2 标题才会重置统计区,H3 及更深标题不构成边界
FENCE_PATTERN/isClosingFence反引号/波浪线围栏(L13、L149-L167)代码围栏内的内容全部跳过,防止误计示例代码中的- [ ]
TODO_CHECKBOX_PATTERN^- \[([ xX])\] ([1-9]\d*\. .+)$todo 区只统计列 0、带1.编号前缀的条目
FINAL_WAVE_CHECKBOX_PATTERN^- \[([ xX])\] (F[1-9]\d*\. .+)$(忽略大小写)Final Verification Wave 区只统计F1.编号格式条目
SIMPLE_CHECKBOX_PATTERN^[-*][ \t]*\[[ \t]*([xX]?)[ \t]*\][ \t]+(.+)$无统计区结构时的回退解析,此时任意列 0 的- [ ]/* [ ]均计入

解析过程要点:

  1. 先由hasStructuredSection(L80-L95)判断是否存在## TODOs## Final Verification Wave;存在则走严格结构化解析,否则回退到parseSimpleChecklist(L97-L124)的简单模式。
  2. 结构化模式下,只有#{1,2}开头的标题会更新当前 section(todo/final-wave/other);其余行若不在统计区直接跳过。
  3. 复选框的勾选判定为marker.toLowerCase() === "x",因此[x][X]等价;nextTaskLabel取第一个未勾选项的标签,用于指令渲染。
  4. 任何解析异常(文件不存在、不可读等)都会由getPlanChecklist(L30-L39)兜底为全 0 的空清单。

夹具逐行演练:plan-with-nested-checkboxes.md 的解析结果

把关联文档 plan-with-nested-checkboxes.md 逐行喂给parsePlanChecklist,按当前实现可得到如下推演:

行内容解析动作结果
# Launch PlanH1,重置 sectionsection =other
## TODOs命中TODO_HEADING_PATTERNsection =todo
- [ ] Top-leveltodo 区,但缺少1.编号前缀,不命中TODO_CHECKBOX_PATTERN不计入
### Acceptance CriteriaH3,不命中SECTION_BOUNDARY_HEADING_PATTERN(只匹配#{1,2}section 保持todo
- [ ] Nested under acceptance criteria带缩进,非列 0,不命中结构化复选框正则不计入
- [x] Nested done带缩进 + 无编号不计入
## Final ChecklistH2 边界,但不属于 TODO/Final Wavesection =other
- [ ] Nested under final checklistsection 为other不计入

最终得到{ completed: 0, remaining: 0, total: 0, nextTaskLabel: null }。也就是说,这份夹具中的任何复选框都不会被延续钩子统计:顶层条目缺编号前缀,嵌套条目要么带缩进、要么挂在非统计 section 下。这正是 README 中"计划无可读顶层清单(plan has no readable top-level checklist)时钩子静默"的样本。

对比同目录 plan-scaffold.md(被 codex-hook.test.ts 直接引用)即可看出"合规写法":- [ ] 1. Implement checklist parser parity带编号且位于列 0 才被计入,而- [ ] 3. Missing numeric prefix must be ignored- [ ] Outside tracked sections must be ignored分别因缺编号、位于## Acceptance Criteria(非统计区)而被忽略,- [ ] F1. Exercise the Codex Stop surface则以F1.前缀进入 Final Wave 统计。

清单消费链路:从 boulder.json 到 block 决策

计数结果被 boulder-reader.ts 与 codex-hook.ts 两级消费:

1.readContinuationState(L37-L57)——决定"是否存在可延续的工作"

  • 读取<cwd>/.omo/boulder.json(schema_version 2,含works映射表);解析失败直接返回null
  • 通过 session 归属匹配活跃工作:session_ids中的 id 统一归一化处理,钩子自身 session 以codex:前缀匹配(L35、L163-L166);裸 id 会被当作旧的opencode:前缀,无法匹配codex:会话,从而保证只延续自己的 Codex 会话
  • 只有statusactivepaused的工作可延续(L174-L176);completed/abandoned直接放行。
  • 解析计划路径(若工作带worktree_path,计划优先在任务所属 worktree 内解析,L131-L143),再调用getPlanChecklistchecklist.total === 0时返回null——这正是嵌套夹具走向静默的关键分支。
  • 台账路径固定为<cwd>/.omo/ulw-execute/ledger.jsonl

2.runStopHook(L6-L17)——决定是否输出 block。以下任一情况输出为空(静默放行):

  • stop_hook_activetrue(防循环,避免 hook 自己触发自己);
  • 上一条助手消息以外部阻塞标记<ulw-execute-blocked-external>开头(或紧跟ULTRAWORK MODE ENABLED!首行、位于第二行),且标记后至少有一行说明阻塞原因与恢复条件(L50-L61)——防止仅回显标记就跳过延续守卫;
  • 转录文件中出现context compactedcontext_too_largecodex ran out of room in the model's context window等上下文压力标记(L63-L81);
  • readContinuationState返回null(无工作 / 已完成 / 会话不匹配 /清单 total 为 0)。

否则输出{"decision":"block","reason":...}reasonrenderDirective(L19-L41)把 directive.md 中的占位符替换为实际状态:{{PLAN_NAME}}{{PLAN_PATH}}{{BOULDER_PATH}}{{REMAINING_COUNT}}{{TOTAL_COUNT}}{{NEXT_TASK_LABEL}}(无剩余时渲染为none (final gate pending))、{{WORKTREE_BLOCK}}{{LEDGER_PATH}}{{SESSION_ID}}。注意一个细节:即使顶层清单全部勾选(remaining = 0),只要 total > 0,钩子仍会 block 一次,用于执行 Final gate(自测 + 对照验收标准评审),通过后才把 Boulder 工作标记为 completed——这一点在测试#given active codex work with zero remaining tasks #when hook runs #then blocks for the final gate中有明确断言。

CLI 入口 cli.ts 从 stdin 读取 JSON 负载,支持hook stophook subagent-stop两个子命令;SubagentStop事件在 codex-hook.ts 中被刻意失活(de-wired),只会静默返回。

实测验证:测试用例与 smoke test

单元测试:codex-hook.test.ts 以#given/#when/#then风格覆盖了全部静默分支与 block 分支,包括:stop_hook_active静默、SubagentStop 静默、两种外部阻塞标记形式放行、裸标记(无阻塞说明)仍 block、上下文压力静默、会话归属不匹配(opencode:前缀/裸 id)静默、已完成工作静默、畸形 boulder JSON 静默、畸形输入静默、以及"零剩余仍 block 等 Final gate"。这些用例与上文推演一一对应。

smoke test:组件 README 记录了一条可直接运行的端到端验证流程,它同时演示了 hook 的接线方式:

TMP=$(mktemp -d) mkdir -p "$TMP/.omo/plans" cat > "$TMP/.omo/plans/test.md" <<EOF ## TODOs - [ ] Task one - [ ] Task two EOF cat > "$TMP/.omo/boulder.json" <<EOF {"schema_version":2,"active_work_id":"w1","works":{"w1":{"work_id":"w1","active_plan":".omo/plans/test.md","plan_name":"test","session_ids":["codex:smoke-session"],"status":"active"}}} EOF PAYLOAD='{"session_id":"smoke-session","turn_id":"t1","transcript_path":"","cwd":"'"$TMP"'","hook_event_name":"Stop","model":"gpt-5.5","permission_mode":"default","stop_hook_active":false}' npm run build echo "$PAYLOAD" | node dist/cli.js hook stop PAYLOAD_LOOP='{"session_id":"smoke-session","turn_id":"t1","transcript_path":"","cwd":"'"$TMP"'","hook_event_name":"Stop","model":"gpt-5.5","permission_mode":"default","stop_hook_active":true}' echo "$PAYLOAD_LOOP" | node dist/cli.js hook stop rm -rf "$TMP"

README 期望第一条命令输出含"decision":"block"的 JSON、防循环命令无输出。需要说明的是:当前 plan-checklist.ts 实现要求结构化 section 内的条目带编号前缀才会计数,因此编写真实计划时请使用- [ ] 1. Task one这类编号格式(与 plan-scaffold.md 一致),可据此观察 block 输出的实际差异。

钩子接线:hooks.json 将 Stop 事件映射到node "${PLUGIN_ROOT}/components/ulw-execute-continuation/dist/cli.js" hook stop,超时 10 秒,状态提示为 "(OmO 5.0.0-beta.74) Checking Ulw-Execute Continuation"——即每次 Codex 回合收尾时自动执行该检查。

如何写出能被正确统计的计划清单

综合以上实现,编写一份能被 ulw-execute 延续循环正确消费的 launch plan 时,建议遵循以下约束:

  1. 统计区只放两个## TODOs(普通任务)与## Final Verification Wave(终验任务)。
  2. 顶层条目必须位于列 0 并带编号:todo 区用- [ ] 1. Task,终验区用- [ ] F1. Task;勾选后写- [x]- [X]
  3. 验收细节下沉到 H3 子区:把### Acceptance Criteria### Evidence### Definition of Done等子区的条目写为带缩进的嵌套复选框(如两个空格),它们不会被统计,但作为验收证据供 Final gate 评审。
  4. 代码示例中的- [ ]要放进围栏:解析器会跳过

【免费下载链接】oh-my-openagentOmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.项目地址: https://gitcode.com/gh_mirrors/oh/oh-my-openagent

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询