<?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: Jeel Vankhede</title>
    <description>The latest articles on DEV Community by Jeel Vankhede (@jeelvankhede).</description>
    <link>https://dev.to/jeelvankhede</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%2F1050284%2F6055714a-b46c-4a13-b353-b6c807eba6ff.jpeg</url>
      <title>DEV Community: Jeel Vankhede</title>
      <link>https://dev.to/jeelvankhede</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jeelvankhede"/>
    <language>en</language>
    <item>
      <title>Adding Edges Is Not a Paradigm Shift</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Mon, 17 Aug 2026 19:12:18 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/adding-edges-is-not-a-paradigm-shift-5135</link>
      <guid>https://dev.to/jeelvankhede/adding-edges-is-not-a-paradigm-shift-5135</guid>
      <description>&lt;p&gt;I read the post, agreed with it, and opened my repo to plan the migration.&lt;/p&gt;

&lt;p&gt;Then I could not find the loop I was supposed to be replacing.&lt;/p&gt;

&lt;p&gt;The repo is agentsmyth, a seven-step agent chain I have been building for months. What I found was a fixed sequence with a checkpoint between every step and exactly one edge leaving every node. There was no loop to tear out and no obvious place to put a graph. I spent an evening trying to work out what I had misunderstood, and eventually went back to read the original post properly.&lt;/p&gt;

&lt;p&gt;It was a joke.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Joke Was the Point
&lt;/h2&gt;

&lt;p&gt;Here is the sequence, because that sequence is the story.&lt;/p&gt;

&lt;p&gt;At 00:34 UTC on July 18, 2026, Peter Steinberger, the creator of OpenClaw, posted twelve words: "Are we still talking loops or did we shift to graphs yet?" No definition. No design principles. One line.&lt;/p&gt;

&lt;p&gt;About four and a half hours later, Hamel Husain published a piece declaring loop engineering dead. The next day the slogan was repeated, and a replacement narrative was moving before the replacement had a stable meaning. Within weeks there were guides, comparison tables, and a discipline with a name.&lt;/p&gt;

&lt;p&gt;Steinberger was not proposing a discipline. He was needling the field for how fast it renames things. Prompt engineering had become context engineering, which had become harness engineering, which had become loop engineering, and the underlying work had not changed nearly as much as the vocabulary had. He later posted a diagram of a two-state machine, looping and done, with a caption that left nothing to interpret:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This is the silly thing you all hyped for weeks."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The joke was the point, and the field wrote explainers about the punchline.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Harrison Chase, who created LangGraph, which is the system nearly every one of those explainers pointed to as the destination, responded to the wave by saying he did not know what graph engineering was and still did not, but that it was basically just LangGraph.&lt;/p&gt;

&lt;p&gt;Four days after that, he and Sydney Runkle published the piece that should have ended it. Three years of building graph agent systems, laid out plainly. Their position is not that graphs are overrated. It is that this was never a migration. Production agents need cycles, because they retry failed calls, ask for missing information, correct themselves after validation and pause for human input. A loop is a directed cyclic graph, a point they credit to David Khourshid. Loop engineering is not the alternative to graph engineering. It is the simple case of it.&lt;/p&gt;

&lt;p&gt;The LangChain framework itself runs on top of LangGraph, which means the migration a lot of people were planning had already happened underneath them, three years ago, without a name.&lt;/p&gt;

&lt;p&gt;The prior art runs deeper still. Anthropic documented prompt chaining, routing, parallelization, orchestrator-worker and evaluator-optimizer patterns back in 2024, with the recommendation to add complexity only when something demands it. LangGraph, AutoGen and Google ADK all shipped graph workflows before the word trended.&lt;/p&gt;

&lt;p&gt;So there was no paradigm to shift to. My chain is a graph. It always was one, with a single edge leaving every node.&lt;/p&gt;

&lt;p&gt;One more detail, and it is the one that stayed with me. The explainers cannot agree on how long the tweet was. One says six words. Another says nine. It is twelve. View counts range from 575,000 to 2.9 million depending on who is telling you. Dozens of articles were written about a single sentence, and a measurable share of them did not count the words in it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nobody checked the tweet.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is the thing I actually want to be careful about. Not that the term is empty, because underneath it there is a real design problem about how multiple loops connect. But that a field can produce a month of confident writing on top of a line nobody read closely, and I was four paragraphs into planning a migration before I noticed I was one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  An Edge You Did Not Need Is a Checkpoint You Gave Away
&lt;/h2&gt;

&lt;p&gt;That leaves the question worth asking, which is smaller and harder than the one I started with. Not whether to adopt graphs. What each additional edge is going to cost me.&lt;/p&gt;

&lt;p&gt;Here is the shape of what I built. A fixed sequence of seven steps, running from specification through planning, implementation, review, testing and release. One agent chain. A checkpoint between every step, where each step reads the written output of the one before it rather than the conversation. One human reviewer, which is me, standing at every checkpoint.&lt;/p&gt;

&lt;p&gt;Now put a bad spec into it. Not a broken one. A spec that is coherent, confident, and pointed slightly wrong, which is the only kind that survives long enough to hurt.&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%2Flfhsvebef913x2a3ie8q.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%2Flfhsvebef913x2a3ie8q.png" alt="Two flows compared. The chain is the real seven-step sequence, with a bad spec entering at the first step and a checkpoint immediately after it, costing one step if caught. The graph splits the same spec across three nodes with no checkpoint between split and convergence, so the error only surfaces at the end." width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the chain, that spec meets a checkpoint before anything is built. If I catch it, the cost is one step's work. If I miss it, it moves exactly one step, and there is another checkpoint waiting.&lt;/p&gt;

&lt;p&gt;Add edges and the same spec splits three ways. Three nodes build on it in parallel, each one confidently, each one correct with respect to the thing it was handed. The error does not surface at a checkpoint, because the spec already passed the only checkpoint it was going to meet. It surfaces at convergence, when the branches come back and do not fit each other.&lt;/p&gt;

&lt;p&gt;By then the work exists. &lt;em&gt;All of it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is an obvious objection here, and it is correct.&lt;/p&gt;

&lt;p&gt;Nothing about a graph forbids checkpoints. LangGraph ships interrupts for exactly this, and human-in-the-loop pausing is a documented feature rather than an afterthought. You can gate every node in a branching system if you decide to, and serious teams do.&lt;/p&gt;

&lt;p&gt;So the claim is narrower than my diagram makes it look. A chain has one place to stand. A graph has as many places as it has branches, and every one of them has to be specified, staffed and waited on. Gating is not free in either shape. It is just cheap enough in a chain that I had stopped noticing I was paying for it.&lt;/p&gt;

&lt;p&gt;What I keep finding in the posts recommending the move is edges being added and checkpoints not being. The topology gets the diagram. The gating gets left as an exercise.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every branch that runs unattended is a checkpoint I chose not to stand at.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have hit this failure before, at chain scale, and it was mine. Last year I handed an agent a global event mechanism across a React Native app. I wrote the plan, reviewed it, approved it. The agent implemented the approved plan correctly, and the app broke in places the plan had quietly skipped: passive components sitting outside the event scope, and a duplicate event firing that I only found by adding console logs to trace the flow.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Three days of fixing.&lt;/em&gt; The result landed around seventy to seventy-five percent aligned with what I had actually asked for.&lt;/p&gt;

&lt;p&gt;That was one agent, one sequence, one plan. &lt;strong&gt;The failure was never capability.&lt;/strong&gt; The plan had a hole and nothing in the shape of the process was built to find it before the building started.&lt;/p&gt;

&lt;p&gt;The checkpoint was there. I was standing at it. It still went through.&lt;/p&gt;

&lt;p&gt;That is the part that decides this. A checkpoint I miss costs one step, and I found the hole in three days because there was only one path to trace back along. I do not need to imagine what the same missed spec costs with three branches running through it at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Condition I Have Not Met
&lt;/h2&gt;

&lt;p&gt;There is a clean version of when to add the edges, and it comes from people inside the discipline rather than from anyone selling the word. Add them when the path has to branch. When work has to route between multiple agents. When the run has to survive a human sitting in the middle of it.&lt;/p&gt;

&lt;p&gt;Against my system, nothing branches and there is one agent chain. The third one I arguably meet already, since I stop for a human at every step. Call it &lt;strong&gt;one for three&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I should be plain about the limit of my standing here. I have not built a multi-agent graph yet. This is an argument about whether I should, not a report from the other side of the decision. The people who have built them know things I do not &lt;em&gt;(And I know that few of them would claim that "Loop engineering is dead!" because they know everything around it)&lt;/em&gt;, and the LangChain writeup is the best evidence of that: their own team built early deep research on a predefined graph, then moved it toward a looser agentic loop, because the work would not sit still inside fixed nodes. They migrated away from a graph, on their own product, and said so publicly.&lt;/p&gt;

&lt;p&gt;Structure you have not earned costs you. That holds in both directions.&lt;/p&gt;

&lt;p&gt;So I am not adding graph support to agentsmyth. Not because graphs are hype, and not because the people building them are wrong. Because an edge is a complexity decision like any other. It pays back only when the work genuinely cannot be sequenced, and I have not brought it work that qualifies.&lt;/p&gt;

&lt;p&gt;Processes like this do not usually die from being wrong. They die from friction.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Every edge is a place the thing can catch.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What would flip it is specific, and I want to name it so I am held to it. A task where two parts genuinely cannot be sequenced, where waiting on the first is real waste and not just impatience, and where I can specify both halves well enough that they still fit when they come back. That third clause is the hard one. It is also the one nobody is talking about, because it is not a topology problem. It is the same specification problem, made harder by being cut in two.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The edges were never the interesting part. &lt;strong&gt;The spec was.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;The seven-step chain this article describes is&lt;/em&gt; &lt;a href="https://jeelvankhede.github.io/agentsmyth" rel="noopener noreferrer"&gt;&lt;em&gt;agentsmyth&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. Install with&lt;/em&gt; &lt;code&gt;npx agentsmyth init&lt;/code&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>I Built This to Fix One Task. It Turned Into Something You Can Run.</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Tue, 11 Aug 2026 18:28:06 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/i-built-this-to-fix-one-task-it-turned-into-something-you-can-run-3hn9</link>
      <guid>https://dev.to/jeelvankhede/i-built-this-to-fix-one-task-it-turned-into-something-you-can-run-3hn9</guid>
      <description>&lt;p&gt;There are two ways to work with an AI agent and I had tried both. Write the thing yourself and hand over only the tedious parts. Or hand over the whole task and audit whatever comes back at the end. The first is slow. The second is fast right up until it is wrong, and by then the wrong thing is finished.&lt;/p&gt;

&lt;p&gt;I expected this series to be about forcing a third option into existence. Nine parts of making an agent follow a workflow it would rather skip.&lt;/p&gt;

&lt;p&gt;That is not what happened. I never had to enforce it once.&lt;/p&gt;

&lt;p&gt;The queue that started this had a payload contract nobody had verified, and each phase after that cost me something before it gave anything back. A plan that would not move until the risk register named the provider contract the brief had only guessed at. A build that missed nothing except what my own brief left out. A review that stopped handing back a feeling and started handing back a verdict on every requirement I had already called done. A matrix instead of a trusted green run. A rollback with a name on it before anything got called shipped. And a retrospective that would not let a lesson through until it had checked itself against the trail.&lt;/p&gt;

&lt;p&gt;Eight parts of that. What I did not expect was which part turned out to be automatic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fight I Expected Never Started
&lt;/h2&gt;

&lt;p&gt;By the time I finish writing a requirement, I already know roughly what it is going to cost. Most engineers do. You can feel the difference between a one-line fix and something that is going to touch four files and a migration before you have written a single line of it.&lt;/p&gt;

&lt;p&gt;What I assumed was that the agent could not feel that, and that policing the gap would be my job forever. Reminding it to run the chain. Catching it when it decided a spike was small enough to skip.&lt;/p&gt;

&lt;p&gt;It has not needed the reminder. Small bugs do not trigger a brief and a plan, and they should not. A standard requirement, a spike, anything long or cross-cutting, runs the full cycle in order. The classification lands where I would have put it, without me putting it there.&lt;/p&gt;

&lt;p&gt;That is not the agent being clever. It is the one part of the system I have not shown you across eight parts: a short instruction file at the repo root that classifies every request before anything is touched, with the seven skill files sitting underneath it. Trivial work gets handled inline. Standard or complex work runs the chain, each phase reading the previous artifact rather than the conversation.&lt;/p&gt;

&lt;p&gt;Underneath that sit the pieces that never earned their own article because they are plumbing, not phases: a slug that keeps every artifact for one item under a single name, a requirement manifest that separates what I actually said from what was inferred, an exit gate no artifact passes on its own say-so, and a waiver that leaves a paper trail even when skipping a phase was the right call.&lt;/p&gt;

&lt;p&gt;It is less machinery than it sounds like. It is mostly a rule about when the machinery applies.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Chain Gave Me Somewhere to Stand
&lt;/h2&gt;

&lt;p&gt;It took me most of the series to notice where I had ended up standing.&lt;/p&gt;

&lt;p&gt;Not at the keyboard writing every line. Not at the end of the process reading a finished diff and trying to reconstruct whether it matches something I described days ago. Somewhere in the middle, at the gates, watching each artifact land before the next phase reads it.&lt;/p&gt;

&lt;p&gt;That position did not exist in either of the two ways I had worked before. When I was writing everything, there was nothing to review because I was the one making the decisions as I went. When I was handing off whole tasks, the only place to stand was at the end, where every correction is expensive because the work is already finished.&lt;/p&gt;

&lt;p&gt;The chain put me somewhere in between and gave me something specific to do there. Approve the brief or send it back. Read the plan before the build starts. See a requirement come back partial and decide whether it holds up the work. Every one of those is small on its own. Together they are the difference between hoping the result lands on what I asked for and being able to watch it land, phase by phase, while there is still time to steer.&lt;/p&gt;

&lt;p&gt;That is the actual product of nine parts. Not a more obedient agent. A place for me to stand while it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  So Would I Run It Again
&lt;/h2&gt;

&lt;p&gt;Yes. The more useful question is what would make me stop.&lt;/p&gt;

&lt;p&gt;Processes like this rarely die from being wrong. They die from friction. You override the rule on a Tuesday because the thing in front of you is obviously fine, then again on Thursday, and inside two weeks it is something you describe in the past tense. I have watched that happen to checklists, to templates, to every convention a team agrees on in a meeting and quietly stops following.&lt;/p&gt;

&lt;p&gt;What keeps this one alive is that I have not had to argue with it. The rule makes the call, it makes it the way I would have, and the cost only lands on work that was always going to be expensive. None of that depends on me being disciplined on a bad day, which is the only kind of day that matters for a process surviving.&lt;/p&gt;

&lt;p&gt;If that changes, if I catch myself overriding the classification to get moving, then the answer changes with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Cannot Check Yet
&lt;/h2&gt;

&lt;p&gt;The agent and I agree about complexity. That is the part working best, and it is also the part I have the least evidence for.&lt;/p&gt;

&lt;p&gt;Agreement is comfortable. This series was built on not trusting comfortable. A review that always came back clean would have been suspicious by Part 5, and I do not have a way, right now, to tell the difference between a classification that is right and one that simply matches mine. If it were consistently wrong in the same direction I am wrong, the artifacts would look exactly like this.&lt;/p&gt;

&lt;p&gt;There is a second thing I cannot claim. Every phase here ran through one person, on one task, with nobody but me approving each handoff. Whether an artifact somebody else wrote carries the same weight is a real question and I do not have the answer.&lt;/p&gt;

&lt;p&gt;Neither of those makes the last eight parts less true. They are just the next two things to check, and this series is entirely about the difference between what you have checked and what you have assumed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Guide Is Not Mine to Keep
&lt;/h2&gt;

&lt;p&gt;I could have written one readme and asked you to trust that it works. Nine parts was the slower way to make the same claim and the only honest one, because you got to see where the weight paid for itself and where it did not instead of taking my word for it.&lt;/p&gt;

&lt;p&gt;Put it in a repo. Aim it at something with real risk in it, a contract nobody has verified, a change three other things depend on. Then find out where you end up standing.&lt;/p&gt;

&lt;p&gt;I already know where I did.&lt;/p&gt;

&lt;p&gt;What is in the gist is the compact version, small enough to read once and run this week. It is not everything I ended up building. The complete one, with the detail I had to leave out to keep nine parts readable, is &lt;a href="https://jeelvankhede.github.io/agentsmyth/" rel="noopener noreferrer"&gt;agentsmyth&lt;/a&gt;. That is where this goes next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the whole chain actually gave me:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;guide.md&lt;/code&gt; is not a skill your agent runs. It is the map of the seven skills that are, and the piece that decides when their full weight applies at all.&lt;/p&gt;

&lt;p&gt;It gives you the agent instruction file for your repo root, the classification rule that separates trivial work from standard and complex, the requirement manifest that keeps what you said apart from what was inferred, and the exit gate every artifact passes before the next phase can start.&lt;/p&gt;

&lt;p&gt;Point your agent at it alongside the seven skill files from the earlier parts. What it produces is not one artifact but the whole chain, brief through retrospective, each file written to survive a session restart because the agent reads files instead of remembering or inferring.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/JeelVankhede/23e18110987a795bd31e2cfa9bbdbff4" rel="noopener noreferrer"&gt;guide.md on GitHub Gist&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or try agentsmyth as a complete version of it.&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>developertools</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Anyone Can Build Software Now. We Tried That Already.</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Mon, 03 Aug 2026 15:49:58 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/anyone-can-build-software-now-we-tried-that-already-4o8h</link>
      <guid>https://dev.to/jeelvankhede/anyone-can-build-software-now-we-tried-that-already-4o8h</guid>
      <description>&lt;p&gt;Somewhere on your feed right now, someone is bragging about the app they built in a weekend, no engineering background, no team, just a prompt and a Saturday. The post always ends the same way. Look what I built without needing any of you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Anyone can build software now.&lt;/em&gt; That is the whole pitch, repeated in a hundred different captions this month alone.&lt;/p&gt;

&lt;p&gt;Here is what that post never shows you. The part where someone checks it.&lt;/p&gt;

&lt;p&gt;Not "does it run." Checks it. Someone who did not write it, looking for the version of it that fails, the input nobody thought to try, the assumption that was wrong in a way the builder was structurally the worst person to catch, because they were too close to their own idea to see the hole in it.&lt;/p&gt;

&lt;p&gt;That someone is not optional. It is the actual job.&lt;/p&gt;

&lt;p&gt;None of this is theoretical. A notification icon that, instead of opening a panel, closes the entire page and drops me back on an empty tab. A video call that disconnects mid sentence for no visible reason. A video that plays with the sound simply gone, until I restart it. I do not have a chart proving reliability across the industry is getting worse. What I have is a pattern I keep running into, on products built by some of the most resourced engineering organizations on earth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why software engineering has more than one person in the room
&lt;/h2&gt;

&lt;p&gt;A developer writes the code. A reviewer reads it before it merges. QA tries to break it on purpose. A manager decides if it is actually ready, or just finished. None of these roles exist because engineers do not trust themselves. They exist because a single person, however good, cannot see their own blind spots. That is not a flaw in the person. It is a fact about how blind spots work.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ten sets of eyes exist so that the eleventh mistake gets caught before a million people hit it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We have already watched what happens when that layer disappears, and we did not need AI to run the experiment. We ran it with the spreadsheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The spreadsheet already showed us the cost of skipping this
&lt;/h2&gt;

&lt;p&gt;In 2012, JPMorgan Chase lost 6.2 billion dollars in the London Whale trade. Investigators traced part of the failure to a risk model where a formula divided by the sum of two numbers instead of their average. Someone had copied and pasted the wrong range. Nobody caught it before the number went into a report that told the bank its risk was lower than it actually was.&lt;/p&gt;

&lt;p&gt;Raymond Panko, a University of Hawaii researcher who has spent decades studying exactly this failure, put it in nine words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Spreadsheet programs are not error-prone. People are error prone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;He is right, and he is making a narrower point than it sounds like. The tool did not cause the loss. &lt;strong&gt;The absence of anyone checking the tool did.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In 2010, Carmen Reinhart and Kenneth Rogoff published a paper arguing that growth slows sharply once public debt passes 90 percent of GDP. Governments cited it for years while deciding how hard to cut spending. In 2013, a graduate student trying to replicate the result found a formula that had quietly excluded five countries from the average. Corrected, growth in the high debt group went from negative 0.1 percent to positive 2.2 percent.&lt;/p&gt;

&lt;p&gt;That error sat unreviewed for three years, informing real policy, because nobody with the standing to check the underlying spreadsheet did, until a student did it for a class assignment.&lt;/p&gt;

&lt;p&gt;Neither of these was a skill problem. Both were a review problem. The tool made something that looked finished. Nobody treated "looks finished" as different from "is correct."&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI version of this is worse, because it can close the whole loop
&lt;/h2&gt;

&lt;p&gt;A spreadsheet could not review itself. It could not test itself, or decide it was done, or ship itself into production. A human still had to be the one who trusted it too much.&lt;/p&gt;

&lt;p&gt;AI coding tools are closing that gap. Not just writing the code, but reviewing it, testing it, and in some workflows, deciding it is ready, with no human required at any step. That is a different category of risk than "the code was written badly." It is the removal of the entire mechanism that would have caught JPMorgan's formula, or Reinhart and Rogoff's missing rows, before it cost anyone anything.&lt;/p&gt;

&lt;p&gt;I am not arguing AI should stay out of engineering. I use it every day, and it makes me faster at parts of the job that used to be slow for no good reason. The argument is narrower than that, and I think it is the only argument that actually holds up: &lt;strong&gt;AI has not proven it can review its own work the way a second, independent, motivated engineer does.&lt;/strong&gt; Not yet. It is getting better at an uncomfortable pace, and I would not bet against it eventually closing that gap. It has not closed it now, and treating the current state of the tools as if they already have is the reckless part, not using them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I build what I build
&lt;/h2&gt;

&lt;p&gt;This is the reason I built agentsmyth. Not another assistant that writes code faster. A contract the agent you already use agrees to follow: seven gates, Think, Plan, Build, Review, Test, Ship, Reflect, each one leaving a real artifact behind instead of reasoning that evaporates the moment a chat scrolls off screen. One command, &lt;code&gt;npx agentsmyth init&lt;/code&gt;, wires it into a repo. Skipped checks get recorded as risk, not hidden. Nothing ships on the strength of looking finished.&lt;/p&gt;

&lt;p&gt;Its own pitch is two words. &lt;em&gt;Forge, don't vibe.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I do not know if that is the full answer to the problem this piece describes. It is the piece of the problem I can actually put my hands on. If AI is going to keep closing more of the gap between an idea and a shipped feature, someone still has to decide where the edges of that gap are, and someone still has to check the work against them. I would rather build the scaffolding that forces that check to happen than write another post about how nobody needs it anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reliance itself is not the problem
&lt;/h2&gt;

&lt;p&gt;The completeness of it is.&lt;/p&gt;

&lt;p&gt;Until an AI system can review its own work the way a second engineer does, at two in the morning, with their own name on the outcome and nothing personal riding on being agreeable about it, the review layer does not get to be optional. That is not an argument for keeping developers employed out of sentiment. It is the argument for making sure the next six billion dollar mistake does not ship quietly, built fast, reviewed by no one, because everyone involved assumed the tool had already checked its own work.&lt;/p&gt;

&lt;p&gt;It had not. It still has not. Build with that in mind, and the weekend app stops being something to brag about and starts being something to be honest about.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwaredevelopment</category>
      <category>developer</category>
      <category>developertools</category>
    </item>
    <item>
      <title>Every Session Starts From Zero. I Kept Forgetting That.</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Wed, 29 Jul 2026 18:40:07 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/every-session-starts-from-zero-i-kept-forgetting-that-1gj6</link>
      <guid>https://dev.to/jeelvankhede/every-session-starts-from-zero-i-kept-forgetting-that-1gj6</guid>
      <description>&lt;p&gt;You correct someone once. Not perfectly, but they get it. Next time, they do not make the same mistake. That is not optimism. That is just how correction works, "with people".&lt;/p&gt;

&lt;p&gt;I worked with agents on that assumption for a long time before I even noticed I was doing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plan that never held
&lt;/h2&gt;

&lt;p&gt;Before I had a single written rule anywhere, I would open a new session and ask for a plan first. Resolve the edge cases before touching a line of code, I said. The agent would agree, in whatever way a chat window agrees, and go straight to implementation anyway.&lt;/p&gt;

&lt;p&gt;I corrected it. Same session, it adjusted. New session, next day, same repo, same everything except the chat history: straight to implementation again. Every single time!&lt;/p&gt;

&lt;p&gt;So I did what looked reasonable. I wrote the plan myself. I resolved the edge cases myself, the open questions, the gaps the agent skipped past on its way to code. '&lt;strong&gt;Tedious&lt;/strong&gt;' is the polite word for it. I was doing the one task I brought the agent in to do, and calling it collaboration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same recipe, again
&lt;/h2&gt;

&lt;p&gt;The second correction arrived the same way. Every repo had its own shape. A recipe, a standard, a way things were supposed to be built here and not there. I would explain it. Full session, good results, the agent following the standard like it understood the standard.&lt;/p&gt;

&lt;p&gt;New session. Same repo, sometimes the new repo. Explain it again. Word for word, close enough. It was not that the agent forgot how to code. It was that nothing from the last conversation traveled with it into this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nothing said in the chat survives it
&lt;/h2&gt;

&lt;p&gt;I kept treating this like a training problem. Say it clearer. Say it earlier. Say it with an example next time. None of that was wrong exactly. It was aimed at the wrong layer.&lt;/p&gt;

&lt;p&gt;The actual mistake was assuming correction compounds the way it does with a person. It does not. A person carries what you told them into the next conversation without being asked to. An agent starts the next session exactly where it started the first one. Zero. The correction I gave on Monday was real, useful, entirely gone by Thursday, because it never lived anywhere except the chat.&lt;/p&gt;

&lt;p&gt;That is the whole problem in one sentence. Nothing said in the chat survives the chat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Correction has to live somewhere
&lt;/h2&gt;

&lt;p&gt;Once I saw it that way, the fix stopped being about phrasing and started being about location. A correction that only lives in a message is a correction I will give again. A correction written into something the next session actually reads, before it does anything else, is a correction that holds.&lt;/p&gt;

&lt;p&gt;Every agent solves the memory problem the same generic way. A rules file, a skills folder, an instruction set read before the first token of code. Nothing unusual about that part. The cost shows up later, the day I switched tools. The rules that held for one agent stopped holding for the next, not because the recipe changed but because the folder, the syntax, and the format it expected were different every time. Portability was never free. It was just deferred to the day I changed agents.&lt;/p&gt;

&lt;p&gt;That is the reason &lt;a href="https://jeelvankhede.github.io/frontend-ai-starter-recipes/" rel="noopener noreferrer"&gt;FARE&lt;/a&gt; and &lt;a href="https://jeelvankhede.github.io/backend-ai-starter-recipes/" rel="noopener noreferrer"&gt;BARE&lt;/a&gt; exist. Not to make agents smarter. To move the recipe out of my memory and my typing and into a file the agent inherits instead of me repeating it. The plan-first habit, the edge case resolution, the coding standard: all of it moved off me and onto a file the next session actually opened.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap it did not close
&lt;/h2&gt;

&lt;p&gt;It solved the style layer. It did not solve the sequencing layer. Agents still skipped review, still shipped code no one had tested, because a rules file tells an agent how to write code, not when to stop and check its own work.&lt;/p&gt;

&lt;p&gt;That gap is what &lt;a href="https://jeelvankhede.github.io/agentsmyth/" rel="noopener noreferrer"&gt;agentsmyth&lt;/a&gt; is for. Not a smarter memory, not a better prompt. A record on disk that each phase has to leave behind, so the next session inherits the reasoning instead of guessing at it again.&lt;/p&gt;

&lt;p&gt;I do not correct agents the way I correct people anymore. People remember on their own. Agents remember only what got written down where the next session can find it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Every session starts from zero. I just stopped forgetting that.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>developer</category>
      <category>developertools</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>The Retro Used to Wait for a Calendar Invite. This One Did Not.</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Sun, 26 Jul 2026 19:20:17 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/the-retro-used-to-wait-for-a-calendar-invite-this-one-did-not-4e5l</link>
      <guid>https://dev.to/jeelvankhede/the-retro-used-to-wait-for-a-calendar-invite-this-one-did-not-4e5l</guid>
      <description>&lt;p&gt;Every sprint I have sat through ends with a retro. Gather in a room, say what went well, say what did not, write it on a board nobody reopens. Release day gets a postmortem too, eventually, when someone remembers to schedule it.&lt;/p&gt;

&lt;p&gt;This one ran itself, on the cycle that had just finished, no calendar invite required. I felt the instinct the moment Ship closed: tell someone what you learned, write it down before the feeling fades into a vague memory of a lesson. The deploy had gone out. Quiet. Nothing broke. The rollback trigger I had written sat there unused, exactly the way it was supposed to.&lt;/p&gt;

&lt;p&gt;This is Part 8 of The Contract. If you are new here: seven phases, a human approves every handoff, and Reflect is the last phase in that chain.&lt;/p&gt;

&lt;p&gt;I expected Reflect to be the reward lap. Read back what happened, name the lesson, move to the closing part. It is not that. It made me answer a harder question first, before it let me write a single lesson down: what do I actually know, and what do I just remember feeling.&lt;/p&gt;

&lt;h2&gt;
  
  
  I already knew what the lesson was
&lt;/h2&gt;

&lt;p&gt;Or so I thought.&lt;/p&gt;

&lt;p&gt;One requirement in the notification queue had caused friction through the entire chain. Review had marked it partial. Nothing had broken. The queue introduced a call order and timing the requirement never described. Test found a real bug hiding inside that same gap, a timing issue that only surfaced once the check actually ran. Ship carried a rollback trigger for it anyway, written down, never needed.&lt;/p&gt;

&lt;p&gt;By the time Reflect started, I had a conclusion ready. The risk register should have asked about ordering and timing from the start, not just field-level schema. Write that down, close the loop, move on to Part 9.&lt;/p&gt;

&lt;p&gt;Reflect stopped me before I finished the sentence.&lt;/p&gt;

&lt;h2&gt;
  
  
  A candidate is not a lesson yet
&lt;/h2&gt;

&lt;p&gt;The phase does not let you write a lesson directly into anything. It lets you propose one.&lt;/p&gt;

&lt;p&gt;Every candidate gets a tag: propose-only. Not filed as knowledge. Not folded into anything a future feature will read as settled. It sits in a raw file, apart from anything curated, until I come back and promote it on purpose.&lt;/p&gt;

&lt;p&gt;I wanted to skip that part. The conclusion felt obvious. I had lived the whole chain. I did not think I needed a waiting period to know what I had learned.&lt;/p&gt;

&lt;p&gt;But nothing would have caught me if the guess had been wrong. Once a lesson is curated, the next brief reads it as fact. A diff gets reviewed again. A test run gets rerun. A curated lesson does not.&lt;/p&gt;

&lt;p&gt;A lesson written the same day it happens is just a guess that got there first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading the whole chain back, not remembering it
&lt;/h2&gt;

&lt;p&gt;Reflect does not ask whether the feature works. Ship already answered that. It asks something none of the earlier phases had reason to ask. The whole contract has run once now, from the first brief to a deploy quiet enough to walk away from. What did the process actually cost, and what did it buy.&lt;/p&gt;

&lt;p&gt;Answering that meant reading the chain back in order, brief through ship, one requirement at a time. Checked against evidence, not memory. The notification queue requirement had a paper trail by now: partial in Review, failing then passing in Test, shipped with a rollback in Ship. Reflect's only job on that line was to confirm the trail actually said what I thought it said.&lt;/p&gt;

&lt;p&gt;It did, mostly. The trail also corrected me once. I remembered the rollback trigger as something Ship added late, a safety net bolted on right before the deploy. The trail showed otherwise. It traced back to Plan, to the same risk register that flagged the payload contract months earlier. Ship did not invent the trigger. Ship used what Plan had already written down.&lt;/p&gt;

&lt;p&gt;I had been giving Ship credit that belonged to Plan. A small correction, the kind memory makes on its own until something forces it to check.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the retrospective actually cost
&lt;/h2&gt;

&lt;p&gt;The cost was patience, mostly. Writing a follow-up with a named owner and an actual artifact title, instead of a vague note to revisit the risk register someday. Sitting with a candidate tagged propose-only instead of calling it settled the day I noticed it.&lt;/p&gt;

&lt;p&gt;What it bought was a retrospective I can trust the next time I open it, because it came from the trail, not from how the project felt in hindsight.&lt;/p&gt;

&lt;p&gt;Eight parts in, the reflex has not changed: replace the feeling with a claim I can point to. Reflect was just the last place that reflex was waiting for me. &lt;em&gt;Write down what you learned. You earned it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Not yet. Propose it first.&lt;/p&gt;

&lt;p&gt;One part is left. Closing will ask whether a contract this heavy is something I would run again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Reflect actually earns you:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Most retros produce a good feeling and a template. Neither one is evidence. This one does not let a lesson through until it has been checked against the trail, and that is the entire reason it belongs in your own workflow, not just mine.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;reflect&lt;/code&gt; skill reads the full artifact chain, brief through ship, and builds a coverage retrospective for every requirement still active. It records outcome from evidence rather than intent. It proposes at most three learning candidates, tagged propose-only. And it will not let a follow-up go out without a named owner and a suggested artifact title.&lt;/p&gt;

&lt;p&gt;Give it to your agent on a task that has already shipped. It will not let you call something a lesson before you have checked it, and it will not let a clean result talk you out of naming what did not go well.&lt;/p&gt;

&lt;p&gt;The retrospective it writes is proof the chain was actually read back, not just remembered fondly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/JeelVankhede/1bacb79d020c79e9524ad92b08140ec3" rel="noopener noreferrer"&gt;reflect.md on GitHub Gist&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>softwaredevelopment</category>
      <category>engineering</category>
      <category>developertools</category>
      <category>retrospective</category>
    </item>
    <item>
      <title>The Deploy Was Boring. That Was The Whole Point</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Thu, 16 Jul 2026 19:07:11 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/the-deploy-was-boring-that-was-the-whole-point-29if</link>
      <guid>https://dev.to/jeelvankhede/the-deploy-was-boring-that-was-the-whole-point-29if</guid>
      <description>&lt;p&gt;You know the ten minutes before a deployment. The finger near the button. A dashboard open in the next tab. That low hum of waiting for something to go wrong.&lt;/p&gt;

&lt;p&gt;I sat through those ten minutes more than I can count now! If you have been following this series then it was for the notification scheduler refactor this time. I had braced for them all week.&lt;/p&gt;

&lt;p&gt;Nothing happened.&lt;/p&gt;

&lt;p&gt;The change went out. The checks that needed to be green were green. The queue kept scheduling notifications. No alert fired. I stayed on the dashboard longer than I needed to, waiting for the problem I was sure was coming.&lt;/p&gt;

&lt;p&gt;There was no problem.&lt;/p&gt;

&lt;p&gt;That emptiness bothered me more than a failure would have. A failure I would have known what to do with. A deploy this quiet felt like I had skipped something.&lt;/p&gt;

&lt;p&gt;I had not skipped anything. What I did not understand yet was why it was quiet, and what that quiet was actually worth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ship does not ask whether it works
&lt;/h2&gt;

&lt;p&gt;By the time I reached the button, the question of whether the code worked was already closed. Test had closed it. The call-order change that Review had scored partial went into Test, came out with a real failure found under one timing condition, went back in fixed, and the evidence was recorded both times.&lt;/p&gt;

&lt;p&gt;Ship was not there to answer that question again.&lt;/p&gt;

&lt;p&gt;Which meant the tension I felt in those ten minutes was not about this deploy at all.&lt;/p&gt;

&lt;p&gt;I have felt it at most deploys I have run. I had always filed it under deploy risk. It was not deploy risk. It was unpaid work from the earlier phases, all coming due at once, in front of production.&lt;/p&gt;

&lt;p&gt;A deploy that makes you nervous is a carry forwarded question it should not be in the first place.&lt;/p&gt;

&lt;p&gt;This one was not carrying any.&lt;/p&gt;

&lt;p&gt;Boring was not luck. Boring was what the earlier phases had already paid for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The absence of an error is not evidence
&lt;/h2&gt;

&lt;p&gt;There was one requirement I would not let the quiet speak for.&lt;/p&gt;

&lt;p&gt;The external notification provider does not fail loudly. Send it a payload with the wrong shape and it does not throw. It accepts the request, drops the content in silence, and the only evidence arrives weeks later, when somebody notices the notifications that never came.&lt;/p&gt;

&lt;p&gt;So there I was, taking comfort in a silent dashboard. And silence was the same risk this whole contract had been circling since Plan, since the beginning.&lt;/p&gt;

&lt;p&gt;I could not tell the two apart. A clean deploy and a silently rejected payload look identical from where I was sitting.&lt;/p&gt;

&lt;p&gt;The absence of an error is not evidence.&lt;/p&gt;

&lt;p&gt;"It did not error" and "it worked" are the same sentence to a system that never errors either way.&lt;/p&gt;

&lt;p&gt;That requirement was not marked shipped because the deploy went quietly. It was marked shipped because Test had produced evidence behind it before I ever pressed the button. The quiet confirmed nothing. The evidence did.&lt;/p&gt;

&lt;p&gt;That is not a technicality. It is the line between a boring deploy and a deploy that looks boring which leaks later.&lt;/p&gt;

&lt;h2&gt;
  
  
  I wrote the rollback before I shipped, and then I did not need it
&lt;/h2&gt;

&lt;p&gt;Ship would not let me move without a rollback on record: a written trigger, a written action, a named owner. Not a vague sense that I could revert if things went bad.&lt;/p&gt;

&lt;p&gt;The trigger was the only part that took real thought, because it could not be "an error appears." This provider does not throw one. A trigger for a silent failure has to be something a person checks on purpose, not something that shows up on its own. Review and Test had already named the risk twice, so I was not hunting for a new one. I just wrote down that I would go looking for it. The action was a single revert of the dispatch change. The owner was me.&lt;/p&gt;

&lt;p&gt;Then the change went out, and I never touched any of it.&lt;/p&gt;

&lt;p&gt;From the outside, an unused rollback looks like wasted effort. It was not what kept me calm exactly, the dread was still sitting right there, but it gave the dread somewhere to go if it turned out to be right instead of leaving it to circle with nowhere to land.&lt;/p&gt;

&lt;p&gt;An undo you never use is not a cost. It is the reason you can stand still and watch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shipped is not a feeling
&lt;/h2&gt;

&lt;p&gt;Then the quiet started making its own argument.&lt;/p&gt;

&lt;p&gt;Nothing had failed. The checks were green. The queue was scheduling. Every instinct I had was pointing the same direction. This is done. Close the tab. Go do something else.&lt;/p&gt;

&lt;p&gt;That is the instinct I no longer trust.&lt;/p&gt;

&lt;p&gt;Ship will not record anything it cannot show. A pull request, a CI run, a release, a handoff to whoever is downstream, none of it counts without evidence behind it. And local state never counts on its own. Merged is not shipped. Green is not shipped.&lt;/p&gt;

&lt;p&gt;I have said "it is done" about work that was merged and never released. It did not feel like a lie when I said it. That is what makes it dangerous.&lt;/p&gt;

&lt;p&gt;Shipped is not a feeling. It is a claim, and a claim needs something standing behind it.&lt;/p&gt;

&lt;p&gt;The recommendation came back ship. Not because the deploy felt fine. Because every requirement had a state, every state had evidence, and the one way this could still go wrong had a trigger, an action, and my name on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What comes next
&lt;/h2&gt;

&lt;p&gt;Ship closes with an artifact. Not what I intended to ship. What the evidence supports. What actually went out, what was deferred, and what is still waiting on a human.&lt;/p&gt;

&lt;p&gt;That last category is the one that matters after the tab closes. A deferred item without an owner is just something the next person finds by accident.&lt;/p&gt;

&lt;p&gt;Reflect starts from that record. It does not ask whether the feature works, or whether it went out. Those are settled, and they are written down.&lt;/p&gt;

&lt;p&gt;It asks what the process itself cost and what it bought, now that the whole contract has run once, from the first brief to a deploy so quiet I had to talk myself out of walking away from it.&lt;/p&gt;

&lt;p&gt;That is the next part.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A key takeaway:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;ship.md&lt;/code&gt; is the skill running underneath all of this. It is what actually decided ship, not the quiet dashboard. It maps every live requirement to shipped, deferred, blocked, or waived with evidence behind each one, and it will not let a rollback trigger, action, or owner stay blank. It will not call something released, merged, or handed off without proof standing behind the claim.&lt;/p&gt;

&lt;p&gt;Give it to your agent on a task that already has an approved plan, a finished review, and a verify artifact behind it. It will not let a good feeling substitute for evidence.&lt;/p&gt;

&lt;p&gt;The artifact it writes down is what actually shipped, not what I meant to ship. That record is what Reflect reads first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/JeelVankhede/e2def6e38bb5290f1e1e2469fdcc5eca" rel="noopener noreferrer"&gt;ship.md on GitHub Gist&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>deployment</category>
      <category>devops</category>
      <category>softwareengineering</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>They Asked for My AI Rules. But I Could Not Just Hand Them Over.</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Mon, 13 Jul 2026 18:53:06 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/they-asked-for-my-ai-rules-but-i-could-not-just-hand-them-over-3lhb</link>
      <guid>https://dev.to/jeelvankhede/they-asked-for-my-ai-rules-but-i-could-not-just-hand-them-over-3lhb</guid>
      <description>&lt;p&gt;A team lead announces that the team will start using AI-assisted development. Everyone nods. Nobody asks what that actually means on Monday morning.&lt;/p&gt;

&lt;p&gt;Some times ago I was in that position. A project I was working on needed to start using AI-assisted development, and the team was new to it. Nobody had rules written down for an agent to follow. Nobody had skills defined for it to load. There was no shared idea of how this should work inside our specific repo. Someone had to go first. That someone was me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rules worked because I built them for one repo
&lt;/h2&gt;

&lt;p&gt;I spent time curating a set of rules and skills for that project. Not generic ones. I shaped them tightly around how that repo was actually structured, its conventions, its layout, the things a new engineer usually has to learn by asking around. I wanted an agent working inside that codebase to already know what a human teammate would have picked up in the first two weeks.&lt;/p&gt;

&lt;p&gt;I gave a demo. It landed well. Well enough that it got shared further across team, as something other teams could learn from.&lt;/p&gt;

&lt;p&gt;I gave the demo again. Same reaction. Then a few developers reached out for the actual rules and skills files.&lt;/p&gt;

&lt;p&gt;I said sure, and then I actually looked at what I would be handing them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem showed up the moment other people wanted in
&lt;/h2&gt;

&lt;p&gt;It was not copy-paste-able. The rules referenced folder names, module boundaries, and patterns specific to one repo. Handing them over as-is would have meant handing over advice that was wrong for their project, dressed up as a shortcut.&lt;/p&gt;

&lt;p&gt;So I told them to use it as a reference. Look at the structure, understand the reasoning, adapt it to your own repo.&lt;/p&gt;

&lt;p&gt;That is correct advice. I watched people nod at it and then quietly missing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  I was solving the wrong problem the whole time
&lt;/h2&gt;

&lt;p&gt;I had been thinking about this as a documentation problem. Write good rules, explain them well, let people copy the idea. What I actually had was a generation problem. The rules that worked were the ones rendered specifically for a stack, not the ones written generically and left for someone to translate.&lt;/p&gt;

&lt;p&gt;The thing that was supposed to spread across other teams did not land as expected. What reached them was a reference nobody had time to turn into anything real. That gap sat there whether I looked at it or not.&lt;/p&gt;

&lt;p&gt;What I wanted to build was not another generic harness. I wanted something that looked at a repo's actual stack and produced rules and skills that worked from day one, not rules that needed a translation step before they were useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nobody on a team agrees on one AI tool
&lt;/h2&gt;

&lt;p&gt;Once I sat with that problem, a second one showed up right behind it, and this one turned out to matter just as much.&lt;/p&gt;

&lt;p&gt;Every adoption plan I had seen quietly assumed one AI tool per team. In practice, that assumption breaks almost immediately. One engineer wants Cursor. Another has already built muscle memory in Claude Code. Someone else is testing Windsurf, or is stuck on Copilot because that is what the company licensed, or wants to try Antigravity because something new just came out.&lt;/p&gt;

&lt;p&gt;Nobody wants to be told which editor or which agent to use, and forcing a single choice on a team is its own kind of friction, separate from the rules problem entirely. An adoption effort that only works for one tool is not really team adoption. It is one person's adoption, dressed up as a rollout.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the tool had to actually do
&lt;/h2&gt;

&lt;p&gt;That is the shape the problem ended up taking. Not "write better rules." Generate rules and skills that are rendered for a specific stack, and make sure they work no matter which of the tools a given engineer has already chosen.&lt;/p&gt;

&lt;p&gt;That is what became &lt;strong&gt;FARE&lt;/strong&gt; and &lt;strong&gt;BARE&lt;/strong&gt;, frontend and backend AI starter recipes, published as npm CLI tools. Point either one at a project and it generates rules, skills, and workflow context shaped around that project's actual stack, with adapters for five tools out of the box: Cursor, Claude Code, Windsurf, Copilot, and Antigravity. The output is meant to be used immediately, not adapted first.&lt;/p&gt;

&lt;p&gt;The part worth being honest about is that this did not remove the original judgment call. Something still has to decide what "good rules for this stack" means because it's always well opinionated. The CLI just means that decision gets made once, by the tool, instead of once per engineer, per project, under deadline pressure, with wildly inconsistent results.&lt;/p&gt;

&lt;h2&gt;
  
  
  I did not build everything I wanted to
&lt;/h2&gt;

&lt;p&gt;The scope I first sketched out was larger than what shipped. There were ideas around deeper project-specific customization, additional integrations, and more automated context tracking that I dropped or pushed to later releases. Some of that was a reasonable v1 boundary. Some of it was me wanting to build the interesting version instead of the useful one, and catching myself doing it.&lt;/p&gt;

&lt;p&gt;Keeping it simple was not the easy default. It was a decision, and one I had to make more than once while writing it.&lt;/p&gt;

&lt;p&gt;I do not know yet whether this is the right shape for other teams' problems or just the right shape for the one I kept running into. If you try FARE or BARE on your own project, I would genuinely like to know where it holds up and where it does not.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Awaiting your feedback!&lt;br&gt;&lt;br&gt;
&lt;a href="https://jeelvankhede.github.io/frontend-ai-starter-recipes/" rel="noopener noreferrer"&gt;&lt;strong&gt;F&lt;/strong&gt;rontend &lt;strong&gt;A&lt;/strong&gt;i starter &lt;strong&gt;RE&lt;/strong&gt;cipes&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://jeelvankhede.github.io/backend-ai-starter-recipes/" rel="noopener noreferrer"&gt;&lt;strong&gt;B&lt;/strong&gt;ackend &lt;strong&gt;A&lt;/strong&gt;i starter &lt;strong&gt;RE&lt;/strong&gt;cipes&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>workflow</category>
      <category>npm</category>
      <category>cli</category>
      <category>aitools</category>
    </item>
    <item>
      <title>A Verdict Is Not Evidence. Test Is Where I Learned the Difference.</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Wed, 08 Jul 2026 18:28:04 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/a-verdict-is-not-evidence-test-is-where-i-learned-the-difference-5b96</link>
      <guid>https://dev.to/jeelvankhede/a-verdict-is-not-evidence-test-is-where-i-learned-the-difference-5b96</guid>
      <description>&lt;p&gt;The call-order change came back pass-with-risk. I read the recommendation, saw it had a name and a reason, and felt the task close.&lt;/p&gt;

&lt;p&gt;Then I looked at the row under it. How was this verified: not run.&lt;/p&gt;

&lt;p&gt;Nobody had run the queue. I had a label. I did not have proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is Part 6 of The Contract
&lt;/h2&gt;

&lt;p&gt;Think produced a brief. Plan produced a gate. Build executed inside it. Review scored every requirement against a verdict instead of an impression.&lt;/p&gt;

&lt;p&gt;Review reads the diff and the plan and decides whether one satisfies the other. It does not run the queue. It cannot. Its whole job is judgment about what the code should do.&lt;/p&gt;

&lt;p&gt;Test is where someone finally checks what the code actually does.&lt;/p&gt;

&lt;p&gt;I had been treating those two as the same step. They are not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test asks one question, and a verdict is not the answer
&lt;/h2&gt;

&lt;p&gt;For every active requirement, Test asks how it was verified. Command run, manual QA, or a comparison against known-good output. One of those three, or a written reason none of them ran.&lt;/p&gt;

&lt;p&gt;Not a recommendation. Not a risk level. Evidence.&lt;/p&gt;

&lt;p&gt;I built the matrix against the plan's requirements and filled in each row. Most had a command behind them. The call-order requirement had nothing. The cell read not run, and it sat directly below a pass-with-risk that already carried a name and a reason.&lt;/p&gt;

&lt;p&gt;That name had almost been enough for me. A named risk feels handled. It is not. It is a risk with a label on it, waiting for someone to actually look.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I ran the queue
&lt;/h2&gt;

&lt;p&gt;Three notifications, all with a real reason to fire within the same tick. The scheduler picked them up and ordered them by priority instead of arrival.&lt;/p&gt;

&lt;p&gt;Two landed in the sequence the requirement wanted. The third jumped ahead of a lower-priority notification that was still mid-processing.&lt;/p&gt;

&lt;p&gt;The change worked almost every time. Under one timing condition, it did not.&lt;/p&gt;

&lt;p&gt;That is the gap a verdict cannot see. Review had marked the requirement partial because the wording left the mechanism open. Running it found a real failure inside the mechanism the code had chosen. Same requirement, two different holes, and only one of them shows up when you execute.&lt;/p&gt;

&lt;p&gt;The absence of an error is not evidence. I had to run the thing to learn the error was there.&lt;/p&gt;

&lt;h2&gt;
  
  
  The skipped check looked exactly like the ones that passed
&lt;/h2&gt;

&lt;p&gt;Here is what unsettled me. If I had left that cell at not run, the matrix would have shown three green rows and one blank, and nothing about the blank would have raised its hand.&lt;/p&gt;

&lt;p&gt;A skipped check is a risk hiding in sheep's clothing. It sits in the same table as the passing rows, formatted the same, quiet the same. Nobody flags it, because it does not look like a gap. It looks like the others.&lt;/p&gt;

&lt;p&gt;Done and unverified render identically on the page. The only way to tell them apart is to do the check.&lt;/p&gt;

&lt;h2&gt;
  
  
  I almost deleted the failure after I fixed it
&lt;/h2&gt;

&lt;p&gt;I fixed the ordering. Reran the check. It passed under the same timing condition that had broken it a minute earlier.&lt;/p&gt;

&lt;p&gt;Then my hand went to the failure row to clear it. The bug was gone. Why keep a record of something that no longer happens?&lt;/p&gt;

&lt;p&gt;I stopped, because the record was the point.&lt;/p&gt;

&lt;p&gt;The matrix is not a snapshot of the final state. It is the evidence that the check ran at all. A row that only shows the passing rerun tells the next engineer nothing. A row that shows the failure, the fix, and the clean rerun tells them exactly where the edge was and how close the code came to crossing it.&lt;/p&gt;

&lt;p&gt;I kept both rows. Deleting a fixed failure is not tidying up. It is erasing the only proof that anyone ever ran the check.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Test actually gates
&lt;/h2&gt;

&lt;p&gt;Test does not gate on whether the code works. It gates on whether every requirement has evidence behind it. Command, manual QA, output comparison, or an explicit skip with a reason, a risk, and an owner.&lt;/p&gt;

&lt;p&gt;Not run is not a resting state. It resolves into evidence or into a named, owned risk, and until it does, the recommendation stays at hold.&lt;/p&gt;

&lt;p&gt;Mine resolved. The recommendation came back ship, not because the first run was clean, but because the one requirement with a crack in it now had proof under the words instead of just the words.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A key takeaway:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is not just a template for this article. It is the skill from the workflow I run after every review pass, before anything reaches Ship.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To summarise,&lt;/em&gt; &lt;code&gt;test&lt;/code&gt; &lt;em&gt;skill builds a verification matrix against every active requirement, runs configured commands where available, records manual QA and generated-output checks, and treats every skipped or not-run check as risk with a named owner rather than a silent pass. It writes a verify artifact that Ship can trust, and it will not let a recommendation past hold or hold-with-waiver until every row is accounted for.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Download it. Give it to your agent. Drop it into a task with an approved plan and a completed review. Watch it refuse to call something done until it can show you the evidence.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The verify artifact it produces is proof that Test ran inside the contract.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/JeelVankhede/e6a16d915bb8ecd6fdaf2a4d14697fa6" rel="noopener noreferrer"&gt;&lt;em&gt;test.md on GitHub Gist&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>codereview</category>
      <category>softwaredevelopment</category>
      <category>softwaretesting</category>
      <category>developertools</category>
    </item>
    <item>
      <title>We shipped faster. The debt did too.</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Sun, 05 Jul 2026 16:20:54 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/we-shipped-faster-the-debt-did-too-49a4</link>
      <guid>https://dev.to/jeelvankhede/we-shipped-faster-the-debt-did-too-49a4</guid>
      <description>&lt;p&gt;You open a file you have not touched in months and your first instinct is to read it like it belongs to someone else.&lt;/p&gt;

&lt;p&gt;Not because it is broken. Not because the tests are failing. Just because you do not immediately know where its edges are.&lt;/p&gt;

&lt;p&gt;You gotta believe me when I say I had that feeling recently, on a module I last touched roughly six months ago. The code ran. The logic held. But I had to re-read it like the way you re-read code you did not write: slowly, looking for the load-bearing pieces, rebuilding a picture of why it works before I could safely change it.&lt;/p&gt;

&lt;p&gt;I had written most of it. &lt;em&gt;"With help."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The AI agent had generated large sections. I had reviewed, adjusted, and approved the diffs. At the time, the pace felt like a genuine unlock. Six months later, the code felt like something from totally different era.&lt;/p&gt;

&lt;p&gt;That feeling has a name. I just do not usually expect it from a six month old code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The deferral deal was reasonable when debt was slow
&lt;/h2&gt;

&lt;p&gt;Every team I have worked on had a version of the same arrangement. Not written anywhere, just understood. Debt built up, someone said "we should clean that up" before a release or during a quiet sprint, and a few of us did.&lt;/p&gt;

&lt;p&gt;It worked because the debt built up at a pace we could outrun. I could hold that pace in my head. A feature took a week, maybe two, and "later" meant a real date I could picture, not a vague promise.&lt;/p&gt;

&lt;p&gt;That is what calibration actually is. Not a policy. Not a perfect system. A feel for how much debt a stretch of work adds, built from doing the work slow enough to notice.&lt;/p&gt;

&lt;p&gt;It only needs a name now because the pace it assumed is gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI changed the input rate. Nothing else did.
&lt;/h2&gt;

&lt;p&gt;The first time I generated a real feature with an agent, I was surprised by how much showed up in a short time. Not just the volume. The structure. It read like a focused week's work, done in a few hours.&lt;/p&gt;

&lt;p&gt;I reviewed it, tested the critical paths, and shipped it. What I did not reckon with was the ratio: a few hours of review against a few days of generation, not several days of review against several days of authorship.&lt;/p&gt;

&lt;p&gt;When I write slowly, I carry the context without trying to, I know the tradeoff I made and why, because I was the one standing in front of it. That is where ownership comes from. Not from reading the diff after.&lt;/p&gt;

&lt;p&gt;When the agent writes it, that pacing disappears. The output arrives complete, and my review catches the obvious errors. What it cannot do is hand me the memory of a tradeoff I was never inside long enough to make myself.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It shipped like something I authored. It arrived like something I inherited.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Six months later, nobody on the team fully "knows" that module. It is not broken. It is just so dense in a way pre-AI code of the same age rarely was.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six months now reads the way three years used to
&lt;/h2&gt;

&lt;p&gt;This is not about "code quality" in the obvious sense. What I got back was honestly better than I could ever write; well-structured, function names held, nothing looked like a warning sign. Bad code announces itself. This did not.&lt;/p&gt;

&lt;p&gt;I.e. The module was an integration with an external provider handling bank transactions. I followed their documentation closely. It started clean, one responsibility per file. Then requirements arrived faster than I could sit with any single one, and since most of it was AI-assisted, the smells piled up quietly under that pace. Six months in, when something broke, I could not find the reason by reading the code. The file no longer explained the behaviour it produced.&lt;/p&gt;

&lt;p&gt;I was not holding the quality bar as tightly as I should have either. But that is the point, right? The pace made it easy not to notice I had stopped.&lt;/p&gt;

&lt;p&gt;That kind of code used to take years to arrive at, turnover, drift, decisions made by people who had already left. I got there in six months. Not because I got worse at my job but because the code arrived faster than the ownership that comes with it.&lt;/p&gt;

&lt;p&gt;Heuristic I keep coming back to: generation rate went up, review depth did not, so the gap between what shipped and what I actually understand widens quietly, because the code still looks fine.&lt;/p&gt;

&lt;p&gt;That is the condition the old deferral deal was never built for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deferring to a later that does not arrive
&lt;/h2&gt;

&lt;p&gt;The deferral strategy breaks at a specific point: when the cleanup sprint needed is larger than the capacity available for it.&lt;/p&gt;

&lt;p&gt;That used to be a slow-moving threshold. A team could accrue meaningful debt over a year and still pay it down in a focused month. The math worked because the input rate and the cleanup rate were in the same range.&lt;/p&gt;

&lt;p&gt;I did not clock this until I tried to schedule the cleanup for that six-month-old module and realised the sprint I would need did not fit anywhere on the roadmap. Not because the team was slow. Because the scope had outgrown what a sprint was ever built to absorb.&lt;/p&gt;

&lt;p&gt;The comprehension side, the reading, the refactoring, the rebuilding of shared context, still runs at the pace I run at, because it is still my work to do. Nobody had documented why the decisions were made, so there was nothing to hand the agent that would have let it re-explain its own output. The understanding I needed had never been accumulated in the first place, and there was no shortcut back to it.&lt;/p&gt;

&lt;p&gt;Six months of AI-assisted development had carried the density of what used to take two or three years to build up. The cleanup scope I was staring at was not what "we will get to it later" had ever budgeted for.&lt;/p&gt;

&lt;p&gt;I do not think this is a failure on my part. The old calibration was reasonable. It was just built for a pace that no longer exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  I do not have the answer. I have a question.
&lt;/h2&gt;

&lt;p&gt;I am not sure what the new approach looks like.&lt;/p&gt;

&lt;p&gt;I have gone looking. I have not found a team, a process, or a tool that has solved this completely, not the seeing part and not the deciding part, two different seams. Nothing tells you which modules have quietly lost their owner, or where the gap between what shipped and what anyone actually understands has drifted past what a sprint can close. And even when you can see it, there is no established way to decide what happens next that does not require a refactor window nobody can schedule.&lt;/p&gt;

&lt;p&gt;I am working on an idea in this space. Pretty early to call it a solution. But before I shape it further, a question popped in my head: is the problem I am describing real for anyone, or just real for me?&lt;/p&gt;

&lt;p&gt;If you have felt this: is the harder problem that you cannot see how much AI-generated debt you are carrying, or that you can see it but have no system for what to do next?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I wanna know which one.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>technicaldebt</category>
      <category>softwareengineering</category>
      <category>developertools</category>
    </item>
    <item>
      <title>Every Requirement Gets a Verdict. I Had Been Reviewing Without One.</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Thu, 02 Jul 2026 18:15:19 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/every-requirement-gets-a-verdict-i-had-been-reviewing-without-one-5dgi</link>
      <guid>https://dev.to/jeelvankhede/every-requirement-gets-a-verdict-i-had-been-reviewing-without-one-5dgi</guid>
      <description>&lt;p&gt;You merge the PR. The build passes. The code does what you expected it to do. You move on.&lt;/p&gt;

&lt;p&gt;That is review for most engineers. A final read. A feeling that things looked right before the branch closed.&lt;/p&gt;

&lt;p&gt;I did it the same way for years.&lt;/p&gt;

&lt;p&gt;Three phases had already run before this one. Think had scoped the work, Plan had written the requirements, Build had shipped a diff that matched the plan exactly. I trusted that the chain held. I had never actually checked.&lt;/p&gt;

&lt;p&gt;Then I ran the Review phase, and checking turned out to mean something specific: not does this work, but does this requirement hold up, and what is my evidence.&lt;/p&gt;

&lt;p&gt;I went in expecting to approve it or send it back. The phase gave me three answers instead: covered, partial, missing. I found out what they meant one requirement at a time, starting with the one I almost got wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  I had been giving impressions, not verdicts
&lt;/h2&gt;

&lt;p&gt;The notification scheduler used a queue to manage dispatch. Every call to the external provider went through it. The provider was never exposed directly. The requirement said the provider must be notified. It was notified, exactly the way I had pictured it.&lt;/p&gt;

&lt;p&gt;I almost called it covered and moved to the next line.&lt;/p&gt;

&lt;p&gt;The Review phase stopped me there. But the requirement said &lt;em&gt;must be notified&lt;/em&gt;, not how. The queue had introduced a call order and a timing the requirement never anticipated. Nothing was broken. Something had changed shape, quietly, and nobody had written that shape down.&lt;/p&gt;

&lt;p&gt;I sat with that for longer than I expected to. Not because the code was wrong. Because I could not immediately tell you whether the change mattered.&lt;/p&gt;

&lt;p&gt;The same pass gave the shim from Plan a different verdict on the same page: covered. Mapped to the requirement it existed to satisfy, no gap between what was promised and what was in the diff.&lt;/p&gt;

&lt;p&gt;One requirement held exactly the shape it was given. The other had quietly grown a new one. Same review. Same pass. Two verdicts.&lt;/p&gt;

&lt;p&gt;Partial is not a softer word for broken. It is the verdict for &lt;em&gt;this much, no more, and here is exactly where it stops.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming the risk I almost skipped
&lt;/h2&gt;

&lt;p&gt;A partial verdict did not resolve on its own. It forced a recommendation I had never had to give before: pass, pass-with-risk, or hold. The two options I knew, approve or send back, had no room for the case that actually mattered, the one where the code worked and the requirement was still uncertain.&lt;/p&gt;

&lt;p&gt;I had to decide, in writing, whether the queue change mattered enough to hold the work. It did not feel small in the moment. The provider was being reached. The queue was deliberate architecture, not an accident I had stumbled into. But I could not confirm the call order and timing from the diff alone, and pretending I could would have been the same thing I used to do without a name for it.&lt;/p&gt;

&lt;p&gt;I wrote it down as pass-with-risk. Not because the risk had gone away. Because I had looked at it directly instead of letting it pass quietly, the way every requirement before this phase had been allowed to.&lt;/p&gt;

&lt;p&gt;Pass-with-risk is handing off the baton with the crack already named.&lt;/p&gt;

&lt;h2&gt;
  
  
  The contract was not three phases
&lt;/h2&gt;

&lt;p&gt;Review is the first phase that looks backward and forward at the same time. Backward at everything Think, Plan, and Build produced. Forward at what Test will have to verify because Review could not finish the job alone.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Looks good to me"&lt;/em&gt; was never a verdict. It was an impression wearing a verdict's clothes, and I had been handing those out for years without noticing the difference.&lt;/p&gt;

&lt;p&gt;Covered. Partial. Missing.&lt;/p&gt;

&lt;p&gt;I cannot unlearn that vocabulary now. The next time I review a diff without it, I will feel exactly what is missing, the way I never could before this phase existed.&lt;/p&gt;

&lt;p&gt;Test runs next. It will find out whether pass-with-risk was the right call, or just a well-documented mistake.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A key takeaway:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is not a template I built for this article. It is the skill I run after every plan and build pass.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;review&lt;/code&gt; skill inspects the actual diff against the brief, plan, and task artifacts, not against intent or memory. It maps every active requirement to covered, partial, or missing, runs a blocking pass and a non-blocking pass, and forces a recommendation of pass, pass-with-risk, or hold before Test is allowed to start.&lt;/p&gt;

&lt;p&gt;Download it. Give it to your agent. Drop it into a task that already has a diff and an approved plan. Watch it refuse to call something covered until the evidence says so.&lt;/p&gt;

&lt;p&gt;The review artifact it generates is proof that the diff was actually checked against the contract, not just read.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/JeelVankhede/cc253b5003dbc4b53c2c5c06f7dd9ceb" rel="noopener noreferrer"&gt;review.md on GitHub Gist&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>codereview</category>
      <category>softwaredevelopment</category>
      <category>engineering</category>
      <category>developer</category>
    </item>
    <item>
      <title>The Agent Did Not Drift. I Did.</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Mon, 29 Jun 2026 14:21:37 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/the-agent-did-not-drift-i-did-4ihn</link>
      <guid>https://dev.to/jeelvankhede/the-agent-did-not-drift-i-did-4ihn</guid>
      <description>&lt;p&gt;The agent paused. It was waiting for me. I was not used to that.&lt;/p&gt;

&lt;p&gt;Every AI tool I had worked with before would fill the gap. Ask it to implement a feature and it would implement the feature, then the next logical thing, then the thing after that. You would come back to a diff three times larger than what you asked for. Confident. Finished. Sometimes wrong.&lt;/p&gt;

&lt;p&gt;Build did not do that.&lt;/p&gt;

&lt;p&gt;It executed Phase 1. It stopped.&lt;/p&gt;

&lt;p&gt;I reviewed. I approved. It executed Phase 2. It stopped again.&lt;/p&gt;

&lt;p&gt;I kept expecting it to continue. It never did.&lt;/p&gt;

&lt;p&gt;That patience was not a limitation. It was the contract working.&lt;/p&gt;

&lt;h2&gt;
  
  
  The work that earns the right to be boring
&lt;/h2&gt;

&lt;p&gt;This is Part 4 of The Contract. If you are starting here: Think produced a brief, Plan produced an approved sequence, and Build is where that sequence runs.&lt;/p&gt;

&lt;p&gt;Every frontend codebase has a version of this problem. One notification on launch. Then two. Then three conditions deciding which one to show. Nobody centralises it because it is never urgent enough. Until it is.&lt;/p&gt;

&lt;p&gt;I had let mine reach that point.&lt;/p&gt;

&lt;p&gt;Background items resolved on app launch. Each one could trigger a notification. The logic deciding which notification to show lived at each call site. No scheduler. No priority. Just conditions stacked on conditions, each one unaware of the others. They started colliding.&lt;/p&gt;

&lt;p&gt;I wrote a brief. I wrote a plan.&lt;/p&gt;

&lt;p&gt;Five phases. Three to consolidate everything under one scheduler and build the queue. One to wire it into the launch sequence. One to clean up.&lt;/p&gt;

&lt;p&gt;Brief done. Plan approved.&lt;/p&gt;

&lt;p&gt;By the time Build started, every structural decision had already been made. Build did not need to think. It only needed to execute.&lt;/p&gt;

&lt;p&gt;Build has entry conditions.&lt;/p&gt;

&lt;p&gt;It checks the branch state before touching a file. It verifies the plan artifact is approved. If the branch is wrong, it stops. If scope has expanded beyond what the plan defined, it stops. Build does not interpret intent. It verifies state, then executes.&lt;/p&gt;

&lt;p&gt;Phase 1 executed. Scheduler in place. Files where the plan said they would be. I reviewed it and approved Phase 2.&lt;/p&gt;

&lt;p&gt;Phase 2. Phase 3. Each one scoped, reviewable, testable on its own.&lt;/p&gt;

&lt;p&gt;That is what two phases of upstream work buys. Not code that works. Code that arrives narrow enough to be understood before it is approved.&lt;/p&gt;

&lt;p&gt;That narrowness is what let me catch what was coming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build did exactly what I asked
&lt;/h2&gt;

&lt;p&gt;Phase 4 landed.&lt;/p&gt;

&lt;p&gt;The queue was wired into the launch sequence. First run: correct. The scheduler picked up the items, ordered them, surfaced the right notification.&lt;/p&gt;

&lt;p&gt;Second run: nothing.&lt;/p&gt;

&lt;p&gt;The queue never reset between sessions. Items were scheduled once and never cleared. The scheduler treated the queue as durable when the system treated each session as disposable.&lt;/p&gt;

&lt;p&gt;The brief described the scheduling logic, the priority ordering, the collision rules. It did not say anything about queue lifetime. It did not say when to flush. It did not say what a session boundary meant to the scheduler.&lt;/p&gt;

&lt;p&gt;Build implemented exactly what the artifact said. When the artifact was silent, Build stayed silent too.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Donald Knuth had this right: "Computers are good at following instructions, but not at reading your mind."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I went back to the brief and read it the way Build had read it. The flush condition was not there. Not buried or ambiguous. Just absent. I had written around the scheduler lifecycle without ever writing about it. In my head the reset was obvious. In the artifact it did not exist. The brief was missing the one line that would have made Phase 4 correct on the second run.&lt;/p&gt;

&lt;p&gt;The gap was not in the code. The gap was in what I had decided was too obvious to write down.&lt;/p&gt;

&lt;p&gt;The agent did not drift. I did.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gate that made the gap catchable
&lt;/h2&gt;

&lt;p&gt;The moment I found it, Phase 5 had not started.&lt;/p&gt;

&lt;p&gt;Nothing downstream had been built on top of the broken assumption. That is not luck. That is the architecture of the workflow.&lt;/p&gt;

&lt;p&gt;Build waits between phases because a human checking partial output mid-sequence costs one review. Finding the same problem after Phase 5 costs five phases of rework.&lt;/p&gt;

&lt;p&gt;The exit condition is not delivery. It is confirmation. Without that gate, Build is just a slower way to get a large diff.&lt;/p&gt;

&lt;p&gt;I added the flush condition to the brief. I updated the plan. The phase re-executed. Phase 5 ran clean.&lt;/p&gt;

&lt;p&gt;One gap. Caught at the right moment. Without a cycle of iterations to find it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The brief is the contract
&lt;/h2&gt;

&lt;p&gt;Build executes what exists in the artifact. No more. No less.&lt;/p&gt;

&lt;p&gt;I had expected Build to catch my oversight. That expectation was wrong. The workflow was designed to make it wrong.&lt;/p&gt;

&lt;p&gt;Build is not a safety net for an incomplete brief. It is a precise executor of an approved one. When the brief is honest, Build produces exactly what I imagined. When the brief has a gap, Build produces exactly that too.&lt;/p&gt;

&lt;p&gt;The five phases landed at roughly 95% of what I intended.&lt;/p&gt;

&lt;p&gt;That number felt high at first. Then I looked at where the 5% came from.&lt;/p&gt;

&lt;p&gt;It came from me. Every time. A brief assumption that did not make it into the artifact. A detail that seemed too obvious to write. An edge case I held in my head instead of the plan.&lt;/p&gt;

&lt;p&gt;Build did not miss those things. I never gave them to Build.&lt;/p&gt;

&lt;p&gt;The workflow did not fail. It showed me everything I had decided was too obvious to write down.&lt;/p&gt;

&lt;p&gt;That is the most honest thing a tool has ever told me.&lt;/p&gt;

&lt;h2&gt;
  
  
  What comes next
&lt;/h2&gt;

&lt;p&gt;Build closes with a task artifact.&lt;/p&gt;

&lt;p&gt;Every changed file is recorded. Every check that ran is recorded. Every check that did not run is recorded with a reason.&lt;/p&gt;

&lt;p&gt;Review does not start with the code. It starts with that artifact. The question Review asks is not whether Build made a mistake. It is whether what Build executed was actually what the plan intended.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A key takeaway:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is not a template I built for this article. It is the skill I run after every feature plan.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;build&lt;/code&gt; skill executes exactly one approved plan phase at a time, preserves unrelated changes, inspects branch and repo state before edits, and records every changed file with manifest IDs and command evidence. It stops when scope expands. It waits when branch state is wrong. It produces a task artifact Review can trace back to the plan.&lt;/p&gt;

&lt;p&gt;Download it. Give it to your agent. Drop it into a task that already has an approved brief and plan. Watch it pause instead of fill in the gaps.&lt;/p&gt;

&lt;p&gt;The task artifact it generates is proof that Build ran inside the contract.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/JeelVankhede/9fee08205fd303876b4e54854c6c1acf" rel="noopener noreferrer"&gt;build.md on GitHub Gist&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>softwaredevelopment</category>
      <category>developertools</category>
      <category>aitools</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>The Plan Blocked Me. That Was the Correct Outcome.</title>
      <dc:creator>Jeel Vankhede</dc:creator>
      <pubDate>Tue, 23 Jun 2026 04:05:24 +0000</pubDate>
      <link>https://dev.to/jeelvankhede/the-plan-blocked-me-that-was-the-correct-outcome-279l</link>
      <guid>https://dev.to/jeelvankhede/the-plan-blocked-me-that-was-the-correct-outcome-279l</guid>
      <description>&lt;p&gt;The brief was approved. Scope defined, questions closed, acceptance criteria written. The obvious move was to start building.&lt;/p&gt;

&lt;p&gt;I ran the Plan phase first.&lt;/p&gt;

&lt;p&gt;Planning and the Plan phase are not the same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Planning produces direction. The Plan phase produces a gate.
&lt;/h2&gt;

&lt;p&gt;Every engineer plans. Sprint boards. Jira tickets. A rough sequence before a large refactor starts. It works well enough because a human engineer carries what the plan does not say. They know what they did not write down.&lt;/p&gt;

&lt;p&gt;An agent does not. An agent fills the gaps with its best guess. That is not inefficiency. It is drift. I covered what drift costs in the &lt;a href="https://dev.to/jeelvankhede/an-ai-agent-is-a-hammer-the-think-phase-is-where-you-aim-it-3gkd"&gt;last part of this series&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Plan phase has one property that a sprint board does not: refusal conditions.&lt;/p&gt;

&lt;p&gt;A plan that cannot refuse you is documentation. A plan with refusal conditions is a gate.&lt;/p&gt;

&lt;p&gt;Nobody brings materials to a construction site and figures out the building as they go. There is a blueprint first. Then an estimate. The estimate is not the slow part. Finding out mid-build that a wall cannot go there is the slow part.&lt;/p&gt;

&lt;p&gt;The brief is the blueprint. The Plan phase is the estimate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The impact map found what the brief described in one line
&lt;/h2&gt;

&lt;p&gt;The refactor target was a god class. It owned too much. The brief said split it.&lt;/p&gt;

&lt;p&gt;Most codebases have a version of this. A module that owns too much and the team has learned to work around. The brief names it in one line and moves on. The impact map cannot.&lt;/p&gt;

&lt;p&gt;It found that the god class held the payload formatting logic. Every notification the system sent passed through it before leaving the application boundary. Split it wrong and the notification contract breaks. Which phase owns that during the transition?&lt;/p&gt;

&lt;p&gt;I thought the brief had answered that. It had not.&lt;/p&gt;

&lt;p&gt;The impact map could not answer it either. That required the risk register.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plan blocked. That was correct.
&lt;/h2&gt;

&lt;p&gt;The risk register stopped me at a question I had not prepared for.&lt;/p&gt;

&lt;p&gt;The payload format was a contract with the external notification provider. The provider expected specific field names and structure. It did not return an error when that structure changed. It silently rejected the payload. No exception. The only evidence would come downstream, weeks later, when someone noticed the silence.&lt;/p&gt;

&lt;p&gt;That kind of failure is a time bomb.&lt;/p&gt;

&lt;p&gt;There was no mitigation in the current plan. The plan blocked.&lt;/p&gt;

&lt;p&gt;My first instinct was to push through. Grant myself the waiver. Flag it low risk. Sort it out during Build. That is the exact moment the Plan phase exists to intercept. Not because the risk was catastrophic. Because the question was unanswered, and an unanswered question does not disappear. It travels into Build and becomes the agent's problem.&lt;/p&gt;

&lt;p&gt;I had always sorted things like this mid-build. This time the plan would not move until I had the answer.&lt;/p&gt;

&lt;p&gt;That cost time I had not budgeted. It cost less than tearing down a wall mid-build.&lt;/p&gt;

&lt;p&gt;So I answered it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision was made at plan time, not build time
&lt;/h2&gt;

&lt;p&gt;I made the call. Not automatically. The simpler path was to move everything in one phase. But one ordering changed the external interface before the replacement was verified. The other preserved the notification contract through the transition and required a human to confirm the payload format before the agent could proceed.&lt;/p&gt;

&lt;p&gt;No code was written. I made a sequencing decision. The agent would follow it.&lt;/p&gt;

&lt;p&gt;A human engineer would have caught this mid-build. Professional instinct. Write "migrate notification dispatch" as a task and the agent migrates it. It does not know the field names are a contract. It does not know silent rejection is the failure mode. It does not know to pause before continuing.&lt;/p&gt;

&lt;p&gt;The god class was specific to this refactor. The problem it exposed was not. Something will always look safe to move. What makes it unsafe is external, invisible to a scan, and silent when it breaks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build owns code. Plan owns sequencing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The plan was signed. That was not the end.
&lt;/h2&gt;

&lt;p&gt;Think told me what to build. Plan told me in what order. Those are not the same document and they are not the same decision.&lt;/p&gt;

&lt;p&gt;That is not a handoff. That is a gate.&lt;/p&gt;

&lt;p&gt;Build started with a plan the agent could not diverge from. Whether the plan was precise enough was a question only Build could answer. That is the next part.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A key takeaway:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;This is not a template I built for this article. It is the skill that I run for my plans.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The&lt;/em&gt;&lt;/strong&gt; &lt;code&gt;plan&lt;/code&gt; &lt;strong&gt;&lt;em&gt;skill prepares an impact map, risk registers, phases and verification gates. It enforces that all risks are known and user is acknowledged before Build begins and produces the plan as a versioned artifact.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Use it in the sequence to the Think. Once the brief is generated, you prepare a plan and read how it differs from the regular plans that AI makes.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/JeelVankhede/1a20ee3b11a354cfa2e123ccbee29247" rel="noopener noreferrer"&gt;plan.md on GitHub Gist&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>developertools</category>
    </item>
  </channel>
</rss>
