From 8ec354f6098a383eddc493db362e0dc34bec453b Mon Sep 17 00:00:00 2001 From: Dotta Date: Wed, 30 Sep 2026 21:57:02 -0500 Subject: [PATCH] test(runner): consume ordered permission notifications in forwarding fixture Co-Authored-By: Paperclip --- doc/architecture/runner-rich-acp-capabilities.md | 4 ++++ .../src/live/runnerd-acpx-permission-forwarding.test.ts | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/doc/architecture/runner-rich-acp-capabilities.md b/doc/architecture/runner-rich-acp-capabilities.md index 9914cfabd7f..702fabd19de 100644 --- a/doc/architecture/runner-rich-acp-capabilities.md +++ b/doc/architecture/runner-rich-acp-capabilities.md @@ -11,6 +11,10 @@ qualification are required. The [Cursor](runner-cursor-capabilities.md) and the Copilot 256 KiB output limit and the credential-free native proof scope. Pi remains blocked on a verifiable OpenRouter spending cap. Prior paid failures and case-specific passes remain historical; none is regraded by these fixes. +The controller now dispatches bridged requests in durable notification order. +It consumes earlier activity before presenting a request, while a pending human +answer does not prevent later activity from streaming. A genuine permission-first +provider sequence remains permission-first. Historical source checkpoint (2026-09-30): **Cursor v9, Copilot v8 and Pi v10 remain unqualified**. All three declarations bind shared ACPX patch SHA-256 diff --git a/packages/paperclip-runner/src/live/runnerd-acpx-permission-forwarding.test.ts b/packages/paperclip-runner/src/live/runnerd-acpx-permission-forwarding.test.ts index 70f92e34e0d..14708520b6a 100644 --- a/packages/paperclip-runner/src/live/runnerd-acpx-permission-forwarding.test.ts +++ b/packages/paperclip-runner/src/live/runnerd-acpx-permission-forwarding.test.ts @@ -84,11 +84,15 @@ describe("permission events through the actual transport handler", () => { }; const handled = vi.fn(request => handleServerRequest(state as unknown as CodexSessionState, request)); bundle.transport.setServerRequestHandler(handled); + let drain: Promise | undefined; try { await bundle.transport.request("initialize", {}); await bundle.transport.request("thread/start", { cwd: root }); const start = await bundle.transport.request("turn/start", { input: [{ type: "text", text: "Fixture" }] }); state.activeTurnId = (start.turn as { id: string }).id; + // The real harness consumes notifications before dispatching a bridged + // request at its position in the durable event stream. + drain = (async () => { for await (const _notification of bundle.transport.notifications()) { /* Consume the fixture's turn start. */ } })(); peer.current!.emit("runtime_request.created", { request: { requestId: "permission-7", type: "permission", requestKind: "permission_approval", itemId: "opaque-item-7", prompt: "Change file: result.txt", details, @@ -106,6 +110,7 @@ describe("permission events through the actual transport handler", () => { } finally { for (const entry of pending.values()) entry.settle({ outcome: "cancel" }); await bundle.detachControllerForRestart(); + await drain; rmSync(root, { recursive: true, force: true }); } });