From 3fce49c5b9ff3e397fec9862040e2a49a8169cd1 Mon Sep 17 00:00:00 2001 From: Dotta Date: Fri, 9 Oct 2026 02:18:38 -0500 Subject: [PATCH] fix(runner): carry steering identity into Hermes parent Co-Authored-By: Paperclip --- .../src/live/runnerd-codex-transport.test.ts | 6 ++++++ .../paperclip-runner/src/live/runnerd-codex-transport.ts | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) 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 9d8a8586de..60df48f8ee 100644 --- a/packages/paperclip-runner/src/live/runnerd-codex-transport.test.ts +++ b/packages/paperclip-runner/src/live/runnerd-codex-transport.test.ts @@ -2050,6 +2050,12 @@ it("restores provider identity and streamed text from a canonical delta", () => .toMatchObject({ threadId: "root-thread", turnId: "provider-turn", delta: "Reading Gmail", itemId: "message-1" }); }); +it("keeps a flat steering acknowledgement recognizable for deduplication", () => { + const receipt = { kind: "steering_acknowledgement", correlationId: "steer-1", status: "accepted" }; + expect(rehydrateRunnerdItemNotification(receipt, "opened-thread", "provider-turn")) + .toEqual({ ...receipt, threadId: "opened-thread", turnId: "provider-turn" }); +}); + it("rehydrates a canonical agent item for the strict Codex facade", () => { expect( rehydrateRunnerdItemNotification( diff --git a/packages/paperclip-runner/src/live/runnerd-codex-transport.ts b/packages/paperclip-runner/src/live/runnerd-codex-transport.ts index fcdbb4b04e..8c99af2755 100644 --- a/packages/paperclip-runner/src/live/runnerd-codex-transport.ts +++ b/packages/paperclip-runner/src/live/runnerd-codex-transport.ts @@ -1886,6 +1886,11 @@ export function rehydrateRunnerdItemNotification( activeTurnId: string, ): Record { const rawItem = record(rawParams.item); + if (rawParams.kind === "steering_acknowledgement" && Object.keys(rawItem).length === 0) { + // Preserve runnerd's flat receipt so the driver recognizes the transport + // echo. The acknowledged request emits the user-visible bound item once. + return { ...rawParams, threadId: openedThreadId, turnId: activeTurnId }; + } const channel = rawItem.channel ?? rawParams.channel; const providerPhase = rawItem.phase ?? rawParams.providerPhase; const phase = @@ -3663,7 +3668,9 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { "turn.steer", { text, - turnId: this.#durableTurnId, + // ACPX owns the requested provider turn, which can differ from the + // durable PRP turn that scopes control-plane and semantic events. + turnId: this.options.provider === "acpx" ? expectedTurnId : this.#durableTurnId, providerTurnId: expectedTurnId, ...(params.mode === "follow_up" ? { mode: "follow_up" } : {}), ...(correlationId ? { correlationId } : {}),