///|
/// One independently reviewable release criterion.
pub(all) struct ReleaseCheck {
name : String
passed : Bool
detail : String
}
///|
/// Evidence-backed readiness state for a measured part.
pub(all) struct ReleaseGate {
part_id : String
checks : Array[ReleaseCheck]
ready : Bool
risk : String
}
///|
fn release_check(name : String, passed : Bool, detail : String) -> ReleaseCheck {
{ name, passed, detail }
}
///|
fn feature_has_observation(
feature : Feature,
observations : Array[Observation],
) -> Bool {
for observation in observations {
if observation.feature_id == feature.id {
return true
}
}
false
}
///|
fn release_observation_coverage(
features : Array[Feature],
observations : Array[Observation],
) -> Double {
if features.length() == 0 {
1.0
} else {
let mut measured = 0
for feature in features {
if feature_has_observation(feature, observations) {
measured += 1
}
}
measured.to_double() / features.length().to_double()
}
}
///|
/// Evaluate the practical acceptance criteria for one plan and evidence set.
pub fn evaluate_release_gate(
plan : MeasurementPlan,
features : Array[Feature],
observations : Array[Observation],
) -> ReleaseGate {
let trace = build_audit_trace_with_features(plan~, features~, observations~)
let counts = audit_verdict_counts(trace)
let observation_coverage = release_observation_coverage(
features, observations,
)
let checks = [
release_check(
"plan coverage",
plan.summary.coverage >= 1.0,
"coverage=" + plan.summary.coverage.to_string(),
),
release_check(
"device capability",
plan.summary.capability,
if plan.summary.capability {
"all devices are capable"
} else {
"capability warning present"
},
),
release_check(
"observation coverage",
observation_coverage >= 1.0,
"coverage=" + observation_coverage.to_string(),
),
release_check(
"verdict completeness",
counts.2 == 0,
"unmeasured=" + counts.2.to_string(),
),
release_check(
"passing evidence",
counts.0 > 0 && counts.1 == 0,
"pass=" + counts.0.to_string() + " fail=" + counts.1.to_string(),
),
release_check(
"warning review",
plan.summary.warnings.length() == 0,
"warnings=" + plan.summary.warnings.length().to_string(),
),
]
let mut ready = true
for check in checks {
if !check.passed {
ready = false
}
}
let failures = failed_release_check_count_from_checks(checks)
{
part_id: plan.part_id,
checks,
ready,
risk: if failures == 0 {
"low"
} else if failures < 3 {
"medium"
} else {
"high"
},
}
}
///|
fn failed_release_check_count_from_checks(checks : Array[ReleaseCheck]) -> Int {
let mut result = 0
for check in checks {
if !check.passed {
result += 1
}
}
result
}
///|
/// Count failed release criteria.
pub fn failed_release_check_count(gate : ReleaseGate) -> Int {
failed_release_check_count_from_checks(gate.checks)
}
///|
/// Return a stable gate status for CLI and CI integration.
pub fn release_gate_status(gate : ReleaseGate) -> String {
if gate.ready {
"ready"
} else if gate.risk == "high" {
"blocked"
} else {
"review"
}
}
///|
/// Render every criterion and its evidence detail.
pub fn release_gate_text(gate : ReleaseGate) -> String {
let mut result = "part=" +
gate.part_id +
" status=" +
release_gate_status(gate) +
"\n"
for check in gate.checks {
let state = if check.passed { "pass" } else { "fail" }
result = result + state + " " + check.name + " " + check.detail + "\n"
}
result
}
///|
/// Return the names of criteria that need reviewer attention.
pub fn failed_release_check_names(gate : ReleaseGate) -> Array[String] {
let result = []
for check in gate.checks {
if !check.passed {
result.push(check.name)
}
}
result
}
///|
/// Return the number of passing criteria.
pub fn passed_release_check_count(gate : ReleaseGate) -> Int {
gate.checks.length() - failed_release_check_count(gate)
}
///|
/// Return whether every criterion has a non-empty evidence detail.
pub fn release_evidence_is_explained(gate : ReleaseGate) -> Bool {
let mut result = true
for check in gate.checks {
if check.detail.trim() == "" {
result = false
}
}
result
}