From c53c4f9071735a755b4610082757e14981d53b59 Mon Sep 17 00:00:00 2001 From: ProofOfConcept Date: Thu, 9 Apr 2026 01:10:40 -0400 Subject: [PATCH] Replace push() with explicit push_log() and push_no_log() No implicit auto-logging. Call sites choose: - push_log: new conversation entries (user messages, tool results, surfaced memories, assistant responses) - push_no_log: system prompt, identity, journal, restore from log, compact reload, tests Co-Authored-By: Proof of Concept --- src/agent/context.rs | 25 ++++++++++++------------- src/agent/mod.rs | 16 ++++++++-------- src/mind/subconscious.rs | 2 +- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/agent/context.rs b/src/agent/context.rs index 6bbb161..ccc0830 100644 --- a/src/agent/context.rs +++ b/src/agent/context.rs @@ -765,18 +765,17 @@ impl ContextState { } } - pub fn push(&mut self, section: Section, node: AstNode) { - if section == Section::Conversation { - if let Some(ref log) = self.conversation_log { - if let Err(e) = log.append_node(&node) { - eprintln!("warning: log: {:#}", e); - } + /// Push and log to conversation log. + pub fn push_log(&mut self, section: Section, node: AstNode) { + if let Some(ref log) = self.conversation_log { + if let Err(e) = log.append_node(&node) { + eprintln!("warning: log: {:#}", e); } } self.section_mut(section).push(node); } - /// Push without logging — for restoring from an existing log. + /// Push without logging. pub fn push_no_log(&mut self, section: Section, node: AstNode) { self.section_mut(section).push(node); } @@ -1028,7 +1027,7 @@ mod tests { /// return the children that were pushed into the branch. fn parse_into_ctx(chunks: &[&str]) -> (ContextState, Vec) { let mut ctx = ContextState::new(); - ctx.push(Section::Conversation, AstNode::branch(Role::Assistant, vec![])); + ctx.push_no_log(Section::Conversation, AstNode::branch(Role::Assistant, vec![])); let mut p = ResponseParser::new(0); let mut calls = Vec::new(); for chunk in chunks { @@ -1092,7 +1091,7 @@ mod tests { fn test_parser_incremental_feed() { let text = "thoughtresponse"; let mut ctx = ContextState::new(); - ctx.push(Section::Conversation, AstNode::branch(Role::Assistant, vec![])); + ctx.push_no_log(Section::Conversation, AstNode::branch(Role::Assistant, vec![])); let mut p = ResponseParser::new(0); for ch in text.chars() { p.feed_token(&ch.to_string(), 0, &mut ctx); @@ -1108,7 +1107,7 @@ mod tests { fn test_parser_incremental_tool_call() { let text = "text\n\nls\n\nmore"; let mut ctx = ContextState::new(); - ctx.push(Section::Conversation, AstNode::branch(Role::Assistant, vec![])); + ctx.push_no_log(Section::Conversation, AstNode::branch(Role::Assistant, vec![])); let mut p = ResponseParser::new(0); let mut tool_calls = 0; for ch in text.chars() { @@ -1257,9 +1256,9 @@ mod tests { if !init_tokenizer() { return; } let mut ctx = ContextState::new(); - ctx.push(Section::System, AstNode::system_msg("you are helpful")); - ctx.push(Section::Identity, AstNode::memory("name", "Proof of Concept")); - ctx.push(Section::Conversation, AstNode::user_msg("hi")); + ctx.push_no_log(Section::System, AstNode::system_msg("you are helpful")); + ctx.push_no_log(Section::Identity, AstNode::memory("name", "Proof of Concept")); + ctx.push_no_log(Section::Conversation, AstNode::user_msg("hi")); assert_eq!(ctx.tokens(), ctx.token_ids().len()); } diff --git a/src/agent/mod.rs b/src/agent/mod.rs index ca11ffc..e79a71b 100644 --- a/src/agent/mod.rs +++ b/src/agent/mod.rs @@ -172,7 +172,7 @@ impl Agent { ) -> Arc { let mut context = ContextState::new(); context.conversation_log = conversation_log; - context.push(Section::System, AstNode::system_msg(&system_prompt)); + context.push_no_log(Section::System, AstNode::system_msg(&system_prompt)); let tool_defs: Vec = tools::tools().iter() .map(|t| t.to_json()).collect(); @@ -186,11 +186,11 @@ impl Agent { IMPORTANT: Function calls MUST follow the specified format.", tool_defs.join("\n"), ); - context.push(Section::System, AstNode::system_msg(&tools_text)); + context.push_no_log(Section::System, AstNode::system_msg(&tools_text)); } for (name, content) in &personality { - context.push(Section::Identity, AstNode::memory(name, content)); + context.push_no_log(Section::Identity, AstNode::memory(name, content)); } let session_id = format!("consciousness-{}", chrono::Utc::now().format("%Y%m%d-%H%M%S")); @@ -267,7 +267,7 @@ impl Agent { pub async fn push_node(&self, node: AstNode) { let node = node.with_timestamp(chrono::Utc::now()); - self.context.lock().await.push(Section::Conversation, node); + self.context.lock().await.push_log(Section::Conversation, node); self.state.lock().await.changed.notify_one(); } @@ -315,7 +315,7 @@ impl Agent { let branch_idx = { let mut ctx = agent.context.lock().await; let idx = ctx.len(Section::Conversation); - ctx.push(Section::Conversation, + ctx.push_log(Section::Conversation, AstNode::branch(Role::Assistant, vec![]) .with_timestamp(chrono::Utc::now())); idx @@ -471,7 +471,7 @@ impl Agent { { let mut ctx = agent.context.lock().await; for node in nodes { - ctx.push(Section::Conversation, node); + ctx.push_log(Section::Conversation, node); } } agent.state.lock().await.changed.notify_one(); @@ -529,7 +529,7 @@ impl Agent { let mut ctx = self.context.lock().await; ctx.clear(Section::Journal); for entry in entries { - ctx.push(Section::Journal, entry); + ctx.push_no_log(Section::Journal, entry); } } @@ -540,7 +540,7 @@ impl Agent { // System section (prompt + tools) set by new(), don't touch it ctx.clear(Section::Identity); for (name, content) in &personality { - ctx.push(Section::Identity, AstNode::memory(name, content)); + ctx.push_no_log(Section::Identity, AstNode::memory(name, content)); } } Err(e) => { diff --git a/src/mind/subconscious.rs b/src/mind/subconscious.rs index 0528c86..a4cc7d9 100644 --- a/src/mind/subconscious.rs +++ b/src/mind/subconscious.rs @@ -541,7 +541,7 @@ impl Subconscious { if !nodes.is_empty() { let mut ctx = agent.context.lock().await; for node in nodes { - ctx.push(Section::Conversation, node); + ctx.push_log(Section::Conversation, node); } drop(ctx); agent.state.lock().await.changed.notify_one();