「PR 標題寫 fix:,照理說應該會改到某段實作邏輯吧?」
昨天設計了一份給外部貢獻者 PR 用的審查清單,今天直接拿這份清單去審查一個真實案例——PR #412(跟昨天 Day 05 提到的 PR #413 是不同的兩個貢獻,症狀描述類似,但這裡要看的是完全不同的改動內容)。這個 PR 修的是 issue #410:使用者把 PHP 專案放在子目錄(例如 apps/api),並在設定裡用 ${workspaceFolder} 這個變數指定 --configuration 路徑,結果「執行測試」正常運作,但「探索測試」(VS Code Test Explorer 讀取測試清單的階段)卻讀不到正確的設定檔——同一個變數,兩個階段的解析結果不一致。
貢獻者送出的修復方式,看起來合情合理,我用 Day 05 那份審查清單走一遍,結果卻出現一個沒預料到的狀況。
查證 gh pr diff 412 的完整內容後,會發現一件出乎意料的事:這個 PR 唯一的改動,是在 Configuration.test.ts 裡新增一個測試案例,斷言「當 --configuration 參數帶著 ${workspaceFolder} 這個變數時,getConfigurationFile() 在探索階段能正確解析出實際路徑」。整個 diff 裡沒有出現任何一行production 程式碼的修改。
如果只看 PR 標題「fix: resolve \ in discovery --configuration」,會很自然地預期 diff 裡應該有一段邏輯被改掉——但實際上沒有。
套用 Day 05 的審查清單,AI 在幾個項目上表現得很紮實:
--configuration 帶 ${workspaceFolder} 變數、探索階段解析)用一組對照來看 AI 審查在這個層面能做到什麼:
❌ 沒有查證就下結論:
「PR 標題是 fix,應該有修到 bug,測試也加了,看起來沒問題,可以合併。」
→ 沒有真的核對 diff 內容,只是憑標題跟描述的字面意思做判斷
✅ 逐項對照 diff 實際內容:
「這個 PR 的 diff 只有測試檔案,沒有production 程式碼改動。
這代表兩種可能:(1) 修復邏輯已經在更早的改動裡合併過,
這個 PR 只是補上遺漏的回歸測試;(2) 這個 bug 其實不需要改
production 程式碼,只是先前沒有測試覆蓋到這個情境。
兩種情況都需要進一步查證,不能直接假設『有 fix 就該有程式碼改動』。」
→ 對照 diff 實際內容,而不是只信任標題跟描述
AI 審查清單能做到的,是誠實地把「這個 PR 實際改了什麼」攤開來,不被標題的措辭牽著走——這件事本身已經是價值,因為人在快速瀏覽 PR 列表時,反而最容易被標題誤導,直接照著標題的字面意思腦補這個 PR 做了什麼。
但這份審查清單完全沒辦法回答一個更關鍵的問題:「這個 bug 的實際修復邏輯,到底是不是已經在更早的地方合併過了?」
要回答這個問題,需要去追溯 Configuration 這個類別的變更歷史、對照 issue #410 回報的版本號、確認在那之前有沒有相關的 commit 已經處理過 workspace 變數替換的時序問題。這件事需要的不是「讀懂這一個 PR 的 diff」,而是「熟悉這個專案過去幾週/幾個月的變更脈絡」——這正是 AI 在單獨審查一個 PR 時,結構性地拿不到的資訊,除非明確要求它去查證整個檔案的 commit 歷史。
如果沒有人主動意識到這個問題該被問,AI 給出的審查結論很可能就停在「測試涵蓋合理、改動範圍乾淨,可以合併」——這個結論不是錯的,但它沒有觸及「這個 PR 存在的必要性」這個更深一層的問題。AI 能審查『這個 PR 寫得好不好』,但『這個 PR 到底解決了什麼、有沒有必要』,需要對專案歷史有記憶的人來判斷。
回顧這一週:從介紹這個專案本身、維護者的日常,到 issue 分類、判斷重複回報、設計 PR 審查清單,一路到今天實際套用清單在一個真實案例上——核心命題一直沒有變:AI 能加速機械性、可規則化的工作,但需要專案歷史脈絡、需要判斷「這件事有沒有必要」的地方,終究要人來補。
回想你上一次快速瀏覽一份 PR 列表的經驗:有多少次你是靠標題判斷這個 PR 做了什麼,而不是真的點進去看 diff?如果今天要你對每一個 PR 標題「有沒有跟 diff 內容一致」做一次核對,你覺得會抓到幾個不一致的地方?
明天進入第二部,從「審查別人的貢獻」轉向「AI 自己動手改專案設定」——e2e 測試環境的 CI 設定,是 AI 最容易踩坑的地方之一。