diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/main_loop_tests.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/main_loop_tests.rs index aaaf9ef4f..092785609 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/main_loop_tests.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/main_loop_tests.rs @@ -584,13 +584,30 @@ async fn autonomous_supervisor_converged_final_reply_deserialize_commits_fallbac } assert_eq!(stream.status, "committed"); assert_eq!(stream.accumulated_text, fallback); - assert!(read_game_creator_agent_runtime_finalization_journal( + // finalization 先把 response stream 标为 committed,之后才调 + // remove_..._finalization_recovery_sidecars 清理 sidecar,两步之间有真实时间窗。 + // 上面等 committed 的循环一旦命中前半步就会退出,因此这里必须同样轮询,否则在 + // CI 负载下会偶发读到尚未清理的残留。journal 是该清理链最后删除的一项,等它消失 + // 即可覆盖后面几条 handoff 残留断言。 + let mut finalization_residue = read_game_creator_agent_runtime_finalization_journal( &root, GAME_CREATOR_PROJECT_SUPERVISOR_AGENT_ID, RUN_ID, ) - .expect("read finalization residue") - .is_none()); + .expect("read finalization residue"); + for _ in 0..250 { + if finalization_residue.is_none() { + break; + } + std::thread::sleep(Duration::from_millis(20)); + finalization_residue = read_game_creator_agent_runtime_finalization_journal( + &root, + GAME_CREATOR_PROJECT_SUPERVISOR_AGENT_ID, + RUN_ID, + ) + .expect("poll finalization residue"); + } + assert!(finalization_residue.is_none()); assert!(provider_retry::read_for_run_at( &root, GAME_CREATOR_PROJECT_SUPERVISOR_AGENT_ID,