176 lines
5.8 KiB
Rust
176 lines
5.8 KiB
Rust
use std::fs;
|
|
|
|
use serde::Deserialize;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct G2CandidateBatch {
|
|
#[serde(rename = "batchId")]
|
|
batch_id: String,
|
|
family: String,
|
|
source: String,
|
|
#[serde(rename = "supportingSources")]
|
|
supporting_sources: Vec<String>,
|
|
#[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<PromotedExpansionBaseline>,
|
|
#[serde(rename = "expectedSharedContract")]
|
|
expected_shared_contract: SharedContract,
|
|
candidates: Vec<BatchCandidate>,
|
|
notes: Vec<String>,
|
|
}
|
|
|
|
#[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 = "requiredDefaultMode")]
|
|
required_default_mode: String,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct SharedContract {
|
|
archetype: String,
|
|
#[serde(rename = "requiredGateNames")]
|
|
required_gate_names: Vec<String>,
|
|
#[serde(rename = "requiredVariantPatterns")]
|
|
required_variant_patterns: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct BatchCandidate {
|
|
#[serde(rename = "sceneKey")]
|
|
scene_key: String,
|
|
#[serde(rename = "batchRole")]
|
|
batch_role: String,
|
|
status: String,
|
|
}
|
|
|
|
#[test]
|
|
fn g2_candidate_batch_asset_is_actionable() {
|
|
let batch = load_batch();
|
|
|
|
assert_eq!(batch.batch_id, "g2-lineloss-family-candidates-2026-04-18");
|
|
assert_eq!(batch.family, "G2");
|
|
assert!(batch.source.ends_with(".md"));
|
|
assert_eq!(batch.ledger_cluster_label, "lineloss-family-candidate");
|
|
assert!(batch.selection_rule.contains("Track A"));
|
|
assert_eq!(batch.candidate_count, 6);
|
|
assert!(batch.representative_baseline.ends_with("multi_mode"));
|
|
assert_eq!(batch.promoted_batch_expansion_baselines.len(), 5);
|
|
assert_eq!(
|
|
batch.expected_shared_contract.archetype,
|
|
"multi_mode_request"
|
|
);
|
|
assert!(batch
|
|
.expected_shared_contract
|
|
.required_gate_names
|
|
.iter()
|
|
.any(|item| item == "request_contract_complete"));
|
|
assert!(batch
|
|
.expected_shared_contract
|
|
.required_variant_patterns
|
|
.iter()
|
|
.any(|item| item == "g2_f_diagnosis_drilldown"));
|
|
assert!(batch
|
|
.expected_shared_contract
|
|
.required_variant_patterns
|
|
.iter()
|
|
.any(|item| item == "g2_d_prediction_compute"));
|
|
assert_eq!(batch.candidates.len() as u32, batch.candidate_count);
|
|
assert_eq!(batch.supporting_sources.len(), 2);
|
|
assert!(!batch.notes.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn g2_candidate_batch_promotes_four_expansion_variants() {
|
|
let batch = load_batch();
|
|
|
|
assert!(batch
|
|
.promoted_batch_expansion_baselines
|
|
.iter()
|
|
.any(|item| item.fixture_dir.ends_with("g2_weekly_single_mode")
|
|
&& item.scene_id == "p1-g2-weekly-single-mode-report"
|
|
&& item.scene_name == "P1 G2 weekly single mode report"
|
|
&& item.assertions.required_default_mode == "week"));
|
|
assert!(batch
|
|
.promoted_batch_expansion_baselines
|
|
.iter()
|
|
.any(
|
|
|item| item.fixture_dir.ends_with("g2_mixed_linked_workflow")
|
|
&& item.scene_id == "p1-g2-mixed-linked-workflow-report"
|
|
&& item.scene_name == "P1 G2 mixed linked workflow report"
|
|
&& item.assertions.required_default_mode == "primary"
|
|
));
|
|
assert!(batch
|
|
.promoted_batch_expansion_baselines
|
|
.iter()
|
|
.any(
|
|
|item| item.fixture_dir.ends_with("g2_comparison_crosscheck")
|
|
&& item.scene_id == "p1-g2-comparison-crosscheck-report"
|
|
&& item.scene_name == "P1 G2 comparison crosscheck report"
|
|
&& item.assertions.required_default_mode == "comparison"
|
|
));
|
|
assert!(batch
|
|
.promoted_batch_expansion_baselines
|
|
.iter()
|
|
.any(|item| item.fixture_dir.ends_with("g2_diagnosis_drilldown")
|
|
&& item.scene_id == "p1-g2-diagnosis-drilldown-report"
|
|
&& item.scene_name == "P1 G2 diagnosis drilldown report"
|
|
&& item.assertions.required_default_mode == "diagnosis"));
|
|
assert!(batch
|
|
.promoted_batch_expansion_baselines
|
|
.iter()
|
|
.any(|item| item.fixture_dir.ends_with("g2_prediction_compute")
|
|
&& item.scene_id == "p1-g2-prediction-compute-report"
|
|
&& item.scene_name == "P1 G2 prediction compute report"
|
|
&& item.assertions.required_default_mode == "prediction"));
|
|
}
|
|
|
|
#[test]
|
|
fn g2_candidate_batch_keeps_promoted_candidates_visible() {
|
|
let batch = load_batch();
|
|
|
|
assert!(batch
|
|
.candidates
|
|
.iter()
|
|
.any(|item| item.scene_key == "tq_lineloss_report"
|
|
&& item.batch_role == "p0-anchor"
|
|
&& item.status == "promoted-baseline"));
|
|
assert!(batch
|
|
.candidates
|
|
.iter()
|
|
.any(|item| item.scene_key == "baiyin_lineloss_weekly"
|
|
&& item.batch_role == "first-expansion-anchor"
|
|
&& item.status == "promoted-expansion"));
|
|
assert!(batch
|
|
.candidates
|
|
.iter()
|
|
.any(|item| item.scene_key == "predicted_compute_variant"
|
|
&& item.batch_role == "fifth-expansion-anchor"
|
|
&& item.status == "promoted-expansion"));
|
|
}
|
|
|
|
fn load_batch() -> G2CandidateBatch {
|
|
serde_json::from_str(
|
|
&fs::read_to_string("tests/fixtures/generated_scene/g2_candidate_batch_2026-04-18.json")
|
|
.unwrap(),
|
|
)
|
|
.unwrap()
|
|
}
|