im·a·cto

From the log

Back to the log

Everything Regenerates Except the Nouns

Generation is free, so every implementation in your repo is a prompt away from being rewritten clean. The vocabulary is the layer that stays expensive, and the one thing nothing in your pipeline checks.

You asked for billing on the new plan tier. It came back in twenty minutes: migration, resolver, tests, a commit message better than the ones you write. You read the decisions, they hold up, you merge. What you didn’t read is that somewhere in those four files the person who pays you got called a subscriber, while in the module next to it that same person is a member, and in the admin tool from March they’re an account.

Every one of those files is internally consistent. Every test passes. Nothing is broken, and nothing will be for a while, which is why it never makes it onto anybody’s Tuesday.

nothing you own is checking the words

Walk your pipeline and ask what would have caught it.

Types check shape. A Member and a Subscriber that both carry an id, an email, and a status will never collide, because structurally they agree. The compiler has no opinion about synonyms, and I’ve argued hard for letting it be the tireless reviewer. It reviews what it can see. Tests check the behavior you described, in whatever vocabulary you happened to be using that morning, so they inherit the drift instead of catching it. Lint has nothing to say. The fleet’s own review pass reads the diff and finds it coherent, because within the diff it is.

The one artifact that could catch this is the only one nothing in your pipeline validates. The words.

the check that used to run for free

Synonyms have always crept in. What’s new is that the thing holding them back was never a tool.

It was a person typing slowly with six months of the codebase loaded in their head, badly but continuously. You’d start writing subscriber and some background process would interrupt: wait, we call that a member. Maybe you asked in Slack. Maybe you just changed the word and moved on. That hesitation was a real check, it cost nothing, and nobody ever wrote it down because nobody knew it was there.

A fleet doesn’t hesitate. Each agent sees the context you handed it and the files it opened, and that’s the whole world. Ask for ten features in a week and you can get ten internally consistent dialects, each one defensible on its own, none of them aware of the other nine. Agents don’t go quiet when they hit a gap in context, they fill it, and an unnamed concept is a gap like any other.

one graph, three clients

At GigSmart we ran two React Native apps and a web client against a single GraphQL graph. I’ve written that GraphQL is really a question about who owns the shape of the response, and I stand by that. But the flexibility is the part you notice, and it’s the smaller half of what that schema bought us.

The bigger half was that three clients could not disagree about what a thing was called. You cannot ship an iOS screen using one word and a web page using another when both are reading fields off the same type. The schema forced the argument to happen once, out loud, before anybody built on either answer. A wiki page listing approved terminology asks politely. A schema fails the build.

That is a dictionary with a compiler attached, and it’s worth more than the feature list people buy GraphQL for.

three words holding up a cascade

At Phoneware, the customizations cascade reseller → domain → role. A setting defined for a reseller gets overridden at the domain, and overridden again at the role. Three nouns, and the entire configuration model is just the relationship between them.

If those words are fuzzy, the cascade becomes folklore. Somebody has to ask the one person who remembers whether a domain setting beats a role setting, and that person becomes a dependency. If the words are sharp and they live in the repo, in the manifest API, in the configurator, in the guides the agents read, then an agent can answer that question from source without asking anyone. Same words everywhere is the difference between a rule and a rumor.

the layer that got expensive

The inversion snuck up on me.

For twenty years the implementation was the expensive part, and naming was the cleanup you’d get to later. Names were labels on decisions that had already been made. Now generation costs nothing and any file in your repo is a prompt away from being rewritten clean. The implementation is the cheap layer.

The words are the expensive layer now, because naming is the decision itself. When you settle whether a member and a subscriber are the same person, you’re settling whether there’s one table or two, one lifecycle or two, one set of emails or two, one support workflow or two. And that answer immediately leaks out of the repo: into the API your customers integrate against, the columns in the warehouse, the dashboards finance built, the macros support wrote, the mental model of every person on the team.

One prompt rewrites the implementation.
Nothing rewrites the eleven places outside your repo that already learned the old word.

You can regenerate code. You can’t regenerate agreement, because most of the agreement isn’t yours to regenerate.

an old idea with a new job

Eric Evans named this in 2003. He called it the ubiquitous language in Domain-Driven Design, and Martin Fowler has kept a page on it for about as long. The pitch was that engineers and domain experts should speak one vocabulary so the model in the code matches the model in the business. Good advice. Widely nodded at, rarely funded, because it read like a discipline for teams with spare time.

It has a different job now. A shared vocabulary used to be a human convention, enforced by humans, for the benefit of humans. It’s become a machine-readable interface. The fleet reads your repository and writes in whatever dialect it finds there. Hand it four names for one concept and it picks one per task, confidently, forever. Hand it one and consistency stops being something you enforce in review. This is the part of “write down the why” that I underweighted: the why matters, and so does the what-we-call-it, and the second one is cheaper to write and gets used more often.

  1. Put the dictionary in the repo, not the wiki. A glossary that lives next to the code, in the guides your agents actually load. The nouns, what each one means, and the part everyone skips: where each one stops. “A member has an account.” That possessive is doing the real work. It says there are two things here, so nothing downstream gets to collapse them into one word.
  2. Push the nouns somewhere that can fail. Prose asks nicely and the fleet treats it accordingly. A schema, a database constraint, a shared types package: those break the build. Anywhere a name is load-bearing, move it from a document into something with teeth.
  3. Treat a synonym in a diff as an architecture finding. “Why is this called a subscriber?” is a design question, and review is the last cheap moment to ask it. Renaming a concept costs an afternoon the day it lands and costs a deprecation cycle the day a customer’s integration depends on the word.

where the drift is actually fine

Plenty of synonyms are fine, and hunting every one of them is its own failure mode.

Evans had an answer for this too, and it’s the half people forget: bounded contexts. Billing’s customer and support’s customer can legitimately be different things with different fields and different lifecycles, and forcing one word across an entire company usually gets you a noun so broad it stops meaning anything. Nobody is served by a User that has forty nullable columns and a comment explaining which twelve apply to you.

The test is whether anyone decided. A translation at a boundary you drew on purpose is architecture. Four words nobody chose, spread across a repo by ten agents that never spoke to each other, is drift wearing the same clothes. From a distance they look identical. The difference is whether there’s a person who can tell you why the boundary is where it is.

Go pull up the last thing your fleet shipped for you. Find the most important noun in it, the one the feature is actually about. Then find out who decided that word, and when.

If nobody did, you just found your afternoon. The code will regenerate tomorrow either way. The noun won’t.

Jason Waldrip is a fractional CTO and CAIO through The Bushido Collective, working with founders drowning in AI-generated code and teams scaling past the leadership that got them here. Half of what I do in a codebase is settle the words before the fleet settles them for you. Work with me.

A note on how this was made: I wrote this with AI assistance. The frame, the GigSmart and Phoneware calls, and the judgments about what matters are mine. Claude Opus 5 did most of the drafting. The ubiquitous language and bounded context ideas are Eric Evans’, from Domain-Driven Design, linked above via Martin Fowler.