ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

OmX 近期缺陷回归加固实战:从 planning 门控、Stop 钩子状态权威到 tmux 启动与团队启动证据的四个回归防线

2026/9/11 5:57:57 拓冰建站 浏览量
OmX 近期缺陷回归加固实战:从 planning 门控、Stop 钩子状态权威到 tmux 启动与团队启动证据的四个回归防线 OmX 近期缺陷回归加固实战从 planning 门控、Stop 钩子状态权威到 tmux 启动与团队启动证据的四个回归防线【免费下载链接】oh-my-codexOmX - Oh My codeX: Your codex is not alone. Add hooks, agent teams, HUDs, and so much more.项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-codex导读OmXOh My codeX在 2026-04-11 提交了一组聚焦的编译版 recent-bug 回归加固覆盖四个真实故障面已批准短任务被错误重新门控回 ralplan 规划、Stop 钩子被 stale 根状态误导而抑制 auto-nudge、不支持的环境变量 SHELL 值导致 detached tmux 启动丢失目标目录、以及团队 worker 启动证据对异常状态文件的容错。本文基于 docs/qa/recent-bug-regression-hardening-2026-04-11.md 及其对应源码与测试逐项拆解每个回归的成因、修复断言与可复跑的编译验证命令帮助读者掌握 OmX 关键词路由、native 钩子分发、启动回退与团队运行时四大模块的加固方法论。一、背景编译版 recent-bug 套件与四项加固概览OmX 用一套“编译产物优先”的回归测试策略来防止已修复缺陷复发测试先经npm run build编译到dist/再直接对编译后的 JS 运行node --test从而保证 CI 验证的是用户实际运行的产物而非源码路径。本次加固在该套件上新增四组断言分别命中四个不同的运行时子系统#加固方向涉及模块核心目标1Planning-precedence follow-ups关键词路由 / ralplan 门控已批准短ralph后续任务在规划工件已存在后不被重新门控回ralplan2Stop-hook stale-root vs current-sessionnative 钩子 / 会话状态显式非活跃的 session-scoped deep-interview 状态优先于活跃的根回退auto-nudge 不被 stale 根状态抑制3Detached tmux launch shell drift fallbackCLI 启动不支持的SHELL值触发回退时仍保留请求的 cwd4Team startup worker-state evidence团队运行时容忍格式错误的 worker 状态输入blocked状态视为真实启动进度四个方向的测试文件与验证命令均记录在原文档中下面逐一展开。二、加固一Planning-precedence——已批准后续任务不被重新门控回 ralplan2.1 问题本质后续任务被“旧门控”拦截当一次会话已经完成规划planning artifacts 已存在时用户后续发起的短任务short follow-ups源自已被弃用的$ralph流程线不应再被强制拉回ralplan的共识规划门控。若路由层只看残留的ralplan-state.json与skill-active-state.json就会把已批准的后续执行重新拦截回规划阶段造成死循环式的“规划—批准—再规划”。2.2 源码机制仅路由激活的中和neutralization这一防线落在 src/ralplan/documented-leader-preflight.ts 的neutralizeOwnedRoutingRalplan与readNeutralizedRoutingOverlayneutralizeOwnedRoutingRalplan(cwd)只对“纯路由激活”的 ralplan 状态生效它要求ralplan-state.json与skill-active-state.json构成一对严格匹配的routingOnlyPair模式为ralplan、阶段为planning、会话号一致、字段白名单RALPLAN_KEYS/SKILL_KEYS约束并通过collectOwners校验当前OMX_SESSION_ID确实持有该会话的所有权避免误中和他人状态命中后以.ralplan-neutralization-digest-token.json 对应.commit.json的“数据—提交”两段式文件GENERATION_PREFIX、COMMIT_SUFFIX记录中和结果写入过程使用writeExclusiveO_EXCL 目录sync()保证幂等与崩溃安全readNeutralizedRoutingOverlay读取该 overlay 后返回{ active: false, phase: cancelled, current_phase: cancelled }的中和形态路由层据此判定该 ralplan 激活已“退役”不再重新门控。2.3 测试证据对应测试位于 src/hooks/tests/keyword-detector.test.ts该文件同样导入neutralizeOwnedRoutingRalplan与getRemovedSkillInfo。其中does not activate a workflow for the sunset $ralph token断言$ralph是已声明移除的技能getRemovedSkillInfo(ralph)的replacement为$ultragoal因此不再激活任何工作流只产生非激活诊断prefers ralplan over ralph follow-up language when both implicit routes are presentkeep going but do consensus plan first这类仍带明确规划意图的输入才路由到ralplan避免误中和真正需要规划的请求。从源码结构可以推断规划工件已存在后的短后续任务正是通过“检测到已被中和的 ralplan overlay → 跳过重新门控”来保持已批准状态不被回退。三、加固二Stop 钩子 stale-root 与 current-session 的权威关系3.1 问题本质stale 根状态抑制 auto-nudgeOmX 的会话状态同时存在“根级状态”如.omx/state/ultragoal-state.json、根skill-active-state.json与“会话级状态”.omx/state/sessions/id/…。当某会话已显式将 deep-interview 模式置为非活跃但根级仍残留一个活跃的旧状态时Stop 钩子的 auto-nudge 判断若优先读取根回退root fallback就会错误地认为“仍有活跃的 deep-interview 门控”而抑制本该发送的自动提示。3.2 源码机制session-scoped 状态优先在 src/hooks/keyword-detector.ts 中deep-interview 是带输入锁的状态化技能模式DEEP_INTERVIEW_STATE_FILE deep-interview-state.json会话级 deep-interview 状态文件DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS [yes, y, proceed, continue, ok, sure, go ahead, next i should]访谈期间被锁定的自动批准快捷输入DEEP_INTERVIEW_INPUT_LOCK_MESSAGE Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.persistDeepInterviewModeState把模式状态写入stateDir/sessions/sessionId/会话目录keyword-detector.test.ts 第 4115 行creates the session-scoped deep-interview state directory before persisting mode state直接验证了目录先建后写。加固的权威关系在测试中体现为creates the session-scoped deep-interview state directory before persisting mode state验证会话目录内的deep-interview-state.json被正确持久化ignores stale root child mode state during session-scoped Autopilot child reconciliation第 4485 行在根级存在ultragoal-state.json { active: true, current_phase: executing }的 stale 状态下session-scoped Autopilot 继续以supervised_child_skill: deep-interview协调子技能根 ultragoal 保持active: true不被触碰——即“显式会话态优先stale 根态只作回退”。3.3 native 钩子侧的对称防线Stop 钩子侧的同构加固位于 src/scripts/tests/codex-native-hook.test.tsdoes not block Stop on stale session autopilot mirror when canonical skill state is inactive第 2670 行构造“会话镜像autopilot-state.json为active: true但 canonicalskill-active-state.json为active: false, phase: cancelled”的对立场景调用dispatchCodexNativeHook处理Stop事件断言输出为{}即不阻止、不 nudge、不产生副作用。这正是文档所述“显式非活跃的会话级模式状态优先于活跃根回退”的钩子级落地当权威状态已取消时任何镜像/根残留都不足以重新激活门控。四、加固三detached tmux 启动的 shell 漂移回退与 cwd 保留4.1 问题本质SHELL 与 rc 文件驱动的目录漂移detached tmux 启动会借助用户 shell 的 rc 文件.profile/.zshrc/.bashrc初始化环境但 rc 中的cd语句可能把工作目录“漂移”走。当SHELL环境变量指向不存在的路径如/definitely/missing-shell或非受支持 shell 时OMX 必须回退到/bin/sh执行 detached leader而此时必须保证请求的 cwd 仍然保留——否则整个 detached 会话会在错误目录下启动。4.2 测试证据两个互补用例加固测试位于 src/cli/tests/launch-fallback.test.ts通过wrapFakeTmuxWithDetachedLeader包装的假 tmux 假 codex 完成端到端断言preserves the requested cwd through detached tmux launch when an unsupported SHELL value falls back away from rc-driven cwd drift第 2738 行在HOME下放置cd ..的.profile/.zshrc/.bashrc以SHELL: /definitely/missing-shell运行omx --madmax --tmux随后断言 tmux 日志中出现/bin/sh与__detached-session-leader——回退 shell 被正确选用且 leader 以期望的 cwd 启动falls back to /bin/sh for detached tmux launch when SHELL drifts to an unsupported path第 2833 行以SHELL: /bin/not-a-real-shell验证同一回退路径。两个用例共同锁定契约无论SHELL如何漂移detached tmux 启动都必须回退到受支持的/bin/sh且不得以 rc 文件的cd副作用漂移掉请求的 cwd。测试借助buildRunOmxEnv清空所有OMX_*/CODEX_*/TMUX环境变量以隔离干扰并依赖isRealScriptAvailable/isRealTmuxAvailable做平台跳过Windows 或缺少script(1)时跳过CI 上则必须提供见skipUnlessScriptAvailable。五、加固四团队启动的 worker 状态证据容错5.1 问题本质外部状态根下的异常输入团队team模式支持OMX_TEAM_STATE_ROOT指向外部共享状态根。外部进程如手工编辑、其他工具可能写入格式损坏的status.json此外worker 在 Codex 启动早期可能尚未持久化current_task_id仅先写入blocked状态。启动证据收集waitForWorkerStartupEvidence必须对这两类输入都稳健坏 JSON 不能炸掉 hardening-e2e 覆盖blocked不能被视为“没进展”而反复重试直至超时。5.2 源码与测试证据src/team/tests/hardening-e2e.test.ts 第 87 行tolerates malformed worker status from an external team state root在OMX_TEAM_STATE_ROOT指向的共享根下把workers/worker-1/status.json覆盖为{not valid json随后monitorTeam仍返回快照且 worker 的status.state unknown——即“外部坏输入被降级为 unknown而不是抛异常打断监控”src/team/tests/runtime.test.ts 第 1815 行waitForWorkerStartupEvidence treats blocked worker status as settled progress even without a claimed task id写入{ state: blocked, reason: waiting on shared file, updated_at: … }无current_task_id后waitForWorkerStartupEvidence返回worker_progress证明blocked是合法的“已开始但被外部条件阻塞”的启动证据同一文件第 3774–3776 行还断言失败回滚场景下readWorkerStatus返回reason: codex_bypass_mdm_incompatible且current_task_id: undefined被如实保留——状态读取层对缺失字段不臆造。从测试结构可以推断waitForWorkerStartupEvidence将“已持久化current_task_id”与“明确写入blocked状态”视为同等的进展信号避免把阻塞误判为未启动而重复派发。六、验证目标编译、定向运行与整包回归原文档给出了完整的验证链路对应 package.json 中的脚本定义# 1. 全量编译同时构建 TS 产物与 runtime 产物 npm run build # 2. 对编译产物定向运行四个加固测试文件 hardening-e2e node --test dist/hooks/__tests__/keyword-detector.test.js \ dist/scripts/__tests__/codex-native-hook.test.js \ dist/cli/__tests__/launch-fallback.test.js \ dist/team/__tests__/runtime.test.js \ dist/team/__tests__/hardening-e2e.test.js # 3. 一键整包build - build:runtime - 编译套件全量运行 npm run test:recent-bug-regressions:compiled其中test:recent-bug-regressions:compiled实际执行的清单比定向命令更全还包含dist/hooks/__tests__/session.test.js与dist/hooks/__tests__/issue-3497-hook-simplification.test.js而test:recent-bug-regressions是“先编译再跑”的完整入口npm run build npm run build:runtime npm run test:recent-bug-regressions:compiled。由于定向运行依赖dist/产物任何源码修改后都必须先执行npm run build这正是文档把npm run build列为第一验证目标的原因。七、加固方法论小结从四项回归中可以提炼出 OmX 的通用防线模式权威分层会话级显式状态优先于根级回退canonical 状态优先于镜像/残留加固二、三幂等中和对“已完成使命”的激活记录以数据提交两段式文件做不可变中和路由层据此跳过旧门控加固一回退可预测不支持的运行时输入SHELL走显式回退路径并锁定关键不变式cwd 保留、退出码透传加固三对坏输入降级而非崩溃外部共享状态的损坏 JSON 降级为unknownblocked视为进展信号加固四。如需深入实现细节可继续阅读 src/hooks/keyword-detector.ts、src/ralplan/documented-leader-preflight.ts、src/scripts/codex-native-hook.ts 与 src/cli/index.ts 等核心模块并对照上述四个测试文件复跑验证命令即可在自己的改动上复现这套“编译产物 定向断言 全量回归”的防复发流程。【免费下载链接】oh-my-codexOmX - Oh My codeX: Your codex is not alone. Add hooks, agent teams, HUDs, and so much more.项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-codex创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考