lean-ctx 3.7.1

Context Runtime for AI Agents with CCP. 63 MCP tools, 10 read modes, 60+ compression patterns, cross-session memory (CCP), persistent AI knowledge with temporal facts + contradiction detection, multi-agent context sharing, LITM-aware positioning, AAAK compact format, adaptive compression with Thompson Sampling bandits. Supports 24+ AI tools. Reduces LLM token consumption by up to 99%.
Documentation
use crate::core::contextops::{self, ContextOps};

pub fn cmd_rules(args: &[String]) {
    let action = args.first().map_or("help", String::as_str);

    let Some(home) = dirs::home_dir() else {
        eprintln!("Error: could not determine home directory");
        std::process::exit(1);
    };

    let project_root = std::env::current_dir().unwrap_or_else(|_| home.clone());
    let ops = ContextOps::new(&home, &project_root);

    match action {
        "sync" => cmd_sync(&ops, args),
        "diff" => cmd_diff(&ops),
        "lint" => cmd_lint(&ops),
        "status" => cmd_status(&ops),
        "init" => cmd_init(&ops),
        "help" | "--help" | "-h" => print_help(),
        _ => {
            eprintln!("Unknown rules action: {action}");
            print_help();
            std::process::exit(1);
        }
    }
}

fn cmd_sync(ops: &ContextOps, args: &[String]) {
    let agent = args.get(1).map(String::as_str);

    let report = if let Some(agent_name) = agent {
        println!("Syncing rules for {agent_name}...");
        ops.sync_agent(agent_name)
    } else {
        println!("Syncing rules to all detected agents...");
        ops.sync_all()
    };

    println!("{}", contextops::format_sync(&report));

    if !report.errors.is_empty() {
        std::process::exit(1);
    }
}

fn cmd_diff(ops: &ContextOps) {
    match ops.detect_drift() {
        Ok(reports) => {
            println!("{}", contextops::format_drift(&reports));

            let drifted = reports
                .iter()
                .filter(|r| r.status == contextops::DriftStatus::Drifted)
                .count();
            if drifted > 0 {
                println!("\n{drifted} target(s) drifted. Run `lean-ctx rules sync` to fix.");
            }
        }
        Err(e) => {
            eprintln!("Error: {e}");
            println!("\nFalling back to status-based drift check...");
            let statuses = ops.status();
            let outdated: Vec<_> = statuses.iter().filter(|s| s.state == "outdated").collect();
            if outdated.is_empty() {
                println!("All detected targets appear up to date.");
            } else {
                for s in &outdated {
                    println!("  [OUTDATED] {} ({})", s.name, s.path);
                }
            }
        }
    }
}

fn cmd_lint(ops: &ContextOps) {
    match ops.lint() {
        Ok(warnings) => {
            println!("{}", contextops::format_lint(&warnings));
            let errors = warnings
                .iter()
                .filter(|w| w.severity == contextops::LintSeverity::Error)
                .count();
            if errors > 0 {
                std::process::exit(1);
            }
        }
        Err(e) => {
            eprintln!("Error: {e}");
            eprintln!("Run `lean-ctx rules init` first to create .leanctx/rules.toml");
            std::process::exit(1);
        }
    }
}

fn cmd_status(ops: &ContextOps) {
    let statuses = ops.status();
    println!("{}", contextops::format_status(&statuses));

    let has_config = ops.has_config();
    println!();
    if has_config {
        println!("Central config: ✓ (.leanctx/rules.toml)");
    } else {
        println!("Central config: ✗ (run `lean-ctx rules init` to create)");
    }
}

fn cmd_init(ops: &ContextOps) {
    if ops.has_config() {
        eprintln!("Config already exists at .leanctx/rules.toml");
        eprintln!("Delete it first if you want to reinitialize.");
        std::process::exit(1);
    }

    match ops.init() {
        Ok(_config) => {
            println!("Created .leanctx/rules.toml from existing rules.");
            println!();
            println!("Next steps:");
            println!("  1. Review .leanctx/rules.toml");
            println!("  2. Run `lean-ctx rules lint` to check consistency");
            println!("  3. Run `lean-ctx rules sync` to distribute");
        }
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}

fn print_help() {
    eprintln!(
        "lean-ctx rules — Cross-agent rules governance (ContextOps)\n\
         \n\
         USAGE:\n    \
             lean-ctx rules <action> [args]\n\
         \n\
         ACTIONS:\n    \
             sync [agent]      Sync central rules to all (or one) agent config(s)\n    \
             diff              Show drift between central and distributed rules\n    \
             lint              Check rules for consistency and completeness\n    \
             status            Show sync status for all targets\n    \
             init              Create .leanctx/rules.toml from existing rules\n    \
             help              Show this help"
    );
}