# How to Use System Rules for Path-Based Review Customization in Open Code Review

> Customize your Open Code Review workflow with path-based system rules. Learn how to use glob patterns in YAML to define default review behavior for specific file paths.

- Repository: [Alibaba/open-code-review](https://github.com/alibaba/open-code-review)
- Tags: how-to-guide
- Published: 2026-08-03

---

**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`](https://github.com/alibaba/open-code-review/blob/main/.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`](https://github.com/alibaba/open-code-review/blob/main/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.

```go
// 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`](https://github.com/alibaba/open-code-review/blob/main/internal/config/rules/loader.go). This module reads [`.ocr_rules.yaml`](https://github.com/alibaba/open-code-review/blob/main/.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`](https://github.com/alibaba/open-code-review/blob/main/internal/scan/agent.go), the resolution call looks like this:

```go
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`](https://github.com/alibaba/open-code-review/blob/main/.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

```yaml

# .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:

```yaml
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`](https://github.com/alibaba/open-code-review/blob/main/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

```bash
ocr review --config .ocr_rules.yaml ./src/main.go

```

### Preview Effective Rules

```bash
ocr rules --path src/main.go

```

This invokes [`cmd/opencodereview/rules_cmd.go`](https://github.com/alibaba/open-code-review/blob/main/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:

```go
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`](https://github.com/alibaba/open-code-review/blob/main/internal/config/rules/loader.go) enables introspection of per-rule merge preferences.

## Rule Grouping for Efficient Reviews

[`internal/delegate/rulegroup.go`](https://github.com/alibaba/open-code-review/blob/main/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.go`](https://github.com/alibaba/open-code-review/blob/main/internal/config/rules/system_rules.go) and its `LoadDefault()` function
- **User rules** in [`.ocr_rules.yaml`](https://github.com/alibaba/open-code-review/blob/main/.ocr_rules.yaml) override by pattern with precedence based on declaration order
- **Merge control** via `merge_system_rule: true` combines system and custom guidance instead of replacing
- **Resolution happens** in [`internal/scan/agent.go`](https://github.com/alibaba/open-code-review/blob/main/internal/scan/agent.go) using lowercase-normalized paths
- **Efficiency gains** come from rule-based file grouping in [`internal/delegate/rulegroup.go`](https://github.com/alibaba/open-code-review/blob/main/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`](https://github.com/alibaba/open-code-review/blob/main/.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`](https://github.com/alibaba/open-code-review/blob/main/cmd/opencodereview/rules_cmd.go).