
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 仓库中omo→omo-agent-toolkit这一 CLI 入口改名事件展开深度讲解该仓库如何用范围保真校验Scope-Fidelity Check证明一次大规模改名既删除了旧命令、又未越界触碰无关模块。你将掌握一套可复用的验证方法论用git diff统计与排除项证明改动边界、用jq输出 Removal Proofs删除证据、用保留名集合防抢注、以及用命令字符串审计门agent-command-string audit gate扫描全部被跟踪文件杜绝任何遗留的旧命令发射点。1. 背景为什么要给 CLI 改名做范围保真校验oh-my-openagentnpm 包名oh-my-opencode的 CLI 曾以omo作为默认入口同时保留oh-my-opencode、oh-my-openagent、lazycodex、lazycodex-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.ts59、script/bin-map.test.ts34 等新文件均为审计门基础设施。这为后续所有检查划定了讨论范围。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.json、hooks/hooks.json等。这套负面清单思想非常关键审查者不仅要知道改了什么还要证明没改什么。结合 F1.md 的完整计划合规审计表该 PR 对 18 条Must NOT have / guardrails逐条给出了 PASS/FAIL 证据包括无 npm 包改名无 marketplace 身份改名保留omosisyphuslabs无OMO_*环境变量改名仅新增OMO_EDITION等。3. Removal Proofs用 jq 给出旧命令确实没了的证据改名验证的核心不是我觉得删了而是机器可验证的删除证据。F4 用两条jq命令完成jq -e .bin.omo package.json; echo exit$?输出null exit1jq -e在取值不存在时退出码为 1因此exit1本身就是.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 的实际状态name为oh-my-opencodeversion为5.0.0-beta.69bin字段恰为五个入口且全部指向共享入口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)确保任何安装进来的插件都不能用这些名字创建嵌套可执行文件。omo和omo-agent-toolkit同时留在保留集合里——前者防止旧名被冒用后者保护新名不被插件冲突。这与 F1 中记录的端态命名文档互相印证omo名字被保留给未来的原生版omo-ai即senpi packages/*senpi*的组合产物只是不在当前 npm 版中落地。5. Emitted-command sweep命令字符串审计门范围保真校验最有技术含量的一步是发射命令清扫emitted-command sweep用自动化测试扫描仓库中所有被 git 跟踪的文件凡出现旧命令字符串如omo ulw-loop、omo install、omo 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-])/gAGENT_COMMAND_RE捕获 Agent如 Codex/Senpi向子进程发射的omo ulw-loop、omo boulder这类程序化调用HUMAN_COMMAND_RE捕获omo install、omo doctor、omo 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 Mapstring, 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必须恒为 0test-expectation测试中对旧命令的期望断言债务0必须恒为 0input-compat-preserve为兼容旧输入而有意保留的旧命令解析逻辑合法15docs文档/说明中不可避免的历史提及合法31测试断言了三条核心不变量agent-command-string-audit.test.ts债务门为零emit-migrate与test-expectation必须为空数组任何人在此新增条目都会让门变红——这是刻意设计的债务追踪防止把迁移工作无限期推迟全量比对collectHits()的扫描结果必须与四个类别合并后的白名单完全相等排序后比对多一个命中或少一条白名单都会失败条目唯一所有白名单条目不得重复且不得携带行号钉/^[^:]:\d:/匹配即失败确保文档与发布戳的行号位移不会误伤发布门禁。5.5 当前白名单的合法存量对照当前 script/agent-command-string-audit.allowlist.jsoninput-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.ts与codex-hook.ts同时保留新旧两种形式。docs类别则记录.agents/skills/codex-qa/SKILL.md、AGENTS.md、packages/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 改名验收清单先定边界再验证用 diff stat 明确总体量用负面清单正则证明无关模块零改动删除必须有机器证据jq -e的退出码、rg的空输出比人工确认已删除更可信旧名字要留名不留命令通过保留名集合防抢注同时把旧名字的最终去向如保留给未来版本写进文档命令字符串扫描要按发射方分类Agent 发射、人类指令、裸 bin 引用三种形态分开正则避免command -v omo这类非动词形态漏网白名单即契约合法保留的旧命令输入兼容、文档历史显式入白名单并让新增债务类别恒等于零门禁自身也要被审计扫描器不得扫描自己的白名单与测试文件否则会产生永久红灯的伪门禁。这套方法在 oh-my-openagent 中的实际产物就是 F4.md 及同目录下的 F1计划合规、F2代码质量、F3真实环境 QA四份证据文件——它们共同构成了一次大规模 CLI 改名的完整可追溯审计链任何一步的 REJECT 都会阻止合并直到证据补齐。结语omo→omo-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),仅供参考