mirror of
https://github.com/stablyai/orca.git
synced 2026-10-01 00:02:10 +00:00
* Prevent deleted workspace browser snapshot resurrection * fix: tear down folder workspace browser tabs * fix: fence pre-publication browser snapshots * fix: route folder deletion through runtime cleanup * chore: retrigger CI * fix: sweep folder PTYs on runtime deletion * fix: restore deletion fences after runtime refactor * test: cover deleted renderer snapshot after recreation * fix: avoid publishing ambiguous worktree snapshots * fix: preserve optional worktree index state * fix: fence paired PTYs on worktree removal * fix: harden deletion fence and folder-delete teardown - Folder-group delete no longer fails on a mixed-host group: an ambiguous connection skips the PTY sweep instead of rejecting the delete. - Share one folder-workspace PTY teardown helper between the runtime removal path and the project-group controller. - Simplify the mobile snapshot fence: identity-carrying frames are judged against the live catalog instanceId and clear the fence once the successor is accepted; identity-less frames are fenced by renderer generation. Drops the unbounded epoch bookkeeping. - A fenced frame no longer triggers a resync request on every sync while the renderer still lists it as unchanged. - Cross-host id collisions publish without an instanceId rather than blanking the mobile session for that workspace. - Folder delete IPC always routes through the runtime; the store-only fallback and double notify are gone. - Drop the redundant rescue-path tombstone check; ownership is purged at removal. - Fence tests drive removeWorktreeMetadataAndHistory + syncWindowGraph instead of seeding the fence map, and add accept-after-recreate, no-resync, and ambiguous-host folder delete cases.
65 lines
2.4 KiB
TypeScript
65 lines
2.4 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 controller = new RuntimeProjectGroupController({
|
|
getStore: () => ({ getFolderWorkspaces: () => [workspace], removeFolderWorkspace }) as never,
|
|
resolveRepo: async () => {
|
|
throw new Error('unused')
|
|
},
|
|
notifyReposChanged,
|
|
resolveFolderConnectionId,
|
|
teardownFolderWorkspacePtys,
|
|
cleanupRemovedFolderWorkspaceState
|
|
})
|
|
return {
|
|
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)
|
|
})
|
|
|
|
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')
|
|
warn.mockRestore()
|
|
})
|
|
})
|