rebase(sta-4343): replay #14606 host-qualified removal onto main

Squashed replay of the 14 commits on brennanb2025/sta-4343-fix. Twelve of
them predate the branch's own main-merge, so a commit-by-commit rebase
re-conflicts against the worktrees/persistence slice splits every time.

Re-homed by hand where main moved the code:
- persistence.ts -> persistence/loading-store/store.ts (removeWorktreeMeta)
- persistence.test.ts -> persistence-host-partitioned-sessions.test.ts
- ipc/worktrees.test.ts -> worktrees-remove-host-disambiguation.test.ts,
  worktrees-removal-recovery.test.ts,
  worktrees-preserved-branch-fork-remote.test.ts

Kept main's side where it moved ahead: the folder-workspace
deleteRemoteWorktreeHistory call, and cleanup success toasts no longer
firing from the background-removal path.
This commit is contained in:
Brennan Benson
2026-08-16 21:58:35 -07:00
parent a9f93172cf
commit 4052ea8b8c
79 changed files with 4791 additions and 1141 deletions
+13 -1
View File
@@ -277,8 +277,20 @@ export const WORKTREE_HANDLERS: Record<string, CommandHandler> = {
printResult(result, json, formatWorktreeShow)
},
'worktree rm': async ({ flags, client, cwd, json }) => {
const worktree = await getRequiredWorktreeSelector(flags, 'worktree', cwd, client)
const resolved = await client.call<{ worktree: RuntimeWorktreeRecord }>('worktree.show', {
worktree
})
const hostId = resolved.result.worktree.hostId
if (!hostId) {
throw new RuntimeClientError(
'worktree_host_unresolved',
'Orca cannot tell which host owns this workspace. Refresh projects and try again.'
)
}
const result = await client.call<RuntimeWorktreeRemoveResult>('worktree.rm', {
worktree: await getRequiredWorktreeSelector(flags, 'worktree', cwd, client),
worktree,
hostId,
force: flags.get('force') === true,
// Why (#11960): --force is explicit here, so it may also waive PTY-stop proof.
allowUnverifiedPtyStop: flags.get('force') === true,
+31 -6
View File
@@ -88,27 +88,52 @@ describe('command aliases dispatch to the canonical handler', () => {
})
it('runs `worktree remove` as the canonical `worktree rm` (the incident)', async () => {
queueFixtures(callMock, okFixture('req', { removed: true }))
queueFixtures(
callMock,
okFixture('req_show', { worktree: { hostId: 'local' } }),
okFixture('req', { removed: true })
)
await main(['worktree', 'remove', '--worktree', 'id:wt-1', '--force', '--json'], '/tmp/repo')
expect(callMock).toHaveBeenCalledWith(
expect(callMock).toHaveBeenNthCalledWith(
2,
'worktree.rm',
expect.objectContaining({ worktree: 'id:wt-1', force: true })
expect.objectContaining({ worktree: 'id:wt-1', hostId: 'local', force: true })
)
})
it('runs `worktree delete` as the canonical `worktree rm`', async () => {
queueFixtures(callMock, okFixture('req', { removed: true }))
queueFixtures(
callMock,
okFixture('req_show', { worktree: { hostId: 'runtime:env-1' } }),
okFixture('req', { removed: true })
)
await main(['worktree', 'delete', '--worktree', 'id:wt-1', '--json'], '/tmp/repo')
expect(callMock).toHaveBeenCalledWith(
expect(callMock).toHaveBeenNthCalledWith(
2,
'worktree.rm',
expect.objectContaining({ worktree: 'id:wt-1' })
expect.objectContaining({ worktree: 'id:wt-1', hostId: 'runtime:env-1' })
)
})
it('fails closed when worktree removal cannot resolve a host', async () => {
queueFixtures(callMock, okFixture('req_show', { worktree: { id: 'wt-1' } }))
const priorExitCode = process.exitCode
try {
await main(['worktree', 'rm', '--worktree', 'id:wt-1', '--json'], '/tmp/repo')
expect(process.exitCode).toBe(1)
expect(callMock).toHaveBeenCalledTimes(1)
expect(callMock).toHaveBeenCalledWith('worktree.show', { worktree: 'id:wt-1' })
} finally {
process.exitCode = priorExitCode
}
})
it('still runs `terminal focus` after the handler de-duplication', async () => {
queueFixtures(callMock, okFixture('req', { focus: { ok: true } }))