| name | dual-model-answer |
| description | 双模型同题对拍作答——Claude Code 与 Codex 就同一份 Prompt 各自独立作答,逐轮互审对方最新版并把审阅意见送达对方,各自据意见修订出新版(尾部附逐条回应的修订说明与取舍备忘),末轮补一次只审不改的终审,最后出一份共识与分歧表。全过程一步一档:answer / review / 终审意见 / 共识与分歧分别独立成文,每份文档顶部的 frontmatter 标明生成模型与上下文来源(读了哪份、针对哪份)。Prompt 不限类型:分析问题、写文章、读代码、技术调研皆可。当用户说「双答对拍」「让 Claude 和 Codex 各写一份互相审」「PK 作答」「两个模型分别回答再互相挑错」「dual-model-answer」时触发。宿主须为 Claude Code(流程依赖派发独立子任务与执行 Shell 的能力),Codex CLI 作为被调用的第二模型须在本地可用并已认证。前提是没有既有文档、双方从零作答:已存在一份待审文档时用 cross-review;要改代码仓库、走规划-实现-验收的开发任务用 dual-model-dev;对已有 diff 的代码审查用 code-review。 |
| allowed-tools | Read Bash Write Edit Glob Grep Agent WebFetch WebSearch AskUserQuestion |
双模型同题对拍(dual-model-answer)
把「同一个问题分别丢给 Claude 和 Codex、人肉搬运互相挑错、自己合并版本」收进一条命令。优化目标是答案的事实置信度与可追溯,不是让两个模型达成一致——分歧靠证据裁决,一致也不等于正确。
与手工做法的关键差别:审阅意见真的送达对方。手工时代你是人肉集成层,两个窗口都看,对方挑出的错你替它转达了;自动化之后这个人不在了,通道会断。文末「已知坑」记着实测后果。因此两条通道同时开——对方的审阅意见修我方的短,对方的答案原文补我方的长,少任何一条都是残的。
适用 / 不适用
任何想要高置信、经对抗核查答案的 Prompt 都适用:问题分析、文章、代码解读、技术选型、调研结论。不适用的三种情形与各自的替代技能见 description。
前置两条,分工不同:
- 调度方只能是 Claude Code。 流程依赖
Agent(派发独立 subagent)与 Bash(后台起 codex exec)两项能力,scripts/dma-lib.sh 也只封装了 Codex 一侧的运输通道,Claude 一侧没有等价的 CLI 调用。因此本 skill 只装给 Claude Code,其他宿主能加载但跑不完第一步。
- Codex CLI 是被调用的第二模型,不需要安装本 skill,只要本地可用并已认证:
codex --version 验安装,codex login status 验认证方式(该结果同时决定计费口径,开局播报要照它说)。不可用就如实报告并停,绝不用单模型伪装双答。
配套文件
| 文件 | 内容 | 何时用 |
|---|
references/templates.md | frontmatter 字段、五种文档骨架、成稿规范块、四个 prompt 模板 | 每次拼 prompt、每次写盘前 |
scripts/dma-lib.sh | 正文提取、diff、codex 调用、subagent 回收验收、冒烟核验、写盘、结构校验、留痕配额 | 开工时 source 一次 |
source ~/.agents/skills/dual-model-answer/scripts/dma-lib.sh
这些函数封装的都是抄错了不报错、只会悄悄给出坏结果的操作——三层嵌套的正文提取、退出码不可信的 codex 调用、日志会缺尾的联网核验。一律调用,不要复制片段自己拼。
规则文本按执行者归属:调度员要用的(处置词表、finding 编号、文档分区)写在本文件;只有 agent 要遵守的(成稿四条、核查着力点、修订四规则)住在 templates.md 的 prompt 模板里,那是唯一权威副本,改规则改那里。
输入参数
| 参数 | 默认 | 说明 |
|---|
| Prompt | 必填 | 任意任务 |
| 轮数 N(互审轮) | 2 | 终版为 v(N+1),默认 v3;终审恒在最后 |
| 输出目录 | 当前工作目录下新建 dual-model-answer/ | 用户可指定父目录 |
| 事项名 | 从 Prompt 概括 2~8 字,跟随 Prompt 语言 | 用户可指定 |
| Codex 模型 / effort | 跟随 ~/.codex/config.toml | 用户点名时传 -m <模型> / -c model_reasoning_effort=<级别> |
| Claude 侧 subagent 模型 | 跟随会话模型 | 用户点名时给 Agent 工具传 model(opus / sonnet / haiku / fable)。它优先于 agent 定义的 frontmatter,且与调度员自己的模型无关——调度员跑低配、subagent 跑高配是支持的组合,见下节末段 |
| 成稿档位 | 依 Prompt 性质自动判定 | 研究档(信息查阅/综述/调研/事实密集型)强制引证与 GB/T 7714 参考文献;通用档(代码解读、方案权衡、创作类)不强制编号引证,但事实性断言仍须给可核查依据。判不准就按研究档,并在开局播报里说明 |
对等架构
主会话只当调度员:控步骤、发起调用、跑 diff、统一写盘、生成 frontmatter、与用户交互。自己不作答、不审阅、不润色任何一方内容。
每一步双方各派一个全新 agent——Claude 侧派新 subagent,Codex 侧开新 codex exec 会话。不用持久会话:codex exec resume 虽然可用,但 gpt-5.6-sol 的窗口是 258,400 token,超出后自动压缩是静默有损的(replacement_history 直接把历史换成摘要),而被换掉的正好是本 skill 唯一在乎的那层细节——某条引证的核对结果、某个页码的原文、某条被驳回意见的证据链。持久会话还会引入隐藏状态,中断即失。
持久会话唯一真正独有的资产是作者意图,它被外置成文档:每版答案尾部的取舍备忘,记着为什么选这条引证、放弃了哪些候选、哪些限定语是刻意的。写下来的意图可审计、可传递、不吃压缩。
全部状态存于文件,中断后看缺哪一对文件即知走到哪步。同一步内双方并行:Codex 后台跑,同时派 Claude subagent,两边都回收后再进下一步。
两侧回收对称,一律走文件。 Codex 侧靠 dma_codex 的 -o;Claude 侧在 prompt 末尾附 templates.md 第 5 节的收尾指令,让 subagent 自己把正文 Write 到 scratchpad 的约定路径,回来跑 dma_collect 验收。不要从 subagent 的最终回复里提正文——那要经 transcript 提取,杂质形态每次不同(HTML 转义、对话性开场白、尾部残留围栏),混进交付文档不报错,只会让 dma_body 提不出正文、dma_diff 整份判为改动。走文件还有第二个好处:正文不再经通知灌进调度员上下文,调度员只看见字节数,这是调度员侧最大的一笔可省开销。
调度员可以跑低配模型,subagent 跑高配。 调度员的活本就是机械的——拼 prompt、发起调用、跑 diff、生成 frontmatter、机械抽取共识表。前提是别把判断留在调度员身上:正文回收已由 dma_collect 兜住,异常处置照「异常处理」表走,剩下唯一需要判断的是 07 共识与分歧.md 里跨轮次的状态演化(某条先保留分歧、后被提出方自行撤回改判采纳,或驳回后被对方终审确认成立)——这一步拿不准就照实列两行并注明演化过程,不要合并成一个结论。
文件与命名
输出目录 <父目录>/dual-model-answer/,内部平铺,文件名带执行步号,ls 的字典序即流程顺序。
dual-model-answer/
00 index.md 链路总览 + 状态(中断恢复看它)
01 Claude answer v1.md 01 Codex answer v1.md
02 Claude review-1.md 02 Codex review-1.md
03 Claude answer v2.md 03 Codex answer v2.md
04 Claude review-2.md 04 Codex review-2.md
05 Claude answer v3.md 05 Codex answer v3.md ← 交付
06 Claude 终审意见.md 06 Codex 终审意见.md ← 附件
07 共识与分歧.md ← 附件
步号公式:answer v(k) = 2k-1;review-k = 2k;终审 = 2N+2;共识与分歧 = 2N+3。N=2 时共 14 份文件、12 次 agent 调用。
目标目录已存在,问用户一次:续跑(补齐缺失步骤)还是新开一份(目录名加序号)。调度员生成的中间物(diff、prompt、回收文件、日志)一律落 scratchpad,不进交付目录。
写盘由调度员统一做,frontmatter 由调度员生成而非 agent 自报。两个理由:Codex 在 -s read-only 下不能写文件,放开写权限会破掉只读红线;更要紧的是「读了哪份、针对哪份」一旦让 agent 自己填就成了自我报告,而调度员是唯一真正知道自己传了什么进去的角色。agent 只产出正文,调度员原文照录。
流程
⓪ 开局
确定参数 → 建目录、检查已有文件 → dma_smoke <scratchpad> 验联网 → 向用户播报一句配置:成稿档位、轮数、本次约 12 次模型调用、以及 Codex 侧的计费口径(用户已明示则不提)→ 开工。
计费口径不要硬编码:codex login status 显示 ChatGPT 登录就说「走你的 ChatGPT 套餐用量」,显示 API Key 就说「按 API 用量计费」。写死其中一种会让另一种用户收到错误的成本预期。
联网必须实测:~/.codex/config.toml 里没有 web_search 配置,联网完全依赖调用时的 -c tools.web_search=true。默默降级成无联网的 Codex 会让「能力对称」这个前提失效,而这从最终输出上看不出来。
① 独立作答(步 01)
双方仅凭原始 Prompt 作答,互不见面——任一方的 prompt 不得含对方答案或任何方向性暗示。反锚定只约束这一步,此后交叉阅读正是目的所在。产出正文 + 取舍备忘。
回收后跑 dma_collect <回收文件>(Claude 侧)与 dma_check_ratio <写盘后的 answer> 验留痕配额。
② 互审(步 2k)
每方派新 agent,读四样:对方 answer v(k) 全文(含其修订说明与取舍备忘——前者让我看见我上轮的意见被怎么处理,后者让我避开对方自己都标了存疑的材料)、对方 v(k-1)→v(k) 的正文 diff(k≥2,dma_diff 生成)、我方 answer v(k)(知道我方有什么才写得出「对方有而我方缺」)、我方 review-(k-1)(k≥2,闭环核对用)。
产出三节。三个标题的字面与节数在所有轮次恒定——调度员按标题机械定位,缺一节就错位:
- 一、闭环核对:逐 ID 判断我上轮的发现对方是否处理,并核 diff——删除与弱化之处若未在对方修订说明里交代,逐一追问。无声的回归是实测出现过的失效模式。k=1 时本节保留,写「首轮互审,无上轮发现可核对」。
- 二、核查发现:逐条标题式,送达对方。找不到问题必须明说「未发现」,不许编造弱问题凑数。
- 三、可吸收之处:对方有而我方缺的实质内容,留给我方修订 agent,必须写实内容。实测中同一份核查被双方各做了一遍,就是缺这一节。
回收后跑 dma_check_review <文件> 验结构。
③ 修订(步 2k+1)
每方派新 agent,读五样:原始 Prompt、我方 answer v(k)、对方 review-k(评我,补短)、对方 answer v(k) 全文(补长)、我方 review-k(含吸收清单)。产出正文 + 修订说明 + 取舍备忘。
回收后跑 dma_collect(Claude 侧)与 dma_check_ratio。留痕区超过正文 1/4 就退回该方压缩重出,不由调度员代删——删哪一句是作者意图的取舍。压缩只压单条长度,不许减少回应条数。
④ 终审(步 2N+2)
跑满 N 轮后双方各再审一次对方的终版,读对方 v(N+1)、其正文 diff、我方 review-N。只审不改,产出闭环核对与新发现两节作为交付附件;不写吸收清单,没有下一版消费它。校验用 dma_check_review <文件> final。
这一步补的是结构性缺口:末轮审阅若既没有下一版承载、也没有独立附件收纳,它的发现就没有任何进入交付链路的通道。旧流程的那次实测里,终轮 5 条发现有 4 条「重要」级原样留在交付稿。
⑤ 共识与分歧(步 2N+3)
调度员用 dma_findings 抽出全部 finding,配合两份修订说明的处置字段,机械拼装四节:双方均采纳(已收敛)、一方驳回且对方接受、保留分歧(列双方立场与性质)、终审指出但未修正。纯提取不创作,每行可回溯到源文档——这是调度员唯一允许生成内容的地方,因为它不含任何判断。
⑥ 收敛判定与收尾
某轮双方审阅均无「关键/重要」级新发现,用 AskUserQuestion 问用户:提前结束(仍跑终审)还是跑满 N 轮。仅一方无发现则继续。
收尾更新 00 index.md 状态,交付两份终版 + 两份终审意见 + 共识与分歧表,附两三句简报(轮次、收敛情况、主要分歧及裁决)。
调度员要用到的约定
finding 编号 {提出方}R{轮}-{两位序号},如 CxR1-03 是 Codex review-1 的第 3 条,Claude 侧前缀用 Cl,终审用 {前缀}F-{序号}。已发编号永不重排复用,后续轮次引用原 ID 追加状态。dma_check_review 会校验这个格式。
处置封闭词表 每条收到的发现必须标 采纳 / 驳回 / 保留分歧 之一。驳回须给证据,保留分歧须写明是事实层还是框架层。只有这套词表封闭,07 共识与分歧.md 才能机械抽取,所以不可临时扩充。
文档分区 答案文档是「正文 / --- / 修订说明 / --- / 取舍备忘」。分隔线以上严格无过程痕迹,以下才是留痕区。dma_body 靠这个结构提正文,写法跑偏会让 diff 整体失效。
agent 侧的规则(成稿四条、核查六个着力点、修订四规则)不在这里,见 templates.md 的 prompt 模板。
Codex 调用
一律经 dma_codex <工作目录> <prompt文件> <回收文件> <日志文件> [额外参数],用 Bash 工具的 run_in_background 发起,命令里不要再加 &(否则双重后台,harness 拿到的是包装进程的状态而非 codex 的)。函数里已经封好三件容易出事的:stdin 传参、只读沙箱、回收文件非空判定。
- prompt 必须走 stdin,不要用
"$(cat 文件)" 内联。实测内联会让长中文 prompt 被截断,到达模型的只剩一部分,而退出码、回收文件大小、产出结构全都正常,从外部完全看不出来。走了 stdin 就不要再加 < /dev/null,两者互斥。
- 完成判定是回收文件非空,退出码不可信:参数错误时 codex 秒退,后台包装层照样报 exit 0,
-o 文件根本没建。
- 联网开关是
-c tools.web_search=true(--search 在 0.144.x 已移除)。旗标名会随版本漂移——报 unknown argument 时先查 codex exec --help 与 codex features list | grep -i search 看当前形态,不要硬试。
- 日志不可全信:实测
run.log 会缺尾,工具调用、最终答案、token 计数全都可能没记,而同一次运行的会话 rollout 里工具其实调了很多次。要判断工具有没有真的动过,读 ~/.codex/sessions/YYYY/MM/DD/rollout-*-<session id>.jsonl,dma_smoke 就是这么验的。
- 材料一律给文件路径(Codex 经
-C 自行读取),不把全文塞 prompt。每份文档单一用途,指路只需写文件名。
- Codex 会自动加载并通读本 skill:实测它派活后的第一个动作就是通读 SKILL.md。好处是它免费拿到了规范;风险是本文件里的任何具体举例都会变成它的「标准答案」。因此本 skill 与 templates.md 正文一律不得出现具体的事实性错例(某本书某个页码、某条法规某个条款),只描述失效模式的形态——否则审阅方会照着例子去「找」,而不是照着待审文档去查。review prompt 里也写明了这一条。
安全红线
- 事实核查只许只读操作;任何有副作用的命令一律不执行。唯一例外是为核对页码下载文献 PDF,且只许落在临时目录,不得改动任何既有文件。
- Codex 失败/超时/输出为空:重试一次;仍失败就如实暂停报告用户,绝不伪造内容顶替。Claude subagent 同理。
- 双方一致不等于正确;驳回对方发现必须给证据。
- 只写本次对拍目录与临时回收文件,不动用户其他文件。
异常处理
| 异常 | 处理 |
|---|
| codex CLI 不可用 / 认证或配额错误 | 停下如实报告(可能需 codex login 或等配额),不自行改配置 |
| codex 报 unknown argument | 按上节查当前旗标形态,改用等价参数并回写进 skill;改动后必须重跑 dma_smoke 确认能力未降级 |
dma_codex 报回收文件为空 | 视为失败(多半是参数错误秒退),读日志定位后重发 |
dma_smoke 计数为 0 | 联网没挂上,停下报告用户,不要降级开跑 |
dma_check_review 报警 | 退回该方按模板重出该文档,不由调度员代改 |
dma_collect 报文件为空 | subagent 没按约定 Write 或路径写错;重发该步,别改从最终回复里提正文 |
dma_collect 报首行非二级标题 | 混进了开场白或 frontmatter,退回该方重出,不由调度员代删 |
dma_check_ratio 超配额 | 退回该方压缩留痕区重出;压单条长度,不许减少回应条数 |
dma_diff 空或整份被判改动 | 分隔线/标题写法不符规范,同上退回重出 |
| 正文里混进过程性表述 | 退回该方重写正文 |
| 修订说明缺 ID(漏回应) | 退回该方补齐;下一轮闭环核对也会兜住 |
| 答案超长 | 材料继续走文件路径,不截断 |
| 中断恢复 | 看目录缺哪一对文件,从该步续跑;00 index.md 记着已完成步骤 |
已知坑(实测记录)
出自对一次真实对拍产出的逐条复核,以及本 skill 改版时的实测。异常处理表讲「出事了怎么办」,这张表讲「为什么这些规则长这样」。此处只记失效模式、不记具体错例——原因见上节末条。
| 现象 | 原因与对策 |
|---|
| 终轮审阅发现全数丢失 | 末轮审阅既无下一版承载、也无独立附件收纳,发现就没有进入交付链路的通道。那次实测终轮 5 条发现有 4 条「重要」级原样留在交付稿,其余 1 条亦未进入交付物。对策:终审步骤 + 共识与分歧表 |
| 意见滞后整整一轮才生效 | 旧设计里审阅意见不送达,只能经由审阅者自己下一版的正文间接传递。实测首轮 16 条发现有 10 条在对方次版里原样存活。对策:意见直送 |
| 同一份核查被双方各做一遍 | 写不进自己正文的纯证据质疑没有传递载体,对方只能重做一遍。对策:review 的「可吸收之处」一节 |
| 以删代改 / 内容净减少 | 实测六次订正有三次是删掉争议材料了事,已核实的正确引证反而没能进入交付物。对策:修订规则里的禁止条款 + 下一轮回归检查 |
| 无声回归 | 实测出现过:上一版正确的多项枚举,下一版悄悄少一项,修订说明里毫无记录。作者自己都不知道漏了,声明式约束抓不住。对策:dma_diff 递给审阅方 |
| 反锚定泄漏 | 旧设计两份文档是堆叠结构,指路靠「读到下一个 ## 为止」,实测已发生泄漏(一方引用了只存在于对方审阅章节里的内容)。对策:一步一档,文件级隔离,这条切片路径随之取消。但它是投递边界而非沙箱:首轮的互不见面仍依赖调度员只投递原始 Prompt、agent 守住材料边界 |
| 长 prompt 被静默截断 | 内联传 prompt 时到达模型的只剩一部分,而退出码、文件大小、产出结构全都正常。对策:dma_codex 走 stdin |
| 日志的沉默不是证据 | 实测 run.log 会丢掉工具调用、最终答案与 token 计数,而同次运行的 rollout 显示工具实调了 9 次。对策:dma_smoke 只认 rollout 里的计数 |