weavatrix-rust 1.0.2

Native repository intelligence for coding agents: 39 read-only MCP tools, evidence graph, cross-repository analysis, and lossless parsing
Documentation
#![cfg(feature = "git")]

use blazingly_json::json;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
use weavatrix_rust::{Weavatrix, tools};

static SEQUENCE: AtomicU64 = AtomicU64::new(0);

#[test]
fn compares_analyzed_worktree_with_immutable_git_objects() {
    let root = fixture();
    fs::create_dir_all(root.join("src")).unwrap();
    fs::write(root.join("src/lib.rs"), "pub fn existing() {}\n").unwrap();
    git(&root, &["add", "-A"]);
    git(
        &root,
        &[
            "-c",
            "user.name=Test",
            "-c",
            "user.email=test@example.invalid",
            "commit",
            "-qm",
            "baseline",
        ],
    );
    fs::write(
        root.join("src/lib.rs"),
        "pub fn existing() {}\npub fn added() { existing(); }\n",
    )
    .unwrap();

    let mut engine = Weavatrix::open(&root).unwrap();
    let result = tools::call(
        &mut engine,
        "graph_diff",
        json!({"base_ref": "HEAD", "max_results": 20}),
    )
    .unwrap();

    assert_eq!(result["completeness"], "COMPLETE_FOR_SUPPORTED_LANGUAGES");
    assert_eq!(result["source_mutation"], "NONE");
    assert_eq!(result["git_process"], "NONE");
    assert!(result["counts"]["nodes_added"].as_u64().unwrap() >= 1);
    assert_eq!(
        result["counts"]["nodes_changed"], 1,
        "only the file whose byte length changed is structurally different; hash formats must not mark every file"
    );
    assert_eq!(
        result["nodes"]["changed"][0]["after"]["id"],
        "file:src/lib.rs"
    );
    fs::remove_dir_all(root).ok();
}

#[test]
fn change_impact_uses_the_active_worktree_by_default() {
    let root = fixture();
    fs::create_dir_all(root.join("src")).unwrap();
    fs::write(root.join("src/lib.rs"), "pub fn existing() {}\n").unwrap();
    fs::write(root.join("src/removed.rs"), "pub fn removed() {}\n").unwrap();
    git(&root, &["add", "-A"]);
    git(
        &root,
        &[
            "-c",
            "user.name=Test",
            "-c",
            "user.email=test@example.invalid",
            "commit",
            "-qm",
            "baseline",
        ],
    );
    fs::write(
        root.join("src/lib.rs"),
        "pub fn existing() { changed(); }\npub fn changed() {}\n",
    )
    .unwrap();
    fs::remove_file(root.join("src/removed.rs")).unwrap();
    fs::write(root.join("src/added.rs"), "pub fn added() {}\n").unwrap();

    let mut engine = Weavatrix::open(&root).unwrap();
    let result = tools::call(&mut engine, "change_impact", json!({})).unwrap();
    let files = result["changed_files"]
        .as_array()
        .unwrap()
        .iter()
        .filter_map(blazingly_json::Value::as_str)
        .collect::<Vec<_>>();

    assert_eq!(result["git"]["head"], "WORKTREE");
    assert_eq!(
        files,
        ["src/added.rs", "src/lib.rs", "src/removed.rs"],
        "tracked, deleted and untracked supported sources are all included"
    );
    fs::remove_dir_all(root).ok();
}

#[test]
fn verified_change_passes_an_unchanged_worktree_without_running_processes() {
    let root = fixture();
    fs::create_dir_all(root.join("src")).unwrap();
    fs::write(root.join("src/lib.rs"), "pub fn stable() {}\n").unwrap();
    git(&root, &["add", "-A"]);
    git(
        &root,
        &[
            "-c",
            "user.name=Test",
            "-c",
            "user.email=test@example.invalid",
            "commit",
            "-qm",
            "baseline",
        ],
    );

    let mut engine = Weavatrix::open(&root).unwrap();
    let result = tools::call(
        &mut engine,
        "verified_change",
        json!({"task": "verify stable tree", "phase": "verify", "base_ref": "HEAD"}),
    )
    .unwrap();

    assert_eq!(result["verdict"], "PASS");
    assert_eq!(
        result["changeImpact"]["changed_files"]
            .as_array()
            .unwrap()
            .len(),
        0
    );
    assert_eq!(result["source_mutation"], "NONE");
    assert_eq!(result["test_execution"]["present"], false);
    assert_eq!(
        result["test_execution"]["reason"],
        "no test command was requested"
    );
    fs::remove_dir_all(root).ok();
}

fn fixture() -> PathBuf {
    let unique = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_nanos();
    let root = std::env::temp_dir().join(format!(
        "weavatrix-rust-git-diff-{}-{unique}-{}",
        std::process::id(),
        SEQUENCE.fetch_add(1, Ordering::Relaxed)
    ));
    fs::create_dir_all(&root).unwrap();
    git(&root, &["init", "-q"]);
    root
}

fn git(path: &Path, args: &[&str]) {
    let output = Command::new("git")
        .args(args)
        .current_dir(path)
        .output()
        .unwrap();
    assert!(
        output.status.success(),
        "{}",
        String::from_utf8_lossy(&output.stderr)
    );
}