fix(hibernation): never hibernate floating-workspace terminals (#29790)

* fix(hibernation): never hibernate floating-workspace terminals

* docs(hibernation): clarify floating terminal idle policy

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
This commit is contained in:
Brennan Benson
2026-10-16 14:17:59 -07:00
committed by GitHub
co-authored by m4air
parent e0e2001701
commit f96c672a9e
2 changed files with 21 additions and 0 deletions
@@ -1,5 +1,6 @@
import { describe, expect, it } from 'vitest'
import type { AgentStatusEntry } from '../../../shared/agent-status-types'
import { FLOATING_TERMINAL_WORKTREE_ID } from '../../../shared/constants'
import type { TerminalLayoutSnapshot, TerminalTab } from '../../../shared/terminal-tab-types'
import {
DEFAULT_AGENT_HIBERNATION_IDLE_MS,
@@ -101,6 +102,21 @@ describe('agent sleep planner', () => {
expect(plannedWorktrees(snapshot({ foregroundTerminalTabIds: ['tab-1'] }))).toEqual([])
})
it('never plans automatic hibernation for a floating-workspace pane', () => {
expect(plannedWorktrees(snapshot())).toEqual(['wt-bg'])
const floating = entry({ worktreeId: FLOATING_TERMINAL_WORKTREE_ID })
expect(
plannedWorktrees(
snapshot({
tabsByWorktree: {
[FLOATING_TERMINAL_WORKTREE_ID]: [tab('tab-1', FLOATING_TERMINAL_WORKTREE_ID)]
},
agentStatusByPaneKey: { [floating.paneKey]: floating }
})
)
).toEqual([])
})
it('requires done resumable provider-session entries', () => {
for (const state of ['working', 'waiting', 'blocked'] as const) {
const e = entry({ state })
@@ -1,4 +1,5 @@
import type { AgentStatusEntry } from '../../../shared/agent-status-types'
import { FLOATING_TERMINAL_WORKTREE_ID } from '../../../shared/constants'
import type { TerminalTab } from '../../../shared/terminal-tab-types'
import {
getEligiblePane,
@@ -119,6 +120,10 @@ export function planAgentHibernationCandidates(
if (!worktreeId || tabs.length === 0) {
continue
}
// Floating terminals stay running when idle; the user must not need a hibernation resume.
if (worktreeId === FLOATING_TERMINAL_WORKTREE_ID) {
continue
}
if (
runtimeLivenessRequiredWorktreeIds.has(worktreeId) &&
!Object.hasOwn(snapshot.runtimeLivePtyIdsByWorktreeId ?? {}, worktreeId)