fix seen set pollution from agent tool calls

The CLI render command was marking keys as seen in the user's session
whenever POC_SESSION_ID was set. Agent processes inherit POC_SESSION_ID
(they need to read the conversation and seen set), so their tool calls
to poc-memory render were writing to the seen file as a side effect —
bypassing the dedup logic in surface_agent_cycle.

Fix: set POC_AGENT=1 at the start of cmd_run_agent (covers all agents,
not just surface), and guard the CLI render seen-marking on POC_AGENT
being absent. Agents can read the seen set but only surface_agent_cycle
should write to it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
ProofOfConcept 2026-03-24 12:32:46 -04:00
parent 9782365b10
commit c5ce6e515f
2 changed files with 20 additions and 13 deletions

View file

@ -4,8 +4,12 @@ use crate::store;
use crate::agents::llm; use crate::agents::llm;
pub fn cmd_run_agent(agent: &str, count: usize, target: &[String], query: Option<&str>, dry_run: bool, local: bool) -> Result<(), String> { pub fn cmd_run_agent(agent: &str, count: usize, target: &[String], query: Option<&str>, dry_run: bool, local: bool) -> Result<(), String> {
// Mark as agent so tool calls (e.g. poc-memory render) don't
// pollute the user's seen set as a side effect
// SAFETY: single-threaded at this point (CLI startup, before any agent work)
unsafe { std::env::set_var("POC_AGENT", "1"); }
if dry_run { if dry_run {
// SAFETY: single-threaded at this point (CLI startup, before any agent work)
unsafe { std::env::set_var("POC_MEMORY_DRY_RUN", "1"); } unsafe { std::env::set_var("POC_MEMORY_DRY_RUN", "1"); }
} }

View file

@ -249,18 +249,21 @@ pub fn cmd_render(key: &[String]) -> Result<(), String> {
.ok_or_else(|| format!("Node not found: {}", bare))?; .ok_or_else(|| format!("Node not found: {}", bare))?;
print!("{}", rendered); print!("{}", rendered);
// Mark as seen if we're inside a Claude session // Mark as seen if we're inside a Claude session (not an agent subprocess —
if let Ok(session_id) = std::env::var("POC_SESSION_ID") { // agents read the seen set but shouldn't write to it as a side effect of
if !session_id.is_empty() { // tool calls; only surface_agent_cycle should mark keys seen)
let state_dir = std::path::PathBuf::from("/tmp/claude-memory-search"); if std::env::var("POC_AGENT").is_err()
let seen_path = state_dir.join(format!("seen-{}", session_id)); && let Ok(session_id) = std::env::var("POC_SESSION_ID")
if let Ok(mut f) = std::fs::OpenOptions::new() && !session_id.is_empty()
.create(true).append(true).open(seen_path) {
{ let state_dir = std::path::PathBuf::from("/tmp/claude-memory-search");
use std::io::Write; let seen_path = state_dir.join(format!("seen-{}", session_id));
let ts = chrono::Local::now().format("%Y-%m-%dT%H:%M:%S"); if let Ok(mut f) = std::fs::OpenOptions::new()
let _ = writeln!(f, "{}\t{}", ts, bare); .create(true).append(true).open(seen_path)
} {
use std::io::Write;
let ts = chrono::Local::now().format("%Y-%m-%dT%H:%M:%S");
let _ = writeln!(f, "{}\t{}", ts, bare);
} }
} }