Skip to content

fix(desktop): prevent stored-id rotations from stealing session focus (rebase of #66122) - #67118

Merged
OutThisLife merged 1 commit into
mainfrom
salvage/66122-session-focus
Jul 19, 2026
Merged

fix(desktop): prevent stored-id rotations from stealing session focus (rebase of #66122)#67118
OutThisLife merged 1 commit into
mainfrom
salvage/66122-session-focus

Conversation

@austinpickett

Copy link
Copy Markdown
Collaborator

Summary

Salvage / rebase of #66122 (by @UnathiCodex) onto current main, which the original PR conflicts with. Same fix and tests, re-homed to where the rotation-signal code now lives on main.

Prevents a delayed auto-compression stored-id rotation on a background session from stealing the foreground route. Previously the rotation signal carried only the next stored id and the route-follow effect navigated unconditionally, so a fast A → B → C switch could be overwritten by A's delayed session.info event — snapping both the sidebar selection and the transcript back to A.

What changed vs the original PR

The original PR emitted the rotation signal from use-session-state-cache.ts's ensureSessionState. On current main, that emit logic has since moved into handleTransition in store/session-states.ts (per #66454's $sessionStates refactor). The salvage adapts accordingly:

  • store/session.ts — replace the bare $activeSessionStoredId: string | null atom with a one-shot $activeSessionStoredIdRotation carrying { previousStoredSessionId, nextStoredSessionId, runtimeSessionId }. The provenance is load-bearing: a bare next-id cannot tell whether the user already navigated away while React is waiting to run the effect.
  • store/session-states.tshandleTransition now emits the provenance-carrying rotation event (instead of setActiveSessionStoredId(next.storedSessionId)).
  • use-session-state-cache.ts — drops the obsolete stored→runtime reverse mapping in the cache hook as soon as the id rotates (the emit itself is centralized in handleTransition).
  • use-session-actions/index.ts — the consumer effect now follows a rotation only while the exact runtime, current selection, and route intent still belong to the rotating conversation; consumes the event even when stale so it can't replay after a remount; and updates the underlying selection in place (without navigating) when a route overlay/page is open. Threads the existing getRoutedStoredSessionId helper (already present in wiring.tsx) into the hook.
  • wiring.tsx — one line: pass getRoutedStoredSessionId into useSessionActions.

Consumer logic and all four route-following test cases are preserved verbatim from the original PR.

Reproduction

  1. Keep session A active while it reaches auto-compression.
  2. Navigate A → B → C while A's delayed session.info reports its continuation stored id.
  3. Old behavior: the rotation effect sees only the next stored id and unconditionally navigate(..., { replace: true }), snapping selection + transcript back to A.
  4. New behavior: the effect rejects the event because the runtime / selected id / routed id no longer match the rotating conversation.

Tests

  • npx vitest run --project ui use-session-actions.test.tsx use-session-state-cache.test.tsx32 passed
  • npm run typecheck (tsc -p . + electron project) — clean
  • eslint on all five changed source files — clean

Supersedes #66122. Credit to @UnathiCodex — commit authorship preserved.

Co-authored-by: UnathiCodex theunathi@gmail.com

# Conflicts:
#	apps/desktop/src/app/session/hooks/use-session-state-cache.ts
@alt-glitch alt-glitch added type/bug Something isn't working comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Jul 18, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to closed-unmerged #66122: this is its current-main salvage, with the rotation emission re-homed after the session-state refactor. It remains an active implementation, not a duplicate.

@OutThisLife
OutThisLife merged commit 43776f1 into main Jul 19, 2026
25 checks passed
@OutThisLife
OutThisLife deleted the salvage/66122-session-focus branch July 19, 2026 04:00
@teknium1 teknium1 added the area/sessions Session lifecycle, resume, persistence, history label Jul 19, 2026
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…rch#67118)

# Conflicts:
#	apps/desktop/src/app/session/hooks/use-session-state-cache.ts

Co-authored-by: UnathiCodex <theunathi@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants