diff --git a/apps/ai-game-creator-shell/src-tauri/src/tests/collaboration/static_deliveries.rs b/apps/ai-game-creator-shell/src-tauri/src/tests/collaboration/static_deliveries.rs index 8c4eb9e04..03b38f715 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/tests/collaboration/static_deliveries.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/tests/collaboration/static_deliveries.rs @@ -86,6 +86,50 @@ fn mark_and_claim_static_delegate_needs_repair( .expect("claim needs-repair receipt"); } +/// 把一条已认领的 delivery 改写成「用户修订」形态,用于模拟审批卡上的 revise。 +/// +/// M1C-1 之后 `UserRevisionRequested` 与 `EvidenceReady` 共用同一套客观证据要求 +/// (terminal completed、无缺失产物、验证已满足),所以模拟修订不能只翻 +/// `contract_status`:沿用 needs-repair 的证据落盘时会被判成「evidence-ready/ +/// user-revision-requested 与客观证据冲突」。这里先让 expected_artifacts 真实落盘, +/// 再按真实证据重建 structuredResult——用户是在**已交付**的产物上要求修订。 +fn rewrite_claimed_static_delegate_as_user_revision_requested( + root: &Path, + delegation_id: &str, + expected_artifacts: &[String], +) { + for artifact in expected_artifacts { + let path = root.join(artifact); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent).expect("create delivered artifact parent"); + } + fs::write(&path, b"# user revision evidence\n").expect("write delivered artifact"); + } + let mut result = build_static_delegate_structured_result_at( + root, + "completed", + expected_artifacts, + false, + None, + None, + None, + None, + ) + .expect("build delivered result"); + assert_eq!( + result.contract_status, + StaticDelegateContractStatus::EvidenceReady, + "模拟用户修订之前,客观证据必须先真实达到 evidence-ready" + ); + result.contract_status = StaticDelegateContractStatus::UserRevisionRequested; + let mut delivery = read_static_delegate_delivery_at(root, delegation_id) + .expect("read claimed delivery") + .expect("claimed delivery exists"); + delivery.structured_result = Some(result); + write_static_delegate_delivery_at(root, &delivery) + .expect("persist simulated approval revision status"); +} + /// 把一条已 dispatched 的 delivery 标记为 needs-user-input 终态并认领。 /// 注意:即便这一跳是纯粹的用户澄清、不产出文件,structuredResult 也必须完整覆盖 /// delivery 记录自身声明的 expected_artifacts(校验在 write_static_delegate_delivery_at @@ -3893,16 +3937,7 @@ fn user_revision_continuation_passes_real_gate_at_depth_one_but_stays_single_chi "user-revision-real-gate-d1-claim", ); - let mut d1_user_revision = read_static_delegate_delivery_at(&root, &d1_id) - .expect("read claimed D1") - .expect("claimed D1 exists"); - d1_user_revision - .structured_result - .as_mut() - .expect("D1 structured result") - .contract_status = StaticDelegateContractStatus::UserRevisionRequested; - write_static_delegate_delivery_at(&root, &d1_user_revision) - .expect("persist simulated approval revision status"); + rewrite_claimed_static_delegate_as_user_revision_requested(&root, &d1_id, &expected_artifacts); // D1 的链上 depth 已经是 1;只有 UserRevisionRequested 分支能让这次真实委派继续。 let d2_action = "user-revision-real-gate-d2-revision-action"; @@ -4065,16 +4100,7 @@ fn concurrent_user_revision_dispatch_creates_exactly_one_delivery() { &expected_artifacts, "concurrent-user-revision-d1-claim", ); - let mut d1_user_revision = read_static_delegate_delivery_at(&root, &d1_id) - .expect("read claimed D1") - .expect("claimed D1 exists"); - d1_user_revision - .structured_result - .as_mut() - .expect("D1 structured result") - .contract_status = StaticDelegateContractStatus::UserRevisionRequested; - write_static_delegate_delivery_at(&root, &d1_user_revision) - .expect("persist simulated approval revision status"); + rewrite_claimed_static_delegate_as_user_revision_requested(&root, &d1_id, &expected_artifacts); let start = Arc::new(Barrier::new(3)); let mut workers = Vec::new();