證明「有」很簡單:找到一個就結案。證明「沒有」要窮舉所有可能的地方,而查的人通常只查了一個地方就下結論。這週我的 agent 連續踩了四次,最嚴重的那一次差一點就進了週報。
它判「16 封信沒寄」,結果信早就寄出去了
事情是這樣:我要它確認一批寄給潛在學員的信到底有沒有寄出去。它做了兩件事——ls 了 lead-emails/,沒看到 2026-09-04/ 這個資料夾;然後去搜 gmat 那個帳號的信箱,零命中。兩個查法都回「沒有」,於是它下了結論:這 16 封信沒寄。
真相是:那 16 封信 2026-09-04 11:48–11:49 已經全數寄出,後來逐封驗過,16 封全是 SENT。
錯在哪?寄件走的是 personal 帳號的 support@agentcrew.cc 別名,不是 gmat 帳號。它搜的帳號從頭到尾就是錯的帳號,零命中不代表沒寄,只代表「這個帳號裡沒有」。而資料夾不存在也不代表事情沒做——那個資料夾是被目錄重構吃掉的(下一段講)。
擋下這個誤判的不是任何檢查機制,是我說了一句「我記得有記」。一個模糊的印象,推翻了兩個看起來很硬的查證動作。如果那天我沒開口,這個錯誤結論就直接進週報了。
負向斷言要窮舉可能的存放處與帳號。它只窮舉了一個。
目錄重構會靜默吃掉沒被 git track 的檔案
那個消失的資料夾,來歷是這樣:9/9 做了 official/ → docs/business/ 的四層結構重整,結果只搬了 2026-08-28,official/lead-emails/2026-09-04/(模板+out/_send-log.txt)整批消失。
查 git 全歷史,查不到任何刪除該路徑的 commit。查不到的意思不是「沒被刪」,是它從未被 track——所以重構的時候等於直接被丟掉,git 完全沒有意見,因為在 git 眼裡那些檔案不存在。
教訓很直白:重構前先 git status 確認待搬目錄裡有沒有 untracked 的產出物。git log 查不到刪除紀錄這件事,本身就是一種假的安心。
看手邊一個 repo,就說平台不支援
另一個案例在 harness 這邊。要把一個 guard 移植到 Codex 那一軌,它先去看 knowledge-base 的 .codex/hooks.json——裡面只有 SessionStart 和 Stop。它因此判定 Codex 沒有 PreToolUse 的案例,不敢移植。
實際上 user-level 的 hooks.json 有 12 個 PreToolUse。
取樣一個 repo 就下平台能力的結論,會把「這個 repo 沒用到」誤讀成「平台不支援」。這兩句話的強度差很多,而它從前者直接跳到後者,中間什麼都沒補。
「只在另一軌存在」有兩種相反的成因
最後一個案例更麻煩,因為它連窮舉都救不了。
同一輪在比對兩軌的 skill,找出「只在一邊存在」的項目。同一批裡有兩支 skill,比對結果的形狀一模一樣,結論卻完全相反:一支是真缺口(建立的時候漏掛),另一支是廢棄殘留(它服務的 pipeline 已經停產了)。
ls 對這題完全無效。存在與否這個訊號本身沒有方向性,你必須開檔看內容,才知道那個不對稱是「該補」還是「該刪」。
同一批裡還有一條類似的:audit 的「不存在」斷言要在 .claude/ 與 .codex/ 兩側都驗,cc-update-review 就是只在 codex 側被誤判成死指標。另外,大小寫不敏感的卷上先 ls ~ 看真實目錄名再判「路徑不符」——不然你比對的是自己腦中那個名字,不是磁碟上的。
這週兩個案子:一案真的是言而未行,另一案是反向誤判。前者是事情沒做,後者是事情做了但被判成沒做。兩種都會出現在週報裡,長得一模一樣。
差別只在有沒有人記得。