repotoire 0.7.0

Graph-powered code analysis CLI. 110 detectors for security, architecture, bus factor, and code quality.
Documentation
//! Stage 7: Finding transforms (pure — no caching, no I/O, no presentation).

use crate::config::ProjectConfig;
use crate::graph::GraphQuery;
use crate::models::Finding;
use anyhow::Result;
use std::collections::HashSet;
use std::path::{Path, PathBuf};

/// Input for the postprocess stage. Takes ownership of findings.
pub struct PostprocessInput<'a> {
    pub findings: Vec<Finding>,
    pub project_config: &'a ProjectConfig,
    pub graph: &'a dyn GraphQuery,
    pub all_files: &'a [PathBuf],
    pub repo_path: &'a Path,
    pub verify: bool,
    /// Detector names that opt out of GBDT postprocessor filtering.
    pub bypass_set: HashSet<String>,
}

/// Statistics from the postprocess stage.
pub struct PostprocessStats {
    pub input_count: usize,
    pub output_count: usize,
    pub suppressed: usize,
    pub excluded: usize,
    pub deduped: usize,
    pub fp_filtered: usize,
    pub security_downgraded: usize,
}

/// Output from the postprocess stage.
pub struct PostprocessOutput {
    pub findings: Vec<Finding>,
    pub stats: PostprocessStats,
}

/// Run the postprocessing pipeline on findings.
///
/// Takes ownership of findings (every sub-step mutates the Vec).
pub fn postprocess_stage(input: PostprocessInput) -> Result<PostprocessOutput> {
    let input_count = input.findings.len();
    let mut findings = input.findings;

    let params = crate::cli::analyze::postprocess::PostprocessParams {
        project_config: input.project_config,
        all_files: input.all_files,
        graph: input.graph,
        repo_path: input.repo_path,
        bypass_set: &input.bypass_set,
        verify: input.verify,
    };
    crate::cli::analyze::postprocess::postprocess_findings(&mut findings, &params);

    let output_count = findings.len();
    let total_removed = input_count.saturating_sub(output_count);

    Ok(PostprocessOutput {
        findings,
        stats: PostprocessStats {
            input_count,
            output_count,
            suppressed: 0, // Individual breakdowns not available from existing function
            excluded: 0,
            deduped: 0,
            fp_filtered: total_removed,
            security_downgraded: 0,
        },
    })
}