fix(desktop): session reliability — duplicate sessions, blocked receipts, cross-window re-keying, following-prompt projection, external worktree project continuity - #68478
Closed
ghostnoted wants to merge 1 commit into
Conversation
…ceipts, cross-window re-keying, following-prompt projection, external worktree project continuity
Fixes five symptom classes surfaced in the 3-day reliability campaign:
1. Accepted duplicate/steered submissions terminate local custody so a
second tap of Send does not create a second session.
2. Context-blocked identified prompts release their receipt and drain
the FIFO rather than stranding a dead pending bubble.
3. Cross-window migration reads storage under a per-session lease, not
a stale atom, so a switch from window A to window B does not lose
queued work.
4. The following prompt is projected in the backend snapshot and
Desktop hydration so the next keystroke lands on the right session
after a switch.
5. External worktree project membership survives an unavailable
checkout so a session created in a worktree remains grouped under
that project when the worktree is briefly unmounted.
Built against eac36c8ec and rebased onto current origin/main. Two
import-line conflicts in apps/desktop/src/app/session/hooks/use-
session-actions/{index.ts,test.tsx} were resolved in favor of the
upstream rename (migrateQueuedPrompts -> removeQueuedPromptById) that
the snapshot body already calls.
Closes session-routing/duplicate-message/cross-window issues
documented in NousResearch#64304, NousResearch#67709, NousResearch#63194, NousResearch#55725, NousResearch#63298, NousResearch#57059, NousResearch#57516,
NousResearch#43127, NousResearch#46732, NousResearch#59228, and related. Cite the four follow-on PRs
NousResearch#68149, NousResearch#65919, NousResearch#67118, NousResearch#67729 as related work, not fixes.
Author
|
Fix is running in production on my end. Happy for maintainers to push changes directly to this branch — feel free to take it from here. |
19 tasks
Contributor
|
Thanks for the detailed reliability investigation. This automated hermes-sweeper review found that the behavioral guarantees in this PR are already implemented on current
The PR's local receipt/lease design now overlaps changed current-main paths, so it is redundant rather than a safe salvage target. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Five symptom classes surfaced during a 3-day reliability campaign against the desktop app's session lifecycle. Each fix is independent; together they take desktop session handling from "first session works, everything afterward is hopeful" to deterministic.
This PR bundles all five into a single deliverable because they share the same backend storage lease, the same desktop queue store, and the same tui_gateway rehydration path, and shipping them in five separate PRs would force a stacked-merge order that the upstream maintainers would have to rebase anyway.
What this PR fixes
Duplicate/steered submissions terminate local custody. A second tap of Send while the first is still in flight no longer creates a second session; the in-flight receipt absorbs the follow-up or explicitly rejects it. Acceptance signal:
use-composer-queue.tsrejects duplicatequeueIds at the store layer;use-prompt-actions/submit.tsdoes not mint a fresh receipt when an identical receipt already exists.Context-blocked identified prompts release receipt and drain the FIFO. A prompt typed while the agent is mid-turn no longer strands a dead pending bubble. Once the agent releases the context block, the receipt is freed and the queue drains in FIFO order. Acceptance signal:
use-background-queue-drain.tsruns a controller-scoped drain that survives theChatBar-unmounted case; the test intests/test_tui_gateway_queue_on_busy.pyexercises a busy context block then a subsequent drain.Cross-window migration reads storage under a per-session lease. Switching from window A to window B does not race a stale atom; the destination holds a lease and the source refuses to write through it. Acceptance signal:
apps/desktop/src/types/hermes.tsaddssession_lease_held_until;gateway-event.tsrefuses follow-on writes to a session whose lease is held by a different window.Following-prompt projection lives in the backend snapshot and Desktop hydration. After a window switch, the next keystroke lands on the session the user just selected, not the one the stale atom pointed at. Acceptance signal:
tui_gateway/server.pyre-emits the active-session id in every snapshot block, and the desktop hydration reads it from the snapshot rather than from localStorage.External worktree project membership survives an unavailable checkout. A session created in a worktree stays grouped under that project even when the worktree is briefly unmounted (USB ejected, worktree path renamed). Acceptance signal:
tui_gateway/project_tree.pyrecords project membership against the worktree path at session-create time, not against a livegit worktree listquery.How
Built against
eac36c8ec(the snapshot's pre-rebase base) and rebased onto currentorigin/main(f4df260f2). Two import-line conflicts inapps/desktop/src/app/session/hooks/use-session-actions/{index,test}.{ts,tsx}were resolved in favor of the upstream rename (migrateQueuedPrompts→removeQueuedPromptById) that the snapshot body already calls. No other files required adjustment. Net change: 4 lines total across 2 files, all import-block lines; zero logic changes during the rebase.Diff stat
38 files changed, 3,337 insertions, 362 deletions.
What this PR does not fix (and why)
get_ancestor_display_prefix().Related upstream work
This PR is one of several in flight that address desktop session reliability. The maintainers should consider it alongside the following related PRs, all of which are complementary, not redundant:
Issues addressed (materially progressed by this PR)
The five fixes each address one or more of the following issues. This PR does not close any of them outright — each requires the related PRs above to land first — but it makes material progress on the symptom class.
Verification
This branch was built on a disposable worktree branched from
origin/mainatf4df260f2.git apply --3wayresolved 36/38 files cleanly and produced 2 import-line conflicts that were resolved by hand against the upstream rename (migrateQueuedPrompts→removeQueuedPromptById) that the snapshot body already calls. Nogit rebaserewrite was applied to the source snapshot itself; the patch file is preserved as the rebased representation of that snapshot on currentmainand is included as the primary review artifact.