use affidavit::chain::ChainAssembler;
use affidavit::ocel::{build_event, object_ref, SeqCounter};
use affidavit::quality::{QualityViolation, WesternElectricAnalyzer};
fn main() -> anyhow::Result<()> {
eprintln!("=== Quality Monitor Example ===\n");
eprintln!("Step 1: Measuring code quality from 'src' directory...");
let metrics = affidavit::quality::measure_code_quality("src")?;
eprintln!(" stub_ratio: {:.4}", metrics.stub_ratio);
eprintln!(
" cyclomatic_complexity: {:.4}",
metrics.cyclomatic_complexity
);
eprintln!(" clippy_warnings: {}", metrics.clippy_warnings);
eprintln!(" churn: {}", metrics.churn);
eprintln!(" test_coverage: {:.1}%\n", metrics.test_coverage);
eprintln!("Step 2: Creating Western Electric analyzer...");
let baseline_mean = 0.1;
let baseline_stddev = 0.05;
let window_size = 20;
let mut analyzer = WesternElectricAnalyzer::new(baseline_mean, baseline_stddev, window_size);
eprintln!(" baseline_mean: {:.4}", analyzer.baseline_mean);
eprintln!(" baseline_stddev: {:.4}", analyzer.baseline_stddev);
eprintln!(
" control_limits: ({:.4}, {:.4})\n",
analyzer.control_limits.0, analyzer.control_limits.1
);
eprintln!("Step 3: Adding synthetic measurements to rolling window...");
let synthetic_measurements = vec![
0.08, 0.09, 0.11, 0.10, 0.10, 0.11, 0.13, 0.15, 0.17, 0.19, 0.21, 0.08, 0.20, 0.09, 0.22, ];
for (i, &value) in synthetic_measurements.iter().enumerate() {
analyzer.add_measurement("stub_ratio", value);
eprintln!(" measurement[{}] = {:.4}", i, value);
}
eprintln!();
eprintln!("Step 4: Analyzing violations...");
eprintln!("Total violations detected: {}\n", analyzer.violations.len());
if !analyzer.violations.is_empty() {
eprintln!("Violations by severity:");
let mut critical_count = 0;
let mut high_count = 0;
let mut medium_count = 0;
let mut info_count = 0;
for violation in &analyzer.violations {
let severity = violation.severity();
match severity {
"CRITICAL" => critical_count += 1,
"HIGH" => high_count += 1,
"MEDIUM" => medium_count += 1,
"INFO" => info_count += 1,
_ => {}
}
}
if critical_count > 0 {
eprintln!(" CRITICAL: {}", critical_count);
}
if high_count > 0 {
eprintln!(" HIGH: {}", high_count);
}
if medium_count > 0 {
eprintln!(" MEDIUM: {}", medium_count);
}
if info_count > 0 {
eprintln!(" INFO: {}", info_count);
}
eprintln!();
eprintln!("Detailed violations:");
for (i, violation) in analyzer.violations.iter().enumerate() {
eprintln!(
" [{}] [{}] {}: {}",
i + 1,
violation.severity(),
violation.metric(),
violation.description()
);
}
} else {
eprintln!("No violations detected (all measurements within control limits)");
}
eprintln!();
eprintln!("Step 5: Emitting events to receipt chain...");
let mut counter = SeqCounter::new();
let mut assembler = ChainAssembler::new();
let measurement_payload = serde_json::json!({
"timestamp": metrics.timestamp,
"stub_ratio": metrics.stub_ratio,
"cyclomatic_complexity": metrics.cyclomatic_complexity,
"clippy_warnings": metrics.clippy_warnings,
"churn": metrics.churn,
"test_coverage": metrics.test_coverage,
"doc_coverage": metrics.doc_coverage,
"maintainability_index": metrics.maintainability_index,
})
.to_string();
let measurement_event = build_event(
"quality.measurement",
vec![object_ref("codebase", "src")],
measurement_payload.as_bytes(),
&mut counter,
)?;
assembler.append(measurement_event)?;
eprintln!(" emitted: quality.measurement");
for (i, violation) in analyzer.violations.iter().enumerate() {
let violation_payload = serde_json::json!({
"violation_id": i,
"metric": violation.metric(),
"severity": violation.severity(),
"description": violation.description(),
"rule": match violation {
QualityViolation::Rule1Sigma { .. } => "rule_1_sigma",
QualityViolation::Rule9InRow { .. } => "rule_9_in_a_row",
QualityViolation::RuleTrend { .. } => "rule_trend",
QualityViolation::RuleAlternating { .. } => "rule_alternating",
QualityViolation::Rule2of3Beyond2Sigma { .. } => "rule_2_of_3_beyond_2sigma",
QualityViolation::Rule4of5Beyond1Sigma { .. } => "rule_4_of_5_beyond_1sigma",
QualityViolation::Rule15InRowWithin1Sigma { .. } => "rule_15_in_a_row_within_1sigma",
},
}).to_string();
let violation_event = build_event(
"quality.violation",
vec![object_ref("metric", violation.metric())],
violation_payload.as_bytes(),
&mut counter,
)?;
assembler.append(violation_event)?;
eprintln!(" emitted: quality.violation ({})", violation.metric());
}
eprintln!();
eprintln!("Step 6: Finalizing receipt...");
let receipt = assembler.finalize();
eprintln!(" chain_hash: {}", receipt.chain_hash.as_hex());
eprintln!(" total events: {}\n", receipt.events.len());
eprintln!("Step 7: JSON output format:");
let json_output = serde_json::json!({
"monitor_session": "swarm_example",
"baseline": {
"mean": baseline_mean,
"stddev": baseline_stddev,
},
"measurements_count": synthetic_measurements.len(),
"violations_count": analyzer.violations.len(),
"violations": analyzer.violations.iter().map(|v| {
serde_json::json!({
"metric": v.metric(),
"severity": v.severity(),
"description": v.description(),
})
}).collect::<Vec<_>>(),
"receipt": {
"chain_hash": receipt.chain_hash.as_hex(),
"events_count": receipt.events.len(),
}
});
eprintln!("{}", serde_json::to_string_pretty(&json_output)?);
eprintln!();
eprintln!("=== Example Complete ===");
eprintln!("To run this example:");
eprintln!(" cargo run --example swarm_monitor");
eprintln!();
eprintln!("To use the monitor in production:");
eprintln!(" affi receipt monitor --watch . --metrics all --rules all --output stderr,json");
Ok(())
}