OmXomx autoresearch命令全面校验:Thin-Supervisor 平价运行模型剖析
【免费下载链接】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
omx autoresearch是 OmX(Oh My codeX)中用于驱动“多轮 Codex 实验迭代”的命令面,其核心设计是薄监督器(thin supervisor)模式:每次迭代只启动一个 Codex 实验会话,而保持(keep)、丢弃(discard)、回滚(reset)的决策闭环由 OmX 运行时自己持久化。本指南以 docs/contracts/autoresearch-command-review.md 的校验记录为主线,结合 docs/contracts/autoresearch-command-contract.md 的契约、src/autoresearch/runtime.ts 的实现与配套测试,完整还原这条命令的 CLI 形态、运行时状态权威分层、决策策略、恢复语义与验证方法,帮助你在自己的仓库里复现这套“一个会话一次实验、监督器掌管持久循环”的平价模型。
背景:为什么需要 Thin-Supervisor 模型
在 Agent 驱动的自动化研究中,最典型的失控场景是:启动一个长期存活的 Codex 会话让它“一直改进”,会话内部反复自我循环,既没有明确的停止条件,也没有可审计的迭代记录。OmX 的 autoresearch 采用相反的思路——把循环的控制权从 Agent 会话手里拿回运行时。
其核心约定一句话可以概括:每一次迭代,Codex 会话只做一轮实验并写一个候选产物(candidate artifact),随后立即退出;是否保留这次改动、是否回滚、是否启动下一轮,全部由 OmX 运行时依据持久化的账本和评估器(evaluator)的 JSON 输出决定。
这条命令面由两份文档共同锚定:
- docs/contracts/autoresearch-command-contract.md:定义 CLI、mission/sandbox 契约、运行时模型、候选产物契约、决策策略与 resume 语义;
- docs/contracts/autoresearch-command-review.md:2026-03-14 由 worker-3 评审车道完成的全面校验记录,确认实现与 PRD/测试规格在平价语义上已对齐,并给出剩余的可选优化点。
CLI 形态与参数面
命令形式
契约文档定义了三种入口:
omx autoresearch <mission-dir> [codex-args...] omx autoresearch --resume <run-id> [codex-args...] omx autoresearch --help参数解析逻辑位于 src/cli/autoresearch.ts 的parseAutoresearchArgs,其解析分支如下:
| 首个参数 | 行为 |
|---|---|
| (空) | 进入 guided 引导流程(guided: true),不直接启动 |
init | 解析为 guided 引导 + 透传initArgs |
--help/-h/help | 输出帮助文本 |
--resume <run-id> | 恢复指定 run-id,其余参数作为 codex 透传参数 |
--resume=<run-id> | 等价于上者 |
run <mission-dir> | 显式 run 子命令形态 |
以-开头 | 按引导参数解析(seed args) |
| 其他 | 首参作为missionDir,其余作为 codex 透传参数 |
值得注意的是normalizeAutoresearchCodexArgs(src/cli/autoresearch.ts)会做 codex 参数规整:把MADMAX_FLAG与CODEX_BYPASS_FLAG去重,并确保最终一定注入 bypass 标志——这保证了每次启动的会话都是受控的独立实验会话,而不是递归触发外部钩子。
关于命令面的现状说明
需要澄清一个容易混淆的时点问题:评审文档(2026-03-14)记录的是一次已完成的平价校验,当时的命令面处于活跃可用状态;而在当前仓库的源码里,src/cli/autoresearch.ts顶部已经带有 hard-deprecation 消息(src/cli/autoresearch.ts),指向迁移路径:
- 用
$autoresearchskill 使用 hook-native 的持久循环; - 用
$deep-interview --autoresearch在执行前创建/打磨 mission 产物(规范产物写入.omx/specs/autoresearch-{slug}/)。
因此,本文描述的命令形态属于该功能的历史契约与实现语义,可用于理解底层运行时模型与迁移背景;新项目应优先采用 skill 入口。这与评审文档“reviewer lane 校验通过、后续仅剩可选清理项”的结论并不冲突——它正是平价模型曾被打通的证据。
Mission / Sandbox 契约:一次迭代的实验边界
<mission-dir>必须位于 git 仓库内,且必须包含两个文件:
mission.md:任务说明,随每次迭代写入会话指令;sandbox.md:沙箱策略 + 评估器契约,YAML frontmatter 必须定义:
--- evaluator: command: node scripts/eval.js format: json keep_policy: score_improvement # 可选:score_improvement | pass_only --- <沙箱边界说明>契约与解析逻辑在 src/autoresearch/contracts.ts:
evaluator.command:必填,评估器命令行(以 shell 方式在 worktree 内执行);evaluator.format:必填且当前版本只接受json(src/autoresearch/contracts.ts 定义format: 'json'常量校验);evaluator.keep_policy:可选,取值score_improvement(默认)或pass_only,由parseKeepPolicy严格校验(src/autoresearch/contracts.ts)。
评估器的 stdout 必须是合法 JSON 对象,包含必填布尔pass与可选数值score。parseEvaluatorResult(src/autoresearch/contracts.ts)会逐项校验:必须是 JSON 对象、pass必须是布尔、score出现则必须是数字,任何一项不满足都会抛出带明确诊断信息的错误。
从源码结构看,frontmatter 解析采用轻量的逐行 YAML 子集实现(parseSimpleYamlFrontmatter,src/autoresearch/contracts.ts),支持顶层键与二级 section(如evaluator块),不支持数组等复杂结构,这提醒你在编写sandbox.md时保持 frontmatter 的扁平简单。
运行时模型:Repo-Root 权威 vs Worktree 本地状态
运行时实现位于 src/autoresearch/runtime.ts,采用清晰的“状态权威分层”:
一次全新启动创建的结构
| 对象 | 位置 | 职责 |
|---|---|---|
| 分支 | autoresearch/<mission-slug>/<run-tag> | run-tagged 实验分支 |
| worktree | <repo>.omx/worktrees/autoresearch-<mission-slug>-<run-tag> | 隔离实验工作区 |
| 活跃运行锁 | .omx/state/autoresearch-state.json | 仅作为 active-run 指针/锁 |
| run 目录 | .omx/logs/autoresearch/<run-id>/ | 权威 per-run 产物 |
run 目录内包含(见prepareAutoresearchRuntime中 src/autoresearch/runtime.ts 的路径构造):
manifest.json:权威 per-run 状态(schema_version、run_id、mission 路径、baseline/last_kept commit、keep_policy、status 等完整字段,见 src/autoresearch/runtime.ts 的AutoresearchRunManifest);candidate.json:刚结束的 Codex 会话写回的候选产物(交接点);iteration-ledger.json:可持久化的迭代历史账本(entries数组,schema_version: 1);latest-evaluator-result.json:最近一次评估器输出;bootstrap-instructions.md:每次启动/恢复时生成的会话指令快照。
worktree 本地则只保留两类运行时产物:results.tsv与可选评估日志(如run.log),且这些运行时生成的文件必须通过 worktree 本地的.git/info/exclude排除(AUTORESEARCH_WORKTREE_EXCLUDES = ['results.tsv', 'run.log', 'node_modules', '.omx/'],src/autoresearch/runtime.ts)。ensureRuntimeExcludes(src/autoresearch/runtime.ts)会在启动与恢复时把上述模式写入git info/exclude,确保 reset 安全检查不会把运行时产物误判为污染。
results.tsv 的格式
AUTORESEARCH_RESULTS_HEADER = 'iteration\tcommit\tpass\tscore\tstatus\tdescription\n'(src/autoresearch/runtime.ts)。每一轮迭代追加一行,其中 iteration 从 0 开始,第 0 行是 baseline 记录,后续行对应各次候选评估。
模式状态(mode state)集成
autoresearch 是 OmX 模式生命周期体系的一员——src/modes/base.ts 的ModeName类型明确列出autoresearch。prepareAutoresearchRuntime会调用startMode('autoresearch', taskDescription, 1, projectRoot)并把current_phase依次置为evaluating-baseline→running,同时把 mission、run、各产物路径、keep_policy 等写入模式状态(src/autoresearch/runtime.ts)。模式状态记录在仓库根的.omx/state下,与 active-run 锁配合实现互斥。
单次迭代的指令快照
每次启动或恢复都会由writeInstructionsFile生成bootstrap-instructions.md,内容由buildAutoresearchInstructions(src/autoresearch/runtime.ts)拼装,包含:
- Run ID、mission/sandbox 文件路径、mission slug、迭代号;
- baseline commit、last kept commit、last kept score;
- results 文件与 candidate 产物路径;
- keep policy;
- 迭代状态快照(JSON):
iteration、baseline_commit、last_kept_commit、last_kept_score、previous_iteration_outcome、recent_ledger_summary、keep_policy; - 明确的“薄监督器”操作指令:“恰好执行一轮实验周期(exactly one experiment cycle),最多产生一个候选 commit,写完 candidate artifact JSON 后退出,禁止在会话内无限循环”;
- 候选产物契约字段说明;
- 评估器契约(command、format=json、输出 pass 布尔与可选 score);
- mission 内容与 sandbox 策略正文(超长内容被截断到 4000 字符,
trimContent,src/autoresearch/runtime.ts)。
previous_iteration_outcome与recent_ledger_summary由buildAutoresearchInstructionContext从账本读取(最近最多 3 条,reason 截断 160 字符、description 截断 120 字符),保证每个新会话都知道上一轮发生了什么。
候选产物契约:会话与监督器的交接点
Codex 会话退出前必须把 JSON 写到candidate.json,字段契约(src/autoresearch/runtime.ts):
| 字段 | 类型 | 说明 |
|---|---|---|
status | candidate \| noop \| abort \| interrupted | 会话侧结论 |
candidate_commit | string \| null | status=candidate 时必填非 null |
base_commit | string | 编辑前的基线提交 |
description | string | 一句话摘要 |
notes | string[] | 备注数组 |
created_at | ISO 时间戳 | 创建时间 |
完整性校验由parseAutoresearchCandidateArtifact与validateAutoresearchCandidate(src/autoresearch/runtime.ts)双重把关,核心不变量:
candidate_commit必须在 git 中可解析(git rev-parse --verify <ref>^{commit}),且必须等于会话退出时 worktree 的HEAD;base_commit必须在 git 中可解析,且必须等于监督器提供的last_kept_commit。
这两条规则杜绝了“谎报 commit”与“在错误基线上提交”两类作弊路径。
决策策略:keep / discard / reset 闭环
decideAutoresearchOutcome(src/autoresearch/runtime.ts)是决策核心,完整策略如下:
| 输入 | 决策 | 行为 |
|---|---|---|
status=abort | abort | 停止运行,不 reset,run 状态置为stopped |
status=noop | noop | 记录 noop 迭代,默认继续启动下一轮 |
status=interrupted | interrupted | 检查 worktree:脏则停止等待人工介入;干净则记录后继续 |
| 评估器 error/崩溃 | discard | 回滚 |
pass=false | discard | 回滚 |
pass_only且pass=true | keep | 直接保留 |
score_improvement且 pass 无可比数值 score | ambiguous | 回滚(要求可比数值分数) |
score_improvement且 score 提升 | keep | 保留并更新last_kept_commit/last_kept_score |
score_improvement且 score 未提升 | discard | 回滚 |
关键点:
- baseline 行永远被记录:
seedBaseline(src/autoresearch/runtime.ts)在启动时对初始提交跑一次评估器,写入results.tsv第 0 行与账本 baseline 条目,last_kept_score只在 baseline pass 且带数值时记录; - 所有 discard / ambiguous / error 路径都
reset --hard到last_kept_commit:resetToLastKeptCommit(src/autoresearch/runtime.ts)在 reset 前先执行assertResetSafeWorktree,只允许排除清单内的运行时产物存在,否则报autoresearch_reset_requires_clean_worktree:<path>:<blocking lines>并终止。
processAutoresearchCandidate(src/autoresearch/runtime.ts)串起完整流程:读候选 → 校验 → 非 candidate 状态走recordNonEvaluatedCandidateStatus→ candidate 状态跑评估器 → 决策 → keep 则推进 last_kept,否则 reset → 写 results/ledger → 写回 manifest → 生成下一轮指令。
并发锁与 Fresh-Run 语义
- 活跃运行锁:
.omx/state/autoresearch-state.json保存{active, run_id, mission_slug, ...}。assertAutoresearchLockAvailable(src/autoresearch/runtime.ts)在启动与恢复前都会检查,若state.active && state.run_id存在则直接抛autoresearch_active_run_exists:<run-id>,阻止并发二次启动; - fresh-run 语义:每次全新启动都会由
buildAutoresearchRunTag(src/autoresearch/runtime.ts,ISO 时间戳去符号化)生成 run-tag,再由buildRunId组合成${missionSlug}-${runTag.toLowerCase()}。run 目录、分支、worktree 全部按 run-id/run-tag 命名,因此不会静默复用一条长期存活的 lane; - 命名规划的统一入口:
src/team/worktree.ts的规划函数按 scope 区分命名(src/team/worktree.ts):scope === 'autoresearch'时分支为autoresearch/<sanitized-name>/<runTag>、worktree 为.omx/worktrees/autoresearch-<sanitized-name>-<runTag>。配套测试 src/team/tests/worktree.test.ts 明确断言分支名autoresearch/demo-mission/20260314t000000z与 worktree 路径后缀autoresearch-demo-mission-20260314t000000z; - 模式互斥:启动前还会检查
readModeState('autoresearch', projectRoot),若已有 active 模式则抛autoresearch_active_mode_exists:<run-id>,与锁文件形成双重保护。
Resume 契约与失败条件
resumeAutoresearchRuntime(src/autoresearch/runtime.ts)从--resume <run-id>恢复运行,先加载manifest.json(loadAutoresearchRunManifest,src/autoresearch/runtime.ts),随后必须通过以下失败检查,每种都给出可操作的错误码:
| 失败条件 | 错误 |
|---|---|
| manifest 缺失 | autoresearch_resume_manifest_missing:<run-id> |
| worktree 缺失 | autoresearch_resume_missing_worktree:<path> |
| worktree 在排除清单外存在脏改动 | autoresearch_reset_requires_clean_worktree:... |
manifest 已终结(非running) | autoresearch_resume_terminal_run:<run-id> |
恢复成功后,从last_kept_commit与既有 results 历史继续推进,并重新生成带最新账本摘要的指令文件。运行终结统一走finalizeRun(src/autoresearch/runtime.ts):写回status/stop_reason/completed_at,模式状态置非活跃,active-run 锁解除(deactivateAutoresearchRun)。
测试验证:平价语义如何被钉死
评审记录列出的验证命令如下:
npm run build node --test dist/autoresearch/__tests__/runtime.test.js \ dist/cli/__tests__/autoresearch.test.js \ dist/cli/__tests__/index.test.js \ dist/cli/__tests__/nested-help-routing.test.js \ dist/team/__tests__/worktree.test.js \ dist/modes/__tests__/base-autoresearch-contract.test.jssrc/autoresearch/tests/runtime.test.ts 是核心覆盖,值得重点阅读的用例:
- 指令构建:断言
buildAutoresearchInstructions包含“exactly one experiment cycle”、pass/score输出契约、迭代状态快照等关键语义(src/autoresearch/tests/runtime.test.ts); - reset 安全检查:验证
.omx下的 untracked 运行时文件不会阻断 reset-safe 检查(src/autoresearch/tests/runtime.test.ts); - 运行时产物与模式状态:验证 manifest、ledger、latest-evaluator、results、指令文件全部落盘,baseline 行
0\t...\ttrue\t1\tbaseline\tinitial baseline evaluation正确写入,模式状态active=true / current_phase=running(src/autoresearch/tests/runtime.test.ts); - keep/discard 闭环(最关键的端到端用例,src/autoresearch/tests/runtime.test.ts):先提交 score=2 的改进候选 →
processAutoresearchCandidate返回keep,last_kept_commit前进到改进提交;再提交 score=1 的回退候选 → 返回discard,worktreeHEAD被reset --hard回改进提交;最终 results 出现1\t...\ttrue\t2\tkeep\timproved score与2\t...\ttrue\t1\tdiscard\tworse score两行,账本顺序为baseline → keep → discard,且下一轮指令的previous_iteration_outcome正确携带discard:score did not improve。
此外还有src/autoresearch/__tests__/runtime-parity-extra.test.ts、src/autoresearch/__tests__/contracts.test.ts以及 eval 脚本src/scripts/eval/eval-parity-smoke.ts、src/scripts/eval/eval-candidate-handoff.ts、src/scripts/eval/eval-fresh-run-tagging.ts、src/scripts/eval/eval-resume-dirty-guard.ts等,覆盖 fresh-run 标签、候选交接、恢复脏保护等平价面。
评审结论与遗留风险
评审记录(docs/contracts/autoresearch-command-review.md)给出的结论是:实现已不再是早期 v1 scaffold,与 thin-supervisor 平价模型大体一致,共享的 help/测试措辞不一致问题已解决。同时留下三条可选跟进项:
runAutoresearchLoop()每轮迭代通过execFileSync('cat', ...)+JSON.parse从 manifest 回读 run-id,功能正确但略显笨拙,可简化以避免 shell 调cat;- 焦点测试覆盖了主要平价面,但
noop、abort、interrupted与显式pass_only策略分支仍有扩展空间; - 该车道只验证了焦点平价覆盖与构建状态,未跑完整仓库级测试/lint 套件。
对照当前源码,第一点在现有processAutoresearchCandidate流程中已通过函数参数直传 manifest 的方式得到缓解(不再依赖 shell 回读),说明这些遗留项属于演进中的常规打磨。
结语:平价模型的三条启示
omx autoresearch的完整评审链条(契约 → 评审 → 实现 → 测试)对设计任何 Agent 自动化循环都有借鉴价值:
- 循环归监督器:会话只负责“一轮实验 + 写产物”,循环、决策、回滚全部由外部运行时掌控,天然可审计、可中断、可恢复;
- 状态权威分层:repo-root 的
manifest.json是权威真相,autoresearch-state.json只是锁,worktree 只留运行时产物并显式排除——层次清晰,冲突面最小; - 决策可验证:候选产物有完整性校验(commit 可解析、与 HEAD/last_kept 对齐),决策策略有显式表格(keep/discard/ambiguous/noop/abort/interrupted),每轮结果都落进
results.tsv与账本,形成可回放的历史。
若要继续深入,建议阅读 docs/contracts/autoresearch-command-contract.md 获取契约原文,配合 src/autoresearch/runtime.ts 与 src/autoresearch/tests/runtime.test.ts 逐行对照;迁移到新命令面时,参考 src/cli/autoresearch.ts 顶部的弃用指引,改用$autoresearchskill 与$deep-interview --autoresearch。
【免费下载链接】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),仅供参考