<?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: John Problems</title>
    <description>The latest articles on DEV Community by John Problems (@john_problems_).</description>
    <link>https://dev.to/john_problems_</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%2F4109351%2F2822a5af-73c5-4fc3-a3c4-d22ce544d1e6.png</url>
      <title>DEV Community: John Problems</title>
      <link>https://dev.to/john_problems_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/john_problems_"/>
    <language>en</language>
    <item>
      <title>What 1,135 agent-written pull requests taught me about reviewing AI code</title>
      <dc:creator>John Problems</dc:creator>
      <pubDate>Fri, 04 Sep 2026 08:25:20 +0000</pubDate>
      <link>https://dev.to/john_problems_/what-1135-agent-written-pull-requests-taught-me-about-reviewing-ai-code-593j</link>
      <guid>https://dev.to/john_problems_/what-1135-agent-written-pull-requests-taught-me-about-reviewing-ai-code-593j</guid>
      <description>&lt;p&gt;For the last five months I've run an autonomous software team inside a GitHub&lt;br&gt;
repo. 26 agent roles: a Discussion becomes a spec, a spec becomes a pull&lt;br&gt;
request, and nothing merges until code review, security review and acceptance&lt;br&gt;
all pass. It has merged 1,135 PRs.&lt;/p&gt;

&lt;p&gt;This isn't a post about the tool. It's about the five things that turned out to&lt;br&gt;
be true, most of which I got wrong first. They apply to anyone putting agents&lt;br&gt;
anywhere near a codebase, whether you use my thing or not.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Your reviewer and your author share blind spots
&lt;/h2&gt;

&lt;p&gt;A model reviewing another model's code catches slips, conventions, and missing&lt;br&gt;
cases that were visible on the surface. It is much weaker on the defects that&lt;br&gt;
actually hurt — a race, an off-by-one under load, a guard on the wrong side of&lt;br&gt;
a branch. Those read fine. They read fine to the author &lt;em&gt;and&lt;/em&gt; to the reviewer,&lt;br&gt;
for the same reasons.&lt;/p&gt;

&lt;p&gt;If your pipeline is &lt;code&gt;generate → review → merge&lt;/code&gt; and both steps are the same&lt;br&gt;
kind of mind, you have one opinion sampled twice, not two opinions.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. The evidence can be broken, and then good reviews go bad
&lt;/h2&gt;

&lt;p&gt;This is the one that changed how I think.&lt;/p&gt;

&lt;p&gt;A cleanup script's &lt;code&gt;--dry-run&lt;/code&gt; reported 116 removals. The real run, on an&lt;br&gt;
identical population seconds later, removed zero. 190 directories before, 190&lt;br&gt;
after.&lt;/p&gt;

&lt;p&gt;The skip that protects git-tracked worktrees is gated on the run &lt;em&gt;not&lt;/em&gt; being a&lt;br&gt;
dry run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$dry_run&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$enable_git_tracked_removal&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;skip_git_tracked
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="c"&gt;# a dry run never evaluates this, falls through, and reports "would remove"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nobody lost data — the divergence runs the safe way. What broke was subtler.&lt;br&gt;
&lt;strong&gt;Two code reviews had already cited that dry-run output as their&lt;br&gt;
verification.&lt;/strong&gt; A reviewer asked "did you check this against the live&lt;br&gt;
population?" and got a transcript from a tool that could not tell the truth&lt;br&gt;
about the live population.&lt;/p&gt;

&lt;p&gt;The reviews weren't lazy. The evidence was lying.&lt;/p&gt;

&lt;p&gt;The takeaway isn't "distrust reviewers." It's that a verdict is only as good as&lt;br&gt;
the artifact it cites, and almost nobody records &lt;em&gt;which mode produced the&lt;br&gt;
artifact&lt;/em&gt;. &lt;code&gt;dry-run&lt;/code&gt; output and real output should not be the same shape of&lt;br&gt;
evidence, and if your agents attach proof to their claims, that proof needs&lt;br&gt;
provenance.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Make roles data, not code
&lt;/h2&gt;

&lt;p&gt;An agent role in this system is a Markdown behaviour spec plus a JSON policy&lt;br&gt;
record — timeouts, retries, token ceilings, concurrency caps. Adding a role is&lt;br&gt;
writing a file. Changing what a reviewer cares about is editing prose.&lt;/p&gt;

&lt;p&gt;The moment roles became data, three things got easier: diffing a behaviour&lt;br&gt;
change, capping concurrency per role instead of globally, and testing&lt;br&gt;
orchestration without spawning anything.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Structure the output or you'll parse prose forever
&lt;/h2&gt;

&lt;p&gt;Every agent ends its final message with a structured envelope the orchestrator&lt;br&gt;
parses for routing. Not "read the last paragraph and infer whether it passed."&lt;/p&gt;

&lt;p&gt;This single decision removed most of the flakiness in the system. If you are&lt;br&gt;
regexing model prose to decide what happens next, that is where your&lt;br&gt;
intermittent failures live.&lt;/p&gt;

&lt;p&gt;Related: add an &lt;code&gt;unknowns[]&lt;/code&gt; field. An agent that can say "I could not tell&lt;br&gt;
whether this path is reachable" gets routed to a research step for a few&lt;br&gt;
thousand tokens, instead of producing a confident PR that burns a full review&lt;br&gt;
cycle discovering the same thing.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Automation should refuse to guess
&lt;/h2&gt;

&lt;p&gt;Provisioning halts after its first phase. It installs labels, hooks, state and&lt;br&gt;
dependencies — then stops and asks for a backlog.&lt;/p&gt;

&lt;p&gt;I fought this for a while because a halt feels like an unfinished feature. It&lt;br&gt;
isn't. The next step needs to know what you actually want built and what's&lt;br&gt;
explicitly out of scope, and a system that guessed would produce a hundred&lt;br&gt;
confident pull requests solving the wrong problem. Fast, thorough, and wrong is&lt;br&gt;
worse than stopping.&lt;/p&gt;

&lt;p&gt;If you're building agent tooling, find the place where yours is guessing at&lt;br&gt;
intent and make it stop there instead.&lt;/p&gt;
&lt;h2&gt;
  
  
  The uncomfortable one
&lt;/h2&gt;

&lt;p&gt;Most of those 1,135 PRs are the system's own tooling. Spawn queues, review&lt;br&gt;
gates, the circuit breaker, the sandbox guard. For a long stretch its only&lt;br&gt;
product was itself.&lt;/p&gt;

&lt;p&gt;I've come round to thinking that's the interesting part rather than the&lt;br&gt;
embarrassing one — a team that can't improve its own process needs a human for&lt;br&gt;
every improvement, forever — but you should decide that for yourself, which is&lt;br&gt;
why the queue is public.&lt;/p&gt;
&lt;h2&gt;
  
  
  If you want to look
&lt;/h2&gt;

&lt;p&gt;Everything above is from a real system you can inspect without installing&lt;br&gt;
anything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The live work queue&lt;/strong&gt;, pulled from the repo as the page loads, including
the bugs it filed against itself:
&lt;a href="https://fulcrumaxe.dev/discussions.html" rel="noopener noreferrer"&gt;https://fulcrumaxe.dev/discussions.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The codebase as a browsable graph&lt;/strong&gt;, 4,811 nodes:
&lt;a href="https://fulcrumaxe.dev/understand.html" rel="noopener noreferrer"&gt;https://fulcrumaxe.dev/understand.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three rival architecture designs&lt;/strong&gt; I haven't chosen between, one published
with an unsolved cost problem in it:
&lt;a href="https://fulcrumaxe.dev/proposals.html" rel="noopener noreferrer"&gt;https://fulcrumaxe.dev/proposals.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's AGPL-3.0 and self-hosted — your machine, your repo, your key, no service&lt;br&gt;
in the middle. Install is three lines in Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin marketplace add fulcrumaxe/fulcrumaxe
/plugin install fulcrumaxe@fulcrumaxe
/coldstart --path /path/to/your/repo --name your-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;a href="https://github.com/fulcrumaxe/fulcrumaxe" rel="noopener noreferrer"&gt;https://github.com/fulcrumaxe/fulcrumaxe&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer anything in the comments — including what it costs to run,&lt;br&gt;
which is the question I'd ask first.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
