oh-my-codex 0.20.1 补丁版本深度解读:七个修复背后的可靠性工程与防护边界
【免费下载链接】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
导读
0.20.1是 oh-my-codex 于 2026-07-12 发布的一个纯补丁(patch)版本,精确覆盖v0.20.0..9eadab9f191103177fb3eac1b237188ada1f503c提交区间,包含七个缺陷修复 PR 与两项前版本发布文档的附带修正。本文以 docs/release-notes-0.20.1.md 为骨架,逐条拆解这些修复的动机、行为变化与底层实现,并结合仓库源码(native hook、AGENTS 生成器、setup 配置种子逻辑、Conductor 溯源等)还原每一处防护边界的工作原理。读完本文,你将掌握 oh-my-codex 在行尾保留、规划写入边界、用户配置所有权、Stop 协议 schema 安全、委托子代理溯源以及 Bash 写入目标解析六个可靠性维度上的具体设计。
版本概况与发布范围
补丁版本的定位
0.20.1是一个小步快跑的可靠性补丁:没有有意的破坏性 CLI 或包布局变更(docs/release-notes-0.20.1.md 中的 Compatibility 一节明确声明),全部改动都服务于工作流安全性、配置所有权和边界防护的加固。它紧接在 0.20.0(迁移至 GPT-5.6 模型契约的大版本)之后发布,属于典型的“主版本后快速收尾”节奏,CHANGELOG.md 对此也有对应的条目记录。
提交清单与分类
版本区间内共九个提交,精确构成如下:
| Commit | 分类 | 摘要 |
|---|---|---|
f644d2cd3ae98587942aa94f0030f083ea0bb10f | 直接提交;无 PR;上一版本附带修正 | 修正 0.20.0 发布文档,使其覆盖完整对比区间 |
5d43a5bf6f008de17f9425bee4495c457c60b96a | 直接提交;无 PR;上一版本附带修正 | 澄清 capabilities preflight 是手动命令 |
9ea0181820186e7ac14f2ba60c130af3dfb5ce26 | PR #3107 | 修复生成的 AGENTS 标记在 CRLF 行尾下的插入 |
0f38ebecda8e39c6d0346574364185ff45c29f8d | PR #3110 | 修复 Ralplan Markdown 草稿工件写入 |
05262a1cb27429c72764dc4ba0b3c96a2e987fa3 | PR #3111 | 停止种子化遗留 multi-agent 配置 |
754716f179ee69f58a3df1803ff6bdd5688fba9f | PR #3114 | 保持 Stop 响应 schema 安全 |
5fa4f43585ac539bb2df31a8488c4373594d079a | PR #3115 | 停止种子化遗留上下文默认值 |
d4c605fc44b2ce2e87e650630768449f05bd1492 | PR #3117;issue #3116 | Conductor 防护下信任受委托的协作子代理溯源 |
9eadab9f191103177fb3eac1b237188ada1f503c | PR #3120;issue #3119 | 检测原生委托存在性,修复带引号 Bash 写入目标解析 |
注意两点:恰好七个 PR(#3107、#3110、#3111、#3114、#3115、#3117、#3120),#3116 和 #3119 是对应的 issue 而非额外 PR;前两个提交是上一版本遗留的纯文档修正,不算本版本的产品修复头条。
验证状态:静态、pre-tag 声明
版本说明强调其验证状态是“静态且 pre-tag”:docs/qa/release-readiness-0.20.1.md定义了所需的本地门禁、异常契约、证据 schema 以及待补的外部 CI/发布证明。也就是说,docs/release-notes-0.20.1.md 本身不断言任何测试结果、评审结果、CI 运行、tag、GitHub release 或 npm 发布。阅读发布说明时,应把它理解为“冻结树上的声明 + 待外部收据核验的证据契约”,这是本仓库发布纪律的一部分——docs/qa/release-readiness-0.20.1.md 中记录了精确的九路径发布暂存范围、确定性暂存树校验器(git write-tree捕获stagedTreeOid后逐路径字节比对)以及五个元数据文件只允许同步0.20.1版本号、禁止依赖/完整性抖动的约束。
修复一:CRLF 行尾下 AGENTS 标记插入(#3107)
问题本质
omx agents-init(别名omx deepinit)会为目标目录及其直接子目录生成轻量级AGENTS.md。生成器在文件中写入三类管理标记:
const MANAGED_MARKER = "<!-- OMX:AGENTS-INIT:MANAGED -->"; const MANUAL_START = "<!-- OMX:AGENTS-INIT:MANUAL:START -->"; const MANUAL_END = "<!-- OMX:AGENTS-INIT:MANUAL:END -->";(见 src/cli/agents-init.ts)
在 Windows 工作区等使用 CRLF(\r\n)行尾的项目中,如果生成逻辑硬编码 LF 换行,会导致混行(mixed line endings)——标记间是 CRLF、标记自身换行是 LF,进而污染 diff、触发格式检查失败。PR #3107 的修复目标是:在 CRLF 文件中插入标记时保留原有行尾,避免生成器“改写用户文件的行尾风格”。
实现佐证:生成器如何维护“受管文件”语义
agents-init的核心是“受管但保留手工区”的双区模型(src/cli/agents-init.ts):
isManagedAgentsInitFile通过MANAGED_MARKER识别此前由本工具生成的文件;extractManualSection从MANUAL_START/MANUAL_END之间取出用户手工维护的## Local Notes区块,刷新时原样回填;wrapManagedContent将“生成体 + 手工体”重新包裹进标记对。
对已存在且未被管理的AGENTS.md,默认策略是跳过而非覆盖(skipped,提示“existing unmanaged AGENTS.md (re-run with --force to adopt it)”),只有显式--force才会在备份后接管;对项目根目录AGENTS.md,若检测到活动 omx 会话还额外叠加“避免重写”的防护(rootOverlayRisk,见 src/cli/agents-init.ts)。在这个行尾敏感的插入流程中,CRLF 修复保证了既有文件的行尾风格不会被“管理标记”重写。
命令行用法(src/cli/agents-init.ts):
Usage: omx agents-init [path] [--dry-run] [--force] [--verbose] omx deepinit [path] [--dry-run] [--force] [--verbose] Options: --dry-run Show planned file updates without writing files --force Overwrite existing unmanaged AGENTS.md files after taking a backup --verbose Print per-file actions and skip reasons --help Show this message生成器默认跳过.git、.omx、.codex、node_modules、dist、build、coverage、.next、.nuxt、.turbo、.cache、__pycache__、vendor、target、tmp、temp等目录(src/cli/agents-init.ts),只生成“目标目录 + 直接子目录”两级,且强制目标必须位于当前工作目录内(agents-init target must stay inside the current working directory)。
修复二:Ralplan Markdown 草稿写入边界(#3110)
问题本质
Ralplan 是 oh-my-codex 的规划工作流,核心执行循环包含draft、architect-review、critic-review、complete四个阶段(RALPLAN_ACTIVE_PHASES,见 src/ralplan/runtime-contract.ts)。规划过程需要把 Markdown 草稿工件写盘,但 native hook 的写入防护必须“fail-closed”——只放行白名单路径,其余一律拒绝。0.20.1 之前,.omx/drafts/下直接子级的规范化 Markdown 工件无法通过写入边界,导致规划草稿写盘被误拦。
实现佐证:native hook 的规划写入边界
写入判定集中在 src/scripts/codex-native-hook.ts:
isAllowedPlanningArtifactPath依次检查:路径规范化是否成功、conductorPathnameExpansionIsAmbiguous(路径名展开歧义则拒绝)、conductorPathTraversesLink(穿越符号链接则拒绝)、isProtectedPlanningStatePath(受保护的规划状态文件拒绝)、.omx/tmp下的脚本类扩展名拒绝(isAllowedPlanningTmpScratchPath);isAllowedRalplanDraftPath专门放行匹配^\.omx\/drafts\/[^/]+\.md$的直接子级单层 Markdown——注意正则要求[^/]+,即不允许嵌套子目录;isAllowedRalplanArtifactPath= 草稿路径放行 ∨ 白名单前缀放行,其中RALPLAN_ALLOWED_WRITE_PREFIXES包括.omx/context、.omx/plans、.omx/specs、.omx/tmp、.omx/state、.beads(src/scripts/codex-native-hook.ts)。
受保护的规划状态文件名集合(PROTECTED_PLANNING_STATE_FILE_NAMES)涵盖autopilot-state.json、autoresearch-state.json、deep-interview-state.json、ralplan-state.json、ralph-state.json等(src/scripts/codex-native-hook.ts),这些文件任何情况下都不接受裸工件写入。
也就是说,修复后的边界是:在fail-closed的大前提下,为规范化、单层、.md的.omx/drafts/草稿打开一条精确的窄门,其余目标(嵌套路径、非 Markdown、符号链接穿越、受保护状态文件)仍然默认拒绝。Ralplan 运行时在draft阶段收集RalplanDraftResult并携带advisory_plan_manifest_sha256等完整性证据(src/ralplan/runtime.ts、src/ralplan/runtime-contract.ts),保证“写盘允许”与“共识证据可校验”二者不脱节。
修复三:停止种子化遗留配置默认值(#3111、#3115)
问题本质
两个 PR 属于同一主题:配置所有权(configuration ownership)。
- #3111:全新 setup 不再强制写入遗留的 multi-agent 默认配置;
- #3115:全新 setup 不再种子化遗留的上下文窗口(context-window)默认值(
model_context_window、model_auto_compact_token_limit)。
此前 setup 可能把“默认行为”直接写进用户的.codex/config.toml,这带来两个问题:一是用户配置文件被工具改写,与“uninstall 应能干净移除工具痕迹”的哲学冲突;二是遗留默认值会干扰原生角色路由——当模型/上下文默认值被旧值钉死时,新版本的角色路由与模型契约难以生效。
实现佐证:测试与生成器
测试 src/cli/tests/setup-refresh.test.ts 精确刻画了期望行为:
- 全新 setup 生成的
config.toml不得包含/model_(?:context_window|auto_compact_token_limit)\s*=/和seeded behavioral defaults标记; - 若手工写入带
# oh-my-codex seeded behavioral defaults (uninstall removes unchanged defaults)/# End oh-my-codex seeded behavioral defaults标记的旧区块,刷新 setup 会移除该精确标记对; - 用户自己的
approval_policy = "on-failure"保持不变; - 连续第二次刷新结果与第一次完全一致(幂等)。
这正是“保留用户自有配置 + 移除工具种子化痕迹”的双重断言。配合 #3111 的“不再强制 legacy multi-agent 默认值”,全新用户获得的是一条干净的、由原生角色路由驱动的默认配置,而不是被旧版默认值预占的配置。其余测试还验证了“忽略遗留~/.omc/mcp-registry.json”(src/cli/tests/setup-refresh.test.ts),体现同一所有权原则向 MCP 注册表等区域的延伸。
修复四:Stop 响应保持 schema 安全(#3114)
问题本质
Codex native hook 对Stop事件的响应必须符合宿主约定的 JSON schema。若响应中携带宿主不支持的顶层字段,会破坏 hook 协议(轻则被忽略、重则被拒绝/崩溃)。修复目标是:Stop 响应省略不受支持的顶层字段,保持 schema 安全。
实现佐证:fail-closed 的 JSON 输出
native hook 的事件归一化把Stop归入"stop"(src/scripts/codex-native-hook.ts),并明确从 sanitized 负载中删除stop_hook_active/stopHookActive等字段(src/scripts/codex-native-hook.ts)。测试端则验证了输出形状的严格性:
- 对不可识别/畸形 stdin 但具备原生 Stop 运行时表面的场景,输出必须是
decision: "block"、不含continue、hookSpecificOutput保持undefined,并携带stopReason: "native_hook_stdin_parse_error"与明确的systemMessage(src/scripts/tests/codex-native-hook.test.ts); - 对非 Stop 事件(如畸形
PreToolUse),则走hookSpecificOutput.hookEventName+permissionDecision: "deny"的分支,同样不输出decision/continue/stopReason顶层字段(src/scripts/tests/codex-native-hook.test.ts)。
可见“schema 安全”不是简单删除字段,而是按事件类型选择合法的输出形状:哪些字段可出现、哪些必须省略,都由测试逐一锁定,防止未来重构悄悄引入不兼容字段。
修复五:Conductor 防护下的受委托子代理溯源(#3117;issue #3116)
问题本质
Conductor 是团队模式(Team)下负责执行策略根解析与写入防护的守卫。此前,由 Leader 通过原生协作工具(如collaboration.spawn_agent、multi_agent_v1.spawn_agent、遗留别名task)委托生成的子代理,在 Conductor 的溯源判定中可能被误判为“无主/不可信”的写入者,导致合法委托链路被拦截(issue #3116)。修复目标是:识别受信任的委托协作子代理,同时保留 Leader 与规划写入边界的既有防护。
实现佐证:可判定的委托工具识别与证据型溯源
工具识别侧,src/leader/contract.ts 提供了两个关键判定:
isNativeSubagentSpawnToolName:通过后缀锚定的(?:^|\.)spawn_agent$模式识别裸spawn_agent与multi_agent_v1.spawn_agent、collaboration.spawn_agent等命名空间形式,外加遗留别名task;后缀锚定避免respawn_agent/spawn_agentx误匹配;isNativeSubagentResultToolName:同类识别spawn_agent、list_agents、followup_task、wait_agent等结果工具。
溯源侧,src/team/worker-provenance.ts 实现了证据返回型的权威 Team-worker 上下文解析:只有环境身份(OMX_TEAM_INTERNAL_WORKER与OMX_TEAM_WORKER必须 worker 名一致)、identity.json、manifest.v2.json、config.json、pane、worktree、state-root、leader-CWD 全部交叉校验通过,才产出结构化AuthoritativeTeamWorkerEvidence。resolveConductorPolicyRoot(src/team/worker-provenance.ts)进一步规定:外部 Team state root 只有经过完整权威验证才能贡献策略上下文,未验证或失配的根一律 fail-closed。这与修复五的目标形成闭环——委托子代理的“受信任”资格来自可判定的工具名 + 可验证的证据链,而不是放宽防护本身。
修复六:原生委托检测与带引号 Bash 写入目标解析(#3120;issue #3119)
问题本质
该修复包含两个关联缺陷(issue #3119):
- 不完整能力清单误判:hook 负载中的
available_tools清单可能不完整——collaboration.*委托工具可能暂时缺席于该次负载,但 spawn 表面仍可调用。若把“清单里没有”当作“不支持”的确定性证据,就会得出错误的unsupported结论,进而触发不安全的委托探测或错误门禁。 - 带引号 Bash 参数中的重定向误解析:如
gh issue create --body '...>{1,2}...'或omx state write --input '{"reason":"a>b"}',其中的>位于引号内部,是普通字符而非重定向符。若解析器把它当成写入目标,会错误拦截合法命令。
实现佐证:unknown 而非 false-negative、引号感知的掩码
能力判定侧,src/leader/contract.ts 明确:存在但不完整的工具清单不是显式否定证据,应报告unknown(携带观察到的名称溯源),而不是持久化unsupported假阴性。只有显式能力字段(omx_runtime_capabilities/capabilities)明确报告不可用时,才走unsupported。
Bash 解析侧,src/scripts/codex-native-hook.ts 的maskQuotedRedirectMetacharsForCommandScan实现了引号感知的掩码:
- 维护单引号
'(无转义)、双引号"(反斜杠转义)、ANSI-C$'...'(含\')三种引号状态机; - 只有位于真实引号跨度内的
</>才被掩码;未加引号的重定向符原样保留,保证真正的重定向仍被扫描到; - 顶层反斜杠转义后的引号是字面字符,不能开启引号跨度(否则
gh issue create --body '...'中的转义引号会破坏配对); - 未闭合/歧义引号 fail-closed:返回未掩码的原始命令,让真实重定向保持可见,避免“伪造跨度掩盖真重定向”的漏报。
配套的变量重定向解析resolveCommandRedirectTarget(src/scripts/codex-native-hook.ts)把$NAME/${NAME}形式的写入目标解析为同命令内的字面赋值,并要求严格形态的cat > "$NAME" <<- 'TAG'(boundedCatRedirect,src/scripts/codex-native-hook.ts)才接受,否则视作不可解析目标继续走白名单检查。测试同时覆盖了“带引号重定向/源文本不是写入目标”与“转义引号、ANSI-C 引号下对源的重定向保持阻断”(src/scripts/tests/codex-native-hook.test.ts)。
总结:从七个修复看 oh-my-codex 的可靠性哲学
0.20.1虽然只有七个 PR,但覆盖面极具代表性,可以归纳为四条工程主线:
- 行尾与格式保真(#3107):工具可以生成内容,但不得破坏用户文件的既有风格,管理标记与手工区块分离、刷新幂等。
- fail-closed 的窄门式放行(#3110、#3117、#3120):写入边界、Conductor 溯源、Bash 目标解析都以“默认拒绝、证据放行”为基调——草稿目录只放行单层规范化 Markdown;委托子代理必须通过完整证据链验证;引号歧义时宁可保留原文供扫描也不掩盖真重定向。
- 配置所有权(#3111、#3115):工具不把默认值写进用户配置文件;已写入的标记化默认值在刷新时被精确移除;uninstall 应能干净地收回一切工具痕迹。
- 协议形状纪律(#3114):hook 响应按事件类型选择合法字段集合,并用测试锁定“必须省略的字段”,防止静默破坏 schema。
对于使用 oh-my-codex 的开发者,本版本的升级含义是:跨平台仓库(尤其 Windows/CRLF 工作区)的omx agents-init体验更一致;Ralplan 规划草稿可以正常落盘而不会被误拦;全新 setup 得到的配置更干净、更贴近原生角色路由;团队模式下委托子代理的写入不再被误伤,同时带引号的 Bash 参数(如 JSON 内联、GitHub CLI 的--body)也不会再被误判为重定向写入。这些修复全部以测试为锚(核心证据集中在 src/scripts/tests/codex-native-hook.test.ts 与 src/cli/tests/setup-refresh.test.ts),并遵循 docs/qa/release-readiness-0.20.1.md 声明的静态 pre-tag 发布纪律——外部 CI、tag 与 npm 发布证据由发布流程另行记录,不写入发布说明本身。
【免费下载链接】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),仅供参考