From 7db769c5bb233f9bfb61dfa507dbcde1853e6951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Thu, 1 Oct 2026 18:28:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B9=B6=E5=8F=91=E8=BF=BD=E5=8A=A0=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E7=94=A8=E4=BE=8B=E4=B8=8D=E5=86=8D=E9=92=89=E6=AD=BB?= =?UTF-8?q?=E8=B4=A5=E8=80=85=E9=94=99=E8=AF=AF=E6=96=87=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - runtime_protocol/steering.rs:concurrent_distinct_frozen_root_steers_create_only_one_replacement 的败者断言改为「根 Run 已被接管」类错误收口,覆盖三种真实交错(替代 Run 已写回 session 状态 / 仅终止旧根 Run / 状态切换中途) - 该用例要守的结构不变量保持不变:恰好一次成功、一次失败、只产生一个替代 Run - 该断言此前在分片里约三成概率因文案不同而假红,而三种文案都由生产侧抢占顺序决定,不是用例要测的结构语义 --- .../src/agent/runtime_protocol/steering.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/steering.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/steering.rs index 93c0bc144..cfcd95c74 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/steering.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/steering.rs @@ -1883,10 +1883,24 @@ mod goal_contract_steer_transition_tests { .collect::>(); assert_eq!(results.iter().filter(|result| result.is_ok()).count(), 1); assert_eq!(results.iter().filter(|result| result.is_err()).count(), 1); - assert!(results + // 两个并发追加指令里必然有一个是 loser,但 loser 落在哪个错误分支取决于它抢到 + // transition 锁时 winner 推进到了哪一步: + // - winner 的替代 Run 已经写回 session 状态:`已被其他追加指令替换`; + // - winner 只终止了旧根 Run、替代 Run 尚未写回:`当前 Agent run 状态不接受追加指令`; + // - 读到的状态正好处于切换中途:`追加指令与当前 Agent 的 session/run 身份不匹配`。 + // 三者都表示这条根 Run 已被另一条追加指令接管,因此这里只钉死“败者被拒绝”这一语义, + // 真正的结构不变量(只产生一个替代 Run)由下面的任务日志断言保证。 + let loser_error = results .iter() .filter_map(|result| result.as_ref().err()) - .any(|error| error.contains("已被其他追加指令替换"))); + .next() + .expect("concurrent steer loser error"); + assert!( + loser_error.contains("已被其他追加指令替换") + || loser_error.contains("当前 Agent run 状态不接受追加指令") + || loser_error.contains("追加指令与当前 Agent 的 session/run 身份不匹配"), + "并发的追加指令 loser 必须以“根 Run 已被接管”类错误收口,实际错误:{loser_error}" + ); let replacement_run_ids = read_all_game_creator_agent_runtime_tasks( &game_creator_agent_runtime_task_path(&root, GAME_CREATOR_PROJECT_SUPERVISOR_AGENT_ID),