///|
/// Joined validation result used before execution or release.
pub(all) struct ReadinessReport {
catalog_diagnostics : Array[Diagnostic]
observation_diagnostics : Array[Diagnostic]
plan_diagnostics : Array[Diagnostic]
error_count : Int
warning_count : Int
ready : Bool
}
///|
fn append_diagnostics(
target : Array[Diagnostic],
source : Array[Diagnostic],
) -> Array[Diagnostic] {
for diagnostic in source {
target.push(diagnostic)
}
target
}
///|
/// Assess catalog, plan, and observation readiness together.
pub fn assess_readiness(
features~ : Array[Feature],
devices~ : Array[Device],
plan~ : MeasurementPlan,
observations~ : Array[Observation],
) -> ReadinessReport {
let catalog_diagnostics = validate_catalog(features, devices)
let observation_diagnostics = validate_observations(features, observations)
let plan_diagnostics = validate_plan(plan, features)
let all = []
ignore(append_diagnostics(all, catalog_diagnostics))
ignore(append_diagnostics(all, observation_diagnostics))
ignore(append_diagnostics(all, plan_diagnostics))
let summary = validation_summary(all)
{
catalog_diagnostics,
observation_diagnostics,
plan_diagnostics,
error_count: summary.error_count,
warning_count: summary.warning_count,
ready: summary.is_valid && plan.summary.coverage >= 1.0,
}
}
///|
/// Return the number of readiness errors.
pub fn readiness_error_count(report : ReadinessReport) -> Int {
report.error_count
}
///|
/// Return the number of readiness warnings.
pub fn readiness_warning_count(report : ReadinessReport) -> Int {
report.warning_count
}
///|
/// Return a stable readiness label.
pub fn readiness_status(report : ReadinessReport) -> String {
if report.ready {
"ready"
} else if report.error_count > 0 {
"blocked"
} else {
"review"
}
}
///|
/// Return all readiness diagnostics in boundary order.
pub fn readiness_diagnostics(report : ReadinessReport) -> Array[Diagnostic] {
let result = []
ignore(append_diagnostics(result, report.catalog_diagnostics))
ignore(append_diagnostics(result, report.observation_diagnostics))
ignore(append_diagnostics(result, report.plan_diagnostics))
result
}
///|
/// Render readiness as stable key-value text.
pub fn render_readiness(report : ReadinessReport) -> String {
"status=" +
readiness_status(report) +
" errors=" +
report.error_count.to_string() +
" warnings=" +
report.warning_count.to_string()
}
///|
/// Return whether there are no readiness warnings or errors.
pub fn readiness_is_green(report : ReadinessReport) -> Bool {
report.ready && report.warning_count == 0
}
///|
/// Return whether readiness requires human review but is not blocked.
pub fn readiness_needs_review(report : ReadinessReport) -> Bool {
!report.ready && report.error_count == 0
}
///|
/// Return whether a readiness report has catalog errors.
pub fn readiness_catalog_is_valid(report : ReadinessReport) -> Bool {
!has_errors(report.catalog_diagnostics)
}
///|
/// Return whether a readiness report has plan errors.
pub fn readiness_plan_is_valid(report : ReadinessReport) -> Bool {
!has_errors(report.plan_diagnostics)
}