From 7668cd822db733809df17ca278901b831dd697f2 Mon Sep 17 00:00:00 2001 From: Dotta Date: Tue, 29 Sep 2026 10:00:20 -0500 Subject: [PATCH] Preserve Copilot policy rejection codes across sidecar transport Co-Authored-By: Paperclip --- .../crates/runner-core/src/acpx_sidecar_transport.rs | 7 +++++++ .../paperclip-runner/src/cli/acpx-sidecar-input.test.ts | 6 ++++++ packages/paperclip-runner/src/cli/acpx-sidecar-input.ts | 2 ++ 3 files changed, 15 insertions(+) diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs b/packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs index 9bb2c3b6c0..e111ce2355 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs @@ -697,6 +697,8 @@ fn response_error_classification(error: &ResponseError) -> &'static str { "AGENT_DISCONNECTED" => return "agent_disconnected", "AUTH_REQUIRED" => return "authentication_required", "COPILOT_AUTH_REQUIRED" => return "authentication_required", + "COPILOT_POLICY_VIOLATION" => return "copilot_policy_violation", + "COPILOT_DETACHED_WORK_UNSUPPORTED" => return "copilot_detached_work_unsupported", "COPILOT_ENTITLEMENT_DENIED" => return "provider_entitlement_denied", "COPILOT_MODEL_UNAVAILABLE" => return "requested_model_unsupported", "SESSION_RESUME_REQUIRED" => return "session_resume_required", @@ -888,6 +890,11 @@ mod tests { "provider_lifetime_owned" ); let admission_failures = [ + ("COPILOT_POLICY_VIOLATION", "copilot_policy_violation"), + ( + "COPILOT_DETACHED_WORK_UNSUPPORTED", + "copilot_detached_work_unsupported", + ), ( "ACPX_RUNTIME_ADMISSION_VERIFICATION_TIMEOUT", "runtime_admission_verification_timeout", diff --git a/packages/paperclip-runner/src/cli/acpx-sidecar-input.test.ts b/packages/paperclip-runner/src/cli/acpx-sidecar-input.test.ts index 4ce9ef20a2..bed92b7cef 100644 --- a/packages/paperclip-runner/src/cli/acpx-sidecar-input.test.ts +++ b/packages/paperclip-runner/src/cli/acpx-sidecar-input.test.ts @@ -114,6 +114,12 @@ describe("ACPX sidecar input sequencing", () => { expect(acpxBootstrapBlockedError(null, "turn.start")).toBeNull(); }); + it.each(["COPILOT_POLICY_VIOLATION", "COPILOT_DETACHED_WORK_UNSUPPORTED"])("preserves Copilot policy identity %s", code => { + const error = Object.assign(new Error("safe fixed policy message"), { code }); + expect(acpxSidecarErrorCode(error)).toBe(code); + expect(acpxSidecarErrorCode(new Error("wrapped", { cause: error }))).toBe(code); + }); + it("preserves stable ACPX error identities without copying startup stderr", () => { const missingModule = Object.assign(new Error("provider exited"), { detailCode: "AGENT_STARTUP_FAILED", diff --git a/packages/paperclip-runner/src/cli/acpx-sidecar-input.ts b/packages/paperclip-runner/src/cli/acpx-sidecar-input.ts index 9f508bb289..1887b912ce 100644 --- a/packages/paperclip-runner/src/cli/acpx-sidecar-input.ts +++ b/packages/paperclip-runner/src/cli/acpx-sidecar-input.ts @@ -130,6 +130,8 @@ const GENERIC_ACPX_OUTPUT_CODES = new Set([ ]); const STABLE_ACPX_SIDECAR_CODES = new Set([ + "COPILOT_POLICY_VIOLATION", + "COPILOT_DETACHED_WORK_UNSUPPORTED", "ACP_MODEL_UNSUPPORTED", "ACP_SESSION_INIT_FAILED", "AGENT_DISCONNECTED",