fix(desktop): slash commands target the user's chat, not a new session - #71605
Merged
Conversation
`/goal status` reported "No active goal" for a goal that was live: the desktop's slash pipeline resolved its target session differently than the submit pipeline, so the command ran against a different session than the chat on screen. `/goal` state is persisted per-session in SessionDB (`state_meta` key `goal:<session_id>`). slash.ts resolved with a bare `hint || activeRef || createBackendSessionForSend()`, so whenever the runtime binding was momentarily absent — profile swap, reconnect, orphan-reap, request timeout — it silently MINTED A NEW SESSION and ran there. submit.ts already handles this case by resuming the routed stored session on its owning profile (#55578, #67603). Extract that ladder into one shared resolver both pipelines use, per the "one resolver owns each policy" rule in apps/desktop/AGENTS.md. This fixes the whole class, not just `/goal`: every exec/rpc slash command (`/usage`, `/status`, `/tools`, …) had the same hole. A targeted durable conversation whose runtime cannot be rebound now returns null instead of forking the chat — reporting that a command could not run beats running it against the wrong session.
Contributor
૮ >ﻌ< ა ci reviewran on 344ef09 all good! |
This was referenced Jul 25, 2026
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.
Infographic
Summary
Desktop slash commands now run against the chat the user is looking at, instead of silently creating a new session to run against.
Reported symptom: start a goal in the desktop app, then type
/goal status— it answers "No active goal" for a goal that is live.Root cause:
/goalstate is persisted per-session in SessionDB (state_metakeygoal:<session_id>), so the slash and submit pipelines must agree on which session id they mean. They didn't.slash.ts'sensureSessionIdresolved with a barehint || activeRef || createBackendSessionForSend(), so whenever the runtime binding was momentarily absent — profile swap, reconnect, orphan-reap, request timeout — it minted a new session and ran the command there.submit.tsalready handles that case correctly by resuming the routed stored session on its owning profile (#55578, #67603).This is a whole-class fix, not a
/goalpatch: every exec/rpc slash command (/usage,/status,/tools,/agents, …) shared the hole.Changes
resolve-target-session.ts(new): one shared resolution ladder, per the "one resolver owns each policy" rule inapps/desktop/AGENTS.md.session.resumeon the routed (else selected) stored session, re-registered on the profile that owns itslash.ts:ensureSessionIddelegates to the shared resolver; threadsgetRoutedStoredSessionId+getRuntimeIdForStoredSession.index.ts: passes the two new deps through.nullrather than forking — reporting that a command could not run beats running it against the wrong session.Validation
/goal statuswith runtime binding absentslash.execonbrand-new-session→ "No active goal"session.resume→slash.execon the routed sessiontsc --noEmiteslint10 new regression tests (8 resolver-level, 2 at the
/goallevel reproducing the reported symptom).Sabotage-verified — the tests were re-run with the resolver body reverted to the old
hint || activeRef || createSession()ladder to prove they actually catch the bug rather than passing vacuously: 6 of 10 fail, including both/goal-level tests. Restored and re-verified green afterward.Notes
activeSessionIdRef.currentover the stale prop) is already onmainatsubmit.ts:180— that fixed the submit side of [Bug]: Desktop submit fails after /goal; local session row created but message never reaches backend #63352. This fixes the slash side, which was the remaining half./goal; local session row created but message never reaches backend") — same forked-session seam, seen from the submit direction. Worth confirming before closing it./goalcommand.dispatchhandler intui_gateway/server.pydoes not bindsession["profile_home"], while the turn thread does. Latent divergence for app-global remote mode; goals land in the launchstate.dbeither way today, so it is not this symptom and is left alone here.