Last week, an AI agent generated a clean implementation for me in minutes.
The tests passed. The types passed. The diff looked reasonable.
Then I tried to explain the change without looking at the code.
I couldn't.
That is when I realized I had been measuring the wrong thing.
I was tracking time to working code. I was not tracking time to understanding.
AI had made the first number dramatically smaller while quietly making the second one larger.
And that trade is starting to show up everywhere: developers shipping faster but feeling less confident, reviewing larger diffs they did not design, and returning to code a week later as if it belonged to someone else.
The biggest risk of AI-assisted coding is not that the agent writes bad code.
It is that it writes good-enough code faster than we can build a mental model of it.
The old loop looked roughly like this:
understand → design → write → debug → understand better
The friction was frustrating, but it forced us to learn the system.
The agentic loop often looks like this:
request → generate → skim → accept → next task
That loop feels productive because artifacts appear quickly. But artifact production is no longer the scarce resource. Judgment is.
Can you answer these questions after merging an AI-generated change?
If not, you did not eliminate the work. You deferred it — with interest.
I call that comprehension debt.
Technical debt lives in the code.
Comprehension debt lives in the gap between the codebase and the team's mental model of it.
You can have elegant, tested, well-typed code and still carry dangerous comprehension debt.
A rough way to think about it:
comprehension debt
= change surface
× unfamiliarity
× time since explanation
This is not a scientific formula. It is a useful warning.
AI increases the change surface. Parallel agents increase it again. Long autonomous sessions increase the time between a decision and a human explanation of that decision.
None of those tools is inherently bad. But the default workflow optimizes for output, not ownership.
Tests are evidence. They are not understanding.
A passing suite tells us that the code satisfies the cases we remembered to encode. It does not tell us:
When an agent says, “Implementation complete. All 84 tests pass,” that should begin the review — not end it.
I now use a five-step protocol for any non-trivial agent task.
Before editing, the agent must explain the relevant system in plain language.
Before changing code, explain:
1. the current request flow,
2. the invariants that must remain true,
3. the smallest likely change surface,
4. the assumptions you are making,
5. the part of the system you are least certain about.
Do not write code yet.
This does two things.
First, it exposes a wrong mental model before that model becomes a 700-line diff.
Second, it gives me a map I can challenge.
If I cannot evaluate the explanation, I am not ready to delegate the implementation.
The plan must describe decisions, not just files.
Bad plan:
- Update auth.ts
- Add tests
- Run lint
Better plan:
- Keep token parsing at the HTTP boundary.
- Pass a verified identity into the service layer.
- Reject expired sessions before database access.
- Add one contract test for the boundary and one unit test for expiry.
- Avoid touching the authorization policy module.
A file list tells you where the agent will type. A decision list tells you what it believes.
Ask for the smallest reversible change.
Implement the plan with these constraints:
- Prefer editing existing code over adding an abstraction.
- Do not modify unrelated formatting.
- Stop if the change requires more than 5 files.
- Do not add a dependency without approval.
- Keep the patch easy to revert.
The “stop” conditions matter more than the clever instructions.
Autonomous agents need a budget: files, dependencies, migration scope, runtime permissions, or all four. Without a budget, “helpful” easily becomes “architectural.”
Do not ask only for green tests. Ask for disconfirming evidence.
After implementation:
1. run the narrowest relevant tests,
2. show one failure-path test,
3. state what remains untested,
4. inspect the final diff for unrelated changes,
5. name the most plausible production failure.
Agents are very good at producing confirmation. Good engineering also searches for ways the idea could be wrong.
This is the step most workflows omit.
Before accepting the change, make the agent hand the system back to you.
Teach me this patch in under 250 words.
Include:
- the problem,
- the key decision,
- the data flow,
- one rejected alternative,
- how to debug the most likely failure.
Then ask me three questions that verify I understand it.
If I cannot answer, the task is not done.
The code may be complete. The transfer of ownership is not.
Repeated prompting is fragile, so I keep the workflow in a small reusable instruction file.
---
name: comprehension-first-change
description: Use for non-trivial code changes where maintainability and human understanding matter.
---
## Before editing
- Explain the current flow and invariants.
- List assumptions and uncertainty.
- Propose the smallest change surface.
- Wait for approval.
## While editing
- Make surgical changes.
- Avoid new abstractions unless required.
- Stop after 5 files or before adding dependencies.
- Preserve unrelated formatting.
## Verification
- Run focused tests.
- Include a failure path.
- State what is not tested.
- Review the final diff for scope creep.
## Handoff
- Explain the patch in under 250 words.
- Name one rejected alternative.
- Give one debugging entry point.
- Ask the human 3 comprehension questions.
Call it a skill, a repository instruction, an AGENTS.md
rule, or a checklist. The format matters less than making understanding an explicit deliverable.
This protocol would be annoying for a typo, a known dependency bump, or a mechanical rename.
I use three lanes:
| Lane | Typical work | Required process |
|---|---|---|
| Green | typo, formatting, mechanical rename | generate, diff, merge |
| Yellow | local feature, bug fix, small refactor | plan, patch, prove |
| Red | auth, payments, data migration, concurrency, public API | explain, approve, patch, prove, teach |
The goal is not to slow everything down.
The goal is to spend human attention where misunderstanding is expensive.
“Lines of code generated” is almost meaningless.
“Tasks completed” is better, but still incomplete.
For AI-assisted work, I care about four questions:
That last question is the uncomfortable one.
If five agents can produce five pull requests while one human can responsibly review only one, you do not have a coding bottleneck anymore.
You have a judgment bottleneck wearing a productivity costume.
AI coding is not going away, and I do not want it to.
It is excellent at removing repetitive work, exploring unfamiliar APIs, generating test scaffolding, and turning a clear plan into a first patch.
But speed without a mental model is rented productivity.
Eventually the lease expires: during an incident, a migration, a security review, or the first change the original prompt did not anticipate.
The durable advantage is not “being good at prompting.”
It is being able to:
Use the agent. Let it be fast.
Just do not let it leave the room with your understanding.
What is your rule for accepting AI-generated code? Is passing tests enough, or do you require the author — human or agent — to explain the system back to the team?