mod auditors;
mod cross_platform;
pub(crate) mod helpers;
mod hypothesis_driven;
mod invariants;
mod jidoka;
mod model_cards;
mod numerical_reproducibility;
mod performance_waste;
mod safety;
mod sovereign_data;
mod technical_debt;
mod types;
pub use auditors::*;
pub use cross_platform::evaluate_all as evaluate_cross_platform;
pub use hypothesis_driven::evaluate_all as evaluate_hypothesis_driven;
pub use invariants::*;
pub use jidoka::evaluate_all as evaluate_jidoka;
pub use model_cards::evaluate_all as evaluate_model_cards;
pub use numerical_reproducibility::evaluate_all as evaluate_numerical_reproducibility;
pub use performance_waste::evaluate_all as evaluate_performance_waste;
pub use safety::evaluate_all as evaluate_safety;
pub use sovereign_data::evaluate_all as evaluate_sovereign_data;
pub use technical_debt::evaluate_all as evaluate_technical_debt;
pub use types::*;
use std::path::Path;
pub fn evaluate_project(project_path: &Path) -> ChecklistResult {
let mut result = ChecklistResult::new(project_path);
let sovereign_results = sovereign_data::evaluate_all(project_path);
result.add_section("Sovereign Data Governance", sovereign_results);
let debt_results = technical_debt::evaluate_all(project_path);
result.add_section("ML Technical Debt Prevention", debt_results);
let hdd_results = hypothesis_driven::evaluate_all(project_path);
result.add_section("Hypothesis-Driven Development", hdd_results);
let nr_results = numerical_reproducibility::evaluate_all(project_path);
result.add_section("Numerical Reproducibility", nr_results);
let pw_results = performance_waste::evaluate_all(project_path);
result.add_section("Performance & Waste Elimination", pw_results);
let safety_results = safety::evaluate_all(project_path);
result.add_section("Safety & Formal Verification", safety_results);
let jidoka_results = jidoka::evaluate_all(project_path);
result.add_section("Jidoka Automated Gates", jidoka_results);
let mc_results = model_cards::evaluate_all(project_path);
result.add_section("Model Cards & Auditability", mc_results);
let cp_results = cross_platform::evaluate_all(project_path);
result.add_section("Cross-Platform & API", cp_results);
let invariant_results = invariants::evaluate_all(project_path);
result.add_section("Architectural Invariants", invariant_results);
result.finalize();
result
}
pub fn evaluate_critical_only(project_path: &Path) -> ChecklistResult {
let mut result = ChecklistResult::new(project_path);
let invariant_results = invariants::evaluate_all(project_path);
result.add_section("Architectural Invariants", invariant_results);
result.finalize();
result
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn test_fals_001_evaluate_project_returns_result() {
let path = PathBuf::from(".");
let result = evaluate_project(&path);
assert!(!result.sections.is_empty());
}
#[test]
fn test_fals_002_critical_only_returns_invariants() {
let path = PathBuf::from(".");
let result = evaluate_critical_only(&path);
assert!(result.sections.contains_key("Architectural Invariants"));
}
#[test]
fn test_fals_int_001_batuta_passes_critical_invariants() {
let path = PathBuf::from(".");
let result = evaluate_critical_only(&path);
let mut critical_count = 0;
for items in result.sections.values() {
for item in items {
if item.is_critical_failure() {
critical_count += 1;
}
}
}
assert!(!result.has_critical_failure, "batuta has {critical_count} critical failure(s)",);
}
#[test]
fn test_fals_int_002_batuta_achieves_kaizen_grade() {
let path = PathBuf::from(".");
let result = evaluate_critical_only(&path);
assert!(
result.grade.passes(),
"Expected Kaizen Required or better, got {} ({:.1}%)",
result.grade,
result.score
);
}
#[test]
fn test_fals_int_003_all_items_have_tps_principle() {
let path = PathBuf::from(".");
let result = evaluate_critical_only(&path);
for (section, items) in &result.sections {
for item in items {
assert!(
!item.tps_principle.is_empty(),
"Item {}.{} missing TPS principle",
section,
item.id
);
}
}
}
#[test]
fn test_fals_int_004_result_serializes_to_json() {
let path = PathBuf::from(".");
let result = evaluate_critical_only(&path);
let json = serde_json::to_string(&result);
let serialize_err = json.as_ref().err().map(|e| format!("{e:?}"));
assert!(json.is_ok(), "Failed to serialize result: {serialize_err:?}");
let json_str = json.expect("unexpected failure");
let parsed: Result<ChecklistResult, _> = serde_json::from_str(&json_str);
let parse_err = parsed.as_ref().err().map(|e| format!("{e:?}"));
assert!(parsed.is_ok(), "Failed to deserialize result: {parse_err:?}");
}
#[test]
fn test_fals_int_005_result_summary_format() {
let path = PathBuf::from(".");
let result = evaluate_critical_only(&path);
let summary = result.summary();
assert!(summary.contains('%'), "Summary missing percentage: {}", summary);
assert!(
summary.contains("passed") || summary.contains("RELEASE"),
"Summary missing status: {}",
summary
);
}
#[test]
fn test_fals_int_010_nonexistent_project() {
let path = PathBuf::from("/nonexistent/project/path");
let result = evaluate_critical_only(&path);
assert!(result.total_items > 0);
}
#[test]
fn test_fals_int_011_empty_directory() {
let temp_dir = std::env::temp_dir().join("batuta_test_empty");
let _ = std::fs::create_dir_all(&temp_dir);
let result = evaluate_critical_only(&temp_dir);
assert!(result.total_items > 0);
let _ = std::fs::remove_dir(&temp_dir);
}
#[test]
fn test_fals_mod_evaluate_project_all_sections() {
let path = PathBuf::from(".");
let result = evaluate_project(&path);
assert!(result.sections.len() >= 10);
assert!(result.sections.contains_key("Sovereign Data Governance"));
assert!(result.sections.contains_key("ML Technical Debt Prevention"));
assert!(result.sections.contains_key("Hypothesis-Driven Development"));
assert!(result.sections.contains_key("Numerical Reproducibility"));
assert!(result.sections.contains_key("Performance & Waste Elimination"));
assert!(result.sections.contains_key("Safety & Formal Verification"));
assert!(result.sections.contains_key("Jidoka Automated Gates"));
assert!(result.sections.contains_key("Model Cards & Auditability"));
assert!(result.sections.contains_key("Cross-Platform & API"));
assert!(result.sections.contains_key("Architectural Invariants"));
}
#[test]
fn test_fals_mod_result_finalize_counts() {
let path = PathBuf::from(".");
let result = evaluate_project(&path);
let expected_total: usize = result.sections.values().map(|v| v.len()).sum();
assert_eq!(result.total_items, expected_total);
assert!(result.passed_items + result.failed_items <= result.total_items);
}
#[test]
fn test_fals_mod_result_score_range() {
let path = PathBuf::from(".");
let result = evaluate_project(&path);
assert!(result.score >= 0.0);
assert!(result.score <= 100.0);
}
#[test]
fn test_fals_mod_result_passes_method() {
let path = PathBuf::from(".");
let result = evaluate_critical_only(&path);
assert_eq!(result.passes(), result.grade.passes() && !result.has_critical_failure);
}
#[test]
fn test_fals_mod_evaluate_project_nonexistent() {
let path = PathBuf::from("/nonexistent/project");
let result = evaluate_project(&path);
assert!(result.sections.len() >= 10);
assert!(result.total_items > 0);
}
#[test]
fn test_fals_mod_evaluate_project_temp_dir() {
let temp_dir = std::env::temp_dir().join("batuta_fals_mod_temp");
let _ = std::fs::create_dir_all(&temp_dir);
let result = evaluate_project(&temp_dir);
assert!(result.sections.len() >= 10);
assert!(result.score >= 0.0 && result.score <= 100.0);
let _ = std::fs::remove_dir(&temp_dir);
}
#[test]
fn test_fals_mod_critical_only_nonexistent() {
let path = PathBuf::from("/nonexistent/path/xyz");
let result = evaluate_critical_only(&path);
assert!(result.sections.contains_key("Architectural Invariants"));
assert!(result.score >= 0.0);
}
#[test]
fn test_fals_mod_critical_failure_format_chain() {
let mut result = ChecklistResult::new(std::path::Path::new("/test"));
result.add_section(
"Test",
vec![
CheckItem::new("CF-01", "Critical Test", "Critical claim")
.with_severity(Severity::Critical)
.with_tps("Jidoka")
.fail("Critical failure reason"),
CheckItem::new("OK-01", "Pass Test", "Pass claim").with_tps("Kaizen").pass(),
],
);
result.finalize();
let critical_failures: Vec<_> = result
.sections
.values()
.flat_map(|items| items.iter())
.filter(|i| i.is_critical_failure())
.map(|i| format!("{}: {}", i.id, i.rejection_reason.as_deref().unwrap_or("")))
.collect();
assert_eq!(critical_failures.len(), 1);
assert!(critical_failures[0].contains("CF-01"));
assert!(critical_failures[0].contains("Critical failure reason"));
}
}