A standard cannot live in the prompt

A coding agent gets things wrong with confidence, and the fix is not reviewing harder. It is moving the doctrine out of the prompt and into the repository, where it can be declared once and enforced by machine. The Domain-Driven Context Framework, and what it does not do.
The failure mode is not syntax
A coding agent produces plausible output faster than a reviewer can check it. That is the whole problem, and the first time you meet it you diagnose it wrong, because you go looking for the kind of mistake a compiler catches.
The mistake that matters is a different one. It is a file path invented with confidence. It is a library API from the wrong major version, written with the assurance of someone who read the docs. It is a metric with no source, which survives three reviews because it looks like the sort of number somebody measured. None of that breaks the build. All of it reaches production.
By the time I was running agent-assisted development across more than twenty repositories, that failure mode had stopped being an incident and become a rate. It did not stay contained in one project either: it compounded with every new project, because every new project started from nothing.
The standard was a property of the prompt
The part that took me longest to see is that this was not a quality problem. It was an ownership problem.
The quality of the agent's work was a property of the prompt. Which is to say: of whoever happened to write that prompt, on that day, with the patience they had at that hour. A good prompt produced good code. The same request the following Monday, written by someone else, or by the same person with less time, produced something else.
There was no way to declare a standard once and have every future session obey it. And worse, no way to find out afterwards whether the session had obeyed.
A standard that lives in the prompt is not a standard. It is a habit, and habits do not survive deadline pressure.
The AI does not read minds. It reads documentation.
That is the first of the two sentences the framework rests on, and it is the easy one. The more structured and complete the context, the more consistent the result. Nobody argues.
The second sentence is the one that does work:
Context engineering is finding the smallest possible set of high-signal tokens that maximise the probability of the desired outcome.
Together they form a tension, and that tension is what shapes the design. The first pushes toward documenting more. The second forbids documenting more from meaning loading more on every turn. A context window full of irrelevant doctrine is not a well-informed agent: it is an agent with less room for its actual problem.
The way out is not writing less. It is writing in layers and loading on demand. The agent gets the index, not the archive, and goes down when the work asks for it.
Three layers, each answering what the one above does not
| Layer | Question | Owner |
|---|---|---|
| Business | Why does this exist? | The business team |
| Product | What is being built, and for whom? | The product team |
| Engineering | How is it built, and how is it run? | The engineering team |
The foundation is Domain-Driven Design, and the inheritance that matters is ubiquitous language: one concept, one term, one definition. A domain glossary is the cheapest document to write and the one that cuts invention most, because most of what a model invents is vocabulary.
What the layering buys is not tidiness. It is an owner. A layer with no declared owner is a layer nobody updates, and stale doctrine is worse than absent doctrine, because stale doctrine gets obeyed.
Two directories: what the AI knows, and how it acts
Here is the framework's structural decision.
.contexts/ what the AI knows knowledge
.claude/ how the AI acts executor
.contexts/ is the single source of truth, plain Markdown, nothing tool-specific in it.
.claude/ is the interface the agent actually loads: skills discovered on demand,
specialised agents that each declare which contexts they need to read, hooks bound to
session lifecycle events.
And the rule that makes the pair work: the operational layer references by path, it never repeats.
The reason is what happens when you repeat. A rule copied inside a skill creates two versions of the same standard. Both stay correct for a few weeks. Then one changes, and the one that goes stale is always the copy, because whoever edits doctrine edits the source. Now the agent loads the stale copy and obeys, precisely, a standard that has been revoked. Reference by path has no such failure mode.
Anti-hallucination is a rule, not a review step
This is the inversion that took the most getting right.
The instinct is to treat invention as a review problem: generate, then check. It does not work, because an agent's output volume is larger than a human's review bandwidth. If checking is the next step, it is the step that gets cut when the deadline tightens.
So grounding is a rule, and it is imperative: every file path, every symbol, every library version is confirmed on disk before it is cited. Not after. Verification precedes generation.
That is the inverse of how the model wants to work, which is exactly why it has to be a rule and not a recommendation. A model has a plausible answer available for free, and verification costs a tool call. Without a rule that inverts the order, cheap wins every time.
What an always-active rule costs
Rules split in two: always-active, loaded on every turn, and path-scoped, loaded when the file being touched matches the glob.
The split looks administrative and is economic. An always-active rule costs tokens on every single interaction, forever. So the price of promoting a rule to always-active is deliberately high, and one question decides it: does this need to hold even when the agent does not know it needs to?
Security does. Input validation does. Commit convention does, because the agent does not know it is about to commit until it commits. An accessibility rule does not: it holds when you touch a component, and the glob knows that better than I do.
Without that split the framework has an obvious and silent path to decay. Every new rule looks important to whoever wrote it, they all become always-active, and six months later half the context window is doctrine that does not apply to the open file.
Enforced by machine, or not enforced
Written doctrine is a suggestion until something refuses.
A pre-tool hook rejects a commit that is not a Conventional Commit. A stop hook warns about a claim made without grounding. And my favourite: a session-start hook re-injects the bootstrap skill after every context compaction.
That last one fixes a defect I had not anticipated. A long session compresses context, and what goes first is precisely the instruction from the beginning, because it is furthest away. The agent carries on working, with the same confidence, under no standard at all. Nothing signals it. Losing context must not silently reset the standard, and the only way to guarantee that is a lifecycle event, not a good practice.
Where enforcement can be mechanical, it is. Where it cannot, it is a rule, and the rule is written as an imperative rather than as advice.
What this framework does not do
Here is the part usually missing from writing about one's own framework.
DDC has two readings, and they do not describe the same thing. The general specification has four layers: the three above plus Operations, which carries per-department process, handoffs between teams, internal SLAs, tooling, rituals, infrastructure, monitoring and incidents. What I run in a code repository has three, and folds the technical half of Operations into Engineering.
The technical half survives that fold well. Infrastructure, environments, monitoring with a threshold per signal, incident severity, on-call, post-mortem: all of it is engineering process and it lives in Engineering without being forced.
The organisational half does not survive. Marketing process, sales process, legal process, handoffs between teams, SLAs between teams, company rituals: none of that has a home in a three-layer tree inside a code repository. Nor should it. A code repository is no place for an editorial calendar.
The cost of the fold is measurable in the specification's own table, which lists the layers each area depends on:
| Area | Layers it depends on | Served by the three-layer reading? |
|---|---|---|
| Product | Business, Product, Engineering | Yes |
| Engineering | Product, Engineering, Operations | Yes, its Operations was folded in |
| Marketing | Business, Product, Operations | No |
| Sales | Business, Product, Operations | No |
| Legal | Business, Operations | No |
| Support | Product, Operations | No |
| Customer success | Product, Business, Operations | No |
Two of seven.
So the honest sentence is this: the framework I run is an engineering framework. The framework I specified is a company framework. Same name, and the difference is one layer.
Writing that down is more useful than picking between the two, because the pick changes with who is adopting. An engineering team that takes the four-layer reading will carry process that belongs to other people. A company that takes the three-layer one will discover the gap the day marketing asks for context and has nowhere to look.
What is still open
Three things.
First, whether the Operations layer becomes a fourth layer here, or a separate artefact, or whether the two scopes get different names. All three resolve it, at different costs.
Second, impact measurement. The framework has an implementation roadmap whose last step is measuring time saved and quality, and that is the step I have not done. What exists measured is inventory: how much doctrine, how many repositories, how much readable history. That is counted at /method, with the scope of each number written beside it. It is not the same thing as proving productivity, and swapping one for the other would be exactly the kind of number this framework exists to prevent.
Third, the thing that stays open in any framework running in production: the doctrine written before a counter-example existed. Every rule here came from a real defect, and the ones that have not cost anything yet are the ones I trust least.
The system serving this text was built inside the framework, under a build gate, with tests that refuse a claim without proof. It is not the most spectacular demonstration available. It is the one I can show.