# 前言

同時訂了 Claude 跟 Codex,但主力都用 Claude,Codex 一直閒置,想說別浪費訂閱,讓它來當第二意見。

環境是 Claude Code 跟 Codex 兩個各自裝好,另外在 Claude Code 裡裝了 codex plugin,後面用到的 adversarial-review 指令就是這個 plugin 提供的。

但要它真的有用,不能每次都我手動轉貼、手動判斷、自己盯著何時該停。想要的是:給一個主題,兩個 AI 自己來回討論,中間不用我介入、不被 permission dialog 打斷,有自己的收斂機制與評估機制,跑到收斂為止。

於是做了一個 skill 叫 adversarial-plan:給一個主題,Claude 草擬設計稿,在隔離的 worktree 裡反覆丟給 Codex 的 adversarial-review 攻擊、依問題修訂,直到收斂。整個過程無人值守。

這篇拆成幾塊講:讓兩個 AI 能來回討論的橋梁、把它變成一個能無人值守跑完的完整 skill 所需的必要條件、拿它對自己開刀的 dogfooding,最後是怎麼把這套做成一個 skill

# 無人值守要解決的幾件事

讓兩個 AI 自動來回,難的不是「能不能跑」,是「不用人盯著也能跑得對」。要做到這點,有幾件事得先解決:

  • 不被打斷:迴圈中間若一直跳 permission dialog 要我點同意,就稱不上無人值守。授權範圍得先講好(後面的 allowed-tools)。
  • 自己知道何時停:沒有人喊卡,它得有明確的收斂條件,不然不是提早收手就是無限迴圈。
  • 有客觀的裁判:Claude 既是作者又是迭代者,自評一定護短。停不停得認一個外部判定,不能自己說了算。
  • 不會假裝有共識:兩個 LLM 放著聊,容易互相讓步、三兩下握手言和(sycophancy),看似收斂其實沒交鋒。所以這裡用天生扮反方的 adversarial-review,把對立外包給工具,而不是寄望它們自己吵起來。

後面幾段就照這個順序走:先搭起來回的橋梁,再補上讓它無人值守也跑得對的規範,然後拿它驗證自己,最後固化成 skill。

# 一、兩個 AI 溝通的橋梁

要讓兩個 AI 真正交鋒,得先有一條通道:把 Claude 的想法送到 Codex 面前、再把 Codex 的攻擊帶回來。這條通道由三件東西組成。

# 用 git worktree 突破「只吃 diff」的限制

Codex 的 adversarial-review 是為「審程式碼變更」設計的,它的提示詞明寫任務是 "break confidence in the change, not validate it",天生扮反方,正好是反附和的現成工具,不必自己造辯論框架。

但它有個硬限制:只吃 git diff。一個還沒寫成程式碼的開放式設計問題根本沒有 diff,要怎麼餵給它?

解法是 git worktree:把設計稿寫成一份 .md,從基底分支開一個用完即拋的 worktree,把它 commit 進去,再讓 Codex 對這個 worktree 做審查。這樣 diff 就只剩這份設計稿,Codex 被迫只審它。整個 skill 成不成立全靠這步。

為什麼非 worktree 不可?因為直接在當前分支上跑,審查會把整個工作目錄的改動全送審,沒辦法只圈出目標。唯有開一個乾淨的 worktree、只放這份設計稿,才能讓 Codex 精準只審它,不被無關改動稀釋。

# 把對話留成檔案:draft.mddebate.md

worktree 裡放兩個檔,分工很明確:

  • draft.md:Claude 一開始草擬、之後每輪依問題修訂的設計稿,是乾淨的交付物,不摻辯論痕跡。
  • debate.md:逐輪記下 Codex 指出的問題,以及 Claude 的處置(接受並改 draft.md,或寫明反駁理由)。

兩個檔都是 Claude 在寫,Codex 全程只攻、不碰檔案。

debate.md 看似只是紀錄,其實是對話能不能延續的關鍵。Codex 每一輪都是全新對話,不記得上一輪我反駁過什麼。如果我的反駁只留在腦中、沒寫進這輪給它看的內容,它下一輪就會把同一個問題再提一次,表面看像「這問題一直沒解決」,其實只是它不知道我已經回應過,於是永遠收斂不了。把反駁寫進 debate.md 一起 commit,等於讓它出現在下一輪的審查範圍內,Codex 才看得到我的回應。

# 每輪的訊息:給 Codex 的焦點說明

光把檔案送過去還不夠,每輪還要附一段焦點說明告訴 Codex 這輪要打什麼。三段配方:

  1. 定性:說清楚「這是設計提案不是程式碼,請挑戰假設、取捨、失效情境」
  2. 本輪標的:點名這輪要打的設計決策
  3. 未決區:列出還沒定案的點,含我已經反駁過的點,請它針對性反擊

焦點說明寫得弱、設計稿寫得虛,Codex 會因為「沒有實質可攻」而假性通過。

# 二、完整 skill 的必要條件

有了溝通橋梁,機制就跑得動了。但跑得動不等於能放手讓它自己跑完,要無人值守也可靠(不自我背書、不無限迴圈、失敗不誤判成功),得補上幾道規範。

# 裁判中立(最重要的一條)

Claude 同時是作者跟迭代者,天生會護短。所以鐵則是:收斂只認 Codex 的判定,不認自評。對每個問題只能二選一:接受並改 draft.md,或在 debate.md 寫明反駁理由,不准無聲略過。

# 收斂與停止條件

收斂條件(任一成立):

  • Codex 判定通過
  • 沒有任何問題
  • 嚴重度閘:剩下的問題全是低嚴重度、低信心,只剩雞毛蒜皮
  • 卡住:全是前幾輪已處理過的重複項,沒有新問題

延長賽:基準 5 輪;撞頂時只有當實質問題數「嚴格遞減」(還在進步)才延長,一次一輪,絕對天花板 7 輪。持平或變多就停,並建議「設計可能不穩,宜重想而非續迭代」。

老實說「天花板 7」是隨手定的魔術數字。真正保證終止的是「嚴格遞減」本身,天花板只是防呆。把哪些參數有原理、哪些只是預算選擇誠實標清楚,比假裝都很科學重要。

# 失敗防護:失敗的一輪絕不可當成收斂

這是最大的假性成功風險,要明文寫死:

  • 每輪跑完先分類結果,成功 = 指令正常結束、而且拿得到一個可解析的判定。
  • 指令失敗或拿不到判定的那一輪,絕不可當成通過或收斂。
  • 暫時性錯誤(網路、429)重試一次;額度耗盡或登入失效就終止,保留 worktree 不拆,回報接續方式。

# 邊界:只挑工程風險,設計稿必須先選邊站

  • 限定守備範圍:只挑工程與維運上的風險,不評 UI/UX 好不好、產品決策對不對。範圍講清楚,Codex 才不會發散。
  • 設計稿不能各打五十大板:如果主題是「請 AI 幫忙拍板」的開放決策,設計稿必須先選一案、講明為什麼否決其他案。沒有明確立場,Codex 就沒有靶可打,只會虛應故事、假性通過。

# 三、dogfooding:讓 skill 自我調整

這套機制最強的賣點是:它能對自己施加,真的挖出自己的盲點。我用它做了兩件事。

# 實證一:審 skill 自己的設計

主題:這個 skill 還有沒有要調整的地方。

結果:3 輪挖出 9 個自身漏洞,實質問題數 4 → 3 → 2 單調遞減。最後剩兩條僵在「散文式 skill 要不要上機器可檢查的嚴格機制」,skill 沒有假性收斂,而是停下來交我裁決,正是「裁判中立」要的行為。

# 實證二:評估架構是不是最佳解

主題:這做法是不是目前環境能實踐的最佳方式。

結果:Codex 判定通過,但過程挖出一個我沒看到的高嚴重度缺口:盲信外掛 companion 腳本的內部契約,它若靜默改弱提示詞就會假性收斂;據此補了一道防線(每輪前對提示詞模板算雜湊,被改就停)。順帶查到這不是發明,是重現了業界已知做法。

# 四、怎麼把它做成一個 skill

前面講的是設計理念,這段講它在檔案上實際長什麼樣、又是怎麼長出來的。

# 它的實際長相

一個 skill 就是一份 SKILL.md:一段寫給 LLM 讀的自然語言指示,不是程式。所以前面那些規範(裁判中立、收斂條件、失敗防護)全都是用文字寫進去讓 Claude 照著做,而不是寫成程式碼去判斷。

幾個關鍵的工程點:

allowed-tools:在 frontmatter 列出無人值守迴圈會用到的工具:

allowed-tools:
  - Bash(git *)
  - Bash(node *)
  - Write
  - Edit

它是「預先授權」不是「限制白名單」:沒列的工具還是能用,只是會跳 permission prompt 打斷自動迴圈。把授權範圍寫在 skill 裡,就不用去動全域的 settings.json

怎麼觸發 Codex 審查:Codex 的 adversarial-review 指令標了 disable-model-invocation: true,意思是不能用 Skill 工具叫它。所以 skill 裡是直接呼叫底層的 codex-companion.mjs 腳本來跑審查。

迴圈本體:每一輪做這幾件事,直到收斂或撞頂:

  1. Claude 寫 draft.mddebate.md
  2. commit 進 worktree
  3. 呼叫 companion 跑審查、拿到判定
  4. 依問題修 draft.md、在 debate.md 記下處置
  5. 回到第 2 步重跑

# 它是逐步長出來的,不是一次設計完

這個 skill 的起點不是「我要做一個 skill」,而是一個問題:「能不能讓你跟 Codex 辯論到雙方認同?」整套東西是討論著討論著長出來的:

  1. 先釐清機制:想清楚要的是製造真實對立而非聊天,先找現成的反方工具(adversarial-review 天生扮 "break confidence"),不自己從零搭辯論框架。
  2. 找到關鍵轉接:把無 diff 的設計變成有 diff 的可審物,靠 git worktree(第一段講過),整個 skill 成不成立都在這一步。
  3. 先 trial 再寫 skill:拿一個真實題目手動跑一輪,確認 Codex 真的會精準引用行號、攻設計而非挑格式,機制證實有效才動手寫 SKILL.md。先驗證、後固化,比先寫一大坨再期待它能動可靠得多。
  4. 逐項問出規範:收斂條件、延長賽、失敗防護、焦點說明配方、雙檔分離……每一條都是「丟一個 what-if、釐清、確認,才寫進去」。規範是問出來的,不是憑空列的。
  5. dogfooding:寫完立刻拿它審自己的設計與架構(上一段那兩次實證),挖出並修掉自身盲點。
  6. 去重後 commit:自我檢查重複的規範、跟 Codex 對一次共識,再單獨把 skill commit 進去。

# 可延伸的通用觀點

抽離這個 skill 本身,有三個比較通用的心得:

  • 讓兩個 AI 對抗的前提,是「製造真實對立」(中立鐵則 + 強制選邊 + 留痕反駁),不是讓它們對話。
  • 把「無 diff 的開放問題」轉成「有 diff 的可審物」,是讓既有審查工具跨界使用的通法。
  • 自動迭代迴圈的三大護欄:硬上限、進步才延長、失敗絕不誤判成功。三者缺一,迴圈就會失控或假性成功。

本文使用 Codex 輔助撰寫。所以這篇也算是被它審過。