Repository navigation
ai_chat_send_to_idle_test times out with assistant_count=0 — blocks the pre-push gate (4/5 attempts today) #2224
Description
Summary
packages/desktop-app/src-tauri/tests/ai_chat_send_to_idle_test.rs's only test, ai_chat_send_reaches_idle_with_no_stuck_processing_state (ADR-048 Tauri-seam suite, part of the mandatory scripts/test-gate.ts pre-push gate), is currently timing out at its 300s deadline with assistant_count=0 in 4 of 5 consecutive git push attempts today, blocking every push from this checkout regardless of what changed.
What was observed
Working an unrelated packages/agent change (core#2190 — a comment-only edit to tools.rs plus a new golden-case trio under goldens/ablation/, no touch to desktop-app, ai-chat, or the daemon's event-watcher/inference-dispatch code at all), the pre-push gate failed 5 times in a row:
- FAILED —
ai_chat_send_reaches_idle_with_no_stuck_processing_state, 300s timeout,last status="idle", assistant_count=0 - FAILED — different test (
model-store.test.ts, an unrelated frontend fake-timer flake) — not part of this report - FAILED — same test, same symptom,
finished in 302.86s - FAILED — same test, same symptom,
finished in 303.83s - FAILED — same test, same symptom,
finished in 303.14s
Panic message (identical each time):
thread 'ai_chat_send_reaches_idle_with_no_stuck_processing_state' panicked at packages/desktop-app/src-tauri/tests/ai_chat_send_to_idle_test.rs:98:13:
ai-chat turn did not reach idle-with-new-reply within 300s; last status="idle", assistant_count=0
assistant_count=0 means the polled node never gained a new assistant message at all — not that generation was slow, but that the turn appears to never have produced (or never dispatched) a reply within the daemon under test.
Why this doesn't look like ordinary machine-load flakiness
- The test's own doc comment already documents a prior class of stall (
ministral-3b-q4km"reproducibly stalled to 0 tokens generated within the 300s timeout, independent of machine load") that led to a model swap, so this suite has known history here — but the current lock (per ADR-056) isgemma-4-E4B-it-Q4_K_M. - In the same session, the same model was driven successfully 27/27 times via
nodespace_agent::golden::runner's directLlamaChatInferenceEnginepath (packages/agent/src/bin/golden_runner.rs) for core#2190's own measurement — so the model itself generates correctly through that path. This test instead drives a fullnodespaceddaemon through the real Tauri command layer and pollsget_node, so the failure looks like it's somewhere in the daemon's event-watcher / inference-turn-dispatch path (or a resource contention specific to running a second full daemon+model instance), not in the model or in llama.cpp itself. - 4 of 5 attempts hit the exact same symptom and near-identical duration (~303s), which reads as systematic rather than one-off.
What this is not
Not caused by core#2190's own diff — verified as a pure comment addition to tools.rs (zero functional change) plus new golden-case fixtures. The pre-push gate reproduces this failure regardless of whether that diff is present.
Ask
Someone who owns the ADR-048 Tauri-seam suite / daemon ai-chat dispatch path should reproduce directly (cargo test -p nodespace-app --test ai_chat_send_to_idle_test) outside a loaded pre-push-gate run, and check whether this is transient contention in a specific environment or a live regression in turn dispatch. Until then, this blocks the mandatory pre-push gate for any change touching this checkout.
Activity
mstomar125 commentedon Aug 24, 2026
Root cause: the failing runs spawned a 2026-07-24
nodespaced, not a build ofmainReproduced the reported signature verbatim and traced it. This is not a regression in the daemon's turn-completion path — current
main's daemon passes this test repeatedly, and a month-old daemon binary fails it in exactly the way reported.1. Current
mainpassesFresh worktree at
5c4f3cba, daemon fromcargo build --bin nodespaced:cargo test -p nodespace-app --test ai_chat_send_to_idle_testcargo test -p nodespace-app -- --test-threads=1withNODESPACED_TEST_BIN2. The binary the failing runs used is from 24 July
The first three are byte-identical — copied around, never rebuilt. A real debug
nodespacedtoday is ~99 MB, not 27 MB.nodespace-app-test-support::resolve_daemon_binary()resolvedNODESPACED_TEST_BIN, else the hand-stagedsrc-tauri/binaries/sidecar — so the isolated repro in the primary checkout (no env override) spawned the 24 July sidecar. And whatevercargo build --bin nodespaceddid at gate step 2, the binary the gate then pointedNODESPACED_TEST_BINat was byte-identical to that same July build; cargo's freshness check is mtime-based, so build outputs copied into a fresh worktree date newer than its sources and register as up to date.3. Pointing the test at that July binary reproduces the report exactly
and the daemon's own log, one second into the turn:
The turn failed with
ContextOverflowand that daemon resetstatustoidlewithout appending anything — the pre-#2168 behaviour. #2168 (39d4f08a, merged 2026-08-19) is the change that made a failed inference turn append a visible assistant message instead of going silently idle; its regression testfailed_inference_turn_surfaces_a_visible_error_not_silent_idlepins the identical error string. Any daemon built before 2026-08-19 has the old behaviour, andstatus="idle", assistant_count=0is its signature.version: 3in the node dump above (create → user message → status reset) confirms the silent status write.Ruled out
packages/agentmerges — freshmainpasses; reproducing the failure needs the July binary.agent_loop.rscompletion paths — onmaineveryrun_turnreturn carries non-empty text (including the no-usable-final-text fallback), so theOkarm always appends and theErrarm appends the failure message. The only remaining zero-append idle paths are cancellation (deliberate) and a failedappend_assistant_message; neither is reachable here.nodespace_core::models::AiChatMessageandnodespace_types::ai_chat::AiChatMessageare field-for-field identical, and the node dump confirms the node genuinely held no assistant message.Fix
#2258 — no production code changed. The ADR-048 fixture now prefers
target/debug/nodespacedover the sidecar and refuses to spawn a daemon older than the sources compiled into it, failing in 0.01s with both filenames and how to rebuild, rather than surfacing minutes later as a behavioural failure blamed on whatever is being pushed. Plus two diagnosability fixes that made this traceable at all:RUST_LOGis forwarded to the spawned daemon, and the ai-chat timeout panic now dumps the polled node instead of two derived counters.If you hit this on this machine
core/target/debug/nodespacedandcore/packages/desktop-app/src-tauri/binaries/nodespaced-*are still the July binaries —rmthem and rebuild before running the ADR-048 suite. With this PR merged you get told that instead of having to work it out.