All essays

Current chapter · Six-part field guide

Part 1 of 6 Building an AI-first development system

AI-first development is a system, not a coding trick

Code generation is useful, but reliable AI-first development needs requirements, context, boundaries, verification, release discipline, and a feedback loop.

5 min readAI EngineeringEngineering SystemsProduct Development

I do not care how quickly a tool produces code if the surrounding system cannot tell whether the code is right.

The code generator is the least interesting part

Code generation is the most visible part of AI-assisted development, so it receives most of the attention. It is easy to demonstrate. A prompt goes in, a component appears, and the room feels as though the difficult part has been compressed into a few seconds. I find the result useful, but I do not confuse it with a development system.

Production work begins before the prompt and continues long after the diff. Someone has to identify the real requirement, route the current product and repository context, divide the work, protect existing behavior, verify the result, release it safely, and feed useful learning back into the next cycle. If those responsibilities remain informal, AI only accelerates whichever assumptions happened to be closest to the keyboard.

When I say AI-first development, I mean that AI is treated as a participant across this complete loop. It can help interpret inputs, propose plans, implement bounded changes, generate checks, inspect evidence, and explain results. It does not become the source of truth. The system around it decides what is true, what is allowed to change, and what evidence is required before the work is called complete.

Local speed can still produce system failure

In one sanitized dashboard exercise, an agent implemented a new action from a design and a short behavior note. The page compiled, the action looked correct, and the happy path worked. Two requirements were still lost: the action had to remain unavailable for one user role, and the selected state had to survive a background refresh. Neither fact was visible in the design frame the implementation started from.

The failure was not that the agent could not write the code. It wrote exactly the local change it had been given. The failure was that the delivery system had no complete route from functional intent to verification. A visually convincing screen hid a permissions regression and a state-lifecycle bug. Faster implementation only made the missing control points arrive sooner.

The artifact I use to make this visible is a delivery trace. It connects the requirement source, current context, assumptions, task boundaries, changed surfaces, verification steps, browser evidence, release decision, and unresolved limitations. It does not need to be ceremonial or large. It needs to make it possible to answer one question without archaeology: why do we believe this change satisfies the product contract?

What I automate

I automate the repeatable movement of information through the loop. Product notes, design context, repository guidance, and known constraints can become an implementation packet. A plan can identify dependencies and split independent work. Scoped agents can implement code and tests while validation scripts check types, builds, routes, translations, and common repository rules.

I also automate evidence collection. The system can run focused tests, open the exact browser path, exercise the relevant state, capture the result, inspect console or network failures, and summarize which acceptance conditions were proved. If a check fails, the evidence can return to the implementation loop instead of becoming a surprise during final review.

The purpose is not to remove every pause. It is to stop humans from repeatedly transporting context, running predictable commands, or reconstructing what happened. Automation should carry the mechanical burden and leave a readable trail. That is how speed becomes reusable instead of depending on one person remembering the entire workflow.

What remains a human decision

A human still decides which problem deserves to be solved, which source wins when product documents disagree, and which behavior is too risky to infer. A human decides whether a design is expressing the requirement or merely illustrating one state. A human also decides when a technically valid result creates the wrong product experience.

I do not want human review reduced to watching every generated line. That would preserve the cost while adding a new layer of supervision. I want people at the judgment points: setting intent, resolving ambiguity, choosing architecture, evaluating trade-offs, reviewing meaningful evidence, and accepting the release.

This distinction matters because responsibility cannot be delegated to an output. An agent can recommend that a requirement has been met. The team still owns what the requirement means and whether the proof is sufficient for the product, the users, and the risk involved.

The useful trade-off

A complete loop adds structure. For a tiny, isolated edit, creating a detailed packet and a large verification plan would be wasteful. I scale the system with the risk. A copy correction may need a focused build and visual check. A permissions workflow, route migration, or shared component change deserves stronger traceability and broader evidence.

The trade-off is deliberate friction at the points where silent mistakes become expensive. Requirements take time to name. Context needs ownership. Agents need boundaries. Proof needs to be collected. That can make the beginning of a task feel slower than an immediate prompt, but it makes the result easier to trust, review, and change again.

That is the standard I care about. AI-first development is not complete because code appeared quickly. It is complete when intent, implementation, evidence, and learning form one accountable system.