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

nordisk/dwarves

dwarves-gui/src/dupes.rs

//! **The 🧬 Dupes tab — the duplicate box, a SUB-VIEW of `Mimir.SimilarCode`.**
//!
//! dwarves' Tools answer to *"is this code already somewhere else in the
//! constellation?"* — and, since the lens chain landed, that answer is **read, not
//! folded here**. The findings come off the `lens_similar_code` warehouse table over
//! the SAME thin `Mimir.SimilarCode` RPC seam the Lenses pane's `SimilarCode` view uses
//! (`nornir_warehouse_embed::mimir::similar_code`). A jera job computes the fold once,
//! on populate; this pane renders what the server already computed. **It does not
//! fold.** (LAW 5 — the old local `detect()` over `Warehouse.Scan` was a twin of the
//! lens and is gone from the findings path.)
//!
//! ## Provenance is the header
//! The reading names WHERE it came from, off the `lens_meta` nornir stamps on every
//! answer: `similar_code · snapshot S · computed HH:MM` (cache hit), `queued in jera
//! (#n)` (the chain has not folded it yet), or `folded locally (no server)` for the
//! apply escape hatch below. The pane can never SAY "computed" unless a `lens_runs` row
//! said so — the freshness is derived, never asserted.
//!
//! ## The APPLY seam keeps a local-fold escape hatch — measured, not lazy
//! `lens_similar_code` carries the ranked clusters (`top_clusters`:
//! canonical/size/cosine/structural/score) + `evidence_note` + `feeds` + `lens_meta`.
//! It does **not** carry the `dwarves::dupes` executable [`DupeReport::proposals`]
//! (the type-gated absorb→delete→repoint `RefactorPlan`s) the apply seam drives — those
//! are a DIFFERENT engine (byte-hash + leafwatch), computed nowhere on the wire today.
//! So APPLY, and only apply, still folds locally (`detect()`), behind an explicit
//! button, clearly stamped `folded locally`. The FINDINGS are read; the apply acts on a
//! locally-folded plan because the lens result lacks the proposal detail apply needs.

use dwarves::dupes::{
    apply::{apply_all, ApplyMode, RecordingExecutor},
    corpus::{Corpus, Table},
    detect,
    hydrate::Checkouts,
    DupeOptions, DupeReport,
};
use facett_core::Facet;

// The five warehouse tables the box reads are named ONCE, in `dwarves::dupes::thin`,
// alongside the loader that reads them (L5) — this pane does not keep a second list that
// could drift from it.
use dwarves::dupes::thin::SCAN_LIMIT;

/// The dependency graph behind leafwatch's consumer count. Three short string columns,
/// so unlike `embeddings` it DOES survive the stringified gRPC preview — which is why
/// this one is still a `Warehouse.Scan` read and vectors are not.
const T_DEP_EDGES: &str = "dep_graph_edges";

/// Where the pane's corpus comes from. Injected so the robot test drives the pane over
/// a deterministic corpus without a server, exactly as the Binary tab's data seam does.
pub trait DupeSource: Send {
    /// Load the corpus, or an honest human-readable reason it could not be loaded.
    fn load(&self) -> Result<Corpus, String>;
    /// What to show in the header (`nornir warehouse @ …` / `fixture (demo)`).
    fn describe(&self) -> String;
    /// `(from_repo, to_repo, via_crate)` dependency edges, for leafwatch's CONSUMER
    /// COUNT — *"this leaf 16 crates already use"* is the whole argument of a reverse
    /// hit, and without edges every hit reads `0 consumer(s) · UNKNOWN`.
    ///
    /// Default empty, which leafwatch reports as
    /// [`Unknown`](dwarves::dupes::leafwatch::Discoverability::Unknown) — never as
    /// "no dependency". A source that CAN answer overrides this.
    fn dep_edges(&self) -> Vec<(String, String, String)> {
        Vec::new()
    }
}

/// The shipped source: nornir's warehouse over the thin gRPC read seam.
pub struct WarehouseDupes {
    pub endpoint: String,
    pub token: String,
    pub workspace: String,
}

impl WarehouseDupes {
    pub fn new(
        endpoint: impl Into<String>,
        token: impl Into<String>,
        workspace: impl Into<String>,
    ) -> Self {
        Self {
            endpoint: endpoint.into(),
            token: token.into(),
            workspace: workspace.into(),
        }
    }

    /// One table over gRPC, mapped onto the engine's stringified [`Table`] shape.
    fn scan(&self, table: &str) -> Result<Table, String> {
        nornir_warehouse_embed::scan_warehouse_table(
            &self.endpoint,
            &self.token,
            &self.workspace,
            table,
            SCAN_LIMIT,
        )
        .map(|s| Table::new(s.columns, s.rows))
        .map_err(|e| e.to_string())
    }
}

impl DupeSource for WarehouseDupes {
    /// Delegates to `dwarves::dupes::thin::corpus_from_server` — the ONE thin loader
    /// (L5), which is also what the thin↔fat parity guard drives, so the tab cannot
    /// diverge from the thing that is tested.
    fn load(&self) -> Result<Corpus, String> {
        dwarves::dupes::thin::corpus_from_server(&self.endpoint, &self.token, &self.workspace, true)
    }

    fn describe(&self) -> String {
        format!(
            "nornir warehouse @ {} / {} (THIN — typed vectors)",
            self.endpoint, self.workspace
        )
    }

    /// `dep_graph_edges` is three short string columns, so the stringified preview is
    /// the right transport for it — unlike `embeddings.vector`, which needs the typed
    /// route. An unreachable or empty table yields no edges, which leafwatch reports as
    /// UNKNOWN.
    fn dep_edges(&self) -> Vec<(String, String, String)> {
        let Ok(t) = self.scan(T_DEP_EDGES) else {
            return Vec::new();
        };
        let idx = |name: &str| t.columns.iter().position(|c| c == name);
        let (Some(f), Some(to), Some(via)) = (idx("from_repo"), idx("to_repo"), idx("via_crate"))
        else {
            return Vec::new();
        };
        let mut out: Vec<(String, String, String)> = t
            .rows
            .iter()
            .filter_map(|r| {
                let g = |i: usize| r.get(i).cloned().unwrap_or_default();
                let (a, b) = (g(f), g(to));
                (!a.is_empty() && !b.is_empty()).then(|| (a, b, g(via)))
            })
            .collect();
        out.sort();
        out.dedup();
        out
    }
}

/// **The FAT source — the local Iceberg tree, read straight off disk.**
///
/// Reads the Iceberg data files directly, so the box works with no server up at all.
///
/// It is NO LONGER the only whole leg. The stringified `Warehouse.Scan` preview genuinely
/// cannot carry `embeddings.vector` (a 768-float `list<float32>` renders as its Arrow type
/// name, the same constant on every row), which is why the SEMANTIC tier and leafwatch's
/// semantic leg — the two things that catch *"same thing, written differently"*, the case
/// a byte hash structurally cannot see — used to be fat-only. Vectors now have a typed
/// bulk route (`Warehouse.ScanVectors`, raw little-endian f32, streamed), and both legs
/// feed `Corpus::set_vectors` the same `Vec<f32>`, so the thin verdict equals this one.
///
/// Read-only: it opens the Parquet data files, never the catalog, and never writes. So
/// it is safe to use while a `nornir-server` holds the warehouse — but the fat leg
/// exists precisely for when nothing does.
#[cfg(feature = "dupes-fat")]
pub struct LocalDupes {
    /// The directory holding the Iceberg namespaces (nornir's `<workspace>/warehouse`).
    pub root: std::path::PathBuf,
    /// Normally `nornir`.
    pub namespace: String,
}

#[cfg(feature = "dupes-fat")]
impl LocalDupes {
    pub fn new(root: impl Into<std::path::PathBuf>, namespace: impl Into<String>) -> Self {
        Self {
            root: root.into(),
            namespace: namespace.into(),
        }
    }

    /// Where nornir puts a workspace's warehouse: `$NORNIR_WAREHOUSE`, else
    /// `~/.nornir/workspaces/<workspace>/builds/warehouse`. `None` when neither
    /// resolves to a directory that exists — the caller then stays on the thin leg
    /// rather than inventing a root.
    pub fn discover(workspace: &str) -> Option<std::path::PathBuf> {
        let root = std::env::var("NORNIR_WAREHOUSE")
            .ok()
            .map(std::path::PathBuf::from)
            .or_else(|| {
                let home = std::env::var("HOME").ok()?;
                Some(
                    std::path::Path::new(&home)
                        .join(".nornir/workspaces")
                        .join(workspace)
                        .join("builds/warehouse"),
                )
            })?;
        root.is_dir().then_some(root)
    }
}

#[cfg(feature = "dupes-fat")]
impl DupeSource for LocalDupes {
    fn load(&self) -> Result<Corpus, String> {
        dwarves::dupes::local::corpus_from_local(&self.root, &self.namespace, true).map_err(|e| {
            format!(
                "local warehouse read failed at {}: {e}",
                self.root.display()
            )
        })
    }

    fn describe(&self) -> String {
        format!(
            "{} / {} (FAT — local iceberg, vectors included)",
            self.root.display(),
            self.namespace
        )
    }

    fn dep_edges(&self) -> Vec<(String, String, String)> {
        dwarves::dupes::local::dep_edges(&self.root, &self.namespace).unwrap_or_default()
    }
}

/// The never-blank demo corpus: the twin that motivated the box, and the near-miss that
/// must not be reported.
///
/// * `progress.rs` — byte-identical (same `content_hash`) in nornir and dwarves. The
///   real one, found by hand on 2026-07-22.
/// * `stage.rs` — the SAME file name in the same two repos with DIFFERENT bodies
///   (different hashes). It is in the fixture on purpose: the demo shows the tool
///   NOT reporting it.
#[cfg(any(test, feature = "fixtures"))]
pub struct FixtureDupes;

#[cfg(any(test, feature = "fixtures"))]
impl FixtureDupes {
    fn corpus() -> Corpus {
        use dwarves::dupes::corpus::{ChunkRow, SymbolRow};
        let chunk = |repo: &str, file: &str, s: u32, e: u32, h: &str| ChunkRow {
            repo: repo.into(),
            file: file.into(),
            start_line: s,
            end_line: e,
            content_hash: h.into(),
        };
        let sym = |repo: &str, file: &str, line: u32, kind: &str, name: &str| SymbolRow {
            repo: repo.into(),
            crate_name: repo.into(),
            module_path: String::new(),
            item_kind: kind.into(),
            item_name: name.into(),
            file: file.into(),
            line,
            signature: None,
        };
        Corpus::from_rows(
            vec![
                // The real twin: same body hash, two repos.
                chunk(
                    "nornir",
                    "src/release/progress.rs",
                    1,
                    192,
                    "fdeab15263c9f0188d7da2ec2fc53745",
                ),
                chunk(
                    "dwarves",
                    "crates/dwarves/src/release_doctor/progress.rs",
                    1,
                    192,
                    "fdeab15263c9f0188d7da2ec2fc53745",
                ),
                // The near-miss: same NAME, different bodies. Must not be reported.
                chunk(
                    "nornir",
                    "src/release/stage.rs",
                    1,
                    120,
                    "11111111111111111111111111111111",
                ),
                chunk(
                    "dwarves",
                    "crates/dwarves/src/release_doctor/stage.rs",
                    1,
                    96,
                    "22222222222222222222222222222222",
                ),
            ],
            vec![
                sym(
                    "nornir",
                    "src/release/progress.rs",
                    1,
                    "enum",
                    "ReleaseProgress",
                ),
                sym(
                    "dwarves",
                    "crates/dwarves/src/release_doctor/progress.rs",
                    1,
                    "enum",
                    "ReleaseProgress",
                ),
                sym("nornir", "src/release/stage.rs", 1, "fn", "rehearse"),
                sym(
                    "dwarves",
                    "crates/dwarves/src/release_doctor/stage.rs",
                    1,
                    "struct",
                    "StageGuard",
                ),
            ],
            "fixture (demo) — the progress.rs twin + the stage.rs near-miss",
        )
    }
}

#[cfg(any(test, feature = "fixtures"))]
impl DupeSource for FixtureDupes {
    fn load(&self) -> Result<Corpus, String> {
        Ok(Self::corpus())
    }
    fn describe(&self) -> String {
        "fixture (demo)".to_string()
    }
}

// ── the READ seam: lens_similar_code over Mimir.SimilarCode ────────────────────────
// The findings half of this pane. It reads the answer a jera job already folded into
// the `lens_similar_code` warehouse table; the pane adds no numbers of its own, so a
// reading here is exactly what the server computed (the same value the Lenses pane's
// `SimilarCode` view renders). Injected so a robot drives the pane over a MOCK
// `Mimir.SimilarCode` server, exactly as `robot_mimir_thin_wire.rs` does.
pub trait SimilarReader: Send + Sync {
    /// The lens answer, or an honest reason it could not be read. Blocking — the pane
    /// runs it on a worker thread so the window never waits on it.
    fn read(&self) -> Result<serde_json::Value, String>;
    /// What the header shows for the reading's origin.
    fn describe(&self) -> String;
}

/// **The shipped reader: nornir's `Mimir.SimilarCode` RPC over gRPC.**
///
/// Reads `lens_similar_code` (the jera-computed answer) for the selected workspace.
/// It NEVER folds — the server owns the warehouse and already folded on populate.
#[derive(Clone)]
pub struct RpcSimilar {
    pub endpoint: String,
    pub token: String,
    pub workspace: String,
    /// Optional repo filter (""=all), forwarded to the RPC.
    pub repo: String,
    /// Result cap (0 = the server default).
    pub limit: u32,
}

impl RpcSimilar {
    pub fn new(
        endpoint: impl Into<String>,
        token: impl Into<String>,
        workspace: impl Into<String>,
    ) -> Self {
        Self {
            endpoint: endpoint.into(),
            token: token.into(),
            workspace: workspace.into(),
            repo: String::new(),
            limit: 0,
        }
    }
}

impl SimilarReader for RpcSimilar {
    fn read(&self) -> Result<serde_json::Value, String> {
        // a lens nornir has queued on jera is asked again until it lands (this
        // read already runs as a jera job of the pane, off the frame)
        let mut similar = nornir_warehouse_embed::mimir::until_answered(
            std::time::Duration::from_secs(15 * 60),
            || {
                nornir_warehouse_embed::mimir::similar_code(
                    &self.endpoint,
                    &self.token,
                    &self.workspace,
                    &self.repo,
                    self.limit,
                )
            },
        )
        .map_err(|e| e.to_string())?;
        // the SEMANTIC TWINS beside it (`Mimir.SemanticTwins`): copies and
        // independent re-implementations, each with its plain `why`. A server
        // without the verb is said, not hidden.
        let twins = nornir_warehouse_embed::mimir::until_answered(
            std::time::Duration::from_secs(15 * 60),
            || {
                nornir_warehouse_embed::mimir::semantic_twins(
                    &self.endpoint,
                    &self.token,
                    &self.workspace,
                    &self.repo,
                    self.limit,
                )
            },
        )
        .unwrap_or_else(|e| serde_json::json!({ "unavailable": e.to_string() }));
        if let Some(o) = similar.as_object_mut() {
            o.insert("semantic_twins".into(), twins);
        }
        Ok(similar)
    }

    fn describe(&self) -> String {
        format!(
            "nornir Mimir.SimilarCode @ {} / {}",
            self.endpoint, self.workspace
        )
    }
}

/// A reader that cannot answer — the honest stand-in for a pane built for the LOCAL
/// APPLY path only (no server), so a read attempt is a named failure, never a silent
/// empty that reads as "no duplicates".
pub struct DeadReader(pub String);
impl SimilarReader for DeadReader {
    fn read(&self) -> Result<serde_json::Value, String> {
        Err(self.0.clone())
    }
    fn describe(&self) -> String {
        format!("no reader — {}", self.0)
    }
}

/// **The 🧬 Dupes** pane — a `Mimir.SimilarCode` sub-view with an apply affordance.
pub struct DupesPane {
    title: String,

    // ── the READ half (findings): lens_similar_code over Mimir.SimilarCode ──────────
    /// The reader for `lens_similar_code`. `Arc` so the off-thread worker clones it.
    reader: std::sync::Arc<dyn SimilarReader>,
    /// The last reading — the lens answer verbatim (`None` until the first read lands).
    similar: Option<serde_json::Value>,
    /// A read in flight (worker receiver + when it started). The frame polls it; the
    /// robot seam blocks on it. The read runs OFF the egui thread so `Mimir.SimilarCode`
    /// (cold: seconds) never freezes the window.
    pending: Option<(
        std::sync::mpsc::Receiver<Result<serde_json::Value, String>>,
        std::time::Instant,
    )>,
    /// Honest failure text from the last read (`None` ⇒ no failure).
    read_error: Option<String>,
    /// Whether the read-on-open has already fired (reset by [`Self::forget`]).
    auto_read: bool,

    // ── the APPLY half (escape hatch): a LOCAL fold, because the lens carries no plan ─
    /// The local-fold source — read only when the user asks to fold for apply. It exists
    /// because `lens_similar_code` does NOT carry the executable `RefactorPlan`s the
    /// apply seam drives (measured: the wire answer is ranked clusters, not proposals).
    source: Box<dyn DupeSource>,
    checkouts: Checkouts,
    /// The constellation root (`$DWARVES_CONSTELLATION`), the fallback source of
    /// leafwatch's dependency edges when the warehouse's `dep_graph_edges` is empty.
    constellation: Option<std::path::PathBuf>,
    /// How many dependency edges the last local fold had (`0` ⇒ consumer counts UNKNOWN).
    dep_edges: usize,
    /// The locally-folded report — `None` until the user presses "Fold locally for
    /// apply". This is the ONLY local fold left in the pane, and it feeds APPLY, not the
    /// findings display.
    report: Option<DupeReport>,
    /// Honest failure text from the last local fold.
    fold_error: Option<String>,
    /// The apply seam's last outcome (`apply::apply_all` over the folded report's
    /// refactor plans, dry-run by default). `None` until asked.
    apply: Option<serde_json::Value>,
}

impl DupesPane {
    /// The shipped pane, bound to the selected workspace: it READS `lens_similar_code`
    /// over `Mimir.SimilarCode`, and keeps a local-fold source for the apply escape
    /// hatch. `constellation` hydrates the apply fold's spans / dep-edge fallback.
    pub fn live(
        endpoint: impl Into<String>,
        token: impl Into<String>,
        workspace: impl Into<String>,
        constellation: Option<std::path::PathBuf>,
    ) -> Self {
        let endpoint = endpoint.into();
        let token = token.into();
        let workspace = workspace.into();
        let checkouts = constellation
            .as_deref()
            .map(Checkouts::from_constellation)
            .unwrap_or_default();
        // The findings reader is ALWAYS the thin RPC — the server folded the answer.
        let reader = std::sync::Arc::new(RpcSimilar::new(&endpoint, &token, &workspace));
        // The APPLY escape hatch's local-fold source: the fat local leg when this build
        // carries it AND a warehouse tree is on disk (the only leg the semantic tier can
        // run on), else the thin `Warehouse.Scan` fold.
        #[cfg(feature = "dupes-fat")]
        let source: Box<dyn DupeSource> = match LocalDupes::discover(&workspace) {
            Some(root) => Box::new(LocalDupes::new(root, "nornir")),
            None => Box::new(WarehouseDupes::new(&endpoint, &token, &workspace)),
        };
        #[cfg(not(feature = "dupes-fat"))]
        let source: Box<dyn DupeSource> =
            Box::new(WarehouseDupes::new(&endpoint, &token, &workspace));
        Self::assemble(reader, source, checkouts).with_constellation(constellation)
    }

    /// The never-blank demo pane (no server): the reader is dead (says so), and the
    /// apply escape hatch folds the built-in fixture corpus.
    #[cfg(any(test, feature = "fixtures"))]
    pub fn fixture() -> Self {
        Self::assemble(
            std::sync::Arc::new(DeadReader("no server — demo pane".into())),
            Box::new(FixtureDupes),
            Checkouts::new(),
        )
    }

    /// Inject a findings reader (the seam the robot drives against a mock server) with a
    /// dead apply source. For read-path tests that do not exercise the local fold.
    #[cfg(any(test, feature = "fixtures"))]
    pub fn with_reader(reader: std::sync::Arc<dyn SimilarReader>) -> Self {
        Self::assemble(reader, Box::new(FixtureDupes), Checkouts::new())
    }

    /// Inject a local-fold apply source (the seam the apply test drives) with a dead
    /// reader. The findings path stays honest-unavailable.
    pub fn with_source(source: Box<dyn DupeSource>, checkouts: Checkouts) -> Self {
        Self::assemble(
            std::sync::Arc::new(DeadReader("no reader (apply-only test pane)".into())),
            source,
            checkouts,
        )
    }

    fn assemble(
        reader: std::sync::Arc<dyn SimilarReader>,
        source: Box<dyn DupeSource>,
        checkouts: Checkouts,
    ) -> Self {
        Self {
            title: "Dupes".to_string(),
            reader,
            similar: None,
            pending: None,
            read_error: None,
            auto_read: false,
            source,
            checkouts,
            constellation: None,
            dep_edges: 0,
            report: None,
            fold_error: None,
            apply: None,
        }
    }

    /// Remember the constellation root for the apply fold's dependency-edge fallback.
    pub fn with_constellation(mut self, root: Option<std::path::PathBuf>) -> Self {
        self.constellation = root;
        self
    }

    /// Drop the reading so the pane reads again on its next frame — what a workspace
    /// change calls. Not a re-fold: the chain already folded the new workspace's answer.
    pub fn forget(&mut self) {
        self.similar = None;
        self.read_error = None;
        self.auto_read = false;
        self.report = None;
        self.apply = None;
        self.fold_error = None;
    }

    /// **Start reading `lens_similar_code` OFF the egui thread.** The worker owns a clone
    /// of the reader; the frame keeps painting and [`Self::poll`] lands the result. A
    /// read started while one is in flight is not a second round trip.
    pub fn start_read(&mut self) {
        if self.pending.is_some() {
            return;
        }
        let reader = self.reader.clone();
        let (tx, rx) = std::sync::mpsc::channel();
        // A dead reader answers at once on the worker — no wasted thread hop, but still
        // off-thread so the seam is uniform.
        std::thread::Builder::new()
            .name("dupes-similar-read".into())
            .spawn(move || {
                let _ = tx.send(reader.read());
            })
            .expect("spawn dupes read worker");
        self.pending = Some((rx, std::time::Instant::now()));
    }

    /// Non-blocking: land the in-flight read if the worker finished. Called once/frame.
    pub fn poll(&mut self) {
        let Some((rx, _)) = &self.pending else { return };
        match rx.try_recv() {
            Ok(res) => {
                self.pending = None;
                self.land_read(res);
            }
            Err(std::sync::mpsc::TryRecvError::Empty) => {}
            Err(std::sync::mpsc::TryRecvError::Disconnected) => {
                self.pending = None;
                self.read_error = Some("the read worker died before it answered".into());
            }
        }
    }

    /// Blocking: wait for the in-flight read. The ROBOT seam (`update_json`) uses this so
    /// a scripted read is complete when the call returns; the window never blocks.
    pub fn wait(&mut self) {
        let Some((rx, _)) = self.pending.take() else {
            return;
        };
        let res = rx
            .recv()
            .unwrap_or_else(|_| Err("the read worker died before it answered".into()));
        self.land_read(res);
    }

    fn land_read(&mut self, res: Result<serde_json::Value, String>) {
        match res {
            Ok(v) => {
                self.similar = Some(v);
                self.read_error = None;
            }
            Err(e) => {
                self.read_error = Some(e);
            }
        }
    }

    pub fn is_pending(&self) -> bool {
        self.pending.is_some()
    }

    /// **Fold locally for APPLY** — the escape hatch. Runs `dwarves::dupes::detect` over
    /// the apply source to produce the executable `RefactorPlan`s the lens answer does
    /// NOT carry. Never touches the findings display (that reads the lens). A load
    /// failure is recorded, never swallowed into an empty "no plan" report.
    pub fn fold_local(&mut self) {
        let mut opts = DupeOptions {
            checkouts: self.checkouts.clone(),
            ..Default::default()
        };
        opts.tiers.cross_repo_only = true;
        opts.dep_edges = self.source.dep_edges();
        if opts.dep_edges.is_empty() {
            if let Some(root) = &self.constellation {
                opts.dep_edges = dwarves::dupes::hydrate::dep_edges_from_manifests(root);
            }
        }
        self.dep_edges = opts.dep_edges.len();
        self.apply = None;
        match self.source.load() {
            Ok(corpus) => {
                self.fold_error = None;
                self.report = Some(detect(&corpus, &opts));
            }
            Err(e) => {
                self.fold_error = Some(e);
                self.report = None;
            }
        }
    }

    /// Run the apply seam over the current local fold's refactor plans. `DryRun` projects
    /// the ordered transcript (no executor called); `Execute` drives each plan's state
    /// machine through a [`RecordingExecutor`] (no filesystem I/O). Empty when no plan.
    fn run_apply(&mut self, mode: ApplyMode) {
        let Some(report) = &self.report else {
            self.apply = None;
            return;
        };
        let plans = report.proposals.plans();
        let mut exec = RecordingExecutor::default();
        self.apply = Some(apply_all(plans, mode, &mut exec));
    }

    /// **The provenance line** — what the answer rests on, read off its own
    /// `lens_meta.state` (Mímir v2), never asserted: `similar_code · complete`,
    /// `· partial (lower bound)`, `· empty: nothing found`, or — when the lens did not
    /// compute — its state by name (`NOT WIRED`, `EMPTY, INPUT MISSING`, a refusal).
    /// An answer with no state is named as that; its list is not a verdict.
    pub fn provenance(&self) -> String {
        use crate::mimir_lens::{lens_state_word, LensAnswer};
        if self.pending.is_some() {
            return "similar_code · reading Mimir.SimilarCode…".to_string();
        }
        if let Some(e) = &self.read_error {
            return format!("similar_code · READ FAILED — {e}");
        }
        let Some(v) = &self.similar else {
            return "similar_code · not read yet".to_string();
        };
        let word = lens_state_word(v);
        let mut parts = vec!["similar_code".to_string()];
        parts.push(match LensAnswer::of(v) {
            LensAnswer::Complete => "complete".to_string(),
            LensAnswer::Partial => "partial (lower bound)".to_string(),
            LensAnswer::EmptyFact => "empty: nothing found".to_string(),
            LensAnswer::EmptyGap => "EMPTY, INPUT MISSING — not a verdict".to_string(),
            LensAnswer::NotWired => {
                let producer = v
                    .get("lens_meta")
                    .and_then(|m| m.get("missing_producer"))
                    .and_then(|p| p.as_str())
                    .unwrap_or("");
                if producer.is_empty() {
                    "NOT WIRED".to_string()
                } else {
                    format!("NOT WIRED — waits for {producer}")
                }
            }
            LensAnswer::Refused => format!("REFUSED [{word}]"),
            LensAnswer::Unstated if word.is_empty() => {
                "NO STATE (not a Mímir v2 answer)".to_string()
            }
            LensAnswer::Unstated => format!("UNKNOWN STATE `{word}`"),
            LensAnswer::Waiting => format!("{} on the server — asked again until it lands", word.to_uppercase()),
            LensAnswer::Failed => "ERROR — the call failed".to_string(),
        });
        // The missing-feed honesty, off the answer's own feed record.
        let missing: Vec<String> = v
            .get("feeds")
            .and_then(|f| f.as_array())
            .map(|a| {
                a.iter()
                    .filter(|f| f.get("missing").and_then(|m| m.as_bool()) == Some(true))
                    .filter_map(|f| {
                        f.get("table")
                            .and_then(|t| t.as_str())
                            .map(|s| s.to_string())
                    })
                    .collect()
            })
            .unwrap_or_default();
        if !missing.is_empty() {
            parts.push(format!("feeds missing: {}", missing.join(", ")));
        }
        parts.join(" · ")
    }

    /// The one-line status the header shows. A cluster count only when the lens
    /// COMPUTED: `0 similar-code cluster(s)` from a lens that is not wired would be a
    /// zero nobody measured.
    fn status(&self) -> String {
        if self.pending.is_some() {
            return "reading Mimir.SimilarCode… — the window is not blocked".to_string();
        }
        if let Some(e) = &self.read_error {
            return format!("similar_code unavailable — {e}");
        }
        match &self.similar {
            Some(v) if !crate::mimir_lens::LensAnswer::of(v).is_measured() => {
                format!("no similar-code reading — {}", self.provenance())
            }
            Some(v) => {
                let total = v.get("cluster_count_total").and_then(|n| n.as_u64());
                let shown = v.get("clusters_shown").and_then(|n| n.as_u64());
                match (total, shown) {
                    (Some(t), Some(s)) => format!("{t} similar-code cluster(s) · showing {s}"),
                    _ => {
                        let n = v
                            .get("top_clusters")
                            .and_then(|a| a.as_array())
                            .map(|a| a.len())
                            .unwrap_or(0);
                        format!("{n} similar-code cluster(s)")
                    }
                }
            }
            None => "not read yet — reading on open".to_string(),
        }
    }
}

fn chip(ui: &mut egui::Ui, text: &str, fill: egui::Color32) {
    ui.label(
        egui::RichText::new(format!(" {text} "))
            .background_color(fill)
            .color(egui::Color32::WHITE)
            .monospace(),
    );
}

const TEAL: egui::Color32 = egui::Color32::from_rgb(0x00, 0x69, 0x5c);

impl Facet for DupesPane {
    fn title(&self) -> &str {
        &self.title
    }

    fn ui(&mut self, ui: &mut egui::Ui) {
        // Read ITSELF on open — the chain folded the answer, so making the operator press
        // a button is friction. Poll the in-flight read every frame.
        self.poll();
        if !self.auto_read
            && self.similar.is_none()
            && self.pending.is_none()
            && self.read_error.is_none()
        {
            self.auto_read = true;
            self.start_read();
        }
        if self.pending.is_some() {
            ui.ctx().request_repaint();
        }

        // NO Scan/⟳ button — this is now the Similar Code sub-view under Lenses, and the
        // jera chain folds off populate in the background (owner 2026-08-22). It reads
        // itself on open; the header says computed/queued/not-computed. The only action
        // is the explicit local-fold-for-APPLY below, which the lens result cannot carry.
        ui.heading("🧬 duplicate box");
        // PROVENANCE first — a stale reading of a moved warehouse is worse than none.
        ui.label(egui::RichText::new(self.provenance()).monospace());
        ui.label(egui::RichText::new(self.status()).monospace());
        ui.label(egui::RichText::new(format!("source: {}", self.reader.describe())).small());
        ui.separator();

        // ── FINDINGS — READ from lens_similar_code, never folded here ────────────────
        ui.horizontal_wrapped(|ui| {
            chip(ui, "nornir RPC", TEAL);
            ui.label(
                egui::RichText::new(
                    "Mimir.SimilarCode — the relocated dupes query, computed by nornir on the \
                     request and READ here. This pane does not fold; the line below is what \
                     the answer says it rests on.",
                )
                .small(),
            );
        });
        if let Some(v) = &self.similar {
            if let Some(note) = v
                .get("evidence_note")
                .and_then(|n| n.as_str())
                .filter(|s| !s.is_empty())
            {
                ui.label(egui::RichText::new(note).small().italics());
            }
            egui::ScrollArea::vertical()
                .max_height(300.0)
                .id_salt("dupes-similar")
                .show(ui, |ui| {
                    for c in v
                        .get("top_clusters")
                        .and_then(|a| a.as_array())
                        .map(|a| a.as_slice())
                        .unwrap_or(&[])
                    {
                        ui.horizontal_wrapped(|ui| {
                            let size = c.get("size").and_then(|n| n.as_u64()).unwrap_or(0);
                            let cos = c.get("avg_cosine").and_then(|n| n.as_f64()).unwrap_or(0.0);
                            let stru = c.get("structural").and_then(|n| n.as_f64()).unwrap_or(0.0);
                            chip(
                                ui,
                                &format!("×{size}"),
                                egui::Color32::from_rgb(0x15, 0x65, 0xc0),
                            );
                            ui.monospace(format!("cos {cos:.3} · struct {stru:.2}"));
                            let canon = c.get("canonical").and_then(|s| s.as_str()).unwrap_or("?");
                            ui.label(format!("canonical: {canon}"));
                        });
                    }
                });
            // ── SEMANTIC TWINS — Mimir.SemanticTwins, read beside SimilarCode ──────────
            ui.separator();
            ui.heading("🧬 semantic twins");
            match v.get("semantic_twins") {
                Some(t) if t.get("unavailable").is_some() => {
                    ui.label(egui::RichText::new(format!("semantic twins unavailable — {}", t["unavailable"].as_str().unwrap_or("?"))).small());
                }
                Some(t) => {
                    ui.label(
                        egui::RichText::new(format!(
                            "{} twin(s) · {} copy(ies) · {} deliberate SIMD/width famil(ies) kept out",
                            t.get("twins").and_then(|n| n.as_u64()).unwrap_or(0),
                            t.get("copies").and_then(|n| n.as_u64()).unwrap_or(0),
                            t.get("deliberate_families").and_then(|n| n.as_u64()).unwrap_or(0),
                        ))
                        .monospace(),
                    );
                    if let Some(note) = t.get("evidence_note").and_then(|n| n.as_str()) {
                        egui::CollapsingHeader::new("how it works").id_salt("dupes-twins-theory").show(ui, |ui| {
                            ui.label(egui::RichText::new(note).small().italics());
                        });
                    }
                    egui::ScrollArea::vertical().max_height(300.0).id_salt("dupes-twins").show(ui, |ui| {
                        for f in t.get("worst").and_then(|a| a.as_array()).map(|a| a.as_slice()).unwrap_or(&[]) {
                            ui.horizontal_wrapped(|ui| {
                                let kind = f.get("kind").and_then(|k| k.as_str()).unwrap_or("?");
                                let fill = if kind == "twin" { egui::Color32::from_rgb(0x6a, 0x1b, 0x9a) } else { egui::Color32::from_rgb(0x15, 0x65, 0xc0) };
                                chip(ui, kind, fill);
                                ui.label(f.get("why").and_then(|w| w.as_str()).unwrap_or(""));
                            });
                            for m in f.get("members").and_then(|a| a.as_array()).map(|a| a.as_slice()).unwrap_or(&[]) {
                                ui.monospace(format!(
                                    "    {} — {}:{} ({})",
                                    m.get("path").and_then(|p| p.as_str()).unwrap_or("?"),
                                    m.get("file").and_then(|p| p.as_str()).unwrap_or("?"),
                                    m.get("line").and_then(|p| p.as_u64()).unwrap_or(0),
                                    m.get("repo").and_then(|p| p.as_str()).unwrap_or("?"),
                                ));
                            }
                        }
                    });
                }
                None => {}
            }
        } else if self.read_error.is_some() {
            ui.label(
                egui::RichText::new(
                    "the reading failed — this is an honest UNAVAILABLE, not a green \"no duplicates\"",
                )
                .small(),
            );
        }

        // ── APPLY — a LOCAL fold, because the lens answer carries no executable plan ──
        ui.separator();
        ui.horizontal_wrapped(|ui| {
            chip(ui, "apply seam", TEAL);
            ui.label(
                egui::RichText::new(
                    "APPLY needs the type-gated absorb→delete→repoint RefactorPlans, which \
                     lens_similar_code does NOT carry — so this button folds LOCALLY \
                     (dwarves::dupes) to produce them. Findings above stay read from the lens.",
                )
                .small(),
            );
        });
        let mut apply_request: Option<ApplyMode> = None;
        let mut fold_request = false;
        ui.horizontal_wrapped(|ui| {
            if ui.button("⚒ Fold locally for apply").clicked() {
                fold_request = true;
            }
            if self.report.is_some() {
                if ui.button("▷ Dry-run apply").clicked() {
                    apply_request = Some(ApplyMode::DryRun);
                }
                if ui.button("⚙ Execute (recording, no fs)").clicked() {
                    apply_request = Some(ApplyMode::Execute);
                }
            }
        });
        if let Some(e) = &self.fold_error {
            ui.label(egui::RichText::new(format!("local fold failed — {e}")).small());
        }
        if let Some(r) = &self.report {
            let plans = r.proposals.plans();
            ui.label(
                egui::RichText::new(format!(
                    "folded locally · {} executable refactor plan(s)",
                    plans.len()
                ))
                .small()
                .monospace(),
            );
            egui::ScrollArea::vertical()
                .max_height(180.0)
                .id_salt("dupes-plans")
                .show(ui, |ui| {
                    for pl in plans.iter().take(20) {
                        ui.separator();
                        ui.label(egui::RichText::new(&pl.why).strong());
                        ui.label(
                            egui::RichText::new(format!("survivor: {}", pl.survivor))
                                .small()
                                .monospace(),
                        );
                        ui.horizontal(|ui| {
                            chip(
                                ui,
                                &format!("1. absorb ×{}", pl.absorb().len()),
                                egui::Color32::from_rgb(0xef, 0x6c, 0x00),
                            );
                            chip(
                                ui,
                                &format!("2. delete {} unlocked", pl.delete().len()),
                                egui::Color32::from_rgb(0xc6, 0x28, 0x28),
                            );
                            chip(
                                ui,
                                &format!("3. repoint ×{}", pl.repoint.len()),
                                egui::Color32::from_rgb(0x15, 0x65, 0xc0),
                            );
                        });
                    }
                });
        }
        if let Some(a) = &self.apply {
            let mode = a.get("mode").and_then(|m| m.as_str()).unwrap_or("");
            ui.horizontal_wrapped(|ui| {
                chip(
                    ui,
                    &format!(
                        "{mode}: {} plan(s) · absorb {} · {} {} · repoint {}",
                        a.get("plans").and_then(|n| n.as_u64()).unwrap_or(0),
                        a.get("absorbed").and_then(|n| n.as_u64()).unwrap_or(0),
                        if mode == "dry-run" {
                            "deletable"
                        } else {
                            "deleted"
                        },
                        if mode == "dry-run" {
                            a.get("deletable").and_then(|n| n.as_u64()).unwrap_or(0)
                        } else {
                            a.get("deleted").and_then(|n| n.as_u64()).unwrap_or(0)
                        },
                        a.get("repointed").and_then(|n| n.as_u64()).unwrap_or(0),
                    ),
                    if mode == "dry-run" {
                        egui::Color32::from_rgb(0x15, 0x65, 0xc0)
                    } else {
                        egui::Color32::from_rgb(0x2e, 0x7d, 0x32)
                    },
                );
            });
        }

        if fold_request {
            self.fold_local();
        }
        if let Some(m) = apply_request {
            self.run_apply(m);
        }
    }

    fn state_json(&self) -> serde_json::Value {
        let mut obj = serde_json::Map::new();
        obj.insert("kind".into(), serde_json::json!("dupes"));
        obj.insert("title".into(), serde_json::json!(self.title));
        obj.insert("source".into(), serde_json::json!(self.reader.describe()));
        obj.insert("status".into(), serde_json::json!(self.status()));
        obj.insert("provenance".into(), serde_json::json!(self.provenance()));
        // The read half: whether a reading has landed (a failed read is NOT scanned).
        obj.insert("scanned".into(), serde_json::json!(self.similar.is_some()));
        obj.insert("pending".into(), serde_json::json!(self.pending.is_some()));
        obj.insert("read_error".into(), serde_json::json!(self.read_error));
        // The lens answer VERBATIM — the pane adds no numbers, so a robot asserting on
        // `reading` is asserting on exactly what the server computed.
        obj.insert(
            "reading".into(),
            self.similar.clone().unwrap_or(serde_json::Value::Null),
        );
        obj.insert(
            "cluster_count_total".into(),
            self.similar
                .as_ref()
                .and_then(|v| v.get("cluster_count_total").cloned())
                .unwrap_or(serde_json::Value::Null),
        );
        obj.insert(
            "clusters_shown".into(),
            self.similar
                .as_ref()
                .and_then(|v| v.get("clusters_shown").cloned())
                .unwrap_or(serde_json::Value::Null),
        );
        // The apply half (LOCAL fold escape hatch): whether a fold is present, its plan
        // count, and the last apply outcome. `folded_locally` is the honest provenance of
        // the apply input — it is NEVER the lens answer.
        obj.insert(
            "folded_locally".into(),
            serde_json::json!(self.report.is_some()),
        );
        obj.insert("fold_error".into(), serde_json::json!(self.fold_error));
        obj.insert("dep_edges".into(), serde_json::json!(self.dep_edges));
        obj.insert(
            "apply_plan_count".into(),
            serde_json::json!(self
                .report
                .as_ref()
                .map(|r| r.proposals.plans().len())
                .unwrap_or(0)),
        );
        obj.insert(
            "apply".into(),
            self.apply.clone().unwrap_or(serde_json::Value::Null),
        );
        serde_json::Value::Object(obj)
    }

    fn update_json(&mut self, msg_json: &str) {
        // The remote seam. `"read"` / `{"read":true}` reads lens_similar_code (blocking
        // for a scripted caller, so the read is complete on return). `"fold"` /
        // `{"fold":true}` runs the LOCAL apply fold. `{"apply":"dry-run"|"execute"}`
        // drives the apply seam over that fold.
        let trimmed = msg_json.trim();
        if trimmed == "\"read\"" || trimmed == "\"scan\"" {
            self.start_read();
            self.wait();
            return;
        }
        if trimmed == "\"fold\"" {
            self.fold_local();
            return;
        }
        let Ok(v) = serde_json::from_str::<serde_json::Value>(msg_json) else {
            return;
        };
        if v.get("read").and_then(|b| b.as_bool()).unwrap_or(false)
            || v.get("scan").and_then(|b| b.as_bool()).unwrap_or(false)
        {
            self.start_read();
            self.wait();
        }
        if v.get("fold").and_then(|b| b.as_bool()).unwrap_or(false) {
            self.fold_local();
        }
        if let Some(mode) = v.get("apply").and_then(|m| m.as_str()) {
            match mode {
                "dry-run" | "dry_run" | "dryrun" => self.run_apply(ApplyMode::DryRun),
                "execute" | "apply" => self.run_apply(ApplyMode::Execute),
                _ => {}
            }
        }
    }
}

/// The shipped Dupes tab, bound to the SELECTED workspace. Reads `lens_similar_code`
/// over `Mimir.SimilarCode`; `$DWARVES_CONSTELLATION` hydrates the apply escape hatch.
pub fn dupes_pane(endpoint: &str, token: &str, workspace: &str) -> DupesPane {
    let constellation = std::env::var("DWARVES_CONSTELLATION")
        .ok()
        .map(std::path::PathBuf::from);
    DupesPane::live(endpoint, token, workspace, constellation)
}

#[cfg(test)]
mod tests {
    use super::*;

    /// A findings reader that returns a fixed lens answer — the seam a unit test drives
    /// without a server (the robot suite uses the REAL RPC against a mock server).
    struct CannedReader(serde_json::Value);
    impl SimilarReader for CannedReader {
        fn read(&self) -> Result<serde_json::Value, String> {
            Ok(self.0.clone())
        }
        fn describe(&self) -> String {
            "canned lens_similar_code".into()
        }
    }

    /// A `Mimir.SimilarCode` answer in nornir's Mímir v2 envelope: ranked clusters, the
    /// feeds it read, `lens_meta.state` + an over-wire sentinel a LOCAL fold could never
    /// synthesise.
    fn lens_answer() -> serde_json::Value {
        serde_json::json!({
            "__over_wire__": true,
            "kind": "similar_code",
            "cluster_count": 2,
            "cluster_count_total": 2,
            "clusters_shown": 2,
            "top_clusters": [
                { "canonical": "nornir#progress", "size": 2, "avg_cosine": 0.99, "structural": 0.9, "score": 1.98 },
                { "canonical": "korp#config", "size": 3, "avg_cosine": 0.94, "structural": 0.7, "score": 2.82 }
            ],
            "evidence_note": "similar_code: 2 cluster(s). MISSING: `embeddings` carried no row for 1 repo.",
            "feeds": [ { "table": "embeddings", "rows": 0, "root": "", "missing": true } ],
            "lens_meta": { "state": "partial", "lens": "similar_code", "repo_scope": "", "gaps": [], "lower_bounds": [], "ms": 4 }
        })
    }

    /// **RED-when-broken: the findings are READ from lens_similar_code, never folded.**
    ///
    /// The reading carries `__over_wire__` — a marker no local `detect()` fold could ever
    /// produce — so seeing it in the pane proves the read path, not the fold. And the
    /// pane never calls `detect` on open: `folded_locally` is false and there is no plan
    /// until the apply escape hatch is pressed. Before this refactor the tab folded
    /// locally over `Warehouse.Scan`, so `reading` would be Null / never carry the
    /// sentinel — this asserts the fold path is gone.
    #[test]
    fn the_findings_are_read_from_the_lens_not_folded_locally() {
        let mut pane = DupesPane::with_reader(std::sync::Arc::new(CannedReader(lens_answer())));

        // Read (the shipped seam blocks so the scripted read is complete on return).
        Facet::update_json(&mut pane, "\"read\"");
        let s = pane.state_json();

        assert_eq!(s["scanned"], true, "the reading landed: {}", s["status"]);
        assert_eq!(s["pending"], false);
        // The value is the SERVER's — a local fold has no `__over_wire__`.
        assert_eq!(
            s["reading"]["__over_wire__"], true,
            "read from the lens, not folded: {}",
            s["reading"]
        );
        assert_eq!(s["reading"]["top_clusters"].as_array().unwrap().len(), 2);
        assert_eq!(s["cluster_count_total"], 2);
        // detect() was NOT called: no local fold, no plan.
        assert_eq!(
            s["folded_locally"], false,
            "the findings path never folds locally"
        );
        assert_eq!(s["apply_plan_count"], 0);
    }

    /// **RED-when-broken: provenance is DERIVED off `lens_meta.state`, and it is honest.**
    ///
    /// The header must say what the answer RESTS ON. A computed answer says its state
    /// and the feeds that were missing; a lens that waits for a producer says NOT WIRED
    /// and names the producer — and the status line then carries no cluster count, since
    /// `0 similar-code cluster(s)` from a lens that never ran is a zero nobody measured.
    #[test]
    fn the_provenance_header_says_what_the_answer_rests_on() {
        // (a) computed with a feed missing ⇒ the state + the missing feed.
        let mut pane = DupesPane::with_reader(std::sync::Arc::new(CannedReader(lens_answer())));
        Facet::update_json(&mut pane, "\"read\"");
        let s = pane.state_json();
        let prov = s["provenance"].as_str().unwrap().to_string();
        assert!(
            prov.starts_with("similar_code · partial (lower bound)"),
            "{prov}"
        );
        assert!(prov.contains("feeds missing: embeddings"), "{prov}");
        assert!(
            s["status"]
                .as_str()
                .unwrap()
                .contains("2 similar-code cluster(s)"),
            "{}",
            s["status"]
        );

        // (b) what nornir answers today: `not_wired`, naming the producer it waits for.
        let waiting = serde_json::json!({
            "kind": "similar_code",
            "worst": [],
            "feeds": [],
            "evidence_note": "similar_code: Mímir v2: producer not wired yet — a missing producer, not an absence of findings. Missing producer: item embeddings from driver spans.",
            "lens_meta": { "state": "not_wired", "lens": "similar_code", "missing_producer": "item embeddings from driver spans" }
        });
        let mut pane = DupesPane::with_reader(std::sync::Arc::new(CannedReader(waiting)));
        Facet::update_json(&mut pane, "\"read\"");
        let s = pane.state_json();
        let prov = s["provenance"].as_str().unwrap().to_string();
        assert!(
            prov.contains("NOT WIRED — waits for item embeddings from driver spans"),
            "a lens without a producer says so, and which: {prov}"
        );
        let status = s["status"].as_str().unwrap();
        assert!(status.contains("no similar-code reading"), "{status}");
        assert!(
            !status.contains("0 similar-code cluster(s)"),
            "never a zero nobody measured: {status}"
        );

        // (c) no state at all ⇒ named as that, never as a computed answer.
        let plain = serde_json::json!({ "top_clusters": [], "cluster_count_total": 0, "clusters_shown": 0 });
        let mut pane = DupesPane::with_reader(std::sync::Arc::new(CannedReader(plain)));
        Facet::update_json(&mut pane, "\"read\"");
        let prov = pane.state_json()["provenance"]
            .as_str()
            .unwrap()
            .to_string();
        assert!(prov.contains("NO STATE (not a Mímir v2 answer)"), "{prov}");
    }

    /// A read that fails is an honest UNAVAILABLE, never a green "no duplicates".
    #[test]
    fn a_failed_read_is_unavailable_never_a_green_zero() {
        let mut pane = DupesPane::with_reader(std::sync::Arc::new(DeadReader(
            "nornir-server unreachable".into(),
        )));
        Facet::update_json(&mut pane, "\"read\"");
        let s = pane.state_json();
        assert_eq!(s["scanned"], false, "a failed read is NOT a reading");
        assert_eq!(
            s["reading"],
            serde_json::Value::Null,
            "and produces no findings at all"
        );
        assert!(
            s["read_error"].as_str().unwrap().contains("unreachable"),
            "{}",
            s["read_error"]
        );
        assert!(
            s["provenance"].as_str().unwrap().contains("READ FAILED"),
            "{}",
            s["provenance"]
        );
    }

    /// A source whose twin is a clean LEAF CANDIDATE (extract-to-edda): a
    /// `login_config_from_env` helper duplicated across two repos, so `detect` yields a
    /// real executable `RefactorPlan` and `proposals.plans()` is non-empty.
    struct LeafSource;
    impl DupeSource for LeafSource {
        fn load(&self) -> Result<Corpus, String> {
            use dwarves::dupes::corpus::{ChunkRow, SymbolRow};
            let chunk = |repo: &str, file: &str, h: &str| ChunkRow {
                repo: repo.into(),
                file: file.into(),
                start_line: 1,
                end_line: 40,
                content_hash: h.into(),
            };
            let sym = |repo: &str, file: &str| SymbolRow {
                repo: repo.into(),
                crate_name: repo.into(),
                module_path: String::new(),
                item_kind: "fn".into(),
                item_name: "login_config_from_env".into(),
                file: file.into(),
                line: 1,
                signature: None,
            };
            Ok(Corpus::from_rows(
                vec![
                    chunk("korp", "src/config.rs", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                    chunk("knut", "src/config.rs", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                ],
                vec![sym("korp", "src/config.rs"), sym("knut", "src/config.rs")],
                "fixture (demo) — a clean cross-repo login_config_from_env leaf candidate",
            ))
        }
        fn describe(&self) -> String {
            "fixture (leaf candidate)".into()
        }
    }

    /// **ROBOT — the APPLY SEAM survives the refactor: the local-fold escape hatch
    /// DRY-RUNS and EXECUTES, and read-only stays read-only where no plan exists.**
    ///
    /// The findings now come from the lens; APPLY still needs the executable plans the
    /// lens does not carry, so it folds LOCALLY behind the `"fold"` verb. This drives
    /// that fold then `{"apply":"dry-run"}` / `{"apply":"execute"}` and asserts the
    /// OUTCOME — not that a button exists.
    #[test]
    fn the_apply_seam_dry_runs_and_executes_the_local_fold() {
        let mut pane = DupesPane::with_source(Box::new(LeafSource), Checkouts::new());

        // Before a fold there is no plan — the seam is empty and asking does nothing.
        Facet::update_json(&mut pane, r#"{"apply":"dry-run"}"#);
        assert_eq!(
            pane.state_json()["apply"],
            serde_json::Value::Null,
            "no plan ⇒ nothing to apply"
        );
        assert_eq!(pane.state_json()["apply_plan_count"], 0);
        assert_eq!(pane.state_json()["folded_locally"], false);

        // Fold locally for apply.
        Facet::update_json(&mut pane, "\"fold\"");
        assert_eq!(
            pane.state_json()["folded_locally"],
            true,
            "the escape hatch folded"
        );
        let plan_count = pane.state_json()["apply_plan_count"].as_u64().unwrap();
        assert!(
            plan_count >= 1,
            "the leaf-candidate twin yields at least one executable plan: {plan_count}"
        );

        // ── DRY-RUN — project the transcript, touch nothing ──────────────────────────
        Facet::update_json(&mut pane, r#"{"apply":"dry-run"}"#);
        let dry = pane.state_json()["apply"].clone();
        assert_eq!(dry["mode"], "dry-run");
        assert_eq!(dry["plans"], plan_count, "every computed plan is projected");
        assert!(
            dry["absorbed"].as_u64().unwrap() >= 1,
            "the non-survivor copy is drained: {dry}"
        );
        assert!(
            dry["deletable"].as_u64().unwrap() >= 1,
            "…and becomes a would-delete"
        );
        assert_eq!(dry["deleted"], 0, "a DRY-RUN deletes nothing");
        let o0 = &dry["outcomes"][0];
        assert_eq!(o0["executed"], false, "the executor was never called");

        // ── EXECUTE — drive the state machine (recording executor, no fs I/O) ─────────
        Facet::update_json(&mut pane, r#"{"apply":"execute"}"#);
        let exe = pane.state_json()["apply"].clone();
        assert_eq!(exe["mode"], "execute");
        assert!(
            exe["deleted"].as_u64().unwrap() >= 1,
            "EXECUTE deletes the copy once its knowledge is absorbed: {exe}"
        );
        assert_eq!(exe["blocked"], 0, "a clean run leaves nothing pending");
        let eo0 = &exe["outcomes"][0];
        assert_eq!(eo0["executed"], true);
        let survivor = eo0["survivor"].as_str().unwrap();
        let deleted: Vec<String> = serde_json::from_value(eo0["deleted"].clone()).unwrap();
        assert!(
            !deleted.contains(&survivor.to_string()),
            "the survivor is never deleted: {eo0}"
        );
        assert!(
            !deleted.is_empty(),
            "at least one copy was deleted after absorb"
        );

        // A re-fold supersedes the apply outcome — a stale claim over gone plans is never kept.
        Facet::update_json(&mut pane, "\"fold\"");
        assert_eq!(
            pane.state_json()["apply"],
            serde_json::Value::Null,
            "a fresh fold clears the prior apply"
        );
    }

    /// **RED-when-broken: the reader names the leg it reads.** The shipped reader speaks
    /// `Mimir.SimilarCode`; a pane that silently reverted to a local warehouse scan would
    /// stop saying so.
    #[test]
    fn the_reader_names_the_similarcode_rpc() {
        let r = RpcSimilar::new("http://127.0.0.1:7878", "", "nordisk");
        assert!(
            r.describe().contains("Mimir.SimilarCode"),
            "{}",
            r.describe()
        );
        assert!(r.describe().contains("nordisk"), "{}", r.describe());
    }
}