DEV Community

Adam Dworzyński
Adam Dworzyński

Posted on

EA as code: judgment vs. proof

EA as code: judgment vs. proof

Your AI will happily tell you your architecture is consistent. That's a guess.

Ask any capable model to review a system design and it answers in fluent, confident prose: the boundaries look clean, the dependencies make sense, this all hangs together. It reads like a verdict. It's an impression — pattern-matched from text, with nothing underneath checking whether the thing it describes holds together. When the model says your architecture is sound, not one word of that sentence was verified.

I spent a long time doing enterprise architecture the ordinary way, and the same gap was there long before the models arrived. The architecture lived in slide decks and wiki pages. "The architecture is consistent" was a sentence someone wrote, not a fact anyone could check. The AI didn't create the problem. It just made it faster to produce, and gave the guess a more convincing voice.

So I built the other half. It's called EAaC — enterprise architecture as code — and the whole idea fits in one line: the deterministic part proves; the AI part judges, and never the reverse.

Three ways prose architecture fails

Think about where most architecture lives. Not in a system that understands it — in documents that describe it. That produces three failures, and they compound.

  • Unvalidatable prose. "The architecture is consistent" is an assertion nobody can check. There is no button to press, no exit code, no test that goes red. It's true until someone notices it isn't.
  • Monolithic, lock-in-prone tooling. The moment you do reach for rigor, one vendor's modeler owns your model — and it's only as portable, diffable, and reviewable as their export button lets it be. What should be open and checkable stays locked behind that button.
  • Ungrounded AI assistance. Now add a model on top. It's a spectacular writer and a confident reviewer, and it has no way to know whether what it just blessed is coherent. It guesses, in prose, and the prose is good enough that you believe it.

Notice the shape they share: something that should be checkable is left as narrative. Fix that one thing and all three ease at once.

The split

EAaC makes one move. Separate the parts of architecture that must be provably correct from the parts that require judgment. Give the correct parts one home that no host or vendor owns. And treat the body of architectural knowledge — the methods, the types, the rules — as data the system reads, not logic it hardcodes.

Concretely, that's two things with a hard line between them:

  • A small deterministic core (ea, plain tested Python) that owns every operation with a single correct answer: validate, scaffold, graph, report, promote, migrate. Same inputs in, byte-identical output out. No wall-clock, no randomness, no network, no model.
  • Adapter surfaces — today, a Claude Code plugin and a Google Antigravity plugin — where the AI lives. They tailor a methodology to your org, help author artifacts, advise. They propose. The core decides and writes.

The one integration boundary between them is a CLI contract: JSON on stdout, plus exit codes. Everything above that line is judgment. Everything below it is determinism. An agent can't smuggle a guess past the core, because the only way to change your repository is to hand the core a proposal and let it check and apply it.

Proof is an exit code

This is the part that sounds like marketing until you run it, so run it.

Here's a real architecture — a payments system. One command asks the core whether it's consistent:

$ ea validate --all
{ "status": "ok", "diagnostics": [] }
exit: 0
Enter fullscreen mode Exit fullscreen mode

Exit 0. Not "looks fine" — checks out. Every reference resolves, every rule the method carries is satisfied. Now I'll break it the way a real change breaks things: a service that realizes a capability, pointed at a capability id that no longer exists.

$ sed -i 's/payment-processing/payment-processing-GONE/' …/card-authorization.md
$ ea validate --all
{
  "status": "invalid",
  "diagnostics": [
    { "code": "reference.dangling",
      "message": "reference {type: capability, id: payment-processing-GONE} does not resolve" },
    { "code": "reference.shape",
      "message": "relationship 'realizes' target is not a valid reference" }
  ]
}
exit: 3
Enter fullscreen mode Exit fullscreen mode

Exit 3. No human declared it fine; no model waved it through. The core found the dangling reference and said so, precisely, and it did it with an exit code. Exit 3 means "the tool ran fine, the architecture is invalid," kept deliberately distinct from exit 1/2 (tool and usage errors) and exit 4 (a write-guard). A CI pipeline can then fail the build on a real architectural finding and nothing else:

- run: ea validate --all    # exit 3 fails the build, with JSON diagnostics on stdout
Enter fullscreen mode Exit fullscreen mode

Your architecture's consistency is an exit code now, not an opinion in a document — a gate in your pipeline the build can fail on. The whole thesis, in one number.

Terminal cast — ea validate --all passes (exit 0); then a broken capability reference flips it to invalid (exit 3) with precise diagnostics.

Where the AI helps

None of this makes the model less useful. It makes it useful in the place it's good.

Tailoring a methodology to a specific organization is judgment — it's elicitation, taste, tradeoffs, the stuff with no single right answer. Drafting a first artifact from a messy conversation is judgment. Advising on what's missing is judgment. That work belongs to the surface agent, and the core stays out of it entirely: no authoring intelligence, no "AI reviewer," nothing that requires taste, lives below the line.

The discipline that keeps this honest is elicit-first. The agent doesn't pre-draft your whole architecture and take one bulk approval — it draws the substance out of you one step at a time, and every write is still gated. Every mutating command is dry-run by default: it returns a plan bound to a content-derived token, and only re-running with that token applies it.

$ ea init
{ "status": "ok",
  "writes": ["ea.manifest.yaml"],
  "confirmation_token": "sha256:cfe221b992aeb…31636d" }
Enter fullscreen mode Exit fullscreen mode

The agent proposes the change; you (or the core, on your say-so) confirm the exact bytes. If the repository drifted in between, the token no longer matches and the core refuses. The model never gets to be the thing that silently rewrites your source of truth.

Methods are data, not code

The last piece is what makes this more than one team's opinion about architecture. The methods themselves — the types you can model, the relationships between them, the rules that must hold — ship as versioned Method Packs: plain YAML the core reads at runtime. Adopting a methodology is configuration, not a code change.

The first build command fetches a pack library; from there everything resolves offline and deterministically:

$ ea pack fetch https://github.com/adworzynski/ea-as-code.git
$ ea init --confirm <token>
$ ea preset list                    # enterprise-architecture · lean-ux · open-agile-architecture
$ ea manifest adopt lean-ux --confirm <token>
$ ea project create checkout --confirm <token>
$ ea scaffold hypothesis --project checkout --id faster-checkout
$ ea validate --all                 # exit 0
Enter fullscreen mode Exit fullscreen mode

ea scaffold doesn't just make an empty file — it hands back a typed stub plus the authoring guidance that pack defines: which fields to fill, which relationships are allowed, the steps to follow. The same division shows up here in miniature. The pack supplies the structure and the standard; you supply the judgment that fills it in; the core proves the result is well-formed.

Three archetypes ship today — a rigorous four-domain Enterprise Architecture grounded in TOGAF's ADM, a lightweight outcomes-first Lean UX, and a full outside-in Open Agile Architecture. The same engine runs all three, because the engine doesn't know any of them. It reads them.

Try it

The claim is falsifiable, which is the point. Clone the repo and let the core prove an existing architecture consistent on your own machine — the shipped example needs no setup:

$ git clone https://github.com/adworzynski/ea-as-code.git
$ cd ea-as-code/examples/payments-oaa/repo
$ ea validate --all        # exit 0 — see for yourself
Enter fullscreen mode Exit fullscreen mode

Keep the model for what it's great at — the judgment, the drafting, the conversation. Stop letting it be the thing that tells you your architecture is sound. Let something that can actually check answer that one, in an exit code.

Top comments (0)