Skip to content

Artifact graph

Node kinds: memory (any content type — the base case), concept (inductive tags), topic (tree nodes — an overlay index).

Edge kind Direction Meaning Written by
topic_member topic → memory membership routing
parent_child topic → topic tree structure splits/merges
memory_supports memory → memory provenance — “why this result” rules, indexer, dream, agent
memory_supersedes memory → memory truth replacement — old → new identity rule, agent, dream
memory_contradicts memory → memory unresolved conflict rules, dream, agent
code_calls memory → memory call-site links (index-derived only) indexer

Edges carry weight (positive similarity), confidence (0–1), source (rule | llm | agent), status, and timestamps.

Structural rules and the indexer write edges directly; almost everything else lands pending until a reviewer confirms:

addEdge(...) ──▶ pending (nothing changed yet)
├─▶ confirm(id) ──▶ confirmed (status + valid_at set)
├─▶ reject(id) ──▶ rejected (never surfaces)
└─▶ expire(id) ──▶ expired (soft-delete — excluded, not erased)

The atomic supersede flip. A confirmed memory_supersedes performs the old memory’s active → superseded state flip in the same transaction as the edge write (both on insert with confirmed: true and on confirm). The edge never exists without the flip; the old memory stops ranking the moment the claim is visible. Pending supersedes change nothing — that is the gated recipe for human review.

code_calls edges are index-derived only — the facade rejects hand-authored call edges (a call graph the agent could fake is worthless).

Search results are augmented deterministically from the graph:

supersedes (confirmed) → old endpoint demoted: score × supersedeDemotion (0.5)
+ supersededBy = successor
contradicts (any) → conflicts = [other endpoint] on BOTH sides
supports (confirmed) → supportedBy = [source ids] on the supported side

The demotion also guards upgraded databases whose confirmed edges predate the atomic flip (their from-memories may still be active) — legacy rows soft-rank instead of ghosting at full weight.

explain(kind, id) walks the neighborhood with hard bounds (graph config): maxDepth (2), maxNeighbors per node (12), maxTotal (80) — and edgeKinds scopes the answer (memory_* for memory-only navigation, code_calls for one-hop impact analysis). Traversal is indexed in both directions and deterministic in order.