render: deduplicate footer links against inline references
Render now detects neighbor keys that already appear in the node's content and omits them from the footer link list. Inline references serve as the node's own navigation structure; the footer catches only neighbors not mentioned in prose. Also fixes PEG query parser to accept hyphens in field names (content-len was rejected). memory-instructions-core updated to v12: documents canonical inline link format (→ `key`), adds note about normalizing references when updating nodes, and guidance on splitting oversized nodes. Content is never modified for display — render is round-trippable. Agents can read rendered output and write it back without artifacts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9517b1b310
commit
601a072cfd
2 changed files with 30 additions and 12 deletions
|
|
@ -198,23 +198,41 @@ pub fn cmd_render(key: &[String]) -> Result<(), String> {
|
|||
let node = store.nodes.get(&bare)
|
||||
.ok_or_else(|| format!("Node not found: {}", bare))?;
|
||||
|
||||
print!("{}", node.content);
|
||||
|
||||
// Show links so the graph is walkable
|
||||
let mut neighbors: Vec<(&str, f32)> = Vec::new();
|
||||
// Build neighbor lookup: key → strength
|
||||
let mut neighbor_strengths: std::collections::HashMap<&str, f32> = std::collections::HashMap::new();
|
||||
for r in &store.relations {
|
||||
if r.deleted { continue; }
|
||||
if r.source_key == bare {
|
||||
neighbors.push((&r.target_key, r.strength));
|
||||
let e = neighbor_strengths.entry(&r.target_key).or_insert(0.0);
|
||||
*e = e.max(r.strength);
|
||||
} else if r.target_key == bare {
|
||||
neighbors.push((&r.source_key, r.strength));
|
||||
let e = neighbor_strengths.entry(&r.source_key).or_insert(0.0);
|
||||
*e = e.max(r.strength);
|
||||
}
|
||||
}
|
||||
if !neighbors.is_empty() {
|
||||
neighbors.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
|
||||
neighbors.dedup_by(|a, b| a.0 == b.0);
|
||||
let total = neighbors.len();
|
||||
let shown: Vec<_> = neighbors.iter().take(15)
|
||||
|
||||
// Detect which neighbors are already referenced inline in the content.
|
||||
// These are omitted from the footer to avoid duplication.
|
||||
let mut inline_keys: std::collections::HashSet<String> = std::collections::HashSet::new();
|
||||
for nbr_key in neighbor_strengths.keys() {
|
||||
// Match `key` (backtick-quoted) or bare key after → arrow
|
||||
if node.content.contains(nbr_key) {
|
||||
inline_keys.insert(nbr_key.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
print!("{}", node.content);
|
||||
|
||||
// Footer: only show links NOT already referenced inline
|
||||
let mut footer_neighbors: Vec<(&str, f32)> = neighbor_strengths.iter()
|
||||
.filter(|(k, _)| !inline_keys.contains(**k))
|
||||
.map(|(k, s)| (*k, *s))
|
||||
.collect();
|
||||
|
||||
if !footer_neighbors.is_empty() {
|
||||
footer_neighbors.sort_by(|a, b| b.1.total_cmp(&a.1));
|
||||
let total = footer_neighbors.len();
|
||||
let shown: Vec<_> = footer_neighbors.iter().take(15)
|
||||
.map(|(k, s)| format!("({:.2}) `poc-memory render {}`", s, k))
|
||||
.collect();
|
||||
print!("\n\n---\nLinks:");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue