Provenance navigation for knowledge graphs — traverse facts by compass direction with trust decay
In any knowledge system — whether an AI agent's memory, a research database, or a corporate wiki — facts don't exist in isolation. They have provenance: where they came from, what they were derived from, how they've been summarized, and what raw data they were built on. Knowledge Compass organizes these provenance relationships as a navigable graph using a compass metaphor:
- North (↑): Toward the original source — who said it first? What's the primary reference?
- East (→): Toward derivations — what was built from this fact? What conclusions use it?
- South (↓): Toward summaries — condensed, abstracted, or simplified versions
- West (←): Toward the original raw material — the unprocessed data that led to this fact
Each node in the graph carries a trust score that decays with distance from the original source, modeled by a configurable TrustRadius. Navigate the graph step-by-step or find paths between any two facts using BFS.
Provenance is the backbone of trustworthy knowledge systems:
- Fact-checking: Navigate north to verify a claim's source, check trust scores along the way
- Impact analysis: Navigate east from a source to see everything that depends on it — what breaks if this fact is wrong?
- Abstraction: Navigate south to get condensed summaries of detailed information
- Raw data access: Navigate west to retrieve the original measurements, logs, or transcripts
- Trust propagation: Trust decays with distance — derived facts 5 steps from source are less reliable than the source itself
Real-world applications:
- AI agent memory: Agents need to know where their knowledge came from and how trustworthy it is
- Research pipelines: Track how raw experimental data becomes published conclusions
- News verification: Navigate from a headline (south) back to the original source (north)
- Compliance/audit: Prove the provenance chain for regulatory requirements
- Knowledge management: Explore organizational knowledge by following provenance links
┌──────────────────────────────────────────────────────────────┐
│ Knowledge Compass Map │
│ │
│ North (Source) │
│ ↑ │
│ Original ←[W]── [KnowledgeNode] ──[E]→ Derivation │
│ (Raw) │ "The sky appears │ (Downstream) │
│ │ blue due to │ │
│ │ Rayleigh │ │
│ ↓ scattering" ↓ │
│ South (Summary) │
│ "Sky is blue" │
│ │
│ Trust Radius: trust(d) = max(0, 1 - decay×d) │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Source (d=0) ──East──▶ Derived (d=1) ──East──▶ ... │ │
│ │ trust=1.0 trust=0.9 │ │
│ │ │ │
│ │ Source (d=0) ──South─▶ Summary (d=1) ──South─▶ ...│ │
│ │ trust=1.0 trust=0.8 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Navigation: BFS across all directions to find paths │
└──────────────────────────────────────────────────────────────┘
use knowledge_compass::{KnowledgeNode, CompassRose, CompassDirection, Navigation, TrustRadius};
// Create a compass rose (knowledge graph)
let mut rose = CompassRose::new();
// Add a source node (distance 0, trust 1.0)
let mut source = KnowledgeNode::new_source("paper-1", "Rayleigh scattering causes blue sky");
source.link(CompassDirection::East, "derivation-1");
source.link(CompassDirection::South, "summary-1");
rose.add_node(source);
// Add a derived fact
let mut derived = KnowledgeNode::new_derived("derivation-1", "Blue wavelengths scatter most", 1, 0.9);
derived.link(CompassDirection::West, "paper-1");
rose.add_node(derived);
// Add a summary
let mut summary = KnowledgeNode::new_derived("summary-1", "Sky appears blue", 1, 0.8);
summary.link(CompassDirection::North, "paper-1");
rose.add_node(summary);
// Navigate: go east from source to see derivations
let nav = Navigation::new(&rose);
let derivations = nav.step("paper-1", CompassDirection::East);
println!("Derivations: {:?}", derivations.iter().map(|n| &n.fact).collect::<Vec<_>>());
// Find a path between any two nodes
if let Some(path) = nav.find_path("summary-1", "derivation-1") {
println!("Path: {:?}", path); // ["summary-1", "paper-1", "derivation-1"]
}// Configure trust decay
let trust = TrustRadius::new(10, 0.1);
// Trust at distance 0 (source): 1.0
println!("Trust at d=0: {}", trust.trust_at_distance(0));
// Trust at distance 3: 0.7
println!("Trust at d=3: {}", trust.trust_at_distance(3));
// Trust at distance 10+: 0.0
println!("Trust at d=10: {}", trust.trust_at_distance(10));
// Check if a node is trusted (trust > 0.1)
let node = KnowledgeNode::new_derived("fact", "some fact", 3, 0.7);
println!("Is trusted: {}", trust.is_trusted(&node));
// Validate and correct a node's trust
let mut node = KnowledgeNode::new_derived("fact", "wrong trust", 3, 1.0);
let was_valid = trust.validate_trust(&mut node);
println!("Was valid: {} (corrected to {:.2})", was_valid, node.trust);// Traverse multiple steps in a direction
let all_derivations = nav.traverse("paper-1", CompassDirection::East, 5);
println!("All downstream derivations:");
for node in &all_derivations {
println!(" [d={}, trust={:.2}] {}", node.source_distance, node.trust, node.fact);
}
// Find all sources
let sources = rose.sources();
println!("{} source nodes in the graph", sources.len());| Variant | Label | Meaning |
|---|---|---|
North |
Source | Navigate toward original source |
East |
Derivation | Navigate toward downstream uses |
South |
Summary | Navigate toward condensed versions |
West |
Original | Navigate toward raw material |
| Method | Returns | Description |
|---|---|---|
dir.label() |
&str |
Human-readable direction name |
dir.opposite() |
CompassDirection |
Opposite direction |
| Method | Returns | Description |
|---|---|---|
KnowledgeNode::new_source(id, fact) |
KnowledgeNode |
Source node (distance 0, trust 1.0) |
KnowledgeNode::new_derived(id, fact, distance, trust) |
KnowledgeNode |
Derived node |
node.link(direction, target_id) |
() |
Add a provenance link |
node.get_links(direction) |
&[String] |
Get links in a direction |
node.is_source() |
bool |
Is this a source (distance 0)? |
| Method | Returns | Description |
|---|---|---|
CompassRose::new() |
CompassRose |
Create empty graph |
rose.add_node(node) |
() |
Add a knowledge node |
rose.get(id) |
Option<&KnowledgeNode> |
Look up by ID |
rose.sources() |
Vec<&KnowledgeNode> |
All source nodes |
rose.len() |
usize |
Total nodes |
rose.node_ids() |
Vec<&str> |
All node IDs |
| Method | Returns | Description |
|---|---|---|
Navigation::new(&rose) |
Navigation |
Create navigator |
nav.step(from, direction) |
Vec<&KnowledgeNode> |
One step in a direction |
nav.traverse(from, direction, max_steps) |
Vec<&KnowledgeNode> |
Multi-step traversal |
nav.find_path(from, to) |
Option<Vec<String>> |
BFS path between any two nodes |
| Method | Returns | Description |
|---|---|---|
TrustRadius::new(max_distance, decay_rate) |
TrustRadius |
Configure decay |
tr.trust_at_distance(d) |
f64 |
Trust at distance d |
tr.is_trusted(node) |
bool |
Node within trust radius |
tr.validate_trust(&mut node) |
bool |
Correct trust if inconsistent |
Trust decays linearly with source distance:
trust(d) = max(0, 1 − decay_rate × d)
where d is the shortest path length from the nearest source node. With the default parameters (max_distance=10, decay_rate=0.1):
- d=0: trust=1.0 (source itself)
- d=3: trust=0.7
- d=5: trust=0.5
- d≥10: trust=0.0 (untrusted)
The knowledge graph is a directed multigraph where edges are typed by compass direction:
G = (V, E, label)
V = set of knowledge nodes
E ⊆ V × V × {N, E, S, W}
Direction semantics:
- North edges: from derived → source (provenance chain upward)
- East edges: from source → derivation (impact chain forward)
- South edges: from detailed → summary (abstraction chain)
- West edges: from summary → original (raw data chain)
Navigation uses breadth-first search across all four directions simultaneously, guaranteeing the shortest path in O(V + E) time. Each edge is traversed regardless of direction, treating the graph as undirected for pathfinding purposes.
cargo add knowledge-compassOr add to your Cargo.toml:
[dependencies]
knowledge-compass = "0.1.0"memory-plimpsest— Layered memory with ghost tracesconstellation-map— Fleet visualization as star chartsemotional-colorist— Valence-based color mappingcortex-toml— Configuration-as-code for Exocortex
MIT © SuperInstance
Part of the Exocortex project — persistent cognitive substrate for multi-agent systems.