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());
}
}