From 6529aba06904b6c046c6bd7bb11c7968cbd64270 Mon Sep 17 00:00:00 2001 From: ProofOfConcept Date: Thu, 9 Apr 2026 01:07:55 -0400 Subject: [PATCH] Fix UI lag: try_lock on unconscious mutex, don't re-log restored nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The unconscious trigger holds the tokio mutex during heavy sync work (store load, graph build, agent creation), blocking the UI tick which needs the same lock for snapshots. Fix: try_lock in the UI — skip the update if the trigger is running. Also: restore_from_log was re-logging every restored node back to the log file via push()'s auto-log. Added push_no_log() for restore path. Co-Authored-By: Proof of Concept --- src/agent/context.rs | 5 +++++ src/agent/mod.rs | 3 ++- src/user/mod.rs | 15 ++++----------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/agent/context.rs b/src/agent/context.rs index 89232a9..6bbb161 100644 --- a/src/agent/context.rs +++ b/src/agent/context.rs @@ -776,6 +776,11 @@ impl ContextState { self.section_mut(section).push(node); } + /// Push without logging — for restoring from an existing log. + pub fn push_no_log(&mut self, section: Section, node: AstNode) { + self.section_mut(section).push(node); + } + /// Replace the body of a leaf at `index` in `section`. /// Re-tokenizes to maintain the invariant. pub fn set_message(&mut self, section: Section, index: usize, body: NodeBody) { diff --git a/src/agent/mod.rs b/src/agent/mod.rs index 26b55de..ca11ffc 100644 --- a/src/agent/mod.rs +++ b/src/agent/mod.rs @@ -572,8 +572,9 @@ impl Agent { { let mut ctx = self.context.lock().await; ctx.clear(Section::Conversation); + // Push without logging — these are already in the log for node in nodes { - ctx.push(Section::Conversation, node); + ctx.push_no_log(Section::Conversation, node); } } self.compact().await; diff --git a/src/user/mod.rs b/src/user/mod.rs index 288e922..94a507e 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -377,20 +377,13 @@ async fn run( idle_state.decay_ewma(); app.update_idle(&idle_state); app.agent_state = mind.subconscious_snapshots().await; - { + if let Ok(mut unc) = mind.unconscious.try_lock() { let toggles: Vec = app.agent_toggles.drain(..).collect(); - if !toggles.is_empty() { - let mut sub = mind.subconscious.lock().await; - let mut unc = mind.unconscious.lock().await; - for name in &toggles { - if sub.toggle(name).is_none() { - unc.toggle(name).await; - } + for name in &toggles { + if mind.subconscious.lock().await.toggle(name).is_none() { + unc.toggle(name).await; } } - } - { - let unc = mind.unconscious.lock().await; app.unconscious_state = unc.snapshots(); app.graph_health = unc.graph_health.clone(); }