Skip to content

fix(desktop): keep and recover interrupted chats across update/restart - #81319

Open
Vibe-coding-nvm-delete-repo wants to merge 2 commits into
NousResearch:mainfrom
Vibe-coding-nvm-delete-repo:fix/desktop-recover-interrupted-chats-on-update
Open

fix(desktop): keep and recover interrupted chats across update/restart#81319
Vibe-coding-nvm-delete-repo wants to merge 2 commits into
NousResearch:mainfrom
Vibe-coding-nvm-delete-repo:fix/desktop-recover-interrupted-chats-on-update

Conversation

@Vibe-coding-nvm-delete-repo

Copy link
Copy Markdown

Summary

After a desktop update/refresh, in-flight chats were dying and not coming back.

Root cause: update handoff / tui_shutdown concluded turns cleanly, which retired crash markers in interrupted_turns.json. Auto-continue only runs on session.resume, and lazy tabs don't resume until clicked — so multi-chat work stayed dead after refresh.

Changes

  1. Preserve markers on process/update teardown (tui_shutdown, compute-host reasons, etc.) via _preserve_turn_marker_for_shutdown. User-initiated Stop/close still clears markers.
  2. Boot recovery (_ensure_interrupted_turn_recovery at gateway.ready): cold-resume every fresh marker (cap 12), not only the focused tab.
  3. Marker sidecar: list_turn_markers, optional cause / keep_started_at on record_turn_start.
  4. Also includes local park-not-drop for unowned async_delegation completions (prior local fix on this install).

Test plan

  • uv run --python 3.11 pytest tests/tui_gateway/test_auto_continue.py -q → 19 passed
  • Start several running chats → apply desktop update/restart → all marked chats auto-resume with "Resuming interrupted turn…"
  • User Stop still ends a turn without auto-continue
  • Stale markers beyond freshness window are cleared, not resumed

Jason Ez added 2 commits August 7, 2026 16:50
…opping

After backend restart, restore_undelivered_completions requeues durable
pending child results; a non-owner session poller was dropping them so
parents went silent. Park orphans and let the owning tab claim on resume.

Also raise background_review max_iterations 16→48 so skill self-improve
thrash cannot burn the whole budget and strand a parent mid-wave.
Update handoff and tui_shutdown used to conclude in-flight turns cleanly,
which retired crash markers — so auto-continue had nothing to resume after
refresh. Preserve markers on process/update teardown, and on gateway.ready
cold-resume every fresh marker (not only the focused tab).
@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/tui Terminal UI (ui-tui/ + tui_gateway/) tool/delegate Subagent delegation P2 Medium — degraded but workaround exists sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Aug 7, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #72231, #72585, and #69697 cover adjacent interrupted-turn recovery behavior. This PR's shutdown-marker preservation, boot-time multi-session recovery, and async-delegation ownership parking are distinct mechanisms.

@ryantuc

ryantuc commented Aug 14, 2026

Copy link
Copy Markdown

The shutdown-preservation half of this is a real fix, and the diagnosis is right: tui_shutdown concluding a turn cleanly retires a marker that a lazy tab then never resumes, so the work stays dead. Two notes from running two hermes serve processes against one HERMES_HOME, where both of these changes behave differently than they do on a single-backend box.

_normalize_entry builds its output from scratch with attempts, prompt, started_at, and the new optional cause, and drops every other key on the entry. Since list_turn_markers routes every entry through it, that whitelist is now the only view boot recovery has of a marker. Anything an entry carries about who wrote it disappears at the read, silently, and there is no way for a later reader to tell a stripped entry from one that never had the field. That matters in a shared home, because owner identity on the marker is the only thing that could distinguish another process's live turn from a crash, and it is what any ownership-stamped marker would need to carry. The ask is one function: either copy unknown keys through to the output, or preserve a named owner block alongside the four fields you validate. Round-tripping unknown keys is the smaller change and keeps the PR's validation intact, since you would still be coercing and defaulting exactly the fields you coerce today.

The other one is about the boot scan rather than the code. _ensure_interrupted_turn_recovery runs once per process at gateway.ready and cold-resumes up to 12 markers, and in a multi-backend home every backend runs it, over the same file. Two backends restarting together (which is the normal case after an update, since they share an install) each enumerate the same markers and each schedule continuations for them. The good news is that this does not need new machinery in the PR to be fixable later: both legs of the loop already funnel through _maybe_schedule_auto_continue, the live one directly and the cold one through session.resume, so a single admission gate at that function covers the boot scan and the per-tab resume at once. I have written up what I think that gate should be, and why the marker file is the wrong place to put it, at #86190. Nothing there conflicts with this PR; it would sit under it. Worth a line in the PR description either way, since 12 sessions per process per boot is a much wider window than the focused-tab path this replaces.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state tool/delegate Subagent delegation type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants