use crate::system_check::category::CheckCategory;
use crate::system_check::check::SystemCheck;
use crate::system_check::id::CheckId;
use crate::system_check::report::{CheckResult, CheckStatus};
use crate::system_check::severity::CheckSeverity;
struct FrameworkVersionCheck;
impl SystemCheck for FrameworkVersionCheck {
fn id(&self) -> CheckId {
CheckId::new_unchecked("ARC0001")
}
fn severity(&self) -> CheckSeverity {
CheckSeverity::Error
}
fn category(&self) -> CheckCategory {
CheckCategory::Framework
}
fn description(&self) -> &'static str {
"framework version is recorded as a non-empty YBF string"
}
fn run(&self) -> CheckResult {
let version = crate::FRAMEWORK_VERSION;
if version.is_empty() {
return CheckResult {
id: self.id(),
category: self.category(),
severity: self.severity(),
status: CheckStatus::Fail,
description: self.description(),
context: "FRAMEWORK_VERSION is empty".to_string(),
fix_hint: Some(
"the arcature crate's CARGO_PKG_VERSION is empty; rebuild with a real version"
.to_string(),
),
};
}
if !is_plausible_ybf(version) {
return CheckResult {
id: self.id(),
category: self.category(),
severity: self.severity(),
status: CheckStatus::Fail,
description: self.description(),
context: format!("FRAMEWORK_VERSION is not a YBF version: {version}"),
fix_hint: Some(
"expected YEAR.BREAK.FIX (e.g. 2026.1.0); rebuild with a real YBF version"
.to_string(),
),
};
}
CheckResult {
id: self.id(),
category: self.category(),
severity: self.severity(),
status: CheckStatus::Pass,
description: self.description(),
context: format!("framework {version}"),
fix_hint: None,
}
}
}
#[cfg(feature = "observe")]
struct SpanContractCheck;
#[cfg(feature = "observe")]
impl SystemCheck for SpanContractCheck {
fn id(&self) -> CheckId {
CheckId::new_unchecked("ARC0002")
}
fn severity(&self) -> CheckSeverity {
CheckSeverity::Warning
}
fn category(&self) -> CheckCategory {
CheckCategory::Observability
}
fn description(&self) -> &'static str {
"stable Arcature span-name contract is non-empty"
}
fn run(&self) -> CheckResult {
let spans = crate::observe::spans::ALL;
if spans.is_empty() {
return CheckResult {
id: self.id(),
category: self.category(),
severity: self.severity(),
status: CheckStatus::Fail,
description: self.description(),
context: "the span-name contract is empty".to_string(),
fix_hint: Some(
"arcature-observe's spans::ALL is empty; the Inspector and MCP traces tool \
will have no spans to correlate"
.to_string(),
),
};
}
CheckResult {
id: self.id(),
category: self.category(),
severity: self.severity(),
status: CheckStatus::Pass,
description: self.description(),
context: format!("{} stable span names registered", spans.len()),
fix_hint: None,
}
}
}
fn is_plausible_ybf(version: &str) -> bool {
let parts: Vec<&str> = version.split('.').collect();
parts.len() == 3
&& parts
.iter()
.all(|p| !p.is_empty() && p.bytes().all(|b| b.is_ascii_digit()))
}
pub const CHECKS: &[&dyn SystemCheck] = {
&[
&FrameworkVersionCheck,
#[cfg(feature = "observe")]
&SpanContractCheck,
]
};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn framework_version_check_passes_on_a_real_ybf_version() {
let check = FrameworkVersionCheck;
let result = check.run();
assert_eq!(result.id.as_str(), "ARC0001");
assert_eq!(result.status, CheckStatus::Pass, "{}", result.context);
assert!(result.context.contains("framework"));
}
#[test]
fn framework_version_check_fails_on_empty_version() {
assert!(!is_plausible_ybf(""));
assert!(!is_plausible_ybf("2026.1"));
assert!(!is_plausible_ybf("2026.1.0.0"));
assert!(!is_plausible_ybf("v2026.1.0"));
assert!(is_plausible_ybf("2026.1.0"));
assert!(is_plausible_ybf("2026.12.999"));
}
#[test]
fn checks_slice_is_non_empty_and_well_formed() {
assert!(!CHECKS.is_empty());
for check in CHECKS {
assert!(crate::system_check::id::CheckId::new(check.id().as_str()).is_ok());
assert!(!check.description().is_empty());
}
}
#[cfg(feature = "observe")]
#[test]
fn span_contract_check_passes_when_observe_is_enabled() {
let check = SpanContractCheck;
let result = check.run();
assert_eq!(result.id.as_str(), "ARC0002");
assert_eq!(result.status, CheckStatus::Pass);
assert!(result.context.contains("span names"));
}
}