use std::fs; use serde::Deserialize; #[derive(Debug, Deserialize)] struct G1ECandidateBatch { #[serde(rename = "batchId")] batch_id: String, family: String, source: String, #[serde(rename = "supportingSources")] supporting_sources: Vec, #[serde(rename = "ledgerClusterLabel")] ledger_cluster_label: String, #[serde(rename = "selectionRule")] selection_rule: String, #[serde(rename = "candidateCount")] candidate_count: u32, #[serde(rename = "representativeBaseline")] representative_baseline: String, #[serde(rename = "promotedBatchExpansionBaselines")] promoted_batch_expansion_baselines: Vec, #[serde(rename = "expectedSharedContract")] expected_shared_contract: SharedContract, candidates: Vec, notes: Vec, } #[derive(Debug, Deserialize)] struct PromotedExpansionBaseline { #[serde(rename = "fixtureDir")] fixture_dir: String, #[serde(rename = "sceneId")] scene_id: String, #[serde(rename = "sceneName")] scene_name: String, assertions: ExpansionAssertions, } #[derive(Debug, Deserialize)] struct ExpansionAssertions { #[serde(rename = "requiredMainRequest")] required_main_request: String, #[serde(rename = "requiredEnrichmentRequest")] required_enrichment_request: String, #[serde(rename = "requiredMergeJoinKey")] required_merge_join_key: String, #[serde(rename = "requiredMergeAggregateRule")] required_merge_aggregate_rule: String, #[serde(rename = "requiredOutputColumn")] required_output_column: String, } #[derive(Debug, Deserialize)] struct SharedContract { archetype: String, #[serde(rename = "requiredGateNames")] required_gate_names: Vec, } #[derive(Debug, Deserialize)] struct BatchCandidate { #[serde(rename = "sceneKey")] scene_key: String, #[serde(rename = "batchRole")] batch_role: String, status: String, } #[test] fn g1e_candidate_batch_asset_is_actionable() { let batch = load_batch(); assert_eq!(batch.batch_id, "g1e-light-enrichment-candidates-2026-04-18"); assert_eq!(batch.family, "G1-E"); assert!(batch.source.ends_with(".md")); assert_eq!(batch.ledger_cluster_label, "g1e-light-enrichment-candidate"); assert!(batch.selection_rule.contains("Track B")); assert_eq!(batch.candidate_count, 3); assert!(batch .representative_baseline .ends_with("g1e_light_enrichment")); assert_eq!(batch.promoted_batch_expansion_baselines.len(), 2); assert_eq!( batch.expected_shared_contract.archetype, "single_request_enrichment" ); assert!(batch .expected_shared_contract .required_gate_names .iter() .any(|item| item == "merge_plan_resolved")); assert_eq!(batch.candidates.len() as u32, batch.candidate_count); assert_eq!(batch.supporting_sources.len(), 2); assert!(!batch.notes.is_empty()); } #[test] fn g1e_candidate_batch_keeps_promoted_entries_visible() { let batch = load_batch(); let promoted = batch .promoted_batch_expansion_baselines .iter() .find(|item| item.fixture_dir.ends_with("g1e_light_enrichment_expansion")) .expect("expected promoted G1-E expansion baseline"); assert_eq!( promoted.scene_id, "p1-g1e-light-enrichment-expansion-report" ); assert_eq!( promoted.scene_name, "P1 G1-E light enrichment expansion report" ); assert_eq!(promoted.assertions.required_main_request, "getWkorderAll"); assert_eq!( promoted.assertions.required_enrichment_request, "queryMeterInfo" ); assert_eq!(promoted.assertions.required_merge_join_key, "wkOrderNo"); assert_eq!( promoted.assertions.required_merge_aggregate_rule, "group_by:countyCodeName" ); assert_eq!( promoted.assertions.required_output_column, "meterCapacityThisMonth" ); let additional = batch .promoted_batch_expansion_baselines .iter() .find(|item| { item.fixture_dir .ends_with("g1e_light_enrichment_additional") }) .expect("expected additional G1-E expansion baseline"); assert_eq!( additional.scene_id, "p1-g1e-light-enrichment-additional-report" ); assert_eq!( additional.scene_name, "P1 G1-E light enrichment additional report" ); assert_eq!(additional.assertions.required_main_request, "getWkorderAll"); assert_eq!( additional.assertions.required_enrichment_request, "queryBusAcpt" ); assert_eq!(additional.assertions.required_merge_join_key, "wkOrderNo"); assert_eq!( additional.assertions.required_merge_aggregate_rule, "group_by:countyCodeName" ); assert_eq!( additional.assertions.required_output_column, "batchCapacityThisMonth" ); assert!(batch.candidates.iter().any(|item| item.scene_key == "high_low_voltage_new_capacity_monthly" && item.batch_role == "p0-anchor" && item.status == "promoted-baseline")); assert!(batch .candidates .iter() .any(|item| item.scene_key == "light_enrichment_second_sample" && item.batch_role == "first-expansion-anchor" && item.status == "promoted-expansion")); assert!(batch.candidates.iter().any(|item| item.scene_key == "light_enrichment_additional_real_sample" && item.batch_role == "second-expansion-anchor" && item.status == "promoted-expansion")); } fn load_batch() -> G1ECandidateBatch { serde_json::from_str( &fs::read_to_string("tests/fixtures/generated_scene/g1e_candidate_batch_2026-04-18.json") .unwrap(), ) .unwrap() }