From 26e5a22b3c23ccd4e6ad101178c5328264f7bea7 Mon Sep 17 00:00:00 2001 From: Dotta Date: Mon, 2 Nov 2026 17:31:38 -0600 Subject: [PATCH] test: isolate settled-turn cleanup from credential port contention Use the existing credential admission fixture for this runtime lifecycle case while retaining its retry assertions and checking credential retention and final release. Dedicated real kernel-lease tests remain unchanged. Co-Authored-By: Paperclip --- .../src/drivers/acpx/runtime-host.test.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts b/packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts index 8d14bb2f9da..87548d4b507 100644 --- a/packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts @@ -1986,6 +1986,7 @@ describe("ACPX runtime host", () => { it("retains a settled turn when shutdown cleanup must be retried", async () => { const fixture = await hostFixture(); + const credential = credentialLeaseFixture(fixture.root); let settleTurn!: (value: { stopReason: string }) => void; const turn = { ...runtimeTurn(), @@ -2000,6 +2001,8 @@ describe("ACPX runtime host", () => { if (failRuntimeClose) throw new Error("runtime cleanup failed"); }, }); + const dependencies = fixture.dependencies({ openRuntime: async () => runtime }); + dependencies.stageCredential = vi.fn(async () => credential); const host = await AcpxRuntimeHost.open( { ...fixture.options, @@ -2008,7 +2011,7 @@ describe("ACPX runtime host", () => { permissionMode: "approve-reads", environment: { PAPERCLIP_ACPX_CODEX_AUTH_JSON_SECRET: "{}" }, }, - fixture.dependencies({ openRuntime: async () => runtime }), + dependencies, ); host.startTurn({ text: "Complete the task.", requestId: "turn-1" }); @@ -2016,6 +2019,8 @@ describe("ACPX runtime host", () => { settleTurn({ stopReason: "end_turn" }); await expect(firstClose).rejects.toThrow(/cleanup failed/); expect(turn.cancel).toHaveBeenCalledOnce(); + expect(credential.close).not.toHaveBeenCalled(); + expect(host.isClosed()).toBe(false); failRuntimeClose = false; await expect( @@ -2023,6 +2028,8 @@ describe("ACPX runtime host", () => { ).resolves.toBeUndefined(); expect(turn.cancel).toHaveBeenCalledTimes(2); expect(runtime.close).toHaveBeenCalledTimes(2); + expect(credential.close).toHaveBeenCalledOnce(); + expect(host.isClosed()).toBe(true); }); it("closes a command lease that resolves after admission is aborted", async () => { @@ -2307,7 +2314,7 @@ describe("ACPX runtime host", () => { }, ACPX_LONG_WAIT_TEST_TIMEOUT_MS); }); -// Deadline tests exercise runtime admission and cleanup, not kernel lease +// Runtime lifecycle tests exercise admission and cleanup, not kernel lease // acquisition. Keep their credential owner deterministic: real lease staging // uses hashed loopback ports that unrelated parallel tests can occupy. The // credential and retained-owner integration tests still use real leases.