test(session): guard against workspace-reopen tab fork-bomb (STA-1111) (#10057)

* test(session): guard against workspace-reopen tab fork-bomb (STA-1111)

Relates to STA-1111 (already fixed on main by #6945).

The runaway-tab-on-reopen bug was fixed by #6945 (activeOrQueuedResumeClaimsProviderSession dedup guard) hours before the ticket was filed. Verified: disabling that guard makes tab count climb 1->2->3->4 across reopens; restoring it holds at 1. This adds a revert-sensitive regression test covering the created-agent and sleeping-resume reopen paths so it cannot regress.

Test plan: 2 new tests pass; fail if the #6945 guard is removed.

* test(session): isolate automatic resume replay coverage

* test(session): assert resumed tab identity stays stable
This commit is contained in:
Brennan Benson 2026-07-24 00:36:50 -07:00 committed by GitHub
parent 1b5db4bc2a
commit ec04827b37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 101 additions and 0 deletions

View File

@ -0,0 +1,101 @@
import path from 'node:path'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { useAppStore, type AppState } from '@/store'
import { activateAndRevealWorktree } from './worktree-activation'
import { makeCreatedAgentWorktree as makeWorktree } from '@/lib/worktree-activation-created-agent-test-state'
const initialAppStoreState = useAppStore.getState()
function baseState(worktree: ReturnType<typeof makeWorktree>): Partial<AppState> {
return {
repos: [
{
id: 'repo-1',
path: path.join(path.sep, 'workspace', 'repo'),
displayName: 'repo',
badgeColor: '#000000',
addedAt: 0
}
],
worktreesByRepo: { 'repo-1': [worktree] },
activeRepoId: 'repo-1',
activeView: 'terminal',
tabsByWorktree: {},
unifiedTabsByWorktree: {},
groupsByWorktree: {},
layoutByWorktree: {},
activeGroupIdByWorktree: {},
openFiles: [],
browserTabsByWorktree: {},
activeFileIdByWorktree: {},
activeBrowserTabIdByWorktree: {},
activeTabTypeByWorktree: {},
activeTabIdByWorktree: {},
tabBarOrderByWorktree: {},
pendingStartupByTabId: {},
automaticAgentResumeClaimsByTabId: {},
agentStatusByPaneKey: {},
sleepingAgentSessionsByPaneKey: {},
settings: {
agentCmdOverrides: {},
setupScriptLaunchMode: 'new-tab'
} as unknown as ReturnType<typeof useAppStore.getState>['settings'],
markWorktreeVisited: vi.fn(),
recordWorktreeVisit: vi.fn(),
refreshGitHubForWorktreeIfStale: vi.fn(),
revealWorktreeInSidebar: vi.fn()
}
}
afterEach(() => {
useAppStore.setState(initialAppStoreState, true)
})
describe('STA-1111 worktree reopen does not fork-bomb tabs', () => {
it('re-captured sleeping codex session resumes once, not once per reopen', () => {
const worktree = { ...makeWorktree(), createdWithAgent: undefined }
useAppStore.setState(baseState(worktree))
const providerSession = { key: 'session_id' as const, id: 'codex-session-1' }
let resumedTabId: string | undefined
for (let reopen = 0; reopen < 4; reopen++) {
const paneKey = `slept-pane-${reopen}:0`
useAppStore.setState((s) => ({
sleepingAgentSessionsByPaneKey: {
...s.sleepingAgentSessionsByPaneKey,
[paneKey]: {
paneKey,
tabId: `slept-pane-${reopen}`,
worktreeId: worktree.id,
agent: 'codex',
providerSession,
prompt: 'resume prior task',
state: 'working',
origin: 'live',
capturedAt: 1000 + reopen,
updatedAt: 1000 + reopen,
terminalTitle: 'Codex'
}
}
}))
activateAndRevealWorktree(worktree.id)
const state = useAppStore.getState()
const tabs = state.tabsByWorktree[worktree.id] ?? []
expect(tabs).toHaveLength(1)
resumedTabId ??= tabs[0]!.id
expect(tabs[0]!.id).toBe(resumedTabId)
expect(state.automaticAgentResumeClaimsByTabId[tabs[0]!.id]?.providerSession).toEqual(
providerSession
)
expect(state.sleepingAgentSessionsByPaneKey[paneKey]).toBeUndefined()
if (reopen === 0) {
expect(state.consumeTabStartupCommand(tabs[0]!.id)?.resumeProviderSession).toEqual(
providerSession
)
}
}
})
})