Skip to content

fix(desktop): /goal kickoff queues when busy instead of vanishing - #71632

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-e8b91735
Jul 25, 2026
Merged

fix(desktop): /goal kickoff queues when busy instead of vanishing#71632
teknium1 merged 1 commit into
mainfrom
hermes/hermes-e8b91735

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Infographic

the goal kickoff survives

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 /goal flow. @SHL0MS diagnosed this one and correctly called it separate from the other two:

# Mechanism Status
1 stale activeSessionId prop minting a second runtime session on main (#63376's payload)
2 slash.ts / submit.ts resolving the target session differently on main (#71605)
3 kickoff dropped when busyRef is true this PR

Root cause: the backend sets the goal the moment slash.exec runs, and returns the kickoff as a send directive. handleDispatch saw busyRef.current, rendered "session busy — /interrupt the current turn", and returned without the message — so the goal existed in GoalManager while 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: /goal gains args: true so its prose arg stays editable instead of sealing into a directive chip.
  • 3 new tests (busy-queue regression for [Bug]: Desktop submit fails after /goal; local session row created but message never reaches backend #63352, header token, /goal arg editability).

Salvage notes (mine, on top)

  • Rebased onto current main. The branch predated both fix(desktop): slash commands target the user's chat, not a new session #71605 and the /compressaction migration, so slash.ts and desktop-slash-commands.test.ts conflicted. Resolved in favor of main plus the contributor's intent: the shared resolveTargetSessionId ladder is preserved and now threads the contributor's preview argument through to createBackendSessionForSend.
  • One correctness refinement: the queue key now prefers the storedSessionId resolved at invocation time over re-reading $sessionStates / $selectedStoredSessionId in 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

Result
Full desktop suite 2979 passed, 3 skipped, 0 failed
tsc --noEmit clean
eslint clean (1 pre-existing harness warning, untouched)
Contributor's 3 new tests pass

Sabotage-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.

…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.
@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on a5f9c0b

all good!

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Jul 25, 2026
@teknium1
teknium1 merged commit 6b26b40 into main Jul 25, 2026
36 checks passed
@teknium1
teknium1 deleted the hermes/hermes-e8b91735 branch July 25, 2026 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

[Bug]: Desktop submit fails after /goal; local session row created but message never reaches backend

3 participants