oh-my-openagent 的 CLI 改名 Scope-Fidelity 验证:Removal Proofs 与命令字符串审计门如何守护 `omo-agent-toolkit` 迁移
2026/9/19 21:57:30 网站建设 项目流程

oh-my-openagent 的 CLI 改名 Scope-Fidelity 验证:Removal Proofs 与命令字符串审计门如何守护omo-agent-toolkit迁移

【免费下载链接】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

导读

本篇技术指南围绕 oh-my-openagent 仓库中omoomo-agent-toolkit这一 CLI 入口改名事件展开,深度讲解该仓库如何用"范围保真校验(Scope-Fidelity Check)"证明一次大规模改名既删除了旧命令、又未越界触碰无关模块。你将掌握一套可复用的验证方法论:用git diff统计与排除项证明改动边界、用jq输出 Removal Proofs(删除证据)、用保留名集合防抢注、以及用"命令字符串审计门(agent-command-string audit gate)"扫描全部被跟踪文件,杜绝任何遗留的旧命令发射点。

1. 背景:为什么要给 CLI 改名做"范围保真"校验

oh-my-openagent(npm 包名oh-my-opencode)的 CLI 曾以omo作为默认入口,同时保留oh-my-opencodeoh-my-openagentlazycodexlazycodex-ai等别名。在一次名为omo-agent-toolkit-rename的改名中,omo被移除,新的规范入口omo-agent-toolkit取而代之。

改名最危险的地方不在于"改",而在于"改不干净":源码中任何一个omo <verb>字符串残留、package.json里任何一条遗留的.bin.omo、文档里任何一句omo doctor指令,都会让用户在升级后面对一个"幽灵命令"。更隐蔽的风险是越界改动:一次改名 PR 如果顺手碰了无关模块(如omo-native原生运行时、senpi依赖、hook 装配),会让审查者无法判断哪些破坏是改名引起的。

因此该改名流程在.omo/evidence/20260809-omo-agent-toolkit-rename/F4.md中固化了六个维度的 F4 范围保真检查,逐条输出可复现的命令与证据,最终以 Verdict(通过/拒绝)收尾。下面逐节拆解这套方法。

2. 改动边界:用 Diff Stat 与排除项证明"只改该改的"

2.1 Diff stat 给出总体量

F4 首先用 diff 统计给出这次改名的体量:

git diff origin/dev...HEAD --stat | tail -5

当时的输出显示142 个文件变更,8619 行新增、346 行删除script/agent-command-string-audit.test.ts+59、script/bin-map.test.ts+34 等新文件均为审计门基础设施)。这为后续所有检查划定了讨论范围。

2.2 Exclusions held:证明没有越界

范围保真校验的第二步,是用rg在 diff 文件清单中反向搜索被明令排除的模块,输出为空即证明"未越界":

git diff origin/dev...HEAD --name-only | rg 'omo-native|omo_ai' git diff origin/dev...HEAD -- package.json | rg 'senpi' git diff origin/dev...HEAD --name-only | rg 'hooks\.json|\.codex-plugin'

三条命令的输出全部为空,分别证明:

  • 没有触碰omo-native原生运行时(该模块留待未来原生版omo-ai使用);
  • package.json中没有 senpi 依赖的版本钉死变动;
  • 没有改动任何 Codex hook 装配文件(.codex-plugin/plugin.jsonhooks/hooks.json等)。

这套"负面清单"思想非常关键:审查者不仅要知道改了什么,还要证明没改什么。结合 F1.md 的完整计划合规审计表,该 PR 对 18 条"Must NOT have / guardrails"逐条给出了 PASS/FAIL 证据,包括"无 npm 包改名""无 marketplace 身份改名(保留omo@sisyphuslabs)""无OMO_*环境变量改名(仅新增OMO_EDITION)"等。

3. Removal Proofs:用 jq 给出"旧命令确实没了"的证据

改名验证的核心不是"我觉得删了",而是机器可验证的删除证据。F4 用两条jq命令完成:

jq -e '.bin.omo' package.json; echo "exit=$?"

输出:

null exit=1

jq -e在取值不存在时退出码为 1,因此exit=1本身就是".bin.omo不存在"的机器可读证明。紧接着列出当前全部 bin 入口:

jq -c '.bin | keys' package.json

输出:

["lazycodex","lazycodex-ai","oh-my-openagent","oh-my-opencode","omo-agent-toolkit"]

即:旧的omo消失,新的omo-agent-toolkit就位,其余四个别名原样保留。最后再回到 diff 中确认删除动作本身确实发生过:

git diff origin/dev...HEAD -- package.json | rg '^-.*\"omo\"' # - "omo": "bin/oh-my-opencode.js",

对照当前仓库根目录 package.json 的实际状态(nameoh-my-opencodeversion5.0.0-beta.69),bin字段恰为五个入口且全部指向共享入口bin/oh-my-opencode.js,与 F4 期望的终态完全一致:

{ "oh-my-opencode": "bin/oh-my-opencode.js", "oh-my-openagent": "bin/oh-my-opencode.js", "omo-agent-toolkit": "bin/oh-my-opencode.js", "lazycodex": "bin/oh-my-opencode.js", "lazycodex-ai": "bin/oh-my-opencode.js" }

3.1 No lingering alias:确保不是"换个地方藏着"

删除证据还需要排除"别名残留":改名常犯的错误是把omo藏到别处。F4 用两条空结果证明没有:

rg -n '"omo":' package.json rg -rn 'bin/omo\.js' --glob '!node_modules'

两条命令输出均为空,说明package.json里不再有任何以omo为 key 的 bin 映射,仓库里也不存在旧的bin/omo.js专用入口文件。

4. 防抢注:omo名字被保留而非释放

删除旧命令不等于放弃旧名字。若直接将omo从保留名单移除,任何人都能抢注一个omo包或往安装目录里塞一个同名可执行文件,造成供应链混淆。F4 在 packages/omo-codex/src/install/codex-cache-bins.ts 中找到了防抢注机制:

const RESERVED_NESTED_BIN_NAMES = new Set([ "omo", "omo-agent-toolkit", "lazycodex", "lazycodex-ai", "oh-my-opencode", "oh-my-openagent", ])

该集合被用于安装器的嵌套 bin 解析逻辑:resolvePackageBinTarget在解析时会校验包根目录,而isNestedBinNameReserved(对应源码中的return packageRoot !== root && RESERVED_NESTED_BIN_NAMES.has(name))确保任何安装进来的插件都不能用这些名字创建嵌套可执行文件。omoomo-agent-toolkit同时留在保留集合里——前者防止旧名被冒用,后者保护新名不被插件冲突。

这与 F1 中记录的端态命名文档互相印证:omo名字被保留给未来的原生版omo-ai(即senpi + packages/*senpi*的组合产物),只是不在当前 npm 版中落地。

5. Emitted-command sweep:命令字符串审计门

范围保真校验最有技术含量的一步,是"发射命令清扫"(emitted-command sweep):用自动化测试扫描仓库中所有被 git 跟踪的文件,凡出现旧命令字符串(如omo ulw-loopomo installomo doctor)即命中,命中清单必须与人工审核过的白名单(allowlist)完全一致。

5.1 扫描器的三条正则

核心扫描逻辑位于 script/agent-command-string-scan.ts,按"发射方"分类:

export const AGENT_COMMAND_RE = /\bomo (ulw-loop|boulder)\b/g export const HUMAN_COMMAND_RE = /\bomo (install|uninstall|cleanup|doctor|run|get-local-version|version|mcp)\b/g export const BARE_BIN_RE = /(command -v omo|\/bin\/omo|=omo|\$\(which omo\))(?![\w-])/g
  • AGENT_COMMAND_RE:捕获 Agent(如 Codex/Senpi)向子进程发射的omo ulw-loopomo boulder这类程序化调用
  • HUMAN_COMMAND_RE:捕获omo installomo doctoromo get-local-version这类人可执行指令
  • BARE_BIN_RE:捕获command -v omo/bin/omo=omo$(which omo)这类裸 bin 引用——这正是 F1 审计中发现的隐蔽残留形态(packages/omo-senpi/skills/ulw-loop/references/full-workflow.md曾用command -v omo探测旧命令,因其不含omo <verb>形态而被普通 grep 漏掉)。

5.2 指纹而非行号:抗行号漂移的设计

fingerprintSource的指纹格式为文件路径: 命令字符串刻意不带行号。设计注释解释得很清楚:发布版本号戳或文档编辑会让文件下方所有行号位移,带行号的指纹会因此把绿灯变成红灯(agent-command-string-scan.ts)。同时指纹保留出现次数(如omo install x3),使"已白名单文件里新增一条旧命令"也能被感知——次数变化即指纹变化。

export function fingerprintSource(filePath: string, source: string): string[] { const counts = new Map<string, number>() for (const line of source.split("\n")) { for (const pattern of [AGENT_COMMAND_RE, HUMAN_COMMAND_RE, BARE_BIN_RE]) { for (const match of line.matchAll(pattern)) { const key = `${filePath}: ${match[0]}` counts.set(key, (counts.get(key) ?? 0) + 1) } } } return [...counts.entries()].map(([key, count]) => (count === 1 ? key : `${key} x${count}`)) }

5.3 被跟踪文件的遍历方式

扫描范围通过git ls-files -z获取,而不是简单地递归目录——这样保证只扫被版本控制跟踪的文件,天然排除 node_modules、构建产物与本地杂散文件(agent-command-string-scan.ts)。isExcluded对审计基础设施自身、CHANGELOG.md.omo/证据目录、node_modules/install-dist/dist等做显式排除。

需要特别指出:F4 当时记录的失败正是"审计门扫描了它自己的白名单文件"——allowlist 的每条记录本身都包含旧命令字符串,导致 33 次自命中(self-scan),审计门永远无法通过。该缺陷随后被修复:isExcluded现在把script/agent-command-string-audit.allowlist.json本身加入排除列表(当前源码 agent-command-string-scan.ts 的第一行判断),与既有 CHANGELOG/.omo 排除模式保持一致。这一"门禁不能扫描自己"的教训,恰恰说明了审计门测试的真实性——它不是摆样子的,确实会因为自身缺陷而变红。

5.4 审计测试:四类白名单 + 零容忍债务门

审计门本体在 script/agent-command-string-audit.test.ts,将白名单划分为四个类别:

const ALLOWLIST_CATEGORIES = ["emit-migrate", "test-expectation", "input-compat-preserve", "docs"] as const

各类别语义:

类别含义当前条目数
emit-migrate待迁移的旧命令发射点(债务)0(必须恒为 0)
test-expectation测试中对旧命令的期望断言(债务)0(必须恒为 0)
input-compat-preserve为兼容旧输入而有意保留的旧命令解析逻辑(合法)15
docs文档/说明中不可避免的历史提及(合法)31

测试断言了三条核心不变量(agent-command-string-audit.test.ts):

  1. 债务门为零emit-migratetest-expectation必须为空数组,任何人在此新增条目都会让门变红——这是刻意设计的"债务追踪",防止把迁移工作无限期推迟;
  2. 全量比对collectHits()的扫描结果必须与四个类别合并后的白名单完全相等(排序后比对),多一个命中或少一条白名单都会失败;
  3. 条目唯一:所有白名单条目不得重复,且不得携带行号钉/^[^:]+:\d+:/匹配即失败),确保文档与发布戳的行号位移不会误伤发布门禁。

5.5 当前白名单的合法存量

对照当前 script/agent-command-string-audit.allowlist.json,input-compat-preserve中的条目指向旧输入解析逻辑,例如:

  • packages/omo-codex/plugin/components/ulw-loop/src/steering.ts: omo ulw-loop——旧输入解析器;
  • packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts: omo ulw-loop——Codex hook 对旧命令的兼容;
  • script/lazycodex-published-smoke-workflow.test.ts: omo install x3——发布冒烟测试对旧命令的回归断言。

这些是"旧输入仍被接受"这一设计承诺的直接证据:改名 PR 的 guardrail 明确要求"不得丢弃旧形式输入的接受能力",解析器必须继续识别omo ulw-loop这样的旧输入(见 F1.md 中packages/omo-codex/plugin/components/ulw-loop/src/steering.tscodex-hook.ts同时保留新旧两种形式)。docs类别则记录.agents/skills/codex-qa/SKILL.mdAGENTS.mdpackages/omo-codex/README.md等文档中不可避免的历史命令提及。

6. 让门禁真正落地:本地复现与验收清单

读者可以在当前仓库中复现整套校验:

# 1. 确认 bin 终态(应无 omo、恰为五别名) jq -c '.bin | keys' package.json # 2. 运行命令字符串审计门(应全绿) bun test script/agent-command-string-audit.test.ts # 3. 运行扫描器自身的指纹单测 bun test script/agent-command-string-scan.test.ts

其中 agent-command-string-scan.test.ts 的三组用例分别验证了三个关键行为:行号漂移不影响指纹、同一白名单文件内新增重复出现会使指纹变化、全新文件中的旧 Agent 命令会被按路径报告。这三个用例配合审计门,构成"扫描器正确 + 门禁不扫自己 + 全仓库无幽灵命令"的完整闭环。

7. 方法论提炼:这套验证流程如何复用到其他改名任务

从 F4 这份证据文件可以提炼出一套与具体项目无关的 CLI 改名验收清单:

  1. 先定边界再验证:用 diff stat 明确总体量,用"负面清单"正则证明无关模块零改动;
  2. 删除必须有机器证据jq -e的退出码、rg的空输出,比"人工确认已删除"更可信;
  3. 旧名字要"留名不留命令":通过保留名集合防抢注,同时把旧名字的最终去向(如保留给未来版本)写进文档;
  4. 命令字符串扫描要按发射方分类:Agent 发射、人类指令、裸 bin 引用三种形态分开正则,避免command -v omo这类非动词形态漏网;
  5. 白名单即契约:合法保留的旧命令(输入兼容、文档历史)显式入白名单,并让"新增债务类别"恒等于零;
  6. 门禁自身也要被审计:扫描器不得扫描自己的白名单与测试文件,否则会产生永久红灯的伪门禁。

这套方法在 oh-my-openagent 中的实际产物就是 F4.md 及同目录下的 F1(计划合规)、F2(代码质量)、F3(真实环境 QA)四份证据文件——它们共同构成了一次大规模 CLI 改名的完整可追溯审计链,任何一步的 REJECT 都会阻止合并,直到证据补齐。

结语

omoomo-agent-toolkit的改名看似只是package.json里一行字符串的增删,但 oh-my-openagent 用六维校验证明:一次"干净的"改名,必须有删除证据、边界证明、防抢注保留和全量命令扫描四重保障。F4 这份范围保真检查文档及其背后的审计门实现(agent-command-string-scan.ts + agent-command-string-audit.test.ts),为任何面临 CLI 改名、命令退役或入口整合的工程团队提供了一份可直接照抄的实践模板。

【免费下载链接】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),仅供参考

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

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

立即咨询