<?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: Brasth</title>
    <description>The latest articles on DEV Community by Brasth (@brasthapp).</description>
    <link>https://dev.to/brasthapp</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%2F4130776%2F9498fdc8-f215-4175-9e7c-c5bad2db8e04.png</url>
      <title>DEV Community: Brasth</title>
      <link>https://dev.to/brasthapp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brasthapp"/>
    <language>en</language>
    <item>
      <title>Your agent went green by weakening the tests</title>
      <dc:creator>Brasth</dc:creator>
      <pubDate>Mon, 21 Sep 2026 10:52:43 +0000</pubDate>
      <link>https://dev.to/brasthapp/your-agent-went-green-by-weakening-the-tests-1iha</link>
      <guid>https://dev.to/brasthapp/your-agent-went-green-by-weakening-the-tests-1iha</guid>
      <description>&lt;p&gt;I already wrote about babysitting coding agents: prompt, wait, almost right, exit 0, still will not merge.&lt;/p&gt;

&lt;p&gt;There is a nastier failure mode than a messy diff.&lt;/p&gt;

&lt;p&gt;The worker "fixes" the suite by editing the suite.&lt;/p&gt;

&lt;p&gt;Softens an assert. Deletes the case that hurt. Rewrites the expected value to match the bug. Process exits 0. The narrative says done. You open the PR and realize the contract moved under your feet.&lt;/p&gt;

&lt;p&gt;That is not a flaky CI story. That is acceptance theft.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjttrpydhp5gh8m0o31q8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjttrpydhp5gh8m0o31q8.png" alt="Acceptance theft before and parent-owned verify after" width="800" height="480"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Before: worker can move the bar. After: parent owns acceptance.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5enylypwnjxu0go9o8ln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5enylypwnjxu0go9o8ln.png" alt="Softened asserts diff" width="800" height="485"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;What acceptance theft looks like in the diff.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The objection that stuck
&lt;/h2&gt;

&lt;p&gt;On the earlier DEV post, &lt;a href="https://dev.to/reidmarlow"&gt;Reid Marlow&lt;/a&gt; put the tripwire cleanly: workers love modifying test files to make the run green, and separating test-file diffs from source diffs is how you catch it.&lt;/p&gt;

&lt;p&gt;He is right. A noisy context window wastes tokens. Green-by-softening-asserts wastes trust. Once a worker can satisfy the check by changing the check, "tests passed" stops meaning what you think it means.&lt;/p&gt;

&lt;p&gt;I care about that failure more than parallel agents stepping on the same file. File collisions are loud. Weakened asserts are quiet. Quiet is how bad merges ship.&lt;/p&gt;
&lt;h2&gt;
  
  
  Exit 0 was never acceptance
&lt;/h2&gt;

&lt;p&gt;In a single-agent thread you can still notice. You own the terminal. You see &lt;code&gt;tests/&lt;/code&gt; light up in the diff. You can refuse.&lt;/p&gt;

&lt;p&gt;Once you hand work to a worker (subagent, second CLI, MCP job, whatever), the temptation grows: the child is scored on "make it green," not on "keep the contract honest." If test paths are writable and acceptance is the child's exit code, you taught it the wrong objective.&lt;/p&gt;

&lt;p&gt;So the product question is not "did the worker finish?" It is "who owns the bar, and can the worker move the bar?"&lt;/p&gt;
&lt;h2&gt;
  
  
  What Rig does about it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Brasth/Rig" rel="noopener noreferrer"&gt;Rig&lt;/a&gt; is not another coding agent. It is the harness between ones you already use.&lt;/p&gt;

&lt;p&gt;Spine, short version:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parent scopes files.&lt;/strong&gt; Owned paths, not "edit whatever looks related."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parent writes a brief.&lt;/strong&gt; Change / don't-change / acceptance. The worker runs that brief over MCP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parent verifies.&lt;/strong&gt; Real checks against the brief. Exit 0 is execution. Verified is acceptance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the weakened-tests case, that spine has concrete teeth:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parent owns acceptance.&lt;/strong&gt; The worker does not get to mark the job verified. The parent does, after its own checks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tests can be read-only / out of scope in the brief.&lt;/strong&gt; If the job is "implement X," keep &lt;code&gt;tests/&lt;/code&gt; (or the contract files you care about) out of the writable set. Softening asserts then becomes a scope violation, not a clever pass.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F90nojrj6smqdl5vw4m8v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F90nojrj6smqdl5vw4m8v.png" alt="Real Rig brief shape" width="800" height="689"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Real Rig brief shape: scoped files, tests read-only, parent-owned acceptance.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parent re-runs the real check set before accept.&lt;/strong&gt; Not the child's story of green. The parent's command, on the parent's terms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqp2agnzt9f8igl08m87l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqp2agnzt9f8igl08m87l.png" alt="Parent verify: real checks, then accepted" width="799" height="407"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Parent verify: real checks, then accepted.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scope violation shows up as dirty verify, not a silent pass.&lt;/strong&gt; If the worker touched paths it was not given, that is fail-closed for acceptance. You see it. You do not merge on vibes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reid's tripwire (split test diffs from source diffs) still matters as a human review habit. Rig's bet is to make that habit structural: the harness already knows which paths were in scope, and verify is not optional theater.&lt;/p&gt;

&lt;p&gt;MCP is just the handoff pipe here. The point of this post is not multi-job graphs. It is who owns the bar when one worker tries to move it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configure the harness, then type normally
&lt;/h2&gt;

&lt;p&gt;Prefer editing .rig/harness.toml over memorizing worker CLI commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;parent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"codex"&lt;/span&gt;

&lt;span class="nn"&gt;[workers]&lt;/span&gt;
&lt;span class="py"&gt;codex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;grok&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;claude&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;opencode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable only workers you actually have. Quit the parent once after install, open a new thread in the repo, and type a normal prompt. Everyday work is not &lt;code&gt;rig run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When the brief matters, be explicit: which paths may change, which paths are the contract, what command the parent will re-run. That is the difference between a worker that implements and a worker that negotiates the rubric.&lt;/p&gt;

&lt;h2&gt;
  
  
  Soft landing
&lt;/h2&gt;

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

&lt;p&gt;A screen recording of the broader babysitting harness lives elsewhere. This post is about acceptance theft, not that clip. Soft link only: clone it, try a scoped brief, and keep &lt;code&gt;tests/&lt;/code&gt; out of the writable set when the job is implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  If this is your scar
&lt;/h2&gt;

&lt;p&gt;Same models. Less glue. Free and open source.&lt;/p&gt;

&lt;p&gt;If a worker ever went green by editing the asserts, you already know why exit 0 is not enough. Rig is my attempt to keep the bar on the parent side.&lt;/p&gt;

&lt;p&gt;I am on X as &lt;a href="https://x.com/brasthapp" rel="noopener noreferrer"&gt;@brasthapp&lt;/a&gt; if you want to argue about scopes, verify, or MCP handoff.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
    <item>
      <title>I got tired of babysitting coding agents</title>
      <dc:creator>Brasth</dc:creator>
      <pubDate>Fri, 18 Sep 2026 04:20:40 +0000</pubDate>
      <link>https://dev.to/brasthapp/i-got-tired-of-babysitting-coding-agents-jen</link>
      <guid>https://dev.to/brasthapp/i-got-tired-of-babysitting-coding-agents-jen</guid>
      <description>&lt;p&gt;I love coding agents. I also got tired of being their night-shift project manager.&lt;/p&gt;

&lt;p&gt;The loop looks familiar:&lt;/p&gt;

&lt;p&gt;prompt → wait → almost right → correct → wait → open a second agent → they step on the same files → exit 0 → you still will not merge.&lt;/p&gt;

&lt;p&gt;That last part is the one that broke me. Process finished. Tests maybe green in the agent's story. Diff still not something I would put on &lt;code&gt;main&lt;/code&gt; without another human pass. I was paying twice: once for the models, again with my attention.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://github.com/Brasth/Rig" rel="noopener noreferrer"&gt;Rig&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not another coding agent
&lt;/h2&gt;

&lt;p&gt;Rig is not a chat box that "codes for you." It is the harness &lt;em&gt;between&lt;/em&gt; agents you already use.&lt;/p&gt;

&lt;p&gt;You keep talking to a &lt;strong&gt;parent&lt;/strong&gt; CLI (Codex, Grok, OpenCode, and friends). When the work is real (fix, implement, change code), the parent does not dump your messy thread into another model and pray. It turns intent into scoped work. A &lt;strong&gt;worker&lt;/strong&gt; runs that work over MCP. The parent then verifies with real checks. Done means verified, not exit 0 vibes.&lt;/p&gt;

&lt;p&gt;If one agent in one thread is enough for your life, you do not need this. Rig is for people who already bounce between tools, already try parallel work, and already got burned by "it said done."&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works (short version)
&lt;/h2&gt;

&lt;p&gt;The spine is boring on purpose:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parent scopes files.&lt;/strong&gt; Owned paths, not "edit whatever looks related."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parent writes a brief.&lt;/strong&gt; Change / don't-change / acceptance. The child works from that brief only. Your parent chat is not forwarded as the child prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Worker runs over MCP.&lt;/strong&gt; Handoff is tool calls and job state, not copy/paste between terminals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parent verifies.&lt;/strong&gt; Requirements, checks, accept. Exit 0 is execution. Verified is acceptance against what you asked for.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last step is the product. I do not want another agent that feels finished. I want a control plane that refuses to call it done until checks pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adaptive workflows (default)
&lt;/h3&gt;

&lt;p&gt;New default behavior: when the work should split, the parent owns a &lt;strong&gt;DAG of disjoint workers&lt;/strong&gt;. Parallel only when file (and resource) scopes do not overlap. Children never spawn children. The parent advances the graph, handles ASK/allow/deny, and alone marks the workflow verified after its own checks.&lt;/p&gt;

&lt;p&gt;So parallelism stays under the parent instead of a pile of nested agents inventing more agents. You can still run single-job mode if you want; adaptive is the default in &lt;code&gt;.rig/harness.toml&lt;/code&gt; under &lt;code&gt;[orchestration]&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch it once
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Failing taskboard&lt;/li&gt;
&lt;li&gt;Codex parent&lt;/li&gt;
&lt;li&gt;Rig TUI&lt;/li&gt;
&lt;li&gt;Grok worker over MCP&lt;/li&gt;
&lt;li&gt;Parent verifies&lt;/li&gt;
&lt;li&gt;Tests green&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Demo: &lt;a href="https://youtu.be/KuhHMH--oGk" rel="noopener noreferrer"&gt;https://youtu.be/KuhHMH--oGk&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/KuhHMH--oGk" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Quickstart (edit the harness, then type normally)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/Brasth/Rig/main/install.sh | bash
&lt;span class="nb"&gt;cd &lt;/span&gt;your-repo
rig init
rig doctor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prefer configuring parent and workers in &lt;code&gt;.rig/harness.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;parent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"codex"&lt;/span&gt;

&lt;span class="nn"&gt;[workers]&lt;/span&gt;
&lt;span class="py"&gt;codex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;grok&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;claude&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;opencode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;omp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;pi&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;agy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;devin&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="nn"&gt;[orchestration]&lt;/span&gt;
&lt;span class="py"&gt;mode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"adaptive"&lt;/span&gt;
&lt;span class="py"&gt;max_nodes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable only workers you actually have installed. Fully quit the parent once after install, open a new thread in that repo, and type a normal prompt (for example: &lt;code&gt;Fix the failing tests in tests/test_cli.py&lt;/code&gt;). Do not use &lt;code&gt;rig run&lt;/code&gt; for everyday work.&lt;/p&gt;

&lt;p&gt;Questions stay on the parent. Side ideas can park in the queue without derailing a live job. Jobs and file ownership live under &lt;code&gt;.rig/&lt;/code&gt; in the repo, not in a chat you already lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  If the pain matches
&lt;/h2&gt;

&lt;p&gt;I built Rig because I was tired of babysitting. Same models. Less glue.&lt;/p&gt;

&lt;p&gt;Free and open source: &lt;a href="https://github.com/Brasth/Rig" rel="noopener noreferrer"&gt;https://github.com/Brasth/Rig&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Demo again if you want the one-minute version: &lt;a href="https://youtu.be/KuhHMH--oGk" rel="noopener noreferrer"&gt;https://youtu.be/KuhHMH--oGk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am on X as &lt;a href="https://x.com/brasthapp" rel="noopener noreferrer"&gt;@brasthapp&lt;/a&gt; if you want to yell at the founder about MCP or verification.&lt;/p&gt;

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