repopilot 0.13.0

Local-first CLI for repository audit, architecture risk detection, baseline tracking, and CI-friendly code review.
Documentation
use crate::findings::contract::{
    FindingContractReport, FindingContractViolation, FindingContractViolationKind,
};
use crate::scan::types::ScanDiagnostic;

pub fn finding_contract_diagnostics(report: &FindingContractReport) -> Vec<ScanDiagnostic> {
    if report.violations.is_empty() {
        return Vec::new();
    }

    let sample = report
        .violations
        .iter()
        .take(5)
        .map(describe_violation)
        .collect::<Vec<_>>()
        .join("; ");

    vec![ScanDiagnostic::warning(
        "finding.contract-violation",
        format!(
            "{} finding contract violation(s) across {} invalid finding(s): {}",
            report.violations.len(),
            report.invalid_findings,
            sample
        ),
    )]
}

fn describe_violation(violation: &FindingContractViolation) -> String {
    let rule_id = if violation.rule_id.trim().is_empty() {
        "<empty-rule>"
    } else {
        violation.rule_id.as_str()
    };
    let finding_id = if violation.finding_id.trim().is_empty() {
        "<empty-finding>"
    } else {
        violation.finding_id.as_str()
    };

    format!(
        "{rule_id}/{finding_id}: {}",
        violation_label(violation.violation)
    )
}

fn violation_label(kind: FindingContractViolationKind) -> &'static str {
    match kind {
        FindingContractViolationKind::EmptyId => "empty id",
        FindingContractViolationKind::EmptyRuleId => "empty rule id",
        FindingContractViolationKind::EmptyTitle => "empty title",
        FindingContractViolationKind::EmptyDescription => "empty description",
        FindingContractViolationKind::EmptyRecommendation => "empty recommendation",
        FindingContractViolationKind::MissingEvidence => "missing evidence",
        FindingContractViolationKind::InvalidEvidencePath => "invalid evidence path",
        FindingContractViolationKind::InvalidEvidenceLineRange => "invalid evidence line range",
        FindingContractViolationKind::MissingRiskFormulaVersion => "missing risk formula version",
        FindingContractViolationKind::MissingRiskSignals => "missing risk signals",
        FindingContractViolationKind::MissingDocsForHighSeverity => {
            "missing docs for high severity"
        }
    }
}