weavatrix-rust 2.1.1

Protocol-independent Rust repository intelligence: typed evidence graphs for impact, architecture, APIs, Git, search, and memory
Documentation
#[allow(dead_code)]
mod support;

use blazingly_json::{Value, json};
use support::GitFixture;
use weavatrix_rust::{Weavatrix, tools};

#[test]
fn oversized_file_and_function_budgets_block_with_stable_evidence() {
    let fixture = GitFixture::new();
    fixture.write(
        "src/large.rs",
        "pub fn large() {\n\
         let one = 1;\n\
         let two = 2;\n\
         let three = 3;\n\
         let four = 4;\n\
         let _sum = one + two + three + four;\n\
         }\n",
    );
    fixture.write(".weavatrix/architecture.json", &contract(5, 3, 0));

    let mut engine = Weavatrix::open(&fixture.root).unwrap();
    let first = tools::call(&mut engine, "verify_architecture", json!({})).unwrap();
    let second = tools::call(&mut engine, "verify_architecture", json!({})).unwrap();

    assert_eq!(first["state"], "BLOCKED");
    assert_eq!(first["enforceable"], true);
    assert_eq!(fingerprints(&first), fingerprints(&second));
    let file = violation(&first, "budget.maxFileLoc");
    assert_eq!(file["evidence"]["file"], "src/large.rs");
    assert_eq!(file["evidence"]["actual"], 7);
    assert_eq!(file["evidence"]["maximum"], 5);
    let function = violation(&first, "budget.maxFunctionLoc");
    assert_eq!(function["evidence"]["file"], "src/large.rs");
    assert_eq!(function["evidence"]["symbol"], "large");
    assert_eq!(function["evidence"]["actual"], 7);
    assert_eq!(function["evidence"]["maximum"], 3);
}

#[test]
fn runtime_cycle_budget_blocks_with_cycle_evidence() {
    let fixture = GitFixture::new();
    fixture.write(
        "src/a.ts",
        "import { b } from './b';\nexport function a() { return b(); }\n",
    );
    fixture.write(
        "src/b.ts",
        "import { a } from './a';\nexport function b() { return a(); }\n",
    );
    fixture.write(".weavatrix/architecture.json", &contract(20, 10, 0));

    let mut engine = Weavatrix::open(&fixture.root).unwrap();
    let report = tools::call(&mut engine, "verify_architecture", json!({})).unwrap();

    assert_eq!(report["state"], "BLOCKED");
    let cycle = violation(&report, "budget.runtimeCycles");
    assert_eq!(cycle["evidence"]["actual"], 1);
    assert_eq!(cycle["evidence"]["maximum"], 0);
    assert_eq!(
        cycle["evidence"]["cycles"],
        json!([["file:src/a.ts", "file:src/b.ts"]])
    );
}

#[test]
fn compliant_fixture_passes_every_budget() {
    let fixture = GitFixture::new();
    fixture.write("src/lib.rs", "pub fn answer() -> u32 {\n    42\n}\n");
    fixture.write(".weavatrix/architecture.json", &contract(10, 5, 0));

    let mut engine = Weavatrix::open(&fixture.root).unwrap();
    let report = tools::call(&mut engine, "verify_architecture", json!({})).unwrap();

    assert_eq!(report["state"], "PASS");
    assert_eq!(report["enforceable"], true);
    assert_eq!(report["new"], json!([]));
}

#[test]
fn missing_contract_remains_explicitly_not_configured() {
    let fixture = GitFixture::new();
    fixture.write("src/lib.rs", "pub fn answer() -> u32 { 42 }\n");

    let mut engine = Weavatrix::open(&fixture.root).unwrap();
    let report = tools::call(&mut engine, "verify_architecture", json!({})).unwrap();

    assert_eq!(report["state"], "NOT_CONFIGURED");
    assert_eq!(report["enforceable"], false);
    assert_eq!(report["starter"]["budgets"]["maxFileLoc"], 300);
    assert_eq!(report["starter"]["budgets"]["maxFunctionLoc"], 100);
    assert_eq!(report["starter"]["budgets"]["runtimeCycles"], 0);
}

#[test]
fn malformed_budget_is_rejected_instead_of_silently_skipped() {
    let fixture = GitFixture::new();
    fixture.write("src/lib.rs", "pub fn answer() -> u32 { 42 }\n");
    fixture.write(
        ".weavatrix/architecture.json",
        r#"{
          "components": [{"id": "src", "paths": ["src"]}],
          "dependencyRules": [],
          "budgets": {"maxFileLoc": "three hundred"}
        }"#,
    );

    let mut engine = Weavatrix::open(&fixture.root).unwrap();
    let error = tools::call(&mut engine, "verify_architecture", json!({}))
        .expect_err("invalid budgets must fail closed");

    assert!(error.contains("maxFileLoc"));
    assert!(error.contains("non-negative integer"));
}

fn contract(max_file: u64, max_function: u64, runtime_cycles: u64) -> String {
    format!(
        r#"{{
          "components": [{{"id": "src", "paths": ["src"]}}],
          "dependencyRules": [],
          "budgets": {{
            "maxFileLoc": {max_file},
            "maxFunctionLoc": {max_function},
            "runtimeCycles": {runtime_cycles}
          }},
          "ratchet": {{"baseline": {{"fingerprints": []}}}}
        }}"#
    )
}

fn violation<'report>(report: &'report Value, rule: &str) -> &'report Value {
    report["new"]
        .as_array()
        .unwrap()
        .iter()
        .find(|item| item["rule"]["id"] == rule)
        .unwrap_or_else(|| panic!("missing violation for {rule}: {report}"))
}

fn fingerprints(report: &Value) -> Vec<&str> {
    report["new"]
        .as_array()
        .unwrap()
        .iter()
        .filter_map(|item| item["fingerprint"].as_str())
        .collect()
}