首页
/ OmX 执行就绪排查指南:从 `omx doctor` 绿灯到真实 Codex 执行的完整故障诊断手册

OmX 执行就绪排查指南:从 `omx doctor` 绿灯到真实 Codex 执行的完整故障诊断手册

2026-09-09 21:48:18作者:江焘钦

导读

本文以 docs/troubleshooting.md 为骨架,系统梳理 OmX(Oh My codeX)在"看起来已安装成功、但真实 Codex 执行仍然失败"场景下的全部排查路径:从 omx setup/omx doctor 的能力边界、AGENTS.md 契约丢失、认证与代理配置错位、仓库工件属主异常,到会话指针(session pointer)失效、tmux 扩展键异常、omx explore 硬弃用与 omx update 拒绝自更新等十大典型故障。读完本文,你将掌握一套"先分层验证、再定点修复"的诊断方法论,并能在仓库源码中找到每个结论的落地依据,真正做到可复现、可验证。


一、第一道边界:安装成功 ≠ 真实执行成功

OmX 排障的第一步,是理解两个完全不同的"成功"标准:

  • omx setupomx doctor 校验的是 OmX 的本地安装表面:prompts、skills、AGENTS 脚手架、配置文件、hooks 以及运行时前置条件;
  • 它们并不保证当前激活的 Codex 配置档案(profile)能够完成认证并跑通一次模型请求。

因此,omx doctor 全绿之后,必须从将要实际使用 OmX 的同一个 shell、同一个 HOME、同一个项目目录中,跑一次真实的冒烟测试:

codex login status
omx exec --skip-git-repo-check -C . "Reply with exactly OMX-EXEC-OK"

这条命令链在仓库中同样有测试用例支撑,见 exec.test.ts:测试在一个临时工作目录中通过 native hook 发布 SessionStart 事件,并断言 omx exec 输出符合预期且不出现 stale-dead 相关错误。

把这条边界按以下五层理解:

  • Codex 插件安装/发现层oh-my-codex 可能被缓存到 ${CODEX_HOME:-~/.codex}/plugins/cache/$MARKETPLACE_NAME/oh-my-codex/$VERSION/(本地安装时 local 可充当版本标识)。这只能证明 marketplace/插件工件存在;打包插件虽带有 MCP server 与应用所需的插件级伴生元数据,但 native/runtime hooks 仍归 setup 所有,因此它依然不是完整的 OmX 运行时安装
  • 插件安装 ≠ 传统安装:插件安装/发现不能替代 npm install -g oh-my-codexomx setup。传统 setup 模式会安装 native agents 与 prompts;插件 setup 模式则依赖插件发现来获得内置 skills,归档/移除旧的 OmX 托管 prompts/skills,并刷新 setup 托管的 native agent TOML,使 agent_type 角色在没有陈旧生成角色文件的情况下依然可用。
  • omx doctor 绿:安装与本地运行时接线看起来正常。
  • codex login status 绿:激活的 Codex 档案能看到登录状态。
  • omx exec ... 返回 OMX-EXEC-OK:真实执行、认证、provider 路由与当前工作目录假设已协同工作。

只有第五层全部通过,才叫"真实可用"。


二、AGENTS.md 存在,但 doctor 报"OMX contract 缺失"

其它 Codex 生态工具可能在保留 OmX 的 prompts、skills、hooks 与配置的同时,重写了 AGENTS.md。此时 omx doctor 会发出警告:文件存在,但已不再携带 OmX 生成的 AGENTS 契约标记。

源码中,doctor 对 AGENTS.md 的契约检测确实存在:见 doctor.ts 附近,若检测到"OMX AGENTS contract markers missing",会提示文件可能被其它工具覆盖,并给出恢复指引。

恢复命令与策略选择器

想保留本地指导内容并恢复 OmX 托管的契约段落,运行:

omx setup --scope user --merge-agents

项目级安装则用 --scope project。这一命令族在 setup.ts 中对应 mergeAgents 布尔字段与 mergeAgentsPolicy{ kind: "set"; value: boolean } | { kind: "clear" }),其合并决策逻辑位于 setup.ts

必须严格掌握以下策略语义:

  • 合法裸策略选择器只有三种:--merge-agents--no-merge-agents--clear-merge-agents-policy不支持等号/取值拼写(如 --merge-agents=true)。
  • 显式 set 会覆盖已保存的策略;同一运行中相互冲突的 set/clear 会在任何 setup 变更生效之前失败。
  • 成功的显式 set 会保存到当前工作根目录./.omx/setup-scope.json(即使用户级 scope 也一样),并由立即执行与延迟执行的更新在后续匹配时重放。它不是全局用户偏好
  • --no-merge-agents 只抑制本次合并分支,不承诺保留或替换,因此正常的 prompt、skip、managed-refresh、plugin-default 与 force 行为依旧生效。
  • Review(复查)会在无关设置变化时保留已匹配的策略;Reset 或 scope 变更会移除继承的策略,除非同一运行显式设置它;clear 永远移除策略,且不能与 set 选择器组合
  • 畸形、未知、非布尔或错误 scope 的记录会被忽略;--force 是瞬时的,从不存储或重放
  • 如果 active-session 或 plugin-symlink 保护跳过了本次 AGENTS 写入,但其余 setup 工作成功,显式 set/clear 会以原子方式提交为"未来意图"——这不会让合并成为默认行为,也不会采纳被拒的 #2892 行为。
  • 旧版 OmX 会安全地忽略该字段,但在重写偏好时可能将其抹掉
  • 若你有意整体替换现有文件,使用 omx setup --scope <user|project> --force;setup 在替换前会先备份旧文件。doctor 侧对应的提示文案见 setup.ts

三、doctor 全绿,但 omx exec 报认证错误

常见失败字符串包括:

  • 401 Unauthorized
  • Missing bearer or basic authentication in header
  • Incorrect API key provided

排查时必须检查激活的运行时档案,而不仅是日常登录 shell:

  1. 打印启动 OmX 的 shell 中的 HOMECODEX_HOME
  2. 确认激活的 ~/.codexCODEX_HOME 内含预期的认证信息与 config.toml
  3. 在同一个 shell 中重新运行 codex login status

自定义 HOME、容器、profile、CI 与 service-user 环境通常拥有与机器主用户不同的 ~/.codex。一个 HOME 下可用的 Codex 安装不会自动让另一个 HOME 就绪——这也是"setup/doctor 正常但真实执行失败"最常见的根因之一。


四、本地代理或 openai_base_url 不匹配

如果你的安装依赖 OpenAI 兼容的本地代理或网关,必须确认激活的运行时配置包含匹配的 base URL:

openai_base_url = "http://localhost:8317/v1"

请替换为你的真实代理地址。如果档案本地的 ~/.codex/config.toml 缺失 openai_base_url,Codex 可能把代理签发的 key 发往默认端点,从而出现"setup 与 doctor 看起来都正常,真实执行却报 401 类认证错误"的假象。


五、root 所有或不可写的仓库工件

OmX 运行时与规划工件位于仓库本地的 .omx/.beads/,它们必须可由运行 omx同一操作系统用户写入。通过 sudo、容器或 service user 创建的文件可能变成 root:root 或其它不可写状态,后续阻塞正常 agent 追加计划、状态、日志或上下文工件。

omx doctor 会在 .omx/.beads/ 存在时扫描它们,并报告精确的 root-owned、owner-mismatch 或 non-writable 路径。源码中扫描目录常量即 REPO_ARTIFACT_DIRS = [".omx", ".beads"],见 doctor.ts

安全的手工修复方式:

sudo chown -R $(id -u):$(id -g) <repo>

<repo> 替换为仓库根目录。omx doctor --force 只在仓库根目录归调用用户所有时尝试自动修复属主;否则它保持文件不变,仅打印手工修复指引。源码层面,自动修复通过注入的 chownPath(默认 chown)逐路径执行,并以 root-owned/owner-mismatch/not-writable 三种 reason 归类,见 doctor.ts;推荐的 sudo chown 命令模板见 doctor.ts


六、过期的 doctor --team 或死 tmux 会话状态

omx doctor --teamomx team resume 或启动诊断可能在"之前某个 team 状态引用了已不存在的 tmux 会话"时失败。状态中可能提到 resume_blocker,或死会话被记录在 .omx/state/team/<team-name>/config.jsonmanifest.v2.json 下。

如果 team 被有意废弃且不再有存活 tmux 会话,按以下顺序清理:

omx team shutdown <team-name> --force --confirm-issues
omx cancel
omx doctor --team

不要对可能仍含有效存活 pane 或 worker 状态的 team 强制 shutdown。不确定时优先使用 omx team status <team-name>tmux ls 确认。


七、过期会话指针阻塞状态写入(session.json is present but unusable

这是本文档中最需要精读的一节。当陈旧/死亡的选中指针缺少有效 OMX_SESSION_ID 绑定,或指针畸形、属于其它工作目录、身份不确定(无法进行下文所述的有界精确会话对账)时,状态写入会以如下信息 fail-closed:

Cannot resolve writable state scope: session.json is present but unusable.

规则如下:

  • 畸形指针与外部工作目录指针永远 fail-closed
  • 身份不确定(identity-indeterminate)指针只有下述"精确会话对账"的狭窄恢复路径;
  • 持久化 Ultragoal 变更(goals.json 的 story/goal 转换)会在变更入口与获取锁之后分别执行"时点可写权威检查";之后的 SessionStart 发布仍可能在文件系统写入前穿插进来。

7.1 精确会话对账(stale-dead 指针)

要移除一个已验证死亡的选中指针并保留其精确取证字节,使用官方恢复命令:

omx session pointer recover --cwd /path/to/project

该命令与规范指针锁串行化,只把权威的、确认已死session.json 移到相邻的 no-clobber 隔离路径。它拒绝:存活或可用属主、身份不确定或复用、畸形或外部指针、root/lineage 不匹配、并发变更、I/O 失败以及已存在的隔离目标。恢复成功后规范指针消失,普通重启即可发布新指针。

当指针记录的 PID 确证死亡时,绑定精确的当前会话 ID 并重试同一命令——不要手工动文件

export OMX_SESSION_ID=<current-session-id>
omx state write --input '{"mode":"ultragoal","active":true,"current_phase":"reviewing"}' --json

要点:

  • stale-dead 指针不持有属主权威,因此经过验证的 OMX_SESSION_ID 绑定成为可写会话作用域(状态落在 .omx/state/sessions/<current-session-id>/ 下)。
  • 该绑定是操作者断言:代码证明指针确证死亡且权威,但不证明环境变量值指向你的存活会话——请务必设置为精确的当前会话 ID。
  • 恢复还要求死指针自身对本项目权威:其记录的 cwd 必须包含工作目录;其记录的 state_root(若存在)必须与选中状态根规范匹配(无 state_root 的旧指针,仅在 cwd 推导出的 .omx/state 根完全匹配时才被接受)。缺失或外部权威元数据的指针即使有 env 绑定也保持 fail-closed。
  • 作用域解析从不重写 session.json 本身;只有 SessionStart hook 通过规范指针锁协议对账指针。
  • 注意:带 stale-dead 指针的普通 OmX 重启会以 session_pointer_unusable/stale-dead 中止并保留指针,因此显式设置 OMX_SESSION_ID 才是可靠的恢复路径

该命令在 session-search.ts 中定义,测试覆盖见 session.test.ts(verified-dead selected session pointer recovery)与 doctor-state-root-binding.test.ts(含 stale-dead 快照场景)。

7.2 精确会话对账(identity-indeterminate 指针)

指针身份不确定时的恢复,要求与 stale-dead 恢复相同的 cwd/state_root 权威:记录的 cwd 必须包含工作目录,记录的 state_root(若存在)必须与选中状态根规范匹配(旧指针规则同上)。此外OMX_SESSION_ID 必须精确等于指针自身记录的 session_id不接受任何别名解析

这比 stale-dead 恢复更窄:stale-dead 恢复接受任何经验证的绑定,因为死属主不持权威;而身份不确定的属主可能还活着,所以要求绑定已匹配指针自称的身份。作用域解析同样从不重写 session.json,只有 SessionStart hook 通过指针锁协议对账。

7.3 已知局限

提交前的作用域再验证是时点检查:它降低但无法消除"验证与文件系统提交之间"的窗口。涉及多个文件的完成操作并非原子,并发 SessionStart 发布仍可能穿插。完整解决属于独立后续工作:state: serialize writable commits with SessionStart pointer publication

7.4 仍然 fail-closed 的情形

  • 畸形指针与外部工作目录指针始终 fail-closed;identity-indeterminate 指针除非 OMX_SESSION_ID 精确匹配其自身 session_id 且 cwd/state_root 权威成立,否则也 fail-closed。
  • 没有 env 绑定时,stale-dead 指针仍阻塞写入——必须设置 OMX_SESSION_ID(普通重启会中止而非对账;只有 SessionStart hook 对账指针)。
  • 存活指针带不匹配的 OMX_SESSION_ID 时,以 OMX_SESSION_ID does not match the live session recorded in session.json. fail-closed(该文案在 mcp-parity.test.ts 有断言)。
  • 持久化 Ultragoal 变更(包括曾在纯读时运行的旧版聚合目标迁移)现在要求成功解析可写作用域:无选中指针时保持原有 root/unbound 行为,但 allowlist 违规、冲突根与存活属主不匹配会传播错误而非被忽略。Ultragoal 侧的错误指引明确指向本文档(stale session pointer recovery),见 artifacts.ts

八、tmux 会话中 Shift+Enter 提交而非换行

这通常不是 OmX 新增的功能缺口。

OmX 已携带来自 issue #1271 / PR #12734405f582,"Preserve Shift+Enter inside tmux-backed OMX launches")的 tmux 侧保护,当前 dev 仍在 OmX 托管的 Codex 启动路径上启用 tmux extended-keys=always

  • 在 tmux 内启动时,通过 src/cli/index.ts 中的 withTmuxExtendedKeys(...) 包裹 Codex(导出实现见 index.ts);
  • 分离式 tmux 启动通过 src/cli/index.ts 中的 detached leader bootstrap/cleanup 路径获得同等保护(lease-lock 实现见 index.ts,调用点见 index.tsindex.ts);
  • 回归测试仍覆盖 enable/restore/lease 行为,见 index.test.ts(含 tmux 选项探测失败时的优雅降级、以及无 extended-keys 选项的旧版 tmux 忽略逻辑)。

所以如果 Shift+Enter 仍表现得像普通 Enter,最可能的原因有:

  1. tmux 实际没有为报告者的终端路径转发扩展键——tmux 只在检测到所附终端支持扩展键时才转发更丰富的事件;tmux show -gv extended-keys 可以显示 always,但若终端能力缺失或未被检测到,转发仍会失败;
  2. 报告者不在 OmX 托管的 tmux 启动路径上——例如在 OmX 启动的 pane/会话之外复现,或通过不同客户端路径附加;
  3. 终端特有能力不匹配——部分终端需要在 tmux 显式给出 terminal-featuresextkeys 提示。

操作者检查

在故障发生的同一 tmux client/会话中运行:

tmux show -gv extended-keys
tmux info | grep extkeys
tmux show -gv terminal-features
printf '%s\n' "$TERM" "$TERM_PROGRAM"

期望值:OmX 在该 tmux 托管路径中活跃运行 Codex 时,第一项为 always

  • 若故障会话期间 extended-keys 不是 always:指向 OmX 启动路径 bug/回归;
  • extended-keys always 但仍提交:更可能是终端能力发现或上游 Codex 终端输入解释问题,而非 OmX 提交逻辑。

典型环境修复

如果终端支持扩展键但 tmux 未自动检测到,在 ~/.tmux.conf 添加 extkeys 特性提示并重启 tmux:

set -as terminal-features ',xterm-256color:extkeys'

若你的客户端声明了不同的 terminfo 名称,请相应调整终端模式。

维护者分诊指引

  • 开代码修复:仅当你能证明当前 dev 在存活的 OmX 托管 tmux 启动路径上未设置 extended-keys=always
  • 按环境局限关闭:若当前 dev 正确设置了 tmux 选项,但报告者终端路径仍未转发更丰富的键事件;
  • 优先补文档:当根因是发现性/操作者指引问题而非 OmX 代码路径损坏时。

九、omx explore 已硬弃用

omx explore 处于硬弃用状态,直接命令表面已被移除。现在调用它会有意失败;只有 omx explore --help 仍打印迁移指引。源码 explore.ts 明确声明该命令硬弃用,并仅在参数全部为 --help/-h/help 时放行帮助输出(见 explore.ts)。

替代方案:

  • 只读仓库查询:使用常规 Codex 仓库检查工具/子代理;
  • 显式的 shell-native 只读证据或 --tmux-pane 摘要:使用 omx sparkshell -- <command>

此前的 explore harness 回退边界(sparkshell-backend 回退与 harness 内模型回退)不再适用于面向用户的命令,因为该命令已不再运行 harness。内部 harness 解析助手仅保留用于 omx doctor/native-asset 诊断。


十、omx update 拒绝在 working-tree 构建上运行

直接从检出目录运行、或通过 npm link 链接到全局 root 的构建,不属于任何包管理器所有omx update 会显式拒绝:

[omx] This build runs from a working tree (/path/to/oh-my-codex), which no package manager owns.
      Self-update is refused; pull and rebuild the checkout instead.

对应的源码文案见 update.ts。此类构建请用 git pull && npm run build 更新。启动时的检查会以静默方式做同样的判定并记录节奏,因此链接的开发构建不会在启动时反复提示,也不会覆盖你的工作树。

与之区分的是另一条提示:

[omx] Unable to determine whether this global install is owned by npm or Bun

它表示包根确实位于全局 node_modules 内,但 npm 与 Bun 都未能被验证为其属主——此时请用 npm 或 Bun 重新全局安装。


十一、附:分层排障路线图

把全文收敛成一条可执行的诊断顺序:

  1. 验证安装层omx setup + omx doctor 全绿 → 仅代表本地安装表面正常;
  2. 验证执行层:同 shell 跑 codex login statusomx exec --skip-git-repo-check -C . "Reply with exactly OMX-EXEC-OK",直到得到 OMX-EXEC-OK
  3. 认证层:核对 HOME/CODEX_HOME~/.codex/config.tomlopenai_base_url 是否与本地代理一致;
  4. 工件层omx doctor 检查 .omx/.beads/ 属主;必要时 sudo chown -R $(id -u):$(id -g) <repo>omx doctor --force
  5. 会话层:死 tmux/team 状态用 omx team shutdown ... --force --confirm-issues;失效 session.jsonomx session pointer recover --cwd <repo> + 显式 OMX_SESSION_ID 绑定;
  6. 终端层:Shift+Enter 异常按 tmux show -gv extended-keys 等四连查分诊;
  7. 版本层:working-tree 构建用 git pull && npm run build 更新,勿依赖 omx update

每一步都以仓库源码或文档为据,可随时回查 doctor.tssetup.tssession-search.tsindex.tsexplore.ts 对应的实现与测试,确保排查动作与 OmX 真实行为一致。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

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