fix: fail closed on stale qualified removal owner

This commit is contained in:
Brennan Benson
2026-08-14 15:54:57 -07:00
parent df4d0af910
commit 864cb0b4f1
3 changed files with 45 additions and 2 deletions
+8
View File
@@ -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()
})
+27
View File
@@ -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()
+10 -2
View File
@@ -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)