Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

src/mimir_lens/room_feed/clone_tests.rs

//! The clone signals end to end over [`super::fixture::clones`]: the
//! `clone_shapes` feed, the normalised vectors, and the lenses asked the way a
//! front door asks them.

use serde_json::{Value, json};

use super::fixture::{self, clones as cx, vectors::Bag};

fn state(v: &Value) -> &str {
    v["lens_meta"]["state"].as_str().unwrap_or_else(|| panic!("no lens_meta.state: {v}"))
}

/// Every function id one finding names.
fn ids(item: &Value) -> Vec<String> {
    let mut out = Vec::new();
    fn walk(v: &Value, out: &mut Vec<String>) {
        match v {
            Value::Object(m) => {
                if let Some(Value::String(id)) = m.get("id") {
                    out.push(id.clone());
                }
                m.values().for_each(|x| walk(x, out));
            }
            Value::Array(a) => a.iter().for_each(|x| walk(x, out)),
            _ => {}
        }
    }
    walk(item, &mut out);
    out
}

/// The stable id of a fixture function (what the answers show; the version is an attribute).
fn sid(name: &str) -> String {
    mimir_schema::moniker::stable(&cx::clo(&format!("{name}()."))).into_owned()
}

/// The findings of a lens that name BOTH functions.
fn naming<'a>(v: &'a Value, a: &str, b: &str) -> Vec<&'a Value> {
    let (a, b) = (sid(a), sid(b));
    v["worst"].as_array().unwrap_or_else(|| panic!("no worst: {v}")).iter().filter(|f| ids(f).contains(&a) && ids(f).contains(&b)).collect()
}

fn found_by(f: &Value) -> String {
    f["found_by"].to_string()
}

fn cos(a: &[f32], b: &[f32]) -> f32 {
    crate::vector::pair_index::dot(a, b)
}

/// The same logic under unrelated names (`tally` / `summarize`: a consistent
/// rename, another layout, other comments) is ONE normalised body — an exact
/// clone — and the same structure; a copy with one statement more is a near
/// clone; `place` / `arrange` (other bodies) share only what they touch, and
/// signal 2 says so in words.
#[test]
fn identical_logic_under_unrelated_names_is_found_by_the_normalised_body_and_the_structure() {
    let _g = fixture::serial();
    let f = cx::build();
    let run = f.shapes();
    assert_eq!((run.functions, run.plus, run.minus, run.untokenised), (48, 48, 0, 0), "{run:?}");

    let v = f.ws.ask("exact_clones", json!({}));
    assert_eq!(state(&v), "complete", "{v}");
    let hit = naming(&v, "tally", "summarize");
    assert_eq!(hit.len(), 1, "{v}");
    assert!(found_by(hit[0]).contains("exact"), "{}", hit[0]);
    assert!(naming(&v, "tally", "tally_more").is_empty(), "a near copy is not an exact one");

    let v = f.ws.ask("near_clones", json!({}));
    let hit = naming(&v, "tally", "tally_more");
    assert_eq!(hit.len(), 1, "{v}");
    assert!(found_by(hit[0]).contains("near: MinHash"), "{}", hit[0]);

    let v = f.ws.ask("structural_clones", json!({}));
    assert!(["complete", "empty_fact"].contains(&state(&v)), "{v}");
    let hit = naming(&v, "tally", "summarize");
    assert_eq!(hit.len(), 1, "{v}");
    assert!(found_by(hit[0]).contains("structural"), "{}", hit[0]);
    // the owner's audit (2026-10-22): the same rare types and fields over
    // bodies that share under 0.3 of their text is a shared API, no clone
    assert!(naming(&v, "place", "arrange").is_empty(), "other bodies (MinHash < 0.3) are no structural clone: {v}");
    assert!(v.to_string().contains("of their normalised token runs (MinHash)"), "the left-out pairs are counted: {v}");
    // the common shape (`fn(&str) -> Result<(), Error>`, 30 of them) makes no pair
    assert!(naming(&v, "step0", "step1").is_empty(), "sharing only Result<()> and &str is not structure: {v}");
}

/// The raw model reads the names; the normalised model does not: for the
/// renamed copy the raw cosine is below the normalised one (which is 1: one
/// text), and `semantic_clones` reports it, saying it was held by signal 1.
#[test]
fn the_normalised_model_finds_the_renamed_copy_and_semantic_clones_states_its_signals() {
    let _g = fixture::serial();
    let f = cx::build();
    f.shapes();
    let bag = Bag::default();
    let norm = f.embed(&bag);
    assert!(norm.new_vectors > 0, "{norm:?}");
    let asked = bag.asked.lock().unwrap().clone();
    assert!(asked.iter().any(|t| t.starts_with("fn F1 ( V1 : & T1")), "the normalised texts went through the same embedder: {asked:?}");

    // raw vs normalised cosine of tally / summarize
    let (seq, _) = f.at();
    let read = crate::vector::fnvec::read(&f.ws.warehouse, &[(cx::CLO.to_string(), seq)].into()).unwrap();
    let raw = |name: &str| read.of(cx::CLO, &cx::clo(&format!("{name}()."))).unwrap().1.to_vec();
    let raw_cos = cos(&raw("tally"), &raw("summarize"));
    let n = |t: &str| crate::clone_signals::norm::normalize(t).unwrap().exact;
    let key = n(cx::TALLY);
    assert_eq!(key, n(cx::SUMMARIZE), "one normalised body");
    let keys: std::collections::HashSet<&str> = [key.as_str()].into();
    let (vecs, _) = f.ws.warehouse.block_on(crate::vector::store::read_vectors_present_in(&f.ws.warehouse, crate::warehouse::iceberg::TABLE_EMBEDDINGS_NORM, &read.model_profile, &keys)).unwrap();
    assert_eq!(vecs.len(), 1);
    assert!(raw_cos < 0.95, "the raw model sees the names: {raw_cos}");

    let v = f.ws.ask("semantic_clones", json!({}));
    assert_eq!(state(&v), "complete", "{v}");
    let hit = naming(&v, "tally", "summarize");
    assert_eq!(hit.len(), 1, "{v}");
    let by = found_by(hit[0]);
    assert!(by.contains("exact") && by.contains("normalised model"), "{by}");
    assert!(v["evidence_note"].as_str().unwrap().contains("AND signal 1"), "the rule is stated: {}", v["evidence_note"]);
}

/// `kill` and `delete`: alike in name, nothing alike in what they do — no
/// clone lens pairs them.
#[test]
fn kill_and_delete_with_different_bodies_are_not_clones() {
    let _g = fixture::serial();
    let f = cx::build();
    f.shapes();
    f.embed(&Bag::default());
    for lens in ["exact_clones", "near_clones", "structural_clones", "semantic_clones", "role_neighbours"] {
        let v = f.ws.ask(lens, json!({ "include_tests": true }));
        assert!(v["worst"].is_array(), "{lens}: {v}");
        assert!(naming(&v, "kill", "delete").is_empty(), "{lens} pairs kill/delete: {v}");
    }
}

/// A commit writes shapes only for the function whose body changed; the
/// lenses read the new state.
#[test]
fn a_commit_updates_only_the_function_that_changed() {
    let _g = fixture::serial();
    let f = cx::build();
    f.shapes();
    let again = f.shapes();
    assert_eq!((again.plus, again.minus), (0, 0), "nothing changed, nothing written: {again:?}");
    f.second_commit();
    let run = f.shapes();
    assert_eq!((run.functions, run.plus, run.minus), (48, 1, 0), "{run:?}");
    let events = crate::clone_signals::store::read(&f.ws.warehouse, &[cx::CLO]).unwrap();
    let (seq, _) = f.at();
    let at2: Vec<&str> = events.iter().filter(|e| e.seq == seq).map(|e| e.moniker.as_str()).collect();
    assert_eq!(at2, [mimir_schema::moniker::stable(&cx::clo("summarize().")).as_ref()]);
    let v = f.ws.ask("exact_clones", json!({}));
    assert!(naming(&v, "tally", "summarize").is_empty(), "summarize has another body now: {v}");
}

/// Every finding of every clone lens says which signal found it.
#[test]
fn every_clone_answer_says_which_signal_found_each_pair() {
    let _g = fixture::serial();
    let f = cx::build();
    f.shapes();
    f.embed(&Bag::default());
    for lens in ["exact_clones", "near_clones", "structural_clones", "role_neighbours", "semantic_clones", "same_intent", "semantic_twins"] {
        // the Bag is no language model: the model floors are lowered to test the shape of the answer
        let v = f.ws.ask(lens, if matches!(lens, "same_intent" | "semantic_twins") { json!({ "cosine": 0.65 }) } else { json!({}) });
        let worst = v["worst"].as_array().unwrap_or_else(|| panic!("{lens}: {v}"));
        assert!(!worst.is_empty(), "{lens} found nothing on the fixture: {v}");
        for w in worst {
            let by = w["found_by"].as_array().unwrap_or_else(|| panic!("{lens}: no found_by in {w}"));
            assert!(!by.is_empty(), "{lens}: {w}");
            assert!(w["why"].as_str().is_some_and(|y| !y.is_empty()), "{lens}: every finding has a plain why line: {w}");
            assert!(!ids(w).iter().any(|id| id.contains(" 0.1.0 ")), "{lens}: ids are stable (no version): {w}");
        }
    }
    let v = f.ws.ask("same_intent", json!({ "cosine": 0.65 }));
    assert_eq!(v["name_driven"], true);
    assert!(v["worst"].to_string().contains("NAME-DRIVEN"), "{v}");
    // nearest by role: the renamed copy is tally's role neighbour
    let v = f.ws.ask("role_neighbours", json!({}));
    assert!(!naming(&v, "tally", "summarize").is_empty(), "{v}");
}

/// `semantic_twins` on v1's theory: `tally` / `tally_more` read alike AND
/// touch the same things — a Type-3 COPY (cosine ≥ 0.92, structural ≥ 0.50);
/// `workspace_root` / `repo_root` read alike and touch other things — a
/// Type-4 TWIN (cosine ≥ floor, structural ≤ 0.35, mutual kNN); each says
/// why in a plain line. kill / delete is neither; the step fixtures and the
/// one-liners are left out, counted; the theory is in the note.
#[test]
fn semantic_twins_follow_v1s_gates_copy_and_twin_each_with_a_why_line() {
    let _g = fixture::serial();
    let f = cx::build();
    f.shapes();
    f.embed(&Bag::default());
    // the Bag is no language model: the Type-4 floor is lowered to test the RULE
    let v = f.ws.ask("semantic_twins", json!({ "cosine": 0.65, "limit": 500 }));
    assert_eq!(state(&v), "complete", "{v}");
    let t = &v["thresholds"];
    assert_eq!((t["copy_cosine"].as_f64(), t["copy_structural_floor"].as_f64(), t["twin_structural_ceiling"].as_f64(), t["mutual_k"].as_u64()), (Some(0.92f32 as f64), Some(0.5), Some(0.35f32 as f64), Some(8)), "{t}");
    let copy = naming(&v, "tally", "tally_more");
    assert_eq!(copy.len(), 1, "{v}");
    assert_eq!((copy[0]["kind"].as_str(), copy[0]["clone_type"].as_u64()), (Some("copy"), Some(3)), "{}", copy[0]);
    assert!(copy[0]["cosine"].as_f64().unwrap() >= 0.92 && copy[0]["structural"].as_f64().unwrap() >= 0.5, "{}", copy[0]);
    assert!(copy[0]["why"].as_str().unwrap().contains("read `.MapLayout"), "{}", copy[0]);
    // a twin within ONE file is the file's own rhythm (the owner's audit): left out, counted
    assert!(naming(&v, "workspace_root", "repo_root").is_empty(), "{v}");
    assert!(v["excluded"]["a twin pair within one file"].as_u64().is_some_and(|n| n >= 1), "{}", v["excluded"]);
    assert!(naming(&v, "kill", "delete").is_empty(), "{v}");
    let ex = v["excluded"].to_string();
    assert!(ex.contains("5-line span floor"), "the short step fixtures are counted out: {ex}");
    let note = v["evidence_note"].as_str().unwrap();
    assert!(note.contains("How it works:") && note.contains("0.882") && note.contains("ROC-AUC 0.920") && note.contains("mutual kNN"), "the theory is in the note: {note}");
    // at v1's floor the Bag's 0.70 is no twin
    let v = f.ws.ask("semantic_twins", json!({ "limit": 500 }));
    assert!(naming(&v, "workspace_root", "repo_root").is_empty(), "{v}");
    assert!(!naming(&v, "tally", "tally_more").is_empty(), "{v}");
}

/// One body on two types (`bump_alpha` / `bump_beta`: other params, other
/// callees, structure 0) is a COPY — the same normalised body — never a
/// Type-4 twin: a twin is written DIFFERENTLY (MinHash < 0.80).
#[test]
fn the_same_body_on_two_types_is_a_copy_not_a_twin() {
    let _g = fixture::serial();
    let f = cx::build();
    f.shapes();
    f.embed(&Bag::default());
    let v = f.ws.ask("semantic_twins", json!({ "limit": 500 }));
    let hit = naming(&v, "bump_alpha", "bump_beta");
    assert_eq!(hit.len(), 1, "{v}");
    assert_eq!((hit[0]["kind"].as_str(), hit[0]["clone_type"].as_u64()), (Some("copy"), Some(3)), "{}", hit[0]);
    assert!(hit[0]["why"].as_str().unwrap().contains("the same normalised body"), "{}", hit[0]);
    assert!(found_by(hit[0]).contains("body"), "{}", hit[0]);
    // every twin is written differently
    for t in v["worst"].as_array().unwrap().iter().filter(|x| x["kind"] == "twin") {
        assert!(t["body_similarity"].as_f64().is_some_and(|b| b < 0.8), "a twin with a same/near body: {t}");
    }
    assert!(v["evidence_note"].as_str().unwrap().contains("MinHash < 0.80"), "the rule is stated");
}

/// Two-feature accessors (`-> Option<bool>` reading one field) share all
/// they have — Jaccard 1.0 — but that is too little structure to say
/// anything: no structural pair, no role pair.
#[test]
fn two_feature_accessors_are_no_structural_or_role_pair() {
    let _g = fixture::serial();
    let f = cx::build();
    f.shapes();
    for lens in ["structural_clones", "role_neighbours"] {
        let v = f.ws.ask(lens, json!({ "limit": 500 }));
        assert!(v["worst"].is_array(), "{lens}: {v}");
        assert!(naming(&v, "flag_a", "flag_b").is_empty(), "{lens} pairs two 2-feature accessors: {v}");
        assert!(v["evidence_note"].as_str().unwrap().contains("at least 3 features"), "{lens}: the floor is stated");
    }
    // the real structure still links
    let v = f.ws.ask("structural_clones", json!({ "limit": 500 }));
    assert_eq!(naming(&v, "tally", "summarize").len(), 1, "{v}");
}

/// One algorithm per CPU feature (`sum_lanes_avx2` / `sum_lanes_scalar`) is
/// a deliberate family: labelled, kept out of the actionable list.
#[test]
fn simd_variants_are_labelled_deliberate_and_kept_out_of_the_list() {
    let _g = fixture::serial();
    let f = cx::build();
    f.shapes();
    f.embed(&Bag::default());
    for lens in ["exact_clones", "semantic_twins"] {
        let v = f.ws.ask(lens, json!({ "limit": 500 }));
        assert!(naming(&v, "sum_lanes_avx2", "sum_lanes_scalar").is_empty(), "{lens}: not in the list: {v}");
        let d = v["deliberate"].as_array().unwrap_or_else(|| panic!("{lens}: {v}"));
        let (a, b) = (sid("sum_lanes_avx2"), sid("sum_lanes_scalar"));
        let hit: Vec<&Value> = d.iter().filter(|x| ids(x).contains(&a) && ids(x).contains(&b)).collect();
        assert_eq!(hit.len(), 1, "{lens}: {v}");
        assert_eq!(hit[0]["family"], super::clones::SIMD_FAMILY, "{lens}");
        assert!(v["deliberate_families"].as_u64().unwrap() >= 1 && v["evidence_note"].as_str().unwrap().contains("SIMD"), "{lens}: {v}");
    }
}

// ── the instrument ──────────────────────────────────────────────────────────

/// **The clone-signal instrument** on a real lake (a COPY: it writes shapes,
/// role vectors and — with a local CPU embedder — a SAMPLE of normalised
/// vectors). `#[ignore]`d. Writes `report.json` and every lens answer to
/// `$CLONES_OUT`.
///
/// ```text
/// MIMIR_PROOF_BUILDS=<copy>/builds CLONES_OUT=<dir> [CLONES_SHAPES=1] [CLONES_CALIBRATE=1] \
///   cargo test --lib clone_signals_instrument -- --ignored --nocapture
/// ```
#[test]
#[ignore = "reads a real lake: set MIMIR_PROOF_BUILDS"]
fn clone_signals_instrument() {
    use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
    use std::time::Instant;
    let builds = std::path::PathBuf::from(std::env::var("MIMIR_PROOF_BUILDS").expect("MIMIR_PROOF_BUILDS"));
    let out = std::path::PathBuf::from(std::env::var("CLONES_OUT").unwrap_or_else(|_| "/tmp/clones-out".into()));
    std::fs::create_dir_all(&out).unwrap();
    let env = |k: &str| std::env::var(k).unwrap_or_default();
    let wh = crate::warehouse::iceberg::IcebergWarehouse::open(&builds).unwrap();
    let room = crate::code_room::CodeRoom::new("nordisk", &builds);
    let log = room.log().unwrap();
    let offsets = log.block_on(log.offsets()).unwrap();
    let mut report = serde_json::Map::new();
    let save = |name: &str, v: &Value| std::fs::write(out.join(format!("{name}.json")), serde_json::to_string_pretty(v).unwrap()).unwrap();

    // 1. the clone_shapes feed over every member (the backfill), then once more (an unchanged commit)
    if env("CLONES_SHAPES") == "1" {
        for pass in ["backfill", "again"] {
            let t = Instant::now();
            let mut per = Vec::new();
            for (m, o) in &offsets {
                let co = room.layout().clone_of(m);
                let head = crate::gitio::head_sha(&co).unwrap_or_default();
                if head != o.sha {
                    per.push(json!({ "member": m, "skipped": format!("checkout at {head}, room at {}", o.sha) }));
                    continue;
                }
                let t1 = Instant::now();
                match crate::clone_signals::feed::shapes_member(&wh, &log, m, &co, o.seq, &o.sha) {
                    Ok(r) => per.push(json!({ "member": m, "functions": r.functions, "plus": r.plus, "minus": r.minus, "distinct": r.distinct, "untokenised": r.untokenised, "ms": t1.elapsed().as_millis() as u64 })),
                    Err(e) => per.push(json!({ "member": m, "error": format!("{e:#}") })),
                }
            }
            println!("shapes {pass}: {} ms", t.elapsed().as_millis());
            report.insert(format!("shapes_{pass}"), json!({ "ms": t.elapsed().as_millis() as u64, "members": per }));
        }
    }

    // 2. the lenses, whole room, every finding
    let reach = crate::code_room::Reach::new(&room, &wh);
    let t = Instant::now();
    let opened = room.room(&mimir_room::Scope::current()).unwrap();
    println!("room: {} nodes in {} ms", opened.len(), t.elapsed().as_millis());
    let mut answers: BTreeMap<&str, Value> = BTreeMap::new();
    for lens in ["exact_clones", "near_clones", "structural_clones", "role_neighbours", "role_neighbours", "semantic_clones", "same_intent", "semantic_twins"] {
        let t = Instant::now();
        let v = crate::mimir_lens::answer(lens, &reach, &json!({ "limit": 1_000_000 }));
        let ms = t.elapsed().as_millis() as u64;
        println!("{lens}: {} · {} finding(s) · {} ms\n  {}", state(&v), v["worst"].as_array().map_or(0, Vec::len), ms, v["evidence_note"].as_str().unwrap_or("").chars().take(600).collect::<String>());
        report.insert(format!("ms_{lens}"), json!(ms));
        save(lens, &v);
        answers.insert(lens, v);
    }

    // 3. pairs per signal (stable id pairs), and their overlap
    let pair = |a: &str, b: &str| if a < b { (a.to_string(), b.to_string()) } else { (b.to_string(), a.to_string()) };
    let mut sets: BTreeMap<&str, HashSet<(String, String)>> = BTreeMap::new();
    for g in answers["exact_clones"]["worst"].as_array().unwrap().iter().chain(answers["exact_clones"]["deliberate"].as_array().into_iter().flatten()) {
        let m = ids(g);
        for i in 0..m.len() {
            for j in i + 1..m.len() {
                sets.entry("exact").or_default().insert(pair(&m[i], &m[j]));
            }
        }
    }
    for p in answers["near_clones"]["worst"].as_array().unwrap() {
        for a in ids(&p["a"]) {
            for b in ids(&p["b"]) {
                sets.entry("near").or_default().insert(pair(&a, &b));
            }
        }
    }
    for (lens, key) in [("structural_clones", "structural"), ("role_neighbours", "role")] {
        for p in answers[lens]["worst"].as_array().unwrap() {
            sets.entry(key).or_default().insert(pair(&ids(&p["a"])[0], &ids(&p["b"])[0]));
        }
    }
    // the raw model's pairs (names included), per function vector, through the pair index
    let names: Vec<String> = opened.scope().repos.keys().cloned().collect();
    let (fns, _) = crate::vector::fnvec::room::function_nodes(&opened, &names).unwrap();
    let vectors = crate::vector::fnvec::read(&wh, &opened.scope().repos).unwrap();
    let with: Vec<(&crate::vector::fnvec::room::RoomFn, &[f32])> = fns.iter().filter_map(|f| vectors.of(&f.repo, &f.node.moniker).map(|(_, v)| (f, v))).collect();
    report.insert("coverage".into(), json!({ "functions": fns.len(), "with_raw_vector": with.len(), "without": fns.len() - with.len() }));
    let t = Instant::now();
    // no index below its row floor (a lake without vectors): no raw pairs
    let raw = crate::vector::pair_index::pairs_above(with.iter().map(|(_, v)| *v), 0.80).map(|x| x.0).unwrap_or_default();
    println!("raw pairs ≥ 0.80: {} in {} ms", raw.len(), t.elapsed().as_millis());
    let sid = |f: &crate::vector::fnvec::room::RoomFn| mimir_schema::moniker::stable(&f.node.moniker).into_owned();
    let mut raw_cos: HashMap<(String, String), f32> = HashMap::new();
    for (a, b, c) in &raw {
        let (fa, fb) = (with[*a].0, with[*b].0);
        if fa.node.file == fb.node.file && fa.node.start_line == fb.node.start_line && fa.repo == fb.repo {
            continue; // the same lines compiled twice
        }
        let k = pair(&sid(fa), &sid(fb));
        raw_cos.insert(k.clone(), *c);
        if *c >= 0.92 {
            sets.entry("raw_092").or_default().insert(k);
        }
    }
    let keys: Vec<&str> = sets.keys().copied().collect();
    let mut overlap = serde_json::Map::new();
    for a in &keys {
        let mut row = serde_json::Map::new();
        for b in &keys {
            row.insert(b.to_string(), json!(sets[a].intersection(&sets[b]).count()));
        }
        overlap.insert(a.to_string(), Value::Object(row));
    }
    println!("pairs per signal: {:?}", keys.iter().map(|k| (k, sets[k].len())).collect::<Vec<_>>());
    report.insert("pairs".into(), json!(keys.iter().map(|k| (k.to_string(), sets[k].len())).collect::<BTreeMap<_, _>>()));
    report.insert("overlap".into(), Value::Object(overlap));

    // 4. name-bias candidates: the raw model ≥ 0.92, no clone signal agrees
    let agreed: HashSet<&(String, String)> = ["exact", "near", "structural", "role"].iter().filter_map(|k| sets.get(k)).flatten().collect();
    let by_id: HashMap<String, &crate::vector::fnvec::room::RoomFn> = fns.iter().map(|f| (sid(f), f)).collect();
    let mut bias: Vec<(f32, &(String, String))> = sets.get("raw_092").into_iter().flatten().filter(|k| !agreed.contains(k)).map(|k| (raw_cos[k], k)).collect();
    bias.sort_by(|x, y| y.0.total_cmp(&x.0));
    let sample: Vec<&(String, String)> = bias.iter().map(|x| x.1).filter(|(a, b)| by_id[a].node.end_line - by_id[a].node.start_line >= 3 && by_id[b].node.end_line - by_id[b].node.start_line >= 3).take(80).collect();
    report.insert("raw_only_pairs".into(), json!(bias.len()));
    // the normalised model on that sample, LOCAL CPU (labelled a sample)
    let embedder = crate::vector::load_embedder().ok();
    let text_of = |f: &crate::vector::fnvec::room::RoomFn| -> Option<String> {
        let t = crate::vector::fnvec::room::read_under(&room.layout().clone_of(&f.repo), &f.node.file)?;
        crate::vector::fnvec::cut(&t.lines().collect::<Vec<_>>(), f.node.start_line, f.node.end_line)
    };
    let mut rows = Vec::new();
    if let Some(e) = &embedder {
        let mut texts: Vec<String> = Vec::new();
        let mut at: Vec<(usize, usize, f32, &(String, String))> = Vec::new();
        for k in &sample {
            let (Some(ta), Some(tb)) = (text_of(by_id[&k.0]), text_of(by_id[&k.1])) else { continue };
            let (Some(na), Some(nb)) = (crate::clone_signals::norm::normalize(&ta), crate::clone_signals::norm::normalize(&tb)) else { continue };
            at.push((texts.len(), texts.len() + 1, raw_cos[*k], k));
            texts.push(na.text);
            texts.push(nb.text);
        }
        let t = Instant::now();
        let refs: Vec<&str> = texts.iter().map(String::as_str).collect();
        let vs = e.embed(&refs).unwrap();
        println!("sample: {} normalised texts on {} in {} ms", texts.len(), e.profile().model_name, t.elapsed().as_millis());
        for (i, j, rc, k) in at {
            let nc = crate::vector::pair_index::dot(&crate::vector::normalized(&vs[i]), &crate::vector::normalized(&vs[j]));
            let (fa, fb) = (by_id[&k.0], by_id[&k.1]);
            rows.push(json!({ "raw_cosine": rc, "normalised_cosine": nc, "a": format!("{}:{} {}", fa.node.file, fa.node.start_line, opened.display_path(fa.ordinal)), "b": format!("{}:{} {}", fb.node.file, fb.node.start_line, opened.display_path(fb.ordinal)) }));
        }
        rows.sort_by(|x, y| (y["raw_cosine"].as_f64().unwrap() - y["normalised_cosine"].as_f64().unwrap()).total_cmp(&(x["raw_cosine"].as_f64().unwrap() - x["normalised_cosine"].as_f64().unwrap())));
    }
    save("name_bias_sample", &json!(rows));

    // 5. role vectors: whole room, then a simulated commit of 20 functions
    let t = Instant::now();
    let rs = crate::clone_signals::structure::role_space(&opened, None, false).unwrap();
    let full_ms = t.elapsed().as_millis() as u64;
    let g = crate::clone_signals::structure::role_graph(&opened, &rs.features).unwrap();
    let prev = crate::clone_signals::structure::RoleVectors { data: rs.vectors.iter().flat_map(|v| v.vector.clone()).collect(), ..Default::default() };
    let changed: Vec<usize> = (0..rs.vectors.len()).step_by((rs.vectors.len() / 20).max(1)).take(20).collect();
    let t = Instant::now();
    let only = crate::clone_signals::structure::ball(&g, &changed, 2);
    let inc = crate::clone_signals::structure::role_vectors(&rs.features, &g, Some(&only), Some(&prev)).unwrap();
    let inc_ms = t.elapsed().as_millis() as u64;
    println!("role vectors: {} functions, graph {} nodes; full {} ms (features+graph {} ms, vectors {} ms); a 20-function commit: {} rows recomputed in {} ms", rs.vectors.len(), g.nodes, full_ms, rs.gather_ms, rs.vectors_ms, inc.computed, inc_ms);
    report.insert("role".into(), json!({ "functions": rs.vectors.len(), "graph_nodes": g.nodes, "full_ms": full_ms, "gather_ms": rs.gather_ms, "vectors_ms": rs.vectors_ms, "commit20_rows": inc.computed, "commit20_ms": inc_ms }));

    // 6. calibration (v1's oracle): positives = synthetic Type-1/2/3 of real functions, hard negatives = same signature, other body
    if env("CLONES_CALIBRATE") == "1"
        && let Some(e) = &embedder
    {
        let repo = "nornir";
        let corpus = super::corpus::from_room(&opened, repo, &room.layout().clone_of(repo), 5, 120).unwrap();
        for space in ["raw", "normalised"] {
            let t = Instant::now();
            let mut pos: Vec<f32> = Vec::new();
            let mut by_type: BTreeMap<&str, Vec<f32>> = BTreeMap::new();
            let fns = &corpus.fns;
            let mut rng = crate::mimir_calibrate::Lcg(0xc10e);
            let picked: BTreeSet<usize> = (0..400).map(|_| rng.below(fns.len())).collect::<BTreeSet<_>>().into_iter().take(150).collect();
            let hard = crate::mimir_calibrate::hard_negative_pairs(fns, 300, 0x51ed);
            let prep = |s: &str| if space == "raw" { Some(s.to_string()) } else { crate::clone_signals::norm::normalize(s).map(|n| n.text) };
            let mut texts: Vec<String> = Vec::new();
            let mut posp: Vec<(&str, usize, usize)> = Vec::new();
            for &i in &picked {
                for (label, tf) in crate::mimir_calibrate::positive_transforms() {
                    let (Some(a), Some(b)) = (prep(&fns[i].text), prep(&tf(&fns[i].text))) else { continue };
                    posp.push((label, texts.len(), texts.len() + 1));
                    texts.push(a);
                    texts.push(b);
                }
            }
            let mut negp: Vec<(usize, usize)> = Vec::new();
            for (a, b) in &hard {
                let (Some(x), Some(y)) = (prep(&fns[*a].text), prep(&fns[*b].text)) else { continue };
                negp.push((texts.len(), texts.len() + 1));
                texts.push(x);
                texts.push(y);
            }
            let refs: Vec<&str> = texts.iter().map(String::as_str).collect();
            let vs: Vec<Vec<f32>> = e.embed(&refs).unwrap().iter().map(|v| crate::vector::normalized(v)).collect();
            let cos = |i: usize, j: usize| crate::vector::pair_index::dot(&vs[i], &vs[j]);
            for (label, i, j) in &posp {
                let c = cos(*i, *j);
                pos.push(c);
                by_type.entry(label).or_default().push(c);
            }
            let mut neg: Vec<f32> = negp.iter().map(|(i, j)| cos(*i, *j)).collect();
            neg.sort_by(f32::total_cmp);
            let auc = crate::mimir_calibrate::roc_auc(&pos, &neg);
            let p80 = neg.get(neg.len() * 4 / 5).copied().unwrap_or(0.0);
            let mean = |v: &[f32]| v.iter().sum::<f32>() / v.len().max(1) as f32;
            println!("calibration {space}: AUC {auc:.3} · hard-negative p80 {p80:.3} · positives {} hard negatives {} · {} ms", pos.len(), neg.len(), t.elapsed().as_millis());
            report.insert(format!("calibration_{space}"), json!({ "roc_auc": auc, "hard_negative_p80": p80, "positives": pos.len(), "hard_negatives": neg.len(), "mean_by_type": by_type.iter().map(|(k, v)| (k.to_string(), mean(v))).collect::<BTreeMap<_, _>>(), "mean_hard_negative": mean(&neg), "model": e.profile().model_name, "corpus": format!("{repo}: {} functions", fns.len()) }));
        }
    }

    std::fs::write(out.join("report.json"), serde_json::to_string_pretty(&Value::Object(report)).unwrap()).unwrap();
    println!("report: {}", out.join("report.json").display());
}

/// **The lens dump** — every cosine lens over a real lake (a COPY: the role
/// lens writes its vectors back), whole answers at `limit` 10⁶, written to
/// `$LENS_DUMP_OUT/<lens>.json` with the wall time of each in `times.json`.
/// Two builds' dumps, diffed with the volatile fields (timings, the note's
/// numbers of milliseconds, the pair index's served block) set aside, prove a
/// speed change kept every pair. `#[ignore]`d.
///
/// ```text
/// LENS_DUMP_BUILDS=<copy>/builds LENS_DUMP_OUT=<dir> cargo test --lib clone_lens_dump -- --ignored --nocapture
/// ```
#[test]
#[ignore = "reads a real lake: set LENS_DUMP_BUILDS"]
fn clone_lens_dump() {
    let builds = std::path::PathBuf::from(std::env::var("LENS_DUMP_BUILDS").expect("LENS_DUMP_BUILDS"));
    let out = std::path::PathBuf::from(std::env::var("LENS_DUMP_OUT").expect("LENS_DUMP_OUT"));
    std::fs::create_dir_all(&out).unwrap();
    let wh = crate::warehouse::iceberg::IcebergWarehouse::open(&builds).unwrap();
    let room = crate::code_room::CodeRoom::new("nordisk", &builds);
    let reach = crate::code_room::Reach::new(&room, &wh);
    let mut times = serde_json::Map::new();
    let lenses = std::env::var("LENS_DUMP_LENSES").unwrap_or_else(|_| "similar_code,same_intent,semantic_twins,role_neighbours,semantic_clones,structural_clones,exact_clones,near_clones".into());
    for lens in lenses.split(',') {
        let t = std::time::Instant::now();
        let v = crate::mimir_lens::answer(lens, &reach, &json!({ "limit": 1_000_000 }));
        let ms = t.elapsed().as_millis() as u64;
        println!("{lens}: {} · {} ms", state(&v), ms);
        times.insert(lens.to_string(), json!(ms));
        std::fs::write(out.join(format!("{lens}.json")), serde_json::to_string(&v).unwrap()).unwrap();
    }
    std::fs::write(out.join("times.json"), serde_json::to_string_pretty(&Value::Object(times)).unwrap()).unwrap();
}

/// **The batched-walk probe** over a real lake: `weak_tests`' walk — the
/// forward CALLS reach of EVERY `#[test]` node of the room — one walk per
/// test (the old loop) and all of them as frontier matrices
/// ([`mimir_room::Room::reach_each`]); the two must be identical, test for
/// test, and the times are printed. `#[ignore]`d.
///
/// ```text
/// LENS_DUMP_BUILDS=<copy>/builds cargo test --lib walk_batch_probe -- --ignored --nocapture
/// ```
#[test]
#[ignore = "reads a real lake: set LENS_DUMP_BUILDS"]
fn walk_batch_probe() {
    use mimir_schema::EdgeKind;
    let builds = std::path::PathBuf::from(std::env::var("LENS_DUMP_BUILDS").expect("LENS_DUMP_BUILDS"));
    let room = crate::code_room::CodeRoom::new("nordisk", &builds);
    let r = room.room(&crate::mimir_lens::scope_of("weak_tests", "")).unwrap();
    let tests = r.mask(&mimir_room::MaskSpec { is_test: Some(true), ..Default::default() }).unwrap().value;
    let seeds = tests.ordinals().to_vec();
    // warm the adjacency cache outside the clocks
    let _ = r.reach(&seeds[..1.min(seeds.len())], &[EdgeKind::Calls], None, None).unwrap();
    let t = std::time::Instant::now();
    let old: Vec<Vec<u64>> = seeds.iter().map(|s| r.reach(&[*s][..], &[EdgeKind::Calls], None, None).unwrap().value.reached).collect();
    let old_ms = t.elapsed().as_millis();
    for batch in ["64", "128"] {
        // SAFETY: an ignored probe run alone; nothing reads the env concurrently
        unsafe { std::env::set_var("NORNIR_BFS_BATCH", batch) };
        let t = std::time::Instant::now();
        let new: Vec<Vec<u64>> = r.reach_each(&seeds, &[EdgeKind::Calls], None, None).unwrap().into_iter().map(|a| a.value.reached).collect();
        let new_ms = t.elapsed().as_millis();
        let reached: usize = old.iter().map(Vec::len).sum();
        assert_eq!(old, new, "batch {batch}: a walk differs");
        println!("weak_tests walk: {} test node(s), {reached} reached in all: one walk per test {old_ms} ms, batched ({batch}) {new_ms} ms — identical", seeds.len());
    }
}

/// **The world_impact probe** over a real lake: EVERY commit window of every
/// repo (seq 2 ..= tip), folded from two as-of rooms (the old path) and read
/// from the read-fast zone — identical, window for window — and the callers
/// walk of every window's touched crates, one Jikes walk per crate against
/// all at once. Times printed. `#[ignore]`d.
///
/// ```text
/// LENS_DUMP_BUILDS=<copy>/builds cargo test --lib world_window_probe -- --ignored --nocapture
/// ```
#[test]
#[ignore = "reads a real lake: set LENS_DUMP_BUILDS"]
fn world_window_probe() {
    let builds = std::path::PathBuf::from(std::env::var("LENS_DUMP_BUILDS").expect("LENS_DUMP_BUILDS"));
    let wh = crate::warehouse::iceberg::IcebergWarehouse::open(&builds).unwrap();
    let room = crate::code_room::CodeRoom::new("nordisk", &builds);
    let reach = crate::code_room::Reach::new(&room, &wh);
    let r = room.room(&crate::mimir_lens::scope_of("world_impact", "")).unwrap();
    let public = |r: &mimir_room::Room, o: u64| matches!(r.attr(o, "effective_visibility").and_then(|v| v.as_str()), Some("direct" | "reexported"));
    let item = |r: &mimir_room::Room, o: u64| r.node(o).level == Some(mimir_schema::Level::Item) && r.node(o).origin == Some(mimir_schema::Origin::Local) && r.node(o).defined;
    let (mut old_ms, mut new_ms, mut n, mut tip_old, mut tip_new) = (0u128, 0u128, 0usize, 0u128, 0u128);
    let mut touched: Vec<Vec<String>> = Vec::new();
    let only: Option<usize> = std::env::var("PROBE_LAST").ok().and_then(|v| v.parse().ok());
    for (repo, &tip) in &r.scope().repos {
        let from = only.map_or(2, |k| (tip - k as i64 + 1).max(2));
        for seq in from..=tip {
            let t = std::time::Instant::now();
            let old = super::lenses::fold_window(&reach, repo, seq, &public, &item).unwrap();
            let o = t.elapsed().as_millis();
            let t = std::time::Instant::now();
            let new = super::lenses::window_from_zone(&reach, repo, seq).unwrap().expect("the zone answers");
            let nn = t.elapsed().as_millis();
            assert_eq!(old, new, "window {repo}@{}→{seq} differs", seq - 1);
            let items: i64 = old.per_crate.iter().map(|c| c.added_items + c.removed_items + c.changed_items).sum();
            println!("window {repo}@{}→{seq}: {} crate(s), {items} item(s) — folded {o} ms, zone {nn} ms — identical", seq - 1, old.per_crate.len());
            (old_ms, new_ms, n) = (old_ms + o, new_ms + nn, n + 1);
            if seq == tip {
                (tip_old, tip_new) = (tip_old + o, tip_new + nn);
                touched.extend(old.touched.values().cloned());
            }
        }
    }
    println!("windows: {n} identical; folded {old_ms} ms, zone {new_ms} ms in all; the tips (what one ask reads) folded {tip_old} ms, zone {tip_new} ms");
    let _ = r.dependents(&["warm"][..], None);
    let t = std::time::Instant::now();
    let old: Vec<Vec<u64>> = touched.iter().map(|s| { let s: Vec<&str> = s.iter().map(String::as_str).collect(); r.dependents(&s[..], None).unwrap().value.reached }).collect();
    let o = t.elapsed().as_millis();
    let t = std::time::Instant::now();
    let refs: Vec<Vec<&str>> = touched.iter().map(|s| s.iter().map(String::as_str).collect()).collect();
    let seeds: Vec<mimir_room::Seeds<'_>> = refs.iter().map(|s| mimir_room::Seeds::Monikers(s)).collect();
    let new: Vec<Vec<u64>> = r.dependents_each(&seeds, None).unwrap().into_iter().map(|a| a.value.reached).collect();
    let nn = t.elapsed().as_millis();
    assert_eq!(old, new, "a callers walk differs");
    println!("callers walks: {} crate(s): one Jikes walk per crate {o} ms, batched {nn} ms — identical", touched.len());
}

// ── semantic_clones, incremental: the kept scan advanced by what changed ─────

/// The whole answer, minus what may differ between two EQUAL computations:
/// `lens_meta.ms` and the note's wall-clock numbers (every "N ms" becomes
/// "? ms" — the finding counts and words stay compared byte for byte).
fn sans_work(v: &Value) -> Value {
    let mut v = v.clone();
    if let Some(meta) = v["lens_meta"].as_object_mut() {
        meta.remove("ms");
    }
    if let Some(note) = v["evidence_note"].as_str() {
        let parts: Vec<&str> = note.split(" ms").collect();
        let mut out = String::new();
        for (i, p) in parts.iter().enumerate() {
            if i + 1 < parts.len() {
                out.push_str(p.trim_end_matches(|c: char| c.is_ascii_digit()));
                out.push_str("? ms");
            } else {
                out.push_str(p);
            }
        }
        v["evidence_note"] = json!(out);
    }
    v
}

/// ZERO-LOSS, and the work saved, end to end: the first ask is the FULL scan
/// and is KEPT; an unchanged room CARRIES it; `summarize` gets another body
/// (same signature, same touches) — the feed embeds the one new normalised
/// body, the lens carries the structural scan and reads only the vectors it
/// does not hold — and the advanced answer equals the full recompute (minus
/// the clock), the full path staying in the code as the oracle.
#[test]
fn semantic_clones_advances_when_one_body_changes_and_the_features_hold() {
    use crate::mimir_lens::clone_inc as inc;
    let _g = fixture::serial();
    inc::forget();
    let f = cx::build();
    f.shapes();
    let bag = Bag::default();
    f.embed(&bag);
    let (f0, c0, a0) = inc::stats("semantic_clones");
    let before = f.ws.ask("semantic_clones", json!({}));
    assert_eq!(state(&before), "complete", "{before}");
    let (f1, ..) = inc::stats("semantic_clones");
    assert_eq!(f1 - f0, 1, "no kept scan for this scope: the first ask is the full one");

    // the same room again: nothing the fold reads changed — carried
    let carried = f.ws.ask("semantic_clones", json!({}));
    let (f2, c1, a1) = inc::stats("semantic_clones");
    assert_eq!((f2 - f1, c1 - c0, a1 - a0), (0, 1, 0), "nothing changed: carried, not recomputed");
    assert_eq!(sans_work(&carried), sans_work(&before), "the carried answer IS the previous answer");

    // summarize gets another body: the same signature and touches, another text
    f.second_commit();
    let shapes = f.shapes();
    assert!(shapes.plus < shapes.functions, "only the changed bodies get a new shape: {shapes:?}");
    let norm = f.embed(&bag);
    assert!(norm.new_vectors >= 1, "the new normalised body is embedded: {norm:?}");
    let after = f.ws.ask("semantic_clones", json!({}));
    let (f3, c2, a2) = inc::stats("semantic_clones");
    assert_eq!((f3 - f2, c2 - c1, a2 - a1), (0, 0, 1), "one changed body is ADVANCED: the structural scan is carried");
    let w = inc::last_work().expect("the advance records what it did");
    assert_eq!((w.lens, w.changed), ("semantic_clones", 1), "{w:?}");
    assert!(w.vectors_carried > 0, "the kept normalised vectors are not re-read: {w:?}");
    assert!(w.vectors_read <= 2, "only the missing vectors are read: {w:?}");

    // ZERO-LOSS: forget the kept scan and ask again — the FULL path, the oracle
    inc::forget();
    let full = f.ws.ask("semantic_clones", json!({}));
    let (f4, ..) = inc::stats("semantic_clones");
    assert_eq!(f4 - f3, 1, "forgetting the kept scan forces the full path");
    assert_eq!(sans_work(&after), sans_work(&full), "ZERO-LOSS: the incremental answer IS the full answer");
}

/// **The twins phase probe** — the TWINS / INTENT / CLONE lenses over a real
/// lake (a COPY: the role lens writes its vectors back), each asked twice in
/// one process (cold, then with every process-kept fold warm), the phases on
/// stderr (`NORNIR_CLONE_INC_DEBUG=1`). `#[ignore]`d.
///
/// ```text
/// LENS_DUMP_BUILDS=<copy>/builds NORNIR_CLONE_INC_DEBUG=1 cargo test --lib twins_phase_probe -- --ignored --nocapture
/// ```
#[test]
#[ignore = "reads a real lake: set LENS_DUMP_BUILDS"]
fn twins_phase_probe() {
    let builds = std::path::PathBuf::from(std::env::var("LENS_DUMP_BUILDS").expect("LENS_DUMP_BUILDS"));
    let wh = crate::warehouse::iceberg::IcebergWarehouse::open(&builds).unwrap();
    let room = crate::code_room::CodeRoom::new("nordisk", &builds);
    let reach = crate::code_room::Reach::new(&room, &wh);
    let lenses = std::env::var("LENS_DUMP_LENSES").unwrap_or_else(|_| "role_neighbours,same_intent,semantic_twins,structural_clones,near_clones,exact_clones".into());
    let limit: u64 = std::env::var("PROBE_LIMIT").ok().and_then(|v| v.parse().ok()).unwrap_or(50);
    for lens in lenses.split(',') {
        for pass in ["cold", "warm"] {
            let t = std::time::Instant::now();
            let v = crate::mimir_lens::answer(lens, &reach, &json!({ "limit": limit }));
            eprintln!("PROBE {lens} {pass}: {} · {} ms", state(&v), t.elapsed().as_millis());
        }
    }
}

// ── the twins / intent / role folds, incremental: kept, carried, advanced ────

/// [`sans_work`], and the role space's own work words: how many role vectors
/// the role space (re)computed this ask is upstream bookkeeping (the stored
/// vectors are the lens's INPUT, like the embeddings), never a finding.
fn sans_fold_work(v: &Value) -> Value {
    let mut v = sans_work(v);
    if let Some(m) = v.as_object_mut() {
        m.remove("recomputed");
        m.remove("mode");
        // which join answered (the index, the scan, the kept join advanced)
        m.remove("knn");
    }
    // … and the note's words for it: "by <how> in", "ms by <how>."
    if let Some(note) = v["evidence_note"].as_str() {
        let mut note = note.to_string();
        for (from, to) in [(" candidate pair(s) by ", " in "), (" ms by ", ".")] {
            if let Some(a) = note.find(from) {
                let start = a + from.len();
                if let Some(b) = note[start..].find(to) {
                    note.replace_range(start..start + b, "<join>");
                }
            }
        }
        v["evidence_note"] = json!(note);
    }
    if let Some(note) = v["evidence_note"].as_str() {
        // "N vector(s) (re)computed (MODE — K changed since the kept ones), W written back"
        let mut out = String::new();
        let mut rest = note;
        if let Some(at) = rest.find(" vector(s) (re)computed (") {
            let head = &rest[..at];
            let head = head.trim_end_matches(|c: char| c.is_ascii_digit());
            out.push_str(head);
            out.push_str("? vector(s) (re)computed (…), ? written back");
            rest = &rest[at..];
            rest = rest.find(" written back").map_or("", |e| &rest[e + " written back".len()..]);
        }
        out.push_str(rest);
        v["evidence_note"] = json!(out);
    }
    v
}

/// One lens, end to end over the clone fixture: the first ask is FULL and
/// KEPT; the same room CARRIES it; `change` advances the room and the lens
/// ADVANCES (re-folding only what moved, the work recorded); forgetting the
/// kept fold and asking again is the FULL path — the oracle the advanced
/// answer must equal byte for byte (minus the clock).
fn advance_equals_full(lens: &'static str, params: Value, embed: bool, change: impl Fn(&cx::Clo)) -> crate::mimir_lens::clone_inc::Work {
    use crate::mimir_lens::clone_inc as inc;
    inc::forget();
    let f = cx::build();
    f.shapes();
    let bag = Bag::default();
    if embed {
        f.embed(&bag);
    }
    let (f0, c0, a0) = inc::stats(lens);
    let before = f.ws.ask(lens, params.clone());
    assert!(matches!(state(&before), "complete" | "partial"), "{before}");
    let (f1, ..) = inc::stats(lens);
    assert_eq!(f1 - f0, 1, "{lens}: no kept fold for this scope — the first ask is the full one");

    let carried = f.ws.ask(lens, params.clone());
    let (f2, c1, a1) = inc::stats(lens);
    assert_eq!((f2 - f1, c1 - c0, a1 - a0), (0, 1, 0), "{lens}: nothing changed — carried, not recomputed");
    assert_eq!(sans_fold_work(&carried), sans_fold_work(&before), "{lens}: the carried answer IS the previous answer");

    change(&f);
    f.shapes();
    if embed {
        f.embed(&bag);
    }
    let after = f.ws.ask(lens, params.clone());
    let (f3, c2, a2) = inc::stats(lens);
    assert_eq!((f3 - f2, c2 - c1, a2 - a1), (0, 0, 1), "{lens}: a few functions moved — ADVANCED, not recomputed");
    let w = inc::last_work().expect("the advance records what it did");
    assert_eq!(w.lens, lens, "{w:?}");
    assert!(w.changed >= 1 && w.changed * 2 <= w.functions, "{lens}: only what moved is re-folded: {w:?}");
    let full_dots = (w.functions as u64) * (w.functions as u64 - 1) / 2;
    assert!(w.dots < full_dots, "{lens}: the advance joined fewer pairs than the full scan ({full_dots}): {w:?}");
    eprintln!("{lens}: advanced {} of {} function(s), {} dot(s) (the full scan: {full_dots}), {} pair(s) carried", w.changed, w.functions, w.dots, w.pairs_carried);

    inc::forget();
    let full = f.ws.ask(lens, params);
    let (f4, ..) = inc::stats(lens);
    assert_eq!(f4 - f3, 1, "{lens}: forgetting the kept fold forces the full path");
    assert_eq!(sans_fold_work(&after), sans_fold_work(&full), "{lens}: ZERO-LOSS — the incremental answer IS the full answer");
    assert_ne!(sans_fold_work(&after)["worst"], Value::Null);
    w
}

/// `role_neighbours`: `checksum` calls one function more — its role vector
/// and its neighbourhood's move; only those rows are re-joined.
#[test]
fn role_neighbours_advances_when_one_function_changes_and_equals_the_full_fold() {
    let _g = fixture::serial();
    let w = advance_equals_full("role_neighbours", json!({}), false, |f| f.commit_v(2));
    assert!(w.pairs_carried > 0 || w.dots > 0, "{w:?}");
}

/// `same_intent`: `summarize` and `checksum` get other bodies — their raw
/// vectors move; the kept candidate pairs of every other function carry.
#[test]
fn same_intent_advances_when_bodies_change_and_equals_the_full_fold() {
    let _g = fixture::serial();
    advance_equals_full("same_intent", json!({}), true, |f| f.commit_v(2));
}

/// `semantic_twins`: the same change; the twin / copy judgement of every
/// pair without a changed member is carried.
#[test]
fn semantic_twins_advances_when_bodies_change_and_equals_the_full_fold() {
    let _g = fixture::serial();
    advance_equals_full("semantic_twins", json!({}), true, |f| f.commit_v(2));
}

/// What the kept folds must NOT stand in for plans FULL: a moved threshold
/// (the kept pairs are of another bar) — and the answer then equals the full
/// fold at that bar. A function that APPEARS is an advance (the predicates are
/// pairwise: the new row is joined against every row) and still equals the
/// full fold.
#[test]
fn the_twins_folds_plan_full_on_a_moved_threshold_and_advance_over_a_new_function() {
    use crate::mimir_lens::clone_inc as inc;
    let _g = fixture::serial();
    for (lens, bar) in [("role_neighbours", "cosine"), ("same_intent", "cosine"), ("semantic_twins", "cosine")] {
        inc::forget();
        let f = cx::build();
        f.shapes();
        let bag = Bag::default();
        f.embed(&bag);
        let _ = f.ws.ask(lens, json!({}));
        // another bar: full, never the kept pairs of the old one
        let (f0, c0, a0) = inc::stats(lens);
        let moved = f.ws.ask(lens, json!({ bar: 0.85 }));
        let (f1, c1, a1) = inc::stats(lens);
        assert_eq!((f1 - f0, c1 - c0, a1 - a0), (1, 0, 0), "{lens}: a moved threshold plans FULL");
        inc::forget();
        let oracle = f.ws.ask(lens, json!({ bar: 0.85 }));
        assert_eq!(sans_fold_work(&moved), sans_fold_work(&oracle), "{lens}: the moved-threshold answer is the full one");
        // a new function: advanced, and still the full answer
        let _ = f.ws.ask(lens, json!({}));
        f.commit_v(3);
        f.shapes();
        f.embed(&bag);
        let (f2, _, a2) = inc::stats(lens);
        let grown = f.ws.ask(lens, json!({}));
        let (f3, _, a3) = inc::stats(lens);
        assert_eq!((f3 - f2, a3 - a2), (0, 1), "{lens}: a new function is an advance");
        inc::forget();
        let full = f.ws.ask(lens, json!({}));
        assert_eq!(sans_fold_work(&grown), sans_fold_work(&full), "{lens}: ZERO-LOSS over a grown population");
    }
}

// ── the twins' precision: test code, one method per type, groups ────────────

#[test]
fn a_helper_inside_a_test_module_or_test_file_is_test_code() {
    use super::clones::test_like;
    assert!(test_like("monetize_product_gunnar::guardian::tests::order_kinds", "src/guardian.rs"));
    assert!(test_like("nornir::viz::test_support::mk", "src/viz/test_support.rs"));
    assert!(test_like("nornir::lens::test_boot", "src/lens.rs"));
    assert!(test_like("alpha::f", "src/room_feed/clone_tests.rs"));
    assert!(test_like("alpha::f", "crates/a/tests/it.rs"));
    assert!(test_like("alpha::f", "src/a_tests.rs"));
    assert!(!test_like("alpha::latest::render", "src/latest.rs"));
    assert!(!test_like("alpha::contest::run_tests_report", "src/contest.rs"));
}

#[test]
fn one_method_per_type_is_a_deliberate_family_not_a_twin() {
    use super::clones::{Method, one_method_per_type};
    let m = |name: &'static str, ty: &'static str, self_only: bool| Method { name, self_type: ty.to_string(), self_only };
    // `Level::as_str` and `Origin::as_str`: each type's own view of itself
    assert!(one_method_per_type(&m("as_str", "Level", true), &m("as_str", "Origin", true)));
    assert!(one_method_per_type(&m("state_json", "TrustReport", true), &m("state_json", "ChurnReport", true)));
    // another name, the same type, or arguments beyond self: judged as a twin
    assert!(!one_method_per_type(&m("as_str", "Level", true), &m("label", "Origin", true)));
    assert!(!one_method_per_type(&m("as_str", "Level", true), &m("as_str", "Level", true)));
    assert!(!one_method_per_type(&m("render", "A", false), &m("render", "B", false)));
}

#[test]
fn the_groups_are_the_connected_components_of_the_pairs() {
    use super::clones::groups;
    assert_eq!(groups(&[]), 0);
    assert_eq!(groups(&[(1, 2)]), 1);
    // one helper copied into four places: six pairs, one group
    assert_eq!(groups(&[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]), 1);
    assert_eq!(groups(&[(1, 2), (2, 3), (7, 8)]), 2);
}

#[test]
fn vendored_generated_build_output_examples_and_benches_are_no_clone_finding() {
    use super::clones::path_excluded;
    assert_eq!(path_excluded("vendor/cozo/src/ops.rs"), Some("vendored"));
    assert_eq!(path_excluded("crates/x/vendored/y.rs"), Some("vendored"));
    assert_eq!(path_excluded("src/generated/proto.rs"), Some("generated"));
    assert_eq!(path_excluded("/nonexistent/target/debug/build/gamma-1/out/proto.rs"), Some("build-script / OUT_DIR output"));
    assert_eq!(path_excluded("examples/demo.rs"), Some("example"));
    assert_eq!(path_excluded("crates/a/benches/b.rs"), Some("bench"));
    assert_eq!(path_excluded("src/lib.rs"), None);
    assert_eq!(path_excluded("src/examples_index.rs"), None);
}

#[test]
fn a_body_that_is_one_literal_is_recognised() {
    use super::clones::literal_only;
    assert!(literal_only("pub fn state_json(&self) -> Value {\n    json!({ \"kind\": \"x\", \"n\": self.n })\n}"));
    assert!(literal_only("fn new() -> Self {\n    Self { a: 1, b: vec![] }\n}"));
    assert!(literal_only("fn to(&self) -> Row {\n    // the row\n    Row { a: self.a.clone() }\n}"));
    assert!(!literal_only("fn f(&self) -> Value {\n    let n = self.n + 1;\n    json!({ \"n\": n })\n}"));
    assert!(!literal_only("fn g(x: u32) -> u32 {\n    x.wrapping_mul(31)\n}"));
}

#[test]
fn clone_classes_collapse_a_helper_copied_four_times_into_one_finding() {
    let _g = super::fixture::serial();
    crate::mimir_lens::clone_inc::forget();
    let f = super::fixture::vectors::build();
    f.shapes(super::fixture::vectors::MONO);
    f.shapes(super::fixture::vectors::OTHER);
    let v = f.ws.ask("semantic_twins", json!({ "limit": 500 }));
    let worst = v["worst"].as_array().unwrap();
    let headers: Vec<&Value> = worst.iter().filter(|w| w.to_string().contains("parse_header")).collect();
    assert_eq!(headers.len(), 1, "three copies of parse_header are ONE class: {v}");
    assert!(headers[0]["class_size"].as_u64().is_some_and(|n| n >= 3), "{}", headers[0]);
}