Concepts

A graph that knows what its edges mean.

glia's graph is a domain-parameterised graph, DPG for short: a labeled property graph whose types, walks and identity rules come from a plug-in profile, and whose every edge carries the evidence it was built from. Five ideas, each one animated. The source drawings are the DPG explainer, eleven boards.

It's like a map of a brain, so an LLM can follow the right paths through its memories, faster and with less reading.
James, the first framing, 2025
1 · A walk

What a blast radius is

Seed a node, follow the edges the profile says carry change, keep every node reached with its depth and the weakest tier on its path. This is the demo shop's Order struct, an unedited answer.

WEB · ANGULAR API · GO SAME_AS · http_model HTTP_CALLS USES HANDLED_BY CALLS ENDPOINTGET /api/orders INTERFACE · TSOrder STRUCT · GO · SEEDOrder ROUTEGET METHODOrders.List METHODOrders.Place Memory.Orders Publisher.OrderPlaced DEPTH 1 · 4 ROWS · FACT DEPTH 2 · 9 ROWS · FACT ACROSS THE CLASS · DERIVED
  1. Seed. glia blast-radius examples-glia api::…::Order. The walk starts at the struct and follows the carry edges: calls, uses, handled-by, the cross-service links. Imports and containment are not followed.
  2. Depth 1. Four handler methods use the struct. Each edge was read at a call site in the AST: fact.
  3. Depth 2. The routes the handlers serve, the store they read, the NATS publisher one of them calls. Nine more rows, still fact. The publisher is where a change stops being local.
  4. The identity class. The TypeScript interface the storefront reads is the same model: the models pass paired it with the struct through the HTTP exchange. One derived node in the walk, two rows in the source.
  5. Across the service. So the endpoint that fetches orders is in the radius too, and its row carries the weakest tier on its path: derived. Every row names its seed, its edge and its file:line.
2 · Evidence

Every edge says how it knows

An edge carries one evidence cell: the emitter that wrote it, the rule it applied, and the file and line it was read at. From those an answer derives a tier, and tiers compose: weakest along a path, best across alternative paths.

"So it's a guess?" Is 1 + 1 = 2 a guess? No: you know the rules, you have tested them, and the knowledge formed. Now take people. If seven people of varying calibre all tell you someone is hard work, you have a picture of them before you meet, built from what you trust about the seven, and the meeting makes it better or worse.
James, on tiers

That is the three tiers. A fact is the sum you worked yourself. A derived row is the picture built from sources you trust and rules you know. A heuristic is hearsay, kept, ranked last, and never allowed to decide on its own.

ROUTEPOST /orders FUNCTIONcreateOrder FUNCTIONsaveOrder TABLEorders HANDLED_BY CALLS WRITES · name match WRITES · resolver:db, paired at store.go:38 ANSWER ROWTABLE orders · reached from POST /orders HEURISTIC · WEAKEST EDGE DERIVED · BEST PATH WINS
  1. Read at a site. The route's handler and the call inside it are in the AST: two fact edges.
  2. Weakest along a path. saveOrder writes orders, but only a name match says so. The row the table gets inherits that: heuristic.
  3. Best across paths. The database resolver paired the same write from the ORM call. A second, stronger path exists, so the row is derived. A rule violation through a guess alone stays advisory; this one would block.
fact

Read at a site: a call in the AST, a route registration, an import, a struct's field. Checkable to the line.

derived

Paired by a resolver: an endpoint to its route, a producer to a consumer by topic, a client model to the server struct. The pairing rule and the site are in the cell.

heuristic

A name guess, an overlay stanza, git co-change, a clustering. Shown, ranked below the rest, never allowed to block a gate on its own.

glia why A B prints the cell of the edge between two nodes; glia check gates on min_tier.

3 · Layers

One regulation changes. What is now wrong?

Code is one domain. The law a plant control system satisfies, the chemistry it is constrained by, the docs that describe it, the topics it publishes to and the services it deploys as are others, each with its own profile on the same engine, glued where they share a concept. A walk crosses every layer and reads the answer off the shape.

To me code isn't just one domain. It's many domains of graphs, connected into knowledge about what is to be made, why, how, and what went wrong, plus the glue between software and the real world. The aim is to bound complex systems, climate to economics to geopolitics to science, so people can get a grip on relationships and phenomena they would otherwise never be exposed to.
James, on what the layers are for
WORLD · OWN DOMAINS, OWN PROFILES CHEMISTRY · identity: process / CAS id LAW · citation DOCS CODE · SYSTEM GRAPH OF THREE REPOS hmi · TypeScript control · Rust analytics · Go DATA DEPLOY PROCESSHaber-Bosch CONSTRAINT400 to 500 °C HAZARDrunaway above 520 °C REGULATIONWHS (MHF) Regs CONDITIONlicence: safety case REQUIREMENTalarm on T > 520 °C in 2 s PAGErunbook: alarm response COMPONENTReactorPanel ENDPOINTPOST /setpoint ROUTEPOST /setpoint FUNCTIONclamp_setpoint FUNCTIONpublish_alarm MESSAGE_TYPEAlarm · Rust MESSAGE_TYPEAlarm · Go FUNCTIONreport_incident TOPICplant.alarms TABLEincidents SERVICEcontrol · PLC gw SERVICEanalytics IMPOSES SPECIFIES REQUIRES CARRIES REQUIRED_BY · citation CONSTRAINED_BY · id HANDLED_BY HTTP_CALLS CALLS EMITS SAME_AS HANDLED_BY PUBLISHES_TO CONSUMES WRITES DOCUMENTS DEPLOYS DEPLOYS AMENDED · alarm in 1 s
  1. The world changes. The WHS (Major Hazard Facilities) Regulations are amended: an alarm must sound within one second, not two. A new validity span on the regulation node.
  2. Down the law domain. The condition it imposes on the licence, the requirement that condition specifies. Both read from the regulation's own structure: fact inside its domain. The requirement's text is now out of date.
  3. Into the code. The requirement is REQUIRED_BY the Rust function that raises the alarm, paired by the citation in its doc comment: derived. This is the seed of the code-side walk.
  4. Up the call chain. clamp_setpoint calls it; the POST /setpoint route is handled there. Fact edges from the AST.
  5. Across the HTTP exchange. The TypeScript HMI posts to that route from its reactor panel. The pairing is the HTTP resolver's: derived. Two repos in, one walk.
  6. One message, two languages. The alarm it emits is one message type in Rust and in Go, joined as an identity class, so the Go consumer that reports incidents is reached as one hop.
  7. Data and docs. The topic the alarm publishes to, the incidents table the report writes, and the runbook page that documents the alarm response, now wrong about the deadline.
  8. Deploy. Two services to roll out. Everything lit is the answer, each row carrying the weakest tier on its path from the regulation: derived, through the citation.
  9. And the other way. Why does clamp_setpoint cap at 500 °C? Walk up: the Haber-Bosch constraint it is bound by, the runaway hazard that constraint carries, and sideways the regulation that names 520 °C. The reason the code exists lives outside it.

What ships today: the three repo graphs glued by HTTP_CALLS and SAME_AS, and docs inside the code domain. The data, deploy and world layers are the direction: the seam, the profile and the identity rules are built, the second domain is in progress.

4 · Time

Space from the graph, time from git

The graph is a function of the working tree, built byte-identically on any machine and any thread count. History is read beside it as a snapshot, never baked into a build: commits, blame and co-change pairs from glia history sync, edge validity spans from glia timeline build. A co-change ranking is heuristic, a diff against a revision is a delta between two fact builds, and glia review reports both without blending them.

Space from the DPG, time from git
space · the DPG inside one snapshot
time · git DAG of snapshots
MODULE
web/api.ts
MODULE
server/orders.go
MODULE
server/db.go
HTTP_CALLS valid a1f3 → c9e0 · timeline.gmap sidecar, last --revs
HTTP_CALLS
IMPORTS
co-change · read at query time
a1f3
b72c
c9e0
d410
e55a
this snapshot
git is the time axis (a DAG of snapshots); the DPG is the space axis (what is inside one snapshot)
neither lives in an edge cell: co-change sits in the history snapshot and is read at query time (ranking, glia cochange, the cochange_no_edge gap); validity spans live in the timeline.gmap sidecar
5 · The model

Property graph plus a profile

What a CALLS edge means, which edges a blast radius follows, which nodes are entry points, which rules join two copies of a thing: in a plain property graph all of that is rewritten in every query. A DPG moves it into a domain profile the engine reads. The code profile is one table in one file; a second domain is another table, and a test-only toy domain proves the seam.

LPG vs DPG
LPG · Labeled Property Graph
DPG · Domain-Parameterised Graph
instance graph
instance graph
type graph
type graph + semantics
FUNCTION
createOrder
{ file, line }
FUNCTION
saveOrder
{ file, line }
FUNCTION
FUNCTION
QUERY
meaning is rewritten in every query,
for every domain
FUNCTION
createOrder
{ file, line }
FUNCTION
saveOrder
{ file, line }
FUNCTION
FUNCTION
DOMAIN PROFILE (plug-in)
entry rule · carry · effect sinks
activation presets · identity rules · invoked members
typing homomorphism is the model; the per-edge (src, kind, dst) check is planned, not built
CALLS
CALLS
typing
CALLS
CALLS
typing
parameterises
types + properties
types + properties + semantics
One engine, swappable domain profile
a profile is a cartridge: type graph + semantics. Swap it and the same engine reasons over a different domain.
CODE profile shipped 0.5.0
entry: rule (kinds, roles, names)
carry · effect_sinks
activation: repair / review / onboard
identity: 10 rules · INVOKED_MEMBERS
glia engine
walk · blast radius · trace
Personalised PageRank
walks over the quotient graph
BUILD profile planned · 0.5.4 T9
bazel targets: first second domain
entry: targets
carry: DEPENDS_ON
identity: same output path
DOCS profile later
today docs sit inside CODE (DOCUMENTS edge)
own profile once a second domain exists
CODE + BUILD glue where they share a concept (pushout of type graphs, planned)
many domain graphs, one knowledge graph
answers for that domain
each one carrying its evidence tier
plugged in
swap in
queries
core, activation and rules are domain-free (toy-domain test proves the seam); glia-engine is the CODE orchestrator and knows code names
Compared with other graph models

Where the new parts are

Typed attributed graphs give the formal spine; property graphs give the data shape. The profile and the evidence are the parts glia adds.

modelan edge carriesschemasemanticsprovenancetime
RDFa predicate IRI; attributes need reification or RDF-staroptional global ontologylogical entailment, one global meaningnamed graphs at bestnone built in
LPGa type plus propertiesnone, or optional constraintsnone; rewritten per querywhatever you store; no rulenone built in
Typed attributed grapha typed edge plus attributesa type graph; instance typed by a homomorphismnone; rewrite rules act on structurenonenone
Hypergraphone edge joins any number of nodesoptionalnonenonenone
DPG · gliaa type, cells, and an evidence cell: emitter, rule, file, line, tiera type graph per domain; domains glued where they share a concepta domain profile: entry, carry, weights, identity; swappableevery edge; tiers compose into the answergit beside it: validity spans, co-change