Docs
/

@leumas/architecture-graph

The document format behind the Leumas architecture graphs. One canonical serializer that keeps every node and edge on its own line so an agent can grep-and-edit a single record, a content hash for...

@leumas/architecture-graph

The document format behind the architecture graphs in ops/architecture/*.graph.json. Node-only, no dependencies, no React — three very different callers read it and one of them is a guard running in bare Node.

ImportWhat it is
@leumas/architecture-graphserializeGraph · isCanonical · revOf
@leumas/architecture-graph/kindsUNIT_KINDS · unitsOfKind · allUnits · readManifestDomains · resolveRef

Why a canonical serializer is the whole point

The architecture graphs are edited two ways: in the Leumas Admin editor, and by a coding agent with a text editor. The agent's loop is what makes the second one cheap:

grep -n '"id":"studio"' ops/architecture/ecosystem.graph.json   # -> one line number

…then read that line and edit it. A couple of hundred tokens, whatever the graph's size.

That works only while every node and every edge is exactly one line. The first save that writes JSON.stringify(doc, null, 2) reflows a 60-line file to 350, and in that one commit every line anchor is wrong, every one-node change becomes a whole-file diff, and grep stops answering the question. The JSON is still valid and the app still renders, so nothing else in the repo can see it happen.

So serializeGraph() is the only writer — in the control-plane PUT handler, in ops/architecture/build.mjs, and in check-architecture --fix — and pnpm check:architecture hard-fails a committed file that is not byte-identical to what it would produce. Canonical form is an invariant, not a convention.

The shape: header keys pretty-printed (a person hand-edits lanes, kinds and classes), lookup tables one entry per line, and regions / labels / panels / nodes / edges compact with a fixed key order. Fixed order matters as much as one-line-ness — without it two writers that disagree about key order produce a diff on every record of a file where nothing changed.

revOf — why every write carries one

Two writers means a page left open while an agent works would, on the next node drag, write back the document it loaded an hour ago and silently revert everything in between. revOf hashes the bytes on disk; the store returns it with the document and refuses a PUT carrying a stale one with a 409.

kinds — binding a drawing to the tree

UNIT_KINDS says, per family of thing Leumas contains, where the real ones live and how to recognise one. That is what lets the guard answer is this still true? — a node's refs that no longer resolve is a hard failure, because a map asserting paths that moved is the failure binding exists to prevent.

[critical] readManifestDomains reads a generated index, not the manifests. Grepping the three nav manifests for id: finds the control plane's domains and none of Studio's, because Studio does not write its ids literally — DOMAINS is built from { ...app('graphs'), pillar: 'ai' }, so the id is a function argument. A reader that silently misses most of the tree is worse than no reader, since every coverage number it feeds looks plausible. The source is therefore .claude/skills/leumas-capabilities/reference/domains.md, which pnpm skills:sync builds by importing those manifests and which pnpm check:skills fails the build over when it drifts.

Guards

pnpm check:architecture — canonical form, ref resolution, the hot ownership tree, region coverage. pnpm check:architecture --self-test also asserts that the tidy in @leumas/ui/graph/tidy is idempotent, which is what makes a tidied drawing committable.

What it exports

11 exports: 1 components, 0 hooks, 10 helpers. Import from @leumas/architecture-graph.

UNIT_KINDSallUnitsfamilyOfinferNodeisCanonicalnormalizeGraphreadManifestDomainsresolveRefrevOfserializeGraphunitsOfKind
Source shared/packages/architecture-graph/README.md (no-git)markdownjson
Generated from the Leumas repository. Every page cites the file it came from.leumas.techllms.txt