Don’t Make AI Remember What the Architecture Can Enforce

Over the last couple of weeks, I've written about two lessons that came out of working with AI on increasingly large software projects.

The first was that important rules eventually need to become more than instructions.

If an AI can violate an important architectural rule and still produce a successful build, then the rule is mostly a guideline.

The second was that when an AI repeatedly makes the wrong architectural choice, we should look beyond the immediate mistake.

Sometimes the AI didn't create the architectural problem.

It exposed it.

There is one more step in that progression.

Once you know what the right implementation is, stop asking AI to remember how to recreate it.

Make the architecture use it.

There is a difference between a capability and a copy of a capability

AI has made it astonishingly easy to build the first version of almost anything.

Tell an AI that you want a Markdown editor and you can have something on the screen remarkably quickly.

Tell it you need a document viewer and it can build one.

Tell it you need a grid, a dialog, a navigation shell, a settings panel, or almost any other familiar software component and it can produce something that looks pretty convincing.

That is one of the genuinely wonderful things about AI-assisted programming.

It is also easy to confuse what appears quickly with what has actually been built.

There is a large difference between:

Add a Markdown editor to this application.

and:

Build a Markdown editing capability that we are willing to depend upon across multiple commercial products and eventually place in the hands of other developers.

The first one may take an afternoon.

The second one may take months.

The first 80 percent has become very cheap

Getting text into an editor is easy.

Rendering Markdown is easy.

Putting a toolbar above it is easy.

Showing a preview beside it is easy.

AI is very good at getting you to the point where you can look at the screen and say:

That works.

Unfortunately, users don't stop there.

They paste something unusual.

They drag in an image.

They copy content between documents.

They use a combination of formatting that wasn't in the demonstration.

They follow a link.

They paste a link.

They work with an image whose path doesn't look like the ones you tested.

They switch between editing and preview.

They do something in one product and expect it to behave exactly the same way in another.

Then you discover that the thing that "worked" was really just the beginning.

That's where the work starts accumulating.

You fix one edge case.

Then another.

Then one fix exposes another interaction.

You improve the user experience.

You make behavior consistent.

You add regression tests because the bug you fixed last month has just come back.

You refine how the component fits into the surrounding application.

Eventually you have something very different from the first AI-generated demonstration.

You have a piece of infrastructure.

We spent a lot of time getting there

At LANSRAD, we have spent an inordinate amount of time developing some of the core technologies underneath the applications we've been building.

That was intentional.

We didn't simply want something that looked good in a screenshot.

We wanted components we could depend upon ourselves.

That meant selecting the underlying technologies carefully.

It meant integrating them.

It meant making them work consistently together.

It meant finding all of the odd little cases that only appear after you've actually used something for a while.

It meant fixing those cases without breaking the ones we'd already fixed.

It meant taking capabilities that AI could demonstrate quickly and doing the much less glamorous work required to turn them into professional tools.

Our Markdown editing capability is one example.

Our viewing technology is another.

These are not things we built because one application happened to need a control on one screen.

They became technologies we were willing to use as foundations.

That distinction turns out to matter.

The core technology wasn't drifting

As PageSnip and our ProHelp applications evolved, we started seeing inconsistencies.

At first, that sounds like a problem with the shared technology.

It wasn't.

The technologies underneath the applications were doing what they were supposed to do.

The drift was happening around them.

One application needed something slightly different.

An AI worker solved it locally.

Another application needed similar behavior.

Another worker produced an implementation there.

A prompt told the worker how the established version behaved.

A handoff explained which pattern to follow.

An architecture note identified the preferred approach.

Most of the time that worked.

Sometimes it didn't.

Over enough iterations, those small differences accumulated.

The problem wasn't that the proven component had suddenly become unreliable.

The problem was that we were still allowing applications to create their own interpretations of behavior that should have existed only once.

We were asking AI to reproduce knowledge

Looking back, I think this was the mistake.

We had already paid the cost of learning how something should work.

Then, instead of making every application consume that result directly, we sometimes transferred the knowledge.

Here is how PageSnip does it.

Here is the pattern.

Here are the rules.

Here is the implementation you should follow.

Here is what must remain consistent.

That sounds reasonable.

It is certainly better than telling the AI nothing.

But it introduces a completely unnecessary question:

Will the AI reproduce this correctly?

Once the answer already exists, why are we even asking that question?

If there is one right implementation, have one implementation

This sounds almost embarrassingly obvious when written down.

If there should be one Markdown editing capability, there should be one Markdown editing capability.

PageSnip can use it.

ProHelp Studio can use it.

Another product can use it.

A Clarion developer using one of our core components can use it.

But those applications shouldn't each contain their own version of what the component is supposed to do.

Once we reached that conclusion, something important changed.

We stopped trying to make several implementations stay identical.

We started making sure there was only one implementation to keep correct.

That is a much stronger architecture.

This is where rules become structure

Consider two ways of expressing the same requirement.

The first is an instruction:

When adding Markdown editing functionality, make sure you follow the established implementation used by our other products.

The second is an architecture:

This application consumes the shared Markdown editing component.

The first requires judgment.

The worker has to find the right implementation.

It has to understand it.

It has to identify which pieces matter.

It has to reproduce them correctly.

It has to recognize which differences are intentional and which are accidental.

It has to keep doing that as the original implementation evolves.

The second doesn't require any of those things.

The application uses the component.

That's the difference between making AI remember an architectural decision and making the architecture embody the decision.

Don't teach AI how to rebuild what you've already built

I think this is becoming one of my more important rules for AI-assisted software development.

Don't teach AI how to rebuild what you've already built. Make it use what you've already built.

That applies far beyond editors and viewers.

If there is one authentication implementation, use it.

If there is one rendering pipeline, use it.

If there is one persistence layer, use it.

If there is one package responsible for a business rule, go through that package.

If there is one validated way to produce an artifact, make that the path to producing the artifact.

Every time we replace "remember how this is supposed to work" with "use the thing that already works," we eliminate an opportunity for drift.

This doesn't mean everything belongs in one giant library

There is an obvious danger in taking this too far.

Not every similar-looking piece of code should be shared.

Two things can look alike while serving different responsibilities.

Prematurely forcing unrelated behavior through one abstraction can create a different architectural mess.

The goal isn't maximum reuse.

The goal is a clear source of authority.

If two products genuinely need different behavior, let them differ.

If a product-specific layer needs to extend a common capability, create an intentional extension point.

But when several products are supposed to be doing exactly the same thing, reproducing that behavior independently is asking for trouble.

AI simply makes that trouble arrive faster.

The same component should mean the same experience

There is another reason this matters to us.

One of our goals with the LANSRAD core technologies is that developers should be able to recognize the relationship between the applications we build and the components we provide.

If you see a viewing capability working in one of our applications, the corresponding core component shouldn't be a rough approximation that was rebuilt later for developers.

If you see our Markdown editing capability in one product and then use the corresponding core technology in your own application, our goal is for you to be working with that same proven capability.

The same behavior.

The same foundation.

The same lessons learned from actual use.

That's useful for us because we aren't maintaining separate imitations.

It is useful for developers because they aren't starting where we started months earlier.

They get the benefit of the work that happened between "AI can build this" and "we are willing to ship this."

A commercial component has to survive reality

This is also where I think some of the excitement around AI-generated software can be misleading.

AI can absolutely generate something that resembles a commercial component.

Sometimes it can generate a very good one.

But code appearing on the screen isn't the expensive part anymore.

The expensive part is discovering everything the code didn't account for.

The edge cases.

The interactions.

The compatibility issues.

The user expectations.

The regression cases.

The little details that don't show up in the original prompt because you don't know they're problems yet.

That work still has value.

In fact, AI may make it more valuable.

When everybody can generate the first 80 percent quickly, the distinction shifts toward how much work has gone into the remaining 20 percent.

A demonstration proves that something can work.

A mature component proves that somebody has stayed around long enough to discover how it fails.

Shared components also give AI less room to improvise

There is another advantage.

Once the architecture says that a product consumes a shared capability, an AI worker has fewer opportunities to invent a nearby substitute.

It can still misuse the component.

It can still make mistakes in the integration.

No architecture eliminates mistakes.

But an entire class of bad decisions disappears.

The worker no longer needs to decide how Markdown editing should work.

That's already decided.

It needs to decide how this product uses the Markdown editor.

That is a much smaller problem.

This is exactly the kind of boundary that makes AI more useful.

AI remains free to solve the problems where we want creativity.

The architecture removes choices where we have already paid to discover the correct answer.

The conductor should know the difference too

This changes the role of an AI project conductor.

The conductor shouldn't hand a worker a description of an existing capability and ask it to reproduce the capability unless reproduction is genuinely the assignment.

It should identify the authority.

This component owns editing.

That component owns viewing.

This package owns rendering.

This service owns persistence.

Then the worker's assignment becomes integration rather than reinvention.

And qualification can ask a much stronger question.

Not:

Does this new implementation look sufficiently similar to the established one?

But:

Did the product use the established implementation?

One of those questions requires interpretation.

The other can often be answered mechanically.

Sometimes the right thing to do is stop building

This can be uncomfortable in the middle of an active product.

There is always another visible feature to build.

Another screen.

Another capability.

Another bug somebody would like fixed.

Stopping to restructure shared technology can feel like you're moving backward.

Nothing visible may happen for a while.

But there comes a point where continuing forward means continuing to create more things you'll eventually have to unwind.

That's where we found ourselves.

The core capabilities were solid.

What needed attention was the way the larger applications were being assembled around them.

So we stopped pushing some of those applications forward long enough to improve the foundation they shared.

That isn't abandoning working technology.

It is recognizing which technology has already earned the right to become infrastructure.

The best instruction is sometimes no instruction at all

In Mostly Guidelines, I argued that an important rule shouldn't depend forever on an AI remembering it.

In AI Didn’t Create the Architectural Problem. It Exposed It., I argued that repeated AI mistakes can reveal places where the architecture itself is ambiguous.

This is where those ideas lead.

If the right answer already exists, don't create a better paragraph explaining the answer.

Remove the unnecessary decision.

If there is one proven implementation, use one proven implementation.

If there is one authority, make it authoritative.

If there is one capability every product should share, build the architecture so they actually share it.

We still need prompts.

We still need context.

We still need good project conductors.

We still need tests and guards.

But the most reliable instruction may be the one an AI never has to read because the architecture has already made the decision.

Related field note

For the story of why we stopped pushing several products forward long enough to make their shared foundation truly shared, read Where Reality Meets the Road.