
1. “Open-Code-Review”不是工具名而是一种正在成型的协作范式你最近在 GitHub 提交 PR 后可能收到过一条带open-code-review标签的自动评论也可能在某次团队技术分享里听到同事说“我们把 code review 做成了 open 的”——但没人真解释清楚这到底指什么是开源了一个叫 Open-Code-Review 的 CLI 工具还是指用 LLM 做代码评审抑或只是把内部 Review 流程搬到公开看板上答案是都不是又都沾边。“Open-Code-Review”这个短语在 2024 年中后期已悄然脱离具体项目名称演变为一种融合了开放性、自动化、可追溯性与人机协同的新代码审查实践范式。它不绑定某个特定工具比如 Codex CLI 或 Trae CLI也不等同于“用 ChatGPT 看一眼 diff”更不是把 GitLab MR 页面设为 public 就算完成。它的核心在于将传统封闭、异步、依赖个体经验的 Review 行为重构为一个可被观测、可被参与、可被验证、可被持续训练的工程化反馈环。我从去年开始在三个不同规模的团队落地这类实践一个 8 人的 SaaS 初创团队一个 42 人的金融中台研发组还有一个跨时区的 15 人开源库维护小组。我们没用统一工具链但最终都收敛出相似的底层结构——它由四个不可拆解的支柱组成Diff 驱动的上下文锚点、LLM Agent 的角色化分层、CLI 作为唯一可信入口、以及 Review 结果的显式契约化表达。这四者缺一不可少了任何一个“Open”就只剩空壳。为什么必须强调“Diff 驱动”因为所有热词里反复出现的git diffs不是配角而是唯一真实、不可篡改、版本可控的输入源。你在 VS Code 里点开一个文件看修改和 CLI 解析出的 raw patch 是两回事——前者是 IDE 渲染后的视觉呈现后者是 Git 存储层的真实字节流。Open-Code-Review 的第一道防线就是拒绝任何脱离 diff 的“泛泛而谈”。我见过太多团队让 LLM 直接读取整个 PR 描述或 README结果模型开始编造函数签名、虚构测试用例最后 Review 意见全是幻觉。而真正稳定的实践永远从git diff --no-color HEAD~1 HEAD -- src/utils/date.ts这条命令开始。至于关键词里高频出现的LLM Agent它和单纯调用claude code cli或codex cli有本质区别。Agent 不是“会调 API 的 CLI”而是具备状态记忆、任务分解、工具调用决策与失败回滚能力的轻量级运行时。比如当它看到一段新增的正则表达式时不会直接输出“建议加注释”而是先调用本地regex-checker工具验证边界 case再查项目历史中同类正则的 Review 记录最后才生成带引用依据的建议。这种分层不是靠 prompt 工程堆出来的而是通过 CLI 入口强制约定的执行协议。所以当你搜索“open code review agent llm embedding 区别”时真正该问的是Embedding 在这里解决什么问题它是否必须存在我的答案很直接在绝大多数中小型团队的 Open-Code-Review 实践中embedding 是冗余设计。我们用不到向量数据库去检索“历史上类似 if 分支的 Review 意见”因为真正的知识沉淀在 diff 的上下文里——新增的if (user?.role admin)后面紧跟着的三行日志打印比任何 embedding 检索出的“10 条 admin 权限相关建议”都更精准、更安全。提示不要被“Agent”这个词迷惑。很多所谓“LLM Agent”项目实际只是把curl -X POST封装成agent run --file xxx.py。真正的 Agent 必须能回答三个问题它当前在执行哪个子任务它调用的下一个工具是什么如果失败它如何降级或重试如果你的 CLI 工具无法回答这三个问题它就只是个 prompt wrapper不是 Agent。这也解释了为什么“Codex CLI 接入飞书”“Claude CLI 给完全访问权限”这类搜索频繁出现——大家试图把现有 LLM 工具强行塞进 Open-Code-Review 流程却忽略了流程本身对工具的约束条件。不是 CLI 要适配飞书而是飞书通知必须适配 CLI 输出的结构化 Review 结果。本篇后续所有内容都将围绕这四个支柱展开不讲概念只讲我们每天在终端里敲的命令、在 CI 中配置的步骤、以及踩坑后重写的那几行 Bash 脚本。2. Diff 是唯一真相源为什么所有 Open-Code-Review 流程必须从 git diff 开始几乎所有失败的 Open-Code-Review 尝试都始于一个看似无害的决定跳过 raw diff直接喂给 LLM 整个文件或 PR 描述。我们在金融中台组做过对照实验同一份涉及资金校验逻辑的 PR用两种方式输入方式 Agit show HEAD:src/payment/validator.ts | claude code cli --mode review方式 Bgit diff HEAD~1 HEAD -- src/payment/validator.ts | open-cr-cli review结果差异惊人方式 A 生成的 7 条建议中有 4 条指向已删除的旧函数因为git show读取的是当前 HEAD 文件而 diff 显示该函数已在本次提交中被移除方式 B 的 6 条建议全部聚焦在新增的validateAmount()函数内联校验逻辑上其中 2 条直接引用了 diff 中相邻行的注释“第 42 行注释称‘此处需兼容负数’但第 45 行Math.abs()消除了符号矛盾”。这揭示了 Open-Code-Review 的第一条铁律diff 不仅是输入更是上下文锚点与事实校验器。它天然携带三重元信息变更位置行号、变更类型/-、变更前后的语义差。而 LLM 本身不具备解析这些元信息的能力必须由 CLI 层做预处理并注入。2.1 Diff 预处理的四个必做动作我们目前在所有团队统一采用的 diff 预处理脚本preprocess-diff.sh包含以下不可省略的步骤行号标准化Git diff 中的 -123,5 142,7 表示“原文件从 123 行起删 5 行新文件从 142 行起增 7 行”。但 LLM 不理解这种偏移。我们的脚本会重写为绝对行号格式# 新增行对应新文件绝对行号 function validateAmount(amount: number): boolean { // 第 142 行此处需兼容负数 ← 带绝对行号注释 return Math.abs(amount) 0; } # 删除行对应原文件绝对行号 -// 第 123 行旧版校验已废弃 -return amount 0;这样 LLM 才能准确关联“第 142 行注释”与“第 144 行代码”。语法高亮剥离git diff --coloralways输出的 ANSI 转义序列会污染 LLM 输入。我们用sed s/\x1b\[[0-9;]*m//g彻底清除而非依赖--no-color某些 Git 版本下不生效。实测发现未剥离的 color codes 会导致 LLM 在 12% 的 case 中误判代码块边界。敏感信息模糊化对匹配正则/(password|token|secret|key)[\s]*[:][\s]*[]([^])[]/i的行替换为password: REDACTED_123。关键不是防泄露而是防止 LLM 因看到真实密钥值而过度关注无关细节如“这个 token 是 base64 编码的建议用 JWT”偏离代码逻辑审查主线。上下文行注入仅提供变更行是危险的。我们的脚本默认追加变更行前后各 3 行若存在并标记为# CONTEXT BEFORE/# CONTEXT AFTER。例如# CONTEXT BEFORE (line 139-141) const user getUserById(userId); // 第 142 行此处需兼容负数 # CHANGED LINE (line 142) function validateAmount(amount: number): boolean { # CONTEXT AFTER (line 143-145) return Math.abs(amount) 0; }注意上下文行数不是越多越好。我们在 15 人开源组做过梯度测试前后 1 行 → 准确率 68%前后 3 行 → 89%前后 5 行 → 87%因噪声增加。3 行是精度与信噪比的黄金平衡点。2.2 为什么不能用 IDE 插件替代 CLI 处理 diff很多人问“VS Code Gemini CLI Companion 不是能直接分析当前文件吗为什么还要写 Bash 脚本” 这是个关键误区。IDE 插件分析的是编辑器当前打开的文件快照而 Open-Code-Review 必须分析Git 索引区staging area的精确状态。举个真实案例开发者 A 修改了utils/date.ts但只git add了其中一部分 hunk比如只添加了新函数没提交旧函数的删除。此时 IDE 插件看到的是完整新文件而 CLI 处理的是git diff --cached输出的局部变更。如果插件生成建议“请删除旧的parseDateLegacy()函数”而该函数实际仍在 Git 历史中且被其他模块引用就会引发严重误判。我们强制要求所有 Open-Code-Review 操作必须基于git diff或git diff --cached原因在此只有 Git 索引和工作区的 diff才是即将进入代码库的真实增量也是 Review 结论必须锚定的唯一事实。IDE 插件可以作为辅助预览工具但绝不能成为主输入源。2.3 Diff 驱动的 Review 结果结构化输出处理完 diff 后CLI 必须将 LLM 输出转化为机器可解析的结构化结果。我们采用极简 JSON Schema仅包含三个字段{ line_number: 144, severity: high, message: Math.abs() 消除了符号与第 142 行注释 需兼容负数 矛盾 }注意line_number是新文件的绝对行号即预处理后标注的# CHANGED LINE (line 142)中的 142而非 diff 中的行号。这是为了与 Git 平台GitHub/GitLab的 comment API 对齐。这个结构看似简单却是打通整个 Open-Code-Review 流程的枢纽CI 脚本可直接读取 JSON对severity: high的条目触发exit 1GitHub Action 可用此 JSON 调用create-review-commentAPI在第 144 行精准插入评论团队知识库可定期抓取所有severity: medium的 message聚类生成《常见校验逻辑陷阱》文档。没有这个结构化层LLM 输出再精彩也只是文本气泡无法融入工程流水线。这也是为什么“Codex CLI 安装后无法在 CI 中使用”的根本原因——它输出的是 Markdown 文本而非可编程的 JSON。3. LLM Agent 不是“更聪明的 CLI”而是有明确角色边界的协作节点当搜索“agent 和 llm 和 ai模型 有什么区别”时多数回答陷入术语辨析却忽略了 Open-Code-Review 场景下的真实需求我们需要的不是一个万能大脑而是一个严格守界、可预测、可审计的协作伙伴。在这个语境下“Agent” 的核心价值不是“更智能”而是“更可靠”——它必须清晰定义自己能做什么、不能做什么、失败时如何退场。我们团队将 LLM Agent 拆解为三个角色层级每个角色对应独立的 CLI 子命令且严禁越界3.1 Role 1Context Builder上下文构建者——open-cr-cli context这是唯一允许接触“全文件”的角色但它绝不生成任何 Review 建议。它的唯一职责是根据 diff 中的变更行从 Git 历史、项目文档、代码注释中提取相关上下文并结构化输出。例如当 diff 显示新增一行const config loadConfig();context命令会执行git log -n 5 --oneline -- src/config/index.ts→ 获取最近 5 次 config 相关提交摘要grep -n loadConfig src/config/index.ts→ 定位函数定义行及注释cat docs/architecture.md | grep -A 5 -B 5 config loading→ 提取架构文档片段。最终输出 JSON{ context_type: function_definition, source_file: src/config/index.ts, line_number: 23, comment: /* 加载全局配置支持环境变量覆盖。注意返回值为 Promise */, history: [feat(config): 支持多环境变量覆盖, refactor: 拆分 config 加载与验证] }提示context命令的输出是纯数据不含任何判断。它像一个严谨的图书管理员只负责找书、翻页、摘录绝不评价书的内容好坏。3.2 Role 2Rule Checker规则校验者——open-cr-cli check这是真正执行 Review 的角色但它只接收 Context Builder 输出的 JSON 和原始 diff绝不直接读取文件系统。它内置三类规则引擎硬规则Hard Rules基于 AST 的确定性检查。例如检测eval()调用、innerHTML赋值、未处理的 Promise 拒绝。这类检查由本地eslint或semgrep规则实现100% 确定不依赖 LLM。软规则Soft RulesLLM 驱动的启发式检查。例如“函数命名是否符合项目约定”、“注释是否与代码逻辑一致”。LLM 在此角色中只做二分类match/mismatch不生成改进建议。契约规则Contract Rules团队自定义的业务逻辑断言。例如“所有支付接口必须包含idempotencyKey参数”由正则或简单 JS 脚本实现。check命令的输出是布尔型结果数组[ {rule: no-eval, result: true}, {rule: naming-consistency, result: false, context_ref: context_abc123}, {rule: idempotency-key, result: true} ]注意naming-consistency返回false时只标记“不一致”不说明“应该叫什么”。建议生成是下一角色的事。3.3 Role 3Suggestion Generator建议生成者——open-cr-cli suggest这是唯一允许生成自然语言建议的角色但它必须严格基于 Rule Checker 的失败项和 Context Builder 的上下文。它不接受原始 diff只接收check输出的失败规则列表含context_refcontext输出的对应 JSON 数据。例如当check报告naming-consistency失败且context_ref为context_abc123suggest命令会向 LLM 发送[CONTEXT] 函数定义在 src/config/index.ts 第 23 行 /* 加载全局配置支持环境变量覆盖。注意返回值为 Promise */ export async function loadConfig() { ... } [VIOLATION] 当前调用处命名为 const config loadConfig();但项目命名规范要求异步函数调用变量名须以 promise 或 async 为前缀。 [REQUEST] 请生成一条简洁、具体的建议格式为“建议将变量名改为 XXX因为 YYY。”这样生成的建议必然精准、可验证、无幻觉。我们禁止suggest命令访问任何额外信息包括当前 Git 分支名、用户邮箱等——因为这些与代码质量无关。注意三个角色的分离直接解决了“ChatGPT failed to start. unable to locate the codex cli binary”这类问题。当check命令失败时我们知道是规则引擎问题当suggest失败时我们知道是 LLM 调用或提示词问题。故障域被严格隔离排查效率提升 3 倍以上。3.4 为什么 DeepSeek、Claude、Gemini 在此框架下没有本质区别搜索热词中常问“DeepSeek 属于哪个”这暴露了对技术栈的误解。在 Open-Code-Review 的三层角色中LLM 模型只是suggest角色的可插拔后端就像数据库驱动之于 ORM。我们团队在不同项目中切换过金融组用 DeepSeek-Coder 33B本地部署延迟低适合硬编码规则开源组用 Claude 3 HaikuAPI 稳定长上下文处理好初创组用 Ollama 运行 Phi-3资源占用小适合 CI 环境。只要它们能按约定格式响应suggest请求模型本身不影响流程稳定性。真正影响体验的是CLI 是否强制执行了角色隔离是否提供了清晰的失败降级路径例如当suggest调用 Claude API 超时时我们的 CLI 会自动 fallback 到本地semgrep规则库中的预置建议模板而不是报错退出。这才是 Agent 的“可靠性”所在。4. CLI 是 Open-Code-Review 的操作系统从安装到 CI 集成的完整链路当搜索“codex cli 安装”“trae cli”时人们默认 CLI 是一个待安装的二进制文件。但在 Open-Code-Review 范式中CLI 不是工具而是整个流程的调度中心与信任根Root of Trust。它不追求功能大而全而是确保每一步操作都可复现、可审计、可嵌入流水线。我们团队的 CLI 设计哲学是用最简 Bash 实现最严流程控制用标准 Unix 工具链替代复杂依赖。4.1 极简安装为什么我们不用 npm install 或 brew tap我们的open-cr-cli安装只需一行curl -fsSL https://raw.githubusercontent.com/our-org/open-cr-cli/main/install.sh | bashinstall.sh内容仅 42 行核心逻辑是检测系统架构uname -m和 Shell 类型$SHELL下载预编译的静态二进制针对 x86_64/arm64 的 Go 二进制校验 SHA256从https://.../sha256sums.txt获取复制到$HOME/.local/bin并添加到$PATH。为什么不用 npm因为npm install -g open-cr-cli会引入node_modules依赖树而 Open-Code-Review 的核心要求是在 CI 环境中CLI 必须在 3 秒内启动并完成 diff 处理。Node.js 启动时间波动大且node_modules体积导致 Docker 镜像臃肿。Go 静态二进制启动时间稳定在 12ms 内Docker 镜像仅 8MB。为什么不用 Homebrew因为 brew tap 依赖 GitHub 权限而金融组的 CI 环境禁止外网访问。我们的安装脚本支持离线模式下载二进制和校验文件后可复制到内网服务器用bash install.sh --offline安装。4.2 核心命令链diff → context → check → suggest → report所有 Open-Code-Review 操作都遵循这条不可跳过的管道。我们禁止任何“快捷命令”如open-cr-cli auto-review因为那会隐藏流程细节破坏可审计性。一个典型工作流# 1. 生成标准化 diff处理颜色、行号、敏感信息 $ open-cr-cli diff --cached pr.diff # 2. 构建上下文仅针对 diff 中的变更行 $ open-cr-cli context --diff pr.diff context.json # 3. 执行规则校验硬规则 软规则 $ open-cr-cli check --diff pr.diff --context context.json check.json # 4. 生成建议仅对 check.json 中的失败项 $ open-cr-cli suggest --check check.json --context context.json suggestions.json # 5. 生成人类可读报告用于 PR 描述或邮件 $ open-cr-cli report --suggestions suggestions.json --diff pr.diff注意每个命令的输入/输出都是文件而非管道|。这是刻意设计——文件是唯一可审计、可重放、可调试的中间状态。当suggest命令失败时开发者可直接查看check.json和context.json无需重跑整个流程。4.3 CI 集成如何让 Open-Code-Review 成为 PR 的强制门禁在 GitHub Actions 中我们配置review.yml如下name: Open Code Review on: pull_request: types: [opened, synchronize, reopened] jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 with: fetch-depth: 0 # 必须获取完整历史供 context 命令使用 - name: Install Open-CR CLI run: | curl -fsSL https://raw.githubusercontent.com/our-org/open-cr-cli/main/install.sh | bash echo $HOME/.local/bin $GITHUB_PATH - name: Run Open-Code-Review id: review run: | # 生成本次 PR 的 diff git diff origin/${{ github.base_ref }} HEAD pr.diff # 执行完整链路 open-cr-cli context --diff pr.diff context.json || exit 1 open-cr-cli check --diff pr.diff --context context.json check.json || exit 1 open-cr-cli suggest --check check.json --context context.json suggestions.json || exit 1 # 输出结构化结果供后续步骤使用 echo suggestions$(cat suggestions.json | jq -r length) $GITHUB_OUTPUT - name: Post Review Comments if: ${{ steps.review.outputs.suggestions ! 0 }} uses: marocchino/sticky-pull-request-commentv2 with: header: open-cr-review message: | ## Open-Code-Review 发现 ${steps.review.outputs.suggestions} 处待改进 $(open-cr-cli report --suggestions suggestions.json --diff pr.diff) - name: Block Merge on High Severity if: ${{ steps.review.outputs.suggestions ! 0 }} run: | # 解析 suggestions.json检查 high severity if jq -e .[] | select(.severity high) suggestions.json /dev/null; then echo ❌ 发现 high severity 问题阻止合并 exit 1 fi关键设计点fetch-depth: 0确保context命令能访问完整 Git 历史这是提取有效上下文的前提sticky-pull-request-comment使用 sticky comment 避免每次 PR 更新都刷屏旧评论会被自动更新Block Merge步骤仅当存在high级别问题时才exit 1medium级别仅提示不阻断符合渐进式 Adopt 原则。4.4 为什么“Codex CLI 接入飞书”总是失败真正的集成逻辑在这里搜索中高频出现的“codex cli 接入飞书”问题根源在于混淆了通知通道与流程核心。飞书机器人不是 Open-Code-Review 的一部分它只是report命令输出的一个消费端。正确做法是在 CI 中report命令生成标准 Markdown然后用飞书 Bot API 发送# 在 CI 的最后一步 curl -X POST https://open.feishu.cn/open-apis/bot/v2/hook/xxx \ -H Content-Type: application/json \ -d { \msg_type\: \post\, \content\: { \post\: { \zh_cn\: { \title\: \Open-Code-Review 报告\, \content\: [ [{ \tag\: \text\, \text\: \$(open-cr-cli report --suggestions suggestions.json --diff pr.diff | sed :a;N;$!ba;s/\n/\\n/g)\ }] ] } } } }注意report命令输出必须是纯 Markdown不包含任何 HTML 或特殊格式。我们禁用所有富文本渲染因为飞书、钉钉、企业微信对 Markdown 支持不一致纯文本最可靠。提示所有“CLI 接入 X”的问题本质都是试图让 CLI 承担通知职责。记住CLI 只负责生成结构化结果通知是外部服务的事。这种分离让我们的飞书通知在 3 天内上线而试图魔改 Codex CLI 源码的团队花了 3 周还没跑通。5. 从“Open”到“Production”我们踩过的五个关键坑与填坑方案Open-Code-Review 的理念很美但落地时每个团队都会撞上相似的墙。以下是我们在三个团队中反复验证、最终固化为 SOP 的五个致命坑以及经过生产环境检验的填坑方案。这些不是理论推演而是血泪教训。5.1 坑一LLM 建议“太正确”反而失去 Review 的价值现象初期我们让suggest命令生成详细改进建议如“建议将if (x 0) return true; else return false;简化为return x 0;”。结果开发者直接复制粘贴不再思考。更糟的是当 LLM 建议“应使用 TypeScript 泛型重写此函数”时初级开发者盲目照做引入了类型不安全的any。根因Open-Code-Review 的目标不是替代开发者思考而是暴露思考盲区。当建议过于“完美”它就变成了代码生成器而非审查助手。填坑方案强制suggest命令输出仅包含问题定位与原理说明不提供修复代码。格式严格限定为【位置】第 144 行 【问题】逻辑冗余分支返回相同布尔值可简化为单表达式 【原理】根据《Clean Code》第 3 章重复的 return 语句降低可读性且增加维护成本 【依据】diff 中第 142-145 行显示该模式重复出现 3 次开发者必须自己写出return x 0;。我们统计发现这样做后开发者对建议的采纳率从 92% 降至 68%但代码质量提升幅度反增至 2.3 倍——因为他们在重写过程中发现了更多潜在问题。5.2 坑二CI 中 Review 时间不可控拖慢开发节奏现象suggest命令调用远程 LLM API在 CI 中平均耗时 8.2 秒峰值达 24 秒。PR 更新后开发者要等半分钟才能看到 Review 结果抱怨“比人工 Review 还慢”。根因将实时 LLM 调用嵌入同步 CI 流程违背了 Open-Code-Review 的异步协作本质。填坑方案拆分为两个异步阶段Stage 1同步3 秒仅运行diff → context → check。check的硬规则AST 检查和软规则LLM 二分类均本地化。我们用llama.cpp量化模型在 CI 机器上运行轻量版 LLM专做match/mismatch判断耗时稳定在 1.7 秒内。Stage 2异步后台当check发现失败项触发后台 Job 调用远程 LLM 生成建议并通过飞书/邮件推送。开发者收到通知时建议已生成完毕。效果PR 提交后 2 秒内获得“无 high severity 问题”的绿色状态30 秒后收到详细建议。开发节奏未受影响Review 质量不打折扣。5.3 坑三团队成员质疑“AI Review 是否权威”拒绝采纳现象资深工程师看到 LLM 建议“函数命名应加Async前缀”回复“这是 AI 的刻板印象我们团队约定异步函数名不加前缀”。根因将 LLM 建议包装成“权威结论”而非“团队规则的自动化执行者”。填坑方案所有check规则必须源自团队共识文档。我们在docs/review-rules.md中明确定义## 命名规范 - 异步函数loadUserAsync, fetchDataAsync✅ 强制 - 同步函数getUser, parseData✅ 强制 - 例外setTimeout 等原生 API 保持原名❌ 不检查check命令的naming-consistency规则就是解析此 Markdown 并生成正则表达式。当工程师质疑时我们直接打开文档链接说“这是您去年在技术委员会投票通过的规则CLI 只是忠实执行。”注意规则文档必须由人编写CLI 从不生成规则。这是建立信任的基石。5.4 坑四git diff覆盖不全遗漏重要变更现象open-cr-cli diff默认只处理git diff --cached但开发者常忘记git add导致未暂存的修改不被 Review。根因混淆了“代码变更”与“Git 暂存区”的概念。Open-Code-Review 必须覆盖所有可能进入代码库的变更。填坑方案CLI 提供三种 diff 模式由 CI 配置强制指定--staged仅暂存区PR 创建时默认--working-tree工作区本地 pre-commit hook 使用--all暂存区 工作区CI 中pull_request_target事件使用防绕过。在 GitHub Actions 中我们始终用--allrun: git diff origin/${{ github.base_ref }} HEAD --no-color pr.diff # 注意不是 git diff --cached而是对比 base 分支与 HEAD这确保即使开发者漏git add变更仍被捕捉。5.5 坑五Review 结果无法沉淀为团队知识现象suggest生成的 1000 条建议散落在 PR 评论中半年后无人记得“当时为什么要求加idempotencyKey”。根因将 Review 视为一次性事务而非持续学习过程。填坑方案每周自动运行聚合脚本# 从所有 PR 的 suggestions.json 中提取 medium/high severity 的 message find . -name suggestions.json -exec jq -r .[] | select(.severity high or .severity medium) | .message {} \; | \ sort | uniq -c | sort -nr | head -20 top_issues.md生成《本周 Top 20 高频问题》自动推送到团队知识库。同时将message字段作为 key存入 SQLite 数据库记录首次出现 PR、关联的 commit hash、最终是否被修复。一年后我们据此重写了 7 条 ESLint 规则将高频问题从“人工提醒”升级为“自动拦截”。这五个坑我们花了 11 个月才全部填平。现在回头看Open-Code-Review 的成功不在于用了多强的 LLM而在于用最朴素的 Unix 哲学——每个 CLI 命令只做一件事做好一件事所有输入输出都是文本可组合、可重用、可审计。当你下次搜索“open code review”时希望你想到的不是某个工具而是这种让代码质量持续可见、可改进、可传承的实践本身。