test: remove 19 low-value cases and three suites (#34628)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
OrcaWin
2026-10-27 17:57:15 -07:00
committed by GitHub
co-authored by OrcaWin
parent 4d3451601a
commit 3b4ae900d3
11 changed files with 4 additions and 722 deletions
-3
View File
@@ -10467,7 +10467,6 @@
"src/renderer/src/lib/ai-vault-resume-shell.test.ts": 487,
"src/renderer/src/lib/ai-vault-resume-target.test.ts": 199,
"src/renderer/src/lib/ai-vault-session-drag.test.ts": 45,
"src/renderer/src/lib/ai-vault-session-fork-startup.test.ts": 315,
"src/renderer/src/lib/ai-vault-session-resume-preparation.test.ts": 135,
"src/renderer/src/lib/ai-vault-tab-title-sync-inputs.test.ts": 192,
"src/renderer/src/lib/ai-vault-tab-title-sync.test.ts": 803,
@@ -11039,7 +11038,6 @@
"src/renderer/src/lib/worktree-agent-live-surface-adoption-layout-owner.test.ts": 1430,
"src/renderer/src/lib/worktree-agent-structured-inventory.test.ts": 155,
"src/renderer/src/lib/worktree-attachment-label.test.ts": 34,
"src/renderer/src/lib/worktree-creation-agent-seeding.test.ts": 846,
"src/renderer/src/lib/worktree-creation-agent-seeds.test.ts": 1098,
"src/renderer/src/lib/worktree-creation-backend-startup-focus.test.ts": 1775,
"src/renderer/src/lib/worktree-creation-background-mount.test.ts": 2109,
@@ -11056,7 +11054,6 @@
"src/renderer/src/lib/worktree-creation-structured-session-host-decline.test.ts": 2373,
"src/renderer/src/lib/worktree-creation-structured-session.test.ts": 837,
"src/renderer/src/lib/worktree-default-display-name.test.ts": 48,
"src/renderer/src/lib/worktree-default-terminal-tabs-layout-owner.test.ts": 1147,
"src/renderer/src/lib/worktree-display-name-order.test.ts": 57,
"src/renderer/src/lib/worktree-host-connection-phase.test.ts": 1364,
"src/renderer/src/lib/worktree-initial-terminal-close-records.test.ts": 2576,
@@ -1,101 +0,0 @@
import { getDefaultSettings } from '../../../shared/constants'
import { TEST_REPO, makeWorktree } from '../store/slices/worktrees-slice-test-fixtures'
import { describe, expect, it, vi } from 'vitest'
import type { AppState } from '@/store/types'
import { buildAiVaultForkStartupForWorktree } from './ai-vault-session-fork-startup'
vi.mock('@/lib/new-workspace', () => ({
CLIENT_PLATFORM: 'darwin'
}))
type ForkState = Pick<
AppState,
| 'activeRepoId'
| 'activeWorktreeId'
| 'folderWorkspaces'
| 'projectGroups'
| 'endpointProjects'
| 'endpointProjectHostSetups'
| 'repos'
| 'settings'
| 'worktreesByRepo'
>
function makeState(): ForkState {
return {
activeRepoId: 'repo-1',
activeWorktreeId: 'repo-1::worktree-1',
folderWorkspaces: [],
projectGroups: [],
repos: [{ ...TEST_REPO, id: 'repo-1', path: '/Users/ada/repo' }],
endpointProjects: [
{
id: 'repo-1',
displayName: 'repo',
badgeColor: '',
sourceRepoIds: ['repo-1'],
createdAt: 0,
updatedAt: 0
}
],
endpointProjectHostSetups: [],
settings: {
...getDefaultSettings('/tmp'),
agentPermissionDefault: 'own',
agentDefaultArgs: { claude: '', codex: '' },
agentDefaultEnv: { claude: {}, codex: {} }
},
worktreesByRepo: {
'repo-1': [
makeWorktree({ id: 'repo-1::worktree-1', repoId: 'repo-1', path: '/Users/ada/repo' })
]
}
}
}
const SESSION_ID = '019fd532-7c11-7a90-b6de-4e1a2c3d5f60'
describe('AI Vault fork into the CLI', () => {
it('forks Claude in the recorded folder without claiming the chat-owned session', () => {
const startup = buildAiVaultForkStartupForWorktree({
state: makeState(),
worktreeId: 'repo-1::worktree-1',
session: { agent: 'claude', sessionId: SESSION_ID, cwd: '/Users/ada/repo', codexHome: null }
})
expect(startup).toMatchObject({
command: `claude '--resume' '${SESSION_ID}' '--fork-session'`,
cwd: '/Users/ada/repo'
})
// A cold restore of the tab must never re-enter the conversation the chat still owns.
expect(startup).not.toHaveProperty('providerSession')
})
it('forks Codex under the home the transcript was found in', () => {
const startup = buildAiVaultForkStartupForWorktree({
state: makeState(),
worktreeId: 'repo-1::worktree-1',
session: {
agent: 'codex',
sessionId: SESSION_ID,
cwd: '/Users/ada/repo',
codexHome: '/Users/ada/.orca/codex-accounts/a1/home'
}
})
expect(startup?.command).toBe(
`CODEX_HOME='/Users/ada/.orca/codex-accounts/a1/home' codex '-c' 'tui.resume_cwd=current' 'fork' '${SESSION_ID}'`
)
expect(startup).not.toHaveProperty('providerSession')
})
it('returns null for an agent that cannot fork instead of a plain resume', () => {
expect(
buildAiVaultForkStartupForWorktree({
state: makeState(),
worktreeId: 'repo-1::worktree-1',
session: { agent: 'gemini', sessionId: SESSION_ID, cwd: '/Users/ada/repo', codexHome: null }
})
).toBeNull()
})
})
@@ -23,75 +23,6 @@ describe('resolveGitHubPrStartPointForRepo', () => {
})
})
it('resolves local PR heads through worktree IPC with PR branch hints', async () => {
vi.mocked(window.api.worktrees.resolvePrBase).mockResolvedValue({
baseBranch: 'abc123',
compareBaseRef: 'refs/remotes/origin/main',
branchNameOverride: 'feature/fix',
pushTarget: { remoteName: 'origin', branchName: 'feature/fix' }
})
await expect(
resolveGitHubPrStartPointForRepo({
repoId: 'repo-1',
prNumber: 42,
target: { kind: 'local' as const },
headRefName: 'feature/fix',
baseRefName: 'main',
isCrossRepository: false
})
).resolves.toMatchObject({
baseBranch: 'abc123',
branchNameOverride: 'feature/fix'
})
expect(window.api.worktrees.resolvePrBase).toHaveBeenCalledWith({
repoId: 'repo-1',
prNumber: 42,
headRefName: 'feature/fix',
baseRefName: 'main',
isCrossRepository: false
})
expect(callRuntimeRpc).not.toHaveBeenCalled()
})
it('routes runtime-owned PR head resolution through runtime RPC', async () => {
vi.mocked(callRuntimeRpc).mockResolvedValue({
baseBranch: 'def456',
compareBaseRef: 'refs/remotes/origin/develop',
branchNameOverride: 'feature/runtime',
pushTarget: { remoteName: 'fork', branchName: 'feature/runtime' }
})
await expect(
resolveGitHubPrStartPointForRepo({
repoId: 'repo-runtime',
prNumber: 7,
target: { kind: 'environment' as const, environmentId: 'env-1' },
headRefName: 'feature/runtime',
baseRefName: 'develop',
isCrossRepository: true
})
).resolves.toMatchObject({
baseBranch: 'def456',
branchNameOverride: 'feature/runtime'
})
expect(callRuntimeRpc).toHaveBeenCalledWith(
{ kind: 'environment', environmentId: 'env-1' },
'worktree.resolvePrBase',
{
repo: 'repo-runtime',
prNumber: 7,
headRefName: 'feature/runtime',
baseRefName: 'develop',
isCrossRepository: true
},
{ timeoutMs: 30_000 }
)
expect(window.api.worktrees.resolvePrBase).not.toHaveBeenCalled()
})
it('throws resolver errors so submit can abort before creating from the wrong base', async () => {
vi.mocked(window.api.worktrees.resolvePrBase).mockResolvedValue({
error: 'Could not resolve PR head.'
@@ -41,28 +41,6 @@ describe('beginDirectWorkItemStructuredLaunch', () => {
})
})
it('opens the provisional chat synchronously and preserves the requested tab id', () => {
const order: string[] = []
mocks.beginStructuredAgentSessionProvisionalLaunch.mockImplementation((args) => {
order.push('begin')
args.beforeOpen('session-1')
order.push('open')
return { sessionId: 'session-1', tab: { id: 'agent-session:session-1' } }
})
expect(
beginDirectWorkItemStructuredLaunch({
plan: structuredPlan,
primaryTabId: null,
beforeOpen: (sessionId) => {
order.push(`reveal:${sessionId}`)
return true
}
})
).toEqual({ completed: true, structuredLaunch: true, primaryTabId: 'agent-session:session-1' })
expect(order).toEqual(['begin', 'reveal:session-1', 'open'])
})
it('does not claim completion when the provisional opener is refused', () => {
mocks.beginStructuredAgentSessionProvisionalLaunch.mockReturnValue(null)
@@ -74,20 +52,6 @@ describe('beginDirectWorkItemStructuredLaunch', () => {
})
).toEqual({ completed: false, structuredLaunch: true, primaryTabId: 'setup-shell-tab' })
})
it('skips structured opening for non-structured routes', () => {
expect(
beginDirectWorkItemStructuredLaunch({
plan: adoptAgentSessionLaunchVerdict({
...structuredPlan,
route: 'terminal-tui'
}),
primaryTabId: null,
beforeOpen: vi.fn()
})
).toEqual({ completed: false, structuredLaunch: false, primaryTabId: null })
expect(mocks.beginStructuredAgentSessionProvisionalLaunch).not.toHaveBeenCalled()
})
})
// Why (#29599): a paired server's new workspace picks from that workspace's agents on the server.
@@ -1,85 +0,0 @@
/**
* What the deleted `resolveRuntimeOwnerForWorktree` answered over the owner matrix (main @
* 37c314bcc960), so its replacements can list every deliberate difference.
*/
export const LEGACY_RUNTIME_OWNER_GOLDEN: Readonly<Record<string, string | null>> = {
'focused | null': null,
'focused | global-floating-terminal': null,
'focused | local-repo::wt': null,
'focused | legacy-repo::wt': null,
'focused | runtime-repo::wt': 'owner-env',
'focused | ssh-repo::wt': null,
'focused | hub-repo::wt': 'hub-env',
'focused | twin-repo::wt': 'ambiguous',
'focused | repo-twin-only::wt': 'ambiguous',
'focused | stale-hub-repo::wt': null,
'focused | rival-repo::wt': 'ambiguous',
'focused | conflict-repo::wt': 'ambiguous',
'focused | projected-twin::wt': 'ambiguous',
'focused | detected-repo::wt': 'owner-env',
'focused | unknown-repo::wt': null,
'focused | folder:local-folder': null,
'focused | folder:runtime-folder': 'owner-env',
'focused | folder:ssh-folder': null,
'focused | folder:twin-folder': null,
'focused | folder:group-twin-folder': null,
'focused | folder:unstamped-folder': null,
'focused | folder:restored-folder': 'owner-env',
'focused | folder:missing-folder': null,
'no focus | null': null,
'no focus | global-floating-terminal': null,
'no focus | local-repo::wt': null,
'no focus | legacy-repo::wt': null,
'no focus | runtime-repo::wt': 'owner-env',
'no focus | ssh-repo::wt': null,
'no focus | hub-repo::wt': 'hub-env',
'no focus | twin-repo::wt': 'ambiguous',
'no focus | repo-twin-only::wt': 'ambiguous',
'no focus | stale-hub-repo::wt': null,
'no focus | rival-repo::wt': 'ambiguous',
'no focus | conflict-repo::wt': 'ambiguous',
'no focus | projected-twin::wt': 'ambiguous',
'no focus | detected-repo::wt': 'owner-env',
'no focus | unknown-repo::wt': null,
'no focus | folder:local-folder': null,
'no focus | folder:runtime-folder': 'owner-env',
'no focus | folder:ssh-folder': null,
'no focus | folder:twin-folder': null,
'no focus | folder:group-twin-folder': null,
'no focus | folder:unstamped-folder': null,
'no focus | folder:restored-folder': 'owner-env',
'no focus | folder:missing-folder': null,
'single focus | null': null,
'single focus | global-floating-terminal': null,
'single focus | local-repo::wt': null,
'single focus | legacy-repo::wt': 'focused-env',
'single focus | runtime-repo::wt': 'owner-env',
'single focus | ssh-repo::wt': null,
'single focus | hub-repo::wt': 'hub-env',
'single focus | twin-repo::wt': 'ambiguous',
'single focus | repo-twin-only::wt': 'ambiguous',
'single focus | stale-hub-repo::wt': null,
'single focus | rival-repo::wt': 'ambiguous',
'single focus | conflict-repo::wt': 'ambiguous',
'single focus | projected-twin::wt': 'ambiguous',
'single focus | detected-repo::wt': 'owner-env',
'single focus | unknown-repo::wt': null,
'single focus | folder:local-folder': null,
'single focus | folder:runtime-folder': 'owner-env',
'single focus | folder:ssh-folder': null,
'single focus | folder:twin-folder': 'focused-env',
'single focus | folder:group-twin-folder': 'focused-env',
'single focus | folder:unstamped-folder': 'focused-env',
'single focus | folder:restored-folder': 'owner-env',
'single focus | folder:missing-folder': 'focused-env',
'active local | twin-repo::wt': null,
'active ssh:box | twin-repo::wt': null,
'active local | rival-repo::wt': null,
'active ssh:box | rival-repo::wt': null,
'active local | conflict-repo::wt': null,
'active ssh:box | conflict-repo::wt': 'hub-a',
'active local | folder:twin-folder': null,
'active ssh:box | folder:twin-folder': null,
'active local | folder:group-twin-folder': null,
'active ssh:box | folder:group-twin-folder': null
}
@@ -1,9 +1,6 @@
import type { ILink, ILinkProvider, Terminal } from '@xterm/xterm'
import type { ILink, ILinkProvider } from '@xterm/xterm'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import {
guardLinkProvider,
installGuardedLinkProviderRegistration
} from './terminal-link-provider-guard'
import { guardLinkProvider } from './terminal-link-provider-guard'
const mocks = vi.hoisted(() => ({
recordRendererCrashBreadcrumb: vi.fn()
@@ -51,17 +48,6 @@ describe('guardLinkProvider', () => {
)
})
it('passes provided links through unchanged when the provider succeeds', () => {
const links = [{ text: 'term_abc' }] as unknown as ILink[]
const provider: ILinkProvider = {
provideLinks: (_lineNumber, callback) => callback(links)
}
const guarded = guardLinkProvider(provider, 'orca-handle')
expect(collectLinks(guarded)).toBe(links)
expect(mocks.recordRendererCrashBreadcrumb).not.toHaveBeenCalled()
})
it('does not double-invoke the callback when the provider throws after resolving', () => {
const links = [{ text: 'file.ts' }] as unknown as ILink[]
const provider: ILinkProvider = {
@@ -79,31 +65,3 @@ describe('guardLinkProvider', () => {
expect(mocks.recordRendererCrashBreadcrumb).toHaveBeenCalledOnce()
})
})
describe('installGuardedLinkProviderRegistration', () => {
it('guards every provider registered after install (addon-internal included)', () => {
const registered: ILinkProvider[] = []
const terminal = {
registerLinkProvider: (provider: ILinkProvider) => {
registered.push(provider)
return { dispose: vi.fn() }
}
} as unknown as Terminal
installGuardedLinkProviderRegistration(terminal)
terminal.registerLinkProvider({
provideLinks: () => {
throw new RangeError('Invalid array length')
}
})
expect(registered).toHaveLength(1)
expect(() => collectLinks(registered[0])).not.toThrow()
expect(collectLinks(registered[0])).toBeUndefined()
expect(mocks.recordRendererCrashBreadcrumb).toHaveBeenCalledWith(
'terminal_link_provider_error',
expect.objectContaining({ provider: 'provider-1', errorName: 'RangeError' })
)
})
})
@@ -1,79 +0,0 @@
/** Hand-reviewed owner per matrix case for `resolveOwnerOrLocal` (round-3 design §5). */
export const OWNER_OR_LOCAL_ACCEPTANCE: Record<string, string> = {
'focused | global-floating-terminal': 'self@local',
'focused | local-repo::wt': 'self@local',
'focused | legacy-repo::wt': 'self@local',
'focused | runtime-repo::wt': 'env:owner-env@local',
'focused | ssh-repo::wt': 'self@ssh:box',
'focused | hub-repo::wt': 'env:hub-env@ssh:box',
'focused | twin-repo::wt': 'ambiguous',
'focused | repo-twin-only::wt': 'self@local',
'focused | stale-hub-repo::wt': 'env:hub-env@ssh:target',
'focused | rival-repo::wt': 'ambiguous',
'focused | conflict-repo::wt': 'ambiguous',
'focused | projected-twin::wt': 'ambiguous',
'focused | detected-repo::wt': 'env:owner-env@local',
'focused | unknown-repo::wt': 'self@local',
'focused | folder:local-folder': 'self@local',
'focused | folder:runtime-folder': 'env:owner-env@ssh:inner-ssh',
'focused | folder:ssh-folder': 'self@ssh:box',
'focused | folder:twin-folder': 'ambiguous',
'focused | folder:group-twin-folder': 'ambiguous',
'focused | folder:unstamped-folder': 'self@local',
'focused | folder:restored-folder': 'env:owner-env@local',
'focused | folder:missing-folder': 'self@local',
'no focus | global-floating-terminal': 'self@local',
'no focus | local-repo::wt': 'self@local',
'no focus | legacy-repo::wt': 'self@local',
'no focus | runtime-repo::wt': 'env:owner-env@local',
'no focus | ssh-repo::wt': 'self@ssh:box',
'no focus | hub-repo::wt': 'env:hub-env@ssh:box',
'no focus | twin-repo::wt': 'ambiguous',
'no focus | repo-twin-only::wt': 'self@local',
'no focus | stale-hub-repo::wt': 'env:hub-env@ssh:target',
'no focus | rival-repo::wt': 'ambiguous',
'no focus | conflict-repo::wt': 'ambiguous',
'no focus | projected-twin::wt': 'ambiguous',
'no focus | detected-repo::wt': 'env:owner-env@local',
'no focus | unknown-repo::wt': 'self@local',
'no focus | folder:local-folder': 'self@local',
'no focus | folder:runtime-folder': 'env:owner-env@ssh:inner-ssh',
'no focus | folder:ssh-folder': 'self@ssh:box',
'no focus | folder:twin-folder': 'ambiguous',
'no focus | folder:group-twin-folder': 'ambiguous',
'no focus | folder:unstamped-folder': 'self@local',
'no focus | folder:restored-folder': 'env:owner-env@local',
'no focus | folder:missing-folder': 'self@local',
'single focus | global-floating-terminal': 'self@local',
'single focus | local-repo::wt': 'self@local',
'single focus | legacy-repo::wt': 'self@local',
'single focus | runtime-repo::wt': 'env:owner-env@local',
'single focus | ssh-repo::wt': 'self@ssh:box',
'single focus | hub-repo::wt': 'env:hub-env@ssh:box',
'single focus | twin-repo::wt': 'ambiguous',
'single focus | repo-twin-only::wt': 'self@local',
'single focus | stale-hub-repo::wt': 'env:hub-env@ssh:target',
'single focus | rival-repo::wt': 'ambiguous',
'single focus | conflict-repo::wt': 'ambiguous',
'single focus | projected-twin::wt': 'ambiguous',
'single focus | detected-repo::wt': 'env:owner-env@local',
'single focus | unknown-repo::wt': 'self@local',
'single focus | folder:local-folder': 'self@local',
'single focus | folder:runtime-folder': 'env:owner-env@ssh:inner-ssh',
'single focus | folder:ssh-folder': 'self@ssh:box',
'single focus | folder:twin-folder': 'ambiguous',
'single focus | folder:group-twin-folder': 'ambiguous',
'single focus | folder:unstamped-folder': 'self@local',
'single focus | folder:restored-folder': 'env:owner-env@local',
'single focus | folder:missing-folder': 'self@local',
'active local | twin-repo::wt': 'self@local',
'active ssh:box | twin-repo::wt': 'self@ssh:box',
'active local | rival-repo::wt': 'self@local',
'active ssh:box | rival-repo::wt': 'ambiguous',
'active local | conflict-repo::wt': 'self@local',
'active ssh:box | conflict-repo::wt': 'ambiguous',
'active local | folder:twin-folder': 'self@local',
'active ssh:box | folder:twin-folder': 'self@ssh:box',
'active local | folder:group-twin-folder': 'self@local',
'active ssh:box | folder:group-twin-folder': 'self@ssh:box'
}
@@ -3,8 +3,7 @@ import type { ExecutionHostOwnerMatch } from '../../../shared/worktree-execution
import type { HostAuthority } from '../../../shared/host-authority'
import { resolveOwnerOrLocal } from './worktree-runtime-owner'
import { OWNER_RESOLUTION_CASES } from './runtime-owner-alias-matrix.test-fixture'
import { OWNER_OR_LOCAL_ACCEPTANCE } from './resolve-owner-acceptance.test-fixture'
import { LEGACY_RUNTIME_OWNER_GOLDEN } from './legacy-runtime-owner-answers.test-fixture'
import type { WorktreeRuntimeOwnerState } from './worktree-runtime-owner-state'
function describeMatch(match: ExecutionHostOwnerMatch<HostAuthority>): string {
@@ -15,55 +14,6 @@ function describeMatch(match: ExecutionHostOwnerMatch<HostAuthority>): string {
return `${endpoint.kind === 'self' ? 'self' : `env:${endpoint.environmentId}`}@${at}`
}
const casesWithIds = OWNER_RESOLUTION_CASES.flatMap((c) =>
c.worktreeId === null ? [] : [{ ...c, worktreeId: c.worktreeId }]
)
// Each deliberate change from the deprecated resolver, with the design's reason (§5).
const DELIBERATE_CHANGES: Record<string, string> = {
'twin-repo::wt': 'D77: a twin is never picked by default',
'projected-twin::wt': 'D77',
'folder:twin-folder': 'D77',
'folder:group-twin-folder': 'D77',
'rival-repo::wt': 'B: servers contest the SSH host',
'conflict-repo::wt': 'B',
'stale-hub-repo::wt': 'C: reached through the server whose repo row names the target',
'legacy-repo::wt': 'an unstamped row is local; the Active Server focus never claims it',
'folder:unstamped-folder': 'same',
'folder:missing-folder': 'same'
}
describe('resolveOwnerOrLocal acceptance (round-3 design §5)', () => {
it('pins the owner of every matrix case', () => {
const actual = Object.fromEntries(
casesWithIds.map((c) => [
c.name,
describeMatch(resolveOwnerOrLocal(c.state, { workspaceId: c.worktreeId }))
])
)
expect(actual).toEqual(OWNER_OR_LOCAL_ACCEPTANCE)
})
it('differs from the deprecated resolver only in the deliberate cases', () => {
const changed = casesWithIds.filter((c) => {
const owner = resolveOwnerOrLocal(c.state, { workspaceId: c.worktreeId })
const environmentId =
owner.kind === 'resolved' && owner.owner.endpoint.kind === 'environment'
? owner.owner.endpoint.environmentId
: null
const legacy = LEGACY_RUNTIME_OWNER_GOLDEN[c.name]
// Why: the deprecated environment-id reader collapsed `ambiguous` to `null`.
return owner.kind !== 'resolved' || environmentId !== (legacy === 'ambiguous' ? null : legacy)
})
for (const c of changed) {
expect(DELIBERATE_CHANGES[c.worktreeId], c.name).toBeDefined()
}
expect(new Set(changed.map((c) => c.worktreeId))).toEqual(
new Set(Object.keys(DELIBERATE_CHANGES))
)
})
})
describe('resolveOwnerOrLocal probes', () => {
const base = OWNER_RESOLUTION_CASES.find((c) => c.name === 'focused | stale-hub-repo::wt')!.state
const single = OWNER_RESOLUTION_CASES.find(
@@ -2,48 +2,10 @@ import { describe, expect, it } from 'vitest'
import { resolveTerminalHostOwnership, resolveTerminalPtyOwner } from './terminal-worktree-route'
import { resolveOwner } from './resolve-owner'
import { OWNER_RESOLUTION_CASES } from './runtime-owner-alias-matrix.test-fixture'
import { LEGACY_RUNTIME_OWNER_GOLDEN } from './legacy-runtime-owner-answers.test-fixture'
import type { WorktreeRuntimeOwnerState } from './worktree-runtime-owner-state'
const describeOwner = (owner: ReturnType<typeof resolveTerminalPtyOwner>) =>
owner.kind === 'runtime' ? owner.environmentId : owner.kind === 'ambiguous' ? 'ambiguous' : null
// Each deliberate change from the deleted resolver's teardown answer (round-3 design §3, §4, §7).
const DELIBERATE_CHANGES: Record<string, string | null> = {
// C: teardown follows spawn, which already starts these PTYs on the server.
'focused | stale-hub-repo::wt': 'hub-env',
'no focus | stale-hub-repo::wt': 'hub-env',
'single focus | stale-hub-repo::wt': 'hub-env',
// D77: a folder twin names no host; only each PTY's own `remote:<env>` id may.
'focused | folder:twin-folder': 'ambiguous',
'no focus | folder:twin-folder': 'ambiguous',
'single focus | folder:twin-folder': 'ambiguous',
'focused | folder:group-twin-folder': 'ambiguous',
'no focus | folder:group-twin-folder': 'ambiguous',
'single focus | folder:group-twin-folder': 'ambiguous',
// B: two servers contest the selected SSH host, so spawn refuses and teardown must too.
'active ssh:box | rival-repo::wt': 'ambiguous',
'active ssh:box | conflict-repo::wt': 'ambiguous',
// An unstamped row is this machine's; the Active Server focus never claims its PTYs.
'single focus | legacy-repo::wt': null,
'single focus | folder:unstamped-folder': null,
'single focus | folder:missing-folder': null
}
describe('resolveTerminalPtyOwner acceptance', () => {
it('answers as the deleted resolver did, except the deliberate cases', () => {
const actual = Object.fromEntries(
OWNER_RESOLUTION_CASES.map((c) => [
c.name,
describeOwner(resolveTerminalPtyOwner(c.state, c.worktreeId))
])
)
expect(actual).toEqual({ ...LEGACY_RUNTIME_OWNER_GOLDEN, ...DELIBERATE_CHANGES })
for (const name of Object.keys(DELIBERATE_CHANGES)) {
expect(LEGACY_RUNTIME_OWNER_GOLDEN[name], name).not.toBe(DELIBERATE_CHANGES[name])
}
})
it('keeps a setup terminal and a row-less worktree local under single focus', () => {
const single = OWNER_RESOLUTION_CASES.find((c) => c.name === 'single focus | legacy-repo::wt')!
expect(resolveTerminalPtyOwner(single.state, 'ephemeral-setup-terminal:skill-panel')).toEqual({
@@ -1,99 +0,0 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { WorktreeCreationRequest } from './pending-worktree-creation'
const mocks = vi.hoisted(() => ({
activateAndRevealWorktree: vi.fn(),
completeWorktreeCreation: vi.fn(),
ensureWorktreeHasInitialTerminal: vi.fn(),
ensureWebRuntimeWorktreeTerminalAfterWake: vi.fn()
}))
const store = {
activePendingCreationId: null as string | null,
activeView: 'tasks' as 'tasks' | 'terminal',
createWorktree: vi.fn(),
pendingWorktreeCreations: {} as Record<string, unknown>,
repos: []
}
vi.mock('@/store', () => ({ useAppStore: { getState: () => store } }))
vi.mock('@/lib/worktree-activation', () => ({
activateAndRevealWorktree: mocks.activateAndRevealWorktree
}))
vi.mock('@/lib/worktree-initial-terminal-seeding', () => ({
ensureWorktreeHasInitialTerminal: mocks.ensureWorktreeHasInitialTerminal
}))
vi.mock('@/lib/worktree-creation-completion', () => ({
completeWorktreeCreation: mocks.completeWorktreeCreation
}))
vi.mock('@/lib/web-runtime-worktree-terminal-after-wake', () => ({
ensureWebRuntimeWorktreeTerminalAfterWake: mocks.ensureWebRuntimeWorktreeTerminalAfterWake
}))
import { executeWorktreeCreation } from './worktree-creation-flow-execute'
const request: WorktreeCreationRequest = {
repoId: 'repo-1',
name: 'feature',
setupDecision: 'inherit',
agent: 'codex',
agentLaunchRoute: 'terminal-tui',
pendingFirstAgentMessageRename: false,
note: '',
startupPlan: null,
quickPrompt: '',
quickTelemetry: null
}
describe('executeWorktreeCreation agent seeding', () => {
beforeEach(() => {
vi.clearAllMocks()
store.activePendingCreationId = null
store.activeView = 'tasks'
store.pendingWorktreeCreations = { 'creation-1': { creationId: 'creation-1' } }
store.createWorktree.mockResolvedValue({
worktree: { id: 'worktree-1', repoId: request.repoId }
})
})
it('treats a background blank workspace as empty instead of waiting for the host', async () => {
await executeWorktreeCreation('creation-1', { ...request, agent: null })
expect(mocks.ensureWebRuntimeWorktreeTerminalAfterWake).toHaveBeenCalledWith('worktree-1', {
startup: undefined,
agent: null,
activate: false,
unknownHostCountIsEmpty: true
})
})
it('routes a background agent selection through host-aware surface creation', async () => {
await executeWorktreeCreation('creation-1', request)
expect(mocks.activateAndRevealWorktree).not.toHaveBeenCalled()
expect(mocks.ensureWorktreeHasInitialTerminal).not.toHaveBeenCalled()
expect(mocks.ensureWebRuntimeWorktreeTerminalAfterWake).toHaveBeenCalledOnce()
expect(mocks.ensureWebRuntimeWorktreeTerminalAfterWake).toHaveBeenCalledWith('worktree-1', {
startup: undefined,
agent: 'codex',
activate: false,
unknownHostCountIsEmpty: true
})
expect(mocks.completeWorktreeCreation).toHaveBeenCalledWith(
expect.objectContaining({ primaryTabId: null })
)
})
it('passes the agent selection through an active reveal', async () => {
store.activePendingCreationId = 'creation-1'
store.activeView = 'terminal'
mocks.activateAndRevealWorktree.mockReturnValue({ primaryTabId: null })
await executeWorktreeCreation('creation-1', request)
expect(mocks.activateAndRevealWorktree).toHaveBeenCalledWith(
'worktree-1',
expect.objectContaining({ agent: 'codex' })
)
})
})
@@ -1,116 +0,0 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { useAppStore, type AppState } from '@/store'
import { makeWorktree, seedStore } from '@/store/slices/store-test-helpers'
import { createStoreCascadesMockApi } from '@/store/slices/store-cascades-test-harness'
import { LayoutApplyParams } from '../../../shared/rpc-contract/workspace-layout-params'
import { applyDefaultTerminalTabs } from './worktree-default-terminal-tabs'
const mocks = vi.hoisted(() => ({
layoutOwnerIsMain: true,
callRuntimeRpc: vi.fn(async (_target: unknown, _method: string, _params: unknown) => ({
ok: true,
result: {}
}))
}))
vi.mock('../../../shared/layout-owner-switch', () => ({
get ORCA_LAYOUT_OWNER_IS_MAIN() {
return mocks.layoutOwnerIsMain
}
}))
vi.mock('@/runtime/runtime-rpc-client', () => ({ callRuntimeRpc: mocks.callRuntimeRpc }))
vi.mock('sonner', () => ({
toast: { info: vi.fn(), success: vi.fn(), error: vi.fn(), warning: vi.fn() }
}))
createStoreCascadesMockApi()
const WT = 'repo1::/path/wt1'
const NO_TEMPLATES = { runCommands: false, tabs: [] }
const store = useAppStore
let initialState: AppState
beforeEach(() => {
mocks.layoutOwnerIsMain = true
mocks.callRuntimeRpc.mockClear()
initialState = store.getState()
seedStore(store, {
worktreesByRepo: { repo1: [makeWorktree({ id: WT, repoId: 'repo1', path: '/path/wt1' })] },
activeWorktreeId: WT
})
})
afterEach(() => {
store.setState(initialState, true)
})
function applyNoTemplates(): string | null {
return applyDefaultTerminalTabs(
store.getState(),
WT,
undefined,
undefined,
undefined,
NO_TEMPLATES,
undefined,
undefined
)
}
function sentCommands() {
return mocks.callRuntimeRpc.mock.calls.map(([, method, params]) => {
expect(method).toBe('layout.apply')
return LayoutApplyParams.parse(params).command
})
}
describe('the default-tabs mark in a layout-owner build', () => {
it('records the mark in main when a workspace has no default tab templates', () => {
expect(applyNoTemplates()).toBeNull()
expect(store.getState().tabsByWorktree[WT]).toBeUndefined()
expect(sentCommands()).toEqual([{ type: 'setDefaultTabsApplied', workspace: WT }])
})
it('records the mark after the default tabs, so main never holds it without their rows', () => {
const tabId = applyDefaultTerminalTabs(
store.getState(),
WT,
undefined,
undefined,
undefined,
{ runCommands: false, tabs: [{ title: 'one' }, { title: 'two' }] },
undefined,
undefined
)
expect(tabId).not.toBeNull()
expect(sentCommands().map((command) => command.type)).toEqual([
'createTerminalTab',
'renameTab',
'createTerminalTab',
'renameTab',
'setDefaultTabsApplied'
])
})
it('records it once: a workspace already marked sends nothing', () => {
applyNoTemplates()
mocks.callRuntimeRpc.mockClear()
store.getState().markDefaultTerminalTabsApplied(WT)
applyNoTemplates()
expect(mocks.callRuntimeRpc).not.toHaveBeenCalled()
})
it('sends nothing with the switch off', () => {
mocks.layoutOwnerIsMain = false
applyNoTemplates()
expect(store.getState().defaultTerminalTabsAppliedByWorktreeId[WT]).toBe(true)
expect(mocks.callRuntimeRpc).not.toHaveBeenCalled()
})
})