ripr 0.10.0

Find static mutation-exposure gaps before expensive mutation testing
Documentation
use crate::output;
use std::path::Path;

use super::super::{
    policy_readiness_generated_at, read_optional_manifest_for_report,
    read_optional_text_for_report, write_text_file,
};
use super::parse::{
    parse_policy_history_options, parse_policy_operations_options,
    parse_policy_preview_promotion_options, parse_policy_promotion_options,
    parse_policy_readiness_options, parse_policy_suppression_health_options,
    parse_policy_waiver_aging_options,
};

fn write_policy_report_files(
    out: &Path,
    out_md: &Path,
    rendered_json: &str,
    rendered_md: &str,
) -> Result<(), String> {
    write_text_file(out, rendered_json)?;
    write_text_file(out_md, rendered_md)?;
    println!("Wrote {}", out.display());
    println!("Wrote {}", out_md.display());
    Ok(())
}

pub(crate) fn policy_readiness(args: &[String]) -> Result<(), String> {
    let options = parse_policy_readiness_options(args)?;
    let input = output::policy_readiness::PolicyReadinessInput {
        root: options.root,
        generated_at: policy_readiness_generated_at()?,
        gate_decision_path: options
            .gate_decision
            .as_ref()
            .map(|path| output::policy_readiness::display_path(path)),
        baseline_delta_path: options
            .baseline_delta
            .as_ref()
            .map(|path| output::policy_readiness::display_path(path)),
        recommendation_calibration_path: options
            .recommendation_calibration
            .as_ref()
            .map(|path| output::policy_readiness::display_path(path)),
        mutation_calibration_path: options
            .mutation_calibration
            .as_ref()
            .map(|path| output::policy_readiness::display_path(path)),
        waiver_aging_path: options
            .waiver_aging
            .as_ref()
            .map(|path| output::policy_readiness::display_path(path)),
        suppression_health_path: options
            .suppression_health
            .as_ref()
            .map(|path| output::policy_readiness::display_path(path)),
        repo_config_path: options
            .repo_config
            .as_ref()
            .map(|path| output::policy_readiness::display_path(path)),
        previous_readiness_path: options
            .previous_readiness
            .as_ref()
            .map(|path| output::policy_readiness::display_path(path)),
        gate_decision_json: options
            .gate_decision
            .as_ref()
            .map(|path| read_optional_text_for_report("gate decision", path)),
        baseline_delta_json: options
            .baseline_delta
            .as_ref()
            .map(|path| read_optional_text_for_report("baseline debt delta", path)),
        recommendation_calibration_json: options
            .recommendation_calibration
            .as_ref()
            .map(|path| read_optional_text_for_report("recommendation calibration", path)),
        mutation_calibration_json: options
            .mutation_calibration
            .as_ref()
            .map(|path| read_optional_text_for_report("mutation calibration", path)),
        waiver_aging_json: options
            .waiver_aging
            .as_ref()
            .map(|path| read_optional_text_for_report("waiver aging", path)),
        suppression_health_json: options
            .suppression_health
            .as_ref()
            .map(|path| read_optional_text_for_report("suppression health", path)),
        repo_config_json: options
            .repo_config
            .as_ref()
            .map(|path| read_optional_text_for_report("repo config summary", path)),
        previous_readiness_json: options
            .previous_readiness
            .as_ref()
            .map(|path| read_optional_text_for_report("previous policy readiness", path)),
    };
    let report = output::policy_readiness::build_policy_readiness_report(input);
    let rendered_json = output::policy_readiness::render_policy_readiness_json(&report)?;
    let rendered_md = output::policy_readiness::render_policy_readiness_markdown(&report);
    write_policy_report_files(&options.out, &options.out_md, &rendered_json, &rendered_md)?;
    println!(
        "Status: {}",
        output::policy_readiness::policy_readiness_status(&report)
    );
    println!(
        "Recommended mode: {}",
        output::policy_readiness::policy_readiness_recommended_mode(&report)
    );
    Ok(())
}

pub(crate) fn policy_operations(args: &[String]) -> Result<(), String> {
    let options = parse_policy_operations_options(args)?;
    let input = output::policy_operations::PolicyOperationsInput {
        root: options.root,
        generated_at: policy_readiness_generated_at()?,
        policy_readiness_path: options
            .policy_readiness
            .as_ref()
            .map(|path| output::policy_operations::display_path(path)),
        waiver_aging_path: options
            .waiver_aging
            .as_ref()
            .map(|path| output::policy_operations::display_path(path)),
        suppression_health_path: options
            .suppression_health
            .as_ref()
            .map(|path| output::policy_operations::display_path(path)),
        baseline_delta_path: options
            .baseline_delta
            .as_ref()
            .map(|path| output::policy_operations::display_path(path)),
        gate_decision_path: options
            .gate_decision
            .as_ref()
            .map(|path| output::policy_operations::display_path(path)),
        recommendation_calibration_path: options
            .recommendation_calibration
            .as_ref()
            .map(|path| output::policy_operations::display_path(path)),
        mutation_calibration_path: options
            .mutation_calibration
            .as_ref()
            .map(|path| output::policy_operations::display_path(path)),
        preview_boundary_path: options
            .preview_boundary
            .as_ref()
            .map(|path| output::policy_operations::display_path(path)),
        policy_readiness_json: options
            .policy_readiness
            .as_ref()
            .map(|path| read_optional_text_for_report("policy readiness", path)),
        waiver_aging_json: options
            .waiver_aging
            .as_ref()
            .map(|path| read_optional_text_for_report("waiver aging", path)),
        suppression_health_json: options
            .suppression_health
            .as_ref()
            .map(|path| read_optional_text_for_report("suppression health", path)),
        baseline_delta_json: options
            .baseline_delta
            .as_ref()
            .map(|path| read_optional_text_for_report("baseline debt delta", path)),
        gate_decision_json: options
            .gate_decision
            .as_ref()
            .map(|path| read_optional_text_for_report("gate decision", path)),
        recommendation_calibration_json: options
            .recommendation_calibration
            .as_ref()
            .map(|path| read_optional_text_for_report("recommendation calibration", path)),
        mutation_calibration_json: options
            .mutation_calibration
            .as_ref()
            .map(|path| read_optional_text_for_report("mutation calibration", path)),
        preview_boundary_json: options
            .preview_boundary
            .as_ref()
            .map(|path| read_optional_text_for_report("preview boundary", path)),
    };
    let report = output::policy_operations::build_policy_operations_report(input);
    let rendered_json = output::policy_operations::render_policy_operations_json(&report)?;
    let rendered_md = output::policy_operations::render_policy_operations_markdown(&report);
    write_policy_report_files(&options.out, &options.out_md, &rendered_json, &rendered_md)?;
    println!(
        "Current ceiling: {}",
        output::policy_operations::policy_operations_current_ceiling(&report)
    );
    println!(
        "Next safe action: {}",
        output::policy_operations::policy_operations_next_action(&report)
    );
    Ok(())
}

pub(crate) fn policy_history(args: &[String]) -> Result<(), String> {
    let options = parse_policy_history_options(args)?;
    let input = output::policy_history::PolicyHistoryInput {
        root: options.root,
        generated_at: policy_readiness_generated_at()?,
        current_path: output::policy_history::display_path(&options.current),
        history_path: options
            .history
            .as_ref()
            .map(|path| output::policy_history::display_path(path)),
        commit: options.commit,
        pr_number: options.pr_number,
        current_json: read_optional_text_for_report("policy operations", &options.current),
        history_jsonl: options
            .history
            .as_ref()
            .map(|path| read_optional_text_for_report("policy history", path)),
    };
    let report = output::policy_history::build_policy_history_report(input);
    let rendered_json = output::policy_history::render_policy_history_json(&report)?;
    let rendered_md = output::policy_history::render_policy_history_markdown(&report);
    write_policy_report_files(&options.out, &options.out_md, &rendered_json, &rendered_md)?;
    println!(
        "Current ceiling: {}",
        output::policy_history::policy_history_current_ceiling(&report)
    );
    println!(
        "Readiness trend: {}",
        output::policy_history::policy_history_trend_direction(&report)
    );
    Ok(())
}

pub(crate) fn policy_promotion(args: &[String]) -> Result<(), String> {
    let options = parse_policy_promotion_options(args)?;
    let input = output::policy_promotion::PolicyPromotionInput {
        root: options.root,
        generated_at: policy_readiness_generated_at()?,
        target_mode: options.target_mode,
        operations_path: output::policy_promotion::display_path(&options.operations),
        history_path: options
            .history
            .as_ref()
            .map(|path| output::policy_promotion::display_path(path)),
        operations_json: read_optional_text_for_report("policy operations", &options.operations),
        history_json: options
            .history
            .as_ref()
            .map(|path| read_optional_text_for_report("policy history", path)),
    };
    let report = output::policy_promotion::build_policy_promotion_report(input);
    let rendered_json = output::policy_promotion::render_policy_promotion_json(&report)?;
    let rendered_md = output::policy_promotion::render_policy_promotion_markdown(&report);
    write_policy_report_files(&options.out, &options.out_md, &rendered_json, &rendered_md)?;
    println!(
        "Allowed now: {}",
        if output::policy_promotion::policy_promotion_allowed_now(&report) {
            "yes"
        } else {
            "no"
        }
    );
    Ok(())
}

pub(crate) fn policy_preview_promotion(args: &[String]) -> Result<(), String> {
    let options = parse_policy_preview_promotion_options(args)?;
    let input = output::policy_preview_promotion::PreviewPromotionInput {
        root: options.root,
        generated_at: policy_readiness_generated_at()?,
        language: options.language,
        candidate_class: options.candidate_class,
        evidence_path: options
            .evidence
            .as_ref()
            .map(|path| output::policy_preview_promotion::display_path(path)),
        evidence_json: options
            .evidence
            .as_ref()
            .map(|path| read_optional_text_for_report("preview promotion evidence", path)),
    };
    let report = output::policy_preview_promotion::build_preview_promotion_report(input);
    let rendered_json = output::policy_preview_promotion::render_preview_promotion_json(&report)?;
    let rendered_md = output::policy_preview_promotion::render_preview_promotion_markdown(&report);
    write_policy_report_files(&options.out, &options.out_md, &rendered_json, &rendered_md)?;
    println!(
        "Allowed now: {}",
        if output::policy_preview_promotion::preview_promotion_allowed_now(&report) {
            "yes"
        } else {
            "no"
        }
    );
    Ok(())
}

pub(crate) fn policy_waiver_aging(args: &[String]) -> Result<(), String> {
    let options = parse_policy_waiver_aging_options(args)?;
    let input = output::waiver_aging::WaiverAgingInput {
        root: options.root,
        generated_at: policy_readiness_generated_at()?,
        ledger_path: options
            .ledger
            .as_ref()
            .map(|path| output::waiver_aging::display_path(path)),
        history_path: options
            .history
            .as_ref()
            .map(|path| output::waiver_aging::display_path(path)),
        ledger_json: options
            .ledger
            .as_ref()
            .map(|path| read_optional_text_for_report("PR evidence ledger", path)),
        history_json: options
            .history
            .as_ref()
            .map(|path| read_optional_text_for_report("PR evidence ledger history", path)),
    };
    let report = output::waiver_aging::build_waiver_aging_report(input);
    let rendered_json = output::waiver_aging::render_waiver_aging_json(&report)?;
    let rendered_md = output::waiver_aging::render_waiver_aging_markdown(&report);
    write_policy_report_files(&options.out, &options.out_md, &rendered_json, &rendered_md)?;
    println!(
        "Status: {}",
        output::waiver_aging::waiver_aging_status(&report)
    );
    Ok(())
}

pub(crate) fn policy_suppression_health(args: &[String]) -> Result<(), String> {
    let options = parse_policy_suppression_health_options(args)?;
    let input = output::suppression_health::SuppressionHealthInput {
        root: output::suppression_health::display_path(&options.root),
        generated_at: policy_readiness_generated_at()?,
        today: output::suppressions::current_iso_date(),
        manifest_path: output::suppression_health::display_path(&options.manifest),
        manifest_text: read_optional_manifest_for_report(&options.root, &options.manifest),
    };
    let report = output::suppression_health::build_suppression_health_report(input);
    let rendered_json = output::suppression_health::render_suppression_health_json(&report)?;
    let rendered_md = output::suppression_health::render_suppression_health_markdown(&report);
    write_policy_report_files(&options.out, &options.out_md, &rendered_json, &rendered_md)?;
    println!(
        "Status: {}",
        output::suppression_health::suppression_health_status(&report)
    );
    Ok(())
}