Files
claw/tests/g3_candidate_batch_test.rs

295 lines
12 KiB
Rust

use std::fs;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct G3CandidateBatch {
#[serde(rename = "batchId")]
batch_id: String,
family: String,
source: 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 = "firstExpansionBaseline")]
first_expansion_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 SharedContract {
archetype: String,
#[serde(rename = "requiredPaginationFields")]
required_pagination_fields: Vec<String>,
#[serde(rename = "requiredJoinKeyPatterns")]
required_join_key_patterns: Vec<String>,
#[serde(rename = "requiredAggregateRulePatterns")]
required_aggregate_rule_patterns: 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 = "expectedPaginationField")]
expected_pagination_field: String,
#[serde(rename = "requiredJoinKey")]
required_join_key: String,
#[serde(rename = "requiredAggregateRule")]
required_aggregate_rule: String,
}
#[derive(Debug, Deserialize)]
struct BatchCandidate {
#[serde(rename = "sceneKey")]
scene_key: String,
#[serde(rename = "ledgerGroupingResult")]
ledger_grouping_result: String,
#[serde(rename = "ledgerFamilyJudgement")]
ledger_family_judgement: String,
#[serde(rename = "batchRole")]
batch_role: String,
}
#[test]
fn g3_candidate_batch_asset_is_actionable() {
let batch = load_batch();
assert_eq!(
batch.batch_id,
"g3-95598-ticket-family-candidates-2026-04-18"
);
assert_eq!(batch.family, "G3");
assert!(batch.source.ends_with(".json"));
assert_eq!(batch.ledger_cluster_label, "95598-ticket-family-candidate");
assert!(batch
.selection_rule
.contains("95598-ticket-family-candidate"));
assert_eq!(batch.candidate_count, 11);
assert_eq!(
batch.expected_shared_contract.archetype,
"paginated_enrichment"
);
assert!(batch
.expected_shared_contract
.required_pagination_fields
.iter()
.any(|item| item == "pageNum"));
assert!(batch
.expected_shared_contract
.required_pagination_fields
.iter()
.any(|item| item == "pageNo"));
assert!(batch
.expected_shared_contract
.required_join_key_patterns
.iter()
.any(|item| item == "ticketNo"));
assert!(batch
.expected_shared_contract
.required_aggregate_rule_patterns
.iter()
.any(|item| item == "aggregate:riskLevel"));
assert_eq!(batch.candidates.len() as u32, batch.candidate_count);
assert_eq!(batch.promoted_batch_expansion_baselines.len(), 10);
assert!(!batch.notes.is_empty());
}
#[test]
fn g3_candidate_batch_promotes_second_round_expansion_baselines() {
let batch = load_batch();
assert!(batch
.promoted_batch_expansion_baselines
.iter()
.any(|item| item
.fixture_dir
.ends_with("paginated_enrichment_expansion_workorder")
&& item.scene_id == "p1-g3-paginated-expansion-workorder-report"
&& item.scene_name == "P1 G3 paginated expansion workorder report"
&& item.assertions.expected_pagination_field == "pageNo"
&& item.assertions.required_join_key == "workOrderNo"
&& item.assertions.required_aggregate_rule == "aggregate:sourceType"));
assert!(batch
.promoted_batch_expansion_baselines
.iter()
.any(|item| item
.fixture_dir
.ends_with("paginated_enrichment_expansion_orderno")
&& item.scene_id == "p1-g3-paginated-expansion-orderno-report"
&& item.scene_name == "P1 G3 paginated expansion orderno report"
&& item.assertions.expected_pagination_field == "page"
&& item.assertions.required_join_key == "orderNo"
&& item.assertions.required_aggregate_rule == "aggregate:sourceType"));
assert!(batch
.promoted_batch_expansion_baselines
.iter()
.any(|item| item
.fixture_dir
.ends_with("paginated_enrichment_expansion_source_distribution")
&& item.scene_id == "p1-g3-paginated-expansion-source-distribution-report"
&& item.scene_name == "P1 G3 paginated expansion source distribution report"
&& item.assertions.expected_pagination_field == "pageNum"
&& item.assertions.required_join_key == "ticketNo"
&& item.assertions.required_aggregate_rule == "aggregate:sourceType"));
assert!(batch
.promoted_batch_expansion_baselines
.iter()
.any(|item| item
.fixture_dir
.ends_with("paginated_enrichment_expansion_service_risk")
&& item.scene_id == "p1-g3-paginated-expansion-service-risk-report"
&& item.scene_name == "P1 G3 paginated expansion service risk report"
&& item.assertions.expected_pagination_field == "pageNo"
&& item.assertions.required_join_key == "ticketNo"
&& item.assertions.required_aggregate_rule == "aggregate:riskLevel"));
assert!(batch
.promoted_batch_expansion_baselines
.iter()
.any(|item| item
.fixture_dir
.ends_with("paginated_enrichment_expansion_timeout_warning")
&& item.scene_id == "p1-g3-paginated-expansion-timeout-warning-report"
&& item.scene_name == "P1 G3 paginated expansion timeout warning report"
&& item.assertions.expected_pagination_field == "pageNum"
&& item.assertions.required_join_key == "ticketNo"
&& item.assertions.required_aggregate_rule == "aggregate:riskLevel"));
assert!(batch
.promoted_batch_expansion_baselines
.iter()
.any(|item| item
.fixture_dir
.ends_with("paginated_enrichment_expansion_device_monitor_weekly")
&& item.scene_id == "p1-g3-paginated-expansion-device-monitor-weekly-report"
&& item.assertions.expected_pagination_field == "pageNo"
&& item.assertions.required_join_key == "ticketNo"
&& item.assertions.required_aggregate_rule == "aggregate:sourceType"));
assert!(batch
.promoted_batch_expansion_baselines
.iter()
.any(|item| item
.fixture_dir
.ends_with("paginated_enrichment_expansion_customer_satisfaction")
&& item.scene_id == "p1-g3-paginated-expansion-customer-satisfaction-report"
&& item.assertions.expected_pagination_field == "page"
&& item.assertions.required_join_key == "ticketNo"
&& item.assertions.required_aggregate_rule == "aggregate:sourceType"));
assert!(batch
.promoted_batch_expansion_baselines
.iter()
.any(|item| item
.fixture_dir
.ends_with("paginated_enrichment_expansion_repair_return")
&& item.scene_id == "p1-g3-paginated-expansion-repair-return-report"
&& item.assertions.expected_pagination_field == "pageNum"
&& item.assertions.required_join_key == "ticketNo"
&& item.assertions.required_aggregate_rule == "aggregate:riskLevel"));
assert!(batch
.promoted_batch_expansion_baselines
.iter()
.any(|item| item
.fixture_dir
.ends_with("paginated_enrichment_expansion_repair_daily_control")
&& item.scene_id == "p1-g3-paginated-expansion-repair-daily-control-report"
&& item.assertions.expected_pagination_field == "pageNo"
&& item.assertions.required_join_key == "ticketNo"
&& item.assertions.required_aggregate_rule == "aggregate:riskLevel"));
assert!(batch
.promoted_batch_expansion_baselines
.iter()
.any(|item| item
.fixture_dir
.ends_with("paginated_enrichment_expansion_business_stats")
&& item.scene_id == "p1-g3-paginated-expansion-business-stats-report"
&& item.assertions.expected_pagination_field == "page"
&& item.assertions.required_join_key == "ticketNo"
&& item.assertions.required_aggregate_rule == "aggregate:sourceType"));
}
#[test]
fn g3_candidate_batch_keeps_anchor_and_promoted_candidates_visible() {
let batch = load_batch();
assert!(batch
.candidates
.iter()
.any(|item| item.scene_key == "95598_ticket_detail" && item.batch_role == "p0-anchor"));
assert!(batch.candidates.iter().any(|item| {
item.scene_key == "95598_ticket_12398_process_timeout_detail"
&& item.batch_role == "first-expansion-anchor"
}));
assert!(batch.candidates.iter().any(|item| {
item.scene_key == "ticket_source_distribution_analysis"
&& item.batch_role == "fourth-expansion-anchor"
}));
assert!(batch.candidates.iter().any(|item| {
item.scene_key == "process_timeout_risk_ticket_detail"
&& item.batch_role == "fifth-expansion-anchor"
}));
assert!(batch.candidates.iter().any(|item| {
item.scene_key == "ticket_timeout_warning_detail"
&& item.batch_role == "sixth-expansion-anchor"
}));
assert!(batch.candidates.iter().any(|item| {
item.scene_key == "95598_ticket_12398_device_monitor_weekly"
&& item.batch_role == "seventh-expansion-anchor"
}));
assert!(batch.candidates.iter().any(|item| {
item.scene_key == "95598_ticket_customer_satisfaction_daily"
&& item.batch_role == "eighth-expansion-anchor"
}));
assert!(batch.candidates.iter().any(|item| {
item.scene_key == "95598_ticket_repair_return_analysis"
&& item.batch_role == "ninth-expansion-anchor"
}));
assert!(batch.candidates.iter().any(|item| {
item.scene_key == "95598_ticket_repair_daily_control"
&& item.batch_role == "tenth-expansion-anchor"
}));
assert!(batch.candidates.iter().any(|item| {
item.scene_key == "power_supply_service_ticket_business_stats"
&& item.batch_role == "eleventh-expansion-anchor"
}));
assert!(batch.candidates.iter().any(|item| {
item.scene_key == "service_risk_ticket_detail"
&& item.batch_role == "third-expansion-anchor"
}));
assert!(batch.candidates.iter().all(|item| {
item.ledger_grouping_result == "95598-ticket-family-candidate"
&& item.ledger_family_judgement == "pending-regroup"
}));
assert!(batch
.representative_baseline
.ends_with("paginated_enrichment"));
assert!(batch
.first_expansion_baseline
.ends_with("paginated_enrichment_expansion"));
}
fn load_batch() -> G3CandidateBatch {
serde_json::from_str(
&fs::read_to_string("tests/fixtures/generated_scene/g3_candidate_batch_2026-04-18.json")
.unwrap(),
)
.unwrap()
}