<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: vibecodiq</title>
    <description>The latest articles on DEV Community by vibecodiq (@vibecodiq).</description>
    <link>https://dev.to/vibecodiq</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3593028%2F6ec31d08-44c0-4396-8d5e-eee32dbc9910.png</url>
      <title>DEV Community: vibecodiq</title>
      <link>https://dev.to/vibecodiq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vibecodiq"/>
    <language>en</language>
    <item>
      <title>Delivery Slowdown in AI-Generated Codebases — Why Every Sprint Takes Longer Than the Last</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Fri, 10 Apr 2026 16:15:12 +0000</pubDate>
      <link>https://dev.to/vibecodiq/delivery-slowdown-in-ai-generated-codebases-why-every-sprint-takes-longer-than-the-last-4im3</link>
      <guid>https://dev.to/vibecodiq/delivery-slowdown-in-ai-generated-codebases-why-every-sprint-takes-longer-than-the-last-4im3</guid>
      <description>&lt;p&gt;"Six months ago, we shipped features in two days. Now a single change takes two weeks."&lt;/p&gt;

&lt;p&gt;If you've built an application with AI tools — Cursor, Lovable, Bolt.new, Replit, v0 — and you're past the first few months of development, there's a good chance your delivery speed has declined. Not gradually. Sharply.&lt;/p&gt;

&lt;p&gt;This is not a team problem. It's a structural one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mechanism: Verification Debt
&lt;/h2&gt;

&lt;p&gt;Every AI session optimizes for the immediate task. "Fix the checkout bug" — the fix goes where the symptom is. "Add email notification on purchase" — added inline in the payment handler.&lt;/p&gt;

&lt;p&gt;Each session is locally correct. But none of them maintain awareness of the broader codebase structure.&lt;/p&gt;

&lt;p&gt;The result: files that started as single-purpose now handle multiple concerns. Business logic scattered across layers. A dependency graph where everything is connected to everything.&lt;/p&gt;

&lt;p&gt;This creates &lt;strong&gt;verification debt&lt;/strong&gt; — the growing cost of verifying that a change doesn't break something unexpected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VERIFICATION DEBT COMPOUND CURVE

  Time per feature (days)
  |
  10|                                    *  *
   8|                               *
   6|                          *
   5|                     *
   4|                *
   3|           *
   2|      *
   1|  *
   0+--+--+--+--+--+--+--+--+--+--+--+-
    M1 M2 M3 M4 M5 M6 M7 M8 M9 M10

  Each new feature adds coupling.
  Each coupling point adds verification overhead
  to every future change.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why It Compounds
&lt;/h2&gt;

&lt;p&gt;The compound rate is approximately 30-40% per quarter in structurally uncoupled codebases. Here's why:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Month 1-3:&lt;/strong&gt; Small codebase. Blast radius is obvious. One developer ships independently. Features take 1-2 days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Month 4-6:&lt;/strong&gt; Codebase has grown. Files are shared across features. Every change requires checking what else it affects. PR review time doubles because reviewers can't predict side effects. Features take 3-5 days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Month 7-9:&lt;/strong&gt; Team grows to handle the backlog. But more developers in a coupled codebase doesn't create parallelism — it creates coordination overhead. Two developers modify the same 600-line utility file in the same sprint. Merge conflicts. Re-reviews. Features take 5-10 days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Month 10+:&lt;/strong&gt; The team has doubled. Total output has dropped. 40% of developer time goes to merge conflicts, coordination meetings, and verifying side effects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. File churn concentration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"30 days ago"&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%H"&lt;/span&gt; | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read hash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;git diff-tree &lt;span class="nt"&gt;--no-commit-id&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nv"&gt;$hash&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the same files appear in every commit, your codebase is structurally coupled. Changes can't be isolated because domain boundaries don't exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Coupling density
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"30 days ago"&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%H"&lt;/span&gt; | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read hash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;git diff-tree &lt;span class="nt"&gt;--no-commit-id&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nv"&gt;$hash&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{sum+=$1; n++} END {print "Avg files per commit:", sum/n}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Healthy: 2-4 files per commit (changes stay within one domain).&lt;br&gt;
Warning: 5-8 files (cross-domain coupling).&lt;br&gt;
Critical: 8+ files (no structural boundaries exist).&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Verification bottleneck files
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find src/ &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; | xargs &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'$1 &amp;gt; 300 {print}'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Files above 300 lines are verification bottlenecks. Every change to a large file requires reviewing the entire file because the internal blast radius is the whole file.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. PR review time trend
&lt;/h3&gt;

&lt;p&gt;If you use GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;list &lt;span class="nt"&gt;--state&lt;/span&gt; merged &lt;span class="nt"&gt;--limit&lt;/span&gt; 50 &lt;span class="nt"&gt;--json&lt;/span&gt; createdAt,mergedAt | &lt;span class="se"&gt;\&lt;/span&gt;
  jq &lt;span class="s1"&gt;'.[] | {days: (((.mergedAt | fromdateiso8601) - (.createdAt | fromdateiso8601)) / 86400)}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare the average from your first 25 merged PRs vs your last 25. If review time has increased significantly, verification debt is compounding.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Myth: "We Just Need More Developers"
&lt;/h2&gt;

&lt;p&gt;Adding developers to a structurally coupled codebase makes delivery slower, not faster. Each new developer adds coordination overhead without reducing verification debt.&lt;/p&gt;

&lt;p&gt;The research confirms it: PR review times in AI-generated codebases increase by 91% between month 3 and month 9. The cause is not team size — it's structural coupling.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Structural Fix
&lt;/h2&gt;

&lt;p&gt;The fix is not process improvement, better planning, or more standups. It's structural:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bounded domain isolation&lt;/strong&gt; — each business domain owns its files. Cross-domain imports are forbidden by automated rules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enforced import boundaries&lt;/strong&gt; — a boundary linter prevents one domain from reaching into another. Violations are caught before merge, not after.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Known blast radius&lt;/strong&gt; — when domains are isolated, every change has a predictable scope. PR reviews become fast because the reviewer knows exactly what could be affected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parallel delivery&lt;/strong&gt; — isolated domains mean developers work independently. No merge conflicts on shared files. No coordination meetings about who's touching what.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal: delivery time stays flat as the codebase grows. Not because of better developers — because of better structure.&lt;/p&gt;

&lt;p&gt;Based on &lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA (Atomic Slice Architecture)&lt;/a&gt; — an open architecture standard for AI-generated software that enforces these boundaries automatically.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbpk1oh0sym4grr2g267t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbpk1oh0sym4grr2g267t.jpg" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Architecture Drift in AI-Generated Codebases — How Clean Layers Dissolve One Prompt at a Time</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Fri, 03 Apr 2026 16:58:21 +0000</pubDate>
      <link>https://dev.to/vibecodiq/architecture-drift-in-ai-generated-codebases-how-clean-layers-dissolve-one-prompt-at-a-time-58ih</link>
      <guid>https://dev.to/vibecodiq/architecture-drift-in-ai-generated-codebases-how-clean-layers-dissolve-one-prompt-at-a-time-58ih</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkcx00o5qmi4am0h3uvq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkcx00o5qmi4am0h3uvq.jpg" alt=" " width="800" height="419"&gt;&lt;/a&gt;"The architecture changed. Nobody decided it should."&lt;/p&gt;

&lt;p&gt;Architecture drift is the #1 root cause of structural failure in AI-generated codebases. It happens silently, one prompt at a time, and by the time it's visible, the cost of fixing it has compounded significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mechanism
&lt;/h2&gt;

&lt;p&gt;Each AI session optimizes for the immediate task without maintaining awareness of the broader architecture.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BOUNDARY EROSION TIMELINE

  Month 1:  API --&amp;gt; Business --&amp;gt; Data
            (clean layers, clear direction)

  Month 4:  API &amp;lt;-&amp;gt; Business &amp;lt;-&amp;gt; Data
            (boundaries crossed, bidirectional)

  Month 8:  API &amp;lt;-&amp;gt; Business &amp;lt;-&amp;gt; Data
              \      |  X  |      /
               \---&amp;gt; UI &amp;lt;---/
            (boundaries dissolved, spaghetti)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Session 1: "Create a user service" — clean module with clear boundaries.&lt;br&gt;
Session 15: "Fix the checkout bug" — fix goes in the route handler because that's where the symptom is.&lt;br&gt;
Session 30: "Add email on purchase" — notification logic added inline in the payment handler.&lt;br&gt;
Session 50: Business logic lives in 5 layers. Nobody can draw the architecture from memory.&lt;/p&gt;
&lt;h2&gt;
  
  
  Detection
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Layer Violation Check
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Database queries in UI components (should be 0)&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"prisma&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;supabase&lt;/span&gt;&lt;span class="se"&gt;\|\.&lt;/span&gt;&lt;span class="s2"&gt;from("&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/components/ src/app/ | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;

&lt;span class="c"&gt;# Business logic in route handlers (should be minimal)&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"if.*price&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;calculate&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;validate"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; src/app/api/ | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Import Direction Analysis
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Files with the most imports (potential boundary violators)&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"import.*from"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/ | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;: &lt;span class="s1"&gt;'{print $1}'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In a clean architecture, import counts should be low and directional (API imports Business, Business imports Data, never the reverse).&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Business Logic Scattering
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Where does "payment" logic live?&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rln&lt;/span&gt; &lt;span class="s2"&gt;"payment&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;stripe&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;checkout&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;price"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/ | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;/ &lt;span class="s1"&gt;'{print $1"/"$2}'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If a single business concept appears in 4+ directories, the architecture has drifted.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Convention Drift
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check for inconsistent patterns&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"export default function&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;export function&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;export const"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/ | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;: &lt;span class="s1"&gt;'{print $3}'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Multiple export patterns suggest the AI changed conventions mid-project.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Compounding Cost
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feature delivery cost over time:

  Month 1:  2 days   (clean architecture)
  Month 4:  4 days   (50% archaeology)
  Month 8:  8 days   (75% archaeology)
  Month 12: 12+ days (mostly archaeology)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For a 3-person team at $150/hour, the velocity difference between month 1 and month 8 represents ~$36,000/month in wasted capacity.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Sprints Don't Fix This
&lt;/h2&gt;

&lt;p&gt;Architecture drift is a compound structural condition. Sprints are time-boxed delivery cycles. They operate at different scales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sprint: "Fix this module" — fixes surface symptoms&lt;/li&gt;
&lt;li&gt;Structural intervention: "Re-establish all boundaries" — fixes root cause&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without enforcement, the next sprint re-introduces the same violations.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Structural Fix
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1: Map Current State
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate dependency graph&lt;/span&gt;
npx madge &lt;span class="nt"&gt;--image&lt;/span&gt; graph.svg &lt;span class="nt"&gt;--extensions&lt;/span&gt; ts,tsx src/

&lt;span class="c"&gt;# List all circular dependencies&lt;/span&gt;
npx madge &lt;span class="nt"&gt;--circular&lt;/span&gt; &lt;span class="nt"&gt;--extensions&lt;/span&gt; ts,tsx src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 2: Define Target Architecture
&lt;/h3&gt;

&lt;p&gt;Document the intended layer structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  app/           # Routing only (Next.js pages/API routes)
  modules/       # Business logic (one module per domain)
    auth/
    payments/
    users/
    notifications/
  shared/        # Cross-cutting utilities
    types/
    utils/
    lib/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rule: &lt;code&gt;app/&lt;/code&gt; imports &lt;code&gt;modules/&lt;/code&gt;. &lt;code&gt;modules/&lt;/code&gt; imports &lt;code&gt;shared/&lt;/code&gt;. Never the reverse.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Migrate Incrementally
&lt;/h3&gt;

&lt;p&gt;For each layer violation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify the misplaced logic&lt;/li&gt;
&lt;li&gt;Create the correct target module&lt;/li&gt;
&lt;li&gt;Move the logic&lt;/li&gt;
&lt;li&gt;Update imports&lt;/li&gt;
&lt;li&gt;Verify no regressions&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 4: Enforce Boundaries
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// eslint.config.js — import boundary enforcement&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import/no-restricted-paths&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;zones&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="c1"&gt;// modules/ cannot import from app/&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/modules&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="c1"&gt;// shared/ cannot import from modules/ or app/&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/shared&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/modules&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/shared&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: CI/CD Enforcement
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/architecture.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Architecture Check&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;check&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Circular dependency check&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx madge --circular --extensions ts,tsx src/ &amp;amp;&amp;amp; echo "PASS" || (echo "FAIL&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;circular deps" &amp;amp;&amp;amp; exit 1)&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lint (includes boundary rules)&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run lint&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;After structural intervention + enforcement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Layer violations: blocked at CI&lt;/li&gt;
&lt;li&gt;Circular dependencies: prevented&lt;/li&gt;
&lt;li&gt;Business logic: centralized in domain modules&lt;/li&gt;
&lt;li&gt;Feature delivery: predictable again (back to ~2 days for standard features)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Architecture drift is the root cause. Boundary enforcement is the structural fix.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is part of the &lt;a href="https://vibecodiq.com/ai-chaos" rel="noopener noreferrer"&gt;AI Chaos&lt;/a&gt; series — a structural analysis of failure patterns in AI-generated codebases. Based on &lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA (Atomic Slice Architecture)&lt;/a&gt; — an open architecture standard for AI-generated software.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA Standard&lt;/a&gt; — the open specification&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/janvoldan/asa-standard" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; — source, examples, documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vibecodiq.com" rel="noopener noreferrer"&gt;Vibecodiq&lt;/a&gt; — structural diagnostics for AI-built apps&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Regression Fear in AI-Generated Codebases — Why Every PR Feels Like a Gamble</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Sat, 28 Mar 2026 09:31:35 +0000</pubDate>
      <link>https://dev.to/vibecodiq/regression-fear-in-ai-generated-codebases-why-every-pr-feels-like-a-gamble-4cok</link>
      <guid>https://dev.to/vibecodiq/regression-fear-in-ai-generated-codebases-why-every-pr-feels-like-a-gamble-4cok</guid>
      <description>&lt;p&gt;"Every PR is a gamble. We just don't know what it'll break."&lt;/p&gt;

&lt;p&gt;If your team has stopped merging on Fridays — or Thursdays — you're experiencing regression fear. Not a psychological problem. A structural one.&lt;/p&gt;

&lt;p&gt;This post explains the mechanism, how to measure it, and the fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mechanism: Unbounded Blast Radius
&lt;/h2&gt;

&lt;p&gt;In a well-structured codebase, a change in module A affects module A and its direct dependents. The blast radius is bounded and predictable.&lt;/p&gt;

&lt;p&gt;In most AI-generated codebases past month 3, the blast radius is unbounded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BLAST RADIUS MAP

  Change: update pricing display

  PREDICTED impact:        ACTUAL impact:
  pricing/ui.tsx           pricing/ui.tsx
                           payments/checkout.ts
                           users/dashboard.tsx
                           notifications/email.ts

  predicted: 1 file        actual: 4 files
  blast radius: unbounded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mechanism: AI generates code that works by taking the shortest path. That shortest path often creates implicit dependencies — shared state, cross-module imports, business logic in unexpected places. Each implicit dependency extends the blast radius of every future change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detection: Three Measurements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Regression Ratio
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Total commits in last 30 days&lt;/span&gt;
&lt;span class="nv"&gt;TOTAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"30 days ago"&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Fix/revert commits&lt;/span&gt;
&lt;span class="nv"&gt;FIXES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"30 days ago"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--grep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"fix&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;revert&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;hotfix&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;broken&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;rollback"&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Regression ratio: &lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt; FIXES &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; TOTAL &lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What the number means:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;0-10%&lt;/strong&gt;: Normal. Minor regressions caught early.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10-20%&lt;/strong&gt;: Warning. Coupling is growing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;20%+&lt;/strong&gt;: Critical. One in five commits fixes something a previous commit broke.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Cursed Files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"90 days ago"&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format: &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the files that appear in the most commits. In AI-generated codebases, the top 3 files are usually:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The largest files (500+ lines, multiple domains)&lt;/li&gt;
&lt;li&gt;The files where regressions originate&lt;/li&gt;
&lt;li&gt;The files nobody wants to touch&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Merge Velocity Trend
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Commits per week for last 12 weeks&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;seq &lt;/span&gt;0 11&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;START&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;i+1&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt; weeks ago"&lt;/span&gt; +%Y-%m-%d&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;END&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt; weeks ago"&lt;/span&gt; +%Y-%m-%d&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$START&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--until&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$END&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Week -&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="nv"&gt;$COUNT&lt;/span&gt;&lt;span class="s2"&gt; commits"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A declining trend means the team is merging less frequently — not because they're doing less work, but because each merge is riskier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "More QA" Doesn't Fix This
&lt;/h2&gt;

&lt;p&gt;QA catches regressions after they happen. It does not prevent the architectural condition that causes them.&lt;/p&gt;

&lt;p&gt;The regression cycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Developer ships change. Passes unit tests.&lt;/li&gt;
&lt;li&gt;QA finds regression in unrelated area. Files bug.&lt;/li&gt;
&lt;li&gt;Developer context-switches back. Debugs for hours.&lt;/li&gt;
&lt;li&gt;Fix introduces new side effect. Cycle repeats.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Adding more QA people makes the cycle faster — not shorter. The root cause remains: unbounded blast radius.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cost
&lt;/h2&gt;

&lt;p&gt;A team of three developers at $150/hour loaded:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;30% of features cause regressions = 2.4/month&lt;/li&gt;
&lt;li&gt;6 hours average to find, diagnose, fix each&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$2,160/month = $25,920/year&lt;/strong&gt; in regression costs alone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus velocity decay:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Month 3:  8 features/month (productive)
Month 6:  5 features/month (fear + overhead)
Month 9:  3 features/month (regression management dominates)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Structural Fix: Bounded Blast Radius
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Identify Cursed Files
&lt;/h3&gt;

&lt;p&gt;Run the cursed files detection above. The top 3 files are your decomposition targets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Map Implicit Dependencies
&lt;/h3&gt;

&lt;p&gt;For each cursed file, trace what depends on it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find all files that import from the cursed file&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rln&lt;/span&gt; &lt;span class="s2"&gt;"from.*cursedFile&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;require.*cursedFile"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Decompose by Domain
&lt;/h3&gt;

&lt;p&gt;Split cursed files by business domain. Each new file has one responsibility and explicit imports.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Enforce One-Directional Dependencies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify no circular dependencies exist&lt;/span&gt;
npx madge &lt;span class="nt"&gt;--circular&lt;/span&gt; &lt;span class="nt"&gt;--extensions&lt;/span&gt; ts,tsx src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After decomposition, the dependency graph should be a tree, not a web.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Add Regression Tests for Boundaries
&lt;/h3&gt;

&lt;p&gt;For each module boundary, add a test that verifies the contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Test that pricing module doesn't depend on notification module&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getPrice&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/modules/pricing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getPrice returns number without side effects&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getPrice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monthly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// No notifications sent, no user state changed&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: CI/CD Enforcement
&lt;/h3&gt;

&lt;p&gt;Block merges that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduce circular dependencies&lt;/li&gt;
&lt;li&gt;Exceed file size thresholds&lt;/li&gt;
&lt;li&gt;Miss test coverage on boundary contracts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;After structural enforcement, the blast radius of every change is bounded and predictable. QA becomes verification — confirming bounded changes work as expected — not discovery of unrelated breakage.&lt;/p&gt;

&lt;p&gt;Regression fear disappears. Not because the team is braver. Because the architecture makes cross-module leakage structurally impossible.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is part of the &lt;a href="https://vibecodiq.com/ai-chaos" rel="noopener noreferrer"&gt;AI Chaos&lt;/a&gt; series — a structural analysis of failure patterns in AI-generated codebases. Based on &lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA (Atomic Slice Architecture)&lt;/a&gt; — an open architecture standard for AI-generated software.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA Standard&lt;/a&gt; — the open specification&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/janvoldan/asa-standard" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; — source, examples, documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vibecodiq.com" rel="noopener noreferrer"&gt;Vibecodiq&lt;/a&gt; — structural diagnostics for AI-built apps
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5qwj0bwtgtdij84w7li.jpg" alt=" " width="800" height="418"&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>softwareengineering</category>
      <category>testing</category>
    </item>
    <item>
      <title>Hidden Technical Debt in AI-Generated Codebases — Why Working Code Gets Expensive to Change</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Fri, 20 Mar 2026 18:27:11 +0000</pubDate>
      <link>https://dev.to/vibecodiq/hidden-technical-debt-in-ai-generated-codebases-why-working-code-gets-expensive-to-change-454</link>
      <guid>https://dev.to/vibecodiq/hidden-technical-debt-in-ai-generated-codebases-why-working-code-gets-expensive-to-change-454</guid>
      <description>&lt;p&gt;"It worked fine for six months. Then every change became expensive."&lt;/p&gt;

&lt;p&gt;Your AI-generated app is live. Customers are paying. The dashboard looks fine. But every feature takes 2-3x longer than it should, and nobody can explain why.&lt;/p&gt;

&lt;p&gt;This post explains what hidden technical debt looks like in AI-generated codebases, how to detect it, and the structural decomposition that fixes it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes AI-Generated Debt "Hidden"
&lt;/h2&gt;

&lt;p&gt;Traditional technical debt is visible — you know you're cutting corners. AI-generated technical debt is invisible — the shortcuts happen at generation time and nobody notices.&lt;/p&gt;

&lt;p&gt;Here's the mechanism:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Session 1:  User service created (clean, 80 lines)
Session 15: Pricing logic added to user service ("it needs user data")
Session 30: Notification logic added to pricing flow ("notify on purchase")
Session 45: User service is now 600 lines, handles 4 domains
Session 60: "Why does adding a referral system take 3 weeks?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each session makes a locally reasonable decision. The AI puts code where the context is closest. Nobody checks whether the global architecture remains coherent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DOMAIN SCATTERING MAP

  userService.ts (620 lines)
    - user logic         ████████░░  40%
    - pricing logic      ████░░░░░░  20%
    - notifications      ███░░░░░░░  15%
    - audit logging      ███░░░░░░░  15%
    - shared state       ██░░░░░░░░  10%

  AFTER DECOMPOSITION:
    users/userService.ts          (120 lines)
    pricing/priceCalculator.ts    (90 lines)
    notifications/notifier.ts     (70 lines)
    billing/auditLogger.ts        (60 lines)

  1 file x 5 domains --&amp;gt; 4 files x 1 domain each
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Detection: Three Measurements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. File Size Distribution
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find src &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; | xargs &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What to look for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files over 500 lines = almost certainly multi-domain&lt;/li&gt;
&lt;li&gt;Files over 800 lines = critical structural risk&lt;/li&gt;
&lt;li&gt;If your top 10 files average over 400 lines, the architecture has drifted&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Domain Scattering
&lt;/h3&gt;

&lt;p&gt;Pick a core business concept (e.g., "pricing"). Count how many files contain it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rln&lt;/span&gt; &lt;span class="s2"&gt;"price&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;pricing&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;amount&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;cost&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;subscription&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;billing"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/ | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What the number means:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1-3 files: Clean. Pricing logic is centralized.&lt;/li&gt;
&lt;li&gt;4-7 files: Warning. Logic is scattering.&lt;/li&gt;
&lt;li&gt;8+ files: Critical. Pricing decisions happen everywhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Shared Mutable State
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Count module-level mutable variables&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"^let &lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;^var &lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;export let&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;export var"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/ | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each one is a hidden coupling point. A change in one function silently affects every other function that reads or writes the same variable.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Feature Estimate Accuracy
&lt;/h3&gt;

&lt;p&gt;Look at your last 10 features or bug fixes. Calculate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;accuracy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actual_time&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;estimated_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the average is above 2.0, the architecture is fighting you. Hidden dependencies are making scope unpredictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "Refactor Later" Doesn't Work
&lt;/h2&gt;

&lt;p&gt;Technical debt has interest rates. AI-generated codebases have higher interest rates because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shortcuts are invisible.&lt;/strong&gt; Nobody chose to put pricing logic in the user service. The AI did it because that's where the context was.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Coupling compounds.&lt;/strong&gt; Every feature added on top of a coupled module increases the coupling. By month 6, you can't change pricing without touching users, notifications, and payments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The window closes.&lt;/strong&gt; Refactoring in month 3 is a focused sprint. Refactoring in month 9 is a rewrite. The complexity grows faster than capacity.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Month 3:  Refactoring cost = 2-3 days
Month 6:  Refactoring cost = 2-3 weeks
Month 9:  Refactoring cost = "we need to rewrite"
Month 12: "We're stuck"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Structural Fix: Decomposition + Enforcement
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Domain Audit
&lt;/h3&gt;

&lt;p&gt;Map every file to its primary business domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a domain map&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;file &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;find src &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.tsx"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-5&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'import.*from'&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-3&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Identify files that serve multiple domains (these are the decomposition targets).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Extract Domain Modules
&lt;/h3&gt;

&lt;p&gt;For each multi-domain file:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify the distinct responsibilities&lt;/li&gt;
&lt;li&gt;Create separate module files for each domain&lt;/li&gt;
&lt;li&gt;Move logic to the appropriate module&lt;/li&gt;
&lt;li&gt;Update imports
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// BEFORE: src/services/userService.ts (600 lines, 4 domains)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;    &lt;span class="c1"&gt;// pricing domain&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="c1"&gt;// notification domain&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateInvoice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// billing domain&lt;/span&gt;

&lt;span class="c1"&gt;// AFTER: 4 focused modules&lt;/span&gt;
&lt;span class="c1"&gt;// src/modules/users/userService.ts&lt;/span&gt;
&lt;span class="c1"&gt;// src/modules/pricing/priceCalculator.ts&lt;/span&gt;
&lt;span class="c1"&gt;// src/modules/notifications/notificationService.ts&lt;/span&gt;
&lt;span class="c1"&gt;// src/modules/billing/invoiceGenerator.ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Eliminate Shared Mutable State
&lt;/h3&gt;

&lt;p&gt;Replace module-level mutable variables with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function parameters (explicit data flow)&lt;/li&gt;
&lt;li&gt;Immutable state containers&lt;/li&gt;
&lt;li&gt;Event-based communication between modules
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// BEFORE: shared mutable state&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPrice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// hidden dependency&lt;/span&gt;

&lt;span class="c1"&gt;// AFTER: explicit data flow&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Enforce Boundaries
&lt;/h3&gt;

&lt;p&gt;Add automated checks that prevent re-coupling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;script&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"check:boundaries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx madge --circular --extensions ts,tsx src/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"check:size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"find src -name '*.ts' | xargs wc -l | awk '$1 &amp;gt; 500 {print &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;WARN:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, $0}'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"precommit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run check:boundaries &amp;amp;&amp;amp; npm run check:size"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Monitor Trend
&lt;/h3&gt;

&lt;p&gt;Track these metrics weekly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Number of files over 500 lines (should decrease or stay flat)&lt;/li&gt;
&lt;li&gt;Number of circular dependencies (should be 0)&lt;/li&gt;
&lt;li&gt;Feature estimate accuracy (should improve toward 1.0-1.5x)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;After structural decomposition, the cost of change becomes predictable. Adding a referral system touches the referral module — not pricing, users, notifications, and billing. Feature estimates become accurate because scope is bounded.&lt;/p&gt;

&lt;p&gt;Hidden technical debt doesn't require a rewrite. It requires structural decomposition and ongoing enforcement.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is part of the &lt;a href="https://vibecodiq.com/ai-chaos" rel="noopener noreferrer"&gt;AI Chaos&lt;/a&gt; series — a structural analysis of failure patterns in AI-generated codebases. Based on &lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA (Atomic Slice Architecture)&lt;/a&gt; — an open architecture standard for AI-generated software.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA Standard&lt;/a&gt; — the open specification&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/janvoldan/asa-standard" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; — source, examples, documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vibecodiq.com" rel="noopener noreferrer"&gt;Vibecodiq&lt;/a&gt; — structural diagnostics for AI-built apps
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsr6nr4h6bklq3vir5cxo.jpg" alt=" "&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>technicaldebt</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Security Debt in AI-Generated Codebases — A Structural Problem, Not a Tooling Problem</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Fri, 13 Mar 2026 15:54:46 +0000</pubDate>
      <link>https://dev.to/vibecodiq/security-debt-in-ai-generated-codebases-a-structural-problem-not-a-tooling-problem-6jp</link>
      <guid>https://dev.to/vibecodiq/security-debt-in-ai-generated-codebases-a-structural-problem-not-a-tooling-problem-6jp</guid>
      <description>&lt;p&gt;"We passed the security review. Six weeks later, we found auth bypasses in three endpoints."&lt;/p&gt;

&lt;p&gt;Research shows 45% of AI-generated code contains security vulnerabilities. Not because AI is malicious — because security is a system-level property, and AI generates code at the function level.&lt;/p&gt;

&lt;p&gt;This post breaks down the structural mechanism behind security debt in AI-generated codebases, how to detect it, and the enforcement model that prevents it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Structural Mechanism
&lt;/h2&gt;

&lt;p&gt;AI produces code that works. "Works" means it handles expected input correctly. It does not mean it handles unexpected input safely.&lt;/p&gt;

&lt;p&gt;Authentication, authorization, input validation — these are constraints that must be enforced globally, not function by function.&lt;/p&gt;

&lt;p&gt;Here's what happens in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Session 1:  Auth middleware created for /api/users
Session 12: New route /api/billing added — no auth middleware applied
Session 25: Frontend validation added — backend accepts raw input
Session 38: API key hardcoded in utils/stripe.ts for "quick fix"
Session 50: Three unprotected endpoints, no input validation on backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each session solves the immediate problem. Nobody checks whether the global security constraints are maintained.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ROUTE COVERAGE MAP

  /api/users       [AUTH]  protected
  /api/billing     [AUTH]  protected
  /api/webhooks    [    ]  UNPROTECTED
  /api/reports     [    ]  UNPROTECTED
  /api/admin       [AUTH]  protected
  /api/export      [    ]  UNPROTECTED
  /api/settings    [    ]  UNPROTECTED

  coverage: 3/7 routes = 43%
  structural gap: 4 unprotected endpoints
  attack surface: growing with every AI session
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Detection Scripts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Security-Related TODOs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"TODO&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;FIXME&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;HACK"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/ &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"auth&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;token&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;valid&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;secur&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;api.key&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;secret"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are security decisions the AI deferred. Each one is a structural gap.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Auth Middleware Coverage
&lt;/h3&gt;

&lt;p&gt;Count your routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"router&lt;/span&gt;&lt;span class="se"&gt;\.\|&lt;/span&gt;&lt;span class="s2"&gt;app&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;get&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;app&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;app&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;put&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;app&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;delete&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;export.*GET&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;export.*POST&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;export.*PUT&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;export.*DELETE"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/ | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Count your auth references:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"middleware&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;protect&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;auth&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;guard&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;requireAuth&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;withAuth"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/ | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If routes significantly exceed auth references, some endpoints are unprotected.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Hardcoded Secrets
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"sk_live&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;sk_test&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;api_key&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;apiKey&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;secret&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.env*"&lt;/span&gt; src/ &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"node_modules&lt;/span&gt;&lt;span class="se"&gt;\|\.&lt;/span&gt;&lt;span class="s2"&gt;env&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;example"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any match outside &lt;code&gt;.env&lt;/code&gt; files is a structural vulnerability.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Frontend-Only Validation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find validation in frontend components&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"required&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;pattern=&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;minLength&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;maxLength&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;validate"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; src/components/ src/app/ | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;

&lt;span class="c"&gt;# Find validation in API routes/handlers&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"zod&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;yup&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;joi&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;validate&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;sanitize&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;escape"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; src/api/ src/server/ src/lib/ | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If frontend validation count &amp;gt;&amp;gt; backend validation count, input reaches the server unvalidated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "Better Prompts" Don't Fix This
&lt;/h2&gt;

&lt;p&gt;"Just tell the AI to write secure code" sounds reasonable. It doesn't work structurally.&lt;/p&gt;

&lt;p&gt;The AI can generate a secure authentication middleware. But it doesn't enforce that middleware globally. The next session adds a new route without it. The session after that adds frontend validation but skips the backend.&lt;/p&gt;

&lt;p&gt;Security is an architecture property. It requires global enforcement — every route, every input, every dependency. AI optimizes locally. The gap between "works" and "secure" grows with every session.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Structural Fix: Enforcement Model
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Middleware-First Architecture
&lt;/h3&gt;

&lt;p&gt;Every route is protected by default. Exceptions are explicitly declared.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// middleware.ts — applies to ALL routes&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publicPaths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/health&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/auth/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publicPaths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;verifyToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unauthorized&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/:path*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key: protection is the default. Public access is the exception that must be explicitly declared.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Input Validation at the Boundary
&lt;/h3&gt;

&lt;p&gt;Every API endpoint validates input before processing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreateUserSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CreateUserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issues&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Only validated data reaches business logic&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Automated Enforcement
&lt;/h3&gt;

&lt;p&gt;Add CI/CD checks that block insecure code from merging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/security.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Security Checks&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="c1"&gt;# Check for hardcoded secrets&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Secret scan&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;if grep -rn "sk_live\|sk_test\|apiKey.*=.*['\"]" \&lt;/span&gt;
            &lt;span class="s"&gt;--include="*.ts" --include="*.tsx" src/; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "FAIL: Hardcoded secrets detected"&lt;/span&gt;
            &lt;span class="s"&gt;exit 1&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;

      &lt;span class="c1"&gt;# Check for unprotected routes&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Auth coverage check&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;ROUTES=$(grep -rn "export.*GET\|export.*POST" \&lt;/span&gt;
            &lt;span class="s"&gt;--include="*.ts" src/app/api/ | wc -l)&lt;/span&gt;
          &lt;span class="s"&gt;AUTH=$(grep -rn "requireAuth\|withAuth\|middleware" \&lt;/span&gt;
            &lt;span class="s"&gt;--include="*.ts" src/app/api/ | wc -l)&lt;/span&gt;
          &lt;span class="s"&gt;echo "Routes: $ROUTES, Auth refs: $AUTH"&lt;/span&gt;

      &lt;span class="c1"&gt;# Dependency audit&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dependency vulnerability check&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm audit --production --audit-level=high&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Dependency Audit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm audit &lt;span class="nt"&gt;--production&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this on every merge. AI pulls in dependencies because they solve the immediate problem — not because they're security-reviewed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;After structural enforcement, security becomes a system property rather than a per-developer responsibility. New routes are protected by default. Input is validated at the boundary. Secrets never reach the codebase. Dependencies are audited automatically.&lt;/p&gt;

&lt;p&gt;Security debt is a structural condition. The fix is structural enforcement.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is part of the &lt;a href="https://vibecodiq.com/ai-chaos" rel="noopener noreferrer"&gt;AI Chaos&lt;/a&gt; series — a structural analysis of failure patterns in AI-generated codebases. Based on &lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA (Atomic Slice Architecture)&lt;/a&gt; — an open architecture standard for AI-generated software.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA Standard&lt;/a&gt; — the open specification&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/janvoldan/asa-standard" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; — source, examples, documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vibecodiq.com" rel="noopener noreferrer"&gt;Vibecodiq&lt;/a&gt; — structural diagnostics for AI-built apps
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpn28xve40eqern90gq3.jpg" alt=" " width="800" height="418"&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Comprehension Debt — When Your AI-Generated Codebase Outgrows Your Understanding</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Fri, 06 Mar 2026 14:11:37 +0000</pubDate>
      <link>https://dev.to/vibecodiq/comprehension-debt-when-your-ai-generated-codebase-outgrows-your-understanding-2fcl</link>
      <guid>https://dev.to/vibecodiq/comprehension-debt-when-your-ai-generated-codebase-outgrows-your-understanding-2fcl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyxgmupvbfz70fwfmgsq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyxgmupvbfz70fwfmgsq.jpg" alt=" " width="800" height="418"&gt;&lt;/a&gt;"I'm running a SaaS on code I don't fully understand."&lt;/p&gt;

&lt;p&gt;A founder told us this during our first call. Not ashamed. Just honest. The product had 80 paying users, revenue was growing, and the AI had built most of the codebase across 70+ sessions.&lt;/p&gt;

&lt;p&gt;But when a customer reported a billing error, nobody could trace where pricing logic actually lived.&lt;/p&gt;

&lt;p&gt;This post explains what comprehension debt is, how to measure it, and how to fix it structurally.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Comprehension Debt
&lt;/h2&gt;

&lt;p&gt;Comprehension debt is what happens when code is generated faster than it can be understood.&lt;/p&gt;

&lt;p&gt;AI produces working software. But "working" and "understood" are not the same thing. Each AI session solves the immediate task without asking whether the solution is structurally coherent with what came before.&lt;/p&gt;

&lt;p&gt;By month 4, the codebase has implicit conventions that nobody explicitly chose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Naming patterns that shifted mid-project&lt;/li&gt;
&lt;li&gt;Business logic in unexpected locations&lt;/li&gt;
&lt;li&gt;Functions that do three things&lt;/li&gt;
&lt;li&gt;Files that nobody can summarize in one sentence
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GENERATION SPEED vs COMPREHENSION SPEED

  Session 1   ████░░░░░░░░  ████░░░░░░░░
  Session 15  ████████░░░░  █████░░░░░░░
  Session 30  ████████████  ██████░░░░░░
  Session 50  ████████████  ██████░░░░░░
              ████████████

              gap = comprehension debt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Measure Comprehension Debt
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Test 1: The Explanation Test
&lt;/h3&gt;

&lt;p&gt;Pick any file over 300 lines in your project. Can you explain what it does — without reading the code line by line?&lt;/p&gt;

&lt;p&gt;If not, you have comprehension debt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 2: The Three Questions Test
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find src &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; | xargs &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For your top 10 files, ask:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What domain does this file belong to?&lt;/strong&gt; (auth, payments, users, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What happens if I delete it?&lt;/strong&gt; (what breaks, what depends on it)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Who is responsible for it?&lt;/strong&gt; (which team member, which module)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you can't answer all three for most files, the codebase has outgrown your ability to reason about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 3: The TODO Audit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"TODO&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;FIXME&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;HACK&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;XXX"&lt;/span&gt; src/ | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A high number means the AI left breadcrumbs it never cleaned up. Each one is a comprehension gap — a place where the AI deferred a decision that nobody came back to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 4: The Convention Drift Check
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check for inconsistent naming patterns&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"export default function&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;export function&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;export const"&lt;/span&gt; src/ &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the first 30 exports. Are they consistent? &lt;code&gt;default function&lt;/code&gt; vs &lt;code&gt;named export&lt;/code&gt; vs &lt;code&gt;const arrow function&lt;/code&gt;? If you see all three patterns, the AI shifted conventions mid-project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Documentation Doesn't Fix This
&lt;/h2&gt;

&lt;p&gt;"We'll add documentation later" is the default response. It's also the wrong fix applied at the wrong layer.&lt;/p&gt;

&lt;p&gt;Documentation describes what the code does. It does not change what the code does.&lt;/p&gt;

&lt;p&gt;If the architecture is incoherent — business logic in three places, naming conventions that shift mid-project, files that mix four domains — documentation just describes the mess. It's the equivalent of labeling every room in a building with no floor plan.&lt;/p&gt;

&lt;p&gt;Worse: the AI that wrote the code will generate plausible-sounding documentation. But "plausible" and "accurate" diverge when the architecture has drifted.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Structural Fix
&lt;/h2&gt;

&lt;p&gt;Comprehension debt is not a knowledge problem. It's a structure problem. The fix sequence:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Domain Mapping
&lt;/h3&gt;

&lt;p&gt;List every business domain in your application (auth, users, payments, notifications, etc.). Then map which files contain logic for which domain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find all files that reference "price" or "payment"&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rln&lt;/span&gt; &lt;span class="s2"&gt;"price&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;payment&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;stripe&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;checkout"&lt;/span&gt; src/ &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.tsx"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If pricing logic lives in more than 2-3 files, it's scattered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Module Boundaries
&lt;/h3&gt;

&lt;p&gt;Create explicit module boundaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  modules/
    auth/          -- everything authentication
    payments/      -- everything pricing and billing
    users/         -- everything user management
    notifications/ -- everything notifications
  shared/
    types/         -- shared type definitions
    utils/         -- pure utility functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule: each module owns one domain. No file crosses domain boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Self-Documenting Naming
&lt;/h3&gt;

&lt;p&gt;Enforce consistent naming conventions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files named by what they do, not how they're implemented&lt;/li&gt;
&lt;li&gt;Functions named by their business purpose&lt;/li&gt;
&lt;li&gt;No abbreviations that require domain knowledge to decode&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Convention Enforcement
&lt;/h3&gt;

&lt;p&gt;Add linting rules that enforce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistent export patterns&lt;/li&gt;
&lt;li&gt;File size limits (flag files over 300 lines)&lt;/li&gt;
&lt;li&gt;Import boundaries (modules can only import from allowed modules)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Example:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;eslint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;boundary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;rule&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"import/no-restricted-paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"zones"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/modules/auth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/modules/payments"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;After structural reorganization, the codebase becomes self-evident. You can navigate by structure instead of by searching. A new team member can understand the architecture from the folder structure alone. The explanation test becomes trivial — because each file does one thing in one domain.&lt;/p&gt;

&lt;p&gt;Comprehension debt doesn't require more documentation. It requires more structure.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is part of the &lt;a href="https://vibecodiq.com/ai-chaos" rel="noopener noreferrer"&gt;AI Chaos&lt;/a&gt; series — a structural analysis of failure patterns in AI-generated codebases. Based on &lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA (Atomic Slice Architecture)&lt;/a&gt; — an open architecture standard for AI-generated software.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA Standard&lt;/a&gt; — the open specification&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/janvoldan/asa-standard" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; — source, examples, documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vibecodiq.com" rel="noopener noreferrer"&gt;Vibecodiq&lt;/a&gt; — structural diagnostics for AI-built apps&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>codequality</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Why AI-Generated Apps Break After Every Change — The Structural Mechanism</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Wed, 25 Feb 2026 15:22:05 +0000</pubDate>
      <link>https://dev.to/vibecodiq/why-ai-generated-apps-break-after-every-change-the-structural-mechanism-2apj</link>
      <guid>https://dev.to/vibecodiq/why-ai-generated-apps-break-after-every-change-the-structural-mechanism-2apj</guid>
      <description>&lt;p&gt;"Every time we add something, something else breaks."&lt;/p&gt;

&lt;p&gt;If you've built an application with AI tools — Cursor, Lovable, Bolt.new, Replit, v0 — and you're past the first few months of development, there's a good chance you've heard this sentence. Maybe you've said it yourself.&lt;/p&gt;

&lt;p&gt;This post breaks down the structural mechanism behind this pattern, how to detect it in your own codebase, and what the fix actually looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pattern
&lt;/h2&gt;

&lt;p&gt;Here's what we typically see in AI-generated codebases past month 3:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files that have grown past 500–800 lines&lt;/li&gt;
&lt;li&gt;Circular dependency chains between modules&lt;/li&gt;
&lt;li&gt;Business logic in unexpected places (route handlers, UI components, utility files)&lt;/li&gt;
&lt;li&gt;Less than 10% test coverage&lt;/li&gt;
&lt;li&gt;Every "simple" change requires extensive manual testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't bad code. It's structurally incoherent code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mechanism: Architecture Drift
&lt;/h2&gt;

&lt;p&gt;AI-assisted development optimizes locally. Each prompt solves the immediate problem without awareness of the broader architecture.&lt;/p&gt;

&lt;p&gt;Session 1 establishes a clean boundary between your API routes and your business logic. Session 47 erodes it — because the fastest way to fix a bug is to put the fix where the symptoms are, not where the root cause lives.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Session 1:  Clean boundary between modules
Session 15: First shortcut across boundary
Session 30: Business logic in route handlers
Session 47: Circular dependency chain forms
Session 60: "Every change breaks something else"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By month 6, a change in module A breaks module B because they share internal state that nobody intended to share. The dependency graph has become a web rather than a tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOCAL OPTIMIZATION              STRUCTURAL ENFORCEMENT

  A &amp;lt;-&amp;gt; B                         A
  |  X  |                         |
  C &amp;lt;-&amp;gt; D                         B --&amp;gt; C
  |  X  |                               |
  E &amp;lt;-&amp;gt; F                         D --&amp;gt; E

  circular chains: 4              circular chains: 0
  blast radius: unknown           blast radius: bounded
  change cost: unpredictable      change cost: predictable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Detection: Two Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Circular Dependencies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx madge &lt;span class="nt"&gt;--circular&lt;/span&gt; &lt;span class="nt"&gt;--extensions&lt;/span&gt; ts,tsx src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What the number means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;0 chains&lt;/strong&gt;: Clean. Your modules can change independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1–2 chains&lt;/strong&gt;: Warning. Coupling is forming.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3+ chains&lt;/strong&gt;: Critical. Isolation is structurally impossible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Oversized Files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find src &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.ts"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.tsx"&lt;/span&gt; | xargs &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'$1 &amp;gt; 500'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In AI-generated codebases, files over 500 lines usually contain logic from multiple domains. They are where "unrelated" breakage originates.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Test Coverage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx jest &lt;span class="nt"&gt;--coverage&lt;/span&gt; &lt;span class="nt"&gt;--coverageReporters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;text-summary 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Statements"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Less than 10% means the feedback loop between code changes and correctness verification is absent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "Just Add Tests" Doesn't Fix This
&lt;/h2&gt;

&lt;p&gt;Tests detect that a regression happened. They do not prevent the architectural condition that causes it.&lt;/p&gt;

&lt;p&gt;If your architecture allows a pricing change to break authentication, tests will catch the failure — after the fact. But no amount of test coverage prevents the coupling itself. The change still leaks across boundaries because the boundaries don't exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Structural Fix
&lt;/h2&gt;

&lt;p&gt;The fix is not a rewrite. It's boundary enforcement — applied in sequence:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Map the Current State
&lt;/h3&gt;

&lt;p&gt;Run the detection commands above. Document:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many circular dependency chains exist&lt;/li&gt;
&lt;li&gt;Which files exceed 500 lines&lt;/li&gt;
&lt;li&gt;Where business logic actually lives vs. where it should live&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Establish Boundaries
&lt;/h3&gt;

&lt;p&gt;Define which module owns which logic. The rule is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;One module = one domain = one direction of dependency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A pricing module can depend on a user module. A user module cannot depend on a pricing module. If they both need shared data, extract it into a shared types module that both can depend on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Break Circular Chains
&lt;/h3&gt;

&lt;p&gt;For each circular dependency:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify the shared state or logic that creates the cycle&lt;/li&gt;
&lt;li&gt;Extract it into a separate module&lt;/li&gt;
&lt;li&gt;Update both modules to depend on the extracted module instead of each other&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 4: Decompose Oversized Files
&lt;/h3&gt;

&lt;p&gt;Files over 500 lines get split by domain responsibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Route handlers contain only routing logic&lt;/li&gt;
&lt;li&gt;Business logic lives in domain modules&lt;/li&gt;
&lt;li&gt;Shared utilities contain only pure functions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Add Test Baseline
&lt;/h3&gt;

&lt;p&gt;Once boundaries exist, tests become meaningful. Each test covers a bounded module, not the entire system. Focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Critical business paths (payments, auth, core workflows)&lt;/li&gt;
&lt;li&gt;Boundary contracts (what each module exports)&lt;/li&gt;
&lt;li&gt;Regression triggers (the specific changes that caused past breakage)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 6: Enforce Automatically
&lt;/h3&gt;

&lt;p&gt;Set up CI/CD gates that block:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New circular dependencies&lt;/li&gt;
&lt;li&gt;Files exceeding size thresholds&lt;/li&gt;
&lt;li&gt;Merges without test coverage on critical paths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This turns the architecture from "trust-based" to "enforcement-based." Changes that violate boundaries are caught before they reach production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;After structural stabilization, the blast radius of every change becomes predictable. A change in the pricing module affects pricing. A change in authentication affects authentication. "Every time we add something, something else breaks" disappears — not because the team is more careful, but because the architecture makes cross-module leakage structurally impossible.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is part of the &lt;a href="https://vibecodiq.com/ai-chaos" rel="noopener noreferrer"&gt;AI Chaos&lt;/a&gt; series — a structural analysis of failure patterns in AI-generated codebases. Based on &lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA (Atomic Slice Architecture)&lt;/a&gt; — an open architecture standard for AI-generated software.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://asastandard.org" rel="noopener noreferrer"&gt;ASA Standard&lt;/a&gt; — the open specification&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/janvoldan/asa-standard" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; — source, examples, documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vibecodiq.com" rel="noopener noreferrer"&gt;Vibecodiq&lt;/a&gt; — structural diagnostics for AI-built apps&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Taming the 5–10% Instability Rule: Using ASA for Deterministic Regeneration</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Tue, 09 Dec 2025 15:21:27 +0000</pubDate>
      <link>https://dev.to/vibecodiq/taming-the-5-10-instability-rule-using-asa-for-deterministic-regeneration-3j0b</link>
      <guid>https://dev.to/vibecodiq/taming-the-5-10-instability-rule-using-asa-for-deterministic-regeneration-3j0b</guid>
      <description>&lt;p&gt;If you use AI coding tools daily, you've probably seen this:&lt;/p&gt;

&lt;p&gt;You ask the assistant to "update this endpoint", and the PR comes back with &lt;strong&gt;a lot more&lt;/strong&gt; than that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The service changed&lt;/li&gt;
&lt;li&gt;A helper was "cleaned up"&lt;/li&gt;
&lt;li&gt;A test file got rewritten&lt;/li&gt;
&lt;li&gt;An unrelated import moved somewhere else&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing looks obviously wrong, but over time you accumulate a growing zone of &lt;strong&gt;"I don't know why this changed."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's what I call the &lt;strong&gt;5–10% instability rule&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every regeneration quietly destabilizes ~5–10% of your codebase through unrequested changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this post, I'll show how ASA v1.0 (a deterministic CLI for slice‑based architecture) turns regeneration from a risky operation into a &lt;strong&gt;fully controlled, local, repeatable&lt;/strong&gt; process.&lt;/p&gt;




&lt;h2&gt;
  
  
  The concrete pain: AI touching more than you asked for
&lt;/h2&gt;

&lt;p&gt;Typical flow today:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You change requirements for login (extra field, new error).&lt;/li&gt;
&lt;li&gt;You ask AI: "Update the login endpoint, service and tests."&lt;/li&gt;
&lt;li&gt;The assistant edits 5–10 files — some relevant, some "for consistency."&lt;/li&gt;
&lt;li&gt;The diff includes signature changes, helper refactors, and test rewrites.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As an engineer, you now have three problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unclear blast radius&lt;/strong&gt; — what else did we just change?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture erosion&lt;/strong&gt; — a "small cleanup" breaks a domain boundary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fear of regeneration&lt;/strong&gt; — doing this again might overwrite business logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can try to tighten the prompt, but the real issue is that &lt;strong&gt;nothing in your project structure encodes strict boundaries plus regeneration rules.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ASA's core idea is: &lt;em&gt;encode them.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ASA in 30 seconds
&lt;/h2&gt;

&lt;p&gt;ASA v1.0 is a Python CLI that works on &lt;strong&gt;Slices&lt;/strong&gt;: vertical feature units that colocate everything for one use‑case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;domains/auth/login/
├── slice.spec.md        # Human spec
├── slice.contract.json  # Machine contract
├── handler.py           # FastAPI endpoint
├── service.py           # Business logic
├── repository.py        # Data access
├── schemas.py           # Pydantic models
└── tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pipeline is deterministic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slice.spec.md → slice.contract.json → skeleton → your implementation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Slices&lt;/strong&gt; give you local, vertical boundaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specs &amp;amp; contracts&lt;/strong&gt; are the single source of truth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Markers&lt;/strong&gt; preserve your implementation across regeneration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linter&lt;/strong&gt; enforces domain boundaries with AST checks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Before vs After: Changing a Slice
&lt;/h2&gt;

&lt;p&gt;Let's walk through a real change: adding &lt;code&gt;ip_address&lt;/code&gt; to login for security logging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before ASA: free‑form codebase
&lt;/h3&gt;

&lt;p&gt;You might have something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# auth/routes.py
&lt;/span&gt;&lt;span class="nd"&gt;@router.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/login&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_by_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;verify_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password_hash&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_jwt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;audit_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# logging somewhere else
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now product asks: "Also store the IP address and make it available to an analytics job."&lt;/p&gt;

&lt;p&gt;With AI, your prompt is vague by definition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Update login to accept ip_address, store it, and keep tests passing."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The assistant might:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change this handler&lt;/li&gt;
&lt;li&gt;Rewrite some helper called &lt;code&gt;audit_login&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adjust a couple of tests&lt;/li&gt;
&lt;li&gt;Maybe "simplify" a repository interface on the way&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get your feature — and another 5–10% of "not sure what changed".&lt;/p&gt;




&lt;h3&gt;
  
  
  After ASA: slice‑based, deterministic workflow
&lt;/h3&gt;

&lt;p&gt;In ASA, login lives in its own Slice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;domains/auth/login/
  slice.spec.md
  slice.contract.json
  handler.py
  service.py
  repository.py
  schemas.py
  tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 1 — Update the Spec&lt;/strong&gt; (&lt;code&gt;domains/auth/login/slice.spec.md&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Purpose&lt;/span&gt;
User logs in with email and password. Returns JWT token.

&lt;span class="gu"&gt;## Inputs&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; email: string
&lt;span class="p"&gt;-&lt;/span&gt; password: string
&lt;span class="p"&gt;-&lt;/span&gt; ip_address: string

&lt;span class="gu"&gt;## Outputs&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; jwt_token: string
&lt;span class="p"&gt;-&lt;/span&gt; expires_in: int

&lt;span class="gu"&gt;## Behaviour&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Verify user exists.
&lt;span class="p"&gt;-&lt;/span&gt; Verify password.
&lt;span class="p"&gt;-&lt;/span&gt; Generate JWT token.
&lt;span class="p"&gt;-&lt;/span&gt; Log IP address for security.

&lt;span class="gu"&gt;## Errors&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; INVALID_CREDENTIALS: Invalid email or password.

&lt;span class="gu"&gt;## Side Effects&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Logs login attempt with IP address.

&lt;span class="gu"&gt;## Dependencies&lt;/span&gt;
None
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — Regenerate contract + skeleton:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asa generate-contract auth/login
asa regenerate-slice auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;generate-contract&lt;/code&gt; updates &lt;code&gt;slice.contract.json&lt;/code&gt; from the spec.&lt;br&gt;
&lt;code&gt;regenerate-slice&lt;/code&gt; then reads the contract and updates the Python files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;schemas.py&lt;/code&gt; (adds &lt;code&gt;ip_address&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;handler/service/repository structure&lt;/li&gt;
&lt;li&gt;tests skeleton&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Verify your implementation survived&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Business logic in &lt;code&gt;service.py&lt;/code&gt; is wrapped by markers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.repository&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LoginRepository&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.schemas&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LoginRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoginResponse&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoginRepository&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# === BEGIN USER CODE ===
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LoginRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;LoginResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user_by_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USER_NOT_FOUND&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INVALID_CREDENTIALS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_jwt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ip_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;LoginResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expires_in&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# === END USER CODE ===
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ASA regenerates the file &lt;em&gt;around&lt;/em&gt; this block and then reinserts your function body exactly as written.&lt;/p&gt;

&lt;p&gt;You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updated schemas and contracts&lt;/li&gt;
&lt;li&gt;Same business logic&lt;/li&gt;
&lt;li&gt;No surprise changes in unrelated slices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 4 — Run the linter:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asa lint auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If AI tried to sneak in a cross‑domain import (e.g. directly calling &lt;code&gt;domains.analytics&lt;/code&gt;), the linter fails and tells you exactly where.&lt;/p&gt;




&lt;h2&gt;
  
  
  Minimal CLI workflow to adopt ASA
&lt;/h2&gt;

&lt;p&gt;To start using ASA on a new feature, you typically do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1) Create a slice&lt;/span&gt;
asa create-slice auth/login

&lt;span class="c"&gt;# 2) Write the spec (manual or with AI help)&lt;/span&gt;
&lt;span class="c"&gt;#    edit domains/auth/login/slice.spec.md&lt;/span&gt;

&lt;span class="c"&gt;# 3) Generate contract + skeleton&lt;/span&gt;
asa generate-contract auth/login
asa generate-skeleton auth/login

&lt;span class="c"&gt;# 4) Implement your logic between markers in service.py/repository.py&lt;/span&gt;

&lt;span class="c"&gt;# 5) Lint before committing&lt;/span&gt;
asa lint auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From then on, any change to login flows through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asa generate-contract auth/login
asa regenerate-slice auth/login
asa lint auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regeneration becomes a &lt;strong&gt;routine operation&lt;/strong&gt;, not a roll of the dice.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this kills the 5–10% instability rule
&lt;/h2&gt;

&lt;p&gt;The 5–10% rule thrives on three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Global, shared helpers&lt;/li&gt;
&lt;li&gt;Fuzzy boundaries ("we try not to import that…")&lt;/li&gt;
&lt;li&gt;Non‑deterministic generation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ASA attacks all three:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slices encourage &lt;strong&gt;local duplication&lt;/strong&gt; of business helpers instead of sharing them across domains.&lt;/li&gt;
&lt;li&gt;Domain rules are enforced by an AST linter, not just by code review.&lt;/li&gt;
&lt;li&gt;The CLI is deterministic — same spec, same skeleton, every time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI is still in the loop, but &lt;strong&gt;its freedom is constrained by contracts, markers and lint rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You keep the speed. You lose the architectural roulette.&lt;/p&gt;




&lt;p&gt;If you want to see the full starter kit and CLI in action, check out:&lt;/p&gt;

&lt;p&gt;Source code &amp;amp; starter kit: &lt;a href="https://github.com/vibecodiq/asa-starter-kit" rel="noopener noreferrer"&gt;https://github.com/vibecodiq/asa-starter-kit&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>architecture</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Stop Letting AI Delete Your Code: Deterministic Regeneration with ASA v1.0</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Fri, 05 Dec 2025 11:26:45 +0000</pubDate>
      <link>https://dev.to/vibecodiq/stop-letting-ai-delete-your-code-deterministic-regeneration-with-asa-v10-3a5n</link>
      <guid>https://dev.to/vibecodiq/stop-letting-ai-delete-your-code-deterministic-regeneration-with-asa-v10-3a5n</guid>
      <description>&lt;p&gt;AI coding tools are great at one thing: &lt;strong&gt;rewriting lots of code very fast&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s also exactly how they break your system.&lt;/p&gt;

&lt;p&gt;If you’ve ever:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Asked an AI to “update this schema” and lost a hand‑written edge case&lt;/li&gt;
&lt;li&gt;Let a tool “clean up this service” and watched a subtle validation vanish&lt;/li&gt;
&lt;li&gt;Tried to regenerate a scaffolded module and ended up diffing walls of code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…then this post is for you.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll look at how &lt;strong&gt;ASA v1.0&lt;/strong&gt; lets you regenerate Python slices safely – preserving your business logic byte‑for‑byte while still letting AI help with the boring parts.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Pain: Regeneration Fear
&lt;/h2&gt;

&lt;p&gt;A typical AI‑assisted workflow today:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use your favourite tool (Cursor, Copilot, etc.) to scaffold a FastAPI endpoint.&lt;/li&gt;
&lt;li&gt;Add some custom behaviour on top – edge cases, extra validation, domain rules.&lt;/li&gt;
&lt;li&gt;A week later, requirements change. You need a new field or different error semantics.&lt;/li&gt;
&lt;li&gt;You ask AI to “regenerate the handler and service to match the new schema”.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What comes back is a brand‑new version of the file.&lt;/p&gt;

&lt;p&gt;It may be cleaner. It may even pass tests. But it almost certainly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rewrote parts of your manually added logic&lt;/li&gt;
&lt;li&gt;Changed error types or messages&lt;/li&gt;
&lt;li&gt;Modified behaviour in ways the AI can’t explain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After this happens once or twice, you learn a new instinct:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Never regenerate a file you’ve touched.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Congratulations – your “AI‑generated” scaffolding just became zombie code.&lt;/p&gt;




&lt;h2&gt;
  
  
  ASA’s View: Separate Intent from Implementation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Agentic‑Sliced Architecture (ASA)&lt;/strong&gt; starts from a different assumption:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Specs should be regenerated. Business logic should not.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So it separates your flow into three layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Spec (&lt;code&gt;slice.spec.md&lt;/code&gt;)&lt;/strong&gt; – a human‑readable Markdown description of a feature: purpose, inputs, outputs, behaviour, errors, side‑effects, dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contract (&lt;code&gt;slice.contract.json&lt;/code&gt;)&lt;/strong&gt; – a strict, machine‑readable JSON version of that spec.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generated code skeleton&lt;/strong&gt; – FastAPI router + service + repository + schemas + tests.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The important bit: all of this lives inside a &lt;strong&gt;Slice&lt;/strong&gt; – a vertical feature unit like &lt;code&gt;domains/auth/login/&lt;/code&gt; instead of being scattered across folders.&lt;/p&gt;

&lt;p&gt;You create it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asa create-slice auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you fill in &lt;code&gt;domains/auth/login/slice.spec.md&lt;/code&gt; with your feature description.&lt;/p&gt;




&lt;h2&gt;
  
  
  From Spec to Code: The Deterministic Pipeline
&lt;/h2&gt;

&lt;p&gt;Once your spec is ready, ASA v1.0 runs a &lt;strong&gt;deterministic pipeline&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asa generate-contract auth/login
asa generate-skeleton auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Behind the scenes, this does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parse the Markdown spec&lt;/li&gt;
&lt;li&gt;Emit a JSON contract with inputs/outputs/behaviour/errors/side‑effects&lt;/li&gt;
&lt;li&gt;Generate Python modules that match that contract&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The generated folder looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;domains/auth/login/
├── slice.spec.md
├── slice.contract.json
├── handler.py
├── service.py
├── repository.py
├── schemas.py
└── tests/
    └── test_slice.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Given the same spec, you’ll always get the &lt;strong&gt;same&lt;/strong&gt; contract and skeleton files. No randomness, no “almost the same but slightly different” diffs.&lt;/p&gt;

&lt;p&gt;So where does your custom logic live?&lt;/p&gt;




&lt;h2&gt;
  
  
  Markers: Where Your Logic Lives (and Survives)
&lt;/h2&gt;

&lt;p&gt;ASA reserves explicit regions in generated files for your implementation.&lt;/p&gt;

&lt;p&gt;For example, in &lt;code&gt;service.py&lt;/code&gt; you’ll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.repository&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LoginRepository&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.schemas&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LoginRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoginResponse&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoginRepository&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# === BEGIN USER CODE ===
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LoginRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;LoginResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Your implementation here
&lt;/span&gt;        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user_by_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USER_NOT_FOUND&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INVALID_CREDENTIALS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_jwt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;LoginResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expires_in&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# === END USER CODE ===
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything between &lt;code&gt;BEGIN USER CODE&lt;/code&gt; and &lt;code&gt;END USER CODE&lt;/code&gt; is &lt;strong&gt;your territory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hand‑write it&lt;/li&gt;
&lt;li&gt;Ask an AI assistant to generate it&lt;/li&gt;
&lt;li&gt;Refine it over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ASA will never overwrite this region during regeneration.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Magic Trick: Regenerate Without Losing Logic
&lt;/h2&gt;

&lt;p&gt;Now imagine you extend the feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;ip_address: string&lt;/code&gt; to the inputs&lt;/li&gt;
&lt;li&gt;Log login attempts for security&lt;/li&gt;
&lt;li&gt;Maybe enrich the response with an extra field&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You update &lt;code&gt;slice.spec.md&lt;/code&gt; to reflect the new behaviour, then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asa generate-contract auth/login
asa regenerate-slice auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what happens:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ASA re‑parses &lt;code&gt;slice.spec.md&lt;/code&gt; and updates &lt;code&gt;slice.contract.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It regenerates the skeleton files (schemas, handler signatures, test stubs, etc.).&lt;/li&gt;
&lt;li&gt;For files that contain user markers, it &lt;strong&gt;extracts your code&lt;/strong&gt;, regenerates the structure, and injects your code back into the new version.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your &lt;code&gt;execute()&lt;/code&gt; implementation is preserved exactly, but now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;LoginRequest&lt;/code&gt; model includes &lt;code&gt;ip_address&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The handler signature matches the new contract&lt;/li&gt;
&lt;li&gt;Tests and scaffolding are up to date&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ve just updated your feature end‑to‑end without manually touching any glue code – and without losing a single line of business logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Keeping Architecture Clean: Linting Boundaries
&lt;/h2&gt;

&lt;p&gt;Overwriting logic is one problem. &lt;strong&gt;Eroding architecture&lt;/strong&gt; is another.&lt;/p&gt;

&lt;p&gt;When AI tries to “help”, it often reaches for the nearest import that makes the code compile, even if it breaks your domain boundaries.&lt;/p&gt;

&lt;p&gt;ASA ships with a linter that understands Slices and performs AST‑based checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asa lint auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It verifies that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All required files exist and contracts are valid&lt;/li&gt;
&lt;li&gt;Slice structure is consistent&lt;/li&gt;
&lt;li&gt;Imports don’t cross domains in illegal ways&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a repository in &lt;code&gt;auth/login&lt;/code&gt; tries to import something like &lt;code&gt;domains.billing.invoice&lt;/code&gt;, the linter fails and tells you exactly where the violation happened.&lt;/p&gt;

&lt;p&gt;This makes it much harder for “just make it work” AI changes to quietly turn your codebase into spaghetti.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using ASA with AI in Practice
&lt;/h2&gt;

&lt;p&gt;ASA v1.0 is a Python CLI, not a black‑box SaaS.&lt;/p&gt;

&lt;p&gt;You can plug it into whatever workflow you already have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use an LLM to generate &lt;strong&gt;specs&lt;/strong&gt; (&lt;code&gt;slice.spec.md&lt;/code&gt;) from product requirements.&lt;/li&gt;
&lt;li&gt;Let ASA turn those specs into contracts and skeletons.&lt;/li&gt;
&lt;li&gt;Use AI again to help implement the logic &lt;strong&gt;inside marker regions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Regenerate safely whenever the spec changes.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;asa lint&lt;/code&gt; in CI to enforce boundaries before merge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The more agents and tools you add, the more you’ll appreciate that spec → contract → code is deterministic and repeatable.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Reach for ASA
&lt;/h2&gt;

&lt;p&gt;You probably don’t need ASA for throwaway prototypes.&lt;/p&gt;

&lt;p&gt;You almost certainly need it if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are building a long‑lived product with an AI‑heavy dev loop&lt;/li&gt;
&lt;li&gt;Multiple agents or tools will touch the same backend&lt;/li&gt;
&lt;li&gt;You’re already afraid to regenerate code you generated a month ago&lt;/li&gt;
&lt;li&gt;You care about domain boundaries and want them enforced, not just drawn on a diagram&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In that world, “just trust the AI” is not a strategy.&lt;/p&gt;

&lt;p&gt;You want an architecture that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treats specs as the source of truth&lt;/li&gt;
&lt;li&gt;Makes regeneration safe by design&lt;/li&gt;
&lt;li&gt;Protects business logic with explicit markers&lt;/li&gt;
&lt;li&gt;Guards your boundaries with a linter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s what ASA v1.0 is designed to do.&lt;/p&gt;

&lt;p&gt;If you want to see it in action, check out the regeneration demo &lt;a href="https://vibecodiq.com/demo/" rel="noopener noreferrer"&gt;https://vibecodiq.com/demo/&lt;/a&gt; and docs on the ASA starter kit repo &lt;a href="https://github.com/vibecodiq/asa-starter-kit" rel="noopener noreferrer"&gt;https://github.com/vibecodiq/asa-starter-kit&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>architecture</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Deterministic Regeneration with ASA Core v1.0</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Wed, 03 Dec 2025 15:54:40 +0000</pubDate>
      <link>https://dev.to/vibecodiq/why-regenerate-in-ai-coding-should-never-mean-rewrite-1eel</link>
      <guid>https://dev.to/vibecodiq/why-regenerate-in-ai-coding-should-never-mean-rewrite-1eel</guid>
      <description>&lt;p&gt;Most AI-powered coding tools are excellent at generating code &lt;strong&gt;once&lt;/strong&gt;…&lt;br&gt;
But they struggle — sometimes catastrophically — when asked to generate the same feature &lt;strong&gt;again&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You update the spec, click "regenerate," and suddenly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your custom logic disappears&lt;/li&gt;
&lt;li&gt;Your validation rules vanish&lt;/li&gt;
&lt;li&gt;Your test structure no longer matches&lt;/li&gt;
&lt;li&gt;Your handlers and models drift apart&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the &lt;em&gt;regeneration trap&lt;/em&gt;.&lt;br&gt;
ASA Core v1.0 was built specifically to escape it.&lt;/p&gt;

&lt;p&gt;In this article, we'll break down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why regeneration fails in traditional tools&lt;/li&gt;
&lt;li&gt;How ASA's deterministic pipeline prevents code loss&lt;/li&gt;
&lt;li&gt;The slice-based architecture that eliminates drift&lt;/li&gt;
&lt;li&gt;A real example showing safe regeneration&lt;/li&gt;
&lt;li&gt;Why determinism is essential for multi-agent AI workflows&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;
  
  
  1. The Pain: Regeneration as a Full Rewrite
&lt;/h1&gt;

&lt;p&gt;Here is the typical lifecycle developers experience with most generators:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Day 1: Generate scaffolding → looks great
Day 2: Implement business logic → feels great
Day 3: Requirement changes → regenerate → everything is gone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generator doesn't know what you wrote.&lt;br&gt;
It only knows how to produce a new skeleton.&lt;/p&gt;

&lt;p&gt;This leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lost developer time&lt;/li&gt;
&lt;li&gt;Fear of touching generators&lt;/li&gt;
&lt;li&gt;Divergent specs &amp;amp; code&lt;/li&gt;
&lt;li&gt;Architecture decay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't just lose code — you lose trust.&lt;/p&gt;


&lt;h1&gt;
  
  
  2. ASA's Model: Slices, Specs, and Contracts
&lt;/h1&gt;

&lt;p&gt;ASA uses three layers to create a deterministic, AI-safe workflow:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. &lt;strong&gt;Slices&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Self-contained vertical feature units:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;domains/auth/login/
├── slice.spec.md
├── slice.contract.json
├── handler.py
├── service.py
├── repository.py
├── schemas.py
└── tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Specs (Human-readable)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Seven required sections: Purpose, Inputs, Outputs, Behaviour, Errors, Side Effects, Dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Contracts (Machine-readable)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;JSON schema generated from the spec:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"inputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"jwt_token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"expires_in"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"int"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ASA then uses deterministic templates to generate code.&lt;/p&gt;

&lt;p&gt;No randomness.&lt;br&gt;
No heuristics.&lt;br&gt;
No AI in the core pipeline.&lt;/p&gt;


&lt;h1&gt;
  
  
  3. Marker-Based Code Preservation (ASA's Key Feature)
&lt;/h1&gt;

&lt;p&gt;Instead of trying to guess what is "your code" vs "generated code", ASA explicitly marks regions to preserve:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# === BEGIN USER CODE ===
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LoginRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;LoginResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user_by_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_jwt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;LoginResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expires_in&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# === END USER CODE ===
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During regeneration, ASA:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extracts everything inside the markers&lt;/li&gt;
&lt;li&gt;Regenerates the structure around it&lt;/li&gt;
&lt;li&gt;Inserts your code back exactly where it belongs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a &lt;strong&gt;100% deterministic round trip&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Your code can never be overwritten by accident.&lt;/p&gt;




&lt;h1&gt;
  
  
  4. Example: Login Slice with New Requirements
&lt;/h1&gt;

&lt;p&gt;You have a working login slice.&lt;/p&gt;

&lt;p&gt;Later, security wants to log &lt;code&gt;ip_address&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  In most tools:
&lt;/h3&gt;

&lt;p&gt;Regenerate → code loss → manual merge → bugs.&lt;/p&gt;

&lt;h3&gt;
  
  
  In ASA:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Update &lt;code&gt;slice.spec.md&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- email: string
- password: string
- ip_address: string # new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Regenerate safely:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asa generate-contract auth/login
asa regenerate-slice auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ASA updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Models&lt;/li&gt;
&lt;li&gt;Handler signature&lt;/li&gt;
&lt;li&gt;Tests&lt;/li&gt;
&lt;li&gt;Contract&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Your logic remains intact.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  5. Determinism Enables AI-First Engineering
&lt;/h1&gt;

&lt;p&gt;In AI-assisted development, regeneration must be safe because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple agents may touch the same slice&lt;/li&gt;
&lt;li&gt;Specs may change daily&lt;/li&gt;
&lt;li&gt;Contracts evolve quickly&lt;/li&gt;
&lt;li&gt;Automated workflows need predictable behavior&lt;/li&gt;
&lt;li&gt;CI needs to regenerate and lint without human supervision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ASA ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same spec → same contract&lt;/li&gt;
&lt;li&gt;Same contract → same files&lt;/li&gt;
&lt;li&gt;No surprises in diffs&lt;/li&gt;
&lt;li&gt;No accidental overwrite of logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is architecture built for the AI era.&lt;/p&gt;




&lt;h1&gt;
  
  
  6. Why Teams Adopt ASA
&lt;/h1&gt;

&lt;p&gt;ASA Core v1.0 is perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long-lived backends&lt;/li&gt;
&lt;li&gt;Multi-agent coding environments&lt;/li&gt;
&lt;li&gt;Fast-evolving feature sets&lt;/li&gt;
&lt;li&gt;Teams tired of code drift&lt;/li&gt;
&lt;li&gt;Organizations needing deterministic output&lt;/li&gt;
&lt;li&gt;Anyone building with LLMs at the center&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ASA allows you to embrace regeneration — not fear it.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Regeneration should NOT feel like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm -rf my_code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should feel like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;safely update the structure while preserving my logic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ASA Core v1.0 makes that possible using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slice colocation&lt;/li&gt;
&lt;li&gt;Deterministic templates&lt;/li&gt;
&lt;li&gt;Machine-readable contracts&lt;/li&gt;
&lt;li&gt;Marker-based preservation&lt;/li&gt;
&lt;li&gt;Boundary enforcement via linter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want a backend architecture that can keep up with AI-driven development — ASA is it.&lt;/p&gt;

&lt;p&gt;Source code &amp;amp; starter kit: &lt;a href="https://github.com/vibecodiq/asa-starter-kit" rel="noopener noreferrer"&gt;https://github.com/vibecodiq/asa-starter-kit&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>architecture</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>How I Stopped AI Codebases From Collapsing: Architecture Drift vs. Deterministic Slices</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Mon, 01 Dec 2025 21:23:07 +0000</pubDate>
      <link>https://dev.to/vibecodiq/how-i-stopped-ai-codebases-from-collapsing-architecture-drift-vs-deterministic-slices-3pi</link>
      <guid>https://dev.to/vibecodiq/how-i-stopped-ai-codebases-from-collapsing-architecture-drift-vs-deterministic-slices-3pi</guid>
      <description>&lt;p&gt;AI coding tools are amazing… until they silently break your architecture.&lt;/p&gt;

&lt;p&gt;This article shows &lt;strong&gt;exactly&lt;/strong&gt; why drift happens — and how &lt;strong&gt;ASA Core v1.0&lt;/strong&gt; fixes it with deterministic slice-based generation.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Real Pain: AI Code Is Not Deterministic
&lt;/h2&gt;

&lt;p&gt;Run the same instruction twice and you get different outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Version 1
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;# Version 2
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same prompt → different structure → instant drift.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Drift Gets Worse When Specs Change
&lt;/h2&gt;

&lt;p&gt;Traditional workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;edit spec
↓
Regenerate
↓
💀 Custom code overwritten
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So engineers stop regenerating.&lt;br&gt;
Schemas drift from implementation.&lt;br&gt;
Tests no longer match the API.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. ASA Core v1.0: Deterministic Pipeline
&lt;/h2&gt;

&lt;p&gt;ASA uses a strict 3-step flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slice.spec.md → slice.contract.json → skeleton code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every step is deterministic — no randomness, no inference.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Before vs After (Real ASA Behavior)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Before (traditional generation)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Business logic gets overwritten when spec changes
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# custom logic
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the spec → overwrite → cry.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ After (ASA regeneration)
&lt;/h3&gt;

&lt;p&gt;You write logic ONLY between markers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# === BEGIN USER CODE ===
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LoginRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;LoginResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user_by_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;LoginResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expires_in&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# === END USER CODE ===
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the spec:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asa generate-contract auth/login
asa regenerate-slice auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ASA regenerates the file structure and &lt;strong&gt;injects your preserved logic back in&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is guaranteed — documented and implemented in Core.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Boundary Violations Stop Instantly
&lt;/h2&gt;

&lt;p&gt;ASA lints with AST analysis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;asa lint auth/login

❌ &lt;span class="o"&gt;[&lt;/span&gt;LINT FAIL] Boundary violation &lt;span class="k"&gt;in &lt;/span&gt;repository.py:
   Line 1: Illegal import &lt;span class="s1"&gt;'domains.billing.invoice'&lt;/span&gt;
   -&amp;gt; Cannot import from other domains.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same-domain imports are fully allowed; cross-domain imports are forbidden.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Quick Reproducible Workflow
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;".[dev]"&lt;/span&gt;

asa create-slice auth/login

&lt;span class="c"&gt;# edit slice.spec.md&lt;/span&gt;

asa generate-contract auth/login
asa generate-skeleton auth/login

&lt;span class="c"&gt;# implement logic between markers&lt;/span&gt;

asa lint auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when specs change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asa generate-contract auth/login
asa regenerate-slice auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero drift. Zero overwrite. Fully deterministic.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Why This Matters
&lt;/h2&gt;

&lt;p&gt;Clean architecture + deterministic regeneration =&lt;br&gt;
&lt;strong&gt;AI codebases that don’t collapse.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the foundation for stable AI-assisted engineering.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Source code &amp;amp; starter kit:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/vibecodiq/asa-starter-kit" rel="noopener noreferrer"&gt;https://github.com/vibecodiq/asa-starter-kit&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>architecture</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>ASA: The First Architecture Built for the AI-Coding Era</title>
      <dc:creator>vibecodiq</dc:creator>
      <pubDate>Sat, 29 Nov 2025 20:12:50 +0000</pubDate>
      <link>https://dev.to/vibecodiq/asa-the-first-architecture-built-for-the-ai-coding-era-3g2k</link>
      <guid>https://dev.to/vibecodiq/asa-the-first-architecture-built-for-the-ai-coding-era-3g2k</guid>
      <description>&lt;h2&gt;
  
  
  🧩 The Problem: AI Development Is in Chaos
&lt;/h2&gt;

&lt;p&gt;Over the last two years, AI has become the most powerful coding tool ever created.&lt;br&gt;
But it also introduced a new category of problems that traditional architectures were never meant to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Generated code is unstable (drift)&lt;/li&gt;
&lt;li&gt;❌ Small changes break unrelated modules&lt;/li&gt;
&lt;li&gt;❌ Multi-agent workflows conflict&lt;/li&gt;
&lt;li&gt;❌ Regeneration overwrites human logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is no longer a tooling issue.&lt;br&gt;
It’s a &lt;strong&gt;systemic architectural problem&lt;/strong&gt; — and systemic problems require architectural solutions.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧠 The Origin: Why We Needed ASA
&lt;/h2&gt;

&lt;p&gt;Across multiple AI-driven projects, the same destructive pattern kept appearing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI could generate code&lt;/li&gt;
&lt;li&gt;...but couldn’t &lt;strong&gt;preserve architecture&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Small spec changes broke unrelated modules&lt;/li&gt;
&lt;li&gt;Agents overwrote each other’s logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eventually it became undeniable:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;We cannot build AI-generated software on architectures designed before AI existed.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That realization led to the creation of &lt;strong&gt;ASA — the AI-Sliced Architecture&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  🔍 What Is ASA?
&lt;/h2&gt;

&lt;p&gt;ASA introduces &lt;strong&gt;vertical slices&lt;/strong&gt;, deterministic scaffolding, and regeneration safety.&lt;br&gt;
It ensures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;AI cannot break the architecture.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Developers can iterate safely.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Only deterministic scaffold regions regenerate.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Human-written logic stays intact.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ASA transforms AI development from "creative chaos" into &lt;strong&gt;deterministic engineering&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  📂 ASA Slice Structure (v1.0)
&lt;/h2&gt;

&lt;p&gt;A slice contains everything needed for a single feature: handler, service logic, schemas, repository, contract, spec, and tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
└── domains/
    └── auth/
        └── slices/
            └── login/
                ├── __init__.py
                ├── handler.py          # AI-managed entry point
                ├── repository.py       # Data layer
                ├── schemas.py          # Pydantic models (I/O)
                ├── service.py          # Human-written logic (Protected 🔒)
                ├── slice.contract.json # Generated from slice spec
                ├── slice.spec.md       # Human-written slice definition
                └── tests/              # Deterministic test scaffold
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;This structure is deterministic, stable, and regeneration-safe.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 The “Sandwich Pattern”: AI Code Around Human Logic
&lt;/h2&gt;

&lt;p&gt;ASA enforces a strict separation between AI-generated and human-written regions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example (&lt;code&gt;service.py&lt;/code&gt;):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`python&lt;/p&gt;

&lt;h1&gt;
  
  
  src/domains/auth/slices/login/service.py
&lt;/h1&gt;

&lt;h1&gt;
  
  
  ✅ THIS FILE IS SAFELISTED.
&lt;/h1&gt;

&lt;h1&gt;
  
  
  AI regenerates scaffolding around it, but never touches this logic.
&lt;/h1&gt;

&lt;p&gt;def login_user(ctx: LoginContext):&lt;br&gt;
    if not ctx.user_exists:&lt;br&gt;
        raise UserNotFound()&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return {"token": generate_token(ctx.user)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your logic is never overwritten, even when you regenerate the slice 50 times.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Why Traditional Architectures Struggle in the AI Era
&lt;/h2&gt;

&lt;p&gt;Clean Architecture, DDD, and Hexagonal Architecture were created for a world where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Humans wrote 100% of the code&lt;/li&gt;
&lt;li&gt;Refactoring was manual&lt;/li&gt;
&lt;li&gt;Boundaries were conventions&lt;/li&gt;
&lt;li&gt;Regeneration didn’t exist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In modern AI workflows, regeneration happens daily and AI frequently violates invisible boundaries.&lt;br&gt;
ASA doesn’t replace Clean Architecture — it &lt;strong&gt;stabilizes&lt;/strong&gt; it and makes it safe for AI.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 The 3 ASA Gamechangers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;01 // Regeneration Without Destruction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Update the spec → ASA regenerates only deterministic regions.&lt;br&gt;
&lt;strong&gt;Your custom logic stays untouched.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;02 // The Boundary Guardian&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;ASA blocks cross-slice imports, domain leaks, and architecture drift.&lt;br&gt;
AI agents can no longer "accidentally" break the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;03 // Structural Determinism&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Same input → same output.&lt;br&gt;
No hallucinated folders, no random files.&lt;br&gt;
ASA behaves like a &lt;strong&gt;compiler&lt;/strong&gt;, not a creative assistant.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Try ASA in Practice (8-Minute Demo)
&lt;/h2&gt;

&lt;p&gt;Live demo: &lt;strong&gt;&lt;a href="https://vibecodiq.com/demo/" rel="noopener noreferrer"&gt;vibecodiq.com/demo/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`bash&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Define a slice
&lt;/h1&gt;

&lt;p&gt;mkdir -p domains/auth/slices/login_demo&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Generate contract
&lt;/h1&gt;

&lt;p&gt;asa generate-contract auth/login_demo&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Generate skeleton
&lt;/h1&gt;

&lt;p&gt;asa generate-skeleton auth/login_demo&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Regenerate safely
&lt;/h1&gt;

&lt;p&gt;asa regenerate-slice auth/login_demo&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔮 What’s Next?
&lt;/h2&gt;

&lt;p&gt;This is &lt;strong&gt;Part 1&lt;/strong&gt; of the ASA series.&lt;br&gt;
Coming next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Boundary Guardian — AST-Backed Enforcement&lt;/li&gt;
&lt;li&gt;Zero-Hallucination Scaffolding&lt;/li&gt;
&lt;li&gt;Safe Multi-Agent Workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow me here or on LinkedIn &lt;a href="https://www.linkedin.com/in/voldan/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/voldan/&lt;/a&gt; to join the discussion.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>architecture</category>
      <category>vibecoding</category>
    </item>
  </channel>
</rss>
