166 lines
4.7 KiB
Rust
166 lines
4.7 KiB
Rust
use std::fs;
|
|
|
|
use serde::Deserialize;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct RoadmapExecutionStatus {
|
|
#[serde(rename = "statusDate")]
|
|
status_date: String,
|
|
plan: String,
|
|
#[serde(rename = "derivedFrom")]
|
|
derived_from: DerivedFrom,
|
|
#[serde(rename = "phaseStatus")]
|
|
phase_status: Vec<PhaseStatus>,
|
|
#[serde(rename = "trackStatus")]
|
|
track_status: Vec<TrackStatus>,
|
|
#[serde(rename = "boundaryStatus")]
|
|
boundary_status: Vec<GroupStatus>,
|
|
#[serde(rename = "deferredStatus")]
|
|
deferred_status: Vec<GroupStatus>,
|
|
notes: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct DerivedFrom {
|
|
#[serde(rename = "familyPolicy")]
|
|
family_policy: String,
|
|
#[serde(rename = "familyResults")]
|
|
family_results: String,
|
|
#[serde(rename = "ledgerSnapshot")]
|
|
ledger_snapshot: String,
|
|
#[serde(rename = "ledgerStatusOverlay")]
|
|
ledger_status_overlay: String,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct PhaseStatus {
|
|
phase: String,
|
|
status: String,
|
|
notes: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct TrackStatus {
|
|
track: String,
|
|
group: String,
|
|
status: String,
|
|
#[serde(rename = "completedItems")]
|
|
completed_items: Vec<String>,
|
|
#[serde(rename = "remainingItems")]
|
|
remaining_items: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct GroupStatus {
|
|
group: String,
|
|
status: String,
|
|
}
|
|
|
|
#[test]
|
|
fn roadmap_execution_status_asset_is_actionable() {
|
|
let status = load_status();
|
|
|
|
assert_eq!(status.status_date, "2026-04-18");
|
|
assert!(status.plan.ends_with(".md"));
|
|
assert!(status.derived_from.family_policy.ends_with(".json"));
|
|
assert!(status.derived_from.family_results.ends_with(".json"));
|
|
assert!(status.derived_from.ledger_snapshot.ends_with(".json"));
|
|
assert!(status.derived_from.ledger_status_overlay.ends_with(".json"));
|
|
assert_eq!(status.phase_status.len(), 5);
|
|
assert_eq!(status.track_status.len(), 5);
|
|
assert_eq!(status.boundary_status.len(), 3);
|
|
assert_eq!(status.deferred_status.len(), 2);
|
|
assert!(!status.notes.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn roadmap_execution_status_tracks_mainline_progress() {
|
|
let status = load_status();
|
|
|
|
let phase4 = status
|
|
.phase_status
|
|
.iter()
|
|
.find(|item| item.phase == "Phase 4")
|
|
.expect("expected phase 4 status");
|
|
assert_eq!(phase4.status, "in_progress");
|
|
assert!(!phase4.notes.is_empty());
|
|
|
|
let track_a = status
|
|
.track_status
|
|
.iter()
|
|
.find(|item| item.track == "Track A")
|
|
.expect("expected track A");
|
|
assert_eq!(track_a.group, "G2");
|
|
assert_eq!(track_a.status, "batch-expansion-promoted");
|
|
assert!(track_a
|
|
.completed_items
|
|
.iter()
|
|
.any(|item| item == "five-promoted-expansions"));
|
|
assert!(track_a.remaining_items.is_empty());
|
|
|
|
let track_b = status
|
|
.track_status
|
|
.iter()
|
|
.find(|item| item.track == "Track B")
|
|
.expect("expected track B");
|
|
assert_eq!(track_b.group, "G1-E");
|
|
assert_eq!(track_b.status, "batch-expansion-promoted");
|
|
assert!(track_b
|
|
.completed_items
|
|
.iter()
|
|
.any(|item| item == "two-promoted-expansions"));
|
|
assert!(track_b.remaining_items.is_empty());
|
|
|
|
let track_c = status
|
|
.track_status
|
|
.iter()
|
|
.find(|item| item.track == "Track C")
|
|
.expect("expected track C");
|
|
assert_eq!(track_c.group, "G3");
|
|
assert_eq!(track_c.status, "batch-expansion-promoted");
|
|
assert!(track_c
|
|
.completed_items
|
|
.iter()
|
|
.any(|item| item == "ten-promoted-expansions"));
|
|
assert!(track_c.remaining_items.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn roadmap_execution_status_keeps_boundary_and_deferred_scope_clear() {
|
|
let status = load_status();
|
|
|
|
assert!(status.boundary_status.iter().all(|item| {
|
|
matches!(item.group.as_str(), "G6" | "G7" | "G8")
|
|
&& item.status == "boundary-family-established"
|
|
}));
|
|
assert!(status
|
|
.deferred_status
|
|
.iter()
|
|
.any(|item| item.group == "G4" && item.status == "deferred"));
|
|
assert!(status
|
|
.deferred_status
|
|
.iter()
|
|
.any(|item| item.group == "G5" && item.status == "degraded"));
|
|
|
|
let track_e = status
|
|
.track_status
|
|
.iter()
|
|
.find(|item| item.track == "Track E")
|
|
.expect("expected track E");
|
|
assert_eq!(track_e.status, "status-overlay-established");
|
|
assert!(track_e
|
|
.completed_items
|
|
.iter()
|
|
.any(|item| item == "current-ledger-status-overlay"));
|
|
}
|
|
|
|
fn load_status() -> RoadmapExecutionStatus {
|
|
serde_json::from_str(
|
|
&fs::read_to_string(
|
|
"tests/fixtures/generated_scene/roadmap_execution_status_2026-04-18.json",
|
|
)
|
|
.unwrap(),
|
|
)
|
|
.unwrap()
|
|
}
|