DEV Community

CopperSunDev
CopperSunDev

Posted on • Originally published at coppersun.dev

Why Claude Code Emits Eight Findings When One Matters

Open a pull request. Run Claude Code or Cursor over the diff. Wait.

Eight suggestions per file. Maybe more. They look something like:

  1. Consider using a Map instead of a plain object here for better lookup performance.
  2. This function could benefit from explicit type annotations.
  3. You might want to handle the case where the input array is empty.
  4. Consider extracting this logic into a separate function for reusability.
  5. SQL query is concatenating user input without parameterization — possible SQL injection. ← the real one
  6. This variable name could be more descriptive.
  7. Consider adding JSDoc comments to this function.
  8. The use of any here loses type safety.

The fifth item is a ship-blocker. The other seven are speculative, style-driven, or apply to some general-purpose codebase that isn't yours. Combined: a developer spends 80% of their triage time dismissing items 1, 2, 3, 4, 6, 7, 8 to reach item 5 — which by the time they get there, they're mentally tuned to dismiss too, because they've been clicking "ignore" for three minutes straight.

This is the noise problem. It's the single biggest reason AI code review hasn't caught on as a critical-path tool the way linters did 20 years ago.

Why AI Code Review Tools Emit So Much Noise

BrassCoders treats AI-review noise as a structural property of the tool, not a calibration issue. The honest answer: AI assistants are trained to be helpful, and helpfulness in this context manifests as suggesting improvements rather than ranking by what actually breaks.

The model isn't grounded in "what actually breaks production." It's grounded in "what could conceivably be better." Style nits, generic best-practices, refactoring opportunities — all could be valid in some context, somewhere. So the model emits them. The cost is borne by the developer doing the triage.

This isn't a bug in Claude Code or Cursor specifically. It's a structural property of using a general-purpose LLM as a code reviewer. The model's incentive function (be helpful) doesn't have a "speak only when there's a real defect" mode that's distinguishable from "speak only about defects of a particular severity."

You can prompt your way to slightly less noise — only flag actual bugs, not style suggestions — but the LLM's calibration of "actual bug" is fuzzy, and the next response includes a "consider using let instead of var" anyway.

The Real Shape of Static-Analysis Noise

BrassCoders measures the per-codebase shape of static-analysis noise directly. A typical real-world Python project produces around 1,500 raw scanner findings across 12 tools, of which roughly 30 survive relevance ranking. The raw output below is what a competent static-analysis stack produces by default.

  • Secrets detection finds 800 matches. Most are false positives (test fixtures, example values, hash-like strings in comments).
  • Privacy detection finds 300 matches. Most are sample data in test files.
  • Code-quality scanners (Bandit, Pylint) flag 200 items. Most are style issues that don't materially affect correctness.
  • AI anti-pattern scanner flags 50 items. A few are real (eval-on-input, string-concat in loops).
  • Phantom import scanner flags 30 items. About 15 are real broken imports.

Total: ~1380 findings. Real critical/high bugs: maybe 50.

The noise isn't because the scanners are bad. detect-secrets is excellent; Bandit is excellent. The noise is because all useful scanners over-trigger by design — they'd rather flag a false positive than miss a real CVE. Each scanner individually does the right thing. Aggregated, the human reviewer drowns.

Layer AI code review on top of that, and you've made the problem worse: now you have 1380 static-analysis findings PLUS 8-per-file suggestions from your LLM-based reviewer. A 50-file PR ships with 1780 "things to look at." Nobody looks at any of them carefully.

What Actually Works: Adding a Filter Layer

BrassCoders treats the AI-code-review problem as a filtering problem, not a detection problem. The structural insight: the static-analysis ecosystem already detects the bugs, and the bottleneck is the filtering layer that turns 1,500 raw findings into the 30 a developer actually addresses.

What developers need is a layer that runs after detection and before triage — that takes 1500 raw findings and outputs ~300 ranked, deduplicated, project-aware ones. That's what BrassCoders does.

The architecture splits into:

  • Detection layer (free, open source): 12 scanners covering secrets, PII, code quality, AI anti-patterns, taint analysis, performance. These are commodity — Bandit, Pylint, Pyre/Pysa, Semgrep, detect-secrets — wired together with a uniform output format.
  • Filtering layer: priority-bucket assignment, per-file caps, severity-aware noise reduction. Heuristic version ships in the OSS core. AI-powered version (semantic dedup, cluster sizing, rerank-against-project-signature) ships in the $12/month Paid plan.

The AI step happens AFTER detection runs. The model never sees raw source code. It sees scoped findings with their metadata (file path, severity, scanner, snippet) and decides which ones describe the same underlying bug.

What This Looks Like in Practice

Run BrassCoders against whisperx-production (a real ~2K-file Python project). Output:

🧹 Running intelligent optimization...
   Intelligent optimization: 801 → 687 findings (14.2% reduction)
✨ Running AI enrichment...
   Enriched: 687 → 328 findings (359 duplicates dropped)
Enter fullscreen mode Exit fullscreen mode

The 12 scanners surface 801 findings. The OSS-core heuristic filter drops obvious noise down to 687. The AI enrichment dedups + ranks down to 328 — that's the survivor set the developer actually reads.

Of those 328, the top items are real:

🎯 Top Issues:
   1. Broken Import: whisperx (critical)
   2. Broken Import: pyannote.audio (critical)
   3. Hardcoded credential in lib/indexnow.js:12 (high)
   4. SSRF vulnerability in lib/runpod.ts:198 (high)
Enter fullscreen mode Exit fullscreen mode

Each one is a fix to ship, not a style preference. The 1450-item firehose has been distilled to a 4-item priority list.

The Bottom Line

BrassCoders does not replace AI code review tools. AI assistants are useful for what they are useful for (catching obvious patterns, summarizing diffs, generating boilerplate), and their output is noise that needs filtering before a developer can act on it as a triage queue.

BrassCoders is the filter.

  • Free OSS core: pipx install brasscoders
  • Paid plan ($12/dev/mo): semantic dedup + ranking against your project. Subscribe at coppersun.dev/pricing.

For the broader context on AI code review failure modes, see AI Code Review: The Practical Guide for 2026.

Top comments (0)