Summary
Add a derivation-kind tag to graph edges (and extracted facts) that records how a relation was produced: read directly from the source, inferred by the LLM, or ambiguous. This is distinct from the confidence/weight we already store.
Why
While comparing our memory layer against graphify (an LLM-wiki project that builds a concept graph), one of its primitives stood out: every relationship edge carries an EXTRACTED / INFERRED / AMBIGUOUS tag.
We already have more provenance than they do:
GraphNode.provenance / GraphEdge.provenance: source memory IDs (runtime/memory/graph_types.py:85,106)
GraphEdge.weight: LLM confidence score 0–1 (graph_types.py:105)
MemoryEntry.confidence: 0–1 (runtime/types.py:376)
What we can't express today is the kind of derivation. A weight=0.6 edge could be a low-confidence literal extraction or a medium-confidence inference, and a reader can't tell which. That distinction matters for trust: a fact the soul read from a real turn is not the same as one it guessed.
Proposal
- Add a
DerivationKind StrEnum (extracted, inferred, ambiguous) next to RelationType in graph_types.py (open-string contract, same as the other vocab enums).
- Add a
derivation: DerivationKind | None = None field on GraphEdge, and optionally on MemoryEntry for facts that come out of the observe() pipeline. Default None so pre-0.5 souls round-trip with no migration (backfill on awaken, same pattern as retrieval_weight / prediction_error).
- Have the extractor in
update_graph() set it when it writes edges.
- Capture it in the trust-chain payload alongside
prediction_error, so a verifier can see whether a claim was read or inferred.
- Let recall filter on it (e.g. extracted-only), so callers that want grounded facts can ask for them.
Scope
Enum + field + extractor wiring + trust-payload capture + a recall filter. No UI, no new dependency.
Related
Summary
Add a derivation-kind tag to graph edges (and extracted facts) that records how a relation was produced: read directly from the source, inferred by the LLM, or ambiguous. This is distinct from the confidence/weight we already store.
Why
While comparing our memory layer against graphify (an LLM-wiki project that builds a concept graph), one of its primitives stood out: every relationship edge carries an
EXTRACTED/INFERRED/AMBIGUOUStag.We already have more provenance than they do:
GraphNode.provenance/GraphEdge.provenance: source memory IDs (runtime/memory/graph_types.py:85,106)GraphEdge.weight: LLM confidence score 0–1 (graph_types.py:105)MemoryEntry.confidence: 0–1 (runtime/types.py:376)What we can't express today is the kind of derivation. A
weight=0.6edge could be a low-confidence literal extraction or a medium-confidence inference, and a reader can't tell which. That distinction matters for trust: a fact the soul read from a real turn is not the same as one it guessed.Proposal
DerivationKindStrEnum (extracted,inferred,ambiguous) next toRelationTypeingraph_types.py(open-string contract, same as the other vocab enums).derivation: DerivationKind | None = Nonefield onGraphEdge, and optionally onMemoryEntryfor facts that come out of theobserve()pipeline. DefaultNoneso pre-0.5 souls round-trip with no migration (backfill on awaken, same pattern asretrieval_weight/prediction_error).update_graph()set it when it writes edges.prediction_error, so a verifier can see whether a claim was read or inferred.Scope
Enum + field + extractor wiring + trust-payload capture + a recall filter. No UI, no new dependency.
Related