diff --git a/packages/paperclip-runner/src/live/runnerd-codex-transport.test.ts b/packages/paperclip-runner/src/live/runnerd-codex-transport.test.ts index fd10f20052c..47ac7a92091 100644 --- a/packages/paperclip-runner/src/live/runnerd-codex-transport.test.ts +++ b/packages/paperclip-runner/src/live/runnerd-codex-transport.test.ts @@ -1653,9 +1653,11 @@ it.each([ const { preparationDeadline, closeDeadline } = runnerdRecoveryInternals.runnerCloseDeadlines( Date.now(), runnerdRecoveryInternals.runnerCloseGraceMs(options), ); - // The retained restart failure spent 5.2s stopping idle Pi before its - // remote drain acknowledgement crossed the next command round trip. - await vi.advanceTimersByTimeAsync(5_200); + // Native Pi allows thirty seconds for snapshot cleanup and five seconds + // for its lifetime fence before the drain acknowledgement round trip. + const stopMs = options.provider === "acpx" && options.acpxAgent === "pi" + && options.closeGraceMs === undefined ? 35_200 : 5_200; + await vi.advanceTimersByTimeAsync(stopMs); const commands: { commandId: string; status: string; result?: unknown }[] = []; const result = runnerdRecoveryInternals.awaitProviderDrainBarrier({ readProviderState: () => null, @@ -1675,7 +1677,7 @@ it.each([ await vi.advanceTimersByTimeAsync(5_000); expect(await result).toBe(drained); expect(closeDeadline - preparationDeadline).toBeLessThanOrEqual(2_500); - expect(runnerdRecoveryInternals.runnerCloseGraceMs(options)).toBeLessThanOrEqual(15_000); + expect(runnerdRecoveryInternals.runnerCloseGraceMs(options)).toBeLessThanOrEqual(45_000); } finally { vi.useRealTimers(); } }); diff --git a/packages/paperclip-runner/src/live/runnerd-codex-transport.ts b/packages/paperclip-runner/src/live/runnerd-codex-transport.ts index 083241c2be7..45ef8317080 100644 --- a/packages/paperclip-runner/src/live/runnerd-codex-transport.ts +++ b/packages/paperclip-runner/src/live/runnerd-codex-transport.ts @@ -850,11 +850,11 @@ async function awaitRunnerSuspensionBarrier(input: { } function runnerCloseGraceMs(options: Pick): number { - // Idle Pi retirement may consume its five-second RPC stop window. Keep a - // separate five-second drain round trip and the bounded suspension reserve. + // Native Pi retirement allows thirty seconds for snapshot cleanup and five + // for its lifetime fence. Keep a drain round trip and suspension reserve too. // Explicit caller deadlines remain authoritative; all settlement proofs stay // mandatory even when the provider already completed its task. - return options.closeGraceMs ?? (options.provider === "acpx" && options.acpxAgent === "pi" ? 15_000 : 10_000); + return options.closeGraceMs ?? (options.provider === "acpx" && options.acpxAgent === "pi" ? 45_000 : 10_000); } function runnerCloseDeadlines(