open-code-review:面向工程可信的CLI优先代码审查Agent 1. 这不是又一个“AI代码审查工具”open-code-review 的真实定位与设计哲学你点开 GitHub看到一个叫open-code-review的仓库README 第一行写着 “An open-source, CLI-first code review agent powered by LLMs”。这时候大多数人会下意识划走——又一个套着 LLM 外壳的 PR 检查器毕竟市面上已经有 dozens 个标榜“AI Code Review”的项目有的集成进 VS Code 插件弹窗里有的塞进 GitLab CI 流水线当个装饰性步骤还有的干脆做成 SaaS 网页要求你上传代码、授权 token、填邮箱、等审核报告……结果呢要么是泛泛而谈的“建议添加注释”要么是误报率高得离谱的“疑似内存泄漏实际是 Rust 的所有权转移”再或者就是卡在Loading...十分钟最后返回一句 “Model is busy. Please try again later.”。但open-code-review不是这样。它从第一天起就拒绝做“审查结果生成器”而是选择做“审查意图翻译器”——把人类工程师真正关心的、藏在 git diff 里的上下文精准喂给 LLM再把 LLM 的推理过程原样、可追溯、可复现地暴露给你看。它不承诺“自动修复 bug”但保证你每次运行ocr review --pr123得到的不是一坨 JSON 报告而是一份带时间戳、带 diff 行号锚点、带模型调用链路、带 prompt 版本哈希的审查日志。它甚至默认禁用任何远程 API 调用所有 LLM 推理都跑在本地 Ollama 或 LM Studio 实例上除非你明确--remote-model claude-3-haiku。这背后是一套非常克制的设计哲学Code Review 的核心矛盾从来不是“能不能发现 bug”而是“能不能让 reviewer 快速建立上下文共识”。传统人工 Review 靠的是团队成员对业务逻辑、历史包袱、模块边界的共同记忆而 LLM 没有记忆只有 prompt。open-code-review的全部工作就是把 git diff 里那几行新增/删除的代码连同它所在的函数签名、前导注释、相邻测试用例、甚至最近三次 commit message 的语义摘要打包成一份结构化、最小必要、无噪声的 prompt 上下文。它不追求“全量扫描整个 repo”只聚焦于本次变更的“影响域切片”——比如你改了src/auth/jwt.rs它会自动提取src/auth/mod.rs的 pub 声明、tests/auth_token.rs中相关 test 函数、以及Cargo.toml里 jwt 相关依赖的版本变更记录然后把这些碎片按语义权重排序后喂给模型。所以它不是一个“替代 reviewer”的工具而是一个“放大 reviewer 认知带宽”的杠杆。我上周用它帮团队审一个支付回调幂等性重构原本需要 40 分钟逐行比对旧逻辑和新状态机用ocr review --diff-filepayment-idempotent.patch --context-depth2后输出里直接标出三处关键风险一处是if let Some(existing) cache.get(key)缺少Arc::clone()导致潜在的Sendtrait 冲突LLM 结合了 Rust 的 Send/Sync 规则和当前 crate 的 async runtime 配置推断出来一处是测试用例中 mock 的redis::Client::set_ex返回值类型与新实现不匹配它自动解析了mockall的 mock 定义和 impl block还有一处是文档注释里写的“超时后自动重试”与实际代码中tokio::time::timeout的 fallback 逻辑矛盾它对比了 doc comment 和?操作符后的 error handling 分支。这些都不是靠关键词匹配找出来的而是模型在它精心构造的上下文里完成了跨文件、跨抽象层级的语义一致性校验。提示open-code-review的核心价值不在“它说了什么”而在“它为什么这么说”。它的输出里每一条评论后面都跟着[CONTEXT: src/auth/jwt.rs#L87-92]、[PROMPT_VERSION: v0.4.2-ctx-compact]、[MODEL: llama3.1-70b-instruct-q8_0]这样的元信息。这不是炫技而是让你能在三天后回看这条评论时立刻知道它是基于哪段上下文、哪个 prompt 模板、哪次模型加载产生的——这对建立团队对 AI 辅助的信任至关重要。没有可追溯性就没有可问责性没有可问责性AI Review 就永远只是锦上添花的玩具。2. CLI 是它的呼吸方式为什么必须从终端启动而不是点一下按钮几乎所有对标工具都提供 Web UI 或 IDE 插件入口唯独open-code-review的文档首页第一行命令就是curl -fsSL https://raw.githubusercontent.com/open-code-review/cli/main/install.sh | sh然后紧跟着ocr init --model-path ~/.ollama/models/llama3.1:70b ocr review --pr456 --strictnesshigh这不是故作清高而是由它的使用场景决定的——真正的 Code Review 发生在开发者最专注的时刻刚写完最后一行代码、git add .之后、git commit之前或者git push origin main被 CI 拦住、提示 “PR requires review” 的那个瞬间。这个时刻你的手指就在键盘上眼睛盯着 terminal大脑还停留在刚刚调试的 call stack 里。如果此时要你切到浏览器、打开某个 SaaS 页面、粘贴 PR URL、等待页面加载、再点击 “Run AI Review”这个上下文就断了。你会分心去刷邮件会想起待办事项会顺手git checkout -b开始下一个任务……审查意图就此蒸发。CLI 的不可替代性在三个关键环节体现得淋漓尽致2.1 Diff 输入的零摩擦集成open-code-review不要求你提供 PR URL也不要求你 clone 整个 repo。它原生支持四种 diff 输入源输入方式示例命令适用场景关键优势Git 工作区当前变更ocr review --staged本地 commit 前快速扫描无需git diff patch手动导出直接读取 index指定 commit 范围ocr review --commit-range HEAD~3..HEAD审查一组连续提交自动合并多个 commit 的 diff避免重复分析相同文件标准 diff 文件ocr review --diff-file my-feature.patch离线审查、CI 环境复现支持-p1/-p2补丁格式兼容所有 git diff 输出GitHub PR 元数据ocr review --pr123 --repoorg/repo与 GitHub Action 集成不拉取代码只 fetch PR 的filesAPI 和commitsAPI解析出最小 diff 集注意最后一项它从不git clone。它调用 GitHub API 获取GET /repos/{owner}/{repo}/pulls/{pull_number}/files拿到的是一个 JSON 数组每个元素包含filename,patch即该文件的 diff 内容statusadded/modified/deleted。它直接把这个patch字段喂给上下文构建器跳过了整个文件系统 I/O 和语言 parser 加载环节。实测下来处理一个 20 个文件、总计 1500 行 diff 的 PR从 API 请求到 LLM 输出平均耗时 8.3 秒本地 llama3.1-70b而同等规模下某知名 SaaS 工具的 Web UI 需要 47 秒——其中 32 秒花在前端渲染、API 轮询和“正在加载模型…”的 spinner 上。2.2 模型配置的原子化控制ocr init生成的~/.config/open-code-review/config.yaml长这样default_model: name: llama3.1:70b endpoint: http://localhost:11434/api/chat # Ollama 默认 temperature: 0.1 max_tokens: 2048 models: - name: deepseek-coder:33b endpoint: http://localhost:11434/api/chat context_window: 128000 system_prompt: | You are an expert Rust developer reviewing production code. Focus on memory safety, async correctness, and API contract adherence. Never suggest stylistic changes unless they impact correctness. - name: qwen2.5-coder:14b endpoint: http://localhost:11434/api/chat context_window: 64000 system_prompt: | You are reviewing Python backend services for financial compliance. Prioritize data validation, idempotency, and audit trail completeness.这里的关键是system_prompt的 per-model 配置。不是全局一套 prompt 模板硬套所有语言而是为不同模型、不同业务域预设专用的 system role。当你运行ocr review --model deepseek-coder:33b --pr789它会自动加载对应 model 的 system_prompt并将本次 diff 的上下文注入 user message。这种设计源于一个血泪教训我们曾用同一个You are a helpful coding assistantprompt 去审 Rust 和 Python 代码结果 Rust 模型疯狂纠结strvsString的所有权转移Python 模型却对async def函数里漏掉await视而不见——因为 prompt 没告诉它“你现在在审什么”。CLI 让这种精细化控制成为可能。GUI 工具要么让用户在设置页里填一堆文本框极易出错要么干脆固化一套 prompt失去灵活性。而ocr config set model.deepseek-coder.system_prompt ...这样的命令配合 shell history 和git diff查看修改让 prompt 迭代变得像改代码一样自然。2.3 审查结果的管道化与自动化open-code-review的输出默认是 human-readable 的 markdown 格式但它的真正威力在于--format json和--output -# 直接喂给 jq 做过滤 ocr review --pr123 --format json | jq .comments[] | select(.severity critical) # 导出为 SARIF接入 SonarQube ocr review --pr123 --format sarif review.sarif # 在 CI 中失败时打印高危问题 if ! ocr review --pr$PR_NUMBER --strictnesshigh --fail-oncritical; then echo Critical issues found: ocr review --pr$PR_NUMBER --format short --limit5 exit 1 fi这种 Unix-style 的管道哲学让它能无缝嵌入现有工程链路。我们团队的.github/workflows/pr-review.yml里open-code-review步骤只有三行- name: Run Open Code Review run: | ocr review \ --pr${{ github.event.pull_request.number }} \ --repo${{ github.repository }} \ --format sarif \ --output /tmp/ocr-report.sarif - name: Upload SARIF uses: github/codeql-action/upload-sarifv2 with: sarif_file: /tmp/ocr-report.sarif没有额外的 webhook、没有中间服务、没有状态同步——它就是一个二进制输入是 PR 元数据输出是标准 SARIF剩下的交给 GitHub 原生的 code scanning。这种极简集成正是 CLI 赋予它的“隐身能力”它不试图成为流程中心而是作为流水线里一个可插拔的、职责单一的齿轮。注意open-code-review的--strictness参数不是简单的阈值开关。它控制的是上下文构建器的深度和模型的推理策略。low模式只提取 diff 文件本身的函数签名和相邻 5 行medium会额外抓取该文件的mod.rs声明和最近一次修改该文件的 commit messagehigh则触发 full dependency graph walk——它会解析Cargo.toml或pyproject.toml找出本次变更直接影响的所有 public API再反向追踪这些 API 被哪些测试用例和外部 crate 调用。这意味着--strictnesshigh下的审查耗时可能是low的 3.2 倍但它发现的往往是架构级隐患而非单行 bug。3. LLM Agent ≠ LLM CLI拆解open-code-review里的 Agent 架构网络热词里总把 “Agent”、“LLM”、“CLI” 当作可以随意拼接的乐高积木仿佛只要把llm.generate()包一层argparse就叫 Agent。但open-code-review的 Agent 层是经过严格分层设计的它由四个不可分割的组件构成Context Orchestrator上下文编排器、Prompt Compiler提示词编译器、Model Router模型路由、Feedback Loop反馈闭环。缺一不可否则就退化为一个 fancy 的curlwrapper。3.1 Context Orchestrator不是拼接而是语义编织大多数工具的“上下文”就是把 git diff 原样塞进 prompt。open-code-review的 Context Orchestrator 则像一个资深 reviewer 的大脑——它知道哪些信息重要哪些是噪音哪些需要展开哪些应该折叠。它处理一个src/http/handler.rs的 diff 时执行以下步骤Diff 解析用git apply --check --verbose验证 patch 有效性提取出/-行的精确位置file:line:col。AST 边界识别调用tree-sitter-rust或对应语言的 parser定位被修改行所属的 AST node 类型function_definition,struct_definition,impl_block。影响域推导如果是fn handle_payment(...)修改它会查找所有#[cfg(test)] mod tests中调用handle_payment的地方如果是impl PaymentService for StripeClient的修改它会解析lib.rs中pub use http::handler::*的 re-export 链确定哪些外部模块可能间接依赖此 impl如果是#[derive(Debug, Clone)]的增删它会检查该 struct 是否实现了Send/Sync并关联到tokio::spawn的调用点。上下文压缩将上述信息按语义权重排序用 LZW 压缩算法对重复 token如pub fn,- Result,#[derive(进行去重确保最终 prompt 在模型 context window 内。这个过程不是静态模板填充而是动态图遍历。它维护一个轻量级的 in-memory dependency graph节点是文件/函数/类型边是use、call、implement关系。每次 diff 输入它都从变更点出发做 BFS但 BFS 的深度和广度由--strictness和--context-depth参数实时调控。实测表明对一个中等复杂度的 Rust crate--context-depth2平均引入 12.7 个额外文件片段而--context-depth3会激增至 43.2 个——但后者发现的跨模块竞态条件问题是前者完全无法覆盖的。3.2 Prompt Compiler把自然语言指令编译成模型可执行的“字节码”open-code-review没有prompt.txt模板文件。它的 prompt 是运行时编译的编译目标不是字符串而是structured prompt tokens。当你指定--model deepseek-coder:33b它会加载该模型对应的prompt_spec.yamlversion: v2.1 tokenizer: deepseek-coder system_role: template: You are {{role}}. {{rules}} variables: role: Senior Rust Backend Engineer rules: | - Focus ONLY on correctness: memory safety, thread safety, async soundness. - NEVER comment on style, naming, or formatting unless it breaks compilation. - For each finding, cite EXACT line numbers from the provided diff. user_message: sections: - name: Diff Context weight: 0.4 content: {{diff_snippets}} - name: Dependency Graph weight: 0.3 content: {{dependency_summary}} - name: Recent Commits weight: 0.2 content: {{recent_commits}} - name: Review Instructions weight: 0.1 content: | Output format: JSON array of objects with keys file, line, severity, message, suggestion. Severity values: critical, high, medium, low. Do NOT output anything else.这个 spec 被编译成一个 token sequence plan[BOS] [SYS_START] ... [USER_START] [SECTION_DIFF] ... [SECTION_DEP] ... [EOS]。编译器会根据当前 diff 的实际大小动态调整各 section 的 token 预留空间——比如当diff_snippets超过 4096 tokens 时它会自动启用diff_snippets的摘要模式用 LLM 本身生成一段 200 字的 diff 概述而不是粗暴截断。这种编译时决策保证了 prompt 的语义完整性避免了传统字符串拼接导致的 “truncated context” 问题。3.3 Model Router不是负载均衡而是语义路由open-code-review支持同时配置多个模型但它从不随机选一个来用。Model Router 是一个基于 diff 特征的决策引擎语言识别通过 tree-sitter parser 检测 diff 中出现频率最高的语法节点function_definition→ Rust/Python,jsx_element→ TypeScript/React,macro_rules!→ Rust macro。变更类型分类用小型 RoBERTa 模型内置12MB对 diff patch 做 zero-shot 分类refactor,bug_fix,feature_add,test_update,config_change。路由策略refactor Rust →deepseek-coder:33b擅长重构推理bug_fix Python →qwen2.5-coder:14b在 Pydantic 验证规则上表现更稳feature_add TypeScript →llama3.1:70b更大的 context window 处理复杂 interface 依赖这个路由表是可扩展的。你可以用ocr router add --when languagerust and change_typerefactor --then deepseek-coder:33b动态添加规则。它不是简单的 if-else而是加权投票每个规则输出一个 scoreRouter 取最高分模型。这种设计让团队能针对不同代码域部署最合适的模型而不是用一个“万能”模型硬扛所有场景。3.4 Feedback Loop让每次 review 成为下一次的训练数据open-code-review的--feedback模式是它区别于其他工具的核心。当你运行ocr review --pr123 --feedback它不会立即调用 LLM而是先检查本地~/.ocr/feedback/目录下是否有针对该 PR 的历史反馈记录。如果有它会将这些反馈格式为pr-123-feedback.json注入 Context Orchestrator 的初始图中作为“人类专家标注”的 ground truth 节点。例如上次 review 时你手动标记了一条 LLM 误报“unsafe { std::ptr::read_volatile(...) }不是 bug是硬件寄存器访问必需”那么这次--feedback模式下Orchestrator 会主动将std::ptr::read_volatile的文档链接、该 crate 的hardware_abstractionfeature flag 状态、以及unsafeblock 外围的#[cfg(target_arch arm)]条件编译全部加入上下文。这相当于给模型提供了“反例教学”——不是告诉它“别报这个”而是告诉它“在什么条件下这个 unsafe 是合法的”。Feedback 数据默认加密存储在本地不上传。但你可以用ocr feedback export --pr123 --format csv导出用于内部知识库建设。我们团队每月汇总这些 feedback用它们微调一个轻量级的review-judgement分类器仅 8MB部署在 CI 中作为 pre-filter当 LLM 输出某条评论时这个分类器会先判断“人类是否大概率会否决它”如果是则自动降级 severity 或 suppress 该条。三个月下来误报率从 23% 降到 6.8%。提示open-code-review的 Agent 架构里没有 “Planning”、“Tool Use” 这些炫酷但低效的环节。它的 Agent 智能体现在对代码语义的理解深度、对审查意图的精准捕捉、以及对人类反馈的持续吸收。它不试图扮演“全能助手”而是做一个极度专注的“审查协作者”——就像一位坐在你工位旁、熟悉你代码库、记得你上次说“这个 unsafe 是 ok 的”、并且会默默把这句话记在小本本上的资深同事。4. 从零搭建可复现的审查环境Ollama Tree-sitter 自定义 Prompt Spec现在我们动手搭建一个生产可用的open-code-review环境。重点不是“装上就行”而是确保每一步都可验证、可审计、可迁移——因为审查环境的稳定性直接决定了团队对 AI 辅助的信任度。4.1 基础依赖为什么必须用 Ollama 而非直接调 APIopen-code-review官方推荐 Ollama原因很实在模型版本锁定ollama pull llama3.1:70b下载的是特定 commit hash 的模型后续ocr review总是用这个 exact version。而调https://api.openai.com/v1/chat/completions你永远不知道今天用的是 gpt-4o-2024-08-06 还是 gpt-4o-2024-08-12细微的 tokenizer 变更都可能导致 prompt 解析错误。离线可用性CI 服务器通常无外网。Ollama 模型存本地磁盘ocr review调用http://localhost:11434零延迟零失败。资源可控ollama run --num-gpu 1 llama3.1:70b可以精确指定 GPU 显存分配避免模型抢占全部 VRAM 导致其他服务崩溃。安装步骤macOS/Linux# 1. 安装 Ollama官方一键脚本 curl -fsSL https://ollama.com/install.sh | sh # 2. 拉取模型注意不要用 latest 标签 ollama pull llama3.1:70b # sha256:9a8f... (固定哈希) ollama pull deepseek-coder:33b # sha256:2c1e... (固定哈希) # 3. 验证模型加载 ollama list # NAME ID SIZE MODIFIED # llama3.1:70b 9a8f... 4.2GB 2 days ago # deepseek-coder:33b 2c1e... 21GB 3 days ago注意deepseek-coder:33b需要至少 24GB GPU 显存A100 40GB 或 H100。如果资源有限用deepseek-coder:1.3b仅需 6GB替代它在函数级逻辑审查上准确率损失不到 7%但速度提升 4.8 倍。4.2 Language ParserTree-sitter 是如何让上下文理解“活”起来的open-code-review的 Context Orchestrator 依赖 tree-sitter 生成 AST。不同语言需要不同 parser# 安装 tree-sitter CLI npm install -g tree-sitter-cli # 为 Rust 安装 parser其他语言同理 git clone https://github.com/tree-sitter/tree-sitter-rust cd tree-sitter-rust tree-sitter build-wasm # 生成 wasm parser供 ocr 使用 cd .. cp tree-sitter-rust/src/parser.c ~/.ocr/parsers/rust.c但更推荐用ocr setup parsers命令自动完成ocr setup parsers --languages rust,python,typescript # 自动下载、编译、验证各语言 parser # 输出✓ Rust parser loaded (v0.24.0) # ✓ Python parser loaded (v0.22.0) # ✓ TypeScript parser loaded (v0.20.0)验证 parser 是否生效# 创建一个测试 diff cat test.diff EOF diff --git a/src/lib.rs b/src/lib.rs index abc123..def456 100644 --- a/src/lib.rs b/src/lib.rs -10,0 11,3 pub mod auth; pub mod payment; pub use payment::PaymentService; EOF # 运行上下文分析不调用 LLM只测试 parser ocr context analyze --diff-file test.diff --language rust --debug # 输出应包含 # - Detected language: rust # - Extracted AST nodes: [mod_declaration, use_statement] # - Inferred context: payment module declaration, public re-export如果--debug输出里没有Extracted AST nodes说明 parser 未正确加载。常见坑tree-sitter-rust的 C parser 文件路径不对或~/.ocr/parsers/权限不足。4.3 自定义 Prompt Spec为你的团队编写专属的审查规则open-code-review自带defaultprompt spec但必须根据团队规范定制。以 Rust 团队为例创建~/my-rust-spec.yamlversion: v2.1 tokenizer: llama3 system_role: template: | You are a senior Rust engineer at {{company}} reviewing production code. Adhere strictly to our internal RFC-2023: Async Safety Guidelines and RFC-2024: FFI Interop Rules. Focus ONLY on: - Memory safety violations (dangling pointers, use-after-free) - Thread safety issues (Send/Sync mismatches, Arc/Mutex misuse) - Async soundness (blocking calls in async fn, missing .await) - FFI contract breaches (C ABI mismatch, missing #[repr(C)]) NEVER comment on: - Code style (tabs vs spaces, line length) - Naming conventions (unless violates RFC-2022) - Documentation completeness (unless missing critical safety notes) user_message: sections: - name: Diff Snippet weight: 0.5 content: {{diff_snippets}} - name: Relevant RFC Excerpts weight: 0.3 content: | RFC-2023 Section 4.2: All async functions must be fully non-blocking. Calls to std::fs::read() are prohibited. RFC-2024 Section 3.1: FFI structs must be #[repr(C)] and contain only POD types. - name: Review Instructions weight: 0.2 content: | Output ONLY valid JSON array. Each object MUST have: - file: string, absolute path - line: integer, 1-based - severity: critical | high | medium | low - message: concise explanation ( 120 chars) - suggestion: concrete fix, code snippet preferred NO markdown, NO extra text, NO explanations outside JSON.然后注册这个 specocr prompt register --name my-rust-team --file ~/my-rust-spec.yaml ocr config set default_prompt_spec my-rust-team验证它是否生效ocr review --pr123 --prompt-spec my-rust-team --dry-run # --dry-run 不调用 LLM只输出最终编译的 prompt token count 和 sections # 应看到 RFC-2023 Section 4.2 等自定义规则出现在 prompt 中4.4 CI 集成实战GitHub Actions 中的稳定审查流水线.github/workflows/ai-review.yml完整配置name: AI Code Review on: pull_request: types: [opened, synchronize, reopened] jobs: review: runs-on: ubuntu-22.04 steps: - name: Checkout code uses: actions/checkoutv4 with: fetch-depth: 0 # 必须否则无法获取完整 commit history - name: Install Ollama run: | curl -fsSL https://ollama.com/install.sh | sh sudo systemctl enable ollama sudo systemctl start ollama - name: Pull models run: | ollama pull llama3.1:70b ollama pull deepseek-coder:1.3b - name: Install open-code-review run: | curl -fsSL https://raw.githubusercontent.com/open-code-review/cli/main/install.sh | sh - name: Run Open Code Review env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | # 设置模型路由规则 ocr router add --when languagerust and change_typerefactor --then deepseek-coder:1.3b ocr router add --when languagerust and change_typebug_fix --then llama3.1:70b # 执行审查输出 SARIF ocr review \ --pr${{ github.event.pull_request.number }} \ --repo${{ github.repository }} \ --format sarif \ --output /tmp/ocr-report.sarif \ --strictnesshigh \ --timeout300 # 5分钟超时防死锁 - name: Upload SARIF uses: github/codeql-action/upload-sarifv2 with: sarif_file: /tmp/ocr-report.sarif category: ai-review关键细节fetch-depth: 0是必须的否则--commit-range和--recent-commits功能失效。--timeout300防止模型加载失败导致 CI 卡死。open-code-review会在超时后自动 kill 子进程并返回非零 exit code。--strictnesshigh在 CI 中启用因为 CI 有充足资源本地开发用--strictnessmedium更快。category: ai-review让 GitHub 的 code scanning 界面能区分 AI Review 和传统 SAST 结果。实测数据在 16-core CPU 32GB RAM 的 runner 上一个 50 文件、3000 行 diff 的 PR平均审查耗时 42.7 秒含模型加载SARIF 上传后GitHub 界面 3 秒内显示结果Reviewer 点击 “Show details” 即可看到带行号锚点的原始 diff 和 LLM 评论。5. 那些没人告诉你的坑我们在 12 个团队落地中踩过的 7 个真实陷阱open-code-review文档写得很漂亮但真实世界远比 README 复杂。以下是我们在金融、游戏、IoT 三个垂直领域12 个不同规模团队落地过程中反复遇到、必须提前规避的 7 个核心陷阱。每个都附带具体现象、根因分析和可执行的解决方案。5.1 陷阱一模型“幻觉”审查 —— 把不存在的函数调用当成安全隐患现象ocr review --pr888输出一条 critical 评论“auth::validate_token()被payment::process()同步调用违反 async safety guidelines”但payment::process()根本没调用auth::validate_token()且auth::validate_token()是一个 async fn。根因Context Orchestrator 的 dependency graph walk 错误地将use auth::validate_token;的声明当作了调用关系。它没区分use导入和call调用导致图遍历时把所有use的符号都当作潜在调用点。解决方案短期在prompt_spec.yaml的Review Instructions中强制添加约束content: | DO NOT infer function calls from use statements. ONLY report calls that appear as direct function invocations (e.g., auth::validate_token().await). If uncertain, output severity low and message Uncertain call site - manual verification required.长期升级 tree-sitter parser 到 v0.25新版本支持call_expressionnode type 的精确匹配ocr setup parsers会自动检测并启用。5.2 陷阱二Git diff 编码污染 —— 中文注释导致 prompt 解析失败现象ocr review --diff-file zh-comment.patch报错Error: invalid utf-8 sequence in diff content但git apply能正常打补丁。根因open-code-review默认用UTF-8解码 diff但某些编辑器如 Windows 上的 VS Code保存 diff 时用了GBK或BIG5。LLM tokenizer 无法处理乱码直接 crash。解决方案统一 diff