//! Verify that plan JSON emitted by orchestrator-llm parses //! cleanly as a `fai_hub::plan::Plan`. This protects against //! schema drift between this module and the hub. //! //! Note: this test runs only on the host target. The WASM build //! does not include test harnesses. #![cfg(not(target_arch = "wasm32"))] #![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use orchestrator_llm::build_stub_plan; use serde_json::Value; #[test] fn emitted_plan_has_required_top_level_fields() { let json = build_stub_plan("test goal"); let parsed: Value = serde_json::from_str(&json).expect("plan must be valid json"); assert!(parsed["schema_version"].is_u64()); assert!(parsed["goal"].is_string()); assert!(parsed["steps"].is_array()); } #[test] fn each_step_has_kind_tag() { let json = build_stub_plan("test goal"); let parsed: Value = serde_json::from_str(&json).unwrap(); for step in parsed["steps"].as_array().unwrap() { assert!(step["kind"].is_string(), "step missing kind tag: {step}"); } } #[test] fn save_flow_step_yaml_parses_as_flow_definition() { // The save_flow step embeds a YAML flow body. Verify it // round-trips through serde_yaml. let json = build_stub_plan("anything"); let parsed: Value = serde_json::from_str(&json).unwrap(); let save_flow_step = parsed["steps"] .as_array() .unwrap() .iter() .find(|s| s["kind"] == "save_flow") .expect("expected a save_flow step"); let yaml_text = save_flow_step["yaml"].as_str().unwrap(); let flow: Value = serde_yaml::from_str(yaml_text).expect("embedded yaml must parse"); assert_eq!(flow["name"], "orchestrator-stub-greeting"); assert!(flow["steps"].is_array()); }