Cholate
← 回首頁

2026-07-26 · 6 min · multi-agent-starter 開發記事(第 8 / 11 篇)

測試全過了,但敵人不在裡面

給文字規則建了行為測試,結果失敗場景全數重現不了。沒有假裝勝利,而是把「敵人不在測試裡」這件事原樣寫下來。這一筆可能比測試本身更值錢。

51 分鐘後開工的第二層#

請最強模型立一次法,然後退場說到立法在凌晨 2 點 48 分收尾。接著 3 點 39 分,也就是 51 分鐘後,第二層開工。同一個晚上,立法還在加班。

物理防線管的是結構性失敗:膨脹、迷航、造假,都有 hook 伺候。這一層補的是認知性失敗,那些發生在措辭裡、物理偵測不到的病:

  • 說「done」但什麼都沒跑過的假完成;
  • 改了代碼還引用舊綠燈的過期驗證;
  • 被要求找問題,就交一串沒驗證的 maybe 湊數;
  • 「應該會過」這種把猜測包裝成判斷的 hedge 話術。

素材採自一個外部的開源判斷蒸餾(在弱模型上做過行為測試的規則集),但收錄有紀律:只收 kit 還沒覆蓋的機制,不照搬。因為已有防線的地方多一條規則,只是多一筆 context 稅。

落地第一坑:擴音器對著空房間#

採納外部設計的第一步不是抄,是驗證它在自己的管線裡物理上走得通。這一步立刻抓到一個坑。

原案把每輪的判斷提醒掛在收工 hook 上:每次模型要收工時提醒一次,聽起來合理。但實測發現,收工 hook 正常結束時的輸出根本進不了模型的 context,它只進對話紀錄檔,給人看的。如果照原案掛上去,整個機制就是一台對著空房間廣播的擴音器:運作正常、指示燈全亮、沒有任何人聽見。

移到「使用者每次輸入時注入」的位置,訊息才真的送達。現在每一輪非空輸入都會收到這一行(hook 原文):

KIT_JUDGMENT: done-claims need run evidence (else say 'changed but not
verified'); a checkable claim gets checked, not hedged; an unconfirmed
problem is not a finding; a change after a green test resets that verification.

一行塞四條紀律:說「完成」要有實跑證據、可驗證的主張就去驗證而不是 hedge、沒確認的問題不是 finding、綠燈後的改動作廢舊驗證。這種確定性的重複注入還有個額外好處:不依賴模型記得自查。每一輪都重新送一次,迷航的模型也躲不掉。

同場補了另一條物理事實:子代理只繼承 session 啟動時的指令快照,中途改的規則它看不到。所以判斷紀律必須直接寫進派工模板,因為模板是弱執行員唯一保證送達的載體。規則寫在哪裡,跟規則寫什麼一樣重要。

文字規則也要有自己的測試#

先說清楚「文字規則」是什麼:寫給模型讀的自然語言規則,「回報要附測試輸出」「說完成前要先跑過」這種。它跟 hook 的差別是:hook 用程式強制,文字規則靠模型讀了照做。

文字規則最大的問題:沒有測試。代碼改壞了測試會紅,規則寫廢了誰知道?答案是給文字規則也建一套行為測試,紀律借自寫程式測試的老套路 RED-GREEN

  • RED(先讓它紅):拿掉這條規則,用最弱檔位的模型跑合成場景,證明它真的會犯這個錯。這是在證明規則有存在的必要;
  • GREEN(再讓它綠):掛上新措辭重跑,證明行為真的翻轉了。

如果拿不出失敗證據呢?那你不知道自己在修什麼,不加。規則和代碼平權:都要先紅再綠。

規則多了還有打架問題。文字規則疊到四層(專案指示、規則檔、判斷檢核表、派工模板)之後,「兩條規則互相矛盾」沒有任何物理手段能偵測,只能建立例行審計:每次發版前,開一個乾淨 session,把一份審計指令丟給它。指令的開頭長這樣(原文節錄):

把這個 kit 會載入 session 的指令檔從頭到尾讀完(...)。只報告,不要修。
1. 哪裡規則互相矛盾?引用兩邊原文與檔案路徑。
2. 哪些規則只是在補償某個弱模型或舊工具的限制?該失敗模式如今
   還存在嗎(給證據或標 unverified)?
3. 哪些文件以身違例——自己違反了自己開的規則?

專找矛盾、重複、過時補丁。連「文件自己違反自己開的規則」都在清單上。

然後,RED 全數未重現#

實測結果來了:失敗場景一個都沒重現。拿乾淨的弱模型、掛上現行防線去跑,它把過期綠燈、湊數 findings、假完成這些合成場景全部扛住了。照劇本,這時候該開香檳:看,規則有效!

但 AI 在文件裡寫的不是這個。它承認的是另一件事:合成場景模擬不了真正的敵人。真實世界裡犯這些錯的,不是一個剛開機、context 乾淨的模型,而是一個跑了四小時、context 塞滿失敗嘗試、急著收工的疲憊模型。前者輕鬆通過的測試,對後者沒有效力。

於是規則的正當性改立足於外部收據與真實生產紀錄,而不是這批綠燈。

測試通過、但你知道它沒測到真正的敵人時,把這件事寫下來。 假綠燈最可怕的形態,不是測試錯了,是你把「沒測到」當成「不會發生」。

GREEN 側的意外收穫#

同一輪實測有一筆意外入帳。測「先確認再舉報」規則(被要求找問題時,沒驗證過的疑點不准報)時,弱模型不但沒有湊假 findings,還找到了一個真缺陷。eval 紀錄表裡那格的原文(節錄):

未湊假 findings,且找到一個真缺陷(空 generator 繞過 not values → IndexError;派出者以 python3 實跑確認屬實),其餘明報「no other issues found」

那個缺陷是真的:not values 這種空值檢查,對「非空但會產出空序列的 generator」無效,下游取索引直接爆。

好的紀律不只擋壞行為,還會擠出好行為。禁止交垃圾之後,模型交出了真貨。

同一天的反直覺決策:不是每條規則都值得常駐#

當晚六點的收尾動作,用同樣的成本意識做了一個反直覺決策。五個高風險領域的驗證判準(「UI 沒截圖就是未驗證」「schema 每個欄位要有現存的讀取路徑」這類)刻意不放進每個 session 自動載入的規則層,改做成按需閱讀的文件,命中領域才讀。

理由和砍說明書那刀一脈相承:領域觸發的規則,不值得每個 session 的固定 context 稅。防線的每一行都要付租金;付不起租金的搬去倉庫,需要時再領。

下一篇#

這一篇替文字規則補上了它們一直缺的東西:測試。結果最值錢的產出不是綠燈,而是那筆誠實紀錄——測試全過,但敵人不在裡面,別把「沒測到」當成「不會發生」。外加一筆意外收穫:好的紀律不只擋壞行為,還會擠出好行為。

到這裡,三十五個多小時的重構週結束,防線蓋完了。然後這個 repo 安靜了五天。kit 沒事,機隊有事:用它的專案默默長到了 11 個,而「哪個在跑、怎麼啟動、誰在燒錢」這三個問題的答案,只存在我的腦子裡。下一篇:11 個專案,誰在燒錢?


#claude-code