DEV Community

Cover image for Turn a Codebase into a Domain Model Your PM and QA Can Read
MrOops
MrOops

Posted on

Turn a Codebase into a Domain Model Your PM and QA Can Read

Every team I have worked on keeps two versions of the same product in its head.

One is the code. It is honest about what actually runs, but it speaks in class names and package paths. A PM cannot read it, and even an engineer new to the service cannot tell from it why a rule exists or who asked for it.

The other is the intent. It lives in PRDs, design docs, Notion, and an old Slack thread no one can find. It speaks the language of the business, but nobody keeps it in sync once the code lands. Before long, no one trusts it, and everyone ends up back at an engineer's desk to confirm what is actually true.

These two drift apart every sprint, and the team ends up arguing about which one is right. Braid is my attempt to stop that argument by keeping a single model both sides can read. It is a framework. You bring the sources and pick an ontology, and it runs a loop where the AI drafts and asks, and people decide.

The Shape of the Idea

Braid reads your sources, and an AI drafts a domain model from them. The model is typed by an ontology, so it reads as a domain rather than a call graph. The default ontology is Domain-Driven Design, so a node is a bounded context, an aggregate, a command, or a rule, named in the ubiquitous language of the product.

A domain model is less an extraction than an agreement. The same code admits more than one honest reading, and the one that counts is the one the domain's owners will stand behind. Some of it is never in the source at all, like why a rule exists, and only a person can supply that. So the AI never has the final say. Every change arrives as a proposal a person approves before it lands, and when the AI is unsure how an expert sees the domain, it asks rather than guesses. As the code changes, Braid reacts and feeds the diff back as a fresh proposal, so the model keeps pace instead of going stale.

The result is one artifact an engineer, a PM, and a QA can all point at, traced back to the source it was drawn from.

A Real Run, From Code Alone

The strongest version of the claim is the hardest one. Give Braid a codebase with no docs at all, and see whether it produces something a person would recognize as their domain.

So in Studio I created a workspace, pointed it at conciergent, a service of mine that gives MCP tools a chat face on Slack, LINE, and Discord, and gave it no intent documents at all. Only the code.

Braid splits the codebase into business units first, models each one, then reconciles the overlaps into a single graph. The scan found eight units on this repo, and the reconciled model has 120 nodes and 159 edges across five bounded contexts, with no failed unit.

The conciergent model in Braid Studio, bounded contexts and aggregates

The full example is committed at examples/conciergent.

What Braid Actually Does

Three things, each of which showed up in that run.

1. A Model in the Language of the Domain

The nodes are not classes. They are the concepts the product is about, described in plain language. Here is one aggregate from the run, its description quoted directly with the trailing state diagram left out:

Pending Approval. A sensitive action held back until the user says yes. When the assistant wants to use something the tool provider marked destructive, the action does not run: the work already in flight is set aside and the user is shown a confirmation with Confirm and Cancel.

Rules that always hold:

  • At most one confirmation waits per conversation, and picking it up consumes it, so the same held work can never run twice.
  • The confirmation ages out on its own, and held work that can no longer be read counts as expired.
  • One answer decides every action held in that pause.

Nothing in there is Domain-Driven Design jargon, and nothing is a code identifier. It reads like a domain expert explaining the rule, because that register is exactly what the ontology asks the model to write in. A PM can read it, a QA engineer can turn each rule that always holds into a test, and an engineer can check it against the code.

2. The AI Drafts, a Person Decides

An AI-built model will not always match how each expert sees the domain. So Braid does not let the AI write to the model directly. Every change is a proposal, reviewed before it lands, and every disagreement is settled by a person rather than by the model's confidence.

When the model runs into something genuinely ambiguous, it does not paper over it. It raises a question and waits for an answer, and that answer becomes part of the model. The loop is the point. The AI does the drafting, the people who own the domain do the deciding, and neither one is doing the other's job.

Answering a clarification in Studio, then reviewing the proposal it produces and applying it to the domain model

Answering a clarification, running clarify to turn it into a proposal, then reviewing the diff and applying it. The model gains the node the moment it lands.

3. Every Claim Points Back at Its Source

Each node carries a reference to the source it was drawn from, down to the file and line for a code source. A claim in the model can be traced back to the exact place it came from, rather than taken on trust. When you disagree with a node, you can open the evidence and see what the AI was reading when it wrote it.

A View You Can Hand a PM or QA, Projected From the Model

The model is the one artifact everything else derives from. Everything else is a view of it, a read-only projection you regenerate rather than a second copy that drifts. A document is one such view, rendered a file per bounded context or just the one you point it at, in the same plain language as the model, for whoever has to understand it without reading code. Because it all comes from one model, a view can be cut to what a team needs, scoped wider or narrower, aimed at a different reader, or shaped as something other than prose.

Here is how the doc it generated for the Conversation Turn Lifecycle context opens, unedited:

Conversation Turn Lifecycle

A person sends one message in a chat app and expects one useful answer back. Answering can detour through a sign-in, a confirmation the user has to tap, or a conversation so long the assistant can no longer hold all of it. This subsystem owns that single round trip, from an arriving message to a sent reply and an up-to-date conversation memory.

It goes on with a glossary of the terms the subsystem uses, the people it serves, each use case with the rules that always hold, and a lifecycle diagram. None of it is in code terms, and a draft banner sits up top because every node is still unreviewed. It closes with the exact nodes it was drawn from:

Source nodes: ctx.conversationTurn, actor.chatUser, agg.turn, cmd.runTurn, evt.replySent, rule.oneReplyPerTurn, and twenty-five more.

Regenerate it after the model changes and it changes with the model.

How It Compares

I did the homework so you do not have to. Braid sits next to three kinds of tool teams reach for today, each solving part of this problem.

Braid Team Docs AI Repo Wiki Self-Writing Wiki
A Typed Graph Model Yes, Nodes and Edges No, Pages Partly, Diagrams Partly, Linked Pages
Speaks the Domain Yes Yes No, Code-Facing Partly, Freeform
Keeps Pace With the Source Yes, Reacts to Source No, Drifts Yes, Regenerates Yes, Compounds
A PM or QA Can Read It Yes Yes Partly Yes
One Reviewed Source of Truth Yes, Human-Gated No, Hand-Maintained No, Auto-Generated No, Self-Written
Traceable to the Source Yes, Per Node No Partly, Links to Code Weak
Examples Notion, Confluence DeepWiki LLMwiki

Reading guide:

  • Team docs in Notion or Confluence are the simplest option if you can live with prose that drifts.
  • AI repo wiki like DeepWiki gives the quickest read on an unfamiliar repo, but it documents the code rather than the business, and nobody reviews what it writes.
  • Self-writing wiki like LLMwiki maintains itself and resolves contradictions on its own, but that is also the risk, the AI has the final say and you are out of the loop.
  • Braid is for one reviewed, traceable model of the domain that engineers, PMs, and QA can all read and that keeps pace as the code moves.

What Is and Is Not There Yet

Braid is a young project, and I would rather be precise than oversell it. Everything above works today. What does not, in case it would block you:

  • Ontologies beyond DDD. The ontology is a plugin and the framework does not assume DDD, but DDD is the only one shipped so far.
  • Agents beyond a coding agent. The model is built by a coding agent today. A general chat surface over the model is on the roadmap, not in the box.
  • Proof at scale. The runs so far are modest repos like the one above. Whether the model stays coherent on a large, sprawling codebase is unproven, and it is genuinely hard to validate.

If one of these is what stands between you and trying it, an issue with the shape of your problem helps more than my guesses.

Wrapping Up

This is a personal side project, built to settle an argument I have watched teams have for years. If the drift between what shipped and what the team meant sounds like your problem, give it a run and open an issue with what is missing.

Top comments (0)