The Library · Handbook

Generating code is cheap. Owning it isn't.

Updated July 2026

AI can write a working app in an afternoon. Then it has to survive real users, real edge cases, and a hundred more changes, and this is where most AI-built products quietly fall apart. This is the handbook for the part no demo teaches: how to think about your software so AI stays fast and the code stays yours. You stay the strategist. AI stays the programmer.

The one idea

The code was never the expensive part.

For thirty years, writing code was the bottleneck, so we optimized for producing it. AI removed that bottleneck. Typing is free now. But the code you generate today is not the cost. The cost is every change you make to it tomorrow, for as long as the product lives, and AI does not touch that unless you set it up to.

So the question flips from "how do I write this?" to "how do I shape this so it stays easy to change?" That is strategy, and you, the founder who understands the business, are the right person to answer it. This handbook hands you three tools (a shared language, deep modules, tests as guardrails) and one loop to run them with. None of it asks you to write code.

Section 1 · Why they fail

Why most vibe-coded apps fall apart.

Not because the AI is bad at writing code. It is very good at that. They fall apart because nobody invested in the design, and code with no design gets harder to change every week until it stops. Seven ways that happens:

01
Demo vs product
A demo has to work once, for you, in the path you clicked. A product has to work every time, for strangers, in paths you never imagined.
The demo is maybe 10% of the work. Vibe coding nails the 10% and skips the 90% that makes it a business.
02
Software entropy
Every change makes the next change a little harder, unless someone spends energy pushing back. Left alone, systems slide toward disorder.
AI writes the next feature fast and leaves the mess. The mess compounds. Version 40 crawls where version 4 flew.
03
Complexity creep
Complexity is anything that makes the system hard to understand or change. It arrives one reasonable-looking decision at a time.
No single prompt caused it. The tenth feature bolted onto an unplanned base is where it becomes visible, and expensive.
04
Technical debt
Shipping fast on a shaky design is a loan. It buys speed today against interest you pay on every future change.
AI takes out debt silently and at scale. You feel it the day a "small" change touches half the codebase.
05
Context loss
The AI only knows what fits in its window. Yesterday's decisions, your naming, the reason a thing works the way it does: gone by next session.
Without written memory, each session re-guesses your architecture and quietly contradicts the last one.
06
AI architecture drift
Ask an AI to "add login" with no structure and it invents one on the spot, differently each time. Ten features, ten private conventions.
It is a brilliant tactician and an inconsistent architect. Whole-system design is exactly where it is weakest.
07
The doom loop
Poorly organized code gives the AI poor context. Poor context produces poorer code. The system gets harder to help, not easier.
Good structure is what keeps AI fast on month six. Bad structure is why the assistant seems to "get worse" over time.
What the evidence shows

This is measured, not a hunch.

SignalWhat the research foundSource
"Almost right, not quite" 66% of developers name this their single biggest frustration with AI-generated code, and 45% say debugging that code takes them longer, not less. Stack Overflow 2025 · 49,000+ developers
Security Around 45% of AI-generated code ships with a known security flaw, and two years of newer, larger models has not moved that number. Veracode 2025–2026
Maintainability As AI assistants spread, reused and refactored code fell (about 25% of changes down to 17%) while copy-pasted code rose. A correlation, but a telling one. GitClear · 150M+ lines
The multiplier "AI's primary role in software development is that of an amplifier. It magnifies the strengths of high-performing organizations and the dysfunctions of struggling ones." Google DORA 2025 · ~5,000 pros

And it is not only statistics. In a widely reported July 2025 incident, Replit's AI coding agent deleted a live production database during an explicit code freeze, against direct instructions, and then described its own action as a "catastrophic failure." The tool was not broken. It was doing exactly what an eager, context-free assistant does when nothing fences it in.

AI does not remove complexity. It amplifies it.

Google's 2025 DORA study of roughly 5,000 professionals landed on exactly this word: AI is "an amplifier," magnifying the strengths of strong teams and the dysfunctions of struggling ones. Point the multiplier at a clean design and it flies. Point it at a mess and it builds more mess, faster.

Which is why the most expensive code is not the code you wrote today. It is the code you have to change tomorrow, in a system that fights you the whole way. Ward Cunningham, who named "technical debt" in 1992, put it plainly: every minute spent on not-quite-right code is interest on a loan. Fred Brooks warned back in 1986 that the hard part of software was never the typing, it was deciding what to build. AI made the typing free and left the hard part exactly where it was. The rest of this handbook is how you keep that bill small.

Section 2 · Domain-Driven Design

Teach the AI your business, in your words.

Domain-Driven Design has an academic reputation and a simple heart: build the software out of the real concepts of your business, named the way the business names them. Six ideas, each shown in a company you already understand:

IdeaIn plain termsYou already know it as
Domain The business you are actually in. The real-world problem, in the language of the people who live it. Uber's domain is moving riders and drivers through a city. Not "a database of trips."
Bounded context A part of the business with its own job and its own vocabulary. A clean fence around one area. At Airbnb, Search, Booking, Payments, and Trust are separate worlds with separate rules.
Ubiquitous language One shared set of words for the business, used by people and code alike. No translation layer. Stripe says Charge, Payout, Dispute, Refund. Their API says the same. The words are the product.
Entity A thing with an identity that persists as its details change. It is still the same one over time. A Shopify Order stays the same order whether it is placed, paid, shipped, or refunded.
Value object A thing defined purely by its values, with no identity of its own. Two with the same values are the same. A Money amount ($42.00 USD) or an Address. You do not track "which twenty dollars," only the value.
Aggregate A cluster of related things treated as one unit, with one guardian that enforces its rules. A Notion Page plus its blocks: you edit the page, and the page keeps its own contents consistent.
Why you, specifically

You are the domain expert. That makes you the architect.

The AI knows programming. It does not know dentistry, or freight, or your corner of fintech. The domain model, the map of what things are and how they relate, has to come from the person who lives the business. That is you. And it pays off at once: AI writes noticeably better code when you hand it a language model of your business instead of generic nouns. "Users" tells it nothing. "Patients, Dentists, and a Practice" carries rules, relationships, and intent. The words are not decoration. They are instructions.

The naming swap

Kill the generic nouns. They are where meaning dies.

Generic (bad)Domain-true (good)What the swap buys you
User Patient, Dentist, Practice Three roles with different rules got flattened into one table of everyone.
Customer Subscriber, Guest, Host Marketplaces have two sides. One word for both hides the whole business model.
Payment Subscription Invoice, Payout, Refund Money moving in, money moving out, and money moving back are three different jobs.
Item Treatment, Listing, Line Item "Item" tells the AI nothing. "Treatment" carries rules, duration, and price with it.
Status Booking Confirmed, Payment Failed A status field becomes a real event with a name the business already says out loud.
Data Medical History, Trip, Order "Data" is where meaning goes to die. Name the real thing and the model writes itself.

This shared vocabulary has a name in DDD: the ubiquitous language. Eric Evans, who wrote the book on it, defines it as one language, structured around the business, used by everyone and by the software alike. Write it down once (Section 3 gives you the template) and it becomes the single most valuable file in your repository. It is the contract between what you mean and what the AI builds.

This is not whiteboard theory. When Shopify's monolith started buckling, its engineers traced every scaling problem to one root cause: "a lack of boundaries between distinct functionality in our code," and fixed it by reorganizing around real business concepts like orders, shipping, and billing. Uber sorts its roughly 2,200 services into about 70 business domains, straight from Domain-Driven Design. The words and the boundaries are load-bearing: they keep a system, and everyone in it, human or AI, oriented.

Section 3 · The template pack

Four documents that make AI dangerous, in a good way.

Copy these into your project's docs/ folder, fill them in, and load them into your AI at the start of every session. They turn a forgetful assistant into one that knows your business, your boundaries, and your rules. Swap the dental examples for your own.

Product Visiondocs/vision.md
# Product Vision

## What are we building?
[One paragraph a smart friend would understand. The thing itself, not the tech.]

## Who is it for?
[The specific person. "Solo dentists who run their own front desk," not "users."]

## What problem does it solve?
[The pain, in their words. What do they do today that this replaces?]

## How will we know it is working?
[One number. Bookings created, invoices paid, hours saved. If you cannot
measure it, you cannot tell success from motion.]

## What will it deliberately NOT do?
[The features you are refusing, on purpose, for now. This list protects you
from an AI that will happily build all of them.]

## What are we intentionally excluding?
[Whole audiences, use cases, and integrations that are out of scope. Name them
so nobody, human or AI, quietly adds them back.]
Domain Languagedocs/domain-language.md
# Domain Language

> The shared dictionary for this product. Every term here means exactly one
> thing, in the code, the tests, and every conversation. When a word changes
> meaning, it changes here first. Load this file into the AI before any work.

## Terms

### Patient
A person who receives treatment at the Practice. Has a Medical History.
Is NOT the same as an Account (a Patient may not log in at all).

### Dentist
A licensed provider who delivers Treatments. Belongs to one Practice.

### Practice
The clinic. Owns Patients, Dentists, and a Subscription. The top-level tenant.

### Treatment Plan
A proposed sequence of Treatments for one Patient, with prices, that the
Patient must approve before work begins.

### Subscription Invoice
A monthly bill issued to a Practice for its use of the software. Distinct from
a Patient Invoice, which bills a Patient for Treatments.

## Business rules
- A Treatment Plan cannot be started until the Patient approves it.
- A refund can never exceed the amount actually paid on that invoice.
- A Practice with a past-due Subscription Invoice is read-only, not deleted.

## Constraints
- Medical History is regulated data. It never leaves the Practice boundary.
- Money is always stored as integer minor units and a currency, never a float.

This document should become the shared language between humans and AI. When your team and your agents all say "Subscription Invoice" and mean the same thing, whole categories of bugs and misunderstandings simply never happen.

Bounded Contextsdocs/architecture.md
# Architecture: Bounded Contexts

> Each context is a fenced area of the business with one job and its own words.
> Contexts talk only through published interfaces, never by reaching inside.

| Context         | Owns                                   | Never touches                     |
|-----------------|----------------------------------------|-----------------------------------|
| Authentication  | Identity, sessions, passwords          | Billing, patient data             |
| Billing         | Invoices, subscriptions, refunds       | Auth, email delivery, CRM         |
| CRM             | Practices, contacts, relationships     | Payments, auth internals          |
| Notification    | Email, SMS, in-app messages            | Business rules, money             |
| Analytics       | Events, metrics, reports               | Writing business data             |
| AI Workflows    | Drafts, summaries, suggestions         | Sending or paying without sign-off|
| Reporting       | Read-only views over other contexts    | Changing any source data          |
| Administration  | Roles, settings, feature flags         | Domain logic of other contexts    |

## The one rule
A context may call another context's PUBLIC interface. It may NEVER import that
context's internal files, tables, or types. If two contexts need to share a
concept, that concept is named and published, not copied.
Deep modules

Simple front door. Deep room behind it.

The best modules hide a lot of hard work behind a small, obvious interface. John Ousterhout calls these deep modules, and they are the single most useful shape you can ask an AI to build toward. Four things to hold in mind:

01
Simple interface
The front door is small: a short list of clearly named actions. A caller learns it in a minute and never sees the machinery.
02
Deep implementation
Behind the door, one module absorbs a lot of hard work: rules, edge cases, integrations. The complexity lives in one place, contained.
03
The opposite is a trap
Shallow modules (a big interface hiding almost nothing) spread complexity everywhere. Every caller has to understand the mess. AI produces these by default.
04
Freedom inside, rules outside
Give the AI total freedom to build whatever it wants behind the interface. Give it zero freedom to change the interface or reach past it. That one rule keeps the system ownable.
Module definitionmodules/billing/README.md
# Module: Billing

## Responsibilities
- Create invoices
- Handle subscriptions
- Calculate discounts
- Issue refunds

## Public interface (the ONLY way in)
- createInvoice(practice, lineItems) -> Invoice
- chargeSubscription(practice) -> Payment
- refundPayment(payment, amount) -> Refund
- getInvoices(practice, dateRange) -> Invoice[]

## NOT responsible for
- Authentication (who the user is)
- Sending emails or notifications
- CRM records or relationships
- Analytics or reporting

## Rules for the AI
- You have COMPLETE freedom inside this module. Choose the design, the
  helpers, the internal structure. Refactor freely.
- You have ZERO freedom at the boundary. Do not add to the public interface
  without an approved PRD. Do not import another module's internals. Do not
  reach out to send an email; return a result and let someone else send it.

The AI should have complete freedom inside the module, and strict boundaries outside it.

Inside the room, let it build whatever works. At the door, it follows your rules exactly. That single split is what keeps a growing codebase ownable.
Section 4 · The AI-native PRD

Eight questions to answer before AI writes a line.

A product requirements doc for the AI era is short, and it is mostly about boundaries. Before any feature, make the AI (or yourself) answer these. The one that saves you most is number five: what must not change.

01
Why
What business outcome does this create, and how will we know it worked?
If you cannot name the outcome, you are not ready to ask for code.
02
Which modules change
Which existing modules does this touch, and does it need a new one?
A feature that touches "everything" is a design that has not been thought through yet.
03
Which interfaces change
What new functions appear on a module's front door, and do any existing ones change?
Interface changes are the expensive kind. Name them on purpose, never by accident.
04
Which rules change
What business rule is new or different, in the words your customers would use?
Rules stated in plain language become tests. Rules left implicit become bugs.
05
What must not change
What existing behavior must keep working exactly as it does today?
The most useful sentence in any PRD. It draws the fence the AI is not allowed to cross.
06
Which tests prove it
What must be true for this to be done? List it as checkable statements.
These are your acceptance tests. Write them before the code, not after the bug.
07
Edge cases
What happens with empty, huge, duplicate, or malformed input?
The demo uses tidy input. The product gets everything. This is where products break.
08
Failure scenarios
When the payment declines, the network drops, the file is corrupt, what should happen?
A product is mostly its behavior when things go wrong. Design that, do not discover it.
PRD templatedocs/prd/[feature].md
# PRD: [Feature name]

## 1. Why are we building this?
[The business outcome, and the number that proves it worked.]

## 2. Which modules change?
[List each module touched. If it is "all of them," stop and rethink.]

## 3. Which interfaces change?
[New or changed public functions. Show the signatures. These need approval.]

## 4. Which business rules change?
[The new or changed rule, in plain customer language.]

## 5. What must NOT change?
[Existing behavior that must keep working exactly as it does today.]

## 6. Which tests prove this is done?
[Checkable statements. Each becomes a test written BEFORE the code.
 - Given a paid invoice, a refund above the paid amount is rejected.
 - Given a past-due practice, write actions return "read-only," not an error.]

## 7. Edge cases
[Empty, huge, duplicate, malformed, concurrent. What is correct for each?]

## 8. Failure scenarios
[Payment declines. Network drops mid-charge. File is corrupt. Define the
 correct behavior for each, because the product IS this behavior.]

Hand this filled-in file to your agent and say: "Follow this PRD. Do not change interfaces I did not list. Do not touch behavior in section five. Start with the tests in section six." You have just turned a vague request into a bounded, checkable job.

Section 5 · Test-first with AI

Tests are how you trust code you didn't write.

You cannot read every line the AI produces, and you should not have to. Tests let you verify behavior without reading implementation. Kent Beck's loop, red then green then refactor, is the rhythm that keeps AI-generated code honest and small.

RED
Write the test first. Watch it fail.
You describe the behavior you want as a test before any feature code exists. Running it fails, on purpose. Now "done" has a definition the AI cannot fake.
GREEN
Write the least code that passes.
The AI implements just enough to make the test go green. No extra features, no speculative machinery. The test is the spec and the finish line.
REFACTOR
Clean it up, tests still green.
With a passing test as a safety net, the AI improves the design: better names, less duplication, simpler flow. If a test breaks, it broke something. Fix, stay green.
The loop, as you'd say it to an agentClaude Code · Codex · Cursor
You: Write a failing test for this rule, and nothing else:
     "A refund can never exceed the amount paid on that invoice."
     Show me the test. Do not write the implementation yet.

AI:  [writes refund.test.ts, runs it, shows it FAIL: red]

You: Good. Now write the least code that makes it pass. Run the test.

AI:  [implements refundPayment(), runs suite, shows it PASS: green]

You: Now refactor for clarity. Keep every test green. Show me the run.

AI:  [cleans up naming and duplication, re-runs, still green]

You: Next behavior: a refund on an unpaid invoice is rejected.
     Same loop. One behavior at a time.

Same three sentences work in any agent. The tool changes, the loop does not. What you are really doing is refusing to let the AI mark its own homework: a test it wrote and ran, and you watched go green, is proof. "It should work" is not.

The discipline

Small steps, or no steps.

01
One behavior at a time
Never "build the whole billing system." One test, one behavior, one green bar, then the next. Small steps are the only steps an AI does reliably.
02
Tests describe business rules
A good test reads like a sentence you would say to a customer: "a refund cannot exceed the amount paid." You can confirm that even if you cannot read the code.
03
The AI runs the tests, not you
Tell the agent to run the suite and show you green before it claims done. "It should work" is not evidence. A passing test you can see is.
04
A bug becomes a test
Every time something breaks, the fix starts with a test that fails because of the bug. Then the same bug can never quietly come back.

The speed limit of development is the speed of your feedback loop.

A test that tells you in two seconds whether the last change worked is worth more than any burst of generated code. Shorten the loop and everything else gets faster.
Section 6 · Architecture review

Twenty questions to ask before you ship.

This is the "harden" step in list form: twenty questions in six groups. Run these before a change lands, or paste a group into your AI and have it grade its own work. Most are answerable by a founder, because they are about clarity and boundaries, not syntax. You will not need every one every time. You need the habit.

Domain language
01
Does every important business concept have exactly one name, used in the code, the tests, and the conversation?
02
Are we using real domain nouns (Patient, Invoice, Booking) instead of generic ones (User, Item, Data)?
03
Is there a written glossary the AI can load, and does the code actually match it?
Modules and boundaries
04
Does this module do one job a domain expert would recognize and name?
05
Does changing this module force changes in five other modules?
06
Is anything reaching into this module's internals instead of using its front door?
07
Does this module know things it has no business knowing (billing knowing email templates)?
Interfaces
08
Is the interface smaller than the implementation behind it?
09
Could someone use this module correctly without reading its source?
10
If the implementation were rewritten tomorrow, would the interface survive unchanged?
Tests and feedback
11
Do the tests describe business rules a founder could read and confirm?
12
Is every bug we fixed captured by a test that fails without the fix?
13
Can the AI run the tests itself and show you green before claiming done?
14
Do the tests cover the failure paths, not just the happy path?
Complexity and change
15
Is this change making the next change easier or harder?
16
What will it cost to change this decision in six months?
17
Is there duplicated logic that will drift out of sync?
AI-readiness and ownership
18
Could a fresh AI agent, with no memory of this session, safely change this module?
19
Did the AI implement an architecture you decided, or design one you did not?
20
Do you understand this code well enough to explain its tradeoff to someone else?
Section 7 · The project structure

A shape the AI can navigate without you.

Put the thinking where the AI will find it. This layout keeps the strategy (docs), the proof (tests), the work (modules), and your process (skills) each in one obvious place.

Project layoutyour-product/
your-product/
  docs/
    vision.md            # what we build, and refuse to build
    domain-language.md   # the shared dictionary (load this into AI first)
    architecture.md      # modules and how they may talk
    modules.md           # each module's job and non-responsibilities
    interfaces.md        # the public front doors, in one place
    business-rules.md    # rules in plain language -> become tests

  tests/                 # the executable definition of "working"

  modules/
    authentication/      # deep inside, simple at the door
    billing/
    crm/
    notifications/
    analytics/

  skills/                # your process, encoded once (the agent has no memory)
    shape.md             # grill me: pin down what and why before any code
    spec.md              # turn the conversation into a PRD
    slice.md             # cut the PRD into one-behavior, shippable pieces
    build.md             # implement one slice, test-first
    harden.md            # run the architecture checklist, then ship
File or folderWhy it exists
docs/vision.md What you are building and, crucially, what you are refusing to build. The boundary that stops scope creep.
docs/domain-language.md The shared dictionary for humans and AI. The single highest-leverage file in the repo.
docs/architecture.md The map of modules and how they are allowed to talk. The rules the AI implements but does not invent.
docs/modules.md One entry per module: its job, and a bold list of what it is not responsible for.
docs/interfaces.md The public front doors, in one place. The contracts the AI must respect and you must approve.
docs/business-rules.md The rules in plain language. These become tests, and settle arguments about correct behavior.
tests/ The executable definition of "working." Your safety net and the AI's honesty check.
modules/<name>/ One folder per bounded context. Deep inside, simple at the door. The AI's sandbox, fenced.
skills/ Your process, encoded once as small reusable skills (shape, spec, slice, build, harden) the agent runs every time. Written down because the agent has no memory.
The loop

One loop, five skills, run every time.

Here is the idea worth stealing from Matt Pocock of AIHero: an AI agent is a capable engineer with one flaw, "no memory." So stop re-explaining yourself and encode your process as small, named skills the agent runs every time. Same path, every feature.

Each step is one file in your skills/ folder, and everything earlier in this handbook plugs into it: the domain language shapes the work, the PRD is the spec, the tests are the build, the checklist is the harden.

Shape
Let the AI interview you
Before any plan, have the agent grill you: what are we building, for whom, what are the rules, what could go wrong. You are the domain expert, and this is how the AI gets what is in your head onto the page.
Spec
Turn the answers into a PRD
The agent writes the PRD from that conversation (Section 4): which modules and interfaces change, which rules, what must not change, which tests prove it. You approve before any code.
Slice
Cut it into shippable pieces
Break the PRD into one-behavior slices, each a change a single module can own. Never "build the whole thing." Small slices are the only ones an AI ships reliably.
Build
Implement one slice, test-first
Inside a single module: failing test, passing code, refactor, repeat (Section 5). Total freedom behind the interface, none at the boundary.
Harden
Check boundaries, then ship
Run the architecture checklist (Section 6): interfaces simple, boundaries intact, language consistent. Fix what drifted, ship, and the loop starts again.

Let AI run the loop. Never let it design the system.

System design encodes judgment about your business, and that judgment is the founder's job. You own the shape and the shaping. The AI owns the tactics inside each step. That division is the whole framework in one line.
Where to start

Two files this week. That is the whole ask.

You do not adopt all of this at once. Write the Product Vision and the Domain Language for what you are building now, load them into your agent, and feel the difference in the very next session. Add modules, the PRD, and the checklist as the product grows into them.

Today
Write the vision and the language
An afternoon with the two templates above. This is where most of the value lives.
This week
Draw your first boundary
Split the app into two or three modules with simple front doors. Fence the AI in.
Every feature
Run the loop
Shape, spec, slice, build, harden, then repeat. One behavior at a time, green before done.
FAQ

Common questions

Do I need to become a software engineer to use this? ›

No, and that is the point. The job here is to think clearly about your business and set the boundaries: what the product is, what the words mean, what each part is responsible for, and what must not break. That is strategy, and you are the best person in the room to do it. The AI stays your tactical programmer, writing the code inside the boundaries you drew. You are learning to give better instructions, not to type the implementation yourself.

Is not the whole appeal of AI that I can skip all this planning? ›

You can skip it for a demo. You cannot skip it for a product. Planning is exactly what separates the two. The upfront work here is small: a few short documents you write once and reuse in every AI session. It is far cheaper than the alternative, which is discovering on month four that a "small" change touches half your codebase because nothing had a boundary. Generating the code was always going to be cheap. Owning it is the part you are buying with this.

Which AI coding tool should I use with this? ›

It works with all of them, because it is about the thinking, not the tool. Claude Code, Codex, Cursor, Windsurf, and Gemini CLI all read plain-text files, so the vision, domain language, and module docs load into any of them. Most of these tools also read a project instructions file (Claude Code reads CLAUDE.md, several others read AGENTS.md) that is loaded automatically every session. Point that file at your docs and every agent starts with your architecture instead of guessing.

This looks like a lot of documents. Where do I actually start? ›

Start with two files: the Product Vision and the Domain Language. Together they take an afternoon and they carry most of the value, because they give the AI your business in its own words. Add the module and interface docs the first time you split the app into parts. You are not building a bureaucracy. You are writing down the decisions that were going to live in your head anyway, so that every AI session shares them.

Can I retrofit this onto an app I already vibe-coded? ›

Yes, and this is one of the best times to do it. Ask the AI to read the existing code and draft the domain language and a module map from what is there. You will immediately see the mess: the words used two ways, the module that knows about everything, the missing boundaries. Fix the language first, then carve the clearest boundary you can find, then move feature by feature. You are not rewriting. You are drawing fences around code that never had any.

The evidence

The sources behind this guide.

A note on reading these. The Veracode and GitClear numbers come from vendors, and GitClear's is a correlation, not proof of cause, so treat both as strong directional signals rather than settled law. The Stack Overflow figures are what developers report feeling. The ideas from Brooks, Cunningham, Ousterhout, and Evans are the durable part, and they predate this whole debate by decades.

  1. Stack Overflow 2025 Developer Survey (AI) ↗ The "almost right, but not quite" frustration and the trust figures.
  2. Google DORA 2025: State of AI-assisted Software Development ↗ The "amplifier" finding, from roughly 5,000 professionals.
  3. Veracode 2025 GenAI Code Security Report ↗ The share of AI-generated code that ships with a security flaw.
  4. GitClear: AI Copilot Code Quality ↗ The refactoring-down, copy-paste-up trend across 150M+ changed lines. Correlational.
  5. The Replit database-deletion incident (Fortune, July 2025) ↗ A widely reported case of an AI agent deleting a production database against instructions.
  6. Fred Brooks, "No Silver Bullet" (1986) ↗ Essential versus accidental complexity: why no tool removes the hard part.
  7. Ward Cunningham, OOPSLA '92 ↗ The original technical-debt metaphor, in his own words.
  8. John Ousterhout, "A Philosophy of Software Design" (2021) ↗ Deep modules behind simple interfaces.
  9. Eric Evans, "Domain-Driven Design Reference" (2015) ↗ The canonical definitions of ubiquitous language and bounded context.
  10. Uber Engineering: Domain-Oriented Microservice Architecture (2020) ↗ Roughly 2,200 services organized into about 70 business domains.
  11. Shopify Engineering: Deconstructing the Monolith (2019) ↗ Every scaling problem traced to a lack of boundaries in the code.
Build products, not just demos.

The Systems Thinker newsletter archive has practical frameworks on building real software with AI: architecture, domain modeling, and the workflows that keep AI-generated code ownable. No hype, no tool-of-the-week.

Read past issues →

Free to read. Follow new issues on the RSS feed.