Skip to content

Commit 757dd63

Browse files
committed
fix: stop reviewing agent config, ignore files and docs
1 parent 8059d43 commit 757dd63

16 files changed

Lines changed: 389 additions & 18 deletions

File tree

CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
# Changelog
22

3+
## [0.9.1] — 08-12-2026
4+
5+
Config is not code, and reviewing it as though it were produced confident
6+
nonsense. Reported from the field: every file under `.claude/` came back HIGH.
7+
8+
### Fixed
9+
10+
- **Coding-agent and editor config is no longer reviewed.** `.claude/`,
11+
`.cursor/`, `.windsurf/`, `.aider/`, `.vscode/`, `.idea/`, `.zed/` and
12+
`.fleet/` are dropped by the pre-filter. These files are imperative English
13+
about credentials, shell commands and permissions — precisely the shape a
14+
reviewer prompt primed for "exposed secrets, disabled auth" reads as an
15+
emergency. `.claude/` is also instructions written *for* a model, which is a
16+
poor thing to hand to one.
17+
- **Ignore files and formatter config are dropped**: `.gitignore`,
18+
`.dockerignore`, `.prettierignore` and the rest of the `.*ignore` family,
19+
plus `.editorconfig`, `.gitattributes`, `.prettierrc*`, `.eslintrc*`,
20+
`.npmrc`, `.nvmrc`, `.cursorrules`. Declarative lists with no program logic
21+
in them. `eslint.config.js` and friends are still reviewed — those are real
22+
JavaScript, and a bug in one is a bug.
23+
- **Documentation is dropped by default** (`.md`, `.mdx`, `.rst`, `.txt`,
24+
`.adoc`, `.org`, `.tex`). Re-enable with `--include-docs` or
25+
`review.include_docs = true` for docs that carry API contracts. The switch
26+
covers prose only — agent config stays out either way.
27+
28+
Everything dropped is *counted and reported* in the existing summary line
29+
("312 hunks → 74 reviewable"), under the new `docs` and `tool config` reasons,
30+
rather than silently disappearing. Test files are unaffected and still
31+
reviewed: a test that asserts nothing is worth catching.
32+
333
## [0.9.0] — 08-12-2026
434

535
diffmind was built as a gate: run it, get a verdict, pass or fail. This release

README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Diffmind — a code review gate you can actually keep
1+
# Diffmind — local-first AI code review, in your terminal
22

33
[![CI](https://github.com/thinkgrid-labs/diffmind/actions/workflows/ci.yml/badge.svg)](https://github.com/thinkgrid-labs/diffmind/actions/workflows/ci.yml)
44
[![Latest Release](https://img.shields.io/github/v/release/thinkgrid-labs/diffmind)](https://github.com/thinkgrid-labs/diffmind/releases/latest)
@@ -552,12 +552,16 @@ work to it.
552552
1. **Parse** — the diff is turned into per-file hunks with correct before and
553553
after line numbers.
554554
2. **Filter** — lockfiles, `linguist-generated` paths, `@generated` banners,
555-
minified bundles, assets, snapshots, your `ignore` globs and whitespace-only
556-
hunks are dropped. This is free, usually removes most of a real branch, and
557-
the counts are shown instead of hidden:
555+
minified bundles, assets, snapshots, documentation, coding-agent and editor
556+
config (`.claude/`, `.cursor/`, `.vscode/`, …), ignore files and formatter
557+
settings, your `ignore` globs, and whitespace-only hunks are dropped. This is
558+
free, usually removes most of a real branch, and the counts are shown instead
559+
of hidden:
558560
`312 hunks → 74 reviewable (238 filtered: lockfiles, generated, formatting)`.
559561
Whitespace inside a string still counts as a real change, and indentation is
560-
never dropped in Python or YAML.
562+
never dropped in Python or YAML. Tests are *not* filtered — a test that
563+
asserts nothing is worth catching. Docs can be reopened with
564+
`--include-docs`.
561565
3. **Fixed rules** — `DM001`, `DM002` and your regex rules. No model involved.
562566
4. **Context** — built for each review from `.diffmind/graph.db`: the function
563567
the hunk is in, the callers of every changed symbol, the definitions it
@@ -601,6 +605,7 @@ cache = true
601605
temperature = 0.0 # 0 = greedy and reproducible
602606
max_tokens = 1024
603607
ignore = ["**/legacy/**", "*.generated.ts"] # on top of the built-in noise rules
608+
include_docs = false # review .md/.rst/.txt too; off by default
604609
605610
[backend]
606611
kind = "local" # or "ollama" / "openai-compatible"

apps/tui-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "diffmind"
3-
version = "0.9.0"
3+
version = "0.9.1"
44
edition = "2024"
55
description = "Local-first AI code review agent — powered by on-device inference"
66

apps/tui-cli/src/cli.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ pub struct Cli {
115115
#[arg(long)]
116116
pub seed: Option<u64>,
117117

118+
/// Review documentation (.md, .rst, .txt) too. Skipped by default —
119+
/// a reviewer prompt finds vulnerabilities in prose.
120+
#[arg(long)]
121+
pub include_docs: bool,
122+
118123
/// Skip the on-disk result cache for this run
119124
#[arg(long)]
120125
pub no_cache: bool,

apps/tui-cli/src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ pub struct ReviewConfig {
3939
/// Same syntax as a rule's `files`: `*.ts`, `**/legacy/**`, or an exact path.
4040
#[serde(default)]
4141
pub ignore: Option<Vec<String>>,
42+
/// Review documentation (`.md`, `.rst`, `.txt`) as code. Off by default:
43+
/// a model primed for vulnerabilities will find them in prose. Tool config
44+
/// and ignore files are always skipped and have no switch.
45+
pub include_docs: Option<bool>,
4246
/// Refresh the code graph before each review. On by default — a stale graph
4347
/// reports wrong line ranges, not merely missing ones.
4448
pub auto_index: Option<bool>,

apps/tui-cli/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@ fn apply_prefilter(
702702
&PrefilterOptions {
703703
generated_paths,
704704
ignore_globs: settings.ignore_globs.clone(),
705+
include_docs: settings.include_docs,
705706
},
706707
);
707708

apps/tui-cli/src/settings.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ pub struct Settings {
7171
pub debug: bool,
7272
/// Extra globs dropped by the pre-filter, from `.diffmind/config.toml`.
7373
pub ignore_globs: Vec<String>,
74+
/// Send documentation to the model instead of dropping it as prose.
75+
pub include_docs: bool,
7476
/// Refresh the code graph before reviewing.
7577
pub auto_index: bool,
7678
}
@@ -137,6 +139,7 @@ pub fn resolve_settings(cli: &Cli, file: &FileConfig) -> Result<Settings> {
137139
// *supposed* to differ, and replaying one would be a lie.
138140
use_cache: !cli.no_cache && resolve(None, r.cache, true) && temperature == 0.0,
139141
ignore_globs: r.ignore.clone().unwrap_or_default(),
142+
include_docs: cli.include_docs || resolve(None, r.include_docs, false),
140143
auto_index: !cli.no_index && resolve(None, r.auto_index, true),
141144
use_baseline: !cli.no_baseline,
142145
use_daemon: !cli.no_daemon,

apps/tui-cli/tests/stdin_pipeline.rs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,3 +483,146 @@ fn the_exit_code_follows_the_fail_threshold_not_the_finding_count() {
483483

484484
let _ = std::fs::remove_dir_all(&dir);
485485
}
486+
487+
/// Agent config, ignore files and prose must not cost an inference pass — and
488+
/// must not reach the model at all.
489+
///
490+
/// Reported from the field on 0.9.0: every file under `.claude/` came back as a
491+
/// HIGH finding. Those files are imperative English about credentials, shell
492+
/// commands and permissions, which is exactly what a reviewer prompt primed for
493+
/// "exposed secrets, disabled auth" is looking for. The content assertions
494+
/// matter more than the path ones here: a path can vanish from the prompt while
495+
/// the body is still being reviewed under the previous file's header.
496+
#[test]
497+
fn agent_config_ignore_files_and_docs_never_reach_the_model() {
498+
let dir = tmpdir("toolconfig");
499+
let stub = Stub::spawn(2);
500+
501+
let diff = "\
502+
--- a/.claude/skills/deploy.md
503+
+++ b/.claude/skills/deploy.md
504+
@@ -1,2 +1,3 @@
505+
# Deploy
506+
+Always export AWS_SECRET_ACCESS_KEY before deploying.
507+
--- a/.gitignore
508+
+++ b/.gitignore
509+
@@ -1,2 +1,2 @@
510+
-.env
511+
+.env.local
512+
--- a/.prettierrc.json
513+
+++ b/.prettierrc.json
514+
@@ -1,1 +1,1 @@
515+
-{ \"semi\": true }
516+
+{ \"semi\": false }
517+
--- a/README.md
518+
+++ b/README.md
519+
@@ -1,1 +1,2 @@
520+
# Project
521+
+Put your token in .env
522+
--- a/src/two.rs
523+
+++ b/src/two.rs
524+
@@ -10,2 +10,2 @@
525+
-let b = verify(token);
526+
+let b = true;
527+
";
528+
529+
let run = review_stdin(
530+
&dir,
531+
diff,
532+
&[
533+
"--format",
534+
"json",
535+
"--backend",
536+
"openai-compatible",
537+
"--backend-model",
538+
"stub",
539+
"--backend-url",
540+
&stub.url(),
541+
],
542+
);
543+
544+
let prompts = stub.prompts();
545+
assert_eq!(
546+
prompts.len(),
547+
1,
548+
"only src/two.rs is reviewable.\nstderr: {}",
549+
run.stderr
550+
);
551+
552+
for leaked in [
553+
"AWS_SECRET_ACCESS_KEY",
554+
".claude",
555+
".gitignore",
556+
".env.local",
557+
".prettierrc",
558+
"semi",
559+
"README.md",
560+
"Put your token",
561+
] {
562+
assert!(
563+
!prompts[0].contains(leaked),
564+
"{leaked:?} reached the model:\n{}",
565+
prompts[0]
566+
);
567+
}
568+
assert!(prompts[0].contains("src/two.rs"));
569+
570+
let found = findings(&run.stdout);
571+
let files: Vec<&str> = found.iter().filter_map(|f| f["file"].as_str()).collect();
572+
assert_eq!(files, ["src/two.rs"], "only the code file is reported");
573+
574+
let _ = std::fs::remove_dir_all(&dir);
575+
}
576+
577+
/// The opt-in exists for teams whose docs carry contracts. It reopens prose
578+
/// only — agent config stays out regardless.
579+
#[test]
580+
fn include_docs_reopens_prose_but_not_agent_config() {
581+
let dir = tmpdir("includedocs");
582+
let stub = Stub::spawn(3);
583+
584+
let diff = "\
585+
--- a/.claude/skills/deploy.md
586+
+++ b/.claude/skills/deploy.md
587+
@@ -1,2 +1,3 @@
588+
# Deploy
589+
+Always export AWS_SECRET_ACCESS_KEY before deploying.
590+
--- a/docs/api.md
591+
+++ b/docs/api.md
592+
@@ -1,1 +1,2 @@
593+
# API
594+
+POST /v1/charge is idempotent.
595+
";
596+
597+
let run = review_stdin(
598+
&dir,
599+
diff,
600+
&[
601+
"--include-docs",
602+
"--format",
603+
"json",
604+
"--backend",
605+
"openai-compatible",
606+
"--backend-model",
607+
"stub",
608+
"--backend-url",
609+
&stub.url(),
610+
],
611+
);
612+
613+
let prompts = stub.prompts();
614+
assert_eq!(
615+
prompts.len(),
616+
1,
617+
"docs are reviewed, agent config is not.\nstderr: {}",
618+
run.stderr
619+
);
620+
assert!(prompts[0].contains("docs/api.md"));
621+
assert!(
622+
!prompts[0].contains("AWS_SECRET_ACCESS_KEY"),
623+
"--include-docs must not reopen .claude/:\n{}",
624+
prompts[0]
625+
);
626+
627+
let _ = std::fs::remove_dir_all(&dir);
628+
}

npm/cli/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@diffmind/cli",
3-
"version": "0.9.0",
3+
"version": "0.9.1",
44
"description": "Local-first AI code review for your git diffs \u2014 on-device inference, no cloud, no API keys",
55
"author": "Thinkgrid Labs <dennis@thinkgrid.dev>",
66
"license": "MIT",
@@ -39,10 +39,10 @@
3939
"node": ">=18.0.0"
4040
},
4141
"optionalDependencies": {
42-
"@diffmind/cli-darwin-arm64": "0.9.0",
43-
"@diffmind/cli-darwin-x64": "0.9.0",
44-
"@diffmind/cli-linux-arm64": "0.9.0",
45-
"@diffmind/cli-linux-x64": "0.9.0",
46-
"@diffmind/cli-win32-x64": "0.9.0"
42+
"@diffmind/cli-darwin-arm64": "0.9.1",
43+
"@diffmind/cli-darwin-x64": "0.9.1",
44+
"@diffmind/cli-linux-arm64": "0.9.1",
45+
"@diffmind/cli-linux-x64": "0.9.1",
46+
"@diffmind/cli-win32-x64": "0.9.1"
4747
}
4848
}

npm/platform/darwin-arm64/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@diffmind/cli-darwin-arm64",
3-
"version": "0.9.0",
3+
"version": "0.9.1",
44
"description": "diffmind prebuilt binary for darwin-arm64 (aarch64-apple-darwin)",
55
"author": "Thinkgrid Labs <dennis@thinkgrid.dev>",
66
"license": "MIT",

0 commit comments

Comments
 (0)