fix(worktrees): a host-scoped purge leaves a surviving twin's tabs and edits alone (#30030)

This commit is contained in:
Neil
2026-10-17 16:29:17 -07:00
committed by GitHub
parent 27cfee6f7e
commit 299dcb86fc
21 changed files with 1198 additions and 210 deletions
@@ -5,7 +5,9 @@ import {
getExecutionHostIdFromWorktreeHostIdentity,
getWorktreeHostIdentity,
getWorktreeIdFromHostIdentity,
type HostScopedWorktreeKey
hostWorktreeTarget,
type HostScopedWorktreeKey,
type HostWorktreeTarget
} from './host-qualified-identity'
const WORKTREE_ID = 'repo-1::/work/orca'
@@ -120,3 +122,18 @@ describe('worktree host identity golden bytes', () => {
expect([raw, forged]).toEqual([key, WORKTREE_ID])
})
})
describe('host worktree target', () => {
it('carries the row id and its concrete host', () => {
const target = hostWorktreeTarget({ id: WORKTREE_ID, hostId: toSshExecutionHostId('box') })
expect(target).toEqual({ hostId: 'ssh:box', worktreeId: WORKTREE_ID })
})
it('cannot be forged from a plain object or built without a host', () => {
// @ts-expect-error only hostWorktreeTarget mints the brand
const forged: HostWorktreeTarget = { hostId: 'local', worktreeId: WORKTREE_ID }
// @ts-expect-error an unqualified row has no host to scope to
hostWorktreeTarget({ id: WORKTREE_ID, hostId: undefined })
expect(forged.worktreeId).toBe(WORKTREE_ID)
})
})
@@ -22,6 +22,23 @@ declare const hostScopedWorktreeKeyBrand: unique symbol
// Why: for new code only; existing raw-id stores stay as they are (D7).
export type HostScopedWorktreeKey = string & { readonly [hostScopedWorktreeKeyBrand]: true }
declare const hostWorktreeTargetBrand: unique symbol
/** One host's copy of a workspace, for destructive entry points that must not reach its twin. */
export type HostWorktreeTarget = {
readonly hostId: ExecutionHostId
readonly worktreeId: string
readonly [hostWorktreeTargetBrand]: true
}
export function hostWorktreeTarget(row: {
id: string
hostId: ExecutionHostId
}): HostWorktreeTarget {
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the only constructor of the brand; `hostId` is a concrete host by the parameter type.
return { hostId: row.hostId, worktreeId: row.id } as HostWorktreeTarget
}
/**
* Stable key for one workspace on one host (STA-4343).
*