kodegraf-cli 0.1.0

Structural code intelligence for AI coding assistants — CLI
use anyhow::Result;
use kodegraf_core::config::Config;
use kodegraf_core::graph::GraphStore;
use kodegraf_core::signals::analyzer::detect_patterns;
use kodegraf_core::signals::rules::{generate_rules, write_rules_to_claude_md};
use kodegraf_core::signals::store::SignalStore;

pub fn run() -> Result<()> {
    let repo_root = kodegraf_core::config::find_repo_root()?;
    let db_path = Config::graph_db_path(&repo_root);
    let claude_md_path = repo_root.join("CLAUDE.md");

    if !db_path.exists() {
        anyhow::bail!("Graph not built. Run `kodegraf init && kodegraf build` first.");
    }

    let store = GraphStore::open(&db_path)?;
    let signal_store = SignalStore::new(store.connection());

    let (total, _, _, _) = signal_store.get_total_counts()?;
    if total == 0 {
        println!("No signals collected yet. Rules are generated from DiffGuard failure data.");
        return Ok(());
    }

    let patterns = detect_patterns(store.connection(), 3)?;

    if patterns.is_empty() {
        println!("No recurring patterns found (minimum 3 occurrences required).");
        println!("Continue using DiffGuard to accumulate failure data.");
        return Ok(());
    }

    let rules = generate_rules(&patterns, 15);

    // Write rules to CLAUDE.md
    write_rules_to_claude_md(&rules, &claude_md_path)?;

    // Persist rules in the database
    for rule in &rules {
        signal_store.upsert_rule(rule)?;
    }

    println!("Generated {} rule(s) from {} pattern(s).", rules.len(), patterns.len());
    println!();
    for rule in &rules {
        println!("  {}", rule.rule_text);
    }
    println!();
    println!("Rules written to {}", claude_md_path.display());

    Ok(())
}