From 8943ebe69f17a82885298da82d31c13e1d784b69 Mon Sep 17 00:00:00 2001 From: Dennis Paler Date: Wed, 12 Aug 2026 23:31:09 +0800 Subject: [PATCH] fix: only warn about rule sets dropped for files they actually govern --- CHANGELOG.md | 18 ++++++++++ apps/tui-cli/Cargo.toml | 2 +- apps/tui-cli/src/main.rs | 48 +++++++++++++++++++++----- npm/cli/package.json | 12 +++---- npm/platform/darwin-arm64/package.json | 2 +- npm/platform/darwin-x64/package.json | 2 +- npm/platform/linux-arm64/package.json | 2 +- npm/platform/linux-x64/package.json | 2 +- npm/platform/win32-x64/package.json | 2 +- packages/core-engine/Cargo.toml | 2 +- 10 files changed, 70 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87f2717..b242735 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [0.9.2] — 08-12-2026 + +### Fixed + +- **The dropped-rule-set warning no longer cries wolf.** 0.9.1 measured every + rule set in `.diffmind/rules/` against the budget, so a `react.md` scoped to + `**/*.tsx` was reported as dropped from a diff containing no `.tsx` at all. + The check now runs per changed file, against only the rule sets that actually + govern it, and names the file: + + ``` + ! 2 rule set(s) do not fit the prompt budget (4851 bytes) and were dropped: + aaa-style (on app/dashboard/page.tsx), mmm-quality (on app/dashboard/page.tsx) + ``` + + A warning that fires when nothing is wrong is one people learn to scroll past, + which costs more than having no warning at all. + ## [0.9.1] — 08-12-2026 Config is not code, and reviewing it as though it were produced confident diff --git a/apps/tui-cli/Cargo.toml b/apps/tui-cli/Cargo.toml index 3326e52..9c47467 100644 --- a/apps/tui-cli/Cargo.toml +++ b/apps/tui-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "diffmind" -version = "0.9.1" +version = "0.9.2" edition = "2024" description = "Local-first AI code review agent — powered by on-device inference" diff --git a/apps/tui-cli/src/main.rs b/apps/tui-cli/src/main.rs index f5a12c0..d48e8d8 100644 --- a/apps/tui-cli/src/main.rs +++ b/apps/tui-cli/src/main.rs @@ -579,14 +579,26 @@ impl ProjectRules { } } -/// Say so when the prompt budget cannot fit every rule set. +/// Say so when the prompt budget cannot fit every rule set that applies. /// /// The alternative is what shipped before: a rule set stops applying and -/// nothing anywhere says it did. The check is deliberately at the *widest* -/// budget — depth 0, before any retry shrinks it — so this warns about the -/// rule sets that can never apply, not about a transient squeeze on one -/// oversized unit. -fn warn_on_dropped_rulebooks(backend: &dyn ReviewBackend, settings: &Settings, books: &[Rulebook]) { +/// nothing anywhere says it did. +/// +/// Checked **per changed file**, against the sets that actually govern it. +/// Measuring the whole `.diffmind/rules/` directory instead was the obvious +/// implementation and it cried wolf: a `react.md` scoped to `**/*.tsx` was +/// reported as dropped from a diff containing no `.tsx` at all. A warning that +/// fires when nothing is wrong is one people learn to scroll past, which costs +/// more than having no warning. +/// +/// The budget is taken at depth 0 — the widest — so this reports rule sets that +/// can never fit, not a transient squeeze on one oversized unit. +fn warn_on_dropped_rulebooks( + backend: &dyn ReviewBackend, + settings: &Settings, + books: &[Rulebook], + diff: &str, +) { if books.is_empty() { return; } @@ -595,16 +607,34 @@ fn warn_on_dropped_rulebooks(backend: &dyn ReviewBackend, settings: &Settings, b settings.max_tokens as usize, 0, ); - let dropped = core_engine::rulebooks_dropped(books, budget); + + // Worst affected file per rule set: the same set may fit beside one file's + // neighbours and not another's, and the reviewer only needs to be told once. + let mut dropped: std::collections::BTreeMap = Default::default(); + for file in core_engine::parse_diff(diff) { + let applicable: Vec = books + .iter() + .filter(|b| b.applies_to(&file.path)) + .cloned() + .collect(); + for id in core_engine::rulebooks_dropped(&applicable, budget) { + dropped.entry(id).or_insert_with(|| file.path.clone()); + } + } + if dropped.is_empty() { return; } + let named: Vec = dropped + .iter() + .map(|(id, path)| format!("{id} (on {path})")) + .collect(); eprintln!( " ! {} rule set(s) do not fit the prompt budget ({budget} bytes) and were \ dropped: {}", dropped.len(), - dropped.join(", ") + named.join(", ") ); eprintln!( " Lowest severity is dropped first. Narrow their `scope`, shorten them, \ @@ -620,7 +650,7 @@ pub fn build_analyzer( ticket: Option, project: ProjectRules, ) -> ReviewAnalyzer { - warn_on_dropped_rulebooks(&*backend, settings, &project.books); + warn_on_dropped_rulebooks(&*backend, settings, &project.books, diff); let mut analyzer = ReviewAnalyzer::new(backend) .with_unit_grouper(unit_grouper(project_root)) diff --git a/npm/cli/package.json b/npm/cli/package.json index 407e59d..03e3443 100644 --- a/npm/cli/package.json +++ b/npm/cli/package.json @@ -1,6 +1,6 @@ { "name": "@diffmind/cli", - "version": "0.9.1", + "version": "0.9.2", "description": "Local-first AI code review for your git diffs \u2014 on-device inference, no cloud, no API keys", "author": "Thinkgrid Labs ", "license": "MIT", @@ -39,10 +39,10 @@ "node": ">=18.0.0" }, "optionalDependencies": { - "@diffmind/cli-darwin-arm64": "0.9.1", - "@diffmind/cli-darwin-x64": "0.9.1", - "@diffmind/cli-linux-arm64": "0.9.1", - "@diffmind/cli-linux-x64": "0.9.1", - "@diffmind/cli-win32-x64": "0.9.1" + "@diffmind/cli-darwin-arm64": "0.9.2", + "@diffmind/cli-darwin-x64": "0.9.2", + "@diffmind/cli-linux-arm64": "0.9.2", + "@diffmind/cli-linux-x64": "0.9.2", + "@diffmind/cli-win32-x64": "0.9.2" } } diff --git a/npm/platform/darwin-arm64/package.json b/npm/platform/darwin-arm64/package.json index bd63b7e..f52fa92 100644 --- a/npm/platform/darwin-arm64/package.json +++ b/npm/platform/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@diffmind/cli-darwin-arm64", - "version": "0.9.1", + "version": "0.9.2", "description": "diffmind prebuilt binary for darwin-arm64 (aarch64-apple-darwin)", "author": "Thinkgrid Labs ", "license": "MIT", diff --git a/npm/platform/darwin-x64/package.json b/npm/platform/darwin-x64/package.json index c3f5382..8798b2c 100644 --- a/npm/platform/darwin-x64/package.json +++ b/npm/platform/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@diffmind/cli-darwin-x64", - "version": "0.9.1", + "version": "0.9.2", "description": "diffmind prebuilt binary for darwin-x64 (x86_64-apple-darwin)", "author": "Thinkgrid Labs ", "license": "MIT", diff --git a/npm/platform/linux-arm64/package.json b/npm/platform/linux-arm64/package.json index b320b82..1e5e934 100644 --- a/npm/platform/linux-arm64/package.json +++ b/npm/platform/linux-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@diffmind/cli-linux-arm64", - "version": "0.9.1", + "version": "0.9.2", "description": "diffmind prebuilt binary for linux-arm64 (aarch64-unknown-linux-gnu)", "author": "Thinkgrid Labs ", "license": "MIT", diff --git a/npm/platform/linux-x64/package.json b/npm/platform/linux-x64/package.json index a214529..c79a1d0 100644 --- a/npm/platform/linux-x64/package.json +++ b/npm/platform/linux-x64/package.json @@ -1,6 +1,6 @@ { "name": "@diffmind/cli-linux-x64", - "version": "0.9.1", + "version": "0.9.2", "description": "diffmind prebuilt binary for linux-x64 (x86_64-unknown-linux-gnu)", "author": "Thinkgrid Labs ", "license": "MIT", diff --git a/npm/platform/win32-x64/package.json b/npm/platform/win32-x64/package.json index a9bcc26..4782dcd 100644 --- a/npm/platform/win32-x64/package.json +++ b/npm/platform/win32-x64/package.json @@ -1,6 +1,6 @@ { "name": "@diffmind/cli-win32-x64", - "version": "0.9.1", + "version": "0.9.2", "description": "diffmind prebuilt binary for win32-x64 (x86_64-pc-windows-msvc)", "author": "Thinkgrid Labs ", "license": "MIT", diff --git a/packages/core-engine/Cargo.toml b/packages/core-engine/Cargo.toml index bc3a9eb..f4b7c19 100644 --- a/packages/core-engine/Cargo.toml +++ b/packages/core-engine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "core-engine" -version = "0.9.1" +version = "0.9.2" edition = "2024" description = "Diffmind shared AI engine core"