From c8fccec465126d617dd1c6b7b2f7f86c4d1a9804 Mon Sep 17 00:00:00 2001 From: echoVic <137844255@qq.com> Date: Thu, 30 Jul 2026 16:11:50 +0800 Subject: [PATCH] fix(test): make subagent sleep hook portable on Windows The `async_subagent_completes_after_launching_exec_process_exits` test wrote a `pre_model_call` hook running `sleep 0.4`. On Windows the resolved host shell is PowerShell, where `sleep` aliases `Start-Sleep`, and Windows PowerShell 5.1 rejects the fractional `0.4` seconds argument (and cmd.exe has no `sleep` at all). The hook therefore failed and `orca exec` exited with code 1 instead of 0, panicking the test. Because every test in this file shares a single static `Mutex`, that first panic poisoned the lock and cascaded into all 12 tests failing with `PoisonError`, masking the real cause on the Windows CI gate. - Emit a platform-specific delay command: `sleep {seconds}` on Unix and `Start-Sleep -Milliseconds {ms}` (integer, valid on PowerShell 5.1 and 7) on Windows, mirroring the existing hook idiom in tests/exec_jsonl.rs. - Recover from a poisoned test lock so a single failure is reported on its own merits instead of cascading across the whole suite. Co-authored-by: TRAE CLI --- tests/subagent_contract.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/subagent_contract.rs b/tests/subagent_contract.rs index 342eb927..44b20197 100644 --- a/tests/subagent_contract.rs +++ b/tests/subagent_contract.rs @@ -519,9 +519,13 @@ fn find_event<'a>(events: &'a [Value], event_type: &str) -> &'a Value { } fn subagent_cli_test_guard() -> MutexGuard<'static, ()> { + // Recover from a poisoned lock so that a single failing test is reported on + // its own merits instead of cascading into every other test failing with + // `PoisonError`. The guard only serializes access; there is no shared state + // to be left inconsistent by a panicking test. SUBAGENT_CLI_TEST_LOCK .lock() - .expect("subagent CLI test lock") + .unwrap_or_else(std::sync::PoisonError::into_inner) } fn run_git(cwd: &std::path::Path, args: &[&str]) { @@ -640,9 +644,16 @@ fn poll_subagent_status( fn write_sleep_hook_config(home: &std::path::Path, seconds: f32) { std::fs::create_dir_all(home).expect("create ORCA_HOME"); + // The resolved host shell differs per platform, so the delay command has to + // match its dialect. Unix runs the config through `sh -c`, while Windows + // resolves to PowerShell, where `sleep` is not a valid command. + #[cfg(unix)] + let sleep_command = format!("sleep {seconds}"); + #[cfg(windows)] + let sleep_command = format!("Start-Sleep -Milliseconds {}", (seconds * 1000.0).round() as u64); std::fs::write( home.join("config.toml"), - format!("[[hooks]]\nevent = \"pre_model_call\"\ncommand = \"sleep {seconds}\"\n"), + format!("[[hooks]]\nevent = \"pre_model_call\"\ncommand = \"{sleep_command}\"\n"), ) .expect("write hook config"); }