From 3f3198af39a4a6085cecb7815f311fb6d6ac76c6 Mon Sep 17 00:00:00 2001 From: David VIEJO Date: Fri, 16 Oct 2026 00:01:05 +0200 Subject: [PATCH] test(retained): wait for the second prompt before releasing the handed-off subagent claude_background_subagent_survives_a_new_turn waited for any "prompt" log entry, which the first turn had already written, so on a slow runner the subagent was released before the new turn was reading the process. Where its frames landed (this turn's stream or the parked buffer) then decided the assertions, and the test failed intermittently on macOS CI. Wait for the second turn's own prompt instead. Reproduced deterministically by delaying the new turn's start by 300 ms or more; passes with up to 2.5 s. Co-Authored-By: Claude Sonnet 5.5 --- tests/retained_providers.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/retained_providers.rs b/tests/retained_providers.rs index 76ae700..457d742 100644 --- a/tests/retained_providers.rs +++ b/tests/retained_providers.rs @@ -258,6 +258,24 @@ impl Fixture { .await .unwrap_or_else(|_| panic!("fixture never logged {kind}: {:?}", self.events())); } + async fn wait_for_prompt(&self, prompt: &str) { + tokio::time::timeout(Duration::from_secs(10), async { + while !self + .events() + .iter() + .any(|v| v["kind"] == "prompt" && v["prompt"] == prompt) + { + tokio::time::sleep(Duration::from_millis(10)).await; + } + }) + .await + .unwrap_or_else(|_| { + panic!( + "fixture never received prompt {prompt}: {:?}", + self.events() + ) + }); + } /// Start a turn, retrying briefly while the runtime reports busy, as an /// application following `RetryAdvice::After` does. async fn start_retrying(&self, id: &str, prompt: &str) -> TurnHandle { @@ -546,7 +564,10 @@ async fn claude_background_subagent_survives_a_new_turn() { let second = Running::new(f.start_retrying("two", "second").await); let (_, first_result) = first.finish().await; assert_eq!(first_result.unwrap().text, "LAUNCHED"); - f.wait_for_log("prompt").await; + // The first turn's prompt is already in the log, so wait for the second + // one: only once the new turn is reading the process does the subagent's + // output belong to it. + f.wait_for_prompt("second").await; tokio::time::sleep(Duration::from_millis(200)).await; assert!( !second.completion.is_finished(),