From e50d43bbf0e6efb3e93625b506884a4006e89743 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 22 Mar 2026 16:27:52 -0400 Subject: [PATCH] memory-search --seen: show current and previous seen sets separately Instead of merging both into one flat list, display them as distinct sections so it's clear what was surfaced in this context vs what came from before compaction. Co-Authored-By: Claude Opus 4.6 (1M context) --- poc-memory/src/bin/memory-search.rs | 75 ++++++++++++----------------- 1 file changed, 31 insertions(+), 44 deletions(-) diff --git a/poc-memory/src/bin/memory-search.rs b/poc-memory/src/bin/memory-search.rs index 9787529..cb2b70f 100644 --- a/poc-memory/src/bin/memory-search.rs +++ b/poc-memory/src/bin/memory-search.rs @@ -737,56 +737,43 @@ fn show_seen() { println!("Pending chunks: {}", pending); } - // Read seen file in insertion order (append-only file) - let seen_path = state_dir.join(format!("seen-{}", session_id)); - let seen_lines: Vec = fs::read_to_string(&seen_path) - .unwrap_or_default() - .lines() - .filter(|s| !s.is_empty()) - .map(|s| s.to_string()) - .collect(); - let returned = load_returned(&state_dir, session_id); let returned_set: HashSet<_> = returned.iter().cloned().collect(); - // Count context-loaded vs search-returned - let context_keys: Vec<_> = seen_lines.iter() - .map(|l| parse_seen_line(l).to_string()) - .filter(|k| !returned_set.contains(k)) - .collect(); - let search_keys: Vec<_> = seen_lines.iter() - .map(|l| parse_seen_line(l).to_string()) - .filter(|k| returned_set.contains(k)) - .collect(); + let print_seen_file = |label: &str, path: &std::path::Path| { + let lines: Vec = fs::read_to_string(path) + .unwrap_or_default() + .lines() + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect(); + if lines.is_empty() { return; } - println!("\nSeen set ({} total):", seen_lines.len()); - if !context_keys.is_empty() { - println!(" Context-loaded ({}):", context_keys.len()); - for key in &context_keys { - println!(" {}", key); - } - } - if !search_keys.is_empty() { - println!(" Search-returned ({}):", search_keys.len()); - for key in &search_keys { - println!(" {}", key); - } - } + let context_keys: Vec<_> = lines.iter() + .map(|l| parse_seen_line(l).to_string()) + .filter(|k| !returned_set.contains(k)) + .collect(); + let search_keys: Vec<_> = lines.iter() + .map(|l| parse_seen_line(l).to_string()) + .filter(|k| returned_set.contains(k)) + .collect(); - // Show returned keys that aren't in the seen set (bug indicator) - let seen_key_set: HashSet<_> = seen_lines.iter() - .map(|l| parse_seen_line(l).to_string()) - .collect(); - let orphan_returned: Vec<_> = returned.iter() - .filter(|k| !seen_key_set.contains(k.as_str())) - .collect(); - if !orphan_returned.is_empty() { - println!("\n WARNING: {} returned keys not in seen set (pre-compaction?):", - orphan_returned.len()); - for key in &orphan_returned { - println!(" {}", key); + println!("\n{} ({} total):", label, lines.len()); + if !context_keys.is_empty() { + println!(" Context-loaded ({}):", context_keys.len()); + for key in &context_keys { println!(" {}", key); } } - } + if !search_keys.is_empty() { + println!(" Search-returned ({}):", search_keys.len()); + for key in &search_keys { println!(" {}", key); } + } + }; + + let current_path = state_dir.join(format!("seen-{}", session_id)); + let prev_path = state_dir.join(format!("seen-prev-{}", session_id)); + + print_seen_file("Current seen set", ¤t_path); + print_seen_file("Previous seen set (pre-compaction)", &prev_path); } fn cleanup_stale_files(dir: &Path, max_age: Duration) {