mirror of
https://github.com/stablyai/orca.git
synced 2026-10-22 08:03:37 +00:00
fix: fail closed on stale qualified removal owner
This commit is contained in:
@@ -13112,12 +13112,20 @@ describe('Store host-partitioned workspace sessions', () => {
|
||||
store.setWorkspaceSession(session, 'local')
|
||||
store.setWorkspaceSession(session, 'runtime:env-b')
|
||||
store.setWorktreeMeta(worktreeId, { hostId: 'local' })
|
||||
const worktreeLineage = makeWorktreeLineage({ worktreeId })
|
||||
const workspaceLineage = makeWorkspaceLineage({
|
||||
childWorkspaceKey: worktreeWorkspaceKey(worktreeId)
|
||||
})
|
||||
store.setWorktreeLineage(worktreeId, worktreeLineage)
|
||||
store.setWorkspaceLineage(workspaceLineage)
|
||||
|
||||
// The confirmed removal target is env-b. Bare metadata belongs to the same-id
|
||||
// local owner and must not redirect the post-delete purge back to local.
|
||||
store.removeWorktreeMeta(worktreeId, 'runtime:env-b')
|
||||
|
||||
expect(store.getWorktreeMeta(worktreeId)?.hostId).toBe('local')
|
||||
expect(store.getWorktreeLineage(worktreeId)).toEqual(worktreeLineage)
|
||||
expect(store.getWorkspaceLineage(workspaceLineage.childWorkspaceKey)).toEqual(workspaceLineage)
|
||||
expect(store.getWorkspaceSession('local').tabsByWorktree[worktreeId]).toHaveLength(1)
|
||||
expect(store.getWorkspaceSession('runtime:env-b').tabsByWorktree[worktreeId]).toBeUndefined()
|
||||
})
|
||||
|
||||
@@ -2392,6 +2392,33 @@ describe('OrcaRuntimeService', () => {
|
||||
expect(internals.mobileSessionTabsByWorktree.get(TEST_WORKTREE_ID)).toBe(localSession)
|
||||
})
|
||||
|
||||
it('rejects a qualified removal when only another host has persisted ownership', async () => {
|
||||
const runtimeStore = {
|
||||
...store,
|
||||
getWorktreeMeta: () => ({ ...store.getWorktreeMeta(TEST_WORKTREE_ID), hostId: 'local' })
|
||||
}
|
||||
const runtime = new OrcaRuntimeService(runtimeStore as never)
|
||||
const internals = runtime as unknown as {
|
||||
listResolvedWorktrees: () => Promise<unknown[]>
|
||||
resolveWorktreeRemovalTarget: (
|
||||
worktreeSelector: string,
|
||||
requiredHostId?: string
|
||||
) => Promise<unknown>
|
||||
}
|
||||
internals.listResolvedWorktrees = vi.fn().mockResolvedValue([
|
||||
{
|
||||
id: TEST_WORKTREE_ID,
|
||||
repoId: TEST_REPO_ID,
|
||||
path: TEST_WORKTREE_PATH,
|
||||
hostId: 'local'
|
||||
}
|
||||
])
|
||||
|
||||
await expect(
|
||||
internals.resolveWorktreeRemovalTarget(TEST_WORKTREE_ID, 'runtime:env-b')
|
||||
).rejects.toThrow('selector_not_found')
|
||||
})
|
||||
|
||||
it('claims the first window as authoritative and ignores later windows', () => {
|
||||
const runtime = createRuntime()
|
||||
|
||||
|
||||
@@ -24619,7 +24619,11 @@ export class OrcaRuntimeService {
|
||||
}
|
||||
const removalTarget = parseExactWorktreeIdSelector(worktreeSelector)
|
||||
const meta = removalTarget ? this.store?.getWorktreeMeta(removalTarget.id) : undefined
|
||||
if (!removalTarget || !meta) {
|
||||
if (
|
||||
!removalTarget ||
|
||||
!meta ||
|
||||
(requiredHostId !== undefined && meta.hostId !== requiredHostId)
|
||||
) {
|
||||
throw error
|
||||
}
|
||||
// Why: delete requests can arrive after Git no longer lists the worktree.
|
||||
@@ -24894,7 +24898,11 @@ export class OrcaRuntimeService {
|
||||
.catch(() => {})
|
||||
}
|
||||
this.clearOptimisticReconcileToken(removalTarget.id)
|
||||
this.removeWorktreeMetadataAndHistory(store, removalTarget.id, cleanupHostId)
|
||||
this.removeWorktreeMetadataAndHistory(
|
||||
store,
|
||||
removalTarget.id,
|
||||
cleanupHostId ?? orphanHost?.id
|
||||
)
|
||||
this.preservedBranchCleanupByScope.delete(cleanupScopeKey)
|
||||
this.invalidateResolvedWorktreeCache()
|
||||
this.invalidateWorktreeScanCacheForRepo(removalTarget.repoId)
|
||||
|
||||
Reference in New Issue
Block a user