internal/config/rules — 四層規則解析鏈

system_rules.go、composedResolver、FileFilter
套件:internal/config/rules/(system_rules.go + rule_docs/)

大方向

internal/config/rules 實作規則解析:對每個檔案路徑,依「--rule → 專案 → 全域 → 系統內建」四層鏈找第一條匹配規則,決定發給模型 {{system_rule}} 的內容。內建規則集(NPE、執行緒安全、XSS、SQL injection 等)編譯在 system_rules.json + rule_docs/*.md


1. 內建規則集

SystemRule · LoadDefault() · Resolve() system_rules.go載入內嵌系統規則;依路徑解析規則文本。

LoadDefault 從內嵌資源載入 system_rules.json//go:embed 或 embedded loader)。Resolve(path) 依 glob 模式找匹配並回傳對應的 rule_docs/<lang>.md 內容——這些 markdown 是給模型的「審查清單」,含 NPE、thread-safety、XSS、SQL injection 等檢查點。

2. 四層合成解析器

composedResolver · NewResolver() · mergeWithSystemRule() system_rules.go把四層規則合成單一 Resolver。

NewResolver(repoDir, customRulePath) 依序載入:--rule 檔(有給就用)→ <repo>/.opencodereview/rule.jsonloadProjectRule)→ ~/.opencodereview/rule.jsonloadGlobalRule)→ 系統內建。composedResolver.Resolve 依優先級找第一條匹配;找不到專案/全域時 mergeWithSystemRule 回退系統規則。

FileFilter · HasInclude() · IsUserExcluded() · IsUserIncluded() system_rules.goinclude/exclude 的過濾查詢介面。

FileFilter 從各層 rule.json 彙整 include/exclude。五重門過濾(internal/agent/preview.go)用這些方法:IsUserExcluded 對應第二門、IsUserIncluded 對應第三門(立即保留)。

3. 解析細節

expandBraces() · matchProjectRuleEntry() · resolveRuleEntries() system_rules.go花括號展開、rule entry 匹配、相對路徑解析。

expandBraces 展開 *.{ts,tsx}matchProjectRuleEntry 依宣告順序找第一條 path glob 匹配;resolveRuleEntries 把規則中指向 ./file.md 的相對路徑轉成 repo 內實際檔案(tryReadRuleFile 安全讀取)。

readRuleFileSafe() system_rules.go安全讀取規則檔案。

讀取規則檔時做路徑安全檢查,避免路徑穿越。這是「規則檔可以指向 repo 內其他檔案」功能的安全邊界。

看完這頁你應該能說出:四層鏈的載入順序與 NewResolver 的組裝、FileFilter 如何支援五重門、花括號展開與宣告順序、以及 readRuleFileSafe 的路徑安全。

下一步:internal/tool 或回程式碼對照