You asked the agent to “tweak the download popup.” It went off, edited three files, and came back confident. Two of the three were wrong. You rephrased. You added detail. You pasted the relevant component. On the fourth try it finally landed — on a file called DownloadModal.tsx.
You spent five minutes fighting over a word. The agent never had a “popup.” It had a modal. You were both pointing at the same UI element and naming it differently, and every prompt in between was the two of you talking past each other in slightly mismatched English.
This is the failure mode everyone misdiagnoses. You assume you prompted badly and resolve to write longer prompts next time. But the agent didn’t misunderstand your intent. It couldn’t resolve your noun. That’s not a prompting skill gap. It’s a missing shared vocabulary — and you don’t fix a vocabulary problem by talking more. You fix it by writing the dictionary down once.
The gap is a naming gap
Section titled “The gap is a naming gap”Context engineering starts from a lopsided pair: the agent is broad but contextless, you are narrow but deep. It has read more code than you ever will. What it has never read is your codebase, with its particular history of names — the modal that the rest of the world calls a popup, the Workspace that’s really a tenant, the direct versus cdn download URLs that one engineer split in 2023 and nobody renamed since.
Those names are tribal knowledge. They live in three places: the code, the heads of the people who wrote it, and nowhere else. The agent can read the first. It cannot read the second. And when you prompt in your own private dialect, you’re not even handing it the first cleanly — you’re handing it a translation problem on top of the actual task.
None of this is a new problem; what’s new is who’s at the table. Domain-Driven Design named the cure back in 2003 — the ubiquitous language: a single vocabulary, built jointly by the people who know the domain and the people who write the code, used everywhere from standup to class name so that intent and implementation stop diverging in translation. The agent is just the newest party to that contract — and the one that, unlike a human hire, can’t absorb the dialect by osmosis over months of code review. It needs the dictionary handed to it, written down, on day one.
So close the gap where it actually is. Make the agent surface the project’s real vocabulary, commit that vocabulary to a file, point your rules at it, and then prompt using the agent’s own words. Three primitives, one loop.
Step 1: send subagents to read the dictionary you never wrote
Section titled “Step 1: send subagents to read the dictionary you never wrote”You could grep for terms yourself. Don’t. You already know your own dialect — that’s the problem. You want the terms as the codebase actually names them, surfaced by something that reads the code without your assumptions baked in. That’s a job for subagents: dispatch parallel explorers, each mining one slice of the repo, each reporting back a clean list instead of dumping a thousand lines of source into your main context.
Context isolation is the whole point: you don’t want the raw files in your working window, you want the distilled terms. Each subagent reads broadly and reports back narrowly.
Spawn 3 explore subagents in parallel. Each reads its assigned areaand returns ONLY a glossary of domain-specific terms — names that areparticular to THIS codebase, not generic programming vocabulary.
For every term return: - the term as it appears in the code (exact casing/identifier) - the plain-English thing it refers to - 1-2 file paths where it's defined or central
Subagent A: src/components and src/pages (UI nouns)Subagent B: src/lib, src/server, data models and API layerSubagent C: config, infra, build, and deploy scripts
Skip framework/library terms. I want the words a new teammate wouldhave to learn on day one. Merge nothing — return three raw lists.You merge the three lists yourself, because you are the SME who knows which collisions matter. The agent gives you modal from the UI explorer and you, reading it, finally see: that’s the popup I keep mistyping.
Step 2: commit the glossary to the repo root
Section titled “Step 2: commit the glossary to the repo root”A glossary that lives in your chat history dies with the session. The fix has to be durable and shared, which means it goes in the repo — at the root, where it’s findable, version-controlled, and reviewable in a PR like any other artifact. Naming the things is now a code change, not a personal note.
# Domain Glossary
Canonical names for things in this codebase. Use these exact terms inprompts, commits, and PRs. If you catch yourself calling something by adifferent name than what's here, fix the name or fix this file.
| Term | Means | Lives in || --------------- | ---------------------------------------------- | --------------------------------- || modal | The overlay UI we informally call a "popup" | `src/components/DownloadModal.tsx`|| direct URL | Download link served straight from origin | `src/lib/downloads.ts` || CDN URL | Download link served via the edge cache | `src/lib/downloads.ts` || Workspace | A tenant. NOT a UI panel. | `src/server/tenancy.ts` || seed | A pre-publish blog draft, never a DB seed | `src/content/_drafts/` |This table is the artifact that closes the gap. The left column is the agent’s language. The middle column is yours. The file is the place the two are reconciled, once, for everyone — including the next agent session, the next teammate, and the version of you who forgets in three weeks.
Step 3: make it load as context, not as a file you hope gets read
Section titled “Step 3: make it load as context, not as a file you hope gets read”A committed file the agent has to be told to read is barely better than a Slack message. The glossary has to enter the agent’s context automatically, every session, with no prompting. That’s exactly what rules are for — the persistent context layer the agent reads before it does anything. The pattern is the same wherever your agent looks for that layer: an AGENTS.md or CLAUDE.md at the repo root, a Copilot instructions file, a Cursor rules file. Point whichever one your team uses at the glossary.
You don’t paste the whole glossary into the rules file; you reference it, and you give the agent an instruction about how to use it.
## Vocabulary
This project has a domain glossary at `GLOSSARY.md`. Read it beforeworking. Use its canonical terms in code, commits, and replies.
When I describe something using a word that isn't in the glossary butclearly maps to a term that is, work with the canonical term AND tell mewhich word I should have used. If you hit a domain noun that isn't in theglossary at all, propose an entry for it.Now the dictionary is shared context in the truest sense: the deep-but-narrow knowledge that lived only in your team’s heads is written down where the broad-but-contextless agent reads it on every turn. The translation step that used to cost you four prompts now happens silently, up front.
Step 4: keep it from rotting
Section titled “Step 4: keep it from rotting”Vocabulary drifts. New features add new nouns. You don’t want to retype the three-subagent dispatch every quarter, so freeze it as a slash command — a reusable prompt you and your teammates invoke by name.
Re-run the domain-glossary sweep.
1. Spawn 3 explore subagents over UI, server/data, and infra. Each returns only codebase-specific terms (exact identifier, plain-English meaning, defining file).2. Diff their findings against the current GLOSSARY.md.3. Show me: NEW terms, terms whose meaning has DRIFTED, and entries pointing at files that no longer exist.4. On my approval, update GLOSSARY.md. Don't touch anything else.Run /glossary after any sizable feature merge. The sweep becomes maintenance instead of archaeology, and the file stays trustworthy enough that people actually rely on it.
The proof is in the follow-ups
Section titled “The proof is in the follow-ups”Once the glossary is loaded, change how you prompt — use the agent’s words back to it. “Switch the download button to use the CDN URL instead of the direct URL” finds and edits src/lib/downloads.ts on the first pass, because every noun in that sentence is a key the agent already has. Compare it to “make the download link use the faster one.” Same intent. One is a lookup; the other is a guessing game.
Watch the agent’s own output, too. When it replies “I updated the direct URL builder,” that’s the canonical term being handed back to you. Reuse it verbatim in your next message. You’re not adapting to the machine — you’re both finally drawing from the same committed source.
When a session gets hard, grow the glossary
Section titled “When a session gets hard, grow the glossary”Here’s the loop that makes this compound instead of rot. The next time a session takes too much pushing — when you’re three reprompts deep and still not landing — stop and suspect your nouns before you blame the model. Then ask directly:
That took several tries. Which of my words didn't match the codebase'sactual terms? Give me the corrections, and append any missing ones toGLOSSARY.md as a diff for me to review.Now friction has a payoff. Every painful session ends by depositing its lesson into the file the whole team draws from, instead of evaporating into a vague memory of a wall you’ll just hit again next week. The glossary doesn’t get written once and decay. It grows precisely where the language actually broke.
When the glossary isn’t worth it
Section titled “When the glossary isn’t worth it”A caveat, because the discipline has a cost. A glossary earns its keep when the distance between your team’s private dialect and plain English is wide — legacy renames nobody cleaned up, domain nouns a newcomer would stumble over, collisions where one word means two things. On a greenfield solo project you named yesterday, where the code already says what it means, a GLOSSARY.md is ceremony: you’ll spend more time grooming it than you’d ever lose to a misnamed prompt.
The sharper failure mode is over-stuffing. Once the file exists, the instinct is to document every noun — and a glossary that lists Button, User, and fetch next to the genuinely tribal terms buries the five entries that matter under fifty that don’t. The agent reads it on every turn, so a bloated glossary is also wasted context budget. Keep it to the words a new teammate would actually have to be taught. If an entry’s plain-English meaning is the term itself, cut it. The glossary exists for the gaps between your language and the world’s, not as an inventory of your codebase.
Naming is context engineering
Section titled “Naming is context engineering”The instinct when an agent misreads you is to treat it as your personal failing — I should prompt better — and to fix it privately, in your head, one careful sentence at a time. That instinct is wrong twice. It’s wrong because the problem isn’t your phrasing, it’s a vocabulary your team never wrote down. And it’s wrong because the fix isn’t a habit one person carries; it’s a committed file the whole team and every agent session reads from.
Subagents to surface the terms. A glossary file to hold them. A rules file to load them. That’s the recipe, and what it produces is unglamorous and exactly what you want: the agent and the human who actually knows the domain finally calling the same things by the same names, so the edit lands on the first try instead of the fourth.
You were never bad at prompting. You just hadn’t built the dictionary yet — and the best person to write the first draft of it is the agent that’s been reading your code all along.