///|
/// Stable quality-gate aggregation for local tooling and CI annotations.
pub(all) enum QualityGateKind {
Structural
Geometry
Materials
Resources
Runtime
Performance
} derive(Debug, ToJson, Eq)
///|
pub(all) enum QualityGateStatus {
Passed
Warning
Failed
Skipped
} derive(Debug, ToJson, Eq)
///|
pub(all) struct QualityGateCheck {
kind : QualityGateKind
name : String
status : QualityGateStatus
score : Double
findings : Array[String]
} derive(Debug, ToJson, Eq)
///|
pub(all) struct QualityGateMatrix {
checks : Array[QualityGateCheck]
passed : Int
warnings : Int
failed : Int
skipped : Int
score : Double
release_ready : Bool
} derive(Debug, ToJson, Eq)
///|
pub(all) struct QualityGatePolicy {
minimum_score : Double
allow_warnings : Bool
require_kinds : Array[QualityGateKind]
} derive(Debug, ToJson, Eq)
///|
pub fn quality_gate_kind_name(kind : QualityGateKind) -> String {
match kind {
Structural => "structural"
Geometry => "geometry"
Materials => "materials"
Resources => "resources"
Runtime => "runtime"
Performance => "performance"
}
}
///|
pub fn quality_gate_status_name(status : QualityGateStatus) -> String {
match status {
Passed => "passed"
Warning => "warning"
Failed => "failed"
Skipped => "skipped"
}
}
///|
pub fn quality_gate_check(
kind : QualityGateKind,
name : String,
status : QualityGateStatus,
score : Double,
findings : Array[String],
) -> QualityGateCheck {
{ kind, name, status, score, findings }
}
///|
pub fn default_quality_gate_policy() -> QualityGatePolicy {
{
minimum_score: 80.0,
allow_warnings: true,
require_kinds: [Structural, Geometry, Resources],
}
}
///|
pub fn quality_gate_matrix(
checks : Array[QualityGateCheck],
) -> QualityGateMatrix {
let mut passed = 0
let mut warnings = 0
let mut failed = 0
let mut skipped = 0
let mut score = 0.0
for check in checks {
score = score + check.score
match check.status {
Passed => passed = passed + 1
Warning => warnings = warnings + 1
Failed => failed = failed + 1
Skipped => skipped = skipped + 1
}
}
let evaluated = passed + warnings + failed
let average = if evaluated == 0 {
0.0
} else {
score / Double::from_int(evaluated)
}
{
checks,
passed,
warnings,
failed,
skipped,
score: average,
release_ready: failed == 0 && average >= 80.0,
}
}
///|
pub fn quality_gate_has_kind(
matrix : QualityGateMatrix,
kind : QualityGateKind,
) -> Bool {
matrix.checks.any(fn(check) { check.kind == kind })
}
///|
pub fn quality_gate_missing_kinds(
matrix : QualityGateMatrix,
required : Array[QualityGateKind],
) -> Array[String] {
required
.filter(fn(kind) { !quality_gate_has_kind(matrix, kind) })
.map(quality_gate_kind_name)
}
///|
pub fn quality_gate_release_check(
matrix : QualityGateMatrix,
policy : QualityGatePolicy,
) -> QualityGateMatrix {
let missing = quality_gate_missing_kinds(matrix, policy.require_kinds)
let checks = matrix.checks.copy()
if missing.length() > 0 {
checks.push(
quality_gate_check(
Structural,
"required gate coverage",
Failed,
0.0,
missing.map(fn(name) { "missing gate: \{name}" }),
),
)
}
let result = quality_gate_matrix(checks)
{
..result,
release_ready: result.failed == 0 &&
(policy.allow_warnings || result.warnings == 0) &&
result.score >= policy.minimum_score,
}
}
///|
pub fn quality_gate_summary_lines(matrix : QualityGateMatrix) -> Array[String] {
[
"checks=\{matrix.checks.length()}",
"passed=\{matrix.passed}",
"warnings=\{matrix.warnings}",
"failed=\{matrix.failed}",
"skipped=\{matrix.skipped}",
"score=\{matrix.score}",
"release_ready=\{matrix.release_ready}",
]
}