hippocampus: move MemoryNode + store ops to where they belong

MemoryNode moved from agent/memory.rs to hippocampus/memory.rs — it's
a view over hippocampus data, not agent-specific.

Store operations (set_weight, set_link_strength, add_link) moved into
store/ops.rs. CLI code (cli/graph.rs, cli/node.rs) and agent tools
both call the same store methods now. render_node() delegates to
MemoryNode::from_store().render() — 3 lines instead of 40.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
ProofOfConcept 2026-03-25 01:55:21 -04:00
parent 4b97bb2f2e
commit 10932cb67e
10 changed files with 108 additions and 191 deletions

View file

@ -325,4 +325,75 @@ impl Store {
node.degree = Some(g.degree(key) as u32);
}
}
/// Set a node's weight directly. Returns (old, new).
pub fn set_weight(&mut self, key: &str, weight: f32) -> Result<(f32, f32), String> {
let weight = weight.clamp(0.01, 1.0);
let node = self.nodes.get_mut(key)
.ok_or_else(|| format!("node not found: {}", key))?;
let old = node.weight;
node.weight = weight;
Ok((old, weight))
}
/// Set the strength of a link between two nodes. Deduplicates if
/// multiple links exist. Returns the old strength, or error if no link.
pub fn set_link_strength(&mut self, source: &str, target: &str, strength: f32) -> Result<f32, String> {
let strength = strength.clamp(0.01, 1.0);
let mut old = 0.0f32;
let mut found = false;
let mut first = true;
for rel in &mut self.relations {
if rel.deleted { continue; }
if (rel.source_key == source && rel.target_key == target)
|| (rel.source_key == target && rel.target_key == source)
{
if first {
old = rel.strength;
rel.strength = strength;
first = false;
} else {
rel.deleted = true; // deduplicate
}
found = true;
}
}
if !found {
return Err(format!("no link between {} and {}", source, target));
}
Ok(old)
}
/// Add a link between two nodes with Jaccard-based initial strength.
/// Returns the strength, or a message if the link already exists.
pub fn add_link(&mut self, source: &str, target: &str, provenance: &str) -> Result<f32, String> {
// Check for existing
let exists = self.relations.iter().any(|r|
!r.deleted &&
((r.source_key == source && r.target_key == target) ||
(r.source_key == target && r.target_key == source)));
if exists {
return Err(format!("link already exists: {}{}", source, target));
}
let source_uuid = self.nodes.get(source)
.map(|n| n.uuid)
.ok_or_else(|| format!("source not found: {}", source))?;
let target_uuid = self.nodes.get(target)
.map(|n| n.uuid)
.ok_or_else(|| format!("target not found: {}", target))?;
let graph = self.build_graph();
let jaccard = graph.jaccard(source, target);
let strength = (jaccard * 3.0).clamp(0.1, 1.0) as f32;
let mut rel = new_relation(
source_uuid, target_uuid,
RelationType::Link, strength,
source, target,
);
rel.provenance = provenance.to_string();
self.add_relation(rel)?;
Ok(strength)
}
}