<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Adam Miles - AI on Real Codebases]]></title><description><![CDATA[For engineers and CTOs putting AI to work on real production systems, not greenfield demos.]]></description><link>https://www.adammiles.ai</link><image><url>https://substackcdn.com/image/fetch/$s_!dOIu!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf446455-9214-4d0b-8274-a0581b00c0cf_1280x1280.png</url><title>Adam Miles - AI on Real Codebases</title><link>https://www.adammiles.ai</link></image><generator>Substack</generator><lastBuildDate>Sun, 05 Jul 2026 01:12:58 GMT</lastBuildDate><atom:link href="https://www.adammiles.ai/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Adam Miles]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[adammilesai@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[adammilesai@substack.com]]></itunes:email><itunes:name><![CDATA[Adam Miles]]></itunes:name></itunes:owner><itunes:author><![CDATA[Adam Miles]]></itunes:author><googleplay:owner><![CDATA[adammilesai@substack.com]]></googleplay:owner><googleplay:email><![CDATA[adammilesai@substack.com]]></googleplay:email><googleplay:author><![CDATA[Adam Miles]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[How I run an entire module rebuild, start to finish]]></title><description><![CDATA[The strangler-fig rewrite says do one module at a time. Here is the exact sequence of commands I run to take a single module from empty folder to shipped.]]></description><link>https://www.adammiles.ai/p/how-i-run-an-entire-module-rebuild</link><guid isPermaLink="false">https://www.adammiles.ai/p/how-i-run-an-entire-module-rebuild</guid><dc:creator><![CDATA[Adam Miles]]></dc:creator><pubDate>Mon, 29 Jun 2026 15:04:08 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!pqr1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In <a href="https://www.adammiles.ai/p/rebuilding-a-brownfield-application">Rebuilding a brownfield application module-by-module with AI</a>, I made the case for the strangler-fig approach: instead of a big-bang rewrite, you replace a legacy system one module at a time while the product keeps shipping. That post is the <em>why</em>. This one is the <em>how</em>.</p><p>What follows is the actual command sequence I run to take one module from an empty folder to shipped code. Each command runs in its own fresh AI session and writes a numbered file on disk, and that file is the handoff to the next command, so each step picks up exactly where the last one stopped. The module is just this sequence: run once at the top, then looped over each feature inside it.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pqr1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pqr1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!pqr1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!pqr1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!pqr1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pqr1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1392099,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.adammiles.ai/i/204126137?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pqr1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!pqr1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!pqr1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!pqr1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95df7b9b-4c62-4db7-a22d-4aebe894164f_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h1>The sequence</h1><h2>1. Define the module</h2><p>I start with `/module:00-define`. This writes a short charter: what the module is, who uses it, what already exists in the legacy system for this area, and the constraints any rebuild has to respect. It is deliberately cheap and locks nothing. No feature list, no decisions, just the problem framed clearly.</p><p>Why it matters: the framing is the whole point. For a scheduling module, that is a sentence or two: let staff manage the day&#8217;s appointments in one place, cut double-bookings, replace a clunky legacy calendar the team has outgrown. No screens, no fields. That framing gives the research a real target, and gives every later step a shared understanding of what we are building and why.</p><h2>2. Research the landscape</h2><p>Next is `/module:01-research`, which runs deep competitive and industry research against that charter. It reads across the whole landscape: what competitors ship, what the industry treats as table stakes, where the real opportunities are, and what our own users are actually trying to do. It proposes; it decides nothing.</p><p>This step is the easiest to underrate. Our product manager is regularly surprised by features the research proposes, and the surprise is the tell: the AI understood the user&#8217;s problem well enough to find a gap the team had missed. Weak research produces a confident module that solves the wrong problem. Strong research is where most of the value gets created.</p><h2>3. Lock the scope</h2><p>Then `/module:02-requirements` turns the research into a frozen scope: the capabilities the module must have, what we keep or kill from the legacy system, and the decisions every feature inside the module will inherit. This step ends with the <strong>first human gate, the freeze.</strong> Nothing expensive gets built until I confirm it, because everything after this point is built on top of it.</p><p>It is also not the AI working alone. This step runs as a working session between the AI, a developer, and the domain expert or product manager. The research did the reading; this step surfaces the decisions that steer the module: what is in scope, where the technical trade-offs are, and the judgment calls that only someone who knows the business and the customer can make. It proposes, the people in the room decide. These answers set the direction of every feature that follows, so the freeze is only as good as the people confirming it.</p><h2>4. Break it into features</h2><p>With scope frozen, `/module:03-feature-map` splits the module into its features and puts them in build order. It scaffolds a numbered folder per feature, ordered so that features producing data come before the features that read it.</p><p>Why it matters: the ordering is the payoff. Features are built in dependency order, so each feature&#8217;s inputs already exist by the time you reach it. The numbered folders make this self-documenting: the lowest-numbered unfinished folder is always the next thing to build. And because every capability from the frozen scope has to land in exactly one feature, nothing falls through the cracks.</p><p><em>Steps 1 through 4 run once. The next four run per feature, looping until the module is done.</em></p><h2>5. Lock the feature&#8217;s requirements</h2><p>Now I drop into a single feature. A larger feature gets sliced into smaller phases first, and the requirements and prototype steps run over each phase in turn. An optional `/feature:00-research` covers anything the module research did not reach. Then `/feature:03-requirements` does a codebase recon and freezes the feature&#8217;s requirements and a decision register: every decision, the recommendation, the final answer, and the reason where I overrode it.</p><p>Why it matters: like locking the module scope, this is a working session, not the AI alone. The difference is altitude. Module requirements set the high-level scope; this drops into one feature, where intent actually lives and where the AI will otherwise fill in the blanks with its own assumptions. The register that comes out of it is the contract everything downstream is checked against, which is how you catch &#8220;we are about to build the wrong thing&#8221; while it still costs a conversation instead of a rewrite. The codebase recon is the other half: it teaches the AI the unwritten conventions of this feature&#8217;s corner of the system before a line is written, so the generated code fits what is already there. This is the one step I never skip.</p><h2>6. Prototype it</h2><p>If the feature has a user interface, `/feature:04-prototype` builds a clickable prototype. Then comes the <strong>second human gate, the prototype review:</strong> I open it in the browser and actually use it, and `/feature:05-freeze` locks the final design once it matches what we intended. Features with no screen of their own, a pure backend or data job, skip the prototype build and go straight from requirements to a thin freeze.</p><p>Why it matters: this is where we find out what needs to change, while changing it is still cheap. The agreed prototype then becomes the contract the implementation builds against. A spec document leaves room for interpretation, and in the past that room is exactly where the work went sideways: the wrong tangents nobody caught until late. Iterating on something you can click closes that gap before any implementation starts. And the prototype is not throwaway: it is the actual production UI, so the design work done here is not redone later. (I go deep on this step in [<a href="https://www.adammiles.ai/p/from-one-command-to-a-production">Most &#8220;AI in a day&#8221; ships slop. This pipeline has to clear the bar first.</a>])</p><h2>7. Implement it</h2><p>`/feature:06-plan` decomposes the frozen feature into implementation steps sized to fit an AI session, then `/feature:07-implement-all` works through them: it dispatches the right specialist for each step, runs review gates, and commits when things pass.</p><p>Why it matters: the size limit is what keeps the AI sharp. Each step runs in a fresh agent with clean context, so no single session has to hold the whole feature in its head. The planner refuses oversized steps before they run, which is the single biggest reason large features go wrong with AI. (<a href="https://www.adammiles.ai/p/subagents-solve-one-ai-problem-orchestration">That context-discipline problem, and why orchestration is what addresses it, is the subject of [Orchestration solves one AI problem. It hides another.</a>) Splitting the work also lets the right specialist take each piece, instead of one general-purpose agent doing everything adequately and nothing well. And because every step is checked against the frozen register before it commits, the implementation cannot quietly invent scope that nobody signed off on.</p><h2>8. Test it</h2><p>`/test:create-scenarios` generates test scenarios from the frozen requirements, and `/test:run-scenarios` drives them against the real app.</p><p>Why it matters: code that compiles is not code that works. On a system like this, the only real test is whether the feature behaves correctly end to end, with real-shaped data, without breaking the features next to it, and that is exactly what unit tests miss. Generating the scenarios from the frozen requirements closes the loop the contract opened: the same document that said what to build becomes the checklist for whether it got built. A feature is not done when it runs. It is done when it does what it promised.</p><p>This is also where the <strong>third human gate, the ship decision,</strong> lives. The AI prepares the case: the review against the frozen register plus the scenario results. It does not get to ship. I read that and make the call.</p><div><hr></div><h2>Then repeat, feature by feature</h2><p>That four-step loop runs in the build order the breakdown set: take the lowest-numbered unfinished feature from requirements to tested, then move to the next number, until the last feature exits the loop.</p><p>Because each command writes its state to a file, I never have to keep a session open to hold context. I can close everything, come back days later, and the files on disk tell the next command exactly where to start. (That handoff-through-files trick is the state machine I described in the first post.) Nothing goes stale, and nothing is lost between sessions.</p><div><hr></div><h2>Knowing where you are: `/module:status`</h2><p>With several features each moving through requirements, prototype, implementation, and test, the one thing I need at a glance is where the module stands. That is what `/module:status` is for. It reads the same files the pipeline writes and prints a compact rollup: a row per feature, a glyph per step. Then it does the thing that matters more than the status itself: it hands me the literal command to paste for the next unfinished feature&#8217;s next step. I never have to remember where I left off. It writes nothing and decides nothing, so I reach for it constantly.</p><div><hr></div><p>That is the whole spine. One module is this sequence, start to finish. The strangler-fig rewrite is the same loop run module after module, until the legacy system is gone. The sequence is fixed. The discipline is in running it every time.</p><div><hr></div><p><em>I&#8217;m Adam Miles. 25 years of shipping software, including the messy brownfield kind. I write about using AI to move real codebases forward: legacy, greenfield, and the awkward middle.</em></p><p><em>If you&#8217;re rebuilding a legacy system, or thinking about it, I&#8217;m happy to compare notes. </em></p><p><em>The companion to this post:</em></p><ul><li><p><em><a href="https://www.adammiles.ai/p/rebuilding-a-brownfield-application">Rebuilding a brownfield application module-by-module with AI</a>: the strategic case for the strangler migration this sequence runs inside. If this post is the how, that one is the why.</em></p></li></ul><p><em>Deeper dives on two of the steps:</em></p><ul><li><p><em><a href="https://www.adammiles.ai/p/from-one-command-to-a-production">Most &#8220;AI in a day&#8221; ships slop. This pipeline has to clear the bar first</a>: a deeper look at the prototype step.</em></p></li><li><p><em><a href="https://www.adammiles.ai/p/subagents-solve-one-ai-problem-orchestration">Orchestration solves one AI problem. It hides another</a>: why context discipline is the load-bearing problem, and where orchestration helps.</em></p></li></ul><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.adammiles.ai/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Adam Miles - AI on Real Codebases! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Rebuilding a brownfield application module-by-module with AI]]></title><description><![CDATA[A 20-year-old legacy backend, a SQL Server database, a rewrite in flight, a React UI mid-migration, and a methodology that turns the strangler-pattern rewrite into an accelerant, not an anchor.]]></description><link>https://www.adammiles.ai/p/rebuilding-a-brownfield-application</link><guid isPermaLink="false">https://www.adammiles.ai/p/rebuilding-a-brownfield-application</guid><dc:creator><![CDATA[Adam Miles]]></dc:creator><pubDate>Mon, 29 Jun 2026 14:59:42 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!EBq0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A brownfield system is software that already exists and already runs: years of accumulated code, real customers depending on it, constraints you inherited rather than chose. It&#8217;s the opposite of greenfield, the blank repo and clean prompt that most AI coding demos are built on. Those demos look impressive on Twitter and tell you almost nothing about whether AI can ship on the codebases that actually run the world.</p><p>They look more like this: a legacy backend, and a team that knows AI could help but isn&#8217;t sure where to start without breaking production.</p><p>I&#8217;m in the middle of rebuilding one of those codebases right now. Module by module. With humans in the loop at the right gates, not all of them. This isn&#8217;t a retrospective: it&#8217;s the system I&#8217;m running on today, refined over several months of daily use.</p><p>One data point to anchor what this methodology does: <strong>UX and UI work that used to take us four to six weeks now takes a single 1-2 hour session: one developer, one domain expert or PM, and a clickable prototype at the end of it.</strong> The rest of this post is the strategic case for <em>why</em> that&#8217;s possible and <em>when</em> you&#8217;d want to do it.</p><div><hr></div><h1>Why module-by-module, and not a from-scratch rewrite</h1><p>The fantasy version of a legacy rewrite is this: take the team offline for six months, build a clean new application, ship it, sunset the old one. Most engineering leaders have considered it. Most have rejected it, and so did we. Here&#8217;s why:</p><ul><li><p><strong>We don&#8217;t have the luxury of going dark for six months.</strong> The business runs on this software. Customers depend on it for their daily operations. Even if we tried, the requirements would shift underneath us before we shipped, and we&#8217;d ship a system already six months out of date.</p></li><li><p><strong>Big-bang migrations are a customer punishment.</strong> Every customer hits the same wall on the same day: workflows change, integrations break, muscle memory resets. The customers who didn&#8217;t ask for a rewrite (almost all of them) experience it as a regression, and your team spends the next six months firefighting churn instead of building.</p></li><li><p><strong>The cutover concentrates the risk into one day.</strong> Everything either works or it doesn&#8217;t the moment you flip traffic from old to new. Module-by-module spreads that risk across dozens of small cutovers, each independently rollback-able. You trade one terrifying day for many boring weeks.</p></li></ul><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EBq0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EBq0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!EBq0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!EBq0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!EBq0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EBq0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1437571,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.adammiles.ai/i/204059113?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!EBq0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!EBq0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!EBq0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!EBq0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd00a1a-fb37-4483-882e-ef6f334c579c_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p>The alternative, the one we&#8217;re actually doing, is the <strong>strangler pattern.</strong> Named after the strangler fig, which grows around its host tree and replaces it from the outside in until the host can be retired and the fig is load-bearing on its own. </p><p>In practice that means:</p><ul><li><p><strong>All new development happens on the new backend.</strong> No new endpoints get added to the legacy backend, ever. The legacy backend stops growing the day you commit to this.</p></li><li><p><strong>Any time we touch a legacy endpoint for a change, we strongly consider porting it.</strong> Not every touch is a port. But &#8220;is it cheap to port this now?&#8221; is a question we ask every time, and the answer is yes more often than the team expects.</p></li><li><p><strong>Customers don&#8217;t experience the migration.</strong> From their perspective, features keep shipping. The UI gets better. Performance improves on the modules we&#8217;ve rebuilt. They never hit a &#8220;welcome to the new app&#8221; wall. Their muscle memory survives.</p></li></ul><p>And critically: <strong>we&#8217;re not doing parity.</strong> Each module that gets rebuilt is also an opportunity to improve. Features customers have been asking about for years, features the legacy stack couldn&#8217;t accommodate, finally become possible because the module is being touched anyway. The strangler pattern isn&#8217;t lift-and-shift. It&#8217;s <em>rebuild-while-advancing.</em></p><p>This is where AI changes the math. The strangler pattern stops being the expensive option and becomes the <em>only</em> sane one for complex brownfield applications.</p><div><hr></div><h1>The methodology in one screen</h1><p>Every feature, from a one-day fix to a multi-week module rebuild, moves through the same phases. The shape is two tiers. A handful of steps run <strong>once per module</strong> to set direction, then a tight loop runs <strong>once per feature</strong> until the module is done. Not all features need every step, but the ordering is invariant.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!olTz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!olTz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!olTz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!olTz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!olTz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!olTz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1392099,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.adammiles.ai/i/204059113?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!olTz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!olTz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!olTz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!olTz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4452faf1-2712-4b82-ad71-255acb5406af_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p><strong>Module-level, run once:</strong></p><ol><li><p><strong>Define the module.</strong> A short charter: what it is, who uses it, what the legacy system already does here, what a rebuild has to respect.</p></li><li><p><strong>Research the landscape.</strong> Deep competitive and industry research against that charter. The AI becomes an expert in the problem, not a code generator pointed at the repo.</p></li><li><p><strong>Lock the scope.</strong> Turn the research into a frozen scope every feature inherits. <strong>First human gate: the freeze.</strong> A developer and a domain expert confirm what&#8217;s in, and what&#8217;s out. </p></li><li><p><strong>Break it into features.</strong> Split the scope into features in dependency order, so each feature&#8217;s inputs already exist when you reach it.</p><p></p><p><strong>Per feature, looped until the module is done:</strong></p><p></p></li><li><p><strong>Lock the feature&#8217;s requirements.</strong> A working session that freezes this slice&#8217;s requirements.</p></li><li><p><strong>Prototype it.</strong> A multi-agent pipeline produces a clickable, polish-gated UI in 1-2 hours. The prototype is the production UI: same React app, same design system, only the backend mocked. (Its own deep-dive: <a href="https://www.adammiles.ai/p/from-one-command-to-a-production">Most &#8220;AI in a day&#8221; ships slop. This pipeline has to clear the bar first</a>) <strong>Second human gate: the prototype review.</strong> Someone opens it in a browser and <em>uses</em> it. This is a product review, not a code review.</p></li><li><p><strong>Implement it.</strong> An orchestrator dispatches specialist subagents through plan-sized steps, runs review gates between them, and commits when they pass.</p></li><li><p><strong>Test it.</strong> Scenarios automatically generated from the frozen requirements get tested against the real app. Automated testing takes care of 95% of test scenarios, and flags the 5% that need a human to run by hand. <strong>Third human gate: the ship decision.</strong> A human uses the module and decides whether it&#8217;s ready for production.</p></li></ol><p>The full command sequence that runs a module through every one of these steps, start to finish, is its own post: <a href="https://www.adammiles.ai/p/how-i-run-an-entire-module-rebuild">How I run an entire module rebuild, start to finish</a>.</p><div><hr></div><p>Three things hold this together. The AI recommends, but a human always makes the final call: the AI does the reading, the human owns the decision. The work is broken into small pieces, because the AI does careful work on a small, well-defined task and sloppy work on a big vague one. And every step is written down as it finishes, so the work can always be picked up later exactly where it stopped.</p><p><strong>AI for the parts where AI is good, humans for the parts where humans are good, and </strong><em><strong>gates between them that neither side can skip.</strong></em></p><div><hr></div><h1>What this is worth: the actual time savings</h1><p>This isn&#8217;t a &#8220;10x productivity&#8221; story. Brownfield rewrites that used to be 18-month death marches now run as a sequence of 1-2 week phases with clear gates. The AI does most of the typing, reading, and scaffolding, but not the team&#8217;s judgment about <em>what</em> to build.</p><p>And the time savings aren&#8217;t the whole story. The <em>output is better</em>:</p><ul><li><p><strong>It&#8217;s an actually-clickable prototype, not a static mock.</strong> The team reacts to a running thing.</p></li><li><p><strong>The requirements are sharper, and some are ideas the team wouldn&#8217;t have produced on its own.</strong> Not because the AI is smarter, but because it reads at a breadth no human has time for. It studies how dozens of other products solve the same problem, including ones in neighboring markets the team would never think to look at, and surfaces patterns we hadn&#8217;t considered. </p></li><li><p><strong>It catches requirements gaps that would have shipped.</strong> A working prototype surfaces the &#8220;wait, that&#8217;s not what we meant&#8221; moments that a spec document hides. That alone has saved us from multiple multi-week reworks.</p></li></ul><p>That&#8217;s the trade: less time, better output, and a working artifact to validate it. Everything downstream of the prototype (the freeze, the plan gates, the orchestrated implementation) exists to hold that gain across an entire rewrite, not just a single feature.</p><div><hr></div><h1>What I&#8217;d tell a team starting this work</h1><p>If you&#8217;re staring at a legacy system wondering whether AI can help with the rewrite, the answer is yes, but the approach matters more than the tools. What I&#8217;d put on the wall before you start:</p><ul><li><p>Break your application into large modules, and rebuild one at a time. The module is the unit of work, of risk, and of cutover.</p></li><li><p>Make competitor and adjacent-industry research a real step, not a footnote.</p></li><li><p>Put at least a developer and a product manager in the room for requirements. Some of the decisions are business decisions, and they need someone who owns the business there to make them.</p></li><li><p>Build the prototype before you commit to the implementation, and freeze requirements <em>after</em> it, not before. The prototype is the cheapest place to be wrong, and the contract everything downstream builds against.</p></li><li><p>The brownfield rewrite is the hardest thing software does. AI doesn&#8217;t make it easy. It makes it <em>possible</em> at a different speed and cost, but only if you build the scaffolding that respects how hard the problem actually is.</p></li></ul><div><hr></div><p><em>I&#8217;m Adam Miles. 25 years of shipping software, including the messy brownfield kind. I write about using AI to move real codebases forward: legacy, greenfield, and the awkward middle.</em></p><p><em>If you&#8217;re rebuilding a legacy system, or thinking about it, I&#8217;m happy to compare notes. I&#8217;m doing this work right now, the lessons are fresh, and I learn as much from the conversations as I share. </em></p><p><em>The companion to this post:</em></p><ul><li><p><em><a href="https://www.adammiles.ai/p/how-i-run-an-entire-module-rebuild">How I run an entire module rebuild, start to finish</a>: this same spine written out as the exact command sequence that takes one module from empty folder to shipped. If this post is the why, that one is the how.</em></p></li></ul><p><em>Deeper dives on two of the steps:</em></p><ul><li><p><em><a href="https://www.adammiles.ai/p/from-one-command-to-a-production">Most &#8220;AI in a day&#8221; ships slop. This pipeline has to clear the bar first</a>: the multi-agent pipeline that compresses feature design from weeks to hours.</em></p></li><li><p><em><a href="https://www.adammiles.ai/p/subagents-solve-one-ai-problem-orchestration">Subagents solve one AI problem. Orchestration hides another</a>: the engineering discipline that keeps long-running AI work in the sharp zone.</em></p></li></ul><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.adammiles.ai/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Adam Miles - AI on Real Codebases! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Subagents solve one AI problem. Orchestration hides another.]]></title><description><![CDATA[If you're chaining AI agents to do real work, your context discipline lives or dies on what you can't see. Here's the three-rule discipline I run on a production codebase every day.]]></description><link>https://www.adammiles.ai/p/subagents-solve-one-ai-problem-orchestration</link><guid isPermaLink="false">https://www.adammiles.ai/p/subagents-solve-one-ai-problem-orchestration</guid><dc:creator><![CDATA[Adam Miles]]></dc:creator><pubDate>Tue, 19 May 2026 19:51:31 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!KR6q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You already know AI quality degrades as context fills. Past about 40% you start to feel it; past 70% you&#8217;re in the Dumb Zone. (Working heuristic, not a constant. The readable write-ups: [Justin Smith](<a href="https://www.linkedin.com/pulse/40-rule-beating-claudes-dumb-zone-large-codebases-justin-smith-jlffc/">The 40% Rule: Beating Claude&#8217;s &#8216;Dumb Zone&#8217; on Large Codebases</a>), [Dale Husband](<a href="https://dev.to/diggidydale/escaping-the-dumbzone-part-1-why-your-ai-gets-stupider-the-more-you-talk-to-it-4d8k">Escaping the Dumbzone, Part 1: Why Your AI Gets Stupider the More You Talk to It</a>).) The single-session toolkit is well-covered: `/clear`, `/compact`, scoped file reads, deliberate session resets, and spawning subagents to do research for you. Use them. They work.</p><p>This post isn&#8217;t about any of that. It&#8217;s about what happens when you take the next step and let an orchestrator drive <em>multiple</em> AI agents on your behalf, each with its own context window you can&#8217;t see.</p><div><hr></div><h1>The orchestration problem</h1><p><strong>An orchestrator is a foreman.</strong> It doesn&#8217;t lay bricks or wire outlets. It reads the blueprint, calls the right specialist in, inspects what they handed back, calls the next specialist, and keeps the job moving until the building stands. No specialist sees the whole job; only the foreman does.</p><p>A good foreman also doesn&#8217;t run their crew into the ground. Tired bricklayers make mistakes, so the foreman rotates them out before that happens. The orchestrator does the same: dispatch isn&#8217;t just about who&#8217;s doing the work, it&#8217;s about who&#8217;s still sharp enough to do it well.</p><p>The state-machine layer (inspect handoff, decide next step, dispatch) is what makes orchestration different from a bash script that runs commands in a fixed order.</p><div><hr></div><h1>The invisible failure mode</h1><p><strong>Subagents solved the visible problem. Orchestration brings it back invisible.</strong> When you spawn a subagent manually, you&#8217;re still in the loop: you see the digest, you decide whether to spawn another, you catch what looks off. When an orchestrator spawns subagents on your behalf, the context windows that matter are no longer ones you can see. No dashboard tells you agent #3 came back from a 65%-full session and agent #5 came back from an 18%-full session. Each long-running subagent degrades as it fills, and you weren&#8217;t the one who decided to spawn it.</p><p>A worker at 70% context misreads a column type, returns a migration that looks right at a glance, and the orchestrator builds an API endpoint on top of it. A long session crashes loud. An orchestration produces bad work quietly, the whole time.</p><p>The good news: it&#8217;s a structural problem with a structural solution. The piece that makes it work is <strong>handoff files</strong>. A handoff file is a short, structured note an agent writes before its session ends. The next agent reads the note and picks up from a 0% context window. <strong>The state lives on disk, not in any session&#8217;s memory.</strong></p><p>With that piece in place, the rest follows. Three rules keep every session in the tree under the 40% line: one for the orchestrator, one for the subagents it dispatches, one for the long-running workers that save their state to disk.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KR6q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KR6q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!KR6q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!KR6q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!KR6q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KR6q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1380516,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.adammiles.ai/i/198460708?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!KR6q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!KR6q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!KR6q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!KR6q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F240f0354-214f-4122-9d5b-62700fc0e113_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h1>Rule 1: The orchestrator never does the work itself</h1><p>The hardest session to keep sharp is the orchestrator&#8217;s own. A wrong call by an orchestrator at 50% context isn&#8217;t one mistake. <strong>It&#8217;s a dozen subagents working on the wrong thing.</strong></p><p>The mechanism that keeps the orchestrator&#8217;s context low is simple: <strong>it doesn&#8217;t do the work.</strong> No source file reads. No tool output dumps in its own session. No long-form analysis. The orchestrator&#8217;s only job is to dispatch: spawn the right subagent, inspect the handoff that comes back, decide what&#8217;s next, spawn again. Every byte of &#8220;real work&#8221; that lives in the orchestrator&#8217;s session is a byte that didn&#8217;t need to be there.</p><div><hr></div><h1>Rule 2: Delegate discovery to read-only locators</h1><p>The orchestrator stays light by not reading source files. But knowing <em>which</em> source files matter, and what&#8217;s in them, is still required to make good decisions. That&#8217;s discovery: read-only research about the codebase, the database, the conventions. Someone has to do it.</p><p>The answer is a specialized subagent (a <strong>locator</strong>) that the orchestrator delegates the discovery to. Treat every file read as a context withdrawal. Spawning a subagent is almost nothing; pulling five files into the parent&#8217;s context window stays there for the rest of the session.</p><p><strong>A subagent that reads 2,000 lines of source and returns 80 words of summary is the trade you want, every time.</strong></p><p>One general-purpose search agent isn&#8217;t enough. Every distinct research domain in your project deserves its own locator. I run two currently:</p><ul><li><p><strong>`code-finder`</strong>: filesystem locator. &#8220;Where is X defined?&#8221; &#8220;What touches Y?&#8221; Returns file:line maps with &#8804;10-line excerpts. Never dumps whole files.</p></li><li><p><strong>`db-finder`</strong>: database locator. Read-only DB access via MCP tools. Returns table:column digests instead of raw `describe_table` JSON, plus flags for project-specific conventions a general agent wouldn&#8217;t know.</p></li></ul><p><strong>You don&#8217;t need an orchestrator to want these.</strong> The locators pay off in any manual session too. Next time you&#8217;d point Claude at half a dozen files to answer &#8220;where does this get called from,&#8221; let it route to a `code-finder` instead and hand back a tight file:line map while your own context stays clean. The discovery happened; the source it waded through never entered your window. They&#8217;re the cheapest, highest-leverage thing in this whole post to steal, in an orchestrator or out of one.<code><br></code><br>For cross-layer questions (&#8221;where does this stored proc get called from the API?&#8221;), both locators get spawned <strong>in parallel</strong> from the same turn. One turn, two agents, two digests. The orchestrator never reads a file.</p><p><strong>I don&#8217;t type anything different to use these.</strong> Claude reads the CLAUDE.md rules (<em>&#8221;DB questions go to db-finder, code questions go to code-finder, cross-layer questions go to both in parallel&#8221;</em>) and routes the request automatically. Write the rule once; get correct routing forever.</p><p>Each locator is 40-60 lines of plain English plus an output template, and pays for itself the third time you use it.</p><div><hr></div><h1>Rule 3: Long-running agents save state to disk and hand themselves off</h1><p>Workers (implementers, reviewers, anything multi-step) take many turns and do real writes. No session can hold that safely across the budget, so the state goes where it already belongs: on disk.</p><p>When a worker finishes its assigned task, it writes a `handoff.md` describing what it did, then ends. The orchestrator reads the handoff to decide what comes next. If more work remains, a fresh worker reads the same handoff and continues. The orchestrator never holds the worker&#8217;s session context; the worker never carries forward across sessions.</p><p>A good handoff says four things:</p><ul><li><p><strong>What was produced.</strong> &#8220;Wrote three migrations and one stored proc.&#8221;</p></li><li><p><strong>Completed steps.</strong> What <em>not</em> to redo.</p></li><li><p><strong>Remaining steps.</strong> In execution order.</p></li><li><p><strong>Recovery notes.</strong> Gotchas, partial work in flight, decisions made along the way.</p></li></ul><p>A real one:</p><blockquote><p><strong>Produced:</strong> Migration `2024-05-17-add-couples-flag.sql`, stored proc `sp_Booking_GetCouples`, updated `BookingController.cs`, integration tests for the new endpoint.</p><p><strong>Completed:</strong> Steps 1&#8211;4 of phase 02-backend-implementation. Tests written and passing.</p><p><strong>Remaining:</strong> Step 5 (add the audit-log row on couples-flag change), step 6 (wire the new proc into the existing `BookingService` retry path).</p><p><strong>Recovery notes:</strong> The proc returns `&#8217;True&#8217;`/`&#8217;False&#8217;` BOOLSTR, not `bit`. Any caller has to coerce. The `BookingController` already does; `BookingService` retry path does not yet.</p></blockquote><p>Every worker writes one in the same shape, every time, so any future agent can parse it without guessing. Refusal cases are first-class citizens too: when a worker can&#8217;t do the work (wrong tool, oversized request, blocked by missing inputs) <strong>it still writes a handoff</strong> saying why and what needs to change.</p><p>Even if you never build a full orchestrator, the handoff pattern is stealable today. At the end of any meaningful session, ask Claude to write one for &#8220;the next you,&#8221; save it in the repo, and open the next session by reading it. You&#8217;ll feel the difference immediately.</p><p>Task completion isn&#8217;t the only handoff trigger. A worker that gets handed 30 sub-steps will start in the Safe Zone and end deep in the Dumb Zone if it tries to run them all in one session. So the agents themselves know about the budget. My implementer agents self-monitor their step and turn count. After a set threshold, they finish the step they&#8217;re on, write a handoff, and return. The orchestrator catches the early return and spawns a fresh implementer with clean context to continue. Nothing in the system is allowed to outlive its budget.</p><p>The same discipline keeps the orchestrator out of trouble. If you&#8217;ve applied the three rules (it dispatches instead of working, discovery goes to locators, long tasks hand themselves off), the orchestrator&#8217;s own context stays lean almost by construction. So if you ever watch an orchestrator climb past 40%, don&#8217;t reach for a bigger budget. Take a step back and find what&#8217;s bloating it: it&#8217;s reading files it should be delegating, or holding work that belonged in a subagent. A well-run orchestrator should rarely get near the line. One caveat: an orchestrator can&#8217;t safely resume <em>itself</em> (a Claude-harness limitation I ran into), so mine don&#8217;t try. When one crosses the threshold, it saves its state and stops, printing the command to resume. I re-run it in a fresh session and it picks up where it left off. A one-line handoff instead of a silent failure. If you want the details of why self-resume breaks, message me.</p><p>There&#8217;s a second benefit most people miss: <strong>each forced handoff is an implicit review checkpoint.</strong> When work is split into bounded sessions, the orchestrator inspects each handoff before spawning the next agent. It&#8217;s AI reviewing AI&#8217;s output, with fresh context, at a deliberate stopping point. Drift gets caught at the first step, while it&#8217;s still small and cheap to fix.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RnhD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RnhD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!RnhD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!RnhD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!RnhD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RnhD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1729187,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.adammiles.ai/i/198460708?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!RnhD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!RnhD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!RnhD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!RnhD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11316f4c-1c9e-44c1-b539-10ab2f71b94e_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h1>The orchestration discipline, in one screen</h1><ol><li><p><strong>The orchestrator dispatches; it never does the work itself.</strong> No source reads, no tool output in its own session.</p></li><li><p><strong>Discovery goes to read-only locators.</strong> Digest output, word-capped, gotcha-surfacing. One locator per domain.</p></li><li><p><strong>Long-running subagents hand themselves off.</strong> Structured handoff files on disk, self-triggered when budget pressure hits. Workers and orchestrators both stop while still sharp. A worker&#8217;s parent respawns it; the orchestrator has no parent to do that, so it can only resume as a fresh top-level session.</p></li></ol><p>The promise this delivers: <strong>larger multi-step work runs cleanly across many fresh sessions, with no single session falling into the degraded zone.</strong> Work where the <em>combination</em> of steps is the size, not any single step, becomes work the orchestrator handles one fresh session at a time.</p><p>None of this is magic. All of it is boring discipline applied to the one resource everyone underestimates the moment they start chaining agents.</p><p><strong>Subagents are the visible fix. The discipline in this post is the invisible one.</strong></p><p>---</p><p><em>I&#8217;m Adam Miles. 25 years of shipping software, including the messy brownfield kind. I write about using AI to move real codebases forward: legacy, greenfield, and the awkward middle.</em></p><p><em>If you&#8217;re building AI orchestration for real codebases and running into context discipline problems, I&#8217;m happy to compare notes. I&#8217;m doing this work right now, the lessons are fresh, and I learn as much from the conversations as I share. </em></p>]]></content:encoded></item><item><title><![CDATA[Most "AI in a day" ships slop. This pipeline has to clear the bar first.]]></title><description><![CDATA[A multi-agent AI pipeline for feature design and UX, and what it changes about how you work.]]></description><link>https://www.adammiles.ai/p/from-one-command-to-a-production</link><guid isPermaLink="false">https://www.adammiles.ai/p/from-one-command-to-a-production</guid><dc:creator><![CDATA[Adam Miles]]></dc:creator><pubDate>Tue, 19 May 2026 08:47:56 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2yGk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Requirements to production-grade code in a workday &#8212; gated on a 4/5 quality score against the team&#8217;s own design system, with the prototype that becomes the shipped UI, plus what it changes about how you work.</em></p><p>We all know AI can take a feature from requirements to production code now. That part is easy, and the demos are everywhere. So the interesting question stopped being <em>can it build the thing</em> and became <em>does the thing it builds actually hit the mark</em>, and that&#8217;s where almost everyone falls back to AI feature slop: fast, plausible, and subtly wrong in the ways that matter.</p><p>What separates slop from production-quality output isn&#8217;t the generation. It&#8217;s the discipline around it. The real unlock here isn&#8217;t speed at all, it&#8217;s that a built-in research step and a working, clickable prototype surface decisions and ideas the team <em>hadn&#8217;t thought of yet</em>: the edge case nobody scoped, the field that should have come from a column already in the database, the flow that only looks wrong once you click it. The prototype becomes a shared surface the whole team reacts to instead of a spec they imagine. Then a measured quality bar and human gates placed at exactly the right moments keep the output honest. Consistency with the system everything else uses isn&#8217;t a nice-to-have; it&#8217;s enforced. The day is just what&#8217;s left over once that discipline is doing its job.</p><p>Here&#8217;s what a single command produces. I run the orchestrator, walk away, and about 1.5 to 2 hours later come back to a clickable, interactive prototype and a git commit. The UI is production-quality first time, not after rounds of revision: scored above 4/5 on the quality checklist before I see it. Every screen has populated, empty, loading, and error states. The components live inside the production application, in the folder structure features ship from, using the same design system everything else uses. Zero touches between the trigger and the result.</p><p>A morning requirements session and an after-lunch team review bracket that two-hour run. After sign-off, the backend gets built and the whole feature gets tested &#8212; and on a feature that fits a common pattern, that lands the same workday too.</p><p>That same outcome used to take six to ten weeks: initial scoping, multiple rounds of static mocks, stakeholder reviews, the engineering pushback when a mock turned out to be infeasible, the rebuild as code, the iteration cycles after that. Now it lands in a workday.</p><h1>Not the demo you&#8217;ve seen</h1><p>Claude can sketch a prototype from a one-line prompt. That isn&#8217;t this. This pipeline runs against a real codebase with twenty years of schema behind it and walks a PM through thirty-plus grounded requirements questions before a line of UI gets generated. Domain, UX, and UI passes run until a polish reviewer scores the result 4/5 against the team&#8217;s own design contract. The output isn&#8217;t a demo of what AI <em>could</em> do. It&#8217;s the UI that ships in the next release.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2yGk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2yGk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!2yGk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!2yGk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!2yGk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2yGk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1495073,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.adammiles.ai/i/198372453?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2yGk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!2yGk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!2yGk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!2yGk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc05e0e3e-14b5-42d3-a0a5-22838e1df681_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This post is how the pipeline works, what it produces, and what it changes about the way you build features.</p><div><hr></div><h1>Why the old way was the rational way</h1><p>The old workflow had three load-bearing problems:</p><ul><li><p><strong>The artifact arrived late.</strong> Teams argued about static mocks for two weeks, then started over once a clickable thing finally existed.</p></li><li><p><strong>The quality bar was vibes.</strong> &#8220;Looks good to me&#8221; is not a gate. The &#8220;approved&#8221; mock might have been brilliant, or it might have had eight UX problems nobody caught. Which one you got depended on who was in the room.</p></li><li><p><strong>Requirements gaps surfaced mid-implementation</strong>, when fixing them cost days instead of minutes.</p></li></ul><p>None of that was a mistake. It was a sensible response to a real constraint: building the artifact was the most expensive thing in the cycle, so you spent weeks studying the blueprint before anyone broke ground. The multi-week design phase was an elaborate workaround for the fact that you couldn&#8217;t cheaply <em>try</em> the thing before committing to it.</p><p>AI changes the economics. The artifact stops being expensive. When a single command produces a clickable, polished, real-component prototype between breakfast and lunch, the workflow inverts. Framing the house is now cheaper than arguing over the blueprint, so the rational move is to build first and decide second.</p><div><hr></div><h1>The Pipeline</h1><p>One slash command kicks off a sequence of specialized AI agents, each catching what the previous pass couldn&#8217;t. Five phases, plus two half-step review passes:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DYQD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DYQD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!DYQD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!DYQD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!DYQD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DYQD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1403031,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.adammiles.ai/i/198372453?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!DYQD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!DYQD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!DYQD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!DYQD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb94323b4-442e-4eb9-8ab3-0226ee3c473f_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Seven-phase pipeline diagram</figcaption></figure></div><div><hr></div><h2>Build</h2><p>An `implementer` agent reads the frozen requirements and builds the components, screens, mocked API endpoints, and a manifest of states (populated, empty, loading, error) for each screen. Between iterations, Playwright drives a real browser to screenshot every screen and state; the orchestrator runs visual sanity checks and spawns fix-up builders when anything renders blank, clips at the edges, or overlaps.</p><h2>Builder self-review</h2><p>A <em>fresh</em> implementer, with no conversation context from the original build (it still reads the code that was just committed), re-reads the requirements, looks at the screenshots, and fixes what the original missed.</p><h2>Domain expert review</h2><p>An agent role-playing as someone who knows the industry and the users critiques the prototype against how real users would actually do this work. The implementer applies the remediation.</p><h2>UX review - two rounds</h2><p>A UX reviewer scores the prototype against a rubric: flow clarity, information hierarchy, discoverability, state transitions, sensible defaults, error recovery. The implementer applies fixes. A second round runs because the first round&#8217;s fixes always introduce new problem, two rounds is the minimum that produces stable UX.</p><h2>UI review</h2><p>A separate agent reviews visual quality against the design system: styles used correctly, spacing consistent, typography on-spec, components matching the library. Fixes applied. Screenshots retaken.</p><h2>UI polish up to three rounds, gated on a quality bar</h2><p>A polish-expert agent, running on a larger model because polish requires judgment, scores every visual aspect on a 5-point scale. The loop only exits when the average is &#8805; 4/5 <strong>and</strong> no individual item scores below 4 <strong>and</strong> all blocking items pass. The rubric is anchored to the design system itself: spacing tokens, type scale, component variants, color usage, the rules already encoded as the team&#8217;s design contract. It&#8217;s not subjective taste-grading; it&#8217;s spec compliance against rules the codebase already enforces.</p><h2>Learnings + commit</h2><p>The orchestrator captures non-obvious discoveries into a `learnings.md` file, then commits the whole prototype to git.</p><p>The result on a typical feature: a fully-reviewed, polish-gated, clickable prototype that would have taken a designer-and-developer team a week or more to produce by hand.</p><div><hr></div><h1>A walked-through example</h1><p>Here&#8217;s an actual run, real numbers from one feature: a record list with an edit form, the kind of thing every product ships dozens of.</p><h5>9:00am &#8212; Requirements session.</h5><p>Engineer + PM. The AI walks through 32 questions, fields on the list, filters, edit-form validation rules, what happens on save, what happens on conflict, who can see what. The PM accepts about 25 of the AI&#8217;s recommendations, overrides 7 (mostly around business-rule edge cases the AI couldn&#8217;t have known). 45 minutes. Decision register saved to disk.</p><blockquote><p>What makes those 32 questions sharper than a normal scoping doc: the AI has read-only access to the local database schema and data. It knows what tables exist, what columns are on them, what naming conventions the project uses. So when it recommends fields, it&#8217;s grounded in <em>what&#8217;s actually there.</em> A recommendation like <em>&#8221;surface the existing `effective_date` column from the appointments table&#8221;</em> is qualitatively different from <em>&#8221;add an effective date field, somehow.&#8221;</em> The prototype never proposes endpoints that would require schema changes nobody wants to make.</p></blockquote><h5>9:50am &#8212; Engineer triggers the pipeline</h5><p><code>`/prototype:02-orchestrate-prototype`</code>. Walks away. Goes to a meeting. Gets coffee.</p><h5>11:20am &#8212; Pipeline finishes</h5><p>Engineer comes back to a Slack notification, a git commit, and a dev server URL. Opens the URL. Five screens. Every screen has populated/empty/loading/error states. The list filters work. The edit form validates. The error state renders correctly when the mocked save endpoint returns a 422. Polish score: 4.3/5, all blocking items passed.</p><h5>1:00pm, team review gate. </h5><p>Engineer + PM + designer in a room, dev-server URL on the shared screen. They click through. About 30 minutes of real use. Three things surface, and none of them are AI mistakes. They&#8217;re decisions that sounded right in the requirements session and now, in front of the working artifact, are obviously the wrong call: an empty-state CTA that prompts the wrong action, a &#8220;save and continue&#8221; button nobody actually wants, an &#8220;effective date&#8221; field that turns out to mean two different things. The kind of thing that used to cost a team weeks because nobody notices until the feature is built. Here, it&#8217;s a comment on a prototype.</p><h5>1:30pm, notes go back into the pipeline. </h5><p>Each change can run as its own one-shot iteration or batch together with others, and the team can cycle through review-and-iterate as many times as the prototype warrants. Simple features land in one pass. Denser or more ambiguous ones go two or three. This team batches and runs one pass. 20 minutes later the prototype is fixed, screenshots retaken, polish bar re-cleared. The &#8220;effective date&#8221; ambiguity gets written into the final requirements freeze as two separate fields.</p><h5>2:00pm, requirements frozen.</h5><p>Engineer runs the next command in the chain. It splits the backend work into right-sized phases against the API contracts the prototype already implied, and a separate orchestration takes over to write the database changes, the endpoints, and the tests. That run takes 30 to 90 minutes.</p><h5>2:40pm, discovery first.</h5><p>Before any scripted testing, the engineer points an exploratory agent at the new feature and lets it loose with no test plan. It works the screen the way a curious new user would: it pokes at every button, field, and menu, tries the odd path nobody specified, and watches for anything that errors or behaves wrong. This pass isn&#8217;t grounded in the requirements on purpose &#8212; it&#8217;s hunting for the problems nobody thought to write a test for. What it finds gets collected into one batch, ranked worst-first. Then it stops and asks. And here the engineer&#8217;s whole job is one decision: skim the list and tick which bugs to fix. That&#8217;s it. From there the agent takes each approved bug, writes the fix, applies it, and then re-runs the exact steps that triggered the bug to prove the fix actually worked &#8212; and only reports back the ones it has confirmed resolved. The human supplies the judgment about <em>what</em> matters; the AI does all of the <em>how</em>, including grading its own work.</p><h5>3:10pm, the grounded test pass.</h5><p>Running discovery first wasn&#8217;t arbitrary. It clears the rubble &#8212; the dead buttons and broken paths &#8212; so that when the grounded pass runs, anything it flags is a <em>real</em> gap against the requirements, not a symptom of some obvious breakage drowning out the signal. Now a second test command goes the other direction: it reads the frozen requirements and writes out the full list of scenarios the feature is supposed to satisfy, then works through most of them on its own: the screen-level checks by driving a real browser, the data-level checks by querying the live database. Where the discovery pass hunted for the unknown, this one confirms the known. Every requirement the team signed off on becomes a concrete, repeatable test that reruns for free from then on. The few scenarios that genuinely need human judgment are flagged as such, and the engineer works through that short list before the feature is called done.</p><p>Maybe 90 minutes of actual human attention across the day. The team walks out with a frozen spec, a clickable prototype that matches it, and a backend implementation already running against the approved contracts.</p><div><hr></div><h1>The contrarian claim: the prototype is the production UI</h1><p>When most teams say &#8220;prototype,&#8221; they mean <em>a throwaway approximation</em>: a Figma mock, a click-through, or at best a coded mock in Storybook. The mock gets approved. Then someone rebuilds it as production code. The build phase is essentially the second time the same UI gets made.</p><p>That&#8217;s not what happens here. <strong>The components I build in the prototype phase are the components that ship to production.</strong> They live inside the application itself, in the same folder structure features ship from, using the same design system tokens production components do. There is no second build. The &#8220;prototype&#8221; label refers to the <em>backend</em> layer: API endpoints are mocked, no database is involved, data shapes are honest but the implementation is disposable. The <em>frontend</em> is production-grade from day one.</p><p>When implementation begins, the diff between &#8220;prototype&#8221; and &#8220;production&#8221; is concentrated in the data layer. A `mockApi.getBookings()` call becomes `api.getBookings()`, returning the same shape the prototype was already rendering. Same component tree. Same styling. Same behavior. The thing the team approved in thtotype review <em>is</em> what ships.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!n4Rj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!n4Rj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!n4Rj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!n4Rj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!n4Rj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!n4Rj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1371950,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.adammiles.ai/i/198372453?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!n4Rj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!n4Rj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!n4Rj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!n4Rj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc30eb10-ce33-4dc1-bf9a-73bcd9d4b440_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Prototype-IS-production-UI diff diagram</figcaption></figure></div><div><hr></div><p>This matters for two reasons:</p><p><strong>1. The 4/5 polish bar is also the production bar.</strong> In the usual flow, prototype polish doesn&#8217;t carry forward, and production has to clear a separate bar under time pressure. When the prototype passes the polish loop here, it&#8217;s not &#8220;good enough for review.&#8221; It&#8217;s &#8220;good enough to ship.&#8221;</p><p><strong>2. There&#8217;s no second design-and-rebuild cycle.</strong>The gap between &#8220;prototype approved&#8221; and &#8220;UI ready for real APIs&#8221; is the time it takes to swap the API layer. Often a single day. Sometimes hours.</p><div><hr></div><h1>Past the prototype: trusting the code AI writes</h1><p>A polished prototype is the easy thing to believe. The hard sell is the backend. Show a skeptical engineer a clean UI and they&#8217;ll grant you the UI. Tell them an AI wrote the migrations, the stored procs, and the endpoints against a database with twenty years of schema behind it, and the trust evaporates, and they&#8217;re right to be cautious. So this is the part that has to earn it, and it earns it two ways.</p><p><strong>The interesting decisions are already made, so the backend is a fill-in, not a design problem. </strong>By the time backend work starts, the approved prototype has already pinned the contracts. The form renders these fields, so the endpoint returns these fields. The list filters on these columns, so the query takes these parameters. Nobody is in a room negotiating what an endpoint should look like, because the prototype the team signed off on already answered that &#8212; in a shape grounded in real schema from the very first requirements question. What&#8217;s left isn&#8217;t the creative part of backend work; it&#8217;s the mechanical translation of a settled contract into migrations, procs, and endpoints. That&#8217;s exactly the kind of constrained, well-specified work an orchestration of agents is good at, and exactly why it can run unattended in under 90 minutes.</p><p><strong>You don&#8217;t trust the output by reading every line. You trust it because of how it&#8217;s verified. </strong>This is the real answer to the skeptic. The two test passes pull in opposite directions on purpose: the requirements-blind discovery pass proves the feature doesn&#8217;t break in the ways nobody anticipated, and the grounded pass proves it does everything the team explicitly asked for. What survives both isn&#8217;t &#8220;code an AI wrote and a human skimmed.&#8221; It&#8217;s code measured against the requirements and the real world, and every one of those checks becomes a permanent, replayable test that re-runs for free on the next change.</p><p>That&#8217;s the whole trust argument in one line: the contracts make the backend cheap to build, and the two-sided verification makes it safe to ship &#8212; without anyone pretending they read every generated line and understood it.</p><h1>What this changes about how you work</h1><h2>Who does what in the new flow</h2><p>Once the artifact is cheap and the polish bar is the ship bar, the human work changes shape. The design-phase roles become foreman work, not trade work: PM, engineer, and stakeholder all shift from <em>producing</em> the design artifact to <em>steering</em> the one the AI produces. Expertise gets applied to a working artifact instead of an imagined one:</p><p><strong>Engineer:</strong> owns the requirements pass with the PM, triggers the orchestrator, shepherds the prototype to the review gate. A workday to first prototype in place of multi-week revise-and-rebuild cycles. More features designed per quarter.</p><p><strong>PM:</strong> drives the requirements conversation directly, making the high-judgment calls (business rules, edge cases, what the customer actually needs) instead of authoring a long-form spec that gets reinterpreted downstream. Their judgment lands on the artifact the team approves.</p><p><strong>Stakeholders:</strong> click through the deployed prototype the same way they would click through a shipped feature. Feedback grounded in actual use, not in imagining what a mockup might feel like.</p><p>Teams with a dedicated designer plug them into the human review gate: applying taste to a working prototype, directing the next iteration, catching the emotional-resonance and cultural-fit calls that a checklist-based AI review won&#8217;t. Same roles, same names, more time on the work that needed their judgment.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IsCm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IsCm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!IsCm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!IsCm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!IsCm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IsCm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1481809,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.adammiles.ai/i/198372453?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IsCm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!IsCm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!IsCm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!IsCm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faad4bb54-f27d-470f-853e-f55e3d50d6af_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Redistributed roles</figcaption></figure></div><div><hr></div><h2>The order of operations flips</h2><p>Roles aren&#8217;t the only thing that rearranges. The <em>sequence</em> of decisions does too. Three categories that used to happen <em>before</em> the prototype now happen <em>in front of it:</em></p><ul><li><p><strong>Requirements</strong> get a first pass before the prototype, enough to give the build agent something to work from, then freeze <em>after</em> the team has clicked through and surfaced the real gaps. <em>&#8221;That flow doesn&#8217;t make sense; this field should have been on the other screen; what happens when a user does X-then-Y, we never thought about that.&#8221;</em> The prototype isn&#8217;t a downstream artifact of requirements. It&#8217;s a tool that produces better requirements.</p></li><li><p><strong>UX</strong> is exempt from the requirements phase entirely. No modal-vs-drawer debates upstream of the artifact. By the time the prototype reaches the team they&#8217;re reacting to a <em>thing</em>, not debating an i<em>dea</em>.</p></li><li><p><strong>API shape </strong>comes out of the components the AI builds, not the other way around. By the time the backend orchestration kicks off, the contracts are already pinned, and a separate set of AI agents implements them.</p></li></ul><p>The pattern across all three: judgment used to be applied to the imagined version of the thing. Now it&#8217;s applied to the working one.</p><div><hr></div><h1>The honest trade-offs</h1><p>Compressing a whole feature into a day has real costs. The ones worth flagging:</p><ul><li><p><strong>The UX-reviewer has limits.</strong> Emotional resonance, cultural sensitivity, accessibility nuances the checklist doesn&#8217;t catch: these require human review. The human review gate is where those get caught. Don&#8217;t skip it.</p></li><li><p><strong>The prototype is only as good as the requirements.</strong> The requirements command walks the team through structured questions and doesn&#8217;t move on until each one has a concrete answer. The team&#8217;s job is showing up and answering questions, not authoring a 40-page PRD.</p></li><li><p><strong>The workday timeline assumes scaffolding is in place.</strong> If you&#8217;re starting from scratch (no orchestrator, no review checklists, no design-system tokens, no requirements pipeline), that&#8217;s a few days of work before the first prototype lands in a day.</p></li><li><p><strong>This works best for features that fit common patterns, which is most of them.</strong> Booking screens, record lists, edit forms, multi-step wizards: probably 95% of the features any product needs to ship are well-understood patterns, and the pipeline produces strong output on every one of them. The remaining 5% (genuinely novel interactions: multi-touch gestures, real-time collaboration, anything without a category prior) require more human steering during the review rounds.</p></li></ul><div><hr></div><h1>What I&#8217;d tell a team thinking about this</h1><p>Three things hold up across every team I&#8217;ve watched try this:</p><ul><li><p><strong>The AI needs explicit acceptance criteria, or it grades on vibes.</strong> Vague review prompts produce vague reviews. Specific criteria (spacing tokens, type scale, empty-state coverage, error-recovery flows) produce specific, actionable ones. Build the criteria first. The rest of the pipeline is in service of them.</p></li><li><p><strong>Teams who skip the human review break. </strong>Between 15 and 40 percent of features hit a &#8220;wait, that&#8217;s not quite right&#8221; moment at the gate, and those moments almost always surface a missed assumption in the requirements. The AI produces a strong default; the human&#8217;s job is the editing pass that turns the default into the right answer.</p></li><li><p><strong>Don&#8217;t make the prototype pipeline handle everything. </strong>It&#8217;s a single-feature tool, not a system-design tool. Cross-feature flows, multi-screen state machines, third-party integrations: those still need real design work upstream.</p></li></ul><div><hr></div><p><em>I&#8217;m Adam Miles. 25 years of shipping software, including the messy brownfield kind. I write about using AI to move real codebases forward: legacy, greenfield, and the awkward middle.</em></p><p></p>]]></content:encoded></item></channel></rss>