前言

上一篇研究如何把一本書轉成 Agent Skill。這次把視角拉回軟體交付:當 Pull Request 從 3 個檔案長到 60 個檔案,單純對 coding agent 說「請 review 這個 PR」,真的能確保每個重要檔案都有看、留言落在正確行,而且沒有用完 context 後草草收尾嗎?

alibaba/open-code-review 想處理的不是「再寫一段更好的 review prompt」,而是把不能隨機出錯的部分交給程式:Git diff、檔案過濾、coverage、並行排程、token budget、留言定位與 session persistence;只有需要理解語意和找跨檔脈絡的部分交給 LLM Agent。

這個 deterministic engineering × Agent 的切法,是 OpenCodeReview 最值得研究的地方。它也讓我們能更精確地判斷:工具能改善哪些 code review 問題,哪些品質與安全責任仍然不能交出去。

OpenCodeReview 是什麼?

OpenCodeReview,CLI 指令是 ocr,是一套以 Go 實作的 AI code review 工具。它可以檢查:

  • 工作目錄裡 staged、unstaged 與 untracked changes。
  • 單一 commit。
  • 兩個 Git refs 之間的 branch range。
  • 沒有有意義 diff 時,以 ocr scan 檢查完整檔案或目錄。

它不是只把整段 diff 丟給模型。Agent 可以按需讀取完整檔案、搜尋 repository、查看其他 changed files,再以 code_comment tool 產生結構化問題;上層程式則負責安排每個檔案、限制並行與成本、保存 session,最後重新定位與過濾留言。官方 Architecture 有完整管線說明。

官方也提供 Claude Code、Codex、Cursor、OpenCode 與通用 Agent Skill 整合。這些 integration 並沒有改變核心責任:OCR-managed 模式由 ocr 自己呼叫設定的模型;delegation mode 則由現有 coding agent 執行語意 review,ocr 仍提供檔案選擇與規則解析。

它在解決哪一種 Review 失真?

假設一個 PR 同時修改 API handler、資料模型、翻譯檔、migration 與測試。通用 Agent 常見的失真不一定是「完全不懂程式」,而是流程沒有硬約束:

  • 看了最顯眼的三個檔案,就直接總結整個 PR。
  • 不同語言或相關檔案被拆開,漏掉跨檔不一致。
  • 報告的 line number 和實際 diff 漂移。
  • context 變長後,後半段 review 明顯變薄。
  • 一次輸出大量可疑問題,讓人花更多時間排除 false positives。

OpenCodeReview 的策略,是先用程式建立 review manifest,再讓多個隔離 sub-agent 處理檔案。這不保證每個缺陷都會被發現;它保證的是「哪些檔案被選中、哪些被跳過、哪些完成或失敗」比較容易被追蹤,不必只相信一段自然語言回答。

一次 ocr review 的真實資料流

1. 先解析 Review 範圍

CLI 先載入 provider、model、template、tools、rules 與命令列參數,再依模式執行 Git:

  • Workspace:合併 staged、unstaged、untracked changes。
  • Commit:讀取指定 commit 引入的變更。
  • Range:以 merge base 到目標 ref 建立 diff。

Untracked text file 會被視為完整新增檔,因此可以在 commit 前 review;vendor、node_modules 等噪音目錄則較早在 diff provider 被移除。Git diff provider 是理解輸入邊界的第一站。

2. 用固定規則決定哪些檔案進場

每個檔案會依序檢查 binary、使用者 exclude/include、支援的副檔名和內建 test-file pattern。ocr review --preview 可以先看選取結果,不呼叫模型、也不花 token。

這裡有一個容易忽略的細節:include 可以繞過後面的 unsupported extension 與預設 test exclusion。採用前要實際看 preview,不要只以為「預設一定不會 review 測試」。五層檔案篩選 是 deterministic coverage 的核心之一。

但 v1.9.0 的 preview 也不是最終 coverage manifest。正式 review 之後還會套用可設定的 per-file token limit,oversized diff 可能在 preview 顯示 will_review=true,最後仍被排除;issue #782 在查核時仍未關閉。v1.9.0 已修正 --preview --format json 仍輸出 human text,以及 preview 建立未 finalize 空 session 的問題;因此 preview 適合核對靜態選檔,正式稽核仍要看 session manifest 的 selected/done/failed/skipped 狀態。

3. 解析每個檔案適用的 Review Rule

專案內建不同語言與設定檔的規則,也允許用 path pattern 加上團隊規範。規則不是把全部文字一次塞進 prompt,而是先依檔案特性匹配,讓每個 sub-agent 取得較聚焦的 system rule。

這比在一份很長的 AGENTS.md 寫完所有語言規定更可控,但仍要記得:rule 最後是模型 instruction,不是 compiler 或 policy engine。需要零容忍的 license、secret、schema 或 dependency policy,仍應由 static analysis 和 CI 強制執行。

4. 每個檔案交給獨立 Sub-agent

通過篩選的檔案會各自建立 message buffer,以 goroutine 並行處理,預設上限為 8。大 diff 先做一次沒有 tool call 的 plan,小 diff 直接進 main loop。

Main loop 可使用 code_searchfile_findfile_readfile_read_diffcode_commenttask_done 等工具,最多執行設定的 tool rounds。模型沒有成功呼叫 tool 時,程式會要求重試;連續空回合、context cancellation、壓縮失敗或 tool round 用盡都會停止。dispatchSubtasks 同時處理並行、timeout、panic isolation、resume 與 coverage state。

5. Context 太長時壓縮舊軌跡

OpenCodeReview 把 messages 分成 frozen、compress、active 三區。接近 soft threshold 時非同步摘要舊回合;超過 warning threshold 則同步壓縮後才繼續。初始 prompt 或單一 diff 已超過 token 上限一定比例時,程式會跳過該檔並留下 warning。

這比讓模型在 context 末端自行決定「看得差不多」更透明。不過摘要仍由 LLM 產生,可能丟失早期 caveat;token guard 能避免無上限消耗,不能保證壓縮後的 review 等同閱讀完整軌跡。

6. 留言還要經過定位與 Reflection

模型產生的 existing_code 會先用 sliding-window 對回 diff,找不到時可再做一次 LLM re-location。所有 sub-agent 結束後,review filter 會移除能由 diff 證明不正確的留言;頂層再做一次 line resolution,最後才輸出文字或 JSON。

Relocationreview filter prompt 說明「有行號」不是模型自己報一個數字。若定位仍失敗,line 會是 0,代表需要人手尋找,而不是硬貼到錯誤位置。

7. 保存 Session,才能 Resume 與稽核 Coverage

執行結果會寫成本地 session,包含完成、失敗、重用、warning、comments 與 LLM transcript 等資料。中斷後可用 session ID resume;range 或 commit review 也能列出已保存留言。

這讓 review 不只是 terminal 上一段即逝文字,同時帶來隱私責任:session 可能包含 source、diff、prompt、模型回答與缺陷描述,不能把 ~/.opencodereview/ 當成無敏感資訊的 cache。

安裝與最小使用範例

本次正式安裝基線固定在 v1.9.7/commit f269d0ce。需要 Git 2.41 以上,Node.js 安裝路徑可明確固定版本:

npm install -g @alibaba-group/[email protected]
OCR_NO_UPDATE=1 ocr version

先用互動介面設定 provider 與 model:

ocr config provider
ocr config model
ocr llm test

然後在要檢查的 repository 先看 coverage,不花模型 token:

cd your-project
OCR_NO_UPDATE=1 ocr review --preview

確認選取範圍後,再 review 目前 branch 相對 main 的差異:

OCR_NO_UPDATE=1 ocr review --from main --to HEAD

工作目錄模式則只需 ocr review;完整檔案稽核可用 ocr scan --path src/。npm wrapper 預設會在背景檢查並套用更新,因此版本敏感的開發與 CI 應設定 OCR_NO_UPDATE=1;static binary 不會自動更新。正式 CI 應用環境變數或 secret store 提供 API key,不要把真實 key 寫進 repository。互動設定會把 provider 資料寫到 ~/.opencodereview/config.json,使用共用主機時必須檢查檔案權限與備份範圍。InstallationConfiguration 有其他 binary、release 與 provider 選項。

最值得閱讀的關鍵程式碼

CLI 入口與 Review 組裝

executeReview 串起 CLI context、background、resume、LLM runtime、diff、agent 與 output,是從入口理解責任邊界的最好起點。

Agent Dispatch 與 Tool Loop

這裡有 plan、main loop、per-file dispatch、token budget、compression、resume 與 failure classification。尤其值得看 coverage denominator 先凍結、worker panic 隔離,以及 budget 到達時如何把未執行項目標成 partial,而不是假裝 review 全部完成。

檔案篩選與 Git Diff

兩個檔案共同決定「到底 review 了什麼」。評估 AI review 不能只抽樣留言品質,也要測 binary、rename、untracked、generated file、test、vendor 與自訂 include/exclude 的 coverage。

留言定位

它展示 line-level precision 不是 prompt 形容詞,而是一條可失敗、可 fallback、可檢查 line 0 的定位流程。

Session manifest

manifest.go 定義 selected、done、failed、reused、terminal state 與 warning。要把 OCR 接進 CI,這些狀態比「命令 exit 0」更能說明一次 review 是否完整。

和相近工具有什麼差異?

做法 強項 與 OpenCodeReview 的差異
通用 coding agent + review prompt/Skill 彈性高,能同時改 code、跑測試、討論設計 OCR 把檔案選取、per-file dispatch、coverage、定位與 session 做成固定程式,不只依賴模型自行安排。
SaaS PR review bot Git hosting 整合、團隊 dashboard、集中設定通常較完整 OCR 可本地執行、自選 provider、查原始碼;但 hosting、RBAC、企業治理與服務維運要自己處理。
Static analysis/linter/type checker 規則可重現、速度快,適合硬性 gate OCR 擅長跨檔語意與情境判斷,卻有模型不確定性;兩者應互補,不能互相取代。
人類 reviewer 能理解產品意圖、風險承擔與組織脈絡 OCR 適合先擴大檢查面、降低機械工作,不具備核准上線的責任。

官方 benchmark 以 50 個開源 project、200 個真實 PR、10 種語言和 2,145 則 review comments 比較通用 Agent;公開 dataset 將其中 1,505 則標為正確、640 則標為錯誤。結果主張 OCR 在相同模型下有較高 precision/F1、較少 token,但 recall 較低。v1.8.9 起把測試版本標到每一列並加入 Qwen3.8-Max 結果;查核當日 release README 也已連到第一方 AACR-Bench。AACR-Bench repository 公開 OCR/Claude Code/Codex 的 data loading、review、semantic judge 與 metrics pipeline。這比只有表格更容易查核,但資料、annotation 與 harness 仍由專案方提供,本研究沒有付費 judge credentials,也沒有重跑主圖;多數圖表列仍是舊版 OCR,不能當成 v1.9.7 的獨立回歸。維護者在 issue #684 公開的 Go 子集,最高列 OCR+Claude-4.6-Opus precision 33.33%、recall 22.99%、F1 27.21%,同樣要保留模型參數與重跑 variance 的限制。README Benchmark 最重要的訊號其實是取捨:工具明確偏向少報 false positive,因此不能把未報告等同沒有缺陷。

成熟度與維護狀態

2026 年 8 月 19 日 22:09(Asia/Taipei)查核時,GitHub API 顯示 repository 有 20,825 stars、1,484 forks;最新正式 release 與 npm latest 都是 v1.9.7,annotated tag 指向 f269d0ce。該 commit 的 source test、Windows runtime test、五個 cross-compile、三組 CodeQL、六平台 release build、GitHub Release 與 npm publish 共 19 個公開 checks 全部成功。Tag 雖含 SSH signature,GitHub API 仍回報 verified=falseunknown_key,本研究沒有下載 binary 或獨立驗證 signer。

v1.9.6 相對 v1.9.5 前進 16 commits,正式加入 Jupyter Notebook、R、Zig、Elm、Thrift、Cap'n Proto 與 Jsonnet 的選檔/規則支援,也讓 .properties.po.pot 規則真正可被 allowlist 選中,並發布 api_key_cmd/legacy auth_token_cmd credential resolver。它可從 secret helper 取值,有 60 秒 timeout、64 KiB output cap、單行驗證與 fail-closed;但命令會透過 sh -ccmd.exe 執行,代表 config ownership 本身成為 code-execution trust boundary,不能只把它理解成「不把 token 寫進檔案」。v1.9.6 releasecredential resolver PR #605 可交叉確認這段版本邊界。

隔天發布的 v1.9.7 再加入 built-in Gemini provider、OCR_GITHUB_MIRROR 安裝鏡像支援,以及一批 Go dependency 更新。v1.9.7 releasev1.9.6…v1.9.7 compare 顯示這是四個 commits 的小版更新,不是 findings 品質回歸。鏡像會改變 binary 與 checksum 的下載來源,官方文件也明示必須信任鏡像;除非公司已有受控 mirror,否則不要為了速度隨意設定第三方 domain。

main HEAD 已前進到 756203c31,相對 v1.9.7 ahead 4/behind 0;release 後才合併 JSON/SARIF progress 改走 stderr、非 TTY text output 關閉 ANSI、Skill severity flow 與 CI audience 參數等修正。v1.9.7…main compare 可查看差距。Repository 建立於 2026 年 5 月 18 日,短時間內的密集 release 顯示維護活躍,也代表升級前必須重跑自己的 review corpus。

這些資料表示專案非常活躍、包裝與 release pipeline 已能實際使用;也表示版本漂移速度高。Stars、阿里內部使用規模與官方 benchmark 都不是 API stability 或獨立安全審查。本次沒有使用 2026 年 8 月 3 日的 Trending 週增快照,也不把 repository badge 當成固定 168 小時差分。

成熟度要分層判斷:

  • CLI、npm package、release binary、文件、tests 與多平台 CI 已相當完整。
  • Session、coverage、resume、token budget 和 telemetry 顯示它不是一次性 demo。
  • 規則、prompt、provider compatibility 與輸出品質仍會隨高頻 release 改變。
  • Provider 原生 reasoning 的 replay 還在收斂:issue #805#811#812 分別記錄 tool-call replay 丟失 thinking state、Anthropic signed thinking block,以及 OpenAI Responses reasoning item 的問題;使用 resume 或長 tool loop 時,不能假設 provider-native reasoning 會完整保留。
  • 檔案選取仍有 edge cases:issue #844 所述 include/exclude pattern 大小寫問題已進 v1.9.3;處理 quoted 或 ambiguous Git path 的 PR #846 在查核時仍未合併。這些問題直接影響 coverage,所以 preview 與 session manifest 都必須納入驗收。
  • CLI output contract 仍在變動:v1.9.7 的 JSON/SARIF 在 human audience 下會等到最終文件才輸出,非 TTY text output 也可能帶 ANSI;PR #929PR #927 已在查核當日合併到 main,分別把 progress 改送 stderr、依 TTY 決定 color,但尚未發布。CI wrapper 應明確使用 --audience agent、只解析最終 stdout、分開保存 stderr,並把 output schema/color 行為納入版本回歸,不能把 main-only 修補當成 v1.9.7 contract。
  • Automation 的成功與成本語意仍有缺口:issue #931 指出 npm launcher 的 native child 若被 signal 終止可能錯誤 exit 0;issue #935 指出 --max-tools 10..29 會被接受卻仍使用預設 30;issue #949 要求把 completion token 上限從整體 template budget 分離,已因貢獻撤回而關閉,並不代表功能已實作。CI 不能只相信 process exit code、issue state 或 flag 被 parser 接受,仍要核對 terminal state、manifest 與實際 request 設定。
  • Provider 與 Windows 邊界也在收斂:issue #947 記錄 Vertex AI/Gemini tool call 的 opaque fields 未被回放;issue #933PR #934 則涉及 CRLF diff path 與 Windows ..\\ traversal guard。這些是公開 issue 與 source 可見的弱點,不是本研究已重現的 exploit,也不能把尚未合併的修補當成 v1.9.7 已有。
  • 今日新開的 reports 也直接碰到 coverage 與定位:issue #987 指出非 UTF-8 source/diff 可能影響 JSON 與行號匹配;#989 回報模型讀取不存在或已刪除 path 會耗掉 budget 並使 run 成為 partial#991/未合併 PR #992 涉及同檔相同 anchor 的第一個命中歧義;#995/未合併 PR #996 則處理 ocr scan 的 Ctrl-C propagation。本研究只核對 issue、source trace 與 PR 狀態,沒有獨立重現;它們不能寫成已證實 exploit,也不能因為有 PR 就當作 v1.9.7 已修。
  • AI review 本身仍有 false negative/false positive,官方 benchmark 也承認 recall 取捨。
  • v1.9.3 已讓同一 selected item 在 retry/resume 間有較穩定的 fingerprint,但跨多次重跑與 provider 的 semantic identity #369、semantic duplicate grouping #709 仍是公開 issues;viewer comment issue #712 已於 8 月 5 日關閉,machine-readable JSONL/manifest 仍應作為更接近稽核用途的 source of truth。

因此我會把 v1.9.7 視為可做受控 PoC 的早期產品版本,而不是因為 major version 已是 1 就直接設成 merge gate。

安全、隱私與供應鏈風險

Source code 可能離開本機

OCR 會把 diff、規則、背景資料和按需讀取的 source 送給所選 LLM provider。使用自架模型可以縮小外流面,但仍要檢查 endpoint、log、retention 與租戶隔離。私有 repository、未公開漏洞、憑證與客戶資料上線前應先做 provider data-policy review。

API key 與 Session 都是敏感資料

互動設定可以把 API key 保存到 home directory;session 則保存可回放的本地 JSONL 與 manifest。共用 runner 不應重用個人 home,CI artifact、backup、support bundle 與 debug log 也不應無條件收集整個 OCR directory。

Tool 與 MCP 擴充會放大權限

內建 review tools 主要讀 repository 與建立 comment,但不可信 diff 仍會進模型 context;自訂 tool registry 或 MCP server 會進一步擴大 prompt injection 的影響。OCR 預設可註冊 server 宣告的所有 tools,MCP setup 還能從 repository root 執行 shell command。對第三方 MCP 的 schema、setup、command、network egress 與 credential scope 應逐一審查,並明確 allowlist read-only tools;review Agent 不需要 production write token,也不應因為在 CI 裡就自動取得 deployment secrets。MCP 文件 有實際設定邊界。

Telemetry 預設關閉,但啟用後仍要治理

Telemetry 文件 表示 OTel 預設關閉,啟用後輸出 duration、file path、repo dir、token、model 與 error 等結構資料,不輸出 prompt/response 內容。這比預設上傳完整 transcript 保守,但 path、model 和錯誤仍可能揭露內部資訊;OTLP endpoint、TLS、保存期限與存取權限仍需設定。

快速 Release 也是供應鏈決策

不要在 production CI 使用未固定的 install script 或 npm latest。v1.9.2 已把 public composite Action 的內層 actions/* references 固定到完整 SHA,關閉 issue #816;但 ocr_version 預設仍是 latestissue #839 顯示 OCR binary 仍會因此漂移。發布端也有兩個不能只看 issue state 判斷的風險:issue #840 指出 npm 部分發布與 resume 只檢查版號、不比 artifact identity;它在 8 月 17 日沒有 linked PR 就被關閉,不能因此宣稱 workflow source 已修。v1.9.3 的 trusted resume 已改善輸入 identity 驗證,但不是 npm artifact identity 驗證。issue #841 仍指出持有 npm token 與 attestation 權限的 release workflow 引用 floating Action tags。npm 自動更新另有 issue #703 記錄 binary gap window。建議同時固定外層 Action commit、明確指定 ocr_version: 1.9.7、驗證 checksum/package provenance、review release diff,並在升級後用自己的 representative PR set 重跑 precision、recall、token、latency 與 coverage 測試。

採用前怎麼評估?

我會先做一個兩週、report-only 的 PoC:

  1. 固定 v1.9.7,在隔離 runner 安裝,不授予 merge、deploy 或 production secret。
  2. 選 20~50 個已由人 review 完的歷史 PR,保留已知缺陷作為小型 ground truth。
  3. 每次先保存 --preview 與 session manifest,計算 selected/done/failed/skipped coverage。
  4. 分別測小 PR、大 PR、rename、generated file、test、migration 與跨檔變更。
  5. 將 comments 分成 true positive、false positive、重大漏報與無法定位,不只看總留言數。
  6. 記錄 provider、model exact ID、OCR version、rules、token、latency 與費用。
  7. 檢查 session、config、OTel 和 CI artifact 是否含 source、path、key 或客戶資訊。
  8. 追蹤 cross-run semantic identity、near-duplicate comment 與 viewer 漏顯示等公開 issues,升級前用固定 corpus 回歸。
  9. 穩定後先讓它提供 non-blocking 建議;只有可機械驗證的規則交給正式 gate。

若團隊沒有時間標註自己的歷史 PR、沒有人處理 false positive,或期待 AI review 取代 owner review,導入後很可能只增加留言量。若問題是大型 changeset coverage 不透明、line drift 與 review 成本難以追蹤,OpenCodeReview 的工程化切法就很值得試。

研究後的個人結論

OpenCodeReview 最有價值的不是宣稱模型更會找 bug,而是承認 code review 裡有一大部分不該交給模型自由發揮。檔案選取、coverage denominator、並行上限、budget、timeout、session state 和 line resolution 都能由程式記錄;LLM 則專注在語意、脈絡與工具選擇。

我會推薦它給已經使用 AI coding agent、又想把 review 從臨時 prompt 變成可觀測 pipeline 的團隊。固定版本後,CLI 很適合做本地或 CI 的受控 PoC;但官方 benchmark、內部使用敘事與高 stars 都不能替代自己的歷史 PR 評估。它應該補強 static analysis 與人類 review,而不是成為一張自動核准變更的通行證。

下一篇會研究另一種即時 Agent 管線:speech-to-speech 是什麼?用開源模型組出可插話的即時語音 Agent

參考資料