Skip to content
Back to writing

When AI Writes Faster Than We Understand

When AI Writes Faster Than We Understand architecture illustration

A customer chooses several additions to an order. The software must send the right item identifiers and names to the system that prepares it.

That sounds like a small mapping task. In one implementation I reviewed, removing an empty identifier before pairing identifiers with names could attach the wrong name to a valid item.

A cleanup could make the code look simpler while making the order less trustworthy.

I use AI to investigate proposed changes and challenge their assumptions, including which details must survive the next edit.

These reviews helped me identify specific risks and preserve useful safeguards. I do not have a controlled comparison showing what the same codebase would look like without AI.

The examples here come from AI-assisted reviews. They do not establish that AI originally wrote the code or caused the problems. Company and vendor details are omitted, and illustrative values are labeled.

A shorter function can leave a harder problem

The order mapping received two lists: item identifiers and display names. Their positions connected them. The first name belonged to the first identifier, and so on.

Here is a simplified example with illustrative values:

PositionItem identifierDisplay name
FirstAAddition A
SecondEmptyAddition B
ThirdCAddition C

The required result kept A with Addition A and C with Addition C. The empty identifier should produce no item.

Filtering the identifier list first would move C into the second position. Pairing that shorter list with the original names could then give C the name Addition B.

During the review, we tested two deliberate defects in an isolated copy. One allowed empty identifiers into the result. The other removed empty entries before pairing identifiers with names.

The focused test caught both defects. With that test excluded, the remaining tests passed against those same defects.

It did not prove that a customer had received an incorrect order. It showed how a future edit could change the mapping without the remaining tests detecting it.

Before accepting the cleanup, I wanted to know which relationship the code preserved and how we would detect a break.

Working pieces can still be connected incorrectly

Another review examined a cleanup that moved detailed assertions closer to the code responsible for them. That reduced duplication and gave tests clearer responsibilities.

However, a caller still had to choose the right customer identifier before passing it to a shared operation. Tests for that operation supplied a correct identifier themselves. They could not establish that the caller selected it correctly.

We deliberately changed the caller to pass an order identifier instead. The remaining suite passed; the original caller tests caught the defect.

The recommendation was to preserve a small assertion at that boundary while keeping the useful cleanup. Restoring every deleted assertion would also restore maintenance work that the change had reasonably removed.

I describe the caller experiment and a related fulfillment check in Before You Delete the Test, Break the Behavior. Someone maintaining the caller should be able to see what it must select, preserve, and pass on.

Why faster output can become slower maintenance

AI makes it possible to produce substantial changes before the team has developed a shared understanding of them.

An assistant can introduce a helper without finding an existing one. Both work today. When the business rule changes, someone must discover that there are now two places to update.

A passing test can confirm the implementation's assumptions without challenging them. If both code and tests use the wrong interpretation of a requirement, a green result offers little protection against that misunderstanding.

A local fix can also leave the underlying responsibility unclear. The next request adds another condition nearby. Eventually, a small business change requires tracing several exceptions and guessing which one takes precedence.

These are possible failure mechanisms, not evidence that every AI-assisted project follows the same path. Human-written systems accumulate the same problems. Faster generation increases how much code a team may accept before those problems become visible.

In Maintainability sensors for coding agents, Birgitta Böckeler describes practical experiments with automated checks and architecture review. She reports both useful feedback and new tradeoffs, including smaller components that require more values to pass through them. Her experience illustrates why improving one code metric does not settle the maintenance question.

The cost appears when someone needs to change the behavior, investigate a failure, or explain the system to a colleague.

Make the review earn its changes

I ask AI to justify each proposed addition or removal.

For an addition, I want to know which requirement it serves, who owns that behavior, and why the existing path is insufficient. For a removal, I want to know what protection disappears and what evidence supports removing it.

That is the approach behind how I use AI to make software easier to own.

The evidence should fit the decision. Selecting a customer identifier deserved a focused regression experiment. Renaming a local variable usually does not. A claim about provider behavior needs more than a test that supplies a simulated response.

This takes time. It can also become excessive. Repeatedly asking an assistant to find another concern can produce speculative safeguards and abstractions that the business does not need.

I want to stop when the required behavior is clear, relevant checks support it, and I can explain why the remaining complexity is needed. New work should follow a new requirement or supported risk.

The next engineer is the harder test

Careful personal review has a limit. If I am the only person who understands why the code exists, the team still depends on me.

A focused test can show that each item must keep the name from its original position. A short comment can explain why removing empty entries first is unsafe. A decision record can explain a boundary that would otherwise look arbitrary.

Repository instructions help an assistant find those sources. They need maintenance too, and should point to authoritative guidance instead of repeating it across several files.

Over time, I would look for comparable changes that stay within the affected part of the system and tests that catch relevant defects. Another engineer should be able to explain the behavior without reconstructing my chats.

Those signals would support a stronger maintainability claim than the number of generated lines or successful review passes. I have not measured them well enough to claim a broad improvement.

When the business adds an order option, the next engineer needs to know why we pair identifiers with names before filtering. The order must still contain the items the customer chose.

Discuss on Twitter