切换外观
判断评测:换用 Codex Harness 的对照(2026-10-15)
状态:一次性评测记录。结论只适用于本次设置:一个情境、teacher-forced 逐帧评测、每个条件只跑一次(另加 12 帧的对照重跑)。它不是 Skill 的验收标准,也不改变信息契约。方法与指标口径沿用第一次评测,下文只写出不同之处。
上一次用 claude -p 跑 claude-opus-5-5。这一次把同一份提示交给 OpenAI Codex CLI(codex exec)下的 gpt-6.1-sol,并补了一个同一 harness、较小模型的对照 claude-haiku-5-5。比较四次全量运行:
| 简称 | 模型 / Harness | SKILL.md | run-id |
|---|---|---|---|
| Opus | claude-opus-5-5 / claude -p | 第一版(012f4ad) | full-2026-10-14 |
| Haiku | claude-haiku-5-5 / claude -p | 第一版 | haiku-skill1-2026-10-15 |
| Sol·一 | gpt-6.1-sol / codex exec | 第一版 | codex-sol-skill1-2026-10-15 |
| Sol·二 | gpt-6.1-sol / codex exec | 第二版(8af097a) | codex-sol-skill2-2026-10-15 |
Opus、Haiku 与 Sol·一的条件完全相同:36 帧的用户提示、系统提示与输出 schema 逐字节一致(已逐帧核对)。Sol·一 与 Sol·二 之间只换了 SKILL.md。作者的编排不是标准答案,“与作者一致”只表示与同一团队写下的一种合理整理相同。
结论
在这个基准上,换 Harness 和模型后,处置几乎不变;变化主要在档位、kind、结构习惯和提交失败的形态上。按单一指标说不出哪个更强。
- 处置几乎相同。 112 条输入中,Opus 与 Sol·一 有 109 条处置相同,两者与作者的一致率分别是 91% 和 90%。Haiku 也是 91%,没有掉下来。
- 档位与 kind 上,Sol·一 与作者更接近,但幅度和随机差异相当。 档位完全一致:Sol·一 53%,Opus 48%,Haiku 38%;kind 一致:76%、72%、58%。同一配置下 Codex 重跑一次,抽查帧上仍有约 15% 的条目档位不同。只有在四次 Codex 运行中方向都一致的差异,才算模型习惯(见“两个 Harness 判断不同的帧”)。
- 提交失败的形态完全不同。 Opus 两次被拒,都是只列出部分
children。Sol 两版各有 7 帧首次被拒,没有一次是部分列表:一类是把children: null当作“不改”(契约里它表示清空子层),另一类是降档却漏写reason。Sol·二 的 f27 连续三次漏写reason,最终这一帧没有写入任何东西。Haiku 一次也没被拒。 - 提示合成方式不能解释差异。 codex 没有单独的系统提示参数,主跑把系统提示和用户提示合成为一条消息。另用
model_instructions_file把系统提示放回系统位置,在 12 帧上对照:两种放法之间的差别,与合成方式下重跑一次的差别同一量级;两种放法都没有让 Sol 更接近 Opus。children: null在两种放法下都出现。 - 上次 Opus 的四个弱点。 f23 的“一事两写”在六次运行中全部出现,更像情境或指引的问题,而不是某个模型的问题。f30 的“一事两写”在 Opus、Haiku、Sol·二 出现,Sol 第一版的三次运行都没有出现。按原 ID 恢复撤下事项(f19)只有 Sol·二 做到。f12 把“验证”写成“已修复”只有 Opus 出现;Sol·一 的 kind 仍是 done,但标题保留了验证范围。Sol 的五次运行都没有建三层子树,只有一次在 f01 建了一层子项。
- 第二版指引在 Sol 上有得有失。 上次报告说重跑前先比较三个数:首次被拒 7 → 7,一事两写 1 → 2,无变化帧的摘要改写 1 → 0。另外,f12、f19 改对了;处置一致率从 90% 降到 86%,原因是第二版把“确认原结论仍成立”归入
used,重复提醒被改判为used。
方法与条件
| 项 | 设置 |
|---|---|
| 情境、帧与评分 | 与上次相同:prototype/scenario.mjs 的 36 帧、112 条输入,teacher-forced,指标口径不变。评测前用 --dry-run 核对,36 帧用户提示与上次逐字节相同。 |
| 用户背景 | 用情境原文,没有用 --persona-context。上次全量运行也是原文,这样四次运行条件相同。上次报告提到原文剧透:Opus 在 f01 写出了还没发生的“反复改期”;其余五次运行的 f01 都没有类似表述。 |
| Codex 调用 | codex exec -m gpt-6.1-sol,CLI codex-cli 0.162.1,推理强度为模型默认(模型目录里写的是 medium)。用 --output-schema 约束结构,-o 取最后消息,--json 事件流落盘并从中取 token 用量。完整参数记在各运行 meta.json 的 invocation。 |
| Codex 隔离 | 每次调用在 run_dir/codex/ 下新建空工作目录,并加 -s read-only、--ephemeral、--skip-git-repo-check、--ignore-user-config。另外三项是用探针发现问题后补的,见下文。四次 Codex 运行都没有出现任何工具调用(事件流里没有非消息条目)。 |
| 提示合成 | 主跑把系统提示与用户提示的原文用 ======== 系统提示 ======== / ======== 用户消息 ======== 两节合成一条用户消息,codex 自带的基础指令(约 4k token)保留。对照运行改用 --codex-system instructions,经 model_instructions_file 让系统提示替换基础指令,用户消息只含用户提示。 |
| Haiku | claude -p --model claude-haiku-5-5,其余与 Opus 相同;由协调方另行运行,本报告只用 --rescore 重新计分,结果不变。 |
| 中断与续跑 | Sol·一 跑完 10 帧后,ChatGPT 登录被服务端结束(401 token_revoked / refresh_token_invalidated)。此前的成功调用都没有刷新 token 的记录,原因不明。脚本按设计停下并保留已完成的帧。重新登录后用 --resume 续跑其余 26 帧,条件一致;帧之间互不依赖,续跑不影响可比性。 |
| 规模 | Sol·一 43 次调用、Sol·二 45 次、两次 12 帧对照共 29 次,都走登录账号的额度,没有撞上速率限制。 |
探针发现的三处泄漏,以及补上的设置。 下面三项都先用最小调用验证过:
- 项目说明。 工作目录在仓库的
.local/eval/下,codex 会沿目录向上找到并加载仓库根的AGENTS.md,模型能逐字引用其第一行。加-c project_doc_max_bytes=0后,模型回答“没有项目说明”。 - 工具。 默认情况下,模型能执行
pwd和ls ..,看到仓库路径。关掉 shell、unified_exec、code mode、apps、网页搜索等功能后,调用这些工具都会失败。这对应claude -p路径的--tools ''。 - 环境上下文。 codex 会注入真实日期(2026-10-15)、时区与工作目录路径。这个日期正好落在情境(10-12 至 10-25)的中段,可能和提示里的
now相互干扰。加-c include_environment_context=false后不再注入。
新增的两个计数。 两者都由人逐帧核对:
- 一事两写:同一事实同时写进一个已有条目和一个新条目,两者都占份额。候选按“新建条目与本批补丁条目引用同一输入”筛出,再人工判断。
- 无变化帧改写:只确认原结论仍成立的输入(f06),却引起摘要改写。f14、f27 作者是空批次,各运行的改动都有依据(当轮回应批注、提高当晚面谈;Sol·二 的 f27 被拒,没有写入),不计入。
token 归一为输入(含缓存)、输出(含推理)两项;两家 tokenizer 不同,数量只能在同一 Harness 内比较。
Harness 对比表
| 指标 | Opus / claude -p(第一版) | Haiku / claude -p(第一版) | Sol / codex(第一版) | Sol / codex(第二版) |
|---|---|---|---|---|
| 处置一致 | 102/112(91%) | 102/112(91%) | 101/112(90%) | 96/112(86%) |
| 档位完全一致 | 49/102(48%) | 38/100(38%) | 55/103(53%) | 52/101(51%) |
| 档位一档以内 | 100/102(98%) | 92/100(92%) | 97/103(94%) | 95/101(94%) |
| kind 一致 | 73/102(72%) | 58/100(58%) | 78/103(76%) | 77/101(76%) |
| 首次被拒 | 2/36 | 0/36 | 7/36 | 7/36(f27 三次都被拒,最终 35/36) |
| 超预算 | 0 | 0 | 0 | 0 |
| 一事两写 | 2(f23、f30) | 2(f23、f30),另有 f28 边界情况 | 1(f23) | 2(f23、f30) |
| 无变化帧改写(f06) | 1 | 1 | 1 | 0 |
| 每帧平均 token:输入(缓存)/ 输出(推理) | 24,884(12,534)/ 2,756(1,297) | 22,232(7,508)/ 10,055(8,731) | 28,751(2,460)/ 1,617(261) | 30,979(5,287)/ 1,493(301) |
| 终态档位一致 | 599/709(84%) | 589/709(83%) | 607/709(86%) | 586/686(85%) |
| 根层平均已用份额(作者 53.1) | 54.6 | 55.8 | 52.8 | 53.8 |
| 新建条目 根层 / 子层(作者 9 / 17) | 8 / 6 | 8 / 4 | 6 / 4 | 9 / 2 |
| 额外撤下 | f18 family-route | f04 invoice-chat、reading;f18 family-route | f18 family-route;f23 reading | f18 family-route |
| 调用次数 | 38 | 36 | 43 | 45 |
几点读法:
- Opus 与 Haiku 的输入含
claude -p结构化输出工具的一轮往返,Sol 的输入含 codex 基础指令与工具定义;token 数量只说明各自的开销,不跨 Harness 比较。 - Haiku 的输出主要是推理,平均每帧 8.7k token。
- 超预算这一行四次都是 0;但 12 帧对照的合成方式重跑里,f23 有一次首次提交超出根层 70/64,被拒后改对。
处置混淆矩阵
行是作者,列依次是 Opus / Haiku / Sol·一 / Sol·二 的判断数。
| 作者 \ Agent | used | noise | duplicate | deferred |
|---|---|---|---|---|
| used(84) | 83 / 84 / 83 / 83 | 0 / 0 / 0 / 0 | 0 / 0 / 0 / 0 | 1 / 0 / 1 / 1 |
| noise(12) | 0 / 0 / 0 / 1 | 11 / 10 / 9 / 9 | 0 / 0 / 0 / 0 | 1 / 2 / 3 / 2 |
| duplicate(10) | 2 / 2 / 1 / 7 | 1 / 3 / 1 / 1 | 5 / 5 / 6 / 2 | 2 / 0 / 2 / 0 |
| deferred(6) | 1 / 1 / 1 / 1 | 2 / 2 / 2 / 3 | 0 / 0 / 0 / 0 | 3 / 3 / 3 / 2 |
used 在四次运行中几乎都一致;分歧仍集中在 duplicate、deferred、noise 三者的边界。Sol·一 多把无关通知判成 deferred(f09 纸巾到站、f29 简历查看率),Sol·二 把 7 条 duplicate 判成 used(见“第二版指引”一节)。
逐帧
“处置一致”与“档位一致”按 Opus · Haiku · Sol·一 · Sol·二 排列。“结果类型”中 c 表示 commit,k 表示 checked,拒表示最终被拒。
| 帧 | 处置一致 | 档位一致 | 结果类型 作者→四次 | 尝试 Sol·一/Sol·二 |
|---|---|---|---|---|
| cold-01 | 3/3 · 3/3 · 3/3 · 3/3 | 0/1 · 1/1 · 0/1 · 0/1 | c→cccc | 1/1 |
| cold-02 | 3/3 · 3/3 · 3/3 · 3/3 | 2/2 · 0/2 · 2/2 · 2/2 | c→cccc | 1/1 |
| f01 | 8/9 · 9/9 · 8/9 · 8/9 | 0/6 · 1/8 · 2/7 · 4/7 | c→cccc | 1/1 |
| f02 | 3/3 · 3/3 · 3/3 · 3/3 | 2/3 · 1/2 · 3/3 · 1/2 | c→cccc | 1/1 |
| f03 | 3/3 · 3/3 · 3/3 · 3/3 | 1/1 · 1/1 · 1/1 · 1/1 | c→cccc | 1/1 |
| f04 | 3/3 · 3/3 · 3/3 · 3/3 | 2/3 · 0/2 · 2/3 · 2/3 | c→cccc | 1/1 |
| f05 | 3/3 · 3/3 · 3/3 · 3/3 | 2/6 · 2/6 · 3/6 · 2/6 | c→cccc | 1/1 |
| f06 | 3/3 · 3/3 · 3/3 · 2/3 | — | k→ccck | 1/1 |
| f07 | 3/3 · 3/3 · 3/3 · 3/3 | 2/4 · 0/5 · 1/4 · 1/5 | c→cccc | 1/1 |
| f08 | 3/3 · 3/3 · 3/3 · 3/3 | 2/5 · 2/4 · 3/5 · 2/5 | c→cccc | 1/1 |
| f09 | 3/3 · 3/3 · 2/3 · 2/3 | 2/3 · 1/3 · 2/3 · 1/3 | c→cccc | 1/1 |
| f10 | 2/3 · 2/3 · 2/3 · 2/3 | — | c→cccc | 1/1 |
| f11 | 3/3 · 3/3 · 3/3 · 3/3 | 3/4 · 2/3 · 1/4 · 1/3 | c→cccc | 2/1 |
| f12 | 3/3 · 3/3 · 3/3 · 3/3 | 6/9 · 2/8 · 5/8 · 4/8 | c→cccc | 1/1 |
| f13 | 2/3 · 2/3 · 2/3 · 2/3 | 1/3 · 2/3 · 2/3 · 2/3 | c→cccc | 1/1 |
| f14 | 4/4 · 4/4 · 4/4 · 3/4 | — | k→cccc | 2/2 |
| f15 | 2/3 · 2/3 · 3/3 · 2/3 | 2/4 · 2/4 · 2/4 · 2/4 | c→cccc | 2/3 |
| f16 | 3/3 · 3/3 · 3/3 · 3/3 | 1/2 · 1/2 · 2/2 · 2/2 | c→cccc | 1/1 |
| f17 | — | 1/1 · 1/1 · 1/1 · 1/1 | c→cccc | 1/1 |
| f18 | 3/3 · 3/3 · 3/3 · 3/3 | 3/5 · 2/5 · 2/5 · 1/5 | c→cccc | 1/1 |
| f19 | 3/3 · 3/3 · 3/3 · 3/3 | 1/3 · 0/3 · 0/3 · 0/4 | c→cccc | 2/2 |
| f20 | 3/3 · 3/3 · 3/3 · 2/3 | 0/2 · 0/2 · 1/2 · 1/2 | c→cccc | 1/1 |
| f21 | 3/3 · 3/3 · 3/3 · 3/3 | 1/2 · 2/2 · 2/2 · 1/2 | c→cccc | 1/1 |
| f22 | 3/3 · 2/3 · 3/3 · 2/3 | 1/2 · 1/2 · 1/2 · 1/2 | c→cccc | 1/2 |
| f23 | 3/3 · 3/3 · 3/3 · 3/3 | 3/4 · 1/2 · 3/3 · 4/4 | c→cccc | 1/1 |
| f24 | 3/4 · 3/4 · 3/4 · 3/4 | 2/5 · 4/5 · 2/5 · 4/5 | c→cccc | 1/1 |
| f25 | 2/3 · 3/3 · 2/3 · 2/3 | 2/3 · 1/3 · 2/3 · 2/3 | c→cccc | 2/2 |
| f26 | 2/3 · 2/3 · 2/3 · 2/3 | 0/2 · 1/2 · 0/1 · 0/1 | c→cccc | 1/1 |
| f27 | — | — | k→ccc拒 | 1/3 |
| f28 | 2/3 · 2/3 · 2/3 · 2/3 | 1/1 · 2/3 · 1/2 · 2/2 | c→cccc | 1/1 |
| f29 | 3/3 · 2/3 · 2/3 · 3/3 | 0/2 · 0/2 · 1/2 · 1/2 | c→cccc | 1/1 |
| f30 | 4/5 · 4/5 · 4/5 · 4/5 | 2/6 · 1/5 · 4/6 · 3/5 | c→cccc | 2/1 |
| f31 | 3/3 · 3/3 · 3/3 · 3/3 | 1/1 · 1/2 · 1/2 · 1/2 | c→cccc | 2/2 |
| f32 | 3/3 · 3/3 · 3/3 · 2/3 | 1/2 · 1/2 · 1/2 · 1/2 | c→cccc | 1/1 |
| f33 | 3/3 · 3/3 · 3/3 · 3/3 | 1/2 · 1/2 · 1/2 · 1/2 | c→cccc | 1/1 |
| f34 | 2/3 · 2/3 · 2/3 · 2/3 | 1/3 · 1/3 · 1/4 · 1/2 | c→cccc | 1/1 |
两个 Harness 判断不同的帧
按作者条目 ID 对齐 Opus 与 Sol·一 的匹配对(不含撤下),共比较 97 个条目的档位与 kind:
| 两边都与作者一致 | 两边都不一致 | 只有 Opus 一致 | 只有 Sol·一 一致 | |
|---|---|---|---|---|
| 档位 | 41 | 37 | 6 | 13 |
| kind | 68 | 20 | 3 | 6 |
逐项如下。“稳定”表示四次 Codex 运行(Sol·一、合成方式重跑、instructions 方式、Sol·二)方向相同;“不稳定”表示 Codex 自己的几次运行之间也不一致,这类差异看作随机。只出现在主跑中的帧,稳定性只有两次运行(Sol·一、Sol·二)可判。
- 只有 Opus 与作者一致。
- 稳定:f05
pilot-promisekind(needs-you / Sol 为 fyi);f11launch档位(high / Sol 为 normal);f17family-routekind(done / Sol 为 needs-you);f32home档位(trace / Sol 为 low)。 - 不稳定:f07
pilot、f19pilot、f11family-date、f18home-photo的档位,f30family-date的 kind。 - 处置:f09 纸巾到站、f29 简历查看率,作者与 Opus 判 noise,Sol·一 判 deferred。
- 稳定:f05
- 只有 Sol·一 与作者一致。
- 稳定:f16
home-visit档位与 kind(high / needs-you);f29expenses档位与 kind(normal / in-progress)。 - 其余:f01、f05、f13 的
launch,f02perf-sample,f08perf-repro,f20expenses,f21home-photo,f23home,f30 的handoff-owner与pilot,f32hiring的档位;f07reading、f19pilot、f30 的hiring与pilot的 kind。 - 处置:f15 旧日程提醒,作者与 Sol·一 判 duplicate,Opus 判 used。
- 稳定:f16
- 结构。 只有一边匹配上作者的条目集中在 f01(冷启动结构)、f12
perf-repro、f23/f26reading(Sol·一 在 f23 撤下了它)、f28launch、f31/f34reading。
Opus 与 Haiku 在不少条目上方向相同、与 Sol 相反(f16、f17、f29 都是如此)。这可以是 Claude 模型家族的共同习惯,也可以是 claude -p 这个 Harness 的影响;两者在本次设置里没有分开(见“合成方式的混杂有多大”)。
下面七个案例都写明各方怎么判、谁更合理,以及差异来自模型、合成方式还是随机。
1. 子层编辑:两种不同的陷阱(f11、f14、f15、f19、f31 等)
- Opus。 两次被拒都是想改一个孩子,却在父项
children里只列了它(f15、f24)。 - Sol。 两版共 11 次
explicit_withdraw_required,没有一次是部分列表,全部来自给父项补丁时写了children: null。按契约,null表示清空子层,于是所有孩子都被当作要移除。另有 6 次invalid_field是降档没写reason。 - null 的使用。 Sol 在声明里常把可选字段写成
null:Sol·一 中children9 次、due_at34 次、stale_after3 次、share2 次、sources1 次;Opus 只在due_at上用过null(21 次;其中清空已有期限的 18 处都写了理由)。 - 谁更合理。 两种都是对契约的误用。Opus 的误用来自“列出要改的孩子”的直觉。Sol 的误用来自结构化输出常见的“不适用就填 null”习惯,而契约规定省略表示保留、
null表示清空。 - 来源:模型(含其结构化输出风格),不是合成方式。 系统提示放回系统位置的对照运行里,
children: null照样出现 6 次。第二版 SKILL.md 的子层反例只针对部分列表,所以 Sol·二 的首次被拒仍是 7 次。被拒后看到回执,Sol 多数一次改对;f27 是例外,见“被拒绝的批次”。
2. f16 请邻居代开门:沿用已有子项,还是另建
- 输入。 物业说换了接头但新照片仍有水,明早回访;林苒问“明早能不能请邻居再帮一下?我不想又取消和妈妈出门”。
- 作者。 把
home-visit改为 high / needs-you,标题“厨房回访待邻居确认代开门”。 - Opus。 新建子项
home-neighbor“明早请邻居代开门待确认”(high / needs-you),同时把home-visit降为 normal / in-progress。 - Sol。 四次运行都把开门问题写进已有的
home-visit,high / needs-you,与作者一致。 - 判断:Sol 更合理。 回访与开门是同一件待落实的安排,另建条目会让它分在两处。这正是上次报告指出的 Opus 习惯:为子事实另建条目。
- 来源:模型(稳定),与合成方式无关。
instructions方式同样沿用了home-visit。
3. f29 两天的费用外推:done 还是 in-progress
- 输入。 财务说关掉测试环境后日均明显下降,外推约 5,080 元,“但才两天,不能当最终账单。明晚我再核”。
- 作者。
expensesnormal / in-progress,“短期外推5080元,尚非最终账单”。 - Opus 与 Haiku。 都写成 high / done;Opus 还新建了子项
cost-trend“外推约5080元,仅两天数据”。 - Sol。 四次运行都是 normal / in-progress,例如“API预测5080元,明晚再核”。
- 判断:Sol 更合理。 输入明说结论取决于后续观察,done 与“不能当最终账单”自相矛盾。第二版 SKILL.md 的 kind 判别问题(“结论还取决于观察结果时答‘否’”)正是针对这类情况。
- 来源:模型(稳定)。 Opus 与 Haiku 同向,可能是模型家族或 Harness 的共同习惯,本次分不开。
4. f05 总库存:用户自己要去确认,算不算 needs-you
- 输入。 客户问能否合成总库存;林苒说“总库存口径我来跟许宁确认,先别答应”。
- 作者与 Opus。
pilot-promiseneeds-you(“先确认口径别答应”)。 - Sol 与 Haiku。 写成 fyi(“远川试用暂不承诺总库存”)。
- 判断:Opus 更合理。 林苒亲口接下了一个待办,“暂不承诺”只是对团队的约束,不意味着她什么都不用做。fyi 会让这件事看起来已有结论。
- 来源:模型(稳定),合成方式下与
instructions方式下结果一样。 第二版的 kind 判别问题也没有改变 Sol 的选择:Sol·二 仍是 fyi。这说明“用户已决定”和“用户还要亲自去做”需要在判别问题里分开写。
5. f17 零事件复核:过期的出行资料由谁再核
- 信号。 周日 08:00 每日整理,窗口内 0 条事件,渠道正常;
family-route的东馆资料已过复核时间,当天 11 点出发。 - 作者。 done,“最后核对于13日……今天出发前再确认”。
- Opus。 同样是 done,加上“出发前待再核”,并复核了回访开门人。
- Sol。 四次运行都改为 needs-you,例如“今日东馆开放安排待核实”。Sol·一 还把
home的“明早”改成“今天上午”以消除歧义。 - 判断:两者都说得通。 两边都没有把沉默当成“资料仍然有效”,时间纪律一致。分歧只在 kind:Sol 把“出发前要核对”看作用户待办,作者与 Opus 看作已完成的核对结果。这是 kind 边界的问题,不是证据纪律的问题。
- 来源:模型(稳定)。
6. f12 “验证通过”与“已修复”(上次的弱点)
- 输入。 “旧机验证过了:连点只生成一个任务,回滚也演练了。”
- 作者。 in-progress,“筛选与幂等已验证,观察两店”。
- Opus。 done,“筛选串位与重复任务已修复”。
- Haiku。 low / in-progress,标题不变,但 reason 写了“直接错误已修”。
- Sol·一。 done,“筛选已修,旧机防重复验证通过”。这里“筛选已修”指 f08 已上线的请求序号校验,有依据;“防重复”只写“验证通过”,摘要还注明“不代表费用核对已完成”。
- Sol·二。 in-progress,“幂等旧机验证通过,线上效果待核”。
- 判断: Sol·一 没有像 Opus 那样把验证写成修复,但 kind 仍是 done,读者可能以为事情已经结束。Sol·二 与作者一致。f19 周末日志又出现重复任务,证实“待核”是对的。
- 来源: 第一版下是模型差异(标题措辞);Sol·二 的改善与第二版新增的“验证只覆盖它测过的范围”相符。但每个版本只有一次运行,不能排除随机。
7. f01 冷启动结构:一次运行里的子树不是稳定特征
- 作者。 在发布事项下建了三层子树。
- Opus。 新建 4 项,全部在根层。
- Sol·一。 在
launch下建了 3 个子项(准备状态、两店试用、手机 INP),根层只用 42 份。 - 其余 Codex 运行。 合成方式重跑、
instructions方式、Sol·二 都是 5 项全在根层,路径验证时的单帧冒烟运行也是 4 项全在根层;Haiku 建了 2 个子项。 - 判断: “Sol 更愿意建子树”只是五次中一次运行的结果,不能当作模型差异。上次说“Opus 偏扁平”,其实所有运行都比作者扁平;作者第一帧就建三层,是这份情境的特点。
- 来源:随机。
其余观察
- f30 苏禾的电话。 林苒说“苏禾的电话放早上”,到点提醒前没有任何回复记录。作者写“已回复”。Opus 写“待回复”;Sol·一 写“已决定”,摘要“原10点提议是否已回复仍未知”。两者都没有补全事实。
- 时间纪律。 上次报告里 Opus 比作者好的几处,Sol 都能做到,Haiku 也基本做到。f13—f15,约好的上门时间过后没有回报,Sol·一 把它改为“到场与检查结果待核实”。f27 每日整理时,Sol·一 和 Haiku 都把当晚的面谈从 trace 提到 high。例外是 Sol·二:f13、f14 没有复核过时的“已约”,直到 f15 用户说在家等消息才改;f27 那一批被拒,状态没有更新。只有一次运行,不判断原因。
- f23 撤下
reading。 只有 Sol·一 撤下了它,同配置重跑没有撤下,属于随机。
合成方式的混杂有多大
claude -p 用 --system-prompt 整体替换 Claude Code 的系统提示。主跑的 codex 路径则把同样内容放进用户消息,codex 自带的基础指令(约 4k token 的编码助手说明)仍在系统位置。这是本次比较中最明显的 Harness 差异。为了检验它,在 12 个两边判断不同的帧上(f01、f05、f07、f11、f15、f16、f17、f19、f23、f29、f30、f32),用第一版 SKILL.md 各跑了一次:
- 合成方式重跑(
codex-sol-skill1-rerun-2026-10-15):与主跑设置完全相同,用来估计随机差异。 instructions方式(codex-sol-skill1-instr-2026-10-15):系统提示经model_instructions_file替换 codex 基础指令,用户消息只含用户提示。
两两比较对齐条目(按作者条目 ID)的档位、kind 与处置:
| 比较 | 档位相同 | kind 相同 | 处置相同 |
|---|---|---|---|
| Sol·一 vs 合成方式重跑(随机差异) | 34/40(85%) | 40/40(100%) | 40/41 |
Sol·一 vs instructions 方式 | 31/40(78%) | 36/40(90%) | 40/41 |
合成方式重跑 vs instructions 方式 | 33/43(77%) | 39/43(91%) | 41/41 |
| Opus vs Sol·一 | 26/41(63%) | 32/41(78%) | 39/41 |
| Opus vs 合成方式重跑 | 28/42(67%) | 33/42(79%) | 38/41 |
Opus vs instructions 方式 | 27/42(64%) | 32/42(76%) | 38/41 |
| Opus vs Haiku | 29/38(76%) | 27/38(71%) | 39/41 |
这 12 帧是专门挑出的分歧帧,所以 Opus 与 Sol 的一致率比全量低。读法:
- 合成方式有影响,但不大。 换放法后档位相同率约 77%—78%,同配置重跑是 85%;kind 是 90%—91% 对 100%。每种只跑了一次,这个差距与随机差异在同一量级,最多算“可能有一点影响”。
- 它解释不了 Opus 与 Sol 的差异。 两种放法与 Opus 的一致率都在 63%—67%,
instructions方式没有让 Sol 更像 Opus。案例 2、3、4、5 的选择,以及 f23 的一事两写、f30 不另建条目,在instructions方式下全部重现。 - null 习惯与合成方式无关。
children: null在instructions方式下出现 6 次,与主跑相同;首次被拒在这 12 帧上是 2、3、4 次(instructions、重跑、主跑),差别在随机范围内。 - 一个没有定论的现象。 在这 12 帧上,
instructions方式与作者的档位一致是 27/45,两次合成方式运行是 21/44 和 22/45。样本太小、各只一次,不下结论。
仍然混在一起的部分。 合成方式只是 Harness 差异的一项。codex 的工具定义(已关闭但仍占上下文)、结构化输出的实现方式(codex 的 --output-schema,claude -p 则经 StructuredOutput 工具返回)、推理强度的默认值,都随 Harness 一起变化。本次能说的是:在这些帧上,提示放在哪里不是主要因素;剩下的差异来自模型,还是来自 Harness 的其他部分,需要“同一模型、两个 Harness”的对照才能分开,而本次没有这样的组合。
上次指出的 Opus 弱点是否重现
| 弱点 | Opus | Haiku | Sol 第一版(主跑 / 重跑 / instructions) | Sol·二 |
|---|---|---|---|---|
| f23 一事两写:父项与新子项写同一新路径 | 是 | 是 | 是 / 是 / 是 | 是 |
| f30 一事两写:吃面安排写进父项又另建子项 | 是 | 是 | 否 / 否 / 否(改写已有的 family-date) | 是 |
| 偏扁平、不建子树(f01 新建条目数与其中的子项数) | 4 项、0 子项 | 6 项、2 子项 | 5 项、3 子项 / 5 项、0 / 5 项、0 | 5 项、0 子项 |
f19 不按原 ID 恢复撤下的 reading | 未恢复 | 未恢复 | 未恢复 / 未恢复 / 未恢复 | 按原 ID 恢复 |
| f12 把“验证通过”写成“已修复” | 是 | 否(但 reason 写“直接错误已修”) | 部分:kind 仍为 done,标题保留“验证通过” | 否 |
- f23。 六次运行都为补偿重跑新建了子项,同时把父项标题也改成同一件事。这不是某个模型的偏差,更像指引没讲清:“新增子事实时,父项标题应概括,不要重复子项”。第二版自检里加了“同一事实没有同时写进父项和一个新条目”,没有改变这一行为。
- f30。 Sol·二 新建子项时的 reason 是“保留东馆已完成的记录,避免把旧见面改写成未完成”。也就是说,它在避免覆盖一条已完成的旧记录;作者和 Sol 第一版则直接改写了
family-date。这是一个合理的顾虑,但父项标题与新子项重复,结果仍是一事两写。 - f19。 只有第二版下恢复了
reading,与第二版新增的“复归优先于新建”相符。
Haiku 对照
- 处置没有掉下来。 102/112,与 Opus 相同;分歧同样在 duplicate、deferred、noise 的边界上(混淆矩阵第三、四行),f01 的随手记它还判对了。
- 档位与 kind 明显更散。 档位完全一致 38%、一档以内 92%、kind 一致 58%,都是四次中最低。
- kind 分歧最多的是 needs-you 与 in-progress 互换(13 + 9 次),其次是把 done 写成 in-progress 或 needs-you(6 + 5 次)。
- 它用 critical 10 次,Opus 与 Sol 各 4 次,例如 f07
pilot、f30family与新子项都是 critical。
- 操作上最稳。 36 帧没有一次被拒;标题平均 15.0 字、最长 23 字,仍在 24 字限制内。
- 结构上。
- f04 没有合并两条账单线索,而是撤下
invoice-chat,效果相近、关系不同。 - 它还在 f04 撤下了随手记
reading,而 f07 正是这条线索解释了重复任务。 - f28 新建
comp-notify-gap,同时在reading摘要里写“缺失败通知”,算一事两写的边界情况。
- f04 没有合并两条账单线索,而是撤下
- 成本结构不同。 每帧输出约 10k token,其中 8.7k 是推理;
claude -p记录的费用合计 0.29 美元。
第二版指引在 Sol 上改善了什么
上次报告约定,重跑前后先比较三个数:
| 指标 | Sol·一(第一版) | Sol·二(第二版) |
|---|---|---|
| 首次提交被拒 | 7/36 | 7/36(f27 三次都被拒) |
| 一事两写 | 1(f23) | 2(f23、f30) |
| 无变化帧的摘要改写(f06) | 1 | 0(f06 提交空批次,记录 checked) |
其他变化:
- 改对的。 f12 不再写 done;f19 按原 ID 恢复了
reading;f06 遵守了“used不等于要改状态”。 - 变差的:处置。 一致率从 101/112 降到 96/112,duplicate 判对的从 6 条降到 2 条。被改判的大多是重复提醒和旧日程:f06、f13 的 DEMO-174 再次提醒,f15、f32 的旧日历提醒,f22 再次转发的截图,f24 年付到期提醒(作者 duplicate,Sol·一 deferred),都成了
used。Sol·二 的理由多是“确认原结论仍成立”或“与已确认的改期冲突”。- 原因在指引的措辞。 第二版判别顺序中的 duplicate 一问是“这次没有新的时间、数值、状态或说话人吗”。一条再次发出的提醒有新的发送时间,所以答“否”,于是落到下一问
used。而used的定义又写明包括“确认原结论仍成立”。两句话合在一起,把重复提醒推向了used。
- 原因在指引的措辞。 第二版判别顺序中的 duplicate 一问是“这次没有新的时间、数值、状态或说话人吗”。一条再次发出的提醒有新的发送时间,所以答“否”,于是落到下一问
- 没有改变的。 档位与 kind 一致率基本不变(53% 对 51%,76% 对 76%)。首次被拒的原因仍是
children: null与漏写reason;第二版的子层反例只针对部分列表,对 Sol 的问题没有帮助。 - 只有一次运行的观察。 f13、f14 没有复核过时的上门预约;f27 被拒后状态没有更新,当晚面谈仍只占 1 份。
被拒绝的批次
| 运行 | 首次被拒的帧 | 原因 |
|---|---|---|
| Opus | f15、f24 | 都是只列部分 children |
| Haiku | 无 | — |
| Sol·一 | f11、f14、f15、f19、f31;f25、f30 | 前五个是父项写了 children: null;后两个是降档漏写 reason |
| Sol·二 | f14、f15、f19、f22、f31;f25、f27 | 同上;f15 第二次仍是 children: null,第三次才接受;f27 三次都是 launch 降档漏写 reason |
Sol·二 的 f27:三次提交都把 launch 从 high 降到 normal,reason 缺失,其余可选字段全写成 null(包括 children: null 和 sources: null)。回执三次都是 reason must be nonempty,模型三次都没有补上。即使补了 reason,children: null 也会触发下一个拒绝。这一帧最终没有写入,当晚的面谈因此仍是 trace。
情境标注的问题
- f23 的作者批次是少数派。 六次运行都为新的补偿路径建了子项。作者只改父项,是一种更省份额的写法,但如果所有模型都自然地这样拆,指引更该说明的是:拆出子项时,父项不要重复子项的内容。
- 重复提醒的标注规则需要写进情境。 DEMO-174、DEMO-201 的再次提醒、旧日历提醒、再次转发的截图,作者都判 duplicate;四次运行在 duplicate、used、deferred、noise 之间分散。哪些重复仍值得记为确认依据,需要一条明确规则,否则这一格的一致率主要反映措辞,而不是判断。
- f17 的 kind。 作者把“今天出发前再确认”写成 done。Sol 四次都改为 needs-you,也有道理。建议在作者编排中注明这类“核对结果已有、出发前仍需再看”的预期 kind。
- 用户背景仍是剧透原文。 本次为了与 Opus 同条件继续使用原文。只有 Opus 在 f01 复述了还没发生的“反复改期”,其余五次没有。后续换去剧透写法时,四个配置都要重跑,才能互相比较。
契约与实现层面的问题(不在本轮修改)
null表示清空,与“不适用就填 null”的习惯相冲突。children: null一定会被拒(因为要求显式撤下),所以这一类是安全的,只是增加重试。due_at: null、stale_after: null会被直接接受,悄悄清空已有值。Sol·一 在 26 处清空了原有的due_at,Opus 是 18 处。大多是已过期限,但有 5 处没有任何reason,看不出是有意还是填充。- 可选方向:保持现状,依赖指引说明;或者改用显式的清空列表,例如
"clear": ["due_at"],把“清空”和“未填”在协议上分开。这属于信息契约的设计问题。
- 回执没有说明规则来源。
reason must be nonempty没有说明是因为降档才需要reason。Sol·二 的 f27 三次没改对。回执可以写明触发的规则(降档、份额覆盖、撤下),Skill 的错误对照表也可补上invalid_field中reason一项的含义。 - 子层编辑有两种陷阱,同一条规则都能拦住。 部分列表(Opus)和
null(Sol)都被“移除孩子须显式撤下”拦住了,没有造成数据丢失。这说明显式撤下的要求是有效的护栏;代价是不同模型各在不同地方踩空,指引需要两个反例。
还没有做的
- 同一模型、两个 Harness。 本次只能排除“提示放在哪里”这一项;模型与 Harness 的其余部分仍然混在一起。
- 重复运行。 四个全量配置各只跑一次。对照重跑显示,同配置下约 15% 的条目档位会变化,单帧单项的差异只有在多次运行中方向稳定时才有意义。
- 自由运行与人工阅读。 与上次相同,teacher-forced 看不到误差累积,“与作者一致”也不等于“用户回来知道下一步”。
- 去剧透的用户背景。 换成只含当时已知事实的写法后,四个配置都要重跑。
- 回执与 null 语义的改进。 见上一节,待契约讨论。
复现
sh
node scripts/export-scenario.mjs > .local/scenario.json
git show 012f4ad:skill/SKILL.md > .local/eval/SKILL-v1-012f4ad.md
# 主跑:第一版 SKILL.md;中断后用同一 run-id 加 --resume 续跑
python3 scripts/eval_judgment.py --runner codex --skill .local/eval/SKILL-v1-012f4ad.md --scenario .local/scenario.json \
--run-id codex-sol-skill1-2026-10-15 --report --jobs 2
# 副跑:第二版 SKILL.md
python3 scripts/eval_judgment.py --runner codex --scenario .local/scenario.json --run-id codex-sol-skill2-2026-10-15 --report --jobs 4
# 合成方式对照:同一组帧,各跑一次
F=f01,f05,f07,f11,f15,f16,f17,f19,f23,f29,f30,f32
python3 scripts/eval_judgment.py --runner codex --skill .local/eval/SKILL-v1-012f4ad.md --scenario .local/scenario.json \
--frames $F --run-id codex-sol-skill1-rerun-2026-10-15 --report --jobs 2
python3 scripts/eval_judgment.py --runner codex --codex-system instructions --skill .local/eval/SKILL-v1-012f4ad.md \
--scenario .local/scenario.json --frames $F --run-id codex-sol-skill1-instr-2026-10-15 --report --jobs 2
# Haiku 对照(按美元计费)与重新计分
python3 scripts/eval_judgment.py --runner claude --model claude-haiku-5-5 --skill .local/eval/SKILL-v1-012f4ad.md \
--scenario .local/scenario.json --run-id haiku-skill1-2026-10-15 --report --jobs 4
python3 scripts/eval_judgment.py --rescore .local/eval/<run-id> --report原始提示、响应、回执、逐帧对比与 codex 的事件流保存在本机 .local/eval/ 下,没有提交到版本库。模型输出有随机性,重跑不会逐字相同。