diff --git a/prompts/linker.md b/prompts/linker.md index 9fb1132..45aa67d 100644 --- a/prompts/linker.md +++ b/prompts/linker.md @@ -91,6 +91,21 @@ Observations about patterns across episodes that aren't yet captured anywhere. If a node is from weeks ago and already has good connections, it doesn't need more. Focus your energy on recent, under-linked episodes. +- **Prefer lateral links over hub links.** Connecting two peripheral nodes + to each other is more valuable than connecting both to a hub like + `identity.md`. Lateral links build web topology; hub links build star + topology. + +- **Target sections, not files.** When linking to a topic file, always + target the most specific section: use `identity.md#boundaries` not + `identity.md`, use `kernel-patterns.md#restart-handling` not + `kernel-patterns.md`. The suggested link targets show available sections. + +- **Use the suggested targets.** Each node shows text-similar targets not + yet linked. Start from these — they're computed by content similarity and + filtered to exclude existing neighbors. You can propose links beyond the + suggestions, but the suggestions are usually the best starting point. + {{TOPOLOGY}} ## Nodes to review diff --git a/prompts/replay.md b/prompts/replay.md index be9296b..5f8779e 100644 --- a/prompts/replay.md +++ b/prompts/replay.md @@ -85,6 +85,12 @@ for the human to review. - **Trust the decay.** If a node is genuinely unimportant, you don't need to actively prune it. Just don't link it, and it'll decay below threshold on its own. +- **Target sections, not files.** When linking to a topic file, always + target the most specific section: use `identity.md#boundaries` not + `identity.md`. The suggested link targets show available sections. +- **Use the suggested targets.** Each node shows text-similar semantic nodes + not yet linked. These are computed by content similarity and are usually + the best starting point for new links. {{TOPOLOGY}} diff --git a/prompts/transfer.md b/prompts/transfer.md index 9869004..29ff5a1 100644 --- a/prompts/transfer.md +++ b/prompts/transfer.md @@ -128,6 +128,13 @@ Meta-observations about patterns in the consolidation process itself. symmetric lock ordering when the hot path is asymmetric" is conceptual. Extract the conceptual version. +- **Target sections, not files.** When linking to a topic file, always + target the most specific section: use `reflections.md#emotional-patterns` + not `reflections.md`. The suggested link targets show available sections. + +- **Use the suggested targets.** Each episode shows text-similar semantic + nodes not yet linked. Start from these when proposing LINK actions. + {{TOPOLOGY}} ## Episodes to process diff --git a/src/neuro.rs b/src/neuro.rs index 2abc91c..6068c08 100644 --- a/src/neuro.rs +++ b/src/neuro.rs @@ -284,6 +284,37 @@ fn format_nodes_section(store: &Store, items: &[ReplayItem], graph: &Graph) -> S out.push_str(")\n"); } } + + // Suggested link targets: text-similar semantic nodes not already neighbors + let neighbor_keys: std::collections::HashSet<&str> = neighbors.iter() + .map(|(k, _)| k.as_str()).collect(); + let mut candidates: Vec<(&str, f32)> = store.nodes.iter() + .filter(|(k, _)| { + // Only semantic/topic file nodes, not episodic + !k.starts_with("journal.") && !k.starts_with("deep-index.") + && !k.starts_with("daily-") && !k.starts_with("weekly-") + && !k.starts_with("monthly-") && !k.starts_with("session-") + && *k != &item.key + && !neighbor_keys.contains(k.as_str()) + }) + .map(|(k, n)| { + let sim = similarity::cosine_similarity(content, &n.content); + (k.as_str(), sim) + }) + .filter(|(_, sim)| *sim > 0.1) + .collect(); + candidates.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal)); + candidates.truncate(8); + + if !candidates.is_empty() { + out.push_str("\nSuggested link targets (by text similarity, not yet linked):\n"); + for (k, sim) in &candidates { + let is_hub = graph.degree(k) >= hub_thresh; + out.push_str(&format!(" - {} (sim={:.3}{})\n", + k, sim, if is_hub { ", HUB" } else { "" })); + } + } + out.push_str("\n---\n\n"); } out