Files
orca/src/main/runtime/runtime-project-group-controller-folder-delete.test.ts
T
Jinwoo Hong 4b65d95964 feat(connectors): connector follow-ups, held during approvals, behind the off-by-default experimentalConnectors flag (B2b-2) (#31806)
* feat(connectors): connector seam lifecycle, conversation links and start behind experimentalConnectors (B2b-1)

* feat(connectors): connector follow-ups, held while the agent asks, behind experimentalConnectors (B2b-2)

* feat(agent-write): opt-in launch cancel, approval wait and binding fence on the shared writer

executeAgentLaunch takes an optional signal; sendTerminalAgentPrompt (and
sendAgentTurn) take optional onPermission: 'wait' and expectedBinding. No
existing caller sets them, so every current path is unchanged.

* fix(agent-write): keep the default writer path main's; fence cancel and real submit boundary

Only opted-in writes take the submit layer, so default timing and the leaf
re-read are unchanged. Cancellation is rechecked before a structured-refusal
terminal fallback, and an opted-in launch learns Enter from an onSubmitWritten
callback at the write itself, OMP's combined frame included.

* fix(connectors): pass the seam's signal to the launch, read links from each host's rows, and keep delivery ids on orchestration's durable receipts (B2b-1)

* fix(agent-launch): a cancel after a failed startup spawn recovers the created workspace

* fix(connectors): keep an unknown receipt once the launch published, and restore local-only metadata ownership (B2b-1)

* fix(connectors): settle a lane when its process is lost; removal stays host-qualified; folder delete announces removal

* fix(plugins): keep folder removals out of public worktree events

* fix(connectors): a launch admits its process for the lane, so queued sends never adopt a successor

* fix(connectors): classify connector RPCs as host-owned; CLI start output claims a start only when definite
2026-10-22 17:58:29 -04:00

76 lines
2.8 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import { RuntimeProjectGroupController } from './runtime-project-group-controller'
import type { FolderWorkspace } from '../../shared/folder-workspace-types'
const workspace = {
id: 'ws-1',
projectGroupId: 'group-1',
folderPath: '/tmp/ws'
} as FolderWorkspace
function createController(
resolveFolderConnectionId: (workspace: FolderWorkspace) => string | null
) {
const removeFolderWorkspace = vi.fn(() => true)
const teardownFolderWorkspacePtys = vi.fn(async () => undefined)
const cleanupRemovedFolderWorkspaceState = vi.fn()
const notifyReposChanged = vi.fn()
const emitWorktreeLifecycle = vi.fn()
const controller = new RuntimeProjectGroupController({
getStore: () => ({ getFolderWorkspaces: () => [workspace], removeFolderWorkspace }) as never,
resolveRepo: async () => {
throw new Error('unused')
},
notifyReposChanged,
resolveFolderConnectionId,
teardownFolderWorkspacePtys,
cleanupRemovedFolderWorkspaceState,
emitWorktreeLifecycle
})
return {
emitWorktreeLifecycle,
controller,
removeFolderWorkspace,
teardownFolderWorkspacePtys,
cleanupRemovedFolderWorkspaceState,
notifyReposChanged
}
}
describe('RuntimeProjectGroupController.deleteFolderWorkspace', () => {
it('tears down PTYs and runtime state before removing the catalog row', async () => {
const deps = createController(() => 'ssh-1')
await expect(deps.controller.deleteFolderWorkspace('ws-1')).resolves.toEqual({ deleted: true })
expect(deps.teardownFolderWorkspacePtys).toHaveBeenCalledWith('folder:ws-1', 'ssh-1')
expect(deps.cleanupRemovedFolderWorkspaceState).toHaveBeenCalledWith('folder:ws-1')
expect(deps.teardownFolderWorkspacePtys.mock.invocationCallOrder[0]).toBeLessThan(
deps.removeFolderWorkspace.mock.invocationCallOrder[0]!
)
expect(deps.notifyReposChanged).toHaveBeenCalledTimes(1)
expect(deps.emitWorktreeLifecycle).toHaveBeenCalledWith({
kind: 'removed',
worktreeId: 'folder:ws-1',
path: '/tmp/ws'
})
})
it('still deletes when the folder host is ambiguous, skipping only the PTY sweep', async () => {
const warn = vi.spyOn(console, 'warn').mockImplementation(() => undefined)
const deps = createController(() => {
throw new Error('folder_workspace_connection_ambiguous')
})
await expect(deps.controller.deleteFolderWorkspace('ws-1')).resolves.toEqual({ deleted: true })
expect(deps.teardownFolderWorkspacePtys).not.toHaveBeenCalled()
expect(deps.cleanupRemovedFolderWorkspaceState).toHaveBeenCalledWith('folder:ws-1')
expect(deps.removeFolderWorkspace).toHaveBeenCalledWith('ws-1')
expect(deps.emitWorktreeLifecycle).toHaveBeenCalledWith(
expect.objectContaining({ kind: 'removed', worktreeId: 'folder:ws-1' })
)
warn.mockRestore()
})
})