The first month of AI-assisted development feels like a superpower. The third month feels like maintaining a codebase written by a contractor who left no notes and cannot be reached.
Nothing broke in between. The generation stayed good. What changed is that the code you did not write accumulated faster than your understanding of it, and every debugging session now starts from zero context. This guide is the map for avoiding that, and it routes to the nine deeper guides underneath it.
Last verified against the linked guides on this site. Version-specific details drift — check the vendor docs before relying on an exact flag or limit.
Why treating the model as a faster typist predicts the wrong bottleneck
The dominant mental model is autocomplete with ambition. You know what you want, the model types it, you save time proportional to the typing.
That model predicts the wrong bottleneck. Typing was never the expensive part of software. Deciding what should exist was expensive, and being able to trust that it works was expensive. AI assistance collapsed the cost of one stage of a pipeline and left the others where they were, which does not make the pipeline faster. It moves the constraint somewhere you were not watching.
Work the four jobs separately, because they now have wildly different costs.
By the end you will have
- The four jobs that AI-assisted development actually decomposes into
- The reason velocity gains convert into review debt, stated as arithmetic
- A rule for sizing a unit of work to what you can verify
- The Four-Job Routing Matrix
- A specific guide to read next for whichever job is currently your constraint
The four jobs, and which one is your constraint
| Job | The question | What good looks like | Go deeper |
|---|---|---|---|
| Specify | What should exist, and what proves it? | Written acceptance criteria before generation | AGENTS.md guide · Next.js AGENTS.md |
| Generate | Which model, which harness, how much per turn? | Small units, right model per task | Vibe coding stack · Multi-model routing |
| Verify | How do I know it works, cheaply and repeatably? | A command ladder, run before you read the diff | Verification loop · Multi-agent review loop |
| Integrate | Does it survive contact with the rest of the system? | Production gate, and a debug path for code you did not write | Production checklist · Debug an AI-written app |
Only one of these is your constraint right now. Almost everyone assumes it is Generate, and for almost everyone it is Verify.
Diagnose it honestly: if you are regularly shipping code you have not read, the constraint is Verify. If you are regularly getting code that solves the wrong problem, the constraint is Specify. If you are getting good code that breaks the app, the constraint is Integrate. Optimizing Generate when your constraint is Verify makes the situation worse, because it increases arrival rate at the stage that was already backed up.
Mechanism dive: how velocity converts into review debt
The arithmetic is simple enough to do in your head, which is why the conclusion is hard to argue with.
A pipeline's throughput is set by its slowest stage. Generation cost fell dramatically. Review cost did not fall at all, because reading code for correctness is the same cognitive work it always was, and reviewing code you did not write is harder than reviewing your own. Authorship gives you a model of the intent. Without it you are reverse-engineering intent from syntax.
So when generation speeds up and review does not, exactly two things can happen. Either review becomes the visible bottleneck and your throughput barely improves, which feels disappointing but is safe. Or review quietly gets skipped, throughput appears to improve, and the unreviewed code accrues as a liability.
The second path is the default because nothing in the tooling forces the first. There is no error when you approve a diff you did not read.
The liability comes due at debugging time, and it comes due at a markup. Debugging code you never read costs more than writing it would have, because you pay the reading cost anyway, under time pressure, with a bug in the room, and without the design context that authorship would have given you for free. That is the whole mechanism. Every practice below follows from it.
Size the unit of work to what you can verify
The single highest-value habit: never request a change larger than the change you are willing to read.
This is a hard constraint, not a preference. If you cannot review 800 lines carefully, do not ask for 800 lines. Ask for the first 150, verify them, then ask for the next. The model is equally happy either way. You are not.
Practical thresholds that follow from it:
- One user-visible outcome per turn. Not one file, not one function. One thing a person could test.
- Verification defined before generation. Write the check first, even informally. "This is done when the form rejects an empty email and the test passes" is a specification. "Add validation" is a wish.
- The cheapest disproving command runs first. Not the full build. The narrowest command that could show the change is wrong, then broaden. Details in the verification loop.
- Read the diff before the output. Working output on a bad diff is the most expensive false positive available to you, because it passes and stays.
The worked example: the same feature, sized two ways
A file upload with validation, progress, and error states.
Asked as one request, the model returns a working component of a few hundred lines. It runs. The temptation to accept it is strong precisely because it works, and everything that is wrong with it is invisible at that moment: the size limit is enforced only in the browser, the error state swallows the server message, and the progress handler leaks a listener on unmount. All three are things a careful read catches and a manual click-through does not.
Asked as four turns, each one is small enough to actually read. Turn one is the server route with the size and type check, verified with a single failing request. Turn two is the client call with an explicit error surface. Turn three is progress. Turn four is the unmount path. The client-side-only limit never happens, because the server route existed before the client did and the order made the trust boundary obvious.
The four-turn version takes slightly longer in wall-clock and produces code you can still reason about in November. That trade is the entire discipline.
Magnet: Four-Job Routing Matrix
Run this diagnostic when AI-assisted work stops feeling like a gain. Find your row, take the action, read the guide.
| Symptom you actually observe | Constrained job | Immediate action | Read next |
|---------------------------------------|-----------------|----------------------------------------------------|--------------------------------------|
| Output solves the wrong problem | Specify | Write acceptance criteria before prompting | agents-md-guide |
| Rules obeyed for 2 turns, then drift | Specify | Move rules from chat into AGENTS.md | agents-md-nextjs-web-projects |
| Approving diffs you have not read | Verify | Cap unit size at what you will read. No exceptions | vibe-coding-verification-loop |
| Bugs found by users, not by you | Verify | Add the cheapest disproving command, run it first | vibe-coding-verification-loop |
| Reviewing is now the whole job | Verify | Add a second-agent review pass before your read | multi-agent-review-loop |
| Good code, broken app | Integrate | Run the production gate before merge | production-checklist-vibe-coded-web-app |
| Cannot debug your own codebase | Integrate | Stop generating. Read and map what exists | debug-ai-written-nextjs-app |
| Paying frontier prices for edits | Generate | Route mechanical work to a cheaper model | vibe-coding-multi-model-routing |
| Unsure which model at all | Generate | Build a private eval set on your real cases | ai-model-benchmarks-that-matter-2026-07 |
| Everything is fine, nothing ships | Specify | Cut scope to one user-visible outcome per turn | agent-os-for-solo-developers |You should see: exactly one or two rows describing your last two weeks. If more than three rows match, the constraint is not any single job, it is that no verification exists at all, and the only correct next move is to stop generating and build the command ladder first.
Failure modes
| Smell | Result | Repair |
|---|---|---|
| Requests sized by ambition, not by review capacity | Unreviewed code compounds silently | One user-visible outcome per turn |
| Verification described in chat, never in the repository | Every session relitigates the commands | Command ladder in AGENTS.md |
| Manual click-through as the only check | Passes while the trust boundary is wrong | Automated check that can fail |
| Accepting output because it runs | Working code on a bad diff, permanently | Read the diff before the result |
| One frontier model for every task | Cost scales with volume, quality does not | Route by task, see multi-model routing |
| New chat for every task | Context rebuilt from nothing each time, rules drift | Persistent rules plus memory |
| Generating faster when review is the bottleneck | The queue grows, the debt grows | Fix the constrained stage, not the fast one |
When not to code with AI
- You do not understand the domain yet. The model will produce something plausible and you will be unable to tell. Learn enough to grade the answer first.
- The blast radius is large and the rollback is not clean. Migrations, auth changes, money movement, anything destructive. Write it yourself and use the model to review.
- The problem is genuinely novel. No prior art means no strong prior. You will spend longer correcting than solving.
- The code will be read far more than written. A core abstraction that fifty files import deserves authorship, because the mental model matters more than the keystrokes.
- You are already at the review limit. More generation makes the situation strictly worse. This is the one everyone gets wrong.
path
Install the whole loop, not one habit
Agent OS Setup connects repository rules, model routing, verification gates, memory, and handoff into one system you can hand to someone else.
Generating code got cheap. Trusting code did not. Every practice worth keeping is a way of paying that second cost deliberately instead of accidentally.
Your next action: run the Four-Job Routing Matrix against your last two weeks of work, find the row that describes you, and fix that job before touching the other three. If you are new to this entirely, start at the ultimate vibe coding beginners guide and come back when the symptoms above start appearing.







