Code Review and Quality — 換用開源 Skill 的背景與使用心得

背景 開發流程中,每個 PR 合併前都需要經過 code review,目前這個環節以 AI 審查作為輔助。最…

背景

開發流程中,每個 PR 合併前都需要經過 code review,目前這個環節以 AI 審查作為輔助。最初採用的是從 Claude Code 抓取下來的原生 code review skill,但在實際使用過程中出現了以下問題。

原生 Skill 遇到的問題

1. 移植困難

嘗試使用 DeepSeek harness 加入評審時,因為抓取下來的 skill 可能並不完整、難以控制變因,導致只能在 Claude Code 上使用到完整的 skill,無法移植到其他環境。

2. 時間過長、消耗過大

原生 code review 會呼叫子 agent 執行,在開啟 Fable 模型的狀態下,模型選取會被延續到子 agent 上,讓該次任務的消耗量極大幅度提升。

解決方案

基於上述兩個問題,捨棄了 Claude Code 原生的 code review skill,改為向外部開源資源探索類似的技能。剛好在近期的討論中看到 agents-skills 這個開源 repo 有相關技能,因此改為使用這個新的 skill。鏈接如下

agent-skills開源repo的code review

實驗環境

項目DeepSeek 側Claude Code 側
執行環境0814 開源的 DeepSeek harness(dsh),極簡模式Claude Code VSCode 插件
模型DeepSeek V4 ProFable 5
Reasoning effortmaxmax
脈絡狀態全新應用,無累積記憶已有累積記憶
skill 載入方式harness 尚無安裝 skill 的機制,每次將整段 code review skill 貼進輸入框,結尾加上審查指令同樣以貼上 skill 全文的方式執行

使用結果

1. 兩代 skill 的審查產出差異

回頭把兩個時期留下的審查紀錄拿出來對照(原生 skill 累積 9 次、開源 skill 26 次以上),產出形態的差異很明顯:

面向Claude Code 原生 skill開源 skill
執行方式多 agent fan-out(審查報告自述「8 個角度審查」「多 agent 掃描」)單 agent 走固定流程
驗證手段以讀碼核實為主,內文沒有測試/lint 實跑紀錄每份附「獨立重跑」區塊(test / tsc / lint / build 的實跑結果與通過數字)
單輪發現量8–13 條,分「合併前修/次一級/follow-up/已排除疑點」多層清單1–6 條,直接分級(Required / Optional / Nit)
收斂輪數多輪迭代(曾有一個大型 PR 跑了 4 輪才收口:第二輪又掃出 10 條、第三輪還有修復引進的新回歸)最多 2 輪(初審+複審驗收)
固定輸出版型無,段落結構隨當輪內容自由組織有(範圍確認 → 實跑驗證 → 分級發現 → 裁決勾選欄),但需外加約束字串防止退化(見下一章第 3 點)
裁決無固定 Verdict 欄位,結論寫在開頭段落固定 Approve / Request Changes,且綁定「Required 是否清空」
呈現位置單則總評為主,部分輪搭配行內 inline comment(單一 PR 最多掛過 20 條)一律單則總評 comment
可移植性只能在 Claude Code 上跑同一模板可跑在 DeepSeek harness 上(下一章的多模型對照因此才可行)

整體來說,原生 skill 是「廣度掃描器」:多角度平行掃、每輪大量發現、靠多輪迭代收斂——這也是消耗大的直接來源;開源 skill 是「單線審查員」:範圍確認 → 實跑驗證 → 少量分級發現 → 明確裁決,一到兩輪收口。單輪發現量變少,但深度可以靠多模型併行(見下一章)補回來。

另一個值得注意的連動:「實跑測試/lint」是開源 skill 才引入的驗證手段——原生時期靠子 agent 讀碼核實,本機硬體不影響審查時間;下一章的硬體變因正是換 skill 之後才出現的新特性。

2. 成本降低

時間與消耗雙成本下降。同樣選擇 Fable 5(max effort),以 100 美元 Team 方案的五小時用量上限為基準:

Skill單次審查消耗(佔五小時上限)
Claude Code 原生 code review約 20%
開源 skill(小型 PR)可忽略不計
開源 skill(較大 PR)最高約 5%

新版 skill 的使用觀察

以下幾點與原生 skill 無關,是新 skill 用出來之後才浮現的變因與問題,之後不管換不換 skill 都適用。

1. 硬體是運行效率的變因

code review skill 在審查過程中會實際執行 npm run test 或相關 lint 校驗來驗證程式碼,這些指令是在本機運行的,因此整體審查時間不只取決於模型,也會受到電腦本身效能的影響。用同樣的 skill 比較不同環境的審查時間時,需要把硬體當作一個變因來看待:

硬體運行效率
13th Gen Intel(R) Core(TM) i7-1355U (1.70 GHz)顯著較弱
Apple M5顯著較佳

也就是說,同樣的 PR、同樣的模型與 skill,在不同機器上跑出來的總時間可能有明顯落差,這部分的差異不應歸因於 skill 或模型本身。

後續若要在線上 CI 或其他自動化流程中執行這類審查,需要把硬體規格對時間效率的影響納入考量。若期望不拖累開發效率,應使用較高規格的設備,或重新設計 skill 的執行模式(例如減少本機測試與 lint 的執行比重)。

2. 模型是審查深度的變因

使用同樣的 skill、同一個 PR,不同模型的審查深度與處理時間差異明顯(以某次同一 PR 的審查為例):

模型處理時間審查結果審查深度
Fable 5(max effort)2 分鐘Approve較淺
DeepSeek V4 Pro(max effort)20 分鐘Request Changes較深,事後查證確實挖掘出 Fable 沒找到的問題

處理時間為當時的個人感知,非嚴謹計時。由於審查流程多為手動操作(觸發與貼文都有人工延遲、兩份審查常一併貼出),comment 時間戳無法回推各模型的實際執行時長;僅少數輪次兩份審查的貼文相距約 28–30 分鐘,方向上與此觀察一致。真實的時間差異需要在控制變因(同時啟動、完成即貼)的條件下另做嚴謹驗證。

目前累積連續 19 個 PR、共 26 次 review 的觀察,兩個模型的裁決分布如下:

模型Request ChangesApproveRC 比例
DeepSeek V4 Pro(26 輪)151158%
Fable 5(同批 25 輪,1 個 PR 未審)52020%

兩邊裁決分歧的 12 輪中,11 輪是 DeepSeek 較嚴、僅 1 輪相反(DeepSeek 給 Approve、Fable 給 Request Changes)。也就是說 DeepSeek 除了能挖掘到較深的問題外,整體審查結論也更保守——同樣的問題清單下,DeepSeek 可能給出 Request Changes 而非 Approve。幾個事後查證屬實的實例:

  • 案例一:同一個 PR,Fable 明確寫「使用者可見錯誤訊息的脫敏防線未被繞開」給 Approve;DeepSeek 指出未脫敏字串直接外顯是安全回歸、給 Request Changes。審查貼出後幾分鐘內就有修正 commit 收掉該問題,修完才合併——DeepSeek 的發現被接受並落地。
  • 案例二:DeepSeek 初審指出最關鍵的一條串流路徑拿不到截斷旗標、「核心目的只做了一半」給 Request Changes;Fable 初審 Approve 並宣稱「三個截斷點全驗過」,後續增量審查自承上一輪漏了這條路徑。
  • 案例三:同一個問題(排程路徑的外部可控檔名未清洗),Fable 列為不擋合併的 Consider 給 Approve,DeepSeek 列為 blocking finding 給 Request Changes——「同樣的問題清單、不同裁決」的直接例子。

不過因為 DeepSeek 漲價、且目前開發節奏較為緊湊,暫停了 DeepSeek V4 Pro 的併行審查方式。可先簡單假設不同廠商的模型確實會有不同表現,待後續建立自動化審查、且成本允許時,再做較為完整的評測。

更值得期待的是,不同廠商的模型交叉審查,有機會挖出單一模型漏掉的潛藏問題,讓審查結果更可靠。

3. 輸出版型會隨使用逐漸簡化,需要外加約束字串

以貼全文的方式使用 skill 一段時間後,發現兩邊的輸出都會逐漸偏離 skill 要求的版型、往總結式退化,上傳到 comment 的完整程度也跟著下降。回頭看留下的審查紀錄,退化軌跡很清楚:

  • DeepSeek 側:最初幾次是約 6,400 字元的完整版型,之後一路縮水,用到第 9–11 個 PR 前後只剩約 1,400 字元;
  • Fable 側:前 8 個 PR 還維持結構化版型(約 1,700–2,100 字元),之後開頭直接變成「審查結論:Approve ——」的總結式(約 1,200–1,500 字元)。

發現後在輸入中加上約束字串:「嚴格按照要求版型,請不要簡化或是只使用總結式的方式」。效果是斷崖式的:從加上約束後的第一輪起(兩邊同輪切換),所有 comment 都回到完整版型——帶 Context 檢查清單、Verification 實跑紀錄與 Verdict 勾選欄,長度回到 3,000–5,400 字元以上。加約束前兩邊共 34 則沒有一則帶完整檢查清單,加約束後 14 則全部都有。

對應的結論:會考慮把這段約束字串直接整合進 skill 本身,省去每次從網路上複製 skill 全文再手動補約束的流程,也讓版型不再依賴使用者記得加這句話。

結論

這次換用開源 skill 解決了原生方案的兩個痛點:審查流程可以移植到不同模型的 harness 上,單次消耗也從約 20% 降到 5% 以下。更有價值的是,同一份 skill 跑在兩個模型上之後,「審查」本身變成了可以觀察的對象——硬體決定跑多快、模型決定看多深、版型約束決定輸出品質能不能維持,三個變因各自獨立、也各有對策。

接下來的方向:短期先把版型約束字串整合進 skill 本身;待成本與節奏允許時,再把多模型交叉審查納入自動化流程,做一次較完整的評測。

發表留言