Problem
The TUI status bar shows extracting graph... spinner indefinitely after each turn where graph extraction is triggered.
Root cause
In crates/zeph-core/src/agent/persistence.rs:
// line 473
let _ = self.channel.send_status("extracting graph...").await; // spinner ON
// line 489
memory.spawn_graph_extraction(...); // fire-and-forget tokio::spawn — returns immediately
// ← no send_status("") here — spinner is NEVER cleared
spawn_graph_extraction() spawns a background task and returns immediately. The status "" is only reset inside check_summarization() (line 527), which is a separate code path. After graph extraction is spawned, the status bar is never cleared.
Additionally, if the extraction LLM times out (extraction_timeout_secs = 15 default), the timeout is silently swallowed with only a tracing::warn — the spinner still stays visible.
Fix options
Option A (simplest): Clear status immediately after spawn_graph_extraction():
memory.spawn_graph_extraction(...);
let _ = self.channel.send_status("").await; // clear right away
This is honest — the task is background, the UI shouldn't pretend to be waiting for it.
Option B (accurate): Pass a oneshot::Sender into the background task and clear the status when the task completes or times out:
let (done_tx, done_rx) = tokio::sync::oneshot::channel();
memory.spawn_graph_extraction(..., Some(done_tx));
// inside spawn: done_tx.send(()) on completion/error/timeout
// in agent: await done_rx then send_status("")
This would require making the agent block on extraction, defeating the fire-and-forget design.
Recommended: Option A. Since extraction is intentionally async and non-blocking, the status message should reflect that — e.g. change the label to "saving to graph..." and clear it immediately after spawn, or simply remove the send_status call entirely for this path.
Affected code
crates/zeph-core/src/agent/persistence.rs lines 473–489
Steps to reproduce
- Enable graph memory in config (
[memory.graph] enabled = true)
- Start a conversation — after each turn the TUI shows
extracting graph...
- The spinner never goes away until the next status event overwrites it
Problem
The TUI status bar shows
extracting graph...spinner indefinitely after each turn where graph extraction is triggered.Root cause
In
crates/zeph-core/src/agent/persistence.rs:spawn_graph_extraction()spawns a background task and returns immediately. The status""is only reset insidecheck_summarization()(line 527), which is a separate code path. After graph extraction is spawned, the status bar is never cleared.Additionally, if the extraction LLM times out (
extraction_timeout_secs = 15default), the timeout is silently swallowed with only atracing::warn— the spinner still stays visible.Fix options
Option A (simplest): Clear status immediately after
spawn_graph_extraction():This is honest — the task is background, the UI shouldn't pretend to be waiting for it.
Option B (accurate): Pass a
oneshot::Senderinto the background task and clear the status when the task completes or times out:This would require making the agent block on extraction, defeating the fire-and-forget design.
Recommended: Option A. Since extraction is intentionally async and non-blocking, the status message should reflect that — e.g. change the label to
"saving to graph..."and clear it immediately after spawn, or simply remove thesend_statuscall entirely for this path.Affected code
crates/zeph-core/src/agent/persistence.rslines 473–489Steps to reproduce
[memory.graph] enabled = true)extracting graph...