Diffs
patinaDB can show what changed — both for a single engram and between any two points in history.
Single-engram diff
A git-show-style view of one engram: what was created, deleted, and which
properties changed (old → new). Repeated SETs on the same property are
coalesced, no-op sets are dropped, and prior values are resolved by
reconstructing the parent state.
CALL patinadb.diff('<engram-id>')
patinadb ./mygraph diff <engram-id> # human-readable
patinadb ./mygraph diff <engram-id> --json
MCP: the diff tool.
Range diff (structural)
A structural diff between two reconstructed states — not a replay of the
operations between them, but a comparison of the actual graphs at from and
to. Use empty (CLI) / None as from to diff against the empty graph.
patinadb ./mygraph diff-range <from-id> <to-id>
patinadb ./mygraph diff-range empty <to-id>
CALL patinadb.diffRange('<from-id>', '<to-id>')
MCP: the diff_range tool.
Move pairing
A naive structural diff reports a node that changed identity as one removed and one added node. The range diff is move-aware: it pairs a removed and an added vertex that share a label and match on an identity property, reporting a single move instead of an add/remove pair.
The identity-property priority list defaults to
qualified_name, fqn, name. Override it on the CLI:
# Use `email` then `id` as identity; `none` disables move pairing entirely
patinadb ./mygraph diff-range <from> <to> --identity-props email,id
patinadb ./mygraph diff-range <from> <to> --identity-props none
If two candidates match ambiguously, they are left unpaired (reported as separate add/remove) rather than guessed.
Use case: code indexing
The range diff powers patinadb-indexer, which re-indexes a codebase and
reports a real per-run diff of the symbol graph (functions/types added, removed,
or moved) — even though the writes go through query() and don’t produce
per-engram deltas. That’s exactly what structural, move-aware diffing is for.