fix(desktop): /goal kickoff queues when busy instead of vanishing - #71632
Merged
Conversation
…sh header stops echoing long args
Four symptoms from the same /goal flow on desktop:
- Typing '/goal <text>' sealed the command into a directive chip on
Space because /goal was registered without args:true, so the goal
prose rendered awkwardly after a pill. The registry row now matches
/personality and /tools: the arg stays editable text.
- The slash status header echoed the ENTIRE invocation ('slash:/goal
<whole goal prose>') in mono, immediately above the backend notice
that repeats the goal text again, and the kickoff user bubble that
repeats it a third time. The header now carries just the command
token (slash:/goal).
- When the session was busy, handleDispatch rendered 'session busy'
and dropped the dispatch message. For /goal that message is the
kickoff prompt, and the backend has ALREADY set the goal by then —
the goal existed but the agent never heard about it, and later turns
looked goal-unaware (#63352). The busy path now queues the kickoff
on the composer queue: it sends on settle and is visible/editable in
the queue panel meanwhile. Falls back to the old message if the
queue rejects the entry.
- A slash command issued on a fresh draft created the backend session
with no preview, so the sidebar row sat as 'Untitled session' —
and when the kickoff was dropped, auto-title never fired either
(it needs a completed user->assistant exchange). ensureSessionId now
seeds the preview with the typed command.
Tests: registry row contract, busy-path queueing (kickoff neither
sends mid-turn nor vanishes), and the header-token assertion.
Contributor
૮ >ﻌ< ა ci reviewran on a5f9c0b all good! |
13 tasks
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
Salvage of #68776 by @SHL0MS onto current
main. A/goal <text>issued while a turn is running no longer loses its kickoff prompt — it parks on the composer queue and sends when the turn settles.This closes the last of three independent failures in the same desktop
/goalflow. @SHL0MS diagnosed this one and correctly called it separate from the other two:activeSessionIdprop minting a second runtime sessionmain(#63376's payload)slash.ts/submit.tsresolving the target session differentlymain(#71605)busyRefis trueRoot cause: the backend sets the goal the moment
slash.execruns, and returns the kickoff as asenddirective.handleDispatchsawbusyRef.current, rendered "session busy — /interrupt the current turn", and returned without the message — so the goal existed inGoalManagerwhile the agent never heard about it, and follow-up turns looked goal-unaware. On a fresh chat it also stranded the row as "Untitled session", since auto-title needs a completed exchange that never happened.Changes (contributor)
slash.ts: the busy branch enqueues the kickoff on the composer queue instead of dropping it; the message reports a queue rather than demanding/interrupt.slash.ts: slash status header carries the command token only —/goal <prose>used to echo the whole invocation in the mono header and again in the backend notice directly under it.slash.ts: a slash on a fresh draft seeds the sidebar preview with the typed command, so the row doesn't sit as "Untitled session".desktop-slash-commands.ts:/goalgainsargs: trueso its prose arg stays editable instead of sealing into a directive chip./goalarg editability).Salvage notes (mine, on top)
main. The branch predated both fix(desktop): slash commands target the user's chat, not a new session #71605 and the/compress→actionmigration, soslash.tsanddesktop-slash-commands.test.tsconflicted. Resolved in favor ofmainplus the contributor's intent: the sharedresolveTargetSessionIdladder is preserved and now threads the contributor'spreviewargument through tocreateBackendSessionForSend.storedSessionIdresolved at invocation time over re-reading$sessionStates/$selectedStoredSessionIdin the busy branch. A session switch between dispatch and that branch would otherwise park the kickoff on whichever chat is now in front — the same cross-session leak class as [Desktop] Chat tab messages leak across sessions — cross-tab content mixing #59305. Falls back through the original globals for a session whose cache entry hasn't landed yet.Validation
tsc --noEmiteslintSabotage-verified — the busy branch was reverted to the old drop-and-return behavior and the suite re-run to prove the contributor's regression test isn't vacuous:
queues the /goal kickoff instead of dropping it when the session is busy (#63352)fails, alone, exactly as intended. Restored and re-verified green.Closes #63352.