當 PR 看起來沒問題,卻還是覺得哪裡不對
如果你已經用 AI 出貨超過幾個星期,你大概很熟悉這種感覺。
你打開一個 PR。程式碼夠乾淨。命名還不錯。測試也有。看起來沒有任何明顯壞掉的地方。但你就是覺得哪裡怪怪的。
也許邊界有點模糊。也許 contract 只是被暗示,卻沒有被明確寫出來。也許 happy path 被覆蓋了,但真正的業務規則還留在某個人的腦子裡。你感覺得到風險,卻指不出哪一行會直接爆炸。
這就是新的審查問題。
大多數團隊現在還是把 AI 輔助開發塞進舊工作流:寫 prompt、產生 diff、開 PR,然後請資深工程師仔細檢查程式碼,希望能抓出被破壞的 invariants、漏掉的邊界情況、架構漂移,以及藏起來的風險。
當幾乎所有實作都還是人自己寫的時候,這個模型很合理。當模型能一口氣產出實作、第一版測試套件、schema,甚至連 contract scaffolding 都一起生出來時,它就不再那麼合理了。
一旦到了那一步,把資深工程師的注意力花在逐行審程式碼上,就不再是槓桿最高的地方。
真正的問題不再是:「這個函式看起來合理嗎?」
真正的問題是:「在這個函式出現之前,我們有沒有先把正確的行為、邊界和 invariant 定義清楚?」
這就是 AI 帶來的工作流反轉。程式碼審查不會消失。但重心會往上游移動。在 AI 時代,程式碼審查會變成規格審查。
為什麼這個轉變感受上差這麼多
很長一段時間裡,大多數工程團隊都把規格當成輔助材料。
真正重要的是程式碼。doc comment 只是提示。ADR 是你有空才會看的背景脈絡。schema「只是驗證」。Gherkin 檔案如果有人願意維護,算是加分。
這個層級關係正在瓦解。
如果 LLM 能快速而反覆地把規格轉成各種實作工件,那規格就不再只是次要材料。它會變成整個系統其餘部分據以派生的源頭工件。
而這會改變哪裡最適合、也最便宜去抓錯。
如果規格含糊,模型就能把錯的東西實作得漂漂亮亮。它會交給你乾淨的程式碼、看似合理的測試,以及一種假的安心感。再強的程式碼審查,也可能錯過真正的問題,因為 bug 不在語法裡。bug 在意圖裡。
這也是為什麼現在這個時刻既麻煩又關鍵。AI 讓人更容易產出看起來很有說服力的結果,也讓你對自己到底要求了什麼這件事變得更不能馬虎。
如果規格精確、有邊界、而且可測,所有事情都會變簡單。實作更簡單。驗證更簡單。審查更簡單。CI 也更強。
這就是為什麼最有價值的人類審查工作,正在從手動稽核每個分支,轉向把最先定義分支行為的那個工件收得更緊。
規格不是一份巨大的需求文件
當人們聽到「規格」這個詞時,腦中常常會浮現一份臃腫的文件:沒有人想寫,六週後也沒有人相信它還是對的。
但這裡重要的不是那種文件。
在務實的 AI 輔助工作流裡,凡是能把預期行為界定得足夠清楚,讓生成與 enforcement 能夠運作的工件,都算規格。
那可能是:
- 描述 boundary rule 的 Markdown ADR
- 定義外部輸入形狀的 Zod schema
- 帶有明確 doc comment 的函式簽名
- 捕捉可觀察行為的 Gherkin 情境
- 寫出前置條件與後置條件的 contract 區塊
- reducer 模型或狀態轉移表
這些東西都不需要很重。它們只需要清楚到足以讓工具對它們做出有用的事。
真正重要的門檻就在這裡。有用的規格不只是人看得懂,還要能被 codebase 周圍的系統拿來採取動作。
優秀的審查會開始長成什麼樣子
在舊模型裡,資深工程師會把精力花在這些問題上:
- 這個實作乾不乾淨?
- 作者是不是漏了某個邊界情況?
- 這些測試夠不夠扎實?
- 這個 import 有沒有違反邊界?
這些問題還是重要。只是它們不再是第一順位、槓桿最高的問題。
在以規格為先的工作流裡,更有價值的問題是:
- contract 本身真的正確嗎?
- schema 定義的是不是真正的邊界?
- 業務規則完整嗎?
- ADR 精確到足以 enforcement 嗎?
- 這些列出的性質,真的有表達出實際語義嗎?
這些是更好的審查問題,因為一個好答案可以一次改善多個工件。
如果你把一份模糊的 ADR 收緊,你一次就改善了架構規則、實作指引和 CI 裡的 enforcement。
如果你修掉一個薄弱的 schema,你一次就改善了執行期驗證、型別推導和程式碼生成品質。
如果你把 contract 磨得更尖銳,你一次就改善了實作、測試,以及對 mutation testing 的抗性。
這就是槓桿差異。你不再是一個一個檢查輸出,而是在審查那個會塑造輸出的東西。
為什麼傳統程式碼審查開始出現裂縫
傳統程式碼審查的前提是:人類是主要作者,而審查者是在讀成品程式碼,藉此判斷另一個人的思考過程是否紮實。
有了 AI,這個前提每週都在變弱。
模型可以在幾秒內產出五十行看起來合理的程式碼。再五十行也一樣快。之後再來五十行。如果整個流程都靠審查者手動從這股輸出流裡抓出埋著的語義漂移,那審查面就會比人類注意力擴張得更快。
這會形成一種糟糕的均衡:
- 程式碼生成速度變快
- diff 變得更大,或更頻繁
- 審查疲勞上升
- 語義信心下降
- 團隊開始用感覺、直覺,以及「看起來可以」來補破網
這不是可擴張的策略。這只是把風險累積起來,再用好看的排版包住它。
更好的做法,是先降低你對主觀審查的依賴。把更多意義推進可被審查、可被 deterministic checks 驗證的規格裡。接著讓機器去檢查程式碼是不是還和那些意義對齊。
讓這件事成真的,是 CI
只有當規格真的和 enforcement 綁在一起,這種工作流反轉才成立。
否則你只是把文件換個名字,然後希望大家會比較尊重它。
重點是把規格變成可操作的東西。
這表示:
- 架構決策會編譯成 dependency rules
- schema 定義執行期安全且型別安全的邊界
- contracts 會生成可執行的檢查
- 性質清單會驅動測試生成
- 關鍵語義會變成合併關卡
一旦做到這一步,CI 就不再只是被動的建置系統,而會變成讓實作持續對齊意圖的機制。
這也是為什麼 living specifications 對一般團隊來說,終於變得實際了。歷史上,文件會腐壞,是因為沒有人有時間手動把文字和程式碼一直對齊。
AI 改變了撰寫與更新這些工件的經濟帳。CI 改變了 enforcement 的經濟帳。
兩者都要有。沒有 enforcement 的 AI,只會帶來包裝精美的漂移。沒有好規格的 enforcement,只會帶來僵硬的混亂。
硬性護欄,柔性審查
這也是 Autotomy 這套想法裡,我越來越覺得對的一部分。
概念很簡單:把不能談判的規則放進硬性護欄,然後把人類審查留給那些真的需要判斷力的部分。
這代表型別、schema、contracts、dependency rules,以及 deterministic checks 來處理已知的 failure modes。它們每次都跑。不會累。不會因為 diff 排版好看就分心。也不在乎程式碼是資深工程師還是語言模型產生的。
接著,審查這一層就會變小,也會變得更好。
你不再把資深工程師的注意力浪費在系統本來就能自動擋下來的東西上,而是把它花在取捨、語義、interface 和架構上。你會問:邊界是不是正確?contract 誠不誠實?替換進來的實作真的滿足 interface 嗎?系統是變得更容易改,還是更難改?
最後那點非常重要。
以規格為先的工作方式,最健康的副作用之一,就是它會逼你做出更乾淨的切點。只要一個 module 滿足 contract、通過檢查,它就能被替換,你就不會再把每個實作都當成聖物。你會開始為安全替換而設計,而不是為痛苦保留而設計。
這個轉變很細微,但它會改變團隊處理成長的方式。codebase 不再像是一個只能從內部小心修補的東西。它會開始像一個有明確接縫的系統。
這對資深工程師其實是好消息
這個轉變不會讓資深工程判斷變得比較不值錢。它只會讓它更聚焦,也更重要。
資深工程師最有價值的地方,不再是充當人肉語法 diff 引擎。他們最有價值的地方,是在模糊被消解、invariants 被選定、interface 被塑形、取捨被明講的地方。
這代表會有更多時間花在:
- 寫精確的 ADR
- 定義 contracts 和 schema
- 審查語義變更,而不是風格變更
- 決定哪些性質值得 enforcement
- 把架構轉成能在合併時執行的規則
這才是昂貴注意力更值得去的地方。
機器很擅長把實作細節補完。資深工程師仍然更擅長決定:當系統承受壓力、被修改、被擴張時,哪些東西必須持續成立。
你不需要把整個流程全部推翻重來
這聽起來可能比實際上更大。
你不需要發起一場形式化方法運動。你不需要停止出貨。你不需要用流程把整個團隊埋起來。
先做一個很窄的轉變:把某一類規格當成一級、必須被審查的工件。
實際的順序可以長這樣:
- 在關鍵邊界上要求精確的 doc comments 和 schema
- 把 ADR 變更視為需要資深審查的項目
- 從那些工件生成測試和 contracts
- 在 CI 裡 enforcement 架構與 contract 漂移
- 降低只談風格的審查意見權重,把焦點轉到語義審查
這樣就足以改變文化。
當團隊感受到更好的規格能減少下游審查磨損,這個模型就會開始自我強化。審查會更銳利。diff 不再那麼可怕。信任會上升。
真正的策略轉變
在 AI 上贏的團隊,不會只是把程式碼生成得更快的團隊。
它們會是那些把人類注意力移到工作流裡最窄、槓桿最高位置的團隊。
那個位置就是規格。
當規格變成主要工件,程式碼就不再是唯一值得逐行審查的東西。它會變成一個更有紀律的系統所產出的其中一個結果。
這才是真正的轉變。
實作仍然重要。非常重要。但越來越多時候,最重要的審查決策,是在實作存在之前就發生了。
這也就是為什麼,在 AI 時代,程式碼審查會變成規格審查。