How to Use System Rules for Path-Based Review Customization in Open Code Review
System rules in Open Code Review provide default review behavior that you can override or merge with user-defined rules using glob patterns in a YAML configuration file.
Open Code Review (OCR) from Alibaba implements a layered rule system that lets you customize code review behavior for specific file paths. The system rules serve as a built-in fallback layer handling binary detection, language-specific linting, and generic review policies. By adding user rules in .ocr_rules.yaml, you can target specific paths with tailored review instructions while optionally preserving or replacing the system defaults.
Understanding the Rule Resolution Architecture
OCR's rule engine operates through a clear precedence model. The system resolves which rule applies to each file through a multi-stage pipeline before generating LLM prompts.
System Rule Layer
The foundation resides in internal/config/rules/system_rules.go. This file defines the SystemRule struct containing glob patterns mapped to rule text, plus a DefaultRule for unmatched files. The LoadDefault() function parses embedded rule definitions into a runtime resolver.
// From internal/config/rules/system_rules.go
type SystemRule struct {
Patterns []PatternRule
DefaultRule string
}
User Rule Loader
Your customizations enter through internal/config/rules/loader.go. This module reads .ocr_rules.yaml and constructs a Resolver implementing the same interface as the system resolver. User rules take precedence—OCR checks them first in declaration order.
Resolution in the Scan Agent
During actual scanning at internal/scan/agent.go, the resolution call looks like this:
ruleText := a.args.SystemRule.Resolve(strings.ToLower(it.Path))
The lowercase normalization ensures case-insensitive path matching across platforms.
Creating Path-Based Rule Customizations
Define your rules in .ocr_rules.yaml at your project root. Each entry contains a glob pattern, the rule text, and an optional merge_system_rule flag.
Basic Override Pattern
# .ocr_rules.yaml
rules:
- pattern: "**/*.go"
rule: |
# Go-specific review rule
- Check for gofmt / go vet issues
- Enforce proper error handling
- Verify context propagation in function signatures
- pattern: "docs/**"
rule: |
# Documentation rule
- Verify Markdown headings hierarchy (single H1)
- Ensure code snippets are syntactically correct
- Flag broken internal links
merge_system_rule: true
In this example:
- Go files receive only the Go-specific rule (default replace behavior)
- Documentation files receive both system rules and custom rules (merged)
Pattern Precedence
Rules evaluate in list order. Place more specific patterns before general ones:
rules:
- pattern: "internal/crypto/**/*.go" # Specific first
rule: "Apply cryptography security audit..."
- pattern: "**/*.go" # General fallback
rule: "Apply standard Go review..."
Merging vs. Replacing System Rules
The merge_system_rule boolean controls combination behavior. When true, OCR concatenates the system rule with your custom rule, separated by a delimiter. This preserves binary detection and safety checks while adding domain-specific guidance.
| Setting | Behavior | Use Case |
|---|---|---|
false (default) |
Replace system rule entirely | Fully custom review for mature codebases |
true |
Append to system rule | Augment rather than supplant defaults |
The merge logic appears in internal/delegate/rulegroup.go, which also clusters files sharing identical resolved rule text for efficient batch processing.
CLI Commands for Rule Management
Review with Custom Rules
ocr review --config .ocr_rules.yaml ./src/main.go
Preview Effective Rules
ocr rules --path src/main.go
This invokes cmd/opencodereview/rules_cmd.go to display the resolved rule without executing a full review.
Programmatic Rule Resolution
For tooling integrations, use the Go API directly:
package main
import (
"strings"
"github.com/alibaba/open-code-review/internal/config/rules"
"github.com/alibaba/open-code-review/internal/scan"
)
func resolveRulesForPath(filePath string) (string, error) {
// Load user rules
userResolver, err := rules.LoadFile(".ocr_rules.yaml")
if err != nil {
return "", err
}
// Load system rules as fallback
sysResolver, err := rules.LoadDefault()
if err != nil {
return "", err
}
normalized := strings.ToLower(filePath)
ruleText := userResolver.Resolve(normalized)
// Check if merge is requested for this path
if detail, ok := userResolver.(rules.DetailResolver); ok {
sysText := sysResolver.Resolve(normalized)
ruleText = mergeRules(sysText, ruleText)
}
return ruleText, nil
}
The DetailResolver interface exposure in internal/config/rules/loader.go enables introspection of per-rule merge preferences.
Rule Grouping for Efficient Reviews
internal/delegate/rulegroup.go implements an optimization: files with identical resolved rule text get grouped together. This allows the LLM reviewer to process batches sharing the same instructions, reducing token overhead and maintaining context consistency.
The grouping key is the complete resolved rule text, so two files with different merge configurations (one merged, one replaced) will not group together even if their final rule text happens to match.
Summary
- System rules provide built-in defaults via
internal/config/rules/system_rules.goand itsLoadDefault()function - User rules in
.ocr_rules.yamloverride by pattern with precedence based on declaration order - Merge control via
merge_system_rule: truecombines system and custom guidance instead of replacing - Resolution happens in
internal/scan/agent.gousing lowercase-normalized paths - Efficiency gains come from rule-based file grouping in
internal/delegate/rulegroup.go
Frequently Asked Questions
What happens if no user rule matches a file path?
The system falls back to SystemRule.Resolve() which returns either a pattern-matched system rule or the DefaultRule. This ensures every file receives review instructions even without user configuration.
Can I disable system rules entirely for specific paths?
Yes. Omit merge_system_rule or set it to false. The resolved rule will contain only your custom text. However, this removes safety checks like binary file detection—use with caution for security-sensitive repositories.
Does pattern order matter in .ocr_rules.yaml?
Absolutely. The resolver evaluates patterns sequentially and stops at the first match. Place specific patterns (e.g., internal/api/**/*.go) before general ones (e.g., **/*.go) to ensure correct precedence.
How do I verify which rule applies without running a full review?
Use ocr rules --path <filepath>. This command instantiates the same resolver chain used during review but outputs the resolved text instead of invoking the LLM, as implemented in cmd/opencodereview/rules_cmd.go.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →