删除已退役 Supervisor 的持久进程协作治理用例
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled

- tests/command_runtime.rs:删除 `process_session_supervisor_collaboration_blocks_stdin_but_allows_poll_and_terminate_in_isolated_registry`——Supervisor 已于 2026-09-21 永久退役(项目对话收敛为 DirectProject 与 Design Agent,前端零引用),这条用例不再有现役调用方
- tests/mod.rs:同批删除它唯一的夹具 `process_session_supervisor_collaboration_governance_fixture`(256 行)
- 保留 `process_session_agent_runtime_*_isolated_registry` 两条兄弟用例:它们走的是未退役的 `code-prototype` 路径,且仍是通用 process_session 收口的守门人
- 该用例也是分片偶发假红的来源:慢容器上 terminate 收口按设计翻成 needs-reconciliation(finalize_live_process_session 的 2 秒排水窗口),退役面不值得继续钉
- 验证:用例总数 3154 → 3153;两条兄弟用例通过;无新增编译告警;check:encoding、git diff --check 通过
This commit is contained in:
2026-10-01 18:17:30 +08:00
parent bdd315f12f
commit ac0b69875f
2 changed files with 0 additions and 284 deletions
@@ -4109,34 +4109,6 @@ fn process_session_agent_runtime_confirmed_lifecycle_runs_in_isolated_registry()
assert!(status.success(), "isolated lifecycle test failed: {status}");
}
#[cfg(unix)]
#[test]
fn process_session_supervisor_collaboration_blocks_stdin_but_allows_poll_and_terminate_in_isolated_registry(
) {
const CHILD_MARKER: &str =
"GENARRATIVE_PROCESS_SESSION_SUPERVISOR_COLLABORATION_GOVERNANCE_CHILD";
if std::env::var_os(CHILD_MARKER).is_some() {
tauri::async_runtime::block_on(
process_session_supervisor_collaboration_governance_fixture(),
);
return;
}
let status = std::process::Command::new(std::env::current_exe().expect("current test binary"))
.env(CHILD_MARKER, "1")
.args([
"--exact",
"tests::command_runtime::process_session_supervisor_collaboration_blocks_stdin_but_allows_poll_and_terminate_in_isolated_registry",
"--nocapture",
"--test-threads=1",
])
.status()
.expect("spawn isolated Supervisor process collaboration governance test");
assert!(
status.success(),
"isolated Supervisor process collaboration governance test failed: {status}"
);
}
#[cfg(target_os = "linux")]
#[test]
fn process_session_agent_runtime_start_audit_failure_terminates_target_in_isolated_registry() {
@@ -4796,262 +4796,6 @@ async fn execute_approved_process_action_for_test(
(pending, observation)
}
#[cfg(unix)]
async fn process_session_supervisor_collaboration_governance_fixture() {
const READY_SENTINEL: &str = "SUPERVISOR_PROCESS_READY_PRIVATE";
const POLL_SENTINEL: &str = "SUPERVISOR_PROCESS_POLL_PRIVATE";
const BLOCKED_STDIN_SENTINEL: &str = "SUPERVISOR_PROCESS_BLOCKED_STDIN_PRIVATE";
const AGENT_ID: &str = GAME_CREATOR_PROJECT_SUPERVISOR_AGENT_ID;
const RUN_ID: &str = "supervisor-process-collaboration-governance-run";
clear_process_session_registry_for_tests();
let root = unique_project_path();
init_local_game_project_at(
&root,
"supervisor-process-collaboration-governance-project",
"Project Supervisor 持久进程治理项目",
)
.expect("project init");
let _cleanup = ProcessSessionIntegrationCleanup {
root: root.clone(),
agent_id: AGENT_ID,
run_id: RUN_ID,
};
fs::write(
root.join("package.json"),
r#"{"private":true,"scripts":{"dev":"node supervisor-process-fixture.mjs"}}"#,
)
.expect("write Supervisor process package");
fs::write(
root.join("supervisor-process-fixture.mjs"),
format!(
r#"process.stdin.setEncoding('utf8');
console.log('{READY_SENTINEL}');
process.stdin.on('data', (chunk) => console.log(`ECHO:${{chunk.trim()}}`));
setInterval(() => console.log('{POLL_SENTINEL}'), 50);
"#
),
)
.expect("write Supervisor process fixture");
write_supervisor_collaboration_policy_at(&root, SupervisorCollaborationPolicy::default())
.expect("write Supervisor collaboration policy");
write_project_permission_policy_at(
&root,
ProjectPermissionPolicy {
denied_commands: Vec::new(),
confirm_commands: vec![
"command.start".to_string(),
"command.stdin".to_string(),
"command.terminate".to_string(),
],
agent_policies: BTreeMap::new(),
},
)
.expect("write process tool policy");
let mut state = start_game_creator_agent_runtime_task_at(
&root,
AGENT_ID,
"在协作 delivery 前启动持久进程并验证后续治理边界",
RUN_ID,
"agent-chat",
"启动并治理持久进程",
vec!["进程可读取且可终止,协作后 stdin 被阻断".to_string()],
)
.expect("start Supervisor process runtime");
state.loop_iteration = 1;
let (_, start_observation) = execute_approved_process_action_for_test(
&root,
&mut state,
AgentRuntimeToolAction {
tool: "command.start".to_string(),
reason: Some("在 delivery 前启动真实持久进程".to_string()),
input: serde_json::json!({
"program": "npm",
"args": ["run", "dev"],
"cwd": ".",
"timeoutSeconds": 30
}),
},
AGENT_RUNTIME_ACTION_EXECUTION_MODE_CONFIRMATION,
)
.await;
assert_eq!(start_observation.status, "ok", "{start_observation:?}");
let start_detail: Value = serde_json::from_str(
start_observation
.detail
.as_deref()
.expect("start observation detail"),
)
.expect("parse start observation detail");
let process_id = start_detail["processId"]
.as_str()
.expect("start processId")
.to_string();
let mut cursor = start_detail["nextCursor"]
.as_str()
.expect("start next cursor")
.to_string();
let mut ready_output = String::new();
for index in 0..20 {
let (_, observation) = execute_approved_process_action_for_test(
&root,
&mut state,
AgentRuntimeToolAction {
tool: "command.poll".to_string(),
reason: Some(format!("等待 Supervisor fixture ready {index}")),
input: serde_json::json!({
"processId": process_id,
"cursor": cursor,
"maxChars": 8_000,
"waitMs": 500
}),
},
AGENT_RUNTIME_ACTION_EXECUTION_MODE_AUTO,
)
.await;
assert_eq!(observation.status, "ok", "{observation:?}");
let detail: Value = serde_json::from_str(
observation
.detail
.as_deref()
.expect("ready poll observation detail"),
)
.expect("parse ready poll detail");
assert_eq!(detail["processId"], process_id);
ready_output.push_str(detail["output"].as_str().unwrap_or_default());
cursor = detail["nextCursor"]
.as_str()
.expect("ready poll next cursor")
.to_string();
if ready_output.contains(READY_SENTINEL) {
break;
}
}
assert!(ready_output.contains(READY_SENTINEL), "{ready_output}");
let delivery = new_static_delegate_delivery(
AGENT_ID,
&state.session_id,
RUN_ID,
"supervisor-process-collaboration-delegate-action",
"supervisor-process-collaboration-delivery",
"code-prototype",
"supervisor-process-collaboration-child-session",
"supervisor-process-collaboration-child-run",
);
create_or_read_static_delegate_delivery_at(&root, &delivery)
.expect("create same-run durable static delivery");
let blocked_stdin = execute_game_creator_agent_runtime_tool_action(
&root,
AGENT_ID,
RUN_ID,
&state.current_task,
&AgentRuntimeToolAction {
tool: "command.stdin".to_string(),
reason: Some("协作后不得继续写入持久进程".to_string()),
input: serde_json::json!({
"processId": process_id,
"data": BLOCKED_STDIN_SENTINEL,
"appendNewline": true,
"eof": false
}),
},
)
.await;
assert_eq!(blocked_stdin.status, "blocked", "{blocked_stdin:?}");
assert!(blocked_stdin.summary.contains("协作编排"));
assert!(!serde_json::to_string(&blocked_stdin)
.expect("serialize blocked stdin observation")
.contains(BLOCKED_STDIN_SENTINEL));
let mut post_delivery_output = String::new();
for index in 0..20 {
let (_, observation) = execute_approved_process_action_for_test(
&root,
&mut state,
AgentRuntimeToolAction {
tool: "command.poll".to_string(),
reason: Some(format!("协作后继续读取 Supervisor fixture {index}")),
input: serde_json::json!({
"processId": process_id,
"cursor": cursor,
"maxChars": 8_000,
"waitMs": 500
}),
},
AGENT_RUNTIME_ACTION_EXECUTION_MODE_AUTO,
)
.await;
assert_eq!(observation.status, "ok", "{observation:?}");
let detail: Value = serde_json::from_str(
observation
.detail
.as_deref()
.expect("post-delivery poll detail"),
)
.expect("parse post-delivery poll detail");
assert_eq!(detail["processId"], process_id);
let output = detail["output"].as_str().unwrap_or_default();
assert!(!output.contains(BLOCKED_STDIN_SENTINEL), "{output}");
post_delivery_output.push_str(output);
cursor = detail["nextCursor"]
.as_str()
.expect("post-delivery poll next cursor")
.to_string();
if post_delivery_output.contains(POLL_SENTINEL) {
break;
}
}
assert!(
post_delivery_output.contains(POLL_SENTINEL),
"{post_delivery_output}"
);
assert!(!post_delivery_output.contains(BLOCKED_STDIN_SENTINEL));
let transcript_path = root.join(format!(
".agent/runtime/process-sessions/{process_id}.output.json"
));
let transcript = fs::read_to_string(&transcript_path).expect("read process transcript");
assert!(transcript.contains(READY_SENTINEL));
assert!(!transcript.contains(BLOCKED_STDIN_SENTINEL));
let (_, terminate_observation) = execute_approved_process_action_for_test(
&root,
&mut state,
AgentRuntimeToolAction {
tool: "command.terminate".to_string(),
reason: Some("协作后只治理并终止既有持久进程".to_string()),
input: serde_json::json!({
"processId": process_id,
"cursor": cursor
}),
},
AGENT_RUNTIME_ACTION_EXECUTION_MODE_CONFIRMATION,
)
.await;
assert_eq!(
terminate_observation.status, "ok",
"{terminate_observation:?}"
);
let terminate_detail: Value = serde_json::from_str(
terminate_observation
.detail
.as_deref()
.expect("terminate observation detail"),
)
.expect("parse terminate detail");
assert_eq!(terminate_detail["processId"], process_id);
assert!(matches!(
terminate_detail["status"].as_str(),
Some("terminated" | "exited" | "timed-out" | "output-limit-exceeded")
));
assert!(!has_active_process_sessions_at(&root).expect("process inactive after terminate"));
let terminal_transcript =
fs::read_to_string(&transcript_path).expect("read terminal process transcript");
assert!(!terminal_transcript.contains(BLOCKED_STDIN_SENTINEL));
}
#[cfg(target_os = "linux")]
async fn process_session_agent_runtime_start_audit_failure_fixture() {
const AGENT_ID: &str = "code-prototype";