weavatrix-rust 2.1.1

Protocol-independent Rust repository intelligence: typed evidence graphs for impact, architecture, APIs, Git, search, and memory
Documentation
mod language_fixture;

use blazingly_json::json;
use language_fixture::Fixture;
use weavatrix_rust::{Weavatrix, tools};

fn long_module() -> String {
    use std::fmt::Write;
    (1..=200).fold(String::new(), |mut module, index| {
        let _ = writeln!(module, "export const value{index} = {index};");
        module
    })
}

#[test]
fn read_source_trims_lines_to_the_requested_token_budget() {
    let fixture = Fixture::new();
    fixture.write("src/big.js", &long_module());
    let mut engine = Weavatrix::open(&fixture.root).unwrap();

    let unbudgeted = tools::call(
        &mut engine,
        "read_source",
        json!({"path": "src/big.js", "after": 150}),
    )
    .unwrap();
    assert!(
        unbudgeted.get("token_budget").is_none(),
        "without a budget the contract is unchanged"
    );
    let full_lines = unbudgeted["lines"].as_array().unwrap().len();

    let budgeted = tools::call(
        &mut engine,
        "read_source",
        json!({"path": "src/big.js", "after": 150, "token_budget": 300}),
    )
    .unwrap();
    let kept = budgeted["lines"].as_array().unwrap().len();
    assert!(
        kept < full_lines,
        "the budget must trim: {kept} vs {full_lines}"
    );
    assert!(kept > 0, "a 300-token budget holds some lines");
    assert_eq!(budgeted["token_budget"]["fit"], true);
    assert!(budgeted["token_budget"]["dropped_items"].as_u64().unwrap() > 0);
    assert_eq!(
        budgeted["end_line"],
        budgeted["lines"].as_array().unwrap().last().unwrap()["line"],
        "end_line reflects the trimmed answer"
    );

    assert!(
        tools::call(
            &mut engine,
            "read_source",
            json!({"path": "src/big.js", "token_budget": 0}),
        )
        .unwrap_err()
        .contains("token_budget"),
        "a zero budget is a caller error"
    );
}

#[test]
#[cfg(feature = "search")]
fn search_code_reports_budget_truncation_honestly() {
    let fixture = Fixture::new();
    fixture.write("src/big.js", &long_module());
    let mut engine = Weavatrix::open(&fixture.root).unwrap();

    let budgeted = tools::call(
        &mut engine,
        "search_code",
        json!({"query": "export const", "max_results": 100, "token_budget": 200}),
    )
    .unwrap();
    let kept = budgeted["matches"].as_array().unwrap().len();
    assert!(kept < 100, "the budget must trim the match list: {kept}");
    assert_eq!(budgeted["returned_matches"], kept as u64);
    assert_eq!(budgeted["totals"]["returned_matches"], kept as u64);
    assert_eq!(budgeted["truncated"], true);
    assert_eq!(budgeted["token_budget"]["fit"], true);
}

#[test]
fn context_bundle_and_query_graph_fit_their_budgets() {
    let fixture = Fixture::new();
    fixture.write("src/big.js", &long_module());
    fixture.write(
        "src/hub.js",
        "import { value1 } from './big.js';\nexport function hub(){ return value1; }\n",
    );
    let mut engine = Weavatrix::open(&fixture.root).unwrap();

    let bundle = tools::call(
        &mut engine,
        "context_bundle",
        json!({"label": "hub", "token_budget": 400}),
    )
    .unwrap();
    assert_eq!(bundle["token_budget"]["requested"], 400);
    assert!(bundle["token_budget"]["estimated_tokens"].as_u64().unwrap() <= 400);

    let graph = tools::call(
        &mut engine,
        "query_graph",
        json!({"seed_files": ["src/big.js"], "depth": 2, "max_nodes": 200, "token_budget": 250}),
    )
    .unwrap();
    assert!(graph["token_budget"]["estimated_tokens"].as_u64().unwrap() <= 250);
    assert_eq!(
        graph["truncated"], true,
        "dropping nodes or edges to fit a budget is truncation"
    );
}