Skip to main content

ProgramGraph Reference

The ProgramGraph is Zerolang's structured representation of a program's semantics. It is the foundation of the agent-native design: agents inspect, reason about, and edit programs through the graph rather than raw source text.

What Is a ProgramGraph?

A ProgramGraph is a directed graph that describes a Zero program's declarations, expressions, types, and their relationships. Every .0 source file compiles to a ProgramGraph.

zero graph dump --json hello.0

The output contains:

{
"moduleIdentity": "hello",
"graphHash": "graph:a7f7e6899a73f3b4",
"counts": { "nodes": 12, "edges": 8 },
"nodes": [ ... ],
"edges": [ ... ]
}
FieldDescription
moduleIdentityThe module name derived from the source
graphHashContent hash that changes when semantics change
countsNode and edge counts
nodesAll declarations, expressions, and types
edgesRelationships between nodes

Graph Hash

The graphHash is a deterministic content hash of the program's semantic structure. It changes when:

  • A declaration is added or removed
  • A type changes
  • An expression's value changes
  • A function signature changes

It does not change when:

  • Whitespace or comments are modified
  • The file is reformatted without semantic changes

The graph hash is used as a safety mechanism in zero graph patch. An agent passes --expect-graph-hash to ensure the program has not changed since it last read the graph. If the hash does not match, the patch is rejected.

Nodes

Each node represents a semantic element in the program. Nodes have:

FieldDescription
idUnique identifier (e.g., #expr_653eeb6e)
kindNode type: Function, Type, Binding, Literal, Call, If, While, Match, etc.
nameThe declared name (if applicable)
typeThe resolved type
valueThe literal value (for literals)
publicWhether the declaration is exported
mutableWhether the binding is mutable (var vs let)
fallibleWhether the expression can fail
hashContent hash of this node

Common Node Kinds

KindDescriptionExample
FunctionA function declarationfn answer() -> i32
TypeA type declarationtype Point { x: i32, y: i32 }
BindingA let or var bindinglet x: i32 = 42
LiteralA literal value42, "hello", true
CallA function callworld.out.write("hi")
IfAn if/else branchif x > 0 { ... }
WhileA while loopwhile keepGoing { ... }
MatchA match expressionmatch result { ... }
ChoiceA choice typechoice Result { ok: i32, err: String }
EnumAn enum typeenum Status { ready, failed }

Edges

Edges describe relationships between nodes:

Edge TypeDescriptionExample
callFunction call relationshipmain calls world.out.write
importModule importuse std.codec
typeType annotationlet x: i32i32
argFunction argumentwrite("hello")"hello"
fieldField accesspoint.xx
bodyFunction bodyfn main → body block
initBinding initializerlet x = 4242
conditionBranch conditionif x > 0x > 0
then / elseBranch armsif → then block / else block

ProgramGraph Commands

dump

Export the graph for a source file:

zero graph dump --json hello.0
zero graph dump --out hello.program-graph hello.0

import

Import source into a ProgramGraph artifact:

zero graph import --json hello.0
zero graph import --out hello.program-graph hello.0

validate

Check that a ProgramGraph artifact is well-formed:

zero graph validate --json hello.program-graph

view

Render canonical source text from a graph:

zero graph view --json hello.0
zero graph view --out hello.view.0 hello.program-graph

inspect

Inspect modules, symbols, capabilities, and helper use:

zero graph inspect --json hello.0

source-map

Map graph node IDs to source ranges:

zero graph source-map --json hello.0

reconcile

Compare edited source with a prior graph:

zero graph reconcile --json hello.program-graph --source hello.0

check

Typecheck through direct graph lowering:

zero graph check --json hello.0
zero graph check --json hello.program-graph

size

Size analysis for a ProgramGraph artifact:

zero graph size --json hello.program-graph

build

Build from a ProgramGraph artifact:

zero graph build --json --emit obj --target linux-musl-x64 --out hello.o hello.program-graph

patch

Apply checked edits to a graph:

zero graph patch hello.0 \
--expect-graph-hash graph:a7f7e6899a73f3b4 \
--op 'set node="#expr_653eeb6e" field="value" expect="hello from zero\n" value="hello patched\n"'

roundtrip

Verify graph stability through import/export:

zero graph roundtrip --json hello.0
zero graph roundtrip --json hello.program-graph

Graph Patch Operations

zero graph patch supports six operations:

set

Update a scalar field on an existing node:

set node="#expr_653eeb6e" field="value" expect="hello\n" value="hello patched\n"

Editable fields: name, type, value, public, mutable, static, fallible, exportC.

insert

Create a new node and connect it to a parent:

insert node="#patch001" kind="Literal" parent="#expr_c403020c" edge="arg" order="1" type="String" value="again\n"

insertEdge

Connect existing facts across domains:

insertEdge source="#node_abc" target="#type_xyz" kind="type"

replace

Update a node in place with optional hash precondition:

replace node="#expr_653eeb6e" expect="abc123" ...

delete

Remove an owned subtree (rejects external references):

delete node="#patch001"

rename

Update a node's name with optional current-name precondition:

rename node="#decl_ad8d9028" expect="main" value="start"

Patch File Format

For larger edits, use a patch file:

zero-program-graph-patch v1
expect graphHash "graph:a7f7e6899a73f3b4"
set node="#expr_653eeb6e" field="value" expect="hello from zero\n" value="hello patched\n"
insert node="#patch001" kind="Literal" parent="#expr_c403020c" edge="arg" order="1" type="String" value="again\n"
rename node="#decl_ad8d9028" expect="main" value="start"
delete node="#patch001"

The header is required. expect graphHash is optional but recommended.

Source-to-Graph Relationship

The ProgramGraph is derived from source code. The relationship is:

Source (.0) → Compiler → ProgramGraph → Graph Hash

Source Map (node ID → line:column)

An agent can:

  1. Read source → compile → get graph
  2. Inspect graph nodes and edges
  3. Submit graph edits via zero graph patch
  4. Compiler applies edits, rewrites source, verifies graph hash

This bidirectional flow means agents work with semantic facts, not text positions.

JSON Output

All zero graph commands accept --json for structured output. Key fields:

CommandJSON Fields
dumpmoduleIdentity, graphHash, validation, counts, nodes, edges
importmoduleIdentity, graphHash, validation, saved.path
validatemoduleIdentity, graphHash, counts, validation
viewmoduleIdentity, graphHash, source, optional output path
source-mapNode IDs → source ranges, node hashes, symbol/type/effect IDs, file hash facts
reconcileIdentity decisions, ambiguous-match diagnostics, simple graph patch text
checkmoduleIdentity, graphHash, lowering: "direct-program-graph", target readiness, safety facts, graph-mapped diagnostics
sizegraph identity, profileSemantics, profileCatalog, profileBudget, safetyFacts, backendProfile, backendComparison, sizeBreakdown, retentionReasons, optimizationHints
buildgraph identity, selected emit kind, target, artifact path/size, safety facts, compiler cache facts, incremental invalidation
patchPer-operation results, changed graph hash, saved source/artifact path
roundtripsemanticStable, lowering mode, original/roundtripped graph hashes, raw counts, normalized semantic counts, optional ProgramGraph output

Further Reading