generated-scene: add command-center automation semantics

This commit is contained in:
木炎
2026-05-06 15:22:49 +08:00
parent 6122b521a8
commit 1d586dbe27
7 changed files with 894 additions and 15 deletions

View File

@@ -737,6 +737,233 @@ fn binary_wiring_registry_backed_skill_executes_read_only_scripts_with_runtime_i
);
}
#[test]
fn command_center_preview_reflects_automation_semantics() {
let workspace = temp_workspace("sgclaw-command-center-preview-automation-semantics");
let trigger_path = workspace.join("scheduled-trigger.json");
let output_path = workspace.join("run-record.json");
let config_path = workspace.join("sgclaw_config.json");
let rules_path = workspace.join("resources").join("rules.json");
let materialization_root = workspace.join("materialized");
fs::create_dir_all(&materialization_root).unwrap();
write_json(
&trigger_path,
&scheduled_trigger_with_runtime_inputs("monitor_only"),
);
write_runtime_rules(&rules_path);
generate_scheduled_monitoring_action_skill_package(
GenerateScheduledMonitoringActionSkillRequest {
scene_id: "command-center-fee-control-monitor".to_string(),
scene_name: "command-center-fee-control-monitor".to_string(),
output_root: materialization_root.clone(),
source_evidence_json: PathBuf::from(
"tests/fixtures/generated_scene/monitoring_action_source_evidence_extraction_2026-04-21.json",
),
ir_contract_json: PathBuf::from(
"tests/fixtures/generated_scene/scheduled_monitoring_action_ir_contract_2026-04-22.json",
),
trigger_contract_json: PathBuf::from(
"tests/fixtures/generated_scene/scheduled_monitoring_action_trigger_runtime_contract_2026-04-22.json",
),
},
)
.unwrap();
let detect_payload = json!({
"type": "scheduled-monitoring-detect-snapshot",
"report_name": "command-center-fee-control-monitor",
"status": "detect-ok",
"workflowId": "command_center_fee_control_monitoring_action",
"mode": "monitor_only",
"pendingList": [
{ "id": "A1", "consNo": "C1", "phone": "13800000000", "abnorType": "fee_control" }
],
"inputs": {
"source": "browser_attached_live_read",
"queryAbnorList": [
{ "id": "A1", "consNo": "C1", "phone": "13800000000", "abnorType": "fee_control" }
],
"queryHistoryEnergyCharge": [],
"getMonitorLog": { "lastHandled": "2026-04-22T08:00:00Z" },
"getOtherIphones": { "holidaySwitch": "off" },
"getAllSubMgtOrgTreeByOrgCode": {}
},
"localStorageSnapshot": {
"loginUserInfo": "{\"orgNo\":\"62401\"}",
"markToken": "browser-token",
"yxClassList": "[{\"orgNo\":\"62401\"}]",
"zhzxFkycSendTime": "2026-04-22 08:00:00"
},
"readDiagnostics": {
"source": "browser_attached_live_read",
"businessGatewayReadAttempted": true,
"localhostReadAttempted": true,
"queryAbnorListCount": 1,
"queryHistoryEnergyChargeCount": 0
},
"dependencySnapshot": {
"businessReads": [],
"localReads": [],
"blockedLocalWrites": [],
"blockedCalls": ["repetCtrlSend"]
},
"sideEffectCounters": {
"repetCtrlSend": 0,
"sendMessages": 0,
"callOutLogin": 0,
"audioPlay": 0,
"exeTQueue": 0,
"productionLogWrite": 0
}
});
let (browser_ws_url, browser_server) =
start_callback_host_scheduled_monitoring_browser_server(detect_payload);
write_browser_config(&config_path, &browser_ws_url);
let output = run_binary_with_skills_dir_and_config(
&trigger_path,
&materialization_root.join("skills"),
&config_path,
&workspace,
&output_path,
);
browser_server.join().unwrap();
assert!(
output.status.success(),
"stdout={}\nstderr={}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
let record: Value = serde_json::from_str(&fs::read_to_string(output_path).unwrap()).unwrap();
let preview_artifact = &record["previewArtifact"];
assert_eq!(
preview_artifact["actionPlan"][0]["actionContractRef"],
"dispatch_exception_order"
);
assert_eq!(preview_artifact["summary"]["queue_transition_count"], 1);
assert_eq!(
preview_artifact["queueTransitions"][0]["transitionId"],
"queue_continue_on_done"
);
assert_eq!(
preview_artifact["logWritePreview"][0]["logId"],
"dispose_log_after_dispatch"
);
}
#[test]
fn command_center_empty_pending_list_does_not_emit_log_write_preview() {
let workspace = temp_workspace("sgclaw-command-center-empty-preview-semantics");
let trigger_path = workspace.join("scheduled-trigger.json");
let output_path = workspace.join("run-record.json");
let config_path = workspace.join("sgclaw_config.json");
let rules_path = workspace.join("resources").join("rules.json");
let materialization_root = workspace.join("materialized");
fs::create_dir_all(&materialization_root).unwrap();
write_json(
&trigger_path,
&scheduled_trigger_with_runtime_inputs("monitor_only"),
);
write_runtime_rules(&rules_path);
generate_scheduled_monitoring_action_skill_package(
GenerateScheduledMonitoringActionSkillRequest {
scene_id: "command-center-fee-control-monitor".to_string(),
scene_name: "command-center-fee-control-monitor".to_string(),
output_root: materialization_root.clone(),
source_evidence_json: PathBuf::from(
"tests/fixtures/generated_scene/monitoring_action_source_evidence_extraction_2026-04-21.json",
),
ir_contract_json: PathBuf::from(
"tests/fixtures/generated_scene/scheduled_monitoring_action_ir_contract_2026-04-22.json",
),
trigger_contract_json: PathBuf::from(
"tests/fixtures/generated_scene/scheduled_monitoring_action_trigger_runtime_contract_2026-04-22.json",
),
},
)
.unwrap();
let detect_payload = json!({
"type": "scheduled-monitoring-detect-snapshot",
"report_name": "command-center-fee-control-monitor",
"status": "detect-ok",
"workflowId": "command_center_fee_control_monitoring_action",
"mode": "monitor_only",
"pendingList": [],
"inputs": {
"source": "browser_attached_live_read",
"queryAbnorList": [],
"queryHistoryEnergyCharge": [],
"getMonitorLog": {},
"getOtherIphones": {},
"getAllSubMgtOrgTreeByOrgCode": {}
},
"localStorageSnapshot": {
"loginUserInfo": "{\"orgNo\":\"62401\"}",
"markToken": "browser-token",
"yxClassList": "[{\"orgNo\":\"62401\"}]",
"zhzxFkycSendTime": "2026-04-22 08:00:00"
},
"readDiagnostics": {
"source": "browser_attached_live_read",
"businessGatewayReadAttempted": true,
"localhostReadAttempted": true,
"queryAbnorListCount": 0,
"queryHistoryEnergyChargeCount": 0
},
"dependencySnapshot": {
"businessReads": [],
"localReads": [],
"blockedLocalWrites": [],
"blockedCalls": ["repetCtrlSend"]
},
"sideEffectCounters": {
"repetCtrlSend": 0,
"sendMessages": 0,
"callOutLogin": 0,
"audioPlay": 0,
"exeTQueue": 0,
"productionLogWrite": 0
}
});
let (browser_ws_url, browser_server) =
start_callback_host_scheduled_monitoring_browser_server(detect_payload);
write_browser_config(&config_path, &browser_ws_url);
let output = run_binary_with_skills_dir_and_config(
&trigger_path,
&materialization_root.join("skills"),
&config_path,
&workspace,
&output_path,
);
browser_server.join().unwrap();
assert!(
output.status.success(),
"stdout={}\nstderr={}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
let record: Value = serde_json::from_str(&fs::read_to_string(output_path).unwrap()).unwrap();
let preview_artifact = &record["previewArtifact"];
assert_eq!(preview_artifact["summary"]["pending_count"], 0);
assert_eq!(preview_artifact["summary"]["queue_transition_count"], 1);
assert_eq!(
preview_artifact["queueTransitions"][0]["transitionId"],
"queue_continue_on_empty"
);
assert_eq!(
preview_artifact["logWritePreview"].as_array().unwrap().len(),
0
);
}
#[test]
fn binary_wiring_browser_attached_passes_platform_service_base_from_config() {
let workspace = temp_workspace("sgclaw-scheduled-monitoring-binary-platform-service-base");