bctx-weave 0.1.16

bctx-weave — FilterMesh lens pipeline, CLI interception, domain compression
Documentation
use forge::signal::compactor;
use once_cell::sync::Lazy;
use regex::Regex;

#[allow(dead_code)]
static FILE_HEADER_RE: Lazy<Regex> = Lazy::new(||
    // "/path/to/file.ts" — standalone file path line in eslint output
    Regex::new(r"(?m)^/[^\n]+(\.ts|\.tsx|\.js|\.jsx|\.mjs|\.cjs)\n?").unwrap());

pub fn compress_eslint(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    // Already compact format; just collapse blanks + keep summary
    let lines: Vec<&str> = cleaned.lines().filter(|l| !l.trim().is_empty()).collect();
    if lines.len() <= 20 {
        return cleaned;
    }
    // Find summary line (usually last): "✖ N problems (X errors, Y warnings)"
    let summary: Option<&str> = lines
        .iter()
        .rev()
        .find(|l| l.contains("problem") || l.contains("error") || l.contains("warning"))
        .copied();
    // Keep first 20 finding lines + summary
    let mut out: Vec<&str> = lines[..20].to_vec();
    if lines.len() > 20 {
        out.push("...");
    }
    if let Some(s) = summary {
        out.push(s);
    }
    out.join("\n")
}

pub fn compress_eslint_grouped(raw: &str) -> String {
    compress_eslint(raw)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn eslint_keeps_summary() {
        let mut raw = String::new();
        for i in 0..30 {
            raw.push_str(&format!("  {}:1  error  no-unused-vars\n", i));
        }
        raw.push_str("✖ 30 problems (30 errors, 0 warnings)\n");
        let out = compress_eslint(&raw);
        assert!(out.contains("30 problems"), "{out}");
    }
}