fix(hibernation): preserve same-id restored PTY rebinds

This commit is contained in:
Brennan Benson
2026-07-29 15:24:52 -07:00
parent 7213d49758
commit c273fab87a
2 changed files with 32 additions and 4 deletions
@@ -375,6 +375,33 @@ describe('restored subagent liveness sweep', () => {
}
})
it('keeps a pane that rebinds its persisted PTY while the probe is pending', async () => {
const server = await restartWithInFlightSubagent()
const boundPtyIdByPaneKey: Record<string, string> = {}
let resolveProbe!: (live: boolean | null) => void
const probeLiveLocalPty = vi.fn(
() =>
new Promise<boolean | null>((resolve) => {
resolveProbe = resolve
})
)
try {
const sweep = sweepWith(server, {
probeLiveLocalPty,
boundPtyIdByPaneKey,
persistedPtyIdByPaneKey: { [PANE]: PTY }
})
await vi.waitFor(() => expect(probeLiveLocalPty).toHaveBeenCalledExactlyOnceWith(PTY))
boundPtyIdByPaneKey[PANE] = PTY
resolveProbe(false)
expect(await sweep).toBe(0)
expect(paneStatus(server).state).toBe('working')
} finally {
server.stop()
}
})
it('leaves a pane whose lead is genuinely mid-turn at working', async () => {
const server = await restartWithInFlightSubagent()
try {
@@ -32,9 +32,8 @@ export async function sweepRestoredSubagentsWithoutLiveAgent(
return await deps.reap(
(worktreeId) => deps.isLocalExecutionHost(worktreeId),
async (paneKey) => {
const resolvePtyId = (): string | undefined =>
deps.getBoundPtyIdForPaneKey(paneKey) ?? deps.getPersistedPtyIdForPaneKey(paneKey)
const ptyId = resolvePtyId()
const boundPtyId = deps.getBoundPtyIdForPaneKey(paneKey)
const ptyId = boundPtyId ?? deps.getPersistedPtyIdForPaneKey(paneKey)
if (!ptyId) {
return true
}
@@ -45,7 +44,9 @@ export async function sweepRestoredSubagentsWithoutLiveAgent(
probesByPtyId.set(ptyId, probe)
}
const live = await probe
return resolvePtyId() !== ptyId || live !== false
const currentBoundPtyId = deps.getBoundPtyIdForPaneKey(paneKey)
// Why: cold restore can rebind the persisted id while its absence probe is in flight.
return currentBoundPtyId !== boundPtyId || live !== false
} catch {
return true
}