From 189d1d3c2bf84af8cfcd8a5e58dd98a6509477f5 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 9 Oct 2026 23:40:12 +0200 Subject: [PATCH] play-faults fix: the sidecar link errors carry no text SidecarLinkError::Spawn and Codec held error text that the fault type now refuses, leaving two never-read payloads; they are unit variants. Co-Authored-By: Claude Sonnet 5.5 --- crates/ghostlight/src/sdk_inference.rs | 37 ++++++++++---------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/crates/ghostlight/src/sdk_inference.rs b/crates/ghostlight/src/sdk_inference.rs index a751c7e..68a88a1 100644 --- a/crates/ghostlight/src/sdk_inference.rs +++ b/crates/ghostlight/src/sdk_inference.rs @@ -192,10 +192,10 @@ pub(super) enum SidecarLinkError { /// The pipe reached EOF or the child exited. Never a partial output. Closed, /// A length prefix over the cap, a truncated body, or an undecodable one. - Codec(String), + Codec, /// The child could not be started. The entry file existed at open, so this /// is an environment fault an operator must fix. - Spawn(String), + Spawn, } /// The child-process seam, so the protocol driver is testable without Node, a @@ -222,26 +222,21 @@ pub(super) async fn read_frame( .map_err(|_| SidecarLinkError::Closed)?; let length = u32::from_be_bytes(prefix) as usize; if length == 0 || length > MAX_SIDECAR_FRAME_BYTES { - return Err(SidecarLinkError::Codec(format!( - "sidecar frame length {length} is outside 1..={MAX_SIDECAR_FRAME_BYTES}" - ))); + return Err(SidecarLinkError::Codec); } let mut body = vec![0_u8; length]; reader .read_exact(&mut body) .await - .map_err(|error| SidecarLinkError::Codec(error.to_string()))?; - rmp_serde::from_slice(&body).map_err(|error| SidecarLinkError::Codec(error.to_string())) + .map_err(|_| SidecarLinkError::Codec)?; + rmp_serde::from_slice(&body).map_err(|_| SidecarLinkError::Codec) } fn encode_frame(frame: &SidecarFrame) -> Result, SidecarLinkError> { let body = rmp_serde::to_vec_named(frame) - .map_err(|error| SidecarLinkError::Codec(error.to_string()))?; + .map_err(|_| SidecarLinkError::Codec)?; if body.len() > MAX_SIDECAR_FRAME_BYTES { - return Err(SidecarLinkError::Codec(format!( - "sidecar frame of {} bytes exceeds {MAX_SIDECAR_FRAME_BYTES}", - body.len() - ))); + return Err(SidecarLinkError::Codec); } let mut framed = Vec::with_capacity(body.len() + 4); framed.extend_from_slice(&(body.len() as u32).to_be_bytes()); @@ -279,15 +274,15 @@ impl ChildProcessLink { .stderr(Stdio::inherit()) .kill_on_drop(true) .spawn() - .map_err(|error| SidecarLinkError::Spawn(error.to_string()))?; + .map_err(|_| SidecarLinkError::Spawn)?; let stdin = child .stdin .take() - .ok_or_else(|| SidecarLinkError::Spawn("sidecar stdin was not piped".into()))?; + .ok_or(SidecarLinkError::Spawn)?; let stdout = child .stdout .take() - .ok_or_else(|| SidecarLinkError::Spawn("sidecar stdout was not piped".into()))?; + .ok_or(SidecarLinkError::Spawn)?; Ok(SidecarChild { child, stdin, @@ -485,7 +480,7 @@ impl SdkInferencePort { return Err(link_fault(error)); } } - Err(error) => { + Err(_) => { let _ = self.link.restart().await; return Err(InferenceFault::new("the tool-result owner refused a tool call")); } @@ -522,8 +517,8 @@ fn link_fault(error: SidecarLinkError) -> InferenceFault { SidecarLinkError::Closed => { InferenceFault::new("the SDK sidecar exited during a query") } - SidecarLinkError::Spawn(_) => InferenceFault::new("the SDK sidecar could not start"), - SidecarLinkError::Codec(_) => { + SidecarLinkError::Spawn => InferenceFault::new("the SDK sidecar could not start"), + SidecarLinkError::Codec => { InferenceFault::integrity_violation("the SDK sidecar's framing was invalid") } } @@ -1707,7 +1702,7 @@ mod tests { } /// The SDK port's share of the no-input-text rule: text the sidecar sent, - /// the link's own error text, a request's effort and a request's model + /// a request's effort and a request's model /// name each arrive as a canary, and none reaches the fault. The fault /// type carries only fixed text, so this fails if a port ever routes a /// computed string into it (through `Box::leak`, say). @@ -1745,10 +1740,6 @@ mod tests { assert_names_no(&fault, CANARY); } - // The link's own error text. - assert_names_no(&link_fault(SidecarLinkError::Spawn(CANARY.into())), CANARY); - assert_names_no(&link_fault(SidecarLinkError::Codec(CANARY.into())), CANARY); - // An effort the SDK has no counterpart for. let port = SdkInferencePort::new(ScriptedLink::new(Vec::new()), TEST_RUNTIME); let mut prepared = prose_prepared(&port, "Say something true.");