第 3 章 · 01 评审规则


第 3 章 · 01 评审规则

本节摘要:规则告诉 OCR 评审每个文件时应关注什么。本节讲两件事:一是规则的四层优先级链(--rule 参数 → 项目 rule.json → 全局 rule.json → 内嵌系统规则),以及规则文件 include/exclude/rules 三个字段的语义;二是文件的五重门过滤算法(binary → user_exclude → user_include → unsupported_ext → default_path),决定哪些文件最终进入评审。读完你能用 ocr rules check 排查「为什么我的规则没触发」和「为什么我的文件没被评审」这两类高频问题。

内容来源:原项目中文文档 pages/src/content/docs/zh/review-rules.md,套用体系化模板改写。

学习目标

阅读完本节,你应当能够:

  1. 说明规则解析的四层优先级链及匹配顺序。
  2. 写出一个含 include/exclude/rules 的项目级规则文件。
  3. 描述文件过滤的五重门算法及各门的含义。
  4. 用 glob 语法(**、{a,b}、?)编写匹配模式。
  5. 用 ocr rules check 与 ocr review --preview 排查规则与过滤问题。
  6. 列出内置系统规则覆盖的常见语言与配置文件。

一、四层优先级链

OCR 用一条四层优先级链解析规则。对每个文件路径,按序尝试各层;第一个匹配的模式生效。

优先级 来源 路径 说明
1(最高) --rule 参数 用户指定 CLI 覆盖;只要提供就总是生效。
2 项目配置 <repoDir>/.opencodereview/rule.json 项目级规则——可安全提交。
3 全局配置 ~/.opencodereview/rule.json 用户级偏好。
4(最低) 系统默认 内嵌 system_rules.json 覆盖常见语言的内置规则。

💡 技巧:若更高优先级层的文件不存在,会被静默跳过——不是错误。因此从未添加 .opencodereview/rule.json 的项目会直接落到全局 / 系统层。系统层始终存在(随二进制发布),因此总会解析出某个规则。

二、规则文件格式(层 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} 条目数组,按声明顺序求值。第一个 path glob 匹配该文件的条目,决定 OCR 发给模型的 prompt。

glob 能力

OCR 用 bmatcuk/doublestar/v4 做匹配:

  • *——匹配除 / 外的任意字符。
  • **——跨目录边界匹配(src/**/*.go 覆盖任意深度)。
  • {a,b,c}——花括号展开。*.{ts,tsx,js,jsx} 展开为四个模式并依次匹配。
  • ?——匹配单个字符。
  • [abc]——字符类。

⚠️ 注意:模式匹配不区分大小写(匹配前文件路径会被小写化)。不确定时用 ocr rules check <path> 确认。花括号展开对空格敏感——{ts, tsx}(带空格)会静默地无法匹配 tsx。

三、五重门文件过滤

过滤是一个五重门算法。对每个 diff,OCR 依次问:

  1. binary——文件是二进制吗?排除。
  2. user_exclude——路径匹配任何用户 exclude 模式吗?排除。
  3. user_include——若用户定义了 include,路径匹配吗?若是,立即保留(绕过下面的 unsupported_ext 和 default_path 门)。
  4. unsupported_ext——文件扩展名在白名单里吗?不在则排除。
  5. default_path——路径匹配某个内置测试文件排除模式(**/*_test.go、**/*.test.{js,jsx,ts,tsx}、**/*_spec.rb……)吗?排除。

通过全部五重门的文件才发给 LLM。deleted 原因(不是门——它在 Preview() 中单独计算)标记新路径为 /dev/null 的文件;没有新内容可评审。

┌─────────────────────────────────────────────────────────────────┐ │ diff 文件 │ │ │ │ │ ▼ │ │ ① binary ──是──► 排除 │ │ │否 │ │ ▼ │ │ ② user_exclude ──是──► 排除 │ │ │否 │ │ ▼ │ │ ③ user_include ──匹配──► 立即保留(绕过 ④⑤) │ │ │不匹配 / 无 include │ │ ▼ │ │ ④ unsupported_ext ──不在白名单──► 排除 │ │ │在白名单 │ │ ▼ │ │ ⑤ default_path ──匹配测试模式──► 排除 │ │ │不匹配 │ │ ▼ │ │ 保留 → 发给 LLM │ └─────────────────────────────────────────────────────────────────┘ ​

💡 技巧:用 ocr review --preview 可在不花 token 的情况下打印此过滤结果,看到每个文件被保留或丢弃的原因。

默认路径排除

内置排除列表匹配测试文件模式:

  • **/*_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

噪声目录过滤(vendor/、node_modules/、target/……)发生在更早的阶段,位于 diff 层,先于 per-file 过滤运行。

⚠️ 注意:要评审一个匹配这些测试文件模式的文件,把它加入用户 include 列表——那会覆盖 default-path 门。

四、每文件的规则解析

过滤决定某文件将被评审后,OCR 选择 agent 应遵循的规则文本:

  1. 按声明顺序试 --rule(custom)层。
  2. 按声明顺序试 <repo>/.opencodereview/rule.json。
  3. 按声明顺序试 ~/.opencodereview/rule.json。
  4. 回退到内嵌系统规则层。

内嵌系统规则覆盖

内嵌 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。
**/*.{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
**/*.{ftl,ftlh,ftlx} freemarker.md——FreeMarker 模板(SSTI / XSS / null 处理)。
**/*.ets arkts.md——ArkTS / HarmonyOS。
**/*.{ts,js,tsx,jsx} ts_js_tsx_jsx.md
**/*.{kt} kotlin.md
**/*.rs rust.md
**/*.{cpp,cc,hpp} cpp.md
**/*.c c.md
(fallback) default.md

解析出的规则正文成为 plan 和 main task prompt 中 {{system_rule}} 占位符的内容(模板与占位符详见本章架构一节)。

五、查看哪条规则生效: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… ──────────────────────────────────────── ​

当某条规则未按预期生效时用它——它会显示生效的层与模式。若层不对(如期望项目规则却显示 System built-in),多半是声明顺序问题——首条匹配模式生效,把更具体的规则在 rules 数组里前移,或修正 glob。

六、配方

项目级:强制编码规范

保存为 <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 需要完全不同的评审清单(如仅安全评审)时很方便。

全局个人偏好

放到 ~/.opencodereview/rule.json,你机器上每个仓库都会继承:

{ "rules": [ { "path": "**/*.{ts,tsx,js,jsx}", "rule": "Always check for unhandled promise rejections; warn on `// eslint-disable` without a reason comment." } ] } ​

💡 技巧:这套项目级 + 全局级的分层与第 2 章的配置分层(~/.opencodereview/config.json + <repo>/.opencodereview/)是一致的——可安全提交的项目文件放仓库,个人偏好放家目录。

本节要点回顾

  1. 四层链:--rule(最高)→ 项目 → 全局 → 系统(最低),首条匹配生效,系统层总在。
  2. 三字段:include(绕过默认排除,非白名单)、exclude(最高优先级排除)、rules(按声明顺序求值的 {path, rule})。
  3. glob:* / ** / {a,b} / ? / [abc],匹配不区分大小写,花括号对空格敏感。
  4. 五重门:binary → user_exclude → user_include → unsupported_ext → default_path,deleted 单独计算。
  5. 系统规则:覆盖 properties、mapper XML、pom/package/Cargo、YAML、Java/Kotlin/Rust/C/TS/JS 等,fallback 到 default.md。
  6. 排查两件套:ocr rules check <path> 看规则层,ocr review --preview 看过滤原因。
  7. 绕过测试排除:把测试文件加入 include 即可覆盖 default-path 门。

规则讲清了。下一节进入架构,看 OCR 从「按下回车」到「JSON 落在终端」的端到端流水线——规则文本如何嵌入 prompt、文件如何被并行评审、记忆如何被压缩。


作者与出处
原作者: 灏天文库
来源:alibaba
许可证:Apache-2.0
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: 灏天文库 转发
评论区 (0)
U