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 b54ac1ebb3..0652b50923 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 @@ -278,9 +278,10 @@ impl AcpxSidecarTransport { let error = response.error.expect("failed response has validated error"); return Ok(CommandOutcome::Rejected(LocalRunnerError::invalid( format!( - "ACPX sidecar command {} was rejected (retryable={})", + "ACPX sidecar command {} was rejected (retryable={}, classification={})", command.as_str(), error.retryable, + response_error_classification(&error.message), ), ))); } @@ -596,6 +597,19 @@ fn redact_diagnostic(value: &str) -> String { } } +fn response_error_classification(message: &str) -> &'static str { + match message { + "ACPX session handshake exceeded its admission deadline" => "session_handshake_timeout", + "ACPX provider lifetime guardian exited before ownership transfer" => { + "provider_guardian_exit" + } + "ACPX provider lifetime guardian ownership timed out" => "provider_guardian_timeout", + "ACPX session handshake and runtime cleanup failed" => "session_handshake_cleanup_failed", + "ACPX runtime initialization and cleanup failed" => "runtime_initialization_cleanup_failed", + _ => "unclassified", + } +} + #[cfg(test)] mod tests { use super::*; @@ -641,4 +655,16 @@ mod tests { assert!(!message.contains("Q7Z9"), "error leaked input: {message}"); } } + + #[test] + fn classifies_only_allowlisted_internal_sidecar_failures() { + assert_eq!( + response_error_classification("ACPX session handshake exceeded its admission deadline"), + "session_handshake_timeout" + ); + assert_eq!( + response_error_classification("violet-circuit-4821"), + "unclassified" + ); + } } diff --git a/packages/paperclip-runner/runner/crates/runner-core/tests/acpx_sidecar_transport.rs b/packages/paperclip-runner/runner/crates/runner-core/tests/acpx_sidecar_transport.rs index bbead687b5..2299a71e62 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/tests/acpx_sidecar_transport.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/tests/acpx_sidecar_transport.rs @@ -162,6 +162,7 @@ fn keeps_valid_command_rejections_separate_from_protocol_failures() { .expect_err("fake command should be rejected"); let message = error.to_string(); assert!(message.contains("was rejected")); + assert!(message.contains("classification=unclassified")); assert!(!message.contains("Q7Z9")); assert!(!message.contains("violet-circuit-4821")); assert!(!message.contains("unavailable"));