diff --git a/src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.test.ts b/src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.test.ts index b020d51a852..52837e9aa61 100644 --- a/src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.test.ts +++ b/src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.test.ts @@ -95,6 +95,22 @@ describe('selectRetentionForceParkedTerminalWorktrees', () => { ) }) + it('does not let empty retained topology bypass the pane budget', () => { + const worktrees = [ + retentionCandidate('wt-empty-topology', nowMs - TERMINAL_WORKTREE_PARK_DELAY_MS, { + retainedPaneCount: 0 + }) + ] + + expect( + selectRetentionForceParkedTerminalWorktrees({ + ...base, + worktrees, + retentionLimit: 0 + }) + ).toEqual(new Set(['wt-empty-topology'])) + }) + it('spends the budget on the newest weighted worktrees first', () => { const worktrees = [ retentionCandidate('wt-old-small', nowMs - TERMINAL_WORKTREE_PARK_DELAY_MS - 2, { @@ -261,6 +277,13 @@ describe('terminal hidden pane retention weight', () => { expect(getTerminalHiddenPaneRetentionWeight(2, 50_000)).toBe(20) }) + it('charges one pane when retained topology is empty or invalid', () => { + expect(getTerminalHiddenPaneRetentionWeight(0, 5_000)).toBe(1) + expect(getTerminalHiddenPaneRetentionWeight(-1, 5_000)).toBe(1) + expect(getTerminalHiddenPaneRetentionWeight(0.5, 5_000)).toBe(1) + expect(getTerminalHiddenPaneRetentionWeight(Number.NaN, 5_000)).toBe(1) + }) + it('reuses pane counts across unrelated store writes and buffer-only layout changes', () => { const root = { type: 'leaf' as const, leafId: 'leaf-1' } const terminalLayoutsByTabId = { diff --git a/src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.ts b/src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.ts index 1b2c4ebaa0b..2f0ca39d946 100644 --- a/src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.ts +++ b/src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.ts @@ -70,8 +70,9 @@ export function getTerminalHiddenPaneRetentionWeight( retainedPaneCount: number, scrollbackRows: unknown ): number { - const paneCount = - Number.isFinite(retainedPaneCount) && retainedPaneCount > 0 ? Math.floor(retainedPaneCount) : 0 + const paneCount = Number.isFinite(retainedPaneCount) + ? Math.max(1, Math.floor(retainedPaneCount)) + : 1 const rowWeight = Math.ceil( normalizeDesktopTerminalScrollbackRows(scrollbackRows) / DESKTOP_TERMINAL_SCROLLBACK_ROWS_DEFAULT