并发追加指令用例不再钉死败者错误文案
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m29s
Project CI / Backend tests (pull_request) Failing after 16s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m58s
Project CI / Frontend tests (pull_request) Successful in 2m11s
Project CI / Repository checks (pull_request) Failing after 17s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m44s
Project CI / Native shell tests (pull_request) Successful in 5m43s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 11m51s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 10m47s

- runtime_protocol/steering.rs:concurrent_distinct_frozen_root_steers_create_only_one_replacement 的败者断言改为「根 Run 已被接管」类错误收口,覆盖三种真实交错(替代 Run 已写回 session 状态 / 仅终止旧根 Run / 状态切换中途)
- 该用例要守的结构不变量保持不变:恰好一次成功、一次失败、只产生一个替代 Run
- 该断言此前在分片里约三成概率因文案不同而假红,而三种文案都由生产侧抢占顺序决定,不是用例要测的结构语义
This commit is contained in:
2026-10-01 18:28:54 +08:00
parent ac0b69875f
commit 7db769c5bb
@@ -1883,10 +1883,24 @@ mod goal_contract_steer_transition_tests {
.collect::<Vec<_>>();
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),