agents: {{HUBS}} placeholder for top 20 spread-apart hub nodes

New placeholder resolves to the 20 highest-degree nodes, skipping
neighbors of already-selected hubs so the list covers different
regions of the graph. Gives agents a starting point for linking
new content to the right places.

Added to observation.agent prompt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kent Overstreet 2026-03-16 21:00:31 -04:00
parent 15d4bfa01f
commit 1aad6d90af
2 changed files with 30 additions and 0 deletions

View file

@ -65,6 +65,8 @@ If there's nothing worth extracting, just say so.
- **Specific over vague.**
- **Don't force it.** "Nothing new here" is valid output.
{{HUBS}}
## Conversation fragments to mine
{{CONVERSATIONS}}

View file

@ -271,6 +271,34 @@ fn resolve(
})
}
"hubs" => {
// Top hub nodes by degree, spread apart (skip neighbors of already-selected hubs)
let mut hubs: Vec<(String, usize)> = store.nodes.iter()
.filter(|(k, n)| !n.deleted && !k.starts_with('_'))
.map(|(k, _)| {
let degree = graph.neighbors(k).len();
(k.clone(), degree)
})
.collect();
hubs.sort_by(|a, b| b.1.cmp(&a.1));
let mut selected = Vec::new();
let mut seen: std::collections::HashSet<String> = std::collections::HashSet::new();
for (key, degree) in &hubs {
if seen.contains(key) { continue; }
selected.push(format!(" - {} (degree {})", key, degree));
// Mark neighbors as seen so we pick far-apart hubs
for (nbr, _) in graph.neighbors(key) {
seen.insert(nbr.clone());
}
seen.insert(key.clone());
if selected.len() >= 20 { break; }
}
let text = format!("## Hub nodes (link targets)\n\n{}", selected.join("\n"));
Some(Resolved { text, keys: vec![] })
}
// node:KEY — inline a node's content by key
other if other.starts_with("node:") => {
let key = &other[5..];