From 0dfc3e39b95bf47522a1ae33782d668bf71c583e Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Wed, 30 Sep 2026 11:13:03 -0500 Subject: [PATCH] fix(bots): keep the Bot Chat stale-tile probe discard-only so background refreshes never take focus --- .../hermes-bots/canonical-chat-stale-tiles.test.ts | 12 +++++++++++- .../src/plugins/hermes-bots/canonical-chat.ts | 6 ++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/desktop/src/plugins/hermes-bots/canonical-chat-stale-tiles.test.ts b/apps/desktop/src/plugins/hermes-bots/canonical-chat-stale-tiles.test.ts index e426f3c0ee..3753a8b1a9 100644 --- a/apps/desktop/src/plugins/hermes-bots/canonical-chat-stale-tiles.test.ts +++ b/apps/desktop/src/plugins/hermes-bots/canonical-chat-stale-tiles.test.ts @@ -68,7 +68,7 @@ describe('120810: compressed Bot Chat discards the stale tile', () => { expect(focusMock).toHaveBeenCalledTimes(1) const [ownerKey, probe, onlyIds] = focusMock.mock.calls[0] expect(ownerKey).toBe('bot:ops') - expect(onlyIds).toEqual(expect.arrayContaining(['root-1', 'tip-9'])) + expect(onlyIds).toEqual([]) // Stale: Bot Chat-titled tile at an id that is neither registry nor tip. expect(probe({ storedSessionId: 'old-segment', workspaceTabTitle: 'Bot Chat' })).toBe(true) // Live tip and registry row are never stale. @@ -79,4 +79,14 @@ describe('120810: compressed Bot Chat discards the stale tile', () => { // Tip opens after the probe. expect(hostMock.openSession.mock.calls[0][0]).toBe('tip-9') }) + + it('a background refresh discards stale tiles without fronting the live one (#121874)', async () => { + const { openBotCanonicalChat } = await loadModule() + await openBotCanonicalChat('ops', { background: true }) + + expect(focusMock).toHaveBeenCalledTimes(1) + const [, probe, onlyIds] = focusMock.mock.calls[0] + expect(onlyIds).toEqual([]) + expect(probe({ storedSessionId: 'old-segment', workspaceTabTitle: 'Bot Chat' })).toBe(true) + }) }) diff --git a/apps/desktop/src/plugins/hermes-bots/canonical-chat.ts b/apps/desktop/src/plugins/hermes-bots/canonical-chat.ts index b40c94ccf0..33ecf3c1bc 100644 --- a/apps/desktop/src/plugins/hermes-bots/canonical-chat.ts +++ b/apps/desktop/src/plugins/hermes-bots/canonical-chat.ts @@ -157,9 +157,11 @@ async function openStoredBotChat( // Compression rotates the tip while tiles stay keyed by segment, and hidden // Bot Chats never reach the sidebar listing the lineage guard reads, so the // old-segment tile is discarded here or it survives beside the tip - // (hermes-agent#120810). Same owner-scoped probe the roster click runs. + // (hermes-agent#120810). Same owner-scoped probe the roster click runs, but + // discard-only (`[]` fronts nothing): a background refresh must never take + // the tab strip (#121874), and the openSession below fronts explicit opens. const canonicalIds = [...new Set([summary?.id, storedId].filter(Boolean).map(String))] - host.focusOpenWorkspaceSession?.(ownerKey, isStaleBotChatTile(canonicalIds), canonicalIds) + host.focusOpenWorkspaceSession?.(ownerKey, isStaleBotChatTile(canonicalIds), []) await host.openSession(storedId, { ...(route