Skip to content
Back to all posts

You Didn't Write It. You Still Have to Maintain It.

By Maksym Kuzmitskyi
7 min read
You Didn't Write It. You Still Have to Maintain It.

You Didn't Write It. You Still Have to Maintain It.

The feature works. The tests pass. The agent can explain every file it created.

Now ask another engineer to change one business rule without the original conversation.

That is the test I care about after the demonstration. Not whether a human typed the code, but whether the resulting system can be understood and changed by the people responsible for it.

Generated code doesn't need a special moral category. It needs an ordinary maintenance owner. The prompt isn't that owner, and the model being able to regenerate an explanation isn't a substitute for one.

Understanding is not remembering every line

I wouldn't require an engineer to memorize generated code before accepting it. We don't apply that standard to dependencies or to every change written by a colleague.

I would expect someone to understand the important boundaries: where state is authoritative, where input becomes trusted, which contracts are shared, how failures surface and what a future change is likely to affect.

GitHub's current application card explicitly calls for reviewing and testing generated code. I see that as an acceptance floor, not a complete account of whether another engineer can maintain the result.

That understanding can come from code structure, tests, documentation and exploration. It doesn't require manual authorship.

The concern begins when the implementation can only be explained through the agent that produced it. A maintainer asks why a cache exists, which consumer requires an adapter, or whether a retry can repeat a write, and the answer is to start another conversation hoping the model reconstructs the original decision.

The model may produce a persuasive explanation. Without supporting evidence, it may also produce a new justification for an old artifact.

Local plausibility can accumulate into a confusing system

An agent can reasonably add a helper for one task, another wrapper for the next, and an extra configuration layer to keep the third change small.

Each PR can look tidy on its own. The combined codebase can acquire several ways to perform the same operation, with no clear reason to choose among them.

This is a hypothetical pattern, not a report of a particular employer's repository. It is also familiar without AI. More convenient generation can make local additions cheaper while leaving their long-term coordination cost intact.

OpenAI's 2026 harness-engineering report describes agents reproducing existing patterns, including uneven ones, and discusses mechanical constraints and cleanup in its own experiment. It also explicitly leaves long-term architectural coherence as an open question.

I take that as a reason to inspect accumulating structure, not evidence that every generated system inevitably decays or that a recurring cleanup agent solves maintenance universally.

The important question is what the next change will copy. A convenient local pattern can become an accidental standard simply because it is visible.

A useful abstraction should make the next decision easier

I am not against introducing an abstraction with AI assistance. I want its existence to reduce complexity that actually matters.

For an illustrative payment flow, an adapter separating provider responses from application state can be a clear boundary. Several generic layers that forward the same parameters may only make the behavior harder to find.

The review question isn't whether the abstraction looks sophisticated. It is which variation, dependency or invariant it isolates, and where that value can be observed.

I would ask for a concrete next change. Add a provider error, change a validation rule or remove a consumer. Which files move, and which parts should remain untouched?

This doesn't predict every future requirement. It tests whether the explanation of the current design connects to an ordinary modification rather than a diagram alone.

The same standard applies to hand-written code. AI doesn't make architectural taste objective, but it makes it particularly easy to generate more structure before deciding whether the structure earns its place.

Preserve reasons that aren't visible in the code

A good name explains what a function does. It may not explain why an older implementation still exists or why a seemingly simpler migration was deliberately postponed.

Those decisions deserve a small durable record when they affect future work. Link the relevant requirement or design decision, identify the remaining constraint, and keep the record close enough to be discovered.

I don't want a transcript of every rejected alternative. I want the few facts a future maintainer would otherwise have to guess.

That is consistent with keeping repository context useful: context is an engineering artifact with ownership and freshness, not an unlimited pile of prose.

An agent-written explanation still needs review. It can describe the intended design while the implementation differs, or turn an inference into a historical claim. Documentation should point to evidence and make uncertain reasons visible.

When a constraint changes, update or remove the obsolete explanation. A permanent paragraph defending a temporary workaround can become part of the problem.

Tests should explain behavior, not freeze incidental shape

Tests are part of maintenance because they tell the next engineer what must remain true.

A suite dominated by snapshots of internal structure can make a straightforward refactor feel dangerous without explaining the product invariant. A suite of overly broad mocks can give the opposite impression: every change looks safe because the meaningful interaction is replaced.

Neither snapshots nor mocks are inherently wrong. Their value depends on the question they preserve.

I would prefer a future maintainer to see what a denied operation must do, which retry is permitted, or how a state transition handles interruption. Those are constraints that help a change stay local.

The existing React testing article discusses choosing checks by what they establish. The maintenance angle is what those checks teach someone who didn't participate in the implementation.

A test that merely agrees with generated code can preserve the wrong assumption. A well-founded test can make that assumption challengeable without requiring the original prompt.

Try a handoff change before accepting a large structure

For a consequential generated subsystem, I would give another engineer a small realistic modification. Ask them to identify the owning behavior, explain the relevant invariant and make the change using the available repository evidence.

This is a proposed acceptance exercise, not a measured experiment from my work. It shouldn't become compulsory theater for a two-line fix.

The useful observations are where the person has to guess, which explanation doesn't match the code, and whether an unrelated change becomes necessary just to touch the intended behavior.

Another agent can attempt the exercise too, but its success doesn't automatically establish human maintainability. It may tolerate a structure that a team cannot reasonably review or operate.

I also wouldn't require every handoff to produce exactly the same implementation. Different valid solutions can preserve the same contract. The goal is intelligibility and controlled change, not reproducing the author's path.

Ownership includes deciding not to regenerate

When a generated component becomes confusing, asking for a complete rewrite can be tempting. It can also replace one poorly understood system with another and make the previous review evidence obsolete.

I would first identify the concrete maintenance problem: unclear ownership, duplicated behavior, an unnecessary dependency or a test that prevents safe change. Then repair that boundary with proportionate scope.

Sometimes replacement is justified. It still needs a migration and verification plan, not just a cleaner-looking output.

I want AI assistance to reduce the cost of working on a system, not merely the cost of producing its first version. That means judging generated code by the work it leaves behind as well as the work it completes.

The next engineer shouldn't need the same model, the same prompt and the same conversation to make a safe change. They should have a codebase that explains enough of itself.

What would you ask someone else to change before accepting a substantial AI-generated implementation? I'd be interested in the smallest handoff exercise that reveals whether the design is genuinely maintainable.

About the author

Maksym Kuzmitskyi is a Senior Software Developer focused on React and TypeScript. His work includes enterprise applications, shared frontend components, Node.js integration, testing and accessibility. Alongside frontend work, he designs AI-assisted delivery workflows and has developed personal review tooling.

Telegram

More than a blog post

I share frontend news and the reasoning behind it throughout the day. Pick the language that feels natural to you.

Need to discuss your project? Get in touch.