<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nouman Qureshi</title>
    <description>The latest articles on DEV Community by Nouman Qureshi (@nouman_qureshi_dd9fc28a5a).</description>
    <link>https://dev.to/nouman_qureshi_dd9fc28a5a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4223889%2Fe01455cc-7dc7-4cc8-a75a-8c2e64c6b264.jpg</url>
      <title>DEV Community: Nouman Qureshi</title>
      <link>https://dev.to/nouman_qureshi_dd9fc28a5a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nouman_qureshi_dd9fc28a5a"/>
    <language>en</language>
    <item>
      <title>Why developers mute AI code reviewers (and what I changed to stop it)</title>
      <dc:creator>Nouman Qureshi</dc:creator>
      <pubDate>Tue, 03 Nov 2026 09:24:09 +0000</pubDate>
      <link>https://dev.to/nouman_qureshi_dd9fc28a5a/why-developers-mute-ai-code-reviewers-and-what-i-changed-to-stop-it-1pjh</link>
      <guid>https://dev.to/nouman_qureshi_dd9fc28a5a/why-developers-mute-ai-code-reviewers-and-what-i-changed-to-stop-it-1pjh</guid>
      <description>&lt;p&gt;Every team I talked to had the same story about AI code review bots: they installed one, it posted 25 comments on the first PR, half of them were wrong, and within two weeks everyone was scrolling past it.&lt;/p&gt;

&lt;p&gt;The bot wasn't useless. It was &lt;strong&gt;noisy&lt;/strong&gt;, and noise teaches people to ignore you. A reviewer that's right 50% of the time is worse than no reviewer, because it trains your team to skip the 50% that matters.&lt;/p&gt;

&lt;p&gt;I've been building Audit Bench Ai (&lt;a href="https://auditbenchai.com" rel="noopener noreferrer"&gt;https://auditbenchai.com&lt;/a&gt;), an AI reviewer for pull requests, and most of the work hasn't been "make the AI smarter". It's been "make the AI shut up unless it can prove something". Here's what actually moved the needle.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Give the model the code that calls your change
&lt;/h2&gt;

&lt;p&gt;Most review bots see the diff and nothing else. But the bugs that hurt are rarely &lt;em&gt;inside&lt;/em&gt; the diff. They're in what the diff breaks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The PR changes this...&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;refundOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amountCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ...but the bug is in a file the PR never touched,&lt;/span&gt;
&lt;span class="c1"&gt;// still passing dollars instead of cents.&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;refundOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So for every changed function, we find where it's called elsewhere in the repository and include short excerpts of those callers, plus related test files. The model can now say &lt;em&gt;"this breaks &lt;code&gt;processReturn()&lt;/code&gt; in returns.ts"&lt;/em&gt; instead of &lt;em&gt;"consider validating the input"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That one change made findings far more specific, and specific findings get fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Make every finding show its evidence
&lt;/h2&gt;

&lt;p&gt;We require each finding to include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the exact line,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;when it breaks&lt;/strong&gt;: the concrete input or sequence that triggers it ("a retried refund is sent twice"),&lt;/li&gt;
&lt;li&gt;and a fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the model can't describe when it breaks, it usually isn't a real bug. Asking for the failure scenario filters out a surprising amount of "this could potentially maybe be an issue" padding.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Keep severity and confidence separate, then calibrate
&lt;/h2&gt;

&lt;p&gt;Models love to call things "critical". So we ask for two separate numbers: &lt;strong&gt;severity&lt;/strong&gt; (how bad if real) and &lt;strong&gt;confidence&lt;/strong&gt; (how sure it's real). After the model answers, deterministic rules decide what gets posted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;findings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// a guess isn't a defect&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;critical&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;high&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// an unproven claim can't block a merge&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Maintainability&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Architecture&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// style is never a merge blocker&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...then merge duplicates on overlapping lines, keeping the more confident one&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because these rules are plain code, the same model output always publishes the same way, and teams can tune the thresholds if they want a stricter or quieter reviewer.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Never say the same thing twice
&lt;/h2&gt;

&lt;p&gt;The fastest way to get muted: post the same comment on every push. When you push a fix for one issue, the bot shouldn't repeat the other four you already saw.&lt;/p&gt;

&lt;p&gt;We match new findings against comments already on the PR by &lt;strong&gt;file and kind of problem, not line number&lt;/strong&gt; (code moves, line numbers lie):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;still open from an earlier review → not posted again&lt;/li&gt;
&lt;li&gt;dismissed by the team → not posted again&lt;/li&gt;
&lt;li&gt;marked fixed but detected again → posted, flagged as &lt;em&gt;reappeared&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The summary simply says "3 not repeated: still open from an earlier review".&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Let developers argue back
&lt;/h2&gt;

&lt;p&gt;This was the change I didn't expect to matter so much. When a developer replies &lt;em&gt;"this can't be null, the caller already checks it"&lt;/em&gt;, the reviewer goes back to the code at the latest commit and answers honestly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Resolved&lt;/strong&gt;: the fix is in&lt;/li&gt;
&lt;li&gt;👍 &lt;strong&gt;Dismissed&lt;/strong&gt;: you're right, not an issue here&lt;/li&gt;
&lt;li&gt;↘️ &lt;strong&gt;Downgraded&lt;/strong&gt;: real, but less serious than first stated&lt;/li&gt;
&lt;li&gt;🔁 &lt;strong&gt;Still applies&lt;/strong&gt;: with the evidence from the code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It judges the reply against the code, not against how confident the reply sounds. And if a team 👎s the same kind of finding a couple of times in a repo, it turns that into a rule and stops raising it there.&lt;/p&gt;

&lt;p&gt;Developers trust a reviewer that can admit it was wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Do the cheap work first
&lt;/h2&gt;

&lt;p&gt;AI calls cost money, and cost decides whether you can run a reviewer on &lt;em&gt;every&lt;/em&gt; PR. So the free work runs first: linters, type checks, Semgrep, secret scanning and complexity analysis. Then only the changed code (plus its callers and tests) goes to the model, one call per file, with results cached so unchanged code is never reviewed twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Did it work?
&lt;/h2&gt;

&lt;p&gt;On an internal benchmark of 25 seeded cases (16 with a planted bug, 9 clean), the current version caught 15 of the 16 bugs and raised &lt;strong&gt;zero&lt;/strong&gt; false alarms on the 9 clean cases. In the push-back tests, it withdrew, downgraded or held its ground correctly in all 3.&lt;/p&gt;

&lt;p&gt;It's a small benchmark, and real PRs are messier, which is why the reviewer also tracks precision per team: of the findings a team reacted to, how many did they accept? That's the number I watch now, not "findings per PR".&lt;/p&gt;

&lt;p&gt;So far 40 teams use it and it has reviewed 220 pull requests. Still early, and I'm learning something from every false positive.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell anyone building (or choosing) an AI reviewer
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Measure &lt;strong&gt;precision&lt;/strong&gt;, not volume. Fewer, correct comments beat many plausible ones.&lt;/li&gt;
&lt;li&gt;Context beats model size. Show the callers and the tests.&lt;/li&gt;
&lt;li&gt;Require a failure scenario for every finding.&lt;/li&gt;
&lt;li&gt;Never repeat yourself across pushes.&lt;/li&gt;
&lt;li&gt;Let people push back, and actually listen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to see what this looks like on a real PR, Audit Bench Ai is a GitHub App (also GitLab, Bitbucket, VS Code and a CLI), and you can &lt;a href="https://auditbenchai.com/scan" rel="noopener noreferrer"&gt;run a free scan on any public repo&lt;/a&gt; without signing up.&lt;/p&gt;

&lt;p&gt;I'd genuinely love to hear: &lt;strong&gt;what made you mute an AI reviewer, or keep one?&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I wrote this post with help from an AI assistant; the product, numbers and lessons are from building Audit Bench Ai.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>codereview</category>
      <category>github</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
