<?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: Daniel Firu</title>
    <description>The latest articles on DEV Community by Daniel Firu (@daniel_firu).</description>
    <link>https://dev.to/daniel_firu</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%2F4118922%2Ff0090b77-e373-4917-9065-32e2fdeb8063.jpg</url>
      <title>DEV Community: Daniel Firu</title>
      <link>https://dev.to/daniel_firu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/daniel_firu"/>
    <language>en</language>
    <item>
      <title>Why I stopped babysitting coding agents</title>
      <dc:creator>Daniel Firu</dc:creator>
      <pubDate>Thu, 10 Sep 2026 09:55:17 +0000</pubDate>
      <link>https://dev.to/daniel_firu/why-i-stopped-babysitting-coding-agents-54pf</link>
      <guid>https://dev.to/daniel_firu/why-i-stopped-babysitting-coding-agents-54pf</guid>
      <description>&lt;p&gt;&lt;em&gt;How a solo port turned into an autonomous pipeline, and what changed when the agents started reviewing each other.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;For most of the last year I have been building the same product twice. Expause is a video social app. The mobile app is Flutter, and it came first. In October 2025 I started a React web version that has to match it feature for feature. Same behaviour, same rules, same edge cases. There is one of me.&lt;/p&gt;

&lt;p&gt;That sounds like a job for a coding agent, and it was. Every web feature already has a working reference implementation in Dart. You point the agent at the Flutter screen, describe what "the same" means on the web, and let it type. For the first few months that is exactly what I did, and it was faster than doing it by hand. It was also the most tiring way I have ever written software.&lt;/p&gt;

&lt;h2&gt;
  
  
  The babysitting tax
&lt;/h2&gt;

&lt;p&gt;Here is what a day looked like. Open a session. Explain the architecture, again, because the last session is gone. Paste in the conventions. Ask for the feature. Watch it write. Approve a file. Notice it put business logic in a UI hook. Say so. Approve. Notice it skipped the unit test the conventions require. Say so. Notice it invented a constant that already exists under another name. Say so. Approve. Read the diff once more, because by now I no longer trust that I caught everything, and I know that I did not.&lt;/p&gt;

&lt;p&gt;None of those steps is hard. That is the problem. It is a stream of tiny judgements, none of them worth a coffee break, all of them required, and the stream never stops as long as the agent is typing. You cannot leave, because an unwatched agent drifts. You cannot really think either, because the interruptions come every minute. I was faster than before, I ended every day drained, and the code was not even that good. An agent that is being watched optimises for the watcher. It writes whatever makes me say "fine, next" in real time, which is not the same as what survives a proper review a week later.&lt;/p&gt;

&lt;p&gt;Somewhere around spring I admitted that the bottleneck in my project was me, sitting next to a machine, being the review process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the rules down first
&lt;/h2&gt;

&lt;p&gt;The first thing I built was not autonomy. It was boring. I wrote the rules down. One always-loaded project file with the things every agent must know, and one conventions document per layer of the app: how data access works, how the domain layer is shaped, how pages and hooks split their responsibilities. Every rule I had been repeating out loud went into a file instead.&lt;/p&gt;

&lt;p&gt;Then I stopped using one agent for everything. The work got split into narrow roles: a planner that turns a request into small, single-layer tasks; an implementer per layer that reads only its own task and its own layer's conventions; a committer that does nothing but tick the task off and commit. Each one starts with a fresh context and a tool allowlist that matches its job. That alone removed half the re-explaining, because nobody had to remember anything across a long session. Whatever an agent needed to know was in the file it was told to read.&lt;/p&gt;

&lt;p&gt;I was still pressing go on every task at this point. It was better. But I was still the reviewer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The moment reviews changed the code
&lt;/h2&gt;

&lt;p&gt;The change that made this a different kind of tool was adding reviewers that are not me.&lt;/p&gt;

&lt;p&gt;A reviewer agent reads the finished diff against the plan and the conventions and writes its findings to a file. The part that mattered was a decision about tools rather than prompts: reviewers cannot edit. A reviewer that could fix what it found would quietly fix it and say nothing, and I would learn nothing. A reviewer that can only write a finding has to make its case.&lt;/p&gt;

&lt;p&gt;The first reports came back with things I would have missed, or things I would have been too tired to look for by the tenth file. A component over the size ceiling. A hook that had quietly grown a fifth responsibility. A value copied from mobile that ignored a shared constant the web already had. So I kept adding review angles. One reviewer checks parity with the mobile app, payload for payload and threshold for threshold. One checks that every file landed in the right layer. One reviews the whole branch. The bigger reports get a meta-review before anything is fixed, because reviewers make things up too.&lt;/p&gt;

&lt;p&gt;Then I did something I should have done from the start: I measured whether each reviewer earned its cost. The per-task reviewers, the ones that checked every unit right after it was written, turned out to be almost entirely redundant with the end-of-branch reviews, so they were dropped. What the same measurement showed was a class of defect nobody caught. The port had faithfully reproduced bugs from the mobile app, because every reviewer treated the reference implementation as the truth.&lt;/p&gt;

&lt;p&gt;So the last reviewer added was the skeptic. Its premise is that the plan, the implementation and the reference implementation can all be wrong, and its job is to report only what the other reviewers did not. On one of its first branches it found that the mobile app never reset an "upload in progress" flag on the failure path, which the web port had copied exactly, so one failed upload would have locked the button for good. Both clients got fixed. That is when I stopped thinking of the reviews as a safety net and started thinking of them as the reason the output was good.&lt;/p&gt;

&lt;p&gt;And this is the thing I did not expect: the code got better before the reviews ran, not only after. An implementer that will have to pass a parity reviewer, an architecture reviewer and a skeptic writes differently from one trying to satisfy a tired human in real time. The quality jump came from the agents having to convince each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Walking away
&lt;/h2&gt;

&lt;p&gt;Once the reviews were trustworthy, letting the whole thing run without me was mostly plumbing. A small daemon watches a folder. A task prompt dropped there gets its own branch and its own git worktree, and a headless session runs the entire flow: plan, review the plan until it converges, implement task by task, run every review gate, fix every finding, test the feature in a real browser through a tester agent that can drive one and nothing else, update the docs, push the branch. I get a notification.&lt;/p&gt;

&lt;p&gt;It did not work the first time, or the tenth. Runs got stuck, the API had bad days, a resume regenerated work it had already done. Each of those became a rule or a mechanism, and today a run that has to stop writes down where it was and continues from there later. That reliability story deserves its own article, and it will get one. For now the point is simpler: every wrong turn is a line in a file that the next run reads.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stayed human
&lt;/h2&gt;

&lt;p&gt;I still test every feature by hand. This is the part I have no interest in automating.&lt;/p&gt;

&lt;p&gt;When a branch comes back, I use it the way I would use a colleague's branch. I open the app, click through the feature, try the edge cases, look at it on a phone. Then I write down what I found, in plain language, and drop that file where the task prompt went. A fix cycle starts: an agent verifies each observation against the code and plans the fixes, the same review gates grade that plan, the fixes are implemented, the browser tests are extended with one regression test per finding, and I get another notification.&lt;/p&gt;

&lt;p&gt;The last step of that cycle is my favourite part of the whole system. Every finding from my hands-on review that got past all the automated gates is distilled into a one-line rule in a lessons ledger, and every planner and every reviewer reads that ledger before it starts. The rules are boring and specific. Privileged data must be gated on the server, not only in the client. Reuse the shared constant even when the mobile app hand-rolls its own. Mutate optimistically before the await, the way mobile does. The first of those got past the pipeline three times on three different branches, caught by hand each time, before it became a line in the file. It has not come back since.&lt;/p&gt;

&lt;p&gt;So the human review is not a fallback for when the pipeline fails. It is the training signal. Every branch I review by hand makes the next one slightly harder to get wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a day looks like now
&lt;/h2&gt;

&lt;p&gt;I open an ordinary session in the repository and type what I want, the same way I did a year ago. "Add the block-user action to the chat header, same conditions as mobile." The difference is what happens next. The session asks how I want it handled: run it autonomously, do it here, talk it through first, or stop asking. I pick the first, it proposes a branch name, I confirm, and that is the end of my involvement in the implementation.&lt;/p&gt;

&lt;p&gt;Then I go do something else. Work on the mobile app. Think about the product. Have lunch. At some point a notification says the branch is ready. I review it, write what I found, drop it, and get another notification when the fixes are in. Then I merge.&lt;/p&gt;

&lt;p&gt;It is not flashy. Nothing about it looks like the demos. It is a folder, a daemon, a set of agents with narrow jobs and narrow tools, and a stack of files that say what each of them saw. The feeling is closer to having a careful team that works while I am away than to having a fast typist that needs me in the room. The babysitting tax is gone, and the code that comes back is better than the code I used to approve file by file.&lt;/p&gt;

&lt;h2&gt;
  
  
  It is open source
&lt;/h2&gt;

&lt;p&gt;The whole thing is published as a Claude Code plugin plus a small command-line tool that wires it into a repository: &lt;a href="https://github.com/firu-daniel/autonomous-sdlc-harness" rel="noopener noreferrer"&gt;github.com/firu-daniel/autonomous-sdlc-harness&lt;/a&gt;, Apache-2.0. The plugin carries the agents, the commands and the review flow. The CLI generates the permission profile, the scripts and the daemon, which are the parts nobody should have to get right by trial and error twice.&lt;/p&gt;

&lt;p&gt;The next article is the shape of it in plain words: what a run does from the moment you ask until the branch is pushed, with one diagram and no scorecards. After that, short pieces on the parts I think are interesting on their own: planning, the reviewers, the lessons flow, and how the pipeline files bugs against itself without being allowed to fix them.&lt;/p&gt;

&lt;p&gt;If you have been sitting next to an agent all day wondering whether this is what it is supposed to feel like, it is not. It gets boring, in the good way.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Daniel Firu builds and operates an autonomous software-delivery harness for Expause, a Flutter and React product.&lt;/em&gt;&lt;/p&gt;

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