open-code-review 评审规则体系完全指南:四层优先级链、五段式文件过滤与自定义规则实战
【免费下载链接】open-code-reviewFast, efficient, battle-tested at Alibaba's scale. Hybrid architecture code review tool: deterministic pipelines + LLM Agent, precise line-level comments, built-in multi-language ruleset (NPE, thread-safety, XSS, SQL injection), OpenAI & Anthropic compatible.项目地址: https://gitcode.com/GitHub_Trending/op/open-code-review
导读
本文围绕 open-code-review(OCR)的"评审规则(Review Rules)"机制展开,讲解它如何决定每一个被 diff 的文件"该被 AI 关注什么":从--rule参数、项目级.opencodereview/rule.json、全局配置到内置系统规则的四层优先级解析链,再到决定文件"是否进入 LLM 评审"的五段式过滤算法,以及 glob 匹配语法、.m文件内容嗅探和ocr rules check调试命令。读完本文,你将掌握如何用项目级规则强制团队编码规范、如何跳过生成代码、如何按 PR 临时覆盖规则,以及如何精确验证某条规则最终是否生效。本文以 pages/src/content/docs/ja/review-rules.md 为骨架,并结合仓库源码与测试进行原理级扩充。
规则是什么:告诉 OCR "每个文件该看什么"
评审规则的本质是一组「文件路径模式 → 评审指令」的映射。OCR 在评审每个文件时,会先根据文件路径匹配出一条规则,再把这条规则文本注入到发给模型的 prompt 中,告诉模型"对这个类型的文件,重点检查哪些方面"。
规则存放在3 层 JSON 文件中,外加一个随二进制内置的系统默认规则。系统层保证任何时候都有规则可用,即使项目从未配置过任何规则。
四层优先级链(Priority Chain)
OCR 使用四层优先级链解析规则。对于每一个文件路径,按层从上到下依次尝试,第一个匹配成功的模式生效:
| 优先级 | 来源 | 路径 | 说明 |
|---|---|---|---|
| 1(最高) | --rule参数 | 用户指定 | CLI 层覆盖。只要指定就始终生效。 |
| 2 | 项目配置 | <repoDir>/.opencodereview/rule.json | 项目级规则,可安全提交到仓库。 |
| 3 | 全局配置 | ~/.opencodereview/rule.json | 用户级偏好,对机器上所有仓库生效。 |
| 4(最低) | 系统默认 | 内置system_rules.json | 覆盖常见语言的嵌入式规则。 |
更高优先级的层如果文件不存在则静默跳过,不算错误。因此从未添加过.opencodereview/rule.json的项目,会自然落到全局 / 系统层。系统层始终存在(随二进制内置),所以必然能解析出某种规则。
这一优先级逻辑在源码中有清晰对应:composedResolver按custom → project → global → system顺序依次尝试,见 internal/config/rules/system_rules.go 的Resolve方法与 NewResolver。其中还蕴含一个值得注意的工程细节:项目层文件通过符号链接求值(filepath.EvalSymlinks)并校验最终路径必须落在仓库根目录内,防止恶意软链逃逸仓库边界(loadProjectRule)。
注:monorepo 子目录执行
ocr review时,加载的是git 仓库根目录下的.opencodereview/rule.json(规则匹配的是相对仓库根目录的 diff 路径),子目录内的局部 rule.json 不会被读取——共享规则应放在仓库根,或改用--rule显式指定。该行为在 loadProjectRule 的注释中有明确说明。
规则文件格式(层 1~3)
{ "include": ["src/**/*.{ts,tsx}", "src/**/*.go"], "exclude": ["**/*.test.ts", "**/generated/**"], "rules": [ { "path": "src/api/**/*.go", "rule": "All exported handlers must validate request bodies before use." }, { "path": "**/*mapper*.xml", "rule": "Check SQL for injection risks, parameter errors, and missing closing tags." } ] }三个相互独立的字段:
include:可选。用于绕过内置默认排除模式(如测试文件排除,见下)的 glob 模式。它不是白名单——不匹配任何include模式的文件依然会通过unsupported_ext与default_path检查,仍可能被评审。exclude:可选。OCR 不评审的文件的 glob 模式。在过滤中优先级最高。rules:{path, rule}条目数组,按声明顺序求值。对某文件第一个匹配的pathglob 条目,决定 OCR 发送给模型的 prompt。
值得补充的源码细节:rule字段的值不仅可以是内联文本,还可以是一个指向.md/.txt/.markdown文件的相对或绝对路径,加载时该文件内容会被读取并内联进规则(单行、无空格、扩展名符合白名单时才被判定为文件引用,见 resolveRuleEntries)。同时存在安全与体积约束:扩展名白名单校验、512 KB 大小上限、符号链接解析与仓库根目录围栏(readRuleFileSafe),适合团队把冗长的评审规范放进独立 md 文件统一维护。
glob 语法能力
OCR 使用 Go 生态的bmatcuk/doublestar/v4做路径匹配:
*:匹配除/外的任意字符。**:跨越目录边界匹配(src/**/*.go覆盖任意深度)。{a,b,c}:花括号展开。*.{ts,tsx,js,jsx}展开为 4 个模式依次尝试匹配。?:匹配单个字符。[abc]:字符类。
模式匹配不区分大小写(匹配前文件路径会被统一转小写)。不确定时可执行
ocr rules check <path>验证。
花括号展开在源码中由expandBraces实现(internal/config/rules/system_rules.go),doublestar.Match时路径与模式双方均先strings.ToLower(如 resolveDetail),与文档描述完全一致。
文件如何被过滤:五段式门控算法
过滤是五段式门控算法,位于 internal/agent/preview.go。对每个 diff,OCR 依次提问:
binary:文件是二进制吗?→ 排除。user_exclude:路径匹配任一用户exclude模式吗?→ 排除。user_include:用户定义了include时,路径匹配它吗?匹配则立即保留(跳过下面的unsupported_ext与default_path门)。unsupported_ext:文件扩展名在白名单中吗?不在 → 排除。default_path:路径匹配任一内置测试文件排除模式(**/*_test.go、**/*.test.{js,jsx,ts,tsx}、**/*_spec.rb……)吗?匹配 → 排除。
只有通过全部 5 个门控的文件才会被发送给 LLM。deleted是一种独立计算的原因(而非门控):当新路径为/dev/null时表示文件被删除,没有新内容可评审。源码中的whyExcluded方法(internal/agent/preview.go)正是这 5 个门控的直译,返回类型化的ExcludeReason(ExcludeBinary/ExcludeUserRule/ExcludeExtension/ExcludeDefaultPath等)。
使用ocr review --preview可以在不消耗任何 token的情况下打印过滤结果,用于审计哪些文件会被评审、哪些被排除及原因(对应 Preview,它只加载 diff 并应用过滤,不构建 session、manifest 或 runner)。
默认路径排除(Default Path Exclusions)
内置排除清单(见 internal/config/allowlist/default_exclude_patterns.json)主要匹配测试文件模式,文档中列出的核心条目:
**/*_test.go**/src/test/java/**/*.java**/src/test/**/*.kt**/*.test.{js,jsx,ts,tsx}**/*.spec.{js,jsx,ts,tsx}**/__tests__/****/test/**/*_test.py**/tests/**/*_test.py**/*_test.py**/*_spec.rb**/spec/**/*_spec.rb**/*Test.java**/*Tests.java**/*_test.rs**/oh_modules/****/*.test.ets
实际仓库中的清单比文档示例更全面,还额外覆盖了**/*Test.swift、**/Tests/**/*.swift、**/*.snap、**/testdata/**、**/fixtures/**、**/*.pb.go、**/*_test.zig、**/kitex_gen/**/*.go、**/*_capnp.rs等模式,以及**/*.generated.*、**/*.gen.go之类的生成代码模式。噪声目录(vendor/、node_modules/、target/……)的过滤发生在更早的 diff 层(internal/diff/git.go),先于逐文件过滤。
若希望评审这些命中测试文件模式的文件,把它们加入用户include列表即可——include会覆盖 default-path 门控。
逐文件规则解析(Rule Resolution)
当一个文件经过滤被判定为要评审后,OCR 会为该文件选定 agent 应遵循的规则文本:
- 按声明顺序尝试
--rule(custom)层。 - 按声明顺序尝试
<repo>/.opencodereview/rule.json。 - 按声明顺序尝试
~/.opencodereview/rule.json。 - 回退到内置系统规则层。
用户规则默认整体替换系统规则;若某条用户规则设置了merge_system_rule: true,则系统规则与用户规则会被合并(以## System-Specific Rules (Mandatory)与## User-Specific Rules (Mandatory)两段拼接),见 mergeWithSystemRule。
内置系统规则与语言覆盖
以下为内置 system_rules.json 中的主要模式及其对应规则文档(按相对匹配顺序):
| 模式 | 规则文档 |
|---|---|
**/*.properties | properties.md:i18n / 配置文件。 |
**/*{mapper,dao}*.xml | mapper_dao_xml.md:MyBatis 风格 mapper SQL。 |
**/pom.xml | pom_xml.md:Maven 依赖。 |
**/build.gradle | build_gradle.md:Gradle 依赖。 |
**/package.json | package_json.md:NPM 依赖 / 脚本。 |
**/Cargo.toml | cargo_toml.md:Rust manifest。 |
**/composer.json | composer_json.md:Composer 依赖、自动加载、脚本、插件、包配置。 |
**/*.{json,json5} | json.md:通用 JSON(同样匹配.json5)。 |
.github/workflows/**/*.{yaml,yml} | github_workflows.md:GitHub Actions 工作流 YAML。 |
.github/**/*.{yaml,yml} | github_config.md:其他.github配置 YAML。 |
**/*.{yaml,yml} | yaml.md |
**/*.java | java.md |
**/*.go | go.md:Go 源码。 |
**/*.{ftl,ftlh,ftlx} | freemarker.md:FreeMarker 模板(SSTI / XSS / null 处理)。 |
**/*.{hbs,mustache} | handlebars_mustache.md:Handlebars / Mustache 模板。 |
**/*.ets | arkts.md:ArkTS / HarmonyOS。 |
**/*.astro | astro.md:Astro 组件与 islands。 |
**/*.{ts,js,tsx,jsx,mjs,cjs} | ts_js_tsx_jsx.md |
**/*.{kt,kts} | kotlin.md |
**/*.rs | rust.md |
**/*.R | r.md |
**/*.{cpp,cc,cxx,hpp,hxx} | cpp.md |
**/*.c | c.md |
**/*.{py,ipynb} | python.md:Python 源码。 |
**/*.{php,phtml} | php.md:PHP 源码与 PHP 模板。 |
**/*.proto | protobuf.md:Protocol Buffers 线格式兼容性。 |
**/*.po | po.md:gettext 翻译源目录。 |
**/*.pot | pot.md:gettext 模板文件。 |
**/*.{graphql,gql} | graphql.md:GraphQL 模式与操作。 |
**/*.prisma | prisma.md:Prisma 模式。 |
**/*.jl | julia.md:Julia 源码。 |
**/*.{tf,hcl,tfvars} | terraform.md:Terraform / HCL。 |
**/*.bicep | bicep.md:Bicep(Azure)模板。 |
**/*.elm | elm.md:Elm 源码。 |
**/*.{jsonnet,libsonnet} | jsonnet.md:Jsonnet 配置模板与库。 |
**/*.thrift | thrift.md:Apache Thrift IDL 线格式兼容性。 |
**/*.capnp | capnp.md:Cap'n Proto 模式线格式兼容性。 |
**/*.{v,sv,vh} | verilog.md:Verilog 与 SystemVerilog RTL。 |
**/*.{vhd,vhdl} | vhdl.md:VHDL RTL。 |
**/*.m | matlab.md(或经内容嗅探判定为objc.md) |
**/*.mm | objc.md:Objective-C++ 源码。 |
**/*.sol | solidity.md:Solidity 智能合约。 |
**/*.vy | vyper.md:Vyper 智能合约。 |
| (兜底) | default.md |
此外,实际 system_rules.json 还内置了**/*.pug → pug.md、**/*.nix → nix.md、**/*.{hs,lhs} → haskell.md、**/*.{nim,nims,nimble} → nim.md、**/*.swift → swift.md、**/*.zig → zig.md、**/*.{ml,mli} / **/*.{re,rei} → ocaml.md等模式,全部规则文档位于 internal/config/rules/rule_docs/ 目录,规则文本按path_rule_map的键顺序(首个匹配优先)解析——system_rules.go 专门实现了保序的UnmarshalJSON以维持"先匹配先得"语义。
这些内置规则文档并非空泛提示。以 go.md 为例,它明确给出 Go 专项检查清单:错误包装需用%w保留错误链、sync.Once不适合失败重试、context必须显式传递而非存进 struct、math/rand不得用于安全敏感密钥(须用crypto/rand)、SQL/命令拼接需参数化、以及"先取证再上报"(使用file_read与code_search建立调用点证据)等原则。这正是文档所述"内置多语言规则集(NPE、线程安全、XSS、SQL 注入)"的具体承载。
解析出的规则正文,最终成为 plan 与 main task prompt 中{{system_rule}}占位符的内容,见 internal/config/template/prompts/main_task_user.md 与 internal/config/template/prompts/plan_task_user.md,也注入 scan_template.json 的 Review Checklist 段。
.m文件的内容嗅探(Content Sniffing)
.m扩展名被 MATLAB 与 Objective-C 共用。OCR 通过窥视文件首个非空行来区分:若内容像 Objective-C(如#import、@implementation、C 风格注释),则改用objc.md替代matlab.md;若无法读取内容则回退matlab.md。源码见 internal/config/rules/sniffer.go:objcSniffPrefixes列出#import、#include、#pragma、#if、#define、@import、@interface、@implementation、@class、@protocol、//、/*等判定前缀(sniffer.go),并刻意不把裸#当作信号,以免误伤把#当注释符的 Octave/MATLAB 文件。评审模式(range/commit)下还会通过git show <ref>:<path>读取指定 ref 的内容,而不是工作区,保证未检出的 ref 也能正确解析(showAtRef)。
稳定性提示。嗅探启发式可能随 OCR 版本变化。若需要对
.m文件做确定性路由,请为.m路径配置显式的项目级规则——项目规则永远优先于系统层。
验证生效规则:ocr rules check
当某条规则没有按预期生效时,用此命令查看实际生效的层与模式:
$ ocr rules check src/main/java/com/example/UserService.java File: src/main/java/com/example/UserService.java Source: System built-in Pattern: **/*.java Rule: ──────────────────────────────────────── …contents of java.md… ────────────────────────────────────────$ ocr rules check --rule custom.json src/main/resources/mapper/UserMapper.xml File: src/main/resources/mapper/UserMapper.xml Source: Custom (--rule) Pattern: **/*mapper*.xml Rule: ──────────────────────────────────────── …contents of your custom rule… ────────────────────────────────────────命令实现位于 cmd/opencodereview/rules_cmd.go:通过rules.NewResolver构建完整四层解析器,再以DetailResolver.ResolveDetail取回{Rule, Source, Pattern}元数据。Source对应四种标签:Custom (--rule)、Project (.opencodereview/rule.json)、Global (~/.opencodereview/rule.json)、System built-in;若规则经内容嗅探选中(如.m判定为 Objective-C),还会额外打印Note: rule selected by file content (objc), not by path alone一行。该命令还支持--repo标志指定仓库目录。
实战配方(Recipes)
项目级:强制团队编码规范
保存为<repo>/.opencodereview/rule.json并提交到仓库:
{ "rules": [ { "path": "src/api/**/*.go", "rule": "Every public handler must `defer tx.Rollback()` immediately after starting a transaction." }, { "path": "**/*mapper*.xml", "rule": "Check SQL for injection risks, missing parameter binding, and unclosed XML tags." } ] }项目级:跳过生成代码,聚焦 src
{ "include": ["src/**/*.{ts,tsx,js,jsx}"], "exclude": ["**/*.gen.ts", "**/generated/**"] }设置include后,src/内的文件即使原本会命中内置默认排除模式(如测试文件)也会被保留;src/之外的文件仍走常规的 ext / default 检查。再次强调:include是旁路机制,不是白名单。
按 PR 覆盖规则
ocr review --rule ./.review-rules-only-for-this-pr.json这会同时旁路项目层与全局层。适用于单个 PR 需要完全不同的评审清单(例如只做安全评审)的场景。--rule的 CLI 最高优先级、按声明顺序首个匹配生效,均与四层链一致(见 rules_cmd.go 中review命令对--rule的处理)。
全局个人偏好
放在~/.opencodereview/rule.json,本机所有仓库继承:
{ "rules": [ { "path": "**/*.{ts,tsx,js,jsx}", "rule": "Always check for unhandled promise rejections; warn on `// eslint-disable` without a reason comment." } ] }与配置、架构的关联
规则解析是配置系统"层级化解析链"的一部分;解析出的规则正文会经由{{system_rule}}占位符进入 agent prompt(详见 配置文档 与 架构文档)。ocr review的--rule、--preview以及ocr rules check的完整参数说明见 CLI 参考。排查"规则为什么没生效"时,推荐流程为:先ocr rules check <path>确认命中层与模式,再ocr review --preview确认文件是否通过五段式过滤,最后对照本文的四层链与 glob 语法核对配置。
【免费下载链接】open-code-reviewFast, efficient, battle-tested at Alibaba's scale. Hybrid architecture code review tool: deterministic pipelines + LLM Agent, precise line-level comments, built-in multi-language ruleset (NPE, thread-safety, XSS, SQL injection), OpenAI & Anthropic compatible.项目地址: https://gitcode.com/GitHub_Trending/op/open-code-review
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考