From 3d1581eb7499069f2aa618076eee918446440910 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 06:54:21 +0000 Subject: [PATCH 01/11] codegraph: coverage-aware impact report (D-CODEGRAPH-RECON-2 Gate A) Codegraph::impact is unchanged. impact_report returns the same masks plus typed gaps from store facts and a declared scope: unobserved external consumers of a PUBLIC symbol, targets not extracted or undeclared, a dynamic call that may reach the symbol, an incomplete harvest, stale or unrecorded source files, unchecked freshness. A missing symbol is Missing, never an empty answer. Unobserved callers never become positions in Graded.unknown. closed_in_scope is local to the declared scope; no-known-gap is not global completeness. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- crates/lance-graph-codegraph/src/artifact.rs | 10 + crates/lance-graph-codegraph/src/graph.rs | 23 + .../src/impact_report.rs | 337 +++++++++++++++ crates/lance-graph-codegraph/src/lib.rs | 1 + .../tests/impact_coverage.rs | 406 ++++++++++++++++++ 5 files changed, 777 insertions(+) create mode 100644 crates/lance-graph-codegraph/src/impact_report.rs create mode 100644 crates/lance-graph-codegraph/tests/impact_coverage.rs diff --git a/crates/lance-graph-codegraph/src/artifact.rs b/crates/lance-graph-codegraph/src/artifact.rs index a28e2041f..5d75fc47f 100644 --- a/crates/lance-graph-codegraph/src/artifact.rs +++ b/crates/lance-graph-codegraph/src/artifact.rs @@ -104,6 +104,16 @@ pub fn digest(bytes: &[u8]) -> u64 { h.finish() } +/// FNV-1a 64 of `bytes` as 16 lowercase hex digits: the digest ruff_charon +/// writes to `.files.tsv` (`ruff_charon::store::fnv64`, `{:016x}`). +/// Not [`digest`], which is the rows-file change detector. +pub fn fnv64_hex(bytes: &[u8]) -> String { + let h = bytes.iter().fold(0xcbf2_9ce4_8422_2325u64, |h, &b| { + (h ^ u64::from(b)).wrapping_mul(0x0100_0000_01b3) + }); + format!("{h:016x}") +} + /// A multiply-rotate hasher folding eight bytes per step. The interner is /// keyed by short symbol paths and is hit about once per row; SipHash made /// those lookups the dominant cost. Not DoS-resistant, which is fine for a diff --git a/crates/lance-graph-codegraph/src/graph.rs b/crates/lance-graph-codegraph/src/graph.rs index d6a20e156..80cd39639 100644 --- a/crates/lance-graph-codegraph/src/graph.rs +++ b/crates/lance-graph-codegraph/src/graph.rs @@ -1005,6 +1005,29 @@ impl Codegraph { .count() as u32 } + /// Names of the crates with a CRATE row: the first path segment of the + /// symbols each crate defines. + pub(crate) fn stored_crates(&self) -> std::collections::BTreeSet<&str> { + self.crates + .keys() + .map(|&id| self.symbols.name(id)) + .collect() + } + + /// Residual counts of the crate named `krate`, and whether no residuals + /// file was read for it. A name the store did not read under is reported + /// as having no file: unknown, never clean. + pub(crate) fn residuals_of_crate(&self, krate: &str) -> (artifact::ResidualCounts, bool) { + match self + .symbols + .get(krate) + .and_then(|id| self.lanes.residuals_of(id)) + { + Some(Some(r)) => (r, false), + _ => (artifact::ResidualCounts::default(), true), + } + } + /// Whether any stored crate's CRATE row is not `COMPLETE`. pub(crate) fn any_partial(&self) -> bool { self.crates.values().any(|&s| s == RunStatus::Partial) diff --git a/crates/lance-graph-codegraph/src/impact_report.rs b/crates/lance-graph-codegraph/src/impact_report.rs new file mode 100644 index 000000000..c6f92d0d1 --- /dev/null +++ b/crates/lance-graph-codegraph/src/impact_report.rs @@ -0,0 +1,337 @@ +//! Coverage-aware impact: [`Codegraph::impact`] plus a typed account of what +//! the answer could not see. +//! +//! [`Codegraph::impact`] answers over symbol positions. A caller the store +//! never observed has no position, so an empty answer cannot tell "nothing +//! depends on this" from "the dependants were never extracted". This report +//! keeps the impact masks exactly as `impact` returns them and adds a list of +//! [`Gap`]s, each a fact the store or the declared [`Scope`] actually holds. +//! Missing coverage is never written into `Graded.unknown`, which stays the set +//! of observed functions a dynamic call may reach. +//! +//! [`ImpactReport::closed_in_scope`] is the only "nothing else" claim this +//! module makes, and it is local: no gap is known *within the declared scope*. +//! It is never a statement about code outside the stored crates. + +use std::collections::BTreeSet; +use std::path::{Path, PathBuf}; + +use crate::artifact::{fnv64_hex, ResidualCounts}; +use crate::graph::{Codegraph, Pos}; +use crate::query::{Graded, QueryRefusal}; + +/// Which targets of one crate were extracted into the store. The store does +/// not record this; the caller declares it from how the extractor was run. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct Targets { + /// The library target. + pub lib: bool, + /// Integration tests and `#[cfg(test)]` unit tests. + pub tests: bool, + /// Examples. + pub examples: bool, + /// Benches. + pub benches: bool, +} + +impl Targets { + /// The library target only (Charon's default `charon cargo` run). + pub const LIB_ONLY: Targets = Targets { + lib: true, + tests: false, + examples: false, + benches: false, + }; + + /// Every target kind. + pub const ALL: Targets = Targets { + lib: true, + tests: true, + examples: true, + benches: true, + }; + + fn missing(self) -> Targets { + Targets { + lib: !self.lib, + tests: !self.tests, + examples: !self.examples, + benches: !self.benches, + } + } + + fn any(self) -> bool { + self.lib || self.tests || self.examples || self.benches + } +} + +/// What the caller asserts about the analysis beyond the store's own rows. +#[derive(Debug, Clone, Default)] +pub struct Scope { + /// The store directory, for `.files.tsv`. + pub store: Option, + /// The source root the recorded paths are relative to. `None` means + /// freshness was not checked, which is itself a gap. + pub source_root: Option, + /// Extracted targets per stored crate name. A stored crate without an + /// entry is `TargetsUndeclared`. + pub targets: Vec<(String, Targets)>, + /// The caller asserts that every crate which can call the symbol's crate + /// is in the store (for example an unpublished crate whose whole + /// dependent set was extracted). Without this, a public symbol's external + /// callers are unobserved. + pub consumers_closed: bool, +} + +/// Whether the queried symbol has a position. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SymbolState { + /// The symbol is in the store. + Found(Pos), + /// No stored row names the symbol. + Missing { + /// The symbol's first path segment names a stored crate: the crate + /// was read and does not define or mention it. When false, the symbol + /// lies outside every stored crate and nothing was looked at. + owner_stored: bool, + }, +} + +/// One reason the impact answer may be incomplete. Every variant comes from +/// a store fact or a declared scope fact; none is inferred. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Gap { + /// The symbol is `PUBLIC` and the consumer set is not declared closed: + /// crates outside the store can call it. `observed_consumers` lists the + /// stored crates other than the owner that already call into it. + ExternalConsumersUnobserved { + /// The symbol's crate. + owner: String, + /// Other stored crates with a confirmed caller in the answer. + observed_consumers: Vec, + }, + /// Targets of the owning crate that were not extracted, so callers there + /// (for example test functions) have no positions. + TargetsNotExtracted { + /// The crate. + krate: String, + /// The target kinds that were not extracted. + missing: Targets, + }, + /// No target declaration for a stored crate the answer depends on. + TargetsUndeclared { + /// The crate. + krate: String, + }, + /// A dynamic call (`UNRESOLVED_CALL`) may reach the symbol or something + /// it reaches; its target was not named by the compiler. + UnresolvedDispatch { + /// `UNRESOLVED_CALL` rows in the store. + dynamic_calls: u32, + }, + /// The owning crate's harvest recorded residuals, did not finish, or has + /// no residuals file. + HarvestIncomplete { + /// The crate. + krate: String, + /// Residual counts (zero when only the run status is the cause). + residuals: ResidualCounts, + /// The CRATE row is not `COMPLETE`. + partial: bool, + /// No `.residuals.tsv` was read. + no_residuals_file: bool, + }, + /// A recorded source file changed or vanished since extraction. + StaleSource { + /// The crate. + krate: String, + /// The changed or missing files, as recorded. + files: Vec, + }, + /// The crate has no `.files.tsv`, so freshness cannot be checked. + FilesUnrecorded { + /// The crate. + krate: String, + }, + /// No source root was given; freshness was not checked. + FreshnessUnchecked, +} + +/// [`Codegraph::impact`] with its coverage. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ImpactReport { + /// Exactly what [`Codegraph::impact`] returns (empty masks when missing). + pub graded: Graded, + /// Whether the symbol has a position. + pub symbol: SymbolState, + /// Every known reason the answer may be incomplete. + pub gaps: Vec, +} + +impl ImpactReport { + /// The symbol is in the store and no gap is known within the declared + /// scope. This is a local statement: it never claims anything about + /// crates, targets or revisions outside the scope. + pub fn closed_in_scope(&self) -> bool { + matches!(self.symbol, SymbolState::Found(_)) && self.gaps.is_empty() + } +} + +fn owner_of(symbol: &str) -> &str { + symbol.split("::").next().unwrap_or(symbol) +} + +fn has(mask: &[u64], p: Pos) -> bool { + mask.get(p as usize / 64) + .is_some_and(|w| w >> (p % 64) & 1 == 1) +} + +fn bits(mask: &[u64]) -> impl Iterator + '_ { + (0..mask.len() * 64) + .filter(|&p| mask[p / 64] >> (p % 64) & 1 == 1) + .filter_map(|p| Pos::try_from(p).ok()) +} + +/// Recorded files of `krate` whose digest differs under `root`, or `None` +/// when the crate has no files table. +fn stale_files(store: &Path, root: &Path, krate: &str) -> Option> { + let table = std::fs::read_to_string(store.join(format!("{krate}.files.tsv"))).ok()?; + let mut stale = Vec::new(); + for line in table + .lines() + .filter(|l| !l.starts_with('#') && !l.is_empty()) + { + let mut f = line.split('\t'); + let (Some(path), Some(digest)) = (f.next(), f.next()) else { + stale.push(line.to_owned()); + continue; + }; + match std::fs::read(root.join(path)) { + Ok(bytes) if fnv64_hex(&bytes) == digest => {} + _ => stale.push(path.to_owned()), + } + } + Some(stale) +} + +impl Codegraph { + /// [`Codegraph::impact`] of `symbol`, with the gaps of `scope`. + /// + /// Gaps are reported for the symbol's own crate and for every stored crate + /// holding a function in the answer. The masks are those of `impact`; + /// this method never adds a position for an unobserved caller. + pub fn impact_report(&self, symbol: &str, scope: &Scope) -> Result { + let stored = self.stored_crates(); + let Some(g) = self.pos(symbol) else { + let z = vec![0u64; self.words()]; + return Ok(ImpactReport { + graded: Graded { + confirmed: z.clone(), + possible: z.clone(), + unknown: z, + }, + symbol: SymbolState::Missing { + owner_stored: stored.contains(owner_of(symbol)), + }, + gaps: Vec::new(), + }); + }; + let graded = self.impact(g)?; + let owner = owner_of(symbol).to_owned(); + let mut gaps = Vec::new(); + + // Crates the answer depends on: the owner, plus every stored crate + // holding a graded function. + let mut involved: BTreeSet = BTreeSet::new(); + if stored.contains(owner.as_str()) { + involved.insert(owner.clone()); + } + let mut consumers: BTreeSet = BTreeSet::new(); + for m in [&graded.confirmed, &graded.possible, &graded.unknown] { + for p in bits(m) { + if let Some(s) = self.symbol(p) { + let k = owner_of(s); + if stored.contains(k) { + involved.insert(k.to_owned()); + } + } + } + } + for p in bits(&graded.confirmed) { + if let Some(s) = self.symbol(p) { + let k = owner_of(s); + if k != owner && stored.contains(k) { + consumers.insert(k.to_owned()); + } + } + } + + if has(self.public(), g) && !scope.consumers_closed { + gaps.push(Gap::ExternalConsumersUnobserved { + owner: owner.clone(), + observed_consumers: consumers.into_iter().collect(), + }); + } + + for k in &involved { + match scope.targets.iter().find(|(n, _)| n == k) { + None => gaps.push(Gap::TargetsUndeclared { krate: k.clone() }), + Some((_, t)) => { + let missing = t.missing(); + if missing.any() { + gaps.push(Gap::TargetsNotExtracted { + krate: k.clone(), + missing, + }); + } + } + } + } + + let dynamic_calls = self.coverage().dynamic_calls; + let unknown_reached = graded.unknown.iter().any(|&w| w != 0); + if unknown_reached || (dynamic_calls > 0 && self.dynamic_may_reach(g)) { + gaps.push(Gap::UnresolvedDispatch { dynamic_calls }); + } + + for k in &involved { + let (residuals, no_file) = self.residuals_of_crate(k); + let partial = self.crate_status(k) == Some(crate::graph::RunStatus::Partial); + if residuals.total() > 0 || no_file || partial { + gaps.push(Gap::HarvestIncomplete { + krate: k.clone(), + residuals, + partial, + no_residuals_file: no_file, + }); + } + } + + match (&scope.store, &scope.source_root) { + (Some(store), Some(root)) => { + for k in &involved { + match stale_files(store, root, k) { + None => gaps.push(Gap::FilesUnrecorded { krate: k.clone() }), + Some(files) if !files.is_empty() => gaps.push(Gap::StaleSource { + krate: k.clone(), + files, + }), + Some(_) => {} + } + } + } + _ => gaps.push(Gap::FreshnessUnchecked), + } + + Ok(ImpactReport { + graded, + symbol: SymbolState::Found(g), + gaps, + }) + } + + /// Whether a dynamic call may reach `g`: `g` is an impl or referenced. + fn dynamic_may_reach(&self, g: Pos) -> bool { + has(self.impl_subjects(), g) || has(self.referenced(), g) + } +} diff --git a/crates/lance-graph-codegraph/src/lib.rs b/crates/lance-graph-codegraph/src/lib.rs index 4a7144256..f81ba6eb2 100644 --- a/crates/lance-graph-codegraph/src/lib.rs +++ b/crates/lance-graph-codegraph/src/lib.rs @@ -7,6 +7,7 @@ pub mod artifact; pub mod artifact_bin; pub mod diag; pub mod graph; +pub mod impact_report; #[cfg(test)] mod lab_wal; pub mod query; diff --git a/crates/lance-graph-codegraph/tests/impact_coverage.rs b/crates/lance-graph-codegraph/tests/impact_coverage.rs new file mode 100644 index 000000000..f303d85f1 --- /dev/null +++ b/crates/lance-graph-codegraph/tests/impact_coverage.rs @@ -0,0 +1,406 @@ +//! Coverage-aware impact (D-CODEGRAPH-RECON-2, Gate A). +//! +//! `Codegraph::impact` answers over symbol positions; a caller the store never +//! extracted has none. These tests pin that `impact_report` keeps the impact +//! masks unchanged and reports each kind of missing coverage as a typed gap, +//! never as a fabricated position in `Graded.unknown`. Each gate has a +//! can-fire test and a can-stay-silent twin on a non-trivial store. + +use std::path::PathBuf; + +use lance_graph_codegraph::artifact::fnv64_hex; +use lance_graph_codegraph::impact_report::{Gap, Scope, SymbolState, Targets}; +use lance_graph_codegraph::Codegraph; + +const HEADER: &str = "#version 2\n#schema predicate\tsubject\tobject\tgrade\tfile\tstart\tend\n"; +const RES_HEADER: &str = "#version 1\n#schema reason\tsubject\n"; +const FILES_HEADER: &str = "#version 1\n#schema path\tfnv64\n"; + +/// One crate of a store: its rows (predicate, subject, object) and the source +/// files it was extracted from (path, contents). +struct Krate<'a> { + name: &'a str, + rows: &'a [(&'a str, &'a str, &'a str)], + files: &'a [(&'a str, &'a str)], +} + +/// A store directory plus a source root holding each crate's files. +struct Fixture { + dir: PathBuf, + store: PathBuf, + src: PathBuf, +} + +impl Fixture { + fn new(name: &str, crates: &[Krate<'_>]) -> Fixture { + let dir = std::env::temp_dir().join(format!("lgcg_impact_{name}_{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + let (store, src) = (dir.join("store"), dir.join("src")); + std::fs::create_dir_all(&store).unwrap(); + std::fs::create_dir_all(&src).unwrap(); + let fx = Fixture { dir, store, src }; + for k in crates { + fx.add(k); + } + fx + } + + /// Write one crate's rows, empty residuals and files table. + fn add(&self, k: &Krate<'_>) { + let file = k.files.first().map_or("f.rs", |f| f.0); + let mut t = String::from(HEADER); + for (p, s, o) in k.rows { + t += &format!("{p}\t{s}\t{o}\tCOMPILER\t{file}\t1\t2\n"); + } + t += &format!("CRATE\t{}\tCOMPLETE\tCOMPILER\t-\t-\t-\n", k.name); + std::fs::write(self.store.join(format!("{}.rows.tsv", k.name)), t).unwrap(); + std::fs::write( + self.store.join(format!("{}.residuals.tsv", k.name)), + RES_HEADER, + ) + .unwrap(); + let mut f = String::from(FILES_HEADER); + for (path, body) in k.files { + std::fs::write(self.src.join(path), body).unwrap(); + f += &format!("{path}\t{}\n", fnv64_hex(body.as_bytes())); + } + std::fs::write(self.store.join(format!("{}.files.tsv", k.name)), f).unwrap(); + } + + fn open(&self) -> Codegraph { + Codegraph::open(&self.store).unwrap() + } + + /// Every stored crate fully extracted, freshness checked against `src`. + fn scope(&self, crates: &[&str]) -> Scope { + Scope { + store: Some(self.store.clone()), + source_root: Some(self.src.clone()), + targets: crates + .iter() + .map(|c| (c.to_string(), Targets::ALL)) + .collect(), + consumers_closed: false, + } + } +} + +impl Drop for Fixture { + fn drop(&mut self) { + let _ = std::fs::remove_dir_all(&self.dir); + } +} + +/// `lib::entry` is public and calls `lib::used`; `lib::helper` is private +/// and has no caller. +const LIB: &[(&str, &str, &str)] = &[ + ("DEFINES", "lib::entry", "lib::entry"), + ("PUBLIC", "lib::entry", "lib::entry"), + ("DEFINES", "lib::used", "lib::used"), + ("DEFINES", "lib::helper", "lib::helper"), + ("CALLS_RESOLVED", "lib::entry", "lib::used"), +]; + +fn lib_crate() -> Krate<'static> { + Krate { + name: "lib", + rows: LIB, + files: &[( + "lib.rs", + "pub fn entry() { used() }\nfn used() {}\nfn helper() {}\n", + )], + } +} + +fn has(g: &Codegraph, mask: &[u64], symbol: &str) -> bool { + g.pos(symbol).is_some_and(|p| { + mask.get(p as usize / 64) + .is_some_and(|w| w >> (p % 64) & 1 == 1) + }) +} + +fn empty(mask: &[u64]) -> bool { + mask.iter().all(|&w| w == 0) +} + +/// 1. A private symbol with no caller, in a crate whose every target was +/// extracted, whose harvest left no residual and whose sources are unchanged: +/// the empty answer is closed in scope. Anti-vacuity: `lib::used` does have a +/// caller, so the impact query is live, not merely empty. +#[test] +fn no_callers_in_a_fully_observed_scope_is_closed() { + let fx = Fixture::new("closed", &[lib_crate()]); + let g = fx.open(); + let r = g.impact_report("lib::helper", &fx.scope(&["lib"])).unwrap(); + assert!(empty(&r.graded.confirmed) && empty(&r.graded.possible) && empty(&r.graded.unknown)); + assert_eq!(r.gaps, Vec::::new()); + assert!(r.closed_in_scope()); + + let used = g.impact_report("lib::used", &fx.scope(&["lib"])).unwrap(); + assert!(has(&g, &used.graded.confirmed, "lib::entry")); +} + +/// 2. A public symbol with no observed caller: the masks stay exactly what +/// `impact` returns (no fabricated unknown), and the missing external +/// callers are a typed gap. `Coverage::no_known_gap()` is true for this +/// store, and the report is still not closed: no-known-gap is not global +/// completeness. +#[test] +fn a_public_symbol_reports_its_unobserved_external_consumers() { + let fx = Fixture::new("public", &[lib_crate()]); + let g = fx.open(); + assert!(g.coverage().no_known_gap()); + let pos = g.pos("lib::entry").unwrap(); + let r = g.impact_report("lib::entry", &fx.scope(&["lib"])).unwrap(); + assert_eq!(r.graded, g.impact(pos).unwrap()); + assert!( + empty(&r.graded.unknown), + "missing coverage must not become a position" + ); + assert_eq!( + r.gaps, + vec![Gap::ExternalConsumersUnobserved { + owner: "lib".into(), + observed_consumers: vec![], + }] + ); + assert!(!r.closed_in_scope()); + + // Silence twin: the caller declares the consumer set closed. + let closed = Scope { + consumers_closed: true, + ..fx.scope(&["lib"]) + }; + assert!(g + .impact_report("lib::entry", &closed) + .unwrap() + .closed_in_scope()); +} + +/// 3. Test-target callers: with only the lib target extracted, the +/// test-only caller has no position, so the report names the missing +/// targets. With the test target extracted (its rows present, declared ALL), +/// the caller is confirmed and the gap disappears. +#[test] +fn test_callers_absent_from_a_lib_extraction_are_a_gap() { + let fx = Fixture::new("tests", &[lib_crate()]); + let lib_only = Scope { + targets: vec![("lib".into(), Targets::LIB_ONLY)], + ..fx.scope(&["lib"]) + }; + let r = fx.open().impact_report("lib::helper", &lib_only).unwrap(); + assert!(empty(&r.graded.confirmed)); + assert_eq!( + r.gaps, + vec![Gap::TargetsNotExtracted { + krate: "lib".into(), + missing: Targets { + lib: false, + tests: true, + examples: true, + benches: true, + }, + }] + ); + + // An undeclared crate is not assumed complete. + let undeclared = Scope { + targets: vec![], + ..fx.scope(&["lib"]) + }; + let r = fx.open().impact_report("lib::helper", &undeclared).unwrap(); + assert_eq!( + r.gaps, + vec![Gap::TargetsUndeclared { + krate: "lib".into() + }] + ); + + // The test target extracted: the caller is a confirmed position. + let mut rows = LIB.to_vec(); + rows.push(( + "DEFINES", + "lib::tests::helper_works", + "lib::tests::helper_works", + )); + rows.push(("CALLS_RESOLVED", "lib::tests::helper_works", "lib::helper")); + let fx2 = Fixture::new( + "tests_all", + &[Krate { + name: "lib", + rows: &rows, + files: lib_crate().files, + }], + ); + let g = fx2.open(); + let r = g + .impact_report("lib::helper", &fx2.scope(&["lib"])) + .unwrap(); + assert!(has(&g, &r.graded.confirmed, "lib::tests::helper_works")); + assert_eq!(r.gaps, Vec::::new()); +} + +/// 4. Unresolved dispatch: `lib::cb` is referenced (its address is taken) and +/// `lib::runner` makes a call the compiler could not name, so a dynamic call +/// may reach `cb`. Silence twin: `lib::used` is neither an impl nor +/// referenced, so the same dynamic call is not a gap for it. +#[test] +fn an_unresolved_dispatch_that_may_reach_the_symbol_is_a_gap() { + let mut rows = LIB.to_vec(); + rows.extend([ + ("DEFINES", "lib::cb", "lib::cb"), + ("DEFINES", "lib::runner", "lib::runner"), + ("REFERENCES", "lib::entry", "lib::cb"), + ("UNRESOLVED_CALL", "lib::runner", "dynamic"), + ]); + let fx = Fixture::new( + "dyn", + &[Krate { + name: "lib", + rows: &rows, + files: lib_crate().files, + }], + ); + let g = fx.open(); + let r = g.impact_report("lib::cb", &fx.scope(&["lib"])).unwrap(); + assert!( + r.gaps + .contains(&Gap::UnresolvedDispatch { dynamic_calls: 1 }), + "{:?}", + r.gaps + ); + + let quiet = g.impact_report("lib::used", &fx.scope(&["lib"])).unwrap(); + assert!(!quiet + .gaps + .iter() + .any(|x| matches!(x, Gap::UnresolvedDispatch { .. }))); +} + +/// 5. Stale source: a recorded file changed after extraction. Twins: the +/// unchanged tree has no gap; a missing files table and a missing source +/// root are their own gaps, never "fresh". +#[test] +fn a_stale_source_revision_is_a_gap() { + let fx = Fixture::new("stale", &[lib_crate()]); + let g = fx.open(); + assert!(g + .impact_report("lib::helper", &fx.scope(&["lib"])) + .unwrap() + .gaps + .is_empty()); + + std::fs::write( + fx.src.join("lib.rs"), + "pub fn entry() { used(); helper() }\n", + ) + .unwrap(); + let r = g.impact_report("lib::helper", &fx.scope(&["lib"])).unwrap(); + assert_eq!( + r.gaps, + vec![Gap::StaleSource { + krate: "lib".into(), + files: vec!["lib.rs".into()], + }] + ); + + let unchecked = Scope { + source_root: None, + ..fx.scope(&["lib"]) + }; + assert_eq!( + g.impact_report("lib::helper", &unchecked).unwrap().gaps, + vec![Gap::FreshnessUnchecked] + ); + + std::fs::remove_file(fx.store.join("lib.files.tsv")).unwrap(); + assert_eq!( + g.impact_report("lib::helper", &fx.scope(&["lib"])) + .unwrap() + .gaps, + vec![Gap::FilesUnrecorded { + krate: "lib".into() + }] + ); +} + +/// 6. A truly missing symbol is not "no callers": it is `Missing`, never +/// closed, and says whether its crate was read at all. +#[test] +fn a_missing_symbol_is_missing_not_unaffected() { + let fx = Fixture::new("missing", &[lib_crate()]); + let g = fx.open(); + let scope = fx.scope(&["lib"]); + let r = g.impact_report("lib::nope", &scope).unwrap(); + assert_eq!(r.symbol, SymbolState::Missing { owner_stored: true }); + assert!(!r.closed_in_scope()); + let r = g.impact_report("other::thing", &scope).unwrap(); + assert_eq!( + r.symbol, + SymbolState::Missing { + owner_stored: false + } + ); + assert!(!r.closed_in_scope()); + // Twin: a present symbol with no callers is Found. + assert!(matches!( + g.impact_report("lib::helper", &scope).unwrap().symbol, + SymbolState::Found(_) + )); +} + +/// 7. Adding a consumer crate upgrades the answer: before, `lib::entry` has no +/// confirmed caller and the external callers are unobserved; after the `app` +/// crate's compiler facts are stored, `app::main` is a confirmed position and +/// the gap names `app` as an observed consumer. The gap stays until the +/// consumer set is declared closed, and `app` must itself be declared. +#[test] +fn adding_a_consumer_crate_confirms_its_callers() { + let fx = Fixture::new("consumer", &[lib_crate()]); + let before = fx + .open() + .impact_report("lib::entry", &fx.scope(&["lib"])) + .unwrap(); + assert!(empty(&before.graded.confirmed)); + + fx.add(&Krate { + name: "app", + rows: &[ + ("DEFINES", "app::main", "app::main"), + ("CALLS_RESOLVED", "app::main", "lib::entry"), + ], + files: &[("main.rs", "fn main() { lib::entry() }\n")], + }); + let g = fx.open(); + let after = g + .impact_report("lib::entry", &fx.scope(&["lib", "app"])) + .unwrap(); + assert!(has(&g, &after.graded.confirmed, "app::main")); + assert_eq!( + after.gaps, + vec![Gap::ExternalConsumersUnobserved { + owner: "lib".into(), + observed_consumers: vec!["app".into()], + }] + ); + + let closed = Scope { + consumers_closed: true, + ..fx.scope(&["lib", "app"]) + }; + assert!(g + .impact_report("lib::entry", &closed) + .unwrap() + .closed_in_scope()); + + let app_undeclared = Scope { + consumers_closed: true, + ..fx.scope(&["lib"]) + }; + assert_eq!( + g.impact_report("lib::entry", &app_undeclared).unwrap().gaps, + vec![Gap::TargetsUndeclared { + krate: "app".into() + }] + ); +} From c6157add0ecf09b037263fb73f4a9682cf1fce3e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 06:54:43 +0000 Subject: [PATCH 02/11] codegraph: impact_report harvest-incomplete test Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- .../tests/impact_coverage.rs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/lance-graph-codegraph/tests/impact_coverage.rs b/crates/lance-graph-codegraph/tests/impact_coverage.rs index f303d85f1..c39452a1b 100644 --- a/crates/lance-graph-codegraph/tests/impact_coverage.rs +++ b/crates/lance-graph-codegraph/tests/impact_coverage.rs @@ -404,3 +404,43 @@ fn adding_a_consumer_crate_confirms_its_callers() { }] ); } + +/// 8. An incomplete harvest of the owning crate (a residual, a missing +/// residuals file, or a PARTIAL crate row) is a gap: absent rows prove +/// nothing. Twin: the same store with empty residuals has no such gap (test 1). +#[test] +fn an_incomplete_harvest_of_the_owner_is_a_gap() { + let fx = Fixture::new("harvest", &[lib_crate()]); + std::fs::write( + fx.store.join("lib.residuals.tsv"), + format!("{RES_HEADER}BODY_NOT_STRUCTURED\tlib::entry\n"), + ) + .unwrap(); + let r = fx + .open() + .impact_report("lib::helper", &fx.scope(&["lib"])) + .unwrap(); + assert!( + matches!(r.gaps.as_slice(), [Gap::HarvestIncomplete { krate, residuals, partial: false, no_residuals_file: false }] + if krate == "lib" && residuals.total() == 1), + "{:?}", + r.gaps + ); + + std::fs::remove_file(fx.store.join("lib.residuals.tsv")).unwrap(); + let r = fx + .open() + .impact_report("lib::helper", &fx.scope(&["lib"])) + .unwrap(); + assert!( + matches!( + r.gaps.as_slice(), + [Gap::HarvestIncomplete { + no_residuals_file: true, + .. + }] + ), + "{:?}", + r.gaps + ); +} From e14e4eadf829f2411d6abe6969e204912747d208 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 06:55:53 +0000 Subject: [PATCH 03/11] codegraph: impact_coverage doc comments are not list items Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- .../tests/impact_coverage.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/lance-graph-codegraph/tests/impact_coverage.rs b/crates/lance-graph-codegraph/tests/impact_coverage.rs index c39452a1b..faae2a01d 100644 --- a/crates/lance-graph-codegraph/tests/impact_coverage.rs +++ b/crates/lance-graph-codegraph/tests/impact_coverage.rs @@ -123,7 +123,7 @@ fn empty(mask: &[u64]) -> bool { mask.iter().all(|&w| w == 0) } -/// 1. A private symbol with no caller, in a crate whose every target was +/// Case 1: A private symbol with no caller, in a crate whose every target was /// extracted, whose harvest left no residual and whose sources are unchanged: /// the empty answer is closed in scope. Anti-vacuity: `lib::used` does have a /// caller, so the impact query is live, not merely empty. @@ -140,7 +140,7 @@ fn no_callers_in_a_fully_observed_scope_is_closed() { assert!(has(&g, &used.graded.confirmed, "lib::entry")); } -/// 2. A public symbol with no observed caller: the masks stay exactly what +/// Case 2: A public symbol with no observed caller: the masks stay exactly what /// `impact` returns (no fabricated unknown), and the missing external /// callers are a typed gap. `Coverage::no_known_gap()` is true for this /// store, and the report is still not closed: no-known-gap is not global @@ -177,7 +177,7 @@ fn a_public_symbol_reports_its_unobserved_external_consumers() { .closed_in_scope()); } -/// 3. Test-target callers: with only the lib target extracted, the +/// Case 3: Test-target callers: with only the lib target extracted, the /// test-only caller has no position, so the report names the missing /// targets. With the test target extracted (its rows present, declared ALL), /// the caller is confirmed and the gap disappears. @@ -240,7 +240,7 @@ fn test_callers_absent_from_a_lib_extraction_are_a_gap() { assert_eq!(r.gaps, Vec::::new()); } -/// 4. Unresolved dispatch: `lib::cb` is referenced (its address is taken) and +/// Case 4: Unresolved dispatch: `lib::cb` is referenced (its address is taken) and /// `lib::runner` makes a call the compiler could not name, so a dynamic call /// may reach `cb`. Silence twin: `lib::used` is neither an impl nor /// referenced, so the same dynamic call is not a gap for it. @@ -277,7 +277,7 @@ fn an_unresolved_dispatch_that_may_reach_the_symbol_is_a_gap() { .any(|x| matches!(x, Gap::UnresolvedDispatch { .. }))); } -/// 5. Stale source: a recorded file changed after extraction. Twins: the +/// Case 5: Stale source: a recorded file changed after extraction. Twins: the /// unchanged tree has no gap; a missing files table and a missing source /// root are their own gaps, never "fresh". #[test] @@ -324,7 +324,7 @@ fn a_stale_source_revision_is_a_gap() { ); } -/// 6. A truly missing symbol is not "no callers": it is `Missing`, never +/// Case 6: A truly missing symbol is not "no callers": it is `Missing`, never /// closed, and says whether its crate was read at all. #[test] fn a_missing_symbol_is_missing_not_unaffected() { @@ -349,7 +349,7 @@ fn a_missing_symbol_is_missing_not_unaffected() { )); } -/// 7. Adding a consumer crate upgrades the answer: before, `lib::entry` has no +/// Case 7: Adding a consumer crate upgrades the answer: before, `lib::entry` has no /// confirmed caller and the external callers are unobserved; after the `app` /// crate's compiler facts are stored, `app::main` is a confirmed position and /// the gap names `app` as an observed consumer. The gap stays until the @@ -405,7 +405,7 @@ fn adding_a_consumer_crate_confirms_its_callers() { ); } -/// 8. An incomplete harvest of the owning crate (a residual, a missing +/// Case 8: An incomplete harvest of the owning crate (a residual, a missing /// residuals file, or a PARTIAL crate row) is a gap: absent rows prove /// nothing. Twin: the same store with empty residuals has no such gap (test 1). #[test] From b989a990a75a1bcc01c09f9dd7d31db831b475bc Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 07:06:41 +0000 Subject: [PATCH 04/11] codegraph: excluded regions and missing-symbol scope gaps A symbol defined only in an opaque module or a disabled feature has no position, so impact_report now reports declared excluded regions as RegionsExcluded, and a missing symbol in a stored crate carries that crate's target and region gaps instead of reading as absent. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- .../src/impact_report.rs | 64 ++++++++++++---- .../tests/impact_coverage.rs | 75 +++++++++++++++++++ 2 files changed, 125 insertions(+), 14 deletions(-) diff --git a/crates/lance-graph-codegraph/src/impact_report.rs b/crates/lance-graph-codegraph/src/impact_report.rs index c6f92d0d1..3ae1e0f06 100644 --- a/crates/lance-graph-codegraph/src/impact_report.rs +++ b/crates/lance-graph-codegraph/src/impact_report.rs @@ -81,6 +81,11 @@ pub struct Scope { /// dependent set was extracted). Without this, a public symbol's external /// callers are unobserved. pub consumers_closed: bool, + /// Code of a stored crate the extraction did not translate, per crate + /// name: modules passed to Charon as opaque, cargo features left off, cfg + /// branches not taken. The store cannot see what is inside, so a caller, + /// callee or definition there has no position. + pub excluded: Vec<(String, Vec)>, } /// Whether the queried symbol has a position. @@ -155,6 +160,15 @@ pub enum Gap { }, /// No source root was given; freshness was not checked. FreshnessUnchecked, + /// The declared scope excludes regions of the crate from extraction + /// (opaque modules, disabled features). Calls inside them have no rows, + /// and a symbol defined only there is missing without being absent. + RegionsExcluded { + /// The crate. + krate: String, + /// The excluded regions, as declared. + regions: Vec, + }, } /// [`Codegraph::impact`] with its coverage. @@ -214,6 +228,31 @@ fn stale_files(store: &Path, root: &Path, krate: &str) -> Option> { Some(stale) } +/// The declared-scope gaps of one stored crate: its targets and its +/// excluded regions. +fn scope_gaps(k: &str, scope: &Scope, gaps: &mut Vec) { + match scope.targets.iter().find(|(n, _)| n == k) { + None => gaps.push(Gap::TargetsUndeclared { + krate: k.to_owned(), + }), + Some((_, t)) => { + let missing = t.missing(); + if missing.any() { + gaps.push(Gap::TargetsNotExtracted { + krate: k.to_owned(), + missing, + }); + } + } + } + if let Some((_, regions)) = scope.excluded.iter().find(|(n, r)| n == k && !r.is_empty()) { + gaps.push(Gap::RegionsExcluded { + krate: k.to_owned(), + regions: regions.clone(), + }); + } +} + impl Codegraph { /// [`Codegraph::impact`] of `symbol`, with the gaps of `scope`. /// @@ -224,6 +263,14 @@ impl Codegraph { let stored = self.stored_crates(); let Some(g) = self.pos(symbol) else { let z = vec![0u64; self.words()]; + // A missing symbol in a stored crate is absent only from what was + // extracted: undeclared or missing targets and excluded regions + // are each a place it may still be defined. + let mut gaps = Vec::new(); + let owner = owner_of(symbol); + if stored.contains(owner) { + scope_gaps(owner, scope, &mut gaps); + } return Ok(ImpactReport { graded: Graded { confirmed: z.clone(), @@ -231,9 +278,9 @@ impl Codegraph { unknown: z, }, symbol: SymbolState::Missing { - owner_stored: stored.contains(owner_of(symbol)), + owner_stored: stored.contains(owner), }, - gaps: Vec::new(), + gaps, }); }; let graded = self.impact(g)?; @@ -274,18 +321,7 @@ impl Codegraph { } for k in &involved { - match scope.targets.iter().find(|(n, _)| n == k) { - None => gaps.push(Gap::TargetsUndeclared { krate: k.clone() }), - Some((_, t)) => { - let missing = t.missing(); - if missing.any() { - gaps.push(Gap::TargetsNotExtracted { - krate: k.clone(), - missing, - }); - } - } - } + scope_gaps(k, scope, &mut gaps); } let dynamic_calls = self.coverage().dynamic_calls; diff --git a/crates/lance-graph-codegraph/tests/impact_coverage.rs b/crates/lance-graph-codegraph/tests/impact_coverage.rs index faae2a01d..91bb0cd48 100644 --- a/crates/lance-graph-codegraph/tests/impact_coverage.rs +++ b/crates/lance-graph-codegraph/tests/impact_coverage.rs @@ -81,6 +81,7 @@ impl Fixture { .map(|c| (c.to_string(), Targets::ALL)) .collect(), consumers_closed: false, + excluded: Vec::new(), } } } @@ -444,3 +445,77 @@ fn an_incomplete_harvest_of_the_owner_is_a_gap() { r.gaps ); } + +/// Case 9: Regions the extraction did not translate (an opaque module, a +/// cargo feature left off) are a gap for a found symbol and for a missing +/// one. A symbol defined only in an uncompiled feature module is missing from +/// the store without being absent from the crate. +#[test] +fn excluded_regions_are_a_gap_for_found_and_missing_symbols() { + let fx = Fixture::new("excluded", &[lib_crate()]); + let g = fx.open(); + let excluded = Scope { + excluded: vec![("lib".into(), vec!["feature iam".into()])], + ..fx.scope(&["lib"]) + }; + let gap = Gap::RegionsExcluded { + krate: "lib".into(), + regions: vec!["feature iam".into()], + }; + let r = g.impact_report("lib::helper", &excluded).unwrap(); + assert_eq!(r.gaps, vec![gap.clone()]); + assert!(!r.closed_in_scope()); + let r = g.impact_report("lib::authorize", &excluded).unwrap(); + assert_eq!(r.symbol, SymbolState::Missing { owner_stored: true }); + assert_eq!(r.gaps, vec![gap]); + // Silence twins: no exclusion for this crate, or an empty list, leaves the + // found symbol closed and the missing one without gaps. + for silent in [ + fx.scope(&["lib"]), + Scope { + excluded: vec![ + ("lib".into(), Vec::new()), + ("other".into(), vec!["x".into()]), + ], + ..fx.scope(&["lib"]) + }, + ] { + assert!(g + .impact_report("lib::helper", &silent) + .unwrap() + .closed_in_scope()); + assert!(g + .impact_report("lib::authorize", &silent) + .unwrap() + .gaps + .is_empty()); + } +} + +/// Case 10: A missing symbol carries its crate's target gaps. Extracting +/// only the library cannot show that a symbol is absent from the tests. +#[test] +fn a_missing_symbol_carries_its_crate_target_gaps() { + let fx = Fixture::new("missing-targets", &[lib_crate()]); + let g = fx.open(); + let lib_only = Scope { + targets: vec![("lib".into(), Targets::LIB_ONLY)], + ..fx.scope(&["lib"]) + }; + let r = g.impact_report("lib::only_in_tests", &lib_only).unwrap(); + assert!( + matches!( + r.gaps.as_slice(), + [Gap::TargetsNotExtracted { krate, missing }] if krate == "lib" && missing.tests + ), + "{:?}", + r.gaps + ); + // A symbol outside every stored crate reports no crate gap: nothing of + // its crate was read, which `owner_stored: false` already says. + assert!(g + .impact_report("other::x", &lib_only) + .unwrap() + .gaps + .is_empty()); +} From 762dad16f2e327e0675a626640adb35329ab09f4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 07:09:52 +0000 Subject: [PATCH 05/11] codegraph: report unread source files and add cg_query report impact_report now lists .rs files below a directory the extraction read from that its files table does not record (feature-gated modules, binary roots), as SourceFilesUnread. cg_query gains a report subcommand that prints impact_report for a declared scope. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- .../examples/cg_query.rs | 98 +++++++++++++++++++ .../src/impact_report.rs | 71 ++++++++++++-- .../tests/impact_coverage.rs | 41 +++++++- 3 files changed, 199 insertions(+), 11 deletions(-) diff --git a/crates/lance-graph-codegraph/examples/cg_query.rs b/crates/lance-graph-codegraph/examples/cg_query.rs index 4b4975ef8..4ae3b8bd7 100644 --- a/crates/lance-graph-codegraph/examples/cg_query.rs +++ b/crates/lance-graph-codegraph/examples/cg_query.rs @@ -4,8 +4,16 @@ //! ```text //! cargo run --release --example cg_query -- symbols [SUBSTRING] //! cargo run --release --example cg_query -- callers|callees|impact|refs SYMBOL +//! cargo run --release --example cg_query -- report SYMBOL \ +//! [--targets CRATE=lib,tests,examples,benches]... [--exclude CRATE=REGION]... [--consumers-closed] //! ``` //! +//! `report` prints [`Codegraph::impact_report`]: the impact masks, whether the +//! symbol has a position, and every coverage gap of the declared scope, one +//! `GAP` line each. A crate without `--targets` is reported as undeclared; +//! `--exclude` names code the extraction did not translate (an opaque module, +//! a feature left off). +//! //! Output is tab-separated, one fact per line. Every result line carries its //! grade (`CONFIRMED`, `POSSIBLE`, `UNKNOWN`); a refusal is printed verbatim //! with `REFUSED` and exit code 3, never as an empty answer. Callers and impact of @@ -17,6 +25,7 @@ use std::path::{Path, PathBuf}; use std::process::ExitCode; +use lance_graph_codegraph::impact_report::{Scope, SymbolState, Targets}; use lance_graph_codegraph::Codegraph; fn line_of(src_root: &Path, file: &str, offset: u32) -> String { @@ -139,6 +148,9 @@ fn main() -> ExitCode { eprintln!("{cmd} needs a SYMBOL"); return ExitCode::from(2); }; + if cmd == "report" { + return report(&g, &store, &src, sym, &args[4..]); + } let Some(pos) = g.pos(sym) else { println!("UNKNOWN\tsymbol-not-in-store\t{sym}"); return ExitCode::from(4); @@ -205,3 +217,89 @@ fn main() -> ExitCode { } } } + +fn parse_targets(list: &str) -> Option { + let mut t = Targets::default(); + for k in list.split(',') { + match k { + "lib" => t.lib = true, + "tests" => t.tests = true, + "examples" => t.examples = true, + "benches" => t.benches = true, + _ => return None, + } + } + Some(t) +} + +fn report(g: &Codegraph, store: &Path, src: &Path, sym: &str, flags: &[String]) -> ExitCode { + let mut scope = Scope { + store: Some(store.to_path_buf()), + source_root: Some(src.to_path_buf()), + ..Scope::default() + }; + let mut it = flags.iter(); + while let Some(f) = it.next() { + let value = |v: Option<&String>| { + v.and_then(|v| v.split_once('=')) + .map(|(a, b)| (a.to_string(), b.to_string())) + }; + match f.as_str() { + "--consumers-closed" => scope.consumers_closed = true, + "--targets" => match value(it.next()) { + Some((k, list)) => match parse_targets(&list) { + Some(t) => scope.targets.push((k, t)), + None => { + eprintln!("bad --targets list {list}"); + return ExitCode::from(2); + } + }, + None => { + eprintln!("--targets needs CRATE=LIST"); + return ExitCode::from(2); + } + }, + "--exclude" => match value(it.next()) { + Some((k, region)) => match scope.excluded.iter_mut().find(|(n, _)| *n == k) { + Some((_, r)) => r.push(region), + None => scope.excluded.push((k, vec![region])), + }, + None => { + eprintln!("--exclude needs CRATE=REGION"); + return ExitCode::from(2); + } + }, + other => { + eprintln!("unknown flag {other}"); + return ExitCode::from(2); + } + } + } + let r = match g.impact_report(sym, &scope) { + Ok(r) => r, + Err(e) => { + println!("REFUSED\treport\t{e:?}"); + return ExitCode::from(3); + } + }; + match r.symbol { + SymbolState::Found(p) => println!("symbol\tFOUND\t{p}\t{sym}"), + SymbolState::Missing { owner_stored } => { + println!("symbol\tMISSING\towner_stored={owner_stored}\t{sym}") + } + } + for (grade, mask) in [ + ("CONFIRMED", &r.graded.confirmed), + ("POSSIBLE", &r.graded.possible), + ("UNKNOWN", &r.graded.unknown), + ] { + for n in names(g, mask) { + println!("impact\t{grade}\t{n}"); + } + } + for gap in &r.gaps { + println!("GAP\t{gap:?}"); + } + println!("closed_in_scope\t{}", r.closed_in_scope()); + ExitCode::SUCCESS +} diff --git a/crates/lance-graph-codegraph/src/impact_report.rs b/crates/lance-graph-codegraph/src/impact_report.rs index 3ae1e0f06..e0829ca8f 100644 --- a/crates/lance-graph-codegraph/src/impact_report.rs +++ b/crates/lance-graph-codegraph/src/impact_report.rs @@ -160,6 +160,15 @@ pub enum Gap { }, /// No source root was given; freshness was not checked. FreshnessUnchecked, + /// Rust files under a directory the extraction read from that it did not + /// read itself: modules behind a disabled feature or cfg, other targets' + /// roots, files never declared as modules. Their code has no rows. + SourceFilesUnread { + /// The crate. + krate: String, + /// The unread `.rs` files, relative to the source root. + files: Vec, + }, /// The declared scope excludes regions of the crate from extraction /// (opaque modules, disabled features). Calls inside them have no rows, /// and a symbol defined only there is missing without being absent. @@ -206,11 +215,16 @@ fn bits(mask: &[u64]) -> impl Iterator + '_ { .filter_map(|p| Pos::try_from(p).ok()) } -/// Recorded files of `krate` whose digest differs under `root`, or `None` -/// when the crate has no files table. -fn stale_files(store: &Path, root: &Path, krate: &str) -> Option> { +/// The stale and the unread files of `krate`, or `None` when the crate has +/// no files table. Stale: a recorded file whose digest differs under `root`. +/// Unread: a `.rs` file below the top directory of a recorded path that the +/// table does not list. A recorded file at the root names no directory, so +/// nothing is scanned for it. +fn file_gaps(store: &Path, root: &Path, krate: &str) -> Option<(Vec, Vec)> { let table = std::fs::read_to_string(store.join(format!("{krate}.files.tsv"))).ok()?; let mut stale = Vec::new(); + let mut recorded = BTreeSet::new(); + let mut tops = BTreeSet::new(); for line in table .lines() .filter(|l| !l.starts_with('#') && !l.is_empty()) @@ -220,12 +234,40 @@ fn stale_files(store: &Path, root: &Path, krate: &str) -> Option> { stale.push(line.to_owned()); continue; }; + recorded.insert(path.to_owned()); + if let Some((top, _)) = path.split_once('/') { + if top != "." && top != ".." { + tops.insert(top.to_owned()); + } + } match std::fs::read(root.join(path)) { Ok(bytes) if fnv64_hex(&bytes) == digest => {} _ => stale.push(path.to_owned()), } } - Some(stale) + let mut unread = Vec::new(); + for top in &tops { + rust_files(root, top, &mut unread); + } + unread.retain(|f| !recorded.contains(f)); + unread.sort(); + Some((stale, unread)) +} + +/// Every `.rs` file below `root/rel`, as paths relative to `root`. +fn rust_files(root: &Path, rel: &str, out: &mut Vec) { + let Ok(entries) = std::fs::read_dir(root.join(rel)) else { + return; + }; + for e in entries.flatten() { + let name = e.file_name().to_string_lossy().into_owned(); + let path = format!("{rel}/{name}"); + match e.file_type() { + Ok(t) if t.is_dir() => rust_files(root, &path, out), + Ok(t) if t.is_file() && name.ends_with(".rs") => out.push(path), + _ => {} + } + } } /// The declared-scope gaps of one stored crate: its targets and its @@ -346,13 +388,22 @@ impl Codegraph { match (&scope.store, &scope.source_root) { (Some(store), Some(root)) => { for k in &involved { - match stale_files(store, root, k) { + match file_gaps(store, root, k) { None => gaps.push(Gap::FilesUnrecorded { krate: k.clone() }), - Some(files) if !files.is_empty() => gaps.push(Gap::StaleSource { - krate: k.clone(), - files, - }), - Some(_) => {} + Some((stale, unread)) => { + if !stale.is_empty() { + gaps.push(Gap::StaleSource { + krate: k.clone(), + files: stale, + }); + } + if !unread.is_empty() { + gaps.push(Gap::SourceFilesUnread { + krate: k.clone(), + files: unread, + }); + } + } } } } diff --git a/crates/lance-graph-codegraph/tests/impact_coverage.rs b/crates/lance-graph-codegraph/tests/impact_coverage.rs index 91bb0cd48..957e10f15 100644 --- a/crates/lance-graph-codegraph/tests/impact_coverage.rs +++ b/crates/lance-graph-codegraph/tests/impact_coverage.rs @@ -61,7 +61,9 @@ impl Fixture { .unwrap(); let mut f = String::from(FILES_HEADER); for (path, body) in k.files { - std::fs::write(self.src.join(path), body).unwrap(); + let at = self.src.join(path); + std::fs::create_dir_all(at.parent().unwrap()).unwrap(); + std::fs::write(at, body).unwrap(); f += &format!("{path}\t{}\n", fnv64_hex(body.as_bytes())); } std::fs::write(self.store.join(format!("{}.files.tsv", k.name)), f).unwrap(); @@ -519,3 +521,40 @@ fn a_missing_symbol_carries_its_crate_target_gaps() { .gaps .is_empty()); } + +/// Case 11: A `.rs` file under a directory the extraction read from, but not +/// itself recorded, is a gap: its code (a feature-gated module, a binary +/// root) has no rows. Files in the root and non-Rust files are not scanned. +#[test] +fn unread_source_files_under_a_read_directory_are_a_gap() { + let k = Krate { + name: "lib", + rows: &[ + ("DEFINES", "lib::entry", "lib::entry"), + ("DEFINES", "lib::helper", "lib::helper"), + ], + files: &[("crate/lib.rs", "fn entry() {}\nfn helper() {}\n")], + }; + let fx = Fixture::new("unread", &[k]); + let g = fx.open(); + let scope = fx.scope(&["lib"]); + // Silence twin: everything under crate/ is recorded; a non-Rust file and a + // root-level file are not scanned. + std::fs::write(fx.src.join("crate/data.json"), "{}").unwrap(); + std::fs::write(fx.src.join("top.rs"), "fn x() {}").unwrap(); + assert!(g + .impact_report("lib::helper", &scope) + .unwrap() + .closed_in_scope()); + std::fs::create_dir_all(fx.src.join("crate/gated")).unwrap(); + std::fs::write(fx.src.join("crate/iam.rs"), "pub fn authorize() {}").unwrap(); + std::fs::write(fx.src.join("crate/gated/deep.rs"), "fn d() {}").unwrap(); + let r = g.impact_report("lib::helper", &scope).unwrap(); + assert_eq!( + r.gaps, + vec![Gap::SourceFilesUnread { + krate: "lib".into(), + files: vec!["crate/gated/deep.rs".into(), "crate/iam.rs".into()], + }] + ); +} From f114ee4978839c38e672a03e4ce24c095de637ee Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 07:10:57 +0000 Subject: [PATCH 06/11] codegraph: a missing symbol carries its crate's file gaps Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- .../src/impact_report.rs | 63 +++++++++++-------- .../tests/impact_coverage.rs | 8 +++ 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/crates/lance-graph-codegraph/src/impact_report.rs b/crates/lance-graph-codegraph/src/impact_report.rs index e0829ca8f..85653cdd7 100644 --- a/crates/lance-graph-codegraph/src/impact_report.rs +++ b/crates/lance-graph-codegraph/src/impact_report.rs @@ -270,6 +270,39 @@ fn rust_files(root: &Path, rel: &str, out: &mut Vec) { } } +/// Freshness and unread-file gaps of `krates` under the declared store and +/// source root; `FreshnessUnchecked` when either is missing. +fn freshness_gaps<'a>( + krates: impl IntoIterator, + scope: &Scope, + gaps: &mut Vec, +) { + match (&scope.store, &scope.source_root) { + (Some(store), Some(root)) => { + for k in krates { + match file_gaps(store, root, k) { + None => gaps.push(Gap::FilesUnrecorded { krate: k.clone() }), + Some((stale, unread)) => { + if !stale.is_empty() { + gaps.push(Gap::StaleSource { + krate: k.clone(), + files: stale, + }); + } + if !unread.is_empty() { + gaps.push(Gap::SourceFilesUnread { + krate: k.clone(), + files: unread, + }); + } + } + } + } + } + _ => gaps.push(Gap::FreshnessUnchecked), + } +} + /// The declared-scope gaps of one stored crate: its targets and its /// excluded regions. fn scope_gaps(k: &str, scope: &Scope, gaps: &mut Vec) { @@ -306,12 +339,13 @@ impl Codegraph { let Some(g) = self.pos(symbol) else { let z = vec![0u64; self.words()]; // A missing symbol in a stored crate is absent only from what was - // extracted: undeclared or missing targets and excluded regions - // are each a place it may still be defined. + // extracted: undeclared or missing targets, excluded regions and + // unread files are each a place it may still be defined. let mut gaps = Vec::new(); let owner = owner_of(symbol); if stored.contains(owner) { scope_gaps(owner, scope, &mut gaps); + freshness_gaps([&owner.to_owned()], scope, &mut gaps); } return Ok(ImpactReport { graded: Graded { @@ -385,30 +419,7 @@ impl Codegraph { } } - match (&scope.store, &scope.source_root) { - (Some(store), Some(root)) => { - for k in &involved { - match file_gaps(store, root, k) { - None => gaps.push(Gap::FilesUnrecorded { krate: k.clone() }), - Some((stale, unread)) => { - if !stale.is_empty() { - gaps.push(Gap::StaleSource { - krate: k.clone(), - files: stale, - }); - } - if !unread.is_empty() { - gaps.push(Gap::SourceFilesUnread { - krate: k.clone(), - files: unread, - }); - } - } - } - } - } - _ => gaps.push(Gap::FreshnessUnchecked), - } + freshness_gaps(&involved, scope, &mut gaps); Ok(ImpactReport { graded, diff --git a/crates/lance-graph-codegraph/tests/impact_coverage.rs b/crates/lance-graph-codegraph/tests/impact_coverage.rs index 957e10f15..733b98ff8 100644 --- a/crates/lance-graph-codegraph/tests/impact_coverage.rs +++ b/crates/lance-graph-codegraph/tests/impact_coverage.rs @@ -557,4 +557,12 @@ fn unread_source_files_under_a_read_directory_are_a_gap() { files: vec!["crate/gated/deep.rs".into(), "crate/iam.rs".into()], }] ); + // A symbol missing from the store may be defined in an unread file. + let r = g.impact_report("lib::authorize", &scope).unwrap(); + assert_eq!(r.symbol, SymbolState::Missing { owner_stored: true }); + assert!( + matches!(r.gaps.as_slice(), [Gap::SourceFilesUnread { files, .. }] if files.len() == 2), + "{:?}", + r.gaps + ); } From da6b1f9bbf69b678c64cc410ce0e52b8068a3e87 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 07:12:41 +0000 Subject: [PATCH 07/11] codegraph: regenerate .codegraph index for impact_report Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- .codegraph/coverage.tsv | 2 +- .codegraph/crates.tsv | 2 +- .../crates/lance-graph-codegraph.index.md | 159 ++++++++-------- .codegraph/freshness.tsv | 2 +- .codegraph/imports.tsv | 43 +++-- .codegraph/symbols.tsv | 174 ++++++++++-------- .codegraph/views/BindStore.md | 2 +- 7 files changed, 210 insertions(+), 174 deletions(-) diff --git a/.codegraph/coverage.tsv b/.codegraph/coverage.tsv index c2e4302d6..a44ee53b2 100644 --- a/.codegraph/coverage.tsv +++ b/.codegraph/coverage.tsv @@ -36,7 +36,7 @@ lance-graph-benches 0 10 0 macro-generated items invisible;fn-local use not scan lance-graph-callcenter 35 6 3 macro-generated items invisible;fn-local use not scanned lance-graph-catalog 9 1 0 macro-generated items invisible;fn-local use not scanned lance-graph-codec-research 10 0 0 macro-generated items invisible;fn-local use not scanned -lance-graph-codegraph 8 11 0 macro-generated items invisible;fn-local use not scanned +lance-graph-codegraph 9 12 0 macro-generated items invisible;fn-local use not scanned lance-graph-cognitive 60 0 0 macro-generated items invisible;fn-local use not scanned lance-graph-consumer-conformance 2 0 0 macro-generated items invisible;fn-local use not scanned lance-graph-contract 175 35 2 macro-generated items invisible;fn-local use not scanned diff --git a/.codegraph/crates.tsv b/.codegraph/crates.tsv index 9c2335869..970282de2 100644 --- a/.codegraph/crates.tsv +++ b/.codegraph/crates.tsv @@ -36,7 +36,7 @@ lance-graph-benches crates/lance-graph-benches member 2f2fb296a08260fb lance-graph-callcenter crates/lance-graph-callcenter member 41a65d38ac70bc87 lance-graph-catalog crates/lance-graph-catalog member 9d0c34f70c28a465 lance-graph-codec-research crates/lance-graph-codec-research excluded 8b8afbd9a6d0f359 -lance-graph-codegraph crates/lance-graph-codegraph excluded bd209bed318ffbbc +lance-graph-codegraph crates/lance-graph-codegraph excluded 832b307522eeaa24 lance-graph-cognitive crates/lance-graph-cognitive excluded 93f956ac0d69ca66 lance-graph-consumer-conformance crates/lance-graph-consumer-conformance member 82e980465d770990 lance-graph-contract crates/lance-graph-contract member 6b4e13ff1d0afadb diff --git a/.codegraph/crates/lance-graph-codegraph.index.md b/.codegraph/crates/lance-graph-codegraph.index.md index 73728ed9c..c8d71c5c4 100644 --- a/.codegraph/crates/lance-graph-codegraph.index.md +++ b/.codegraph/crates/lance-graph-codegraph.index.md @@ -3,7 +3,7 @@ crate: lance-graph-codegraph path: crates/lance-graph-codegraph workspace: excluded -digest: bd209bed318ffbbc +digest: 832b307522eeaa24 evidence legend: ../index.md#evidence-legend Generated; the code is the truth. See ../index.md. @@ -39,52 +39,53 @@ Generated; the code is the truth. See ../index.md. - const P_OTHER [pub] — crates/lance-graph-codegraph/src/artifact.rs:62 CONFIRMED - fn pred_code [pub] — crates/lance-graph-codegraph/src/artifact.rs:78 CONFIRMED - fn digest [pub] — crates/lance-graph-codegraph/src/artifact.rs:98 CONFIRMED -- struct FastHasher [pub] — crates/lance-graph-codegraph/src/artifact.rs:112 CONFIRMED -- type FastBuild [pub] — crates/lance-graph-codegraph/src/artifact.rs:143 CONFIRMED -- struct Symbols [pub] — crates/lance-graph-codegraph/src/artifact.rs:148 CONFIRMED -- fn Symbols::intern [pub] — crates/lance-graph-codegraph/src/artifact.rs:155 CONFIRMED -- fn Symbols::get [pub] — crates/lance-graph-codegraph/src/artifact.rs:166 CONFIRMED -- fn Symbols::name [pub] — crates/lance-graph-codegraph/src/artifact.rs:171 CONFIRMED -- fn Symbols::len [pub] — crates/lance-graph-codegraph/src/artifact.rs:176 CONFIRMED -- fn Symbols::is_empty [pub] — crates/lance-graph-codegraph/src/artifact.rs:181 CONFIRMED -- fn Symbols::absorb [pub] — crates/lance-graph-codegraph/src/artifact.rs:188 CONFIRMED -- trait Interner [pub] — crates/lance-graph-codegraph/src/artifact.rs:204 CONFIRMED -- struct SymbolStage [pub] — crates/lance-graph-codegraph/src/artifact.rs:238 CONFIRMED -- struct StagedNames [pub] — crates/lance-graph-codegraph/src/artifact.rs:245 CONFIRMED -- fn SymbolStage<'a>::new [pub] — crates/lance-graph-codegraph/src/artifact.rs:252 CONFIRMED -- fn SymbolStage<'a>::added [pub] — crates/lance-graph-codegraph/src/artifact.rs:261 CONFIRMED -- fn SymbolStage<'a>::into_names [pub] — crates/lance-graph-codegraph/src/artifact.rs:266 CONFIRMED -- struct Lanes [pub] — crates/lance-graph-codegraph/src/artifact.rs:303 CONFIRMED -- fn Lanes::len [pub] — crates/lance-graph-codegraph/src/artifact.rs:335 CONFIRMED -- fn Lanes::is_empty [pub] — crates/lance-graph-codegraph/src/artifact.rs:340 CONFIRMED -- fn Lanes::predicate_name [pub] — crates/lance-graph-codegraph/src/artifact.rs:345 CONFIRMED -- fn Lanes::digest_of [pub] — crates/lance-graph-codegraph/src/artifact.rs:357 CONFIRMED -- fn Lanes::residuals_of [pub] — crates/lance-graph-codegraph/src/artifact.rs:370 CONFIRMED -- fn Lanes::set_residuals [pub] — crates/lance-graph-codegraph/src/artifact.rs:375 CONFIRMED -- fn Lanes::crates [pub] — crates/lance-graph-codegraph/src/artifact.rs:383 CONFIRMED -- fn Lanes::drop_crate [pub] — crates/lance-graph-codegraph/src/artifact.rs:389 CONFIRMED -- fn Lanes::append [pub] — crates/lance-graph-codegraph/src/artifact.rs:434 CONFIRMED -- enum ResidualKind [pub] — crates/lance-graph-codegraph/src/artifact.rs:460 CONFIRMED -- const ResidualKind::ALL [pub] — crates/lance-graph-codegraph/src/artifact.rs:477 CONFIRMED -- fn ResidualKind::name [pub] — crates/lance-graph-codegraph/src/artifact.rs:486 CONFIRMED -- struct ResidualCounts [pub] — crates/lance-graph-codegraph/src/artifact.rs:508 CONFIRMED -- fn ResidualCounts::of [pub] — crates/lance-graph-codegraph/src/artifact.rs:512 CONFIRMED -- fn ResidualCounts::total [pub] — crates/lance-graph-codegraph/src/artifact.rs:517 CONFIRMED -- fn ResidualCounts::add [pub] — crates/lance-graph-codegraph/src/artifact.rs:522 CONFIRMED -- enum ResidualRefusal [pub] — crates/lance-graph-codegraph/src/artifact.rs:531 CONFIRMED -- fn refuse_placeholders [pub] — crates/lance-graph-codegraph/src/artifact.rs:563 CONFIRMED -- const RESIDUAL_SUFFIX [pub] — crates/lance-graph-codegraph/src/artifact.rs:591 CONFIRMED -- fn read_residuals [pub] — crates/lance-graph-codegraph/src/artifact.rs:595 CONFIRMED -- const BIN_SUFFIX [pub] — crates/lance-graph-codegraph/src/artifact.rs:640 CONFIRMED -- enum CrateSource [pub] — crates/lance-graph-codegraph/src/artifact.rs:644 CONFIRMED -- fn crate_source [pub] — crates/lance-graph-codegraph/src/artifact.rs:653 CONFIRMED -- fn read_crate_text [pub] — crates/lance-graph-codegraph/src/artifact.rs:663 CONFIRMED -- fn read_crate [pub] — crates/lance-graph-codegraph/src/artifact.rs:668 CONFIRMED -- fn read_dir [pub] — crates/lance-graph-codegraph/src/artifact.rs:678 CONFIRMED -- fn read_bin_as [pub] — crates/lance-graph-codegraph/src/artifact.rs:727 CONFIRMED -- fn dispatch_target [pub] — crates/lance-graph-codegraph/src/artifact.rs:819 CONFIRMED -- fn read_text [pub] — crates/lance-graph-codegraph/src/artifact.rs:857 CONFIRMED -- fn read_text_as [pub] — crates/lance-graph-codegraph/src/artifact.rs:867 CONFIRMED +- fn fnv64_hex [pub] — crates/lance-graph-codegraph/src/artifact.rs:110 CONFIRMED +- struct FastHasher [pub] — crates/lance-graph-codegraph/src/artifact.rs:122 CONFIRMED +- type FastBuild [pub] — crates/lance-graph-codegraph/src/artifact.rs:153 CONFIRMED +- struct Symbols [pub] — crates/lance-graph-codegraph/src/artifact.rs:158 CONFIRMED +- fn Symbols::intern [pub] — crates/lance-graph-codegraph/src/artifact.rs:165 CONFIRMED +- fn Symbols::get [pub] — crates/lance-graph-codegraph/src/artifact.rs:176 CONFIRMED +- fn Symbols::name [pub] — crates/lance-graph-codegraph/src/artifact.rs:181 CONFIRMED +- fn Symbols::len [pub] — crates/lance-graph-codegraph/src/artifact.rs:186 CONFIRMED +- fn Symbols::is_empty [pub] — crates/lance-graph-codegraph/src/artifact.rs:191 CONFIRMED +- fn Symbols::absorb [pub] — crates/lance-graph-codegraph/src/artifact.rs:198 CONFIRMED +- trait Interner [pub] — crates/lance-graph-codegraph/src/artifact.rs:214 CONFIRMED +- struct SymbolStage [pub] — crates/lance-graph-codegraph/src/artifact.rs:248 CONFIRMED +- struct StagedNames [pub] — crates/lance-graph-codegraph/src/artifact.rs:255 CONFIRMED +- fn SymbolStage<'a>::new [pub] — crates/lance-graph-codegraph/src/artifact.rs:262 CONFIRMED +- fn SymbolStage<'a>::added [pub] — crates/lance-graph-codegraph/src/artifact.rs:271 CONFIRMED +- fn SymbolStage<'a>::into_names [pub] — crates/lance-graph-codegraph/src/artifact.rs:276 CONFIRMED +- struct Lanes [pub] — crates/lance-graph-codegraph/src/artifact.rs:313 CONFIRMED +- fn Lanes::len [pub] — crates/lance-graph-codegraph/src/artifact.rs:345 CONFIRMED +- fn Lanes::is_empty [pub] — crates/lance-graph-codegraph/src/artifact.rs:350 CONFIRMED +- fn Lanes::predicate_name [pub] — crates/lance-graph-codegraph/src/artifact.rs:355 CONFIRMED +- fn Lanes::digest_of [pub] — crates/lance-graph-codegraph/src/artifact.rs:367 CONFIRMED +- fn Lanes::residuals_of [pub] — crates/lance-graph-codegraph/src/artifact.rs:380 CONFIRMED +- fn Lanes::set_residuals [pub] — crates/lance-graph-codegraph/src/artifact.rs:385 CONFIRMED +- fn Lanes::crates [pub] — crates/lance-graph-codegraph/src/artifact.rs:393 CONFIRMED +- fn Lanes::drop_crate [pub] — crates/lance-graph-codegraph/src/artifact.rs:399 CONFIRMED +- fn Lanes::append [pub] — crates/lance-graph-codegraph/src/artifact.rs:444 CONFIRMED +- enum ResidualKind [pub] — crates/lance-graph-codegraph/src/artifact.rs:470 CONFIRMED +- const ResidualKind::ALL [pub] — crates/lance-graph-codegraph/src/artifact.rs:487 CONFIRMED +- fn ResidualKind::name [pub] — crates/lance-graph-codegraph/src/artifact.rs:496 CONFIRMED +- struct ResidualCounts [pub] — crates/lance-graph-codegraph/src/artifact.rs:518 CONFIRMED +- fn ResidualCounts::of [pub] — crates/lance-graph-codegraph/src/artifact.rs:522 CONFIRMED +- fn ResidualCounts::total [pub] — crates/lance-graph-codegraph/src/artifact.rs:527 CONFIRMED +- fn ResidualCounts::add [pub] — crates/lance-graph-codegraph/src/artifact.rs:532 CONFIRMED +- enum ResidualRefusal [pub] — crates/lance-graph-codegraph/src/artifact.rs:541 CONFIRMED +- fn refuse_placeholders [pub] — crates/lance-graph-codegraph/src/artifact.rs:573 CONFIRMED +- const RESIDUAL_SUFFIX [pub] — crates/lance-graph-codegraph/src/artifact.rs:601 CONFIRMED +- fn read_residuals [pub] — crates/lance-graph-codegraph/src/artifact.rs:605 CONFIRMED +- const BIN_SUFFIX [pub] — crates/lance-graph-codegraph/src/artifact.rs:650 CONFIRMED +- enum CrateSource [pub] — crates/lance-graph-codegraph/src/artifact.rs:654 CONFIRMED +- fn crate_source [pub] — crates/lance-graph-codegraph/src/artifact.rs:663 CONFIRMED +- fn read_crate_text [pub] — crates/lance-graph-codegraph/src/artifact.rs:673 CONFIRMED +- fn read_crate [pub] — crates/lance-graph-codegraph/src/artifact.rs:678 CONFIRMED +- fn read_dir [pub] — crates/lance-graph-codegraph/src/artifact.rs:688 CONFIRMED +- fn read_bin_as [pub] — crates/lance-graph-codegraph/src/artifact.rs:737 CONFIRMED +- fn dispatch_target [pub] — crates/lance-graph-codegraph/src/artifact.rs:829 CONFIRMED +- fn read_text [pub] — crates/lance-graph-codegraph/src/artifact.rs:867 CONFIRMED +- fn read_text_as [pub] — crates/lance-graph-codegraph/src/artifact.rs:877 CONFIRMED - const HEADER_LEN [pub] — crates/lance-graph-codegraph/src/artifact_bin.rs:32 CONFIRMED - const NO_ID [pub] — crates/lance-graph-codegraph/src/artifact_bin.rs:34 CONFIRMED - mod tag [pub] — crates/lance-graph-codegraph/src/artifact_bin.rs:51 CONFIRMED @@ -171,29 +172,40 @@ Generated; the code is the truth. See ../index.md. - fn Codegraph::pos_of_id [pub(crate)] — crates/lance-graph-codegraph/src/graph.rs:991 CONFIRMED - fn Codegraph::lanes [pub(crate)] — crates/lance-graph-codegraph/src/graph.rs:996 CONFIRMED - fn Codegraph::partial_crates [pub(crate)] — crates/lance-graph-codegraph/src/graph.rs:1001 CONFIRMED -- fn Codegraph::any_partial [pub(crate)] — crates/lance-graph-codegraph/src/graph.rs:1009 CONFIRMED -- fn Codegraph::words [pub] — crates/lance-graph-codegraph/src/graph.rs:1014 CONFIRMED -- fn Codegraph::mask_of [pub] — crates/lance-graph-codegraph/src/graph.rs:1019 CONFIRMED -- fn Codegraph::crate_status [pub] — crates/lance-graph-codegraph/src/graph.rs:1030 CONFIRMED -- fn Codegraph::rows [pub] — crates/lance-graph-codegraph/src/graph.rs:1036 CONFIRMED -- fn Codegraph::row_predicate [pub] — crates/lance-graph-codegraph/src/graph.rs:1041 CONFIRMED -- fn Codegraph::row_subject [pub] — crates/lance-graph-codegraph/src/graph.rs:1046 CONFIRMED -- fn Codegraph::row_object [pub] — crates/lance-graph-codegraph/src/graph.rs:1051 CONFIRMED -- fn Codegraph::site [pub] — crates/lance-graph-codegraph/src/graph.rs:1056 CONFIRMED -- fn Codegraph::cube [pub] — crates/lance-graph-codegraph/src/graph.rs:1070 CONFIRMED -- fn Codegraph::cube_mut [pub] — crates/lance-graph-codegraph/src/graph.rs:1075 CONFIRMED -- fn Codegraph::cube_and_table_mut [pub(crate)] — crates/lance-graph-codegraph/src/graph.rs:1081 CONFIRMED -- fn Codegraph::table [pub] — crates/lance-graph-codegraph/src/graph.rs:1086 CONFIRMED -- fn Codegraph::fns [pub] — crates/lance-graph-codegraph/src/graph.rs:1091 CONFIRMED -- fn Codegraph::public [pub] — crates/lance-graph-codegraph/src/graph.rs:1095 CONFIRMED -- fn Codegraph::impl_subjects [pub] — crates/lance-graph-codegraph/src/graph.rs:1099 CONFIRMED -- fn Codegraph::synthetic [pub] — crates/lance-graph-codegraph/src/graph.rs:1103 CONFIRMED -- fn Codegraph::referenced [pub] — crates/lance-graph-codegraph/src/graph.rs:1107 CONFIRMED -- fn Codegraph::called [pub] — crates/lance-graph-codegraph/src/graph.rs:1111 CONFIRMED -- fn Codegraph::may_targets [pub] — crates/lance-graph-codegraph/src/graph.rs:1115 CONFIRMED -- fn Codegraph::dynamic_callers [pub] — crates/lance-graph-codegraph/src/graph.rs:1119 CONFIRMED -- fn Codegraph::stored_owner [pub] — crates/lance-graph-codegraph/src/graph.rs:1123 CONFIRMED -- fn Codegraph::closure [pub] — crates/lance-graph-codegraph/src/graph.rs:1129 CONFIRMED +- fn Codegraph::stored_crates [pub(crate)] — crates/lance-graph-codegraph/src/graph.rs:1010 CONFIRMED +- fn Codegraph::residuals_of_crate [pub(crate)] — crates/lance-graph-codegraph/src/graph.rs:1020 CONFIRMED +- fn Codegraph::any_partial [pub(crate)] — crates/lance-graph-codegraph/src/graph.rs:1032 CONFIRMED +- fn Codegraph::words [pub] — crates/lance-graph-codegraph/src/graph.rs:1037 CONFIRMED +- fn Codegraph::mask_of [pub] — crates/lance-graph-codegraph/src/graph.rs:1042 CONFIRMED +- fn Codegraph::crate_status [pub] — crates/lance-graph-codegraph/src/graph.rs:1053 CONFIRMED +- fn Codegraph::rows [pub] — crates/lance-graph-codegraph/src/graph.rs:1059 CONFIRMED +- fn Codegraph::row_predicate [pub] — crates/lance-graph-codegraph/src/graph.rs:1064 CONFIRMED +- fn Codegraph::row_subject [pub] — crates/lance-graph-codegraph/src/graph.rs:1069 CONFIRMED +- fn Codegraph::row_object [pub] — crates/lance-graph-codegraph/src/graph.rs:1074 CONFIRMED +- fn Codegraph::site [pub] — crates/lance-graph-codegraph/src/graph.rs:1079 CONFIRMED +- fn Codegraph::cube [pub] — crates/lance-graph-codegraph/src/graph.rs:1093 CONFIRMED +- fn Codegraph::cube_mut [pub] — crates/lance-graph-codegraph/src/graph.rs:1098 CONFIRMED +- fn Codegraph::cube_and_table_mut [pub(crate)] — crates/lance-graph-codegraph/src/graph.rs:1104 CONFIRMED +- fn Codegraph::table [pub] — crates/lance-graph-codegraph/src/graph.rs:1109 CONFIRMED +- fn Codegraph::fns [pub] — crates/lance-graph-codegraph/src/graph.rs:1114 CONFIRMED +- fn Codegraph::public [pub] — crates/lance-graph-codegraph/src/graph.rs:1118 CONFIRMED +- fn Codegraph::impl_subjects [pub] — crates/lance-graph-codegraph/src/graph.rs:1122 CONFIRMED +- fn Codegraph::synthetic [pub] — crates/lance-graph-codegraph/src/graph.rs:1126 CONFIRMED +- fn Codegraph::referenced [pub] — crates/lance-graph-codegraph/src/graph.rs:1130 CONFIRMED +- fn Codegraph::called [pub] — crates/lance-graph-codegraph/src/graph.rs:1134 CONFIRMED +- fn Codegraph::may_targets [pub] — crates/lance-graph-codegraph/src/graph.rs:1138 CONFIRMED +- fn Codegraph::dynamic_callers [pub] — crates/lance-graph-codegraph/src/graph.rs:1142 CONFIRMED +- fn Codegraph::stored_owner [pub] — crates/lance-graph-codegraph/src/graph.rs:1146 CONFIRMED +- fn Codegraph::closure [pub] — crates/lance-graph-codegraph/src/graph.rs:1152 CONFIRMED +- struct Targets [pub] — crates/lance-graph-codegraph/src/impact_report.rs:26 CONFIRMED +- const Targets::LIB_ONLY [pub] — crates/lance-graph-codegraph/src/impact_report.rs:39 CONFIRMED +- const Targets::ALL [pub] — crates/lance-graph-codegraph/src/impact_report.rs:47 CONFIRMED +- struct Scope [pub] — crates/lance-graph-codegraph/src/impact_report.rs:70 CONFIRMED +- enum SymbolState [pub] — crates/lance-graph-codegraph/src/impact_report.rs:93 CONFIRMED +- enum Gap [pub] — crates/lance-graph-codegraph/src/impact_report.rs:108 CONFIRMED +- struct ImpactReport [pub] — crates/lance-graph-codegraph/src/impact_report.rs:185 CONFIRMED +- fn ImpactReport::closed_in_scope [pub] — crates/lance-graph-codegraph/src/impact_report.rs:198 CONFIRMED +- fn Codegraph::impact_report [pub] — crates/lance-graph-codegraph/src/impact_report.rs:337 CONFIRMED - enum Fault [pub(crate)] cfg=test — crates/lance-graph-codegraph/src/lab_wal.rs:19 CONFIRMED - struct LabWal [pub(crate)] cfg=test — crates/lance-graph-codegraph/src/lab_wal.rs:35 CONFIRMED - fn LabWal::new [pub(crate)] cfg=test — crates/lance-graph-codegraph/src/lab_wal.rs:44 CONFIRMED @@ -205,15 +217,14 @@ Generated; the code is the truth. See ../index.md. - mod artifact_bin [pub] — crates/lance-graph-codegraph/src/lib.rs:7 CONFIRMED - mod diag [pub] — crates/lance-graph-codegraph/src/lib.rs:8 CONFIRMED - mod graph [pub] — crates/lance-graph-codegraph/src/lib.rs:9 CONFIRMED -- mod query [pub] — crates/lance-graph-codegraph/src/lib.rs:12 CONFIRMED +- mod impact_report [pub] — crates/lance-graph-codegraph/src/lib.rs:10 CONFIRMED +- mod query [pub] — crates/lance-graph-codegraph/src/lib.rs:13 CONFIRMED - struct Graded [pub] — crates/lance-graph-codegraph/src/query.rs:21 CONFIRMED - struct Calls [pub] — crates/lance-graph-codegraph/src/query.rs:32 CONFIRMED - struct Sites [pub] — crates/lance-graph-codegraph/src/query.rs:41 CONFIRMED - enum QueryRefusal [pub] — crates/lance-graph-codegraph/src/query.rs:52 CONFIRMED - fn Codegraph::callers [pub] — crates/lance-graph-codegraph/src/query.rs:125 CONFIRMED -- fn Codegraph::callees [pub] — crates/lance-graph-codegraph/src/query.rs:157 CONFIRMED -- fn Codegraph::references [pub] — crates/lance-graph-codegraph/src/query.rs:188 CONFIRMED -- fn Codegraph::impact [pub] — crates/lance-graph-codegraph/src/query.rs:239 CONFIRMED +- truncated (203 total), see symbols.tsv ## Imports from in-scope crates diff --git a/.codegraph/freshness.tsv b/.codegraph/freshness.tsv index c6f966411..5fb3e2360 100644 --- a/.codegraph/freshness.tsv +++ b/.codegraph/freshness.tsv @@ -36,7 +36,7 @@ lance-graph-benches 2f2fb296a08260fb Cargo.toml+src (1 files) lance-graph-callcenter 41a65d38ac70bc87 Cargo.toml+src (36 files) lance-graph-catalog 9d0c34f70c28a465 Cargo.toml+src (10 files) lance-graph-codec-research 8b8afbd9a6d0f359 Cargo.toml+src (11 files) -lance-graph-codegraph bd209bed318ffbbc Cargo.toml+src (9 files) +lance-graph-codegraph 832b307522eeaa24 Cargo.toml+src (10 files) lance-graph-cognitive 93f956ac0d69ca66 Cargo.toml+src (61 files) lance-graph-consumer-conformance 82e980465d770990 Cargo.toml+src (3 files) lance-graph-contract 6b4e13ff1d0afadb Cargo.toml+src (176 files) diff --git a/.codegraph/imports.tsv b/.codegraph/imports.tsv index 448f89dc0..5e53cf009 100644 --- a/.codegraph/imports.tsv +++ b/.codegraph/imports.tsv @@ -4738,17 +4738,17 @@ lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 10 lance_graph_x lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 10 lance_graph_xlog::cube::StagedEdges - use - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 11 lance_graph_xlog::wide::WideRows - use - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 11 lance_graph_xlog::wide::WideStats - use - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1149 super::* - use test POSSIBLE -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1150 std::fs - use test CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1151 std::path::PathBuf - use test CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1152 std::sync::atomic::AtomicU32 - use test CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1152 std::sync::atomic::Ordering - use test CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1347 super::* - use test POSSIBLE -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1348 std::collections::BTreeMap - use test CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1349 std::fs - use test CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1350 std::path::PathBuf - use test CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1351 std::sync::atomic::AtomicU32 - use test CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1351 std::sync::atomic::Ordering - use test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1172 super::* - use test POSSIBLE +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1173 std::fs - use test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1174 std::path::PathBuf - use test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1175 std::sync::atomic::AtomicU32 - use test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1175 std::sync::atomic::Ordering - use test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1370 super::* - use test POSSIBLE +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1371 std::collections::BTreeMap - use test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1372 std::fs - use test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1373 std::path::PathBuf - use test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1374 std::sync::atomic::AtomicU32 - use test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1374 std::sync::atomic::Ordering - use test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 14 crate::artifact - use - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 14 crate::artifact::CrateSource - use - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 14 crate::artifact::Interner - use - CONFIRMED @@ -4807,6 +4807,15 @@ lance-graph-codegraph crates/lance-graph-codegraph/src/graph/publication.rs 22 s lance-graph-codegraph crates/lance-graph-codegraph/src/graph/publication.rs 23 super::Codegraph - use test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph/publication.rs 23 super::PreparedRefresh - use test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph/publication.rs 24 crate::lab_wal::LabWal - use test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 16 std::collections::BTreeSet - use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 17 std::path::Path - use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 17 std::path::PathBuf - use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 19 crate::artifact::ResidualCounts - use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 19 crate::artifact::fnv64_hex - use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 20 crate::graph::Codegraph - use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 20 crate::graph::Pos - use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 21 crate::query::Graded - use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 21 crate::query::QueryRefusal - use - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 11 lance_graph_contract::scheduler::DatasetVersion - use test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 13 lance_graph_planner::persist_sink::CommitError - use test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 13 lance_graph_planner::persist_sink::CommitOutcome - use test CONFIRMED @@ -4820,12 +4829,12 @@ lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 14 lance_graph lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 170 super::* - use test POSSIBLE lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 171 lance_graph_planner::persist_sink::CycleFrame - use test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 9 std::collections::BTreeMap - use test CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 14 graph::Codegraph - pub-use - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 14 graph::IntakeRefusal - pub-use - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 14 graph::Pos - pub-use - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 14 graph::RefreshRefusal - pub-use - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 14 graph::RefreshStats - pub-use - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 14 graph::RunStatus - pub-use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 15 graph::Codegraph - pub-use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 15 graph::IntakeRefusal - pub-use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 15 graph::Pos - pub-use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 15 graph::RefreshRefusal - pub-use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 15 graph::RefreshStats - pub-use - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 15 graph::RunStatus - pub-use - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/query.rs 10 lance_graph_xlog::cube::CubeRefusal - use - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/query.rs 10 lance_graph_xlog::cube::RelId - use - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/query.rs 11 lance_graph_xlog::wide::WideRows - use - CONFIRMED diff --git a/.codegraph/symbols.tsv b/.codegraph/symbols.tsv index bea7437c0..973cd63ec 100644 --- a/.codegraph/symbols.tsv +++ b/.codegraph/symbols.tsv @@ -8545,75 +8545,76 @@ lance-graph-codec-research crates/lance-graph-codec-research/src/zeckbf17.rs 645 lance-graph-codec-research crates/lance-graph-codec-research/src/zeckbf17.rs 80 fn verify_golden_coverage pub - CONFIRMED lance-graph-codec-research crates/lance-graph-codec-research/src/zeckbf17.rs 881 impl std::fmt::Display for FidelityReport - - CONFIRMED lance-graph-codec-research crates/lance-graph-codec-research/src/zeckbf17.rs 95 struct BasePattern pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 112 struct FastHasher pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 116 impl Hasher for FastHasher - - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 143 type FastBuild pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 148 struct Symbols pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 153 impl Symbols - - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 155 fn Symbols::intern pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 166 fn Symbols::get pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 171 fn Symbols::name pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 176 fn Symbols::len pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 181 fn Symbols::is_empty pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 188 fn Symbols::absorb pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 204 trait Interner pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 219 impl Interner for Symbols - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 110 fn fnv64_hex pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 122 struct FastHasher pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 126 impl Hasher for FastHasher - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 153 type FastBuild pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 158 struct Symbols pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 163 impl Symbols - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 165 fn Symbols::intern pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 176 fn Symbols::get pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 181 fn Symbols::name pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 186 fn Symbols::len pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 191 fn Symbols::is_empty pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 198 fn Symbols::absorb pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 214 trait Interner pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 229 impl Interner for Symbols - - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 23 const ROWS_VERSION pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 238 struct SymbolStage pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 245 struct StagedNames pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 250 impl SymbolStage<'a> - - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 252 fn SymbolStage<'a>::new pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 261 fn SymbolStage<'a>::added pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 266 fn SymbolStage<'a>::into_names pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 274 impl Interner for SymbolStage<'_> - - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 303 struct Lanes pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 333 impl Lanes - - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 335 fn Lanes::len pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 340 fn Lanes::is_empty pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 345 fn Lanes::predicate_name pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 357 fn Lanes::digest_of pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 248 struct SymbolStage pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 255 struct StagedNames pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 260 impl SymbolStage<'a> - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 262 fn SymbolStage<'a>::new pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 271 fn SymbolStage<'a>::added pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 276 fn SymbolStage<'a>::into_names pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 284 impl Interner for SymbolStage<'_> - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 313 struct Lanes pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 343 impl Lanes - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 345 fn Lanes::len pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 350 fn Lanes::is_empty pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 355 fn Lanes::predicate_name pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 367 fn Lanes::digest_of pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 37 const NO_SPAN pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 370 fn Lanes::residuals_of pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 375 fn Lanes::set_residuals pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 383 fn Lanes::crates pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 389 fn Lanes::drop_crate pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 380 fn Lanes::residuals_of pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 385 fn Lanes::set_residuals pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 393 fn Lanes::crates pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 399 fn Lanes::drop_crate pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 40 const NO_ID pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 43 const P_DEFINES pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 434 fn Lanes::append pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 444 fn Lanes::append pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 45 const P_CALLS pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 460 enum ResidualKind pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 47 const P_MAY pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 475 impl ResidualKind - - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 477 const ResidualKind::ALL pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 486 fn ResidualKind::name pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 470 enum ResidualKind pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 485 impl ResidualKind - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 487 const ResidualKind::ALL pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 49 const P_UNRESOLVED pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 508 struct ResidualCounts pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 496 fn ResidualKind::name pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 51 const P_PUBLIC pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 510 impl ResidualCounts - - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 512 fn ResidualCounts::of pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 517 fn ResidualCounts::total pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 522 fn ResidualCounts::add pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 518 struct ResidualCounts pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 520 impl ResidualCounts - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 522 fn ResidualCounts::of pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 527 fn ResidualCounts::total pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 53 const P_IMPLEMENTS pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 531 enum ResidualRefusal pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 532 fn ResidualCounts::add pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 541 enum ResidualRefusal pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 55 const P_SYNTHETIC pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 563 fn refuse_placeholders pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 57 const P_REFERENCES pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 573 fn refuse_placeholders pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 59 const P_CRATE pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 591 const RESIDUAL_SUFFIX pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 595 fn read_residuals pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 601 const RESIDUAL_SUFFIX pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 605 fn read_residuals pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 62 const P_OTHER pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 640 const BIN_SUFFIX pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 644 enum CrateSource pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 653 fn crate_source pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 663 fn read_crate_text pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 668 fn read_crate pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 678 fn read_dir pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 727 fn read_bin_as pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 650 const BIN_SUFFIX pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 654 enum CrateSource pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 663 fn crate_source pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 673 fn read_crate_text pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 678 fn read_crate pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 688 fn read_dir pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 737 fn read_bin_as pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 78 fn pred_code pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 819 fn dispatch_target pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 833 impl Memo<'a,N> - - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 857 fn read_text pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 867 fn read_text_as pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 829 fn dispatch_target pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 843 impl Memo<'a,N> - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 867 fn read_text pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 877 fn read_text_as pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact.rs 98 fn digest pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact_bin.rs 125 enum BinRefusal pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/artifact_bin.rs 192 impl fmt::Display for BinRefusal - - CONFIRMED @@ -8684,29 +8685,31 @@ lance-graph-codegraph crates/lance-graph-codegraph/src/diag.rs 69 enum FindingSt lance-graph-codegraph crates/lance-graph-codegraph/src/diag.rs 79 enum Run pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/diag.rs 98 enum CrateKind pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1001 fn Codegraph::partial_crates pub(crate) - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1009 fn Codegraph::any_partial pub(crate) - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1014 fn Codegraph::words pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1019 fn Codegraph::mask_of pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1030 fn Codegraph::crate_status pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1036 fn Codegraph::rows pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1041 fn Codegraph::row_predicate pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1046 fn Codegraph::row_subject pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1051 fn Codegraph::row_object pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1056 fn Codegraph::site pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1070 fn Codegraph::cube pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1075 fn Codegraph::cube_mut pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1081 fn Codegraph::cube_and_table_mut pub(crate) - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1086 fn Codegraph::table pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1091 fn Codegraph::fns pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1095 fn Codegraph::public pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1099 fn Codegraph::impl_subjects pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1103 fn Codegraph::synthetic pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1107 fn Codegraph::referenced pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1111 fn Codegraph::called pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1115 fn Codegraph::may_targets pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1119 fn Codegraph::dynamic_callers pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1123 fn Codegraph::stored_owner pub - CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1129 fn Codegraph::closure pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1010 fn Codegraph::stored_crates pub(crate) - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1020 fn Codegraph::residuals_of_crate pub(crate) - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1032 fn Codegraph::any_partial pub(crate) - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1037 fn Codegraph::words pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1042 fn Codegraph::mask_of pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1053 fn Codegraph::crate_status pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1059 fn Codegraph::rows pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1064 fn Codegraph::row_predicate pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1069 fn Codegraph::row_subject pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1074 fn Codegraph::row_object pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1079 fn Codegraph::site pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1093 fn Codegraph::cube pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1098 fn Codegraph::cube_mut pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1104 fn Codegraph::cube_and_table_mut pub(crate) - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1109 fn Codegraph::table pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1114 fn Codegraph::fns pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1118 fn Codegraph::public pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1122 fn Codegraph::impl_subjects pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1126 fn Codegraph::synthetic pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1130 fn Codegraph::referenced pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1134 fn Codegraph::called pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1138 fn Codegraph::may_targets pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1142 fn Codegraph::dynamic_callers pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1146 fn Codegraph::stored_owner pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 1152 fn Codegraph::closure pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 130 impl PosAt for Positions - - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 158 impl PosAt for PosStage<'_> - - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 167 impl PosStage<'a> - - CONFIRMED @@ -8738,6 +8741,18 @@ lance-graph-codegraph crates/lance-graph-codegraph/src/graph.rs 996 fn Codegraph lance-graph-codegraph crates/lance-graph-codegraph/src/graph/publication.rs 108 impl Record - test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph/publication.rs 165 impl W0 - test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/graph/publication.rs 65 impl ClassView for PubView - test CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 108 enum Gap pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 185 struct ImpactReport pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 194 impl ImpactReport - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 198 fn ImpactReport::closed_in_scope pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 26 struct Targets pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 331 impl Codegraph - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 337 fn Codegraph::impact_report pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 37 impl Targets - - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 39 const Targets::LIB_ONLY pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 47 const Targets::ALL pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 70 struct Scope pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/impact_report.rs 93 enum SymbolState pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 19 enum Fault pub(crate) test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 35 struct LabWal pub(crate) test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 43 impl LabWal - test CONFIRMED @@ -8747,7 +8762,8 @@ lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 58 fn LabWal:: lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 64 fn LabWal::reverse_physical_order pub(crate) test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 70 fn LabWal::image pub(crate) test CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lab_wal.rs 78 impl WalSink for LabWal - test CONFIRMED -lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 12 mod query pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 10 mod impact_report pub - CONFIRMED +lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 13 mod query pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 6 mod artifact pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 7 mod artifact_bin pub - CONFIRMED lance-graph-codegraph crates/lance-graph-codegraph/src/lib.rs 8 mod diag pub - CONFIRMED diff --git a/.codegraph/views/BindStore.md b/.codegraph/views/BindStore.md index 0af6749c8..13506d23e 100644 --- a/.codegraph/views/BindStore.md +++ b/.codegraph/views/BindStore.md @@ -53,7 +53,7 @@ Generated; the code is the truth. Same-name symbols stay separate per file. - crates/grammar-constraints-probe/src/when.rs:39 POSSIBLE - crates/grammar-constraints-probe/src/when.rs:313 POSSIBLE - crates/grammar-constraints-probe/src/when.rs:414 POSSIBLE -- crates/lance-graph-codegraph/src/graph.rs:1564 POSSIBLE +- crates/lance-graph-codegraph/src/graph.rs:1587 POSSIBLE - crates/lance-graph-codegraph/src/graph/publication.rs:6 POSSIBLE - crates/lance-graph-codegraph/src/graph/publication.rs:16 POSSIBLE - crates/lance-graph-codegraph/src/graph/publication.rs:39 POSSIBLE From b0364e4ecd33333121a78d8ecb8403529aea818b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 07:17:56 +0000 Subject: [PATCH 08/11] probe: D-CODEGRAPH-RECON-2 report-rs evidence, blind grading, board entry Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- .../entries/2026-11-11-codegraph-recon-2.md | 25 +++ .claude/board/entries/README.md | 3 +- .../2026-11-11-codegraph-recon-2/GRADES.tsv | 26 +++ .../2026-11-11-codegraph-recon-2/REPORT.md | 150 ++++++++++++++++++ .../answer-key.md | 45 ++++++ .../answers/armC.md | 29 ++++ .../answers/armM.md | 36 +++++ .../2026-11-11-codegraph-recon-2/questions.md | 12 ++ .../store-output/fake_new.refs | 2 + .../store-output/identityframe_commit.callees | 10 ++ .../store-output/ledger_pull.callees | 7 + .../store-output/ledger_pull.callers | 4 + .../store-output/ledger_pull.refs | 5 + .../missing.authorize_memberships.report | 2 + .../store-output/missing.maplog.report | 2 + .../missing.report_rs_iam_authorize.report | 5 + .../store-output/poll.callers | 2 + .../store-output/poll.report | 7 + .../store-output/pull.callers | 10 ++ .../store-output/pull.report | 110 +++++++++++++ .../store-output/srcpull.report | 6 + 21 files changed, 497 insertions(+), 1 deletion(-) create mode 100644 .claude/board/entries/2026-11-11-codegraph-recon-2.md create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/GRADES.tsv create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/REPORT.md create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/answer-key.md create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/answers/armC.md create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/answers/armM.md create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/questions.md create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/fake_new.refs create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/identityframe_commit.callees create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.callees create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.callers create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.refs create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.authorize_memberships.report create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.maplog.report create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.report_rs_iam_authorize.report create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/poll.callers create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/poll.report create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/pull.callers create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/pull.report create mode 100644 .claude/probes/2026-11-11-codegraph-recon-2/store-output/srcpull.report diff --git a/.claude/board/entries/2026-11-11-codegraph-recon-2.md b/.claude/board/entries/2026-11-11-codegraph-recon-2.md new file mode 100644 index 000000000..acd5ab61b --- /dev/null +++ b/.claude/board/entries/2026-11-11-codegraph-recon-2.md @@ -0,0 +1,25 @@ +# 2026-11-11 — Coverage-aware impact; report-rs #33 recovered from compiler facts + +**Status:** MEASURED (probe). `.claude/probes/2026-11-11-codegraph-recon-2/`. Follows +`2026-11-11-codegraph-recon-1` (#2000). Board: EXO-229, EXO-230. + +`Codegraph::impact_report` (additive; `impact` unchanged) returns `impact`'s masks plus typed gaps: +external consumers unobserved, targets not extracted or undeclared, excluded regions, unresolved +dispatch, incomplete harvest, stale or unrecorded files, and `.rs` files under a read directory that +`files.tsv` does not list. Missing coverage never enters `Graded.unknown`. A missing symbol carries +its crate's gaps. 11 tests; every guard disable-verified red. + +report-rs `81705d9` through Charon (lib, default features, `crate::app` opaque): CRATE `COMPLETE`, +yet 14 of 59 `src/` files unread (`iam.rs`, `main.rs`, `project_plan/*`, …). The store recovers the +first #33 finding: `workbook_delta::WorkbookSource::poll` has no library caller and no path to +`Ledger::ingest`; `Ledger::pull → source_fake::pull` is dynamic and reported UNKNOWN. + +Blind arms graded strictly against the EXO-185 key (12 items): source arm 12 correct; store arm +7 correct, 3 partial, 2 unsupported; 0 wrong in both. The store's misses are configuration +(feature-gated `iam`), targets (test callers) and manifest facts (Cargo.toml). n = 1 per arm. + +#2000 reproduces from its documented commands: rows equal, `machine-recovered.mmd` byte-identical, +Charon recall column identical. + +OPEN: per-configuration stores (features, test targets); recording targets and opaque modules in +the store instead of declaring them. diff --git a/.claude/board/entries/README.md b/.claude/board/entries/README.md index 6a6e823bb..cf28e5540 100644 --- a/.claude/board/entries/README.md +++ b/.claude/board/entries/README.md @@ -25,10 +25,11 @@ index row, (3) no duplicate entry id. Checks 1 and 2 are deliberately opposite directions; the stranding this convention prevents shows up in exactly one of them, never both. -597 entries, 2026-08-06 .. 2026-11-11. +598 entries, 2026-08-06 .. 2026-11-11. | date | entry id | finding | file | |---|---|---|---| +| 2026-11-11 | `codegraph-recon-2` | | [2026-11-11-codegraph-recon-2.md](2026-11-11-codegraph-recon-2.md) | | 2026-11-11 | `codegraph-recon-1` | | [2026-11-11-codegraph-recon-1.md](2026-11-11-codegraph-recon-1.md) | | 2026-11-10 | `lab-resolve-borrow-all` | | [2026-11-10-lab-resolve-borrow-all.md](2026-11-10-lab-resolve-borrow-all.md) | | 2026-11-10 | `int8-direct-packed-b` | | [2026-11-10-int8-direct-packed-b.md](2026-11-10-int8-direct-packed-b.md) | diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/GRADES.tsv b/.claude/probes/2026-11-11-codegraph-recon-2/GRADES.tsv new file mode 100644 index 000000000..ae87cf288 --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/GRADES.tsv @@ -0,0 +1,26 @@ +#version 1 +#schema key arm grade note +K1.1 M CORRECT both identities, source_fake.rs:19 and workbook_delta/source.rs:210 +K1.1 C PARTIAL both identities CONFIRMED; defining lines UNKNOWN (the store records spans, not struct lines) +K1.2 M CORRECT source_fake.rs:29 impl Source +K1.2 C CORRECT IMPLEMENTS rows; witness source_fake.rs:39 (the pull fn, not the impl line) +K1.3 M CORRECT inherent poll, returns Poll, no Source impl +K1.3 C CORRECT no Source impl for the delta type, ABSENT-IN-SCOPE +K1.4 M CORRECT Ledger::pull calls src.pull (333) then ingest (334); projection.rs:409 passes source_fake +K1.4 C CORRECT ingest edge CONFIRMED at source.rs:334; dyn Source call reported UNKNOWN, not CONFIRMED +K1.5 M CORRECT no src caller of poll; callers in tests/p20 and examples/workbook_sync.rs; lands in Workbook::ingest +K1.5 C PARTIAL poll has 0 callers in the lib scope and no edge to Ledger::ingest; test/example callers not named (targets not extracted, reported as a gap) +K1.6 M CORRECT does not claim poll has no callers at all +K1.6 C CORRECT ABSENT-IN-SCOPE with tests/examples UNOBSERVED; never "no callers" +K2.1 M CORRECT iam.rs:250, behind feature iam (lib.rs:22-23) +K2.1 C UNSUPPORTED iam.rs reported unread, feature off, call UNOBSERVED +K2.2 M CORRECT no authorize_scoped anywhere +K2.2 C CORRECT ABSENT-IN-SCOPE, with the iam build UNOBSERVED +K2.3 M CORRECT gating stated; default build does not compile iam +K2.3 C CORRECT does not claim report-rs never authorizes +K3.1 M CORRECT no dt64-lance dependency (Cargo.toml), no MapLog in any file +K3.1 C PARTIAL no MapLog symbol in scope; the dependency fact is outside the store and not stated; lance-feature build left UNOBSERVED +K3.2 M CORRECT IdentityFrame holds MapTable (frame.rs:55-57), advanced in commit (189-203) +K3.2 C CORRECT MapTable::new frame.rs:69, advance frame.rs:195 in IdentityFrame::commit, called from ingest.rs:264 +K3.3 M CORRECT absence stated over every file and Cargo.toml, independent of features +K3.3 C UNSUPPORTED did not frame it as a dependency-scope fact diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/REPORT.md b/.claude/probes/2026-11-11-codegraph-recon-2/REPORT.md new file mode 100644 index 000000000..fa1adebe1 --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/REPORT.md @@ -0,0 +1,150 @@ +# D-CODEGRAPH-RECON-2: coverage-aware impact, and report-rs #33 from compiler facts + +D-CODEGRAPH-RECON-1 (#2000) showed that `Codegraph::impact` returns an empty set for a public +symbol whose callers live in crates the store does not hold. This probe keeps `impact` as it is +and adds `Codegraph::impact_report`, which returns the same masks plus a typed list of what the +answer could not see. It then answers three questions about report-rs PR #33 from a Charon store +and grades the answers against the manual EXO-185 findings, which were held out. + +Result: the store recovers the first #33 finding (the SharePoint drive source never reaches +`Ledger::ingest` from library code), explains it correctly, and names every region it could not +see. Both arms made no wrong statement. The source-reading arm was more complete, because the +store sees one build configuration and one target. + +## 1. `impact_report` (Gate A) + +`crates/lance-graph-codegraph/src/impact_report.rs`. `Codegraph::impact` is unchanged and +`ImpactReport.graded` is exactly its output. Missing coverage is never written into +`Graded.unknown`, which stays "observed functions a dynamic call may reach". + +| gap | source of the fact | +|---|---| +| `ExternalConsumersUnobserved` | `PUBLIC` row, and the consumer set is not declared closed | +| `TargetsNotExtracted` / `TargetsUndeclared` | declared per crate (the store does not record targets) | +| `RegionsExcluded` | declared: opaque modules, features left off | +| `UnresolvedDispatch` | `UNRESOLVED_CALL` rows that may reach the symbol | +| `HarvestIncomplete` | residuals file, CRATE status | +| `StaleSource` / `FilesUnrecorded` / `FreshnessUnchecked` | `.files.tsv` digests against the source root | +| `SourceFilesUnread` | `.rs` files below a directory the extraction read from, absent from `files.tsv` | + +A missing symbol in a stored crate carries its crate's target, region and file gaps, because each +is a place it may still be defined. `closed_in_scope()` is true only for a found symbol with no +gap, and it claims nothing about code outside the scope. `Coverage::no_known_gap()` alone is not +treated as closure: test 2 asserts it is true while the report is not closed. + +`tests/impact_coverage.rs`, 11 tests, one per case in the brief plus three found while running +Gate B (excluded regions, target gaps of a missing symbol, unread files). Every guard was disabled +and its test went red: external consumers, missing targets, undeclared targets, dispatch fire, +dispatch silence, stale source, owner stored, observed consumers, closed symbol, harvest, +missing-symbol scope gaps, excluded regions, unread files (fire and silence), missing-symbol file +gaps. + +## 2. The report-rs store (Gate B) + +Inputs: report-rs `81705d9` (#33 head). Charon `c69e231`, nightly-2026-09-17, library target, +default features, `--opaque 'crate::app'` (the full crate ran out of memory at 15 GB). ruff_charon +from ruff `9752608`. + +| step | time (µs, reported, not gates) | result | +|---|---|---| +| charon | 42,192,655 | exit 0 | +| ruff_charon import | 25,202,579 | 29,542 harvested, 1 residual (`REFERENCE_NOT_NAMED view::Scope::only`) | +| six cg_query runs (cold open each) | 435,149 | | + +The CRATE row says `COMPLETE`, yet 14 of 59 files under `src/` were never read: `app.rs` and +`app/plan_routes.rs` (opaque), `iam.rs`, `login.rs`, `flow_scratch.rs`, `project_plan/*` (features +off), `main.rs` (binary target), `workbook_delta/dt64/p21_lane_socket_lab.rs`. That is what +`SourceFilesUnread` reports, from `files.tsv` alone. Nothing was inserted into the store by hand. + +Raw query output is in `store-output/`. + +### Q1: the two `WorkbookSource` types + +```mermaid +flowchart LR + load["Projection::load_v1"] -->|"CONFIRMED projection.rs:409"| new["source_fake::WorkbookSource::new"] + load -->|"CONFIRMED projection.rs:408"| lpull["Ledger::pull"] + into["source_graph::pull_into"] -->|"CONFIRMED source_graph.rs:357"| lpull + lpull -->|"UNKNOWN dyn Source, source.rs:333"| fpull["source_fake impl Source::pull"] + fpull -.->|IMPLEMENTS| spull["Source::pull"] + lpull -->|"CONFIRMED source.rs:334"| ingest["Ledger::ingest"] + poll["workbook_delta WorkbookSource::poll"] -.-|"0 callers in lib; tests, examples, app, main unread"| gap(("UNOBSERVED")) +``` + +- Confirmed: two identities, `report_rs::source_fake::WorkbookSource` and + `report_rs::workbook_delta::source::WorkbookSource`; only the first implements `Source`. + `Ledger::pull` calls `Ledger::ingest` (source.rs:334). `Projection::load_v1` builds the + `source_fake` source (projection.rs:409) and passes it to `Ledger::pull`. +- Possible / unknown: `Ledger::pull` reaches `source_fake::pull` only through `&mut dyn Source` + (source.rs:333). The compiler does not name that target, so the store reports UNKNOWN, not an edge. +- Absent in scope: `poll` has no caller in the library target with default features, and no path + from it reaches `Ledger::ingest`. Gaps: tests and examples not extracted, `crate::app` opaque, + `main.rs` unread, the symbol is public. +- Falsifier: one `src/` call of `WorkbookSource::poll` whose result reaches `Ledger::ingest` + (for example an `impl Source` for the delta type) turns this into a confirmed edge on re-import. + +### Q2: authorization + +`lance_graph_rbac` symbols are missing with `owner_stored: false`; `report_rs::iam::*` is missing +with `SourceFilesUnread` naming `src/iam.rs`. The store therefore cannot say whether report-rs +authorizes: the module that would do it was not compiled. Falsifier: re-extract with +`--features iam` and query `iam` callers. + +### Q3: map persistence + +No `lance_graph_dt64_lance` symbol in scope. `IdentityFrame::commit` calls +`lance_graph_dt64::dr::MapTable::advance` (frame.rs:195), CONFIRMED. Whether report-rs depends on +`lance-graph-dt64-lance` is a manifest fact the store does not hold; the store answer is +"absent in scope". Falsifier: a `MapLog` call in any compiled file. + +## 3. Graded comparison (Gate D) + +Two blind arms on the same model, the same questions (`questions.md`) and the same revision. +Arm M read source only. Arm C queried the store with `cg_query` and read source only at lines the +store printed. Grading against `answer-key.md`, strict: a materially false statement is WRONG even +with a coverage disclaimer. Full grades in `GRADES.tsv`; answers in `answers/`. + +| | correct | partial | unsupported | wrong | tool calls | elapsed s | tokens | +|---|---|---|---|---|---|---|---| +| M (source) | 12 | 0 | 0 | 0 | 13 | 71.0 | 456,784 | +| C (store) | 7 | 3 | 2 | 0 | 8 | 59.8 | 456,309 | + +The token counts are dominated by the shared session context both arms load, so they do not +separate the arms. n = 1 per arm; this is an observation, not a ranking. + +Where the store was weaker, and why: + +- **Build configuration.** Source text includes `#[cfg(feature = "iam")]` code; the store holds + one configuration. K2.1 (the `authorize_memberships` call) is visible only to arm M. +- **Targets.** The store holds the library target, so the test and example callers of `poll` + (K1.5) are unobserved. Arm C reported the gap; it did not name the callers. +- **Manifest facts.** "report-rs does not depend on dt64-lance" (K3.1, K3.3) comes from + Cargo.toml, which the store does not read. +- **Definition lines.** The store records function spans, not struct lines (K1.1). + +Where the store was stronger: arm C's `Ledger::pull → source_fake::pull` is reported UNKNOWN +(dynamic dispatch) instead of asserted, and every absence it states carries its scope. Arm M's +text search is feature-blind in both directions: it saw the `iam` call, and it would equally have +reported a cfg-dead call as live. + +Acceptance (brief): the store independently recovers the first #33 missing-integration finding, +explains it correctly, and reports what it cannot prove. Met. + +## 4. #2000 checks + +- The PR description, REPORT.md §4 and `recon.py --self-test` all give 15 tests; the self-test + passes. +- CI at the head (`90fc5a7`) and the merge (`317c4ff`) is green on every workflow. +- Reproduction from the documented commands, in a fresh worktree at `317c4ff` with sibling ndarray + at `fd3d2e7`: rows per crate equal REPORT.md's table (represented + 3), `machine-recovered.mmd` + is byte-identical, and the Charon column of `score.tsv` is identical (61 HIT, 26 MISS, + 32 UNOBSERVED). The rust-analyzer column was not re-run. + +## 5. Open + +- Feature and target matrices: one store per configuration, merged, would close K1.5 and K2.1. + Charon needs `crate::app` opaque at 15 GB. +- `RegionsExcluded` and `Targets` are declared by the caller. The extractor could record both in + the store (they are its own arguments), which would turn them into store facts. +- `SourceFilesUnread` scans the top directory of each recorded path; files recorded at the source + root trigger no scan. diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/answer-key.md b/.claude/probes/2026-11-11-codegraph-recon-2/answer-key.md new file mode 100644 index 000000000..3a86f7b21 --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/answer-key.md @@ -0,0 +1,45 @@ +# Held-out answer key — D-CODEGRAPH-RECON-2 Gate B/D + +Source: EXO-185 manual findings (2026-11-10/11), re-checked by hand against +report-rs `81705d9` (PR #33 head). This file is NOT an input to any store and +is never shown to an arm before grading. + +## Q1 — the two `WorkbookSource` types (EXO-185 loose end A) + +K1.1 Two distinct identities: + - `report_rs::source_fake::WorkbookSource` (src/source_fake.rs:19) + - `report_rs::workbook_delta::source::WorkbookSource` (src/workbook_delta/source.rs:210) +K1.2 Only `source_fake::WorkbookSource` implements `report_rs::source::Source` + (src/source_fake.rs:29); its `pull` builds an `IngestBatch` (source_fake.rs:39, :61). +K1.3 `workbook_delta::source::WorkbookSource` has an inherent `poll` + (workbook_delta/source.rs:292) returning `Poll` (`Unchanged` | `Changed(VerifiedSnapshot)`); + it has no `Source` impl and builds no `IngestBatch`. +K1.4 `Ledger::pull(&mut dyn Source, _)` (src/source.rs:331) calls `Source::pull` (dynamic) + and `Ledger::ingest` (source.rs:334). The lib's only `Ledger::pull` caller with a + workbook source is `projection.rs:409`, passing `source_fake::WorkbookSource::new`. +K1.5 Missing integration: no lib (`src/`) code calls `workbook_delta::...::WorkbookSource::poll`. + Its only caller is `tests/p20_workbook_delta.rs:304`, which feeds `Workbook::ingest` + (tests/p20:308), not the ledger. So the real SharePoint puller never reaches + `Ledger::ingest`. Absence scope: all of `src/` and `tests/` at 81705d9, default features. +K1.6 Correct framing: the edge `poll → IngestBatch/Ledger::ingest` is ABSENT within the + lib target; test callers exist (p20). Claiming "poll has no callers at all" is FALSE. + +## Q2 — reader scope (EXO-185 loose end B, ledger item 3) + +K2.1 report-rs calls `lance_graph_rbac::authorize::authorize_memberships` only from + `src/iam.rs:250`, and `iam` is behind feature `iam` (src/lib.rs:22-23; Cargo.toml:107), + OFF by default. +K2.2 No call to `authorize_scoped` anywhere in report-rs `src/` or `tests/` at 81705d9. +K2.3 Correct framing for a default-features extraction: the `iam` module is UNOBSERVED + (not compiled), so "report-rs never authorizes" is FALSE; "no `authorize_scoped` call" + needs either the iam feature extracted or a source scope check. + +## Q3 — MapLog / value persistence (EXO-185 loose end C, ledger 5a/5b) + +K3.1 report-rs does not depend on `lance-graph-dt64-lance` (Cargo.toml: only + `lance-graph-dt64`, line 46); no `MapLog` use in src/ or tests/. +K3.2 DR identity lives in memory: `IdentityFrame` holds a `MapTable` + (src/workbook_delta/frame.rs:56), advanced in `IdentityFrame::commit` + (frame.rs:189, `self.table.advance(` at :195). +K3.3 Correct framing: the store cannot see crates report-rs does not depend on; "no + MapLog call" is a dependency-scope fact (Cargo.toml), not a call-graph absence. diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/answers/armC.md b/.claude/probes/2026-11-11-codegraph-recon-2/answers/armC.md new file mode 100644 index 000000000..0bfac3131 --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/answers/armC.md @@ -0,0 +1,29 @@ +# Arm C answers (Charon graph, report-rs 81705d9; scope S = lib target, default features, crate::app opaque) +Scope S, stated once: report_rs lib target only (tests/examples/benches NOT extracted); region crate::app opaque; features lance,iam,flow,oidc,projects,projects-pg off. Unread files per GAP: src/app.rs, src/app/plan_routes.rs, src/flow_scratch.rs, src/iam.rs, src/login.rs, src/main.rs, src/project_plan/*, src/workbook_delta/dt64/p21_lane_socket_lab.rs. External consumers of public items are UNOBSERVED. Harvest has 1 residual (HarvestIncomplete). + +## Q1 +a. Two types, identified by graph module paths: + - report_rs::source_fake::WorkbookSource (non-generic; constructor `source_fake::WorkbookSource::new`) + - report_rs::workbook_delta::source::WorkbookSource (generic over a transport T; has new/into_transport/token/meta/poll) + Defining file:line: UNKNOWN from the graph (it prints no def lines; I did not read source at unprinted locations). Files by module path: src/source_fake.rs and src/workbook_delta/source.rs. Witness inside the first: src/source_fake.rs:39 (the `fn pull` in the Source impl). + CONFIRMED (identities), UNKNOWN (def lines). +b. source_fake::WorkbookSource implements Source (impl_Source_for_WorkbookSource::{id,name,lanes,pull} + vtable shim; src/source_fake.rs:39). The workbook_delta WorkbookSource has NO impl_Source_for_* symbol in scope S: ABSENT-IN-SCOPE (scope S). +c. Edges (all CONFIRMED, scope S): + - Ledger::pull -> Ledger::ingest: src/source.rs:334 (`self.ingest(batch)` on Ok). + - Ledger::replay -> Ledger::ingest: src/source.rs:357. + - projection::record_artifact -> Ledger::ingest: src/projection.rs:845, :852. + - Projection::load_v1 -> Ledger::pull: src/projection.rs:408, :413, :416; load_v1 -> source_fake::WorkbookSource::new: src/projection.rs:409. + - source_graph::pull_into -> Ledger::pull: src/source_graph.rs:357; load_v1 -> pull_into: src/projection.rs:429. + - Source::pull for source_fake::WorkbookSource: only edge is its vtable method (src/source_fake.rs:39); callers are dynamic dispatch via Ledger::pull, reported UNKNOWN by the graph (trait-object call, not resolved to the impl). + - IngestBatch: constructed/consumed by pull (return type), ingest, status/last_watermark/values closures and rules::source_basis closures; no separate "IngestBatch edge" witnessed beyond those symbols. + - Separate, different ingest: workbook_delta::ingest::Workbook::ingest, which calls IdentityFrame::commit (src/workbook_delta/ingest.rs:264); IdentityFrame::new called from Workbook::open (src/workbook_delta/ingest.rs:117). This is NOT Ledger::ingest. + CONFIRMED. +d. workbook_delta WorkbookSource::poll has 0 callers in scope S (sites=0); its callees are meta/token/item_url/sha256_hex/status_class and ReqwestDrive::get (POSSIBLE). No edge from poll (or from WorkbookSource::new, 0 refs) to Ledger::ingest or Workbook::ingest; Workbook::ingest also has 0 callers in S. Answer: ABSENT-IN-SCOPE for library code in S. Cannot say absent overall: poll/new/Workbook::ingest are PUBLIC (external callers UNOBSERVED), tests/examples not extracted, src/app.rs (opaque) and src/main.rs unread, and the p21 lab file unread, so a caller there is UNOBSERVED. +e. Scopes: as per header S for every "no caller/no edge" statement (Q1b, Q1d). + +## Q2 +Graph has no symbol containing authoriz, rbac, memberships, or lance_graph_rbac in the extracted scope, so no call to authorize_memberships / authorize_scoped appears: ABSENT-IN-SCOPE under scope S. Only unrelated names found (Ledger::register_scoped, Projection::scoped). The most likely home, src/iam.rs, is unread and feature iam is off, so under the `iam` feature (or in src/app.rs, opaque) the answer is UNOBSERVED. Witnesses: none (absence). Build configuration with a CONFIRMED call: none observed. + +## Q3 +Part 1, persistence through lance-graph-dt64-lance / MapLog: no symbol matching dt64_lance, lance_graph_dt64_lance, or MapLog: ABSENT-IN-SCOPE (scope S; features lance and others off, tests/examples not extracted, p21 lab file unread). Whether it happens under feature `lance` is UNOBSERVED. +Part 2, where the MapTable is held/advanced (CONFIRMED, scope S): lance_graph_dt64::dr::MapTable is held in the identity frame, workbook_delta::frame::IdentityFrame: MapTable::new(0,0) at src/workbook_delta/frame.rs:69 (via IdentityFrame::new, also from Default at :62), seal at src/workbook_delta/frame.rs:101, advance at src/workbook_delta/frame.rs:195 inside IdentityFrame::commit. commit is called by Workbook::ingest (src/workbook_delta/ingest.rs:264); Workbook::open builds the frame (src/workbook_delta/ingest.rs:117). The in-memory table is not persisted by any edge in S. Callers of Workbook::ingest: none in S (see Q1d), so the advance path is reached from library code only if an unobserved caller exists. diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/answers/armM.md b/.claude/probes/2026-11-11-codegraph-recon-2/answers/armM.md new file mode 100644 index 000000000..600356ce3 --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/answers/armM.md @@ -0,0 +1,36 @@ +# Arm M answers (report-rs @ /home/user/rr-81705d9) + +Scope notes: default features = `default = []` (Cargo.toml `[features]`). Searched all `*.rs` under src/, tests/, examples/ (and Cargo.toml, Cargo.lock, Dockerfiles, docs/*.md for Q2/Q3). Only lib crate (src/lib.rs) and bin src/main.rs exist (no src/bin/); no workspace members. + +## Q1 +a. Two `WorkbookSource` types: + - `report_rs::source_fake::WorkbookSource` — src/source_fake.rs:19 (`pub struct WorkbookSource { fixture: Fixture }`). + - `report_rs::workbook_delta::source::WorkbookSource` — src/workbook_delta/source.rs:210 (`pub struct WorkbookSource { cfg, transport }`). Module declared at src/lib.rs:48 (`pub mod workbook_delta;`), `pub mod source;` in src/workbook_delta/mod.rs. + CONFIRMED. + +b. Only `source_fake::WorkbookSource` implements `report_rs::source::Source`: src/source_fake.rs:29 `impl Source for WorkbookSource`. The trait is src/source.rs:171. The workbook_delta type has only inherent impls (src/workbook_delta/source.rs:215 `impl WorkbookSource`); grep of "Source for" / "IngestBatch" / "Ledger" across src/workbook_delta/** found no `Source` trait impl (only an unrelated `LaneSource` in src/workbook_delta/dt64/p21_lane_socket_lab.rs:188 and dt64.rs). CONFIRMED (the delta type is not a `Source`); scope: src/workbook_delta/*.rs, src/workbook_delta/dt64/*.rs, all of src/. + +c. Edges: + - `Source::pull` declared src/source.rs:180 (`fn pull(&mut self, since: Option, now_ms: i64) -> Result`); returns `IngestBatch` (struct src/source.rs:135). Implemented at src/source_fake.rs:39 (workbook fake; builds `IngestBatch{..}`), 107, 188 (other fakes), src/source_graph.rs:257. + - `Ledger` struct src/source.rs:259; `Ledger::ingest(&mut self, batch: IngestBatch)` src/source.rs:302. + - `Ledger::pull(&mut self, src: &mut dyn Source, now_ms)` src/source.rs:330 calls `src.pull(since, now_ms)` (333) and on Ok `self.ingest(batch)` (334). This is the pull->IngestBatch->ingest edge. + - Callers of `Ledger::pull`: src/projection.rs:409 (`.pull(&mut WorkbookSource::new(base.clone()), now_ms)` using source_fake::WorkbookSource, import at projection.rs:10), 414, 417 (fake sharepoint/spear); src/source_graph.rs:357 (`ledger.pull(src, now_ms)` in `pull_into`); many tests (e.g. tests/p2_scope.rs:32). + - Other direct `Ledger::ingest` callers: src/projection.rs:845, 852 (mapping state batches); src/source.rs:357. (src/gov/mod.rs:48 / src/gov/observation.rs:263 are a different `ingest` on a different gov ledger type with `LicSnapshot`, not `source::Ledger`.) + - `poll`: only defined at src/workbook_delta/source.rs:292 (`WorkbookSource::poll(&mut self, last_etag, now_ms) -> Result`); it returns `Poll`, not `IngestBatch`. + - Delta-side landing is `workbook_delta::ingest::Workbook::ingest(&mut self, snap: &VerifiedSnapshot) -> Outcome` (src/workbook_delta/ingest.rs:161), a distinct method, not `Ledger::ingest`. + CONFIRMED. + +d. Does workbook_delta source reach `Ledger::ingest` from library code? No edge found. Callers of the delta `poll`: examples/workbook_sync.rs:37 (`src.poll(wb.last_etag(), now)`, then `wb.ingest(&snap)` at :46 which is `Workbook::ingest`), tests/p20_workbook_delta.rs:304,311,331,350. No call of `.poll(` anywhere in src/ outside its definition. Nothing in src/ outside src/workbook_delta references `workbook_delta` except `pub mod workbook_delta;` (src/lib.rs:48), and nothing in src/workbook_delta references `IngestBatch`/`source::Ledger`. So library code never calls delta `poll` and the delta source never reaches `source::Ledger::ingest`. ABSENT-IN-SCOPE. + +e. Scope for each "no edge / no caller": grep `-rn "poll("`, `"IngestBatch"` (files containing it: src/source_graph.rs, source_fake.rs, projection.rs, source.rs, tests/p3_evidence.rs, tests/p3b_delta.rs), `"workbook_delta"`, `"Workbook::open"` over all *.rs in src/, tests/, examples/ (src/main.rs, src/app.rs, src/app/** included); features: default (none) — and the grep is feature-agnostic (cfg-gated code is still text-searched, none of these hits are cfg-gated). Not examined: external crates (git deps), dynamic dispatch/macros beyond text grep. A grep with no hits is navigation only; I opened src/workbook_delta/mod.rs, source.rs (210-300), ingest.rs (1-125,150-165,260) to confirm the doc says the delta source "returns a verified snapshot" landed via `Workbook::ingest`. + +## Q2 +Yes, but only when feature `iam` is on. `authorize_memberships`: src/iam.rs:21 `use lance_graph_rbac::authorize::authorize_memberships;` and call at src/iam.rs:250 inside `LanceGraphScope::decide_in` (impl at src/iam.rs:243). `authorize_scoped`: no occurrence anywhere (grep of whole repo, *.rs/*.toml/*.md): ABSENT. +Build gating: `pub mod iam;` is `#[cfg(feature = "iam")]` (src/lib.rs:22-23); `lance-graph-rbac` is `optional = true` and enabled only via `iam = ["dep:lance-graph-rbac", ...]`; `lance = ["iam","oidc"]` (Cargo.toml [features]). Reach from app: src/scope.rs:563-566 `authority()` under `#[cfg(feature = "iam")]` constructs `crate::iam::LanceGraphScope::new` (src/scope.rs:566); `#[cfg(not(feature="iam"))]` arm (568) uses `StaticScope`. `authority` is called at src/app.rs:562, 752 etc. Dockerfile:36 builds `--features lance`; Dockerfile.standalone:18 has no rbac. +- authorize_memberships: CONFIRMED under `--features iam` (or `lance`); ABSENT in default-feature build (module not compiled). +- authorize_scoped: ABSENT-IN-SCOPE (all *.rs, Cargo.toml, docs, tests, examples searched; features irrelevant as no text hit). +Also tests/p33_intake.rs:263 only mentions lance_graph_rbac in a test name. + +## Q3 +No. There is no use of `lance-graph-dt64-lance` or `MapLog` anywhere: grep for "dt64-lance|dt64_lance|MapLog" over *.rs, *.toml, *.md, Dockerfiles, Cargo.lock found nothing (Cargo.toml dependencies list only `lance-graph-dt64` (git, main), not a `-lance` crate; Cargo.lock has `lance-graph-dt64` at line 1366 only). ABSENT-IN-SCOPE (all features; text-wide). +Identity `MapTable` (from `lance_graph_dt64::dr`) is held in memory in `IdentityFrame { table: MapTable, tiles }` (src/workbook_delta/frame.rs:55-57, constructed `MapTable::new(0, 0)` at :69) and advanced by `IdentityFrame::commit` calling `self.table.advance(source, 0, ...)` (src/workbook_delta/frame.rs:189-203). `IdentityFrame` is a field of `workbook_delta::ingest::Workbook` (src/workbook_delta/ingest.rs:99, built at :117 in `Workbook::open`); advance occurs at ingest.rs:264 `self.frame.commit(u64::from(number), fplan)`. Planning (`plan`, frame.rs:131) advances nothing. Persistence explicitly absent: src/workbook_delta/ingest.rs:11-16 ("Persistence is not here ... It writes no file and opens no dataset"). `Workbook::open` callers are only examples/ and tests/ (examples/workbook_sync.rs:26, workbook_head_to_head.rs:183, workbook_bench.rs:21, tests/p20_workbook_delta.rs:47,635,651); no src/ caller outside the module. CONFIRMED (in-memory only) / persistence ABSENT-IN-SCOPE. diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/questions.md b/.claude/probes/2026-11-11-codegraph-recon-2/questions.md new file mode 100644 index 000000000..3210137a5 --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/questions.md @@ -0,0 +1,12 @@ +# Questions (report-rs at /home/user/rr-81705d9, commit 81705d9, default cargo features) + +Q1. The crate defines two types named `WorkbookSource`. + a. Give the fully qualified identity and defining file:line of each. + b. Which of them implements `report_rs::source::Source`? + c. Trace `poll`, `Source::pull`, `IngestBatch` and `Ledger::ingest`: which edges exist, with file:line witnesses? + d. Does the workbook_delta (SharePoint drive) source reach `Ledger::ingest` from library code? Who calls its `poll`? + e. For every "no edge / no caller" statement, state the scope you examined (files, targets, features). +Q2. Does report-rs call `lance_graph_rbac::authorize::authorize_memberships` or `authorize_scoped`? Under which build configuration? Give witnesses and scope. +Q3. Does report-rs persist DR identity through `lance-graph-dt64-lance` (`MapLog`)? Where is the identity `MapTable` held and advanced? Give witnesses and scope. + +Answer format: for each sub-question, a short statement, then CONFIRMED / ABSENT-IN-SCOPE / UNOBSERVED, then witnesses (file:line), then scope. Say UNKNOWN rather than guess. diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/fake_new.refs b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/fake_new.refs new file mode 100644 index 000000000..34e097722 --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/fake_new.refs @@ -0,0 +1,2 @@ +ref CALLS_RESOLVED report_rs::projection::{Projection}::load_v1 src/projection.rs:409 +sites confirmed=1 possible=0 diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/identityframe_commit.callees b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/identityframe_commit.callees new file mode 100644 index 000000000..6443bc91b --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/identityframe_commit.callees @@ -0,0 +1,10 @@ +callees CONFIRMED alloc::vec::impl_Deref_for_Vec::deref +callees CONFIRMED alloc::vec::impl_IntoIterator_for_Vec::into_iter +callees CONFIRMED alloc::vec::{Vec[TraitClause0, TraitClause1, TraitClause2]}::push +callees CONFIRMED alloc::vec::{impl IntoIterator for &'a Vec[TraitClause0, TraitClause1, TraitClause2]}::into_iter +callees CONFIRMED core::iter::traits::iterator::Iterator::collect +callees CONFIRMED core::iter::traits::iterator::Iterator::map +callees CONFIRMED core::slice::iter::{impl Iterator for core::slice::iter::Iter<'a, T>[TraitClause0]}::next +callees CONFIRMED core::slice::{[T]}::contains +callees CONFIRMED lance_graph_dt64::dr::{MapTable}::advance +sites 9 diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.callees b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.callees new file mode 100644 index 000000000..45aa1a09e --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.callees @@ -0,0 +1,7 @@ +callees CONFIRMED core::result::{Result[TraitClause0, TraitClause1]}::map +callees CONFIRMED report_rs::source::{report_rs::source::Ledger}::ingest +callees CONFIRMED report_rs::source::{report_rs::source::Ledger}::last_watermark +callees CONFIRMED report_rs::source::{report_rs::source::Ledger}::record_failure +callees CONFIRMED report_rs::source::{report_rs::source::Ledger}::register_scoped +callees UNKNOWN ?dynamic +sites 5 diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.callers b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.callers new file mode 100644 index 000000000..d3f09cfee --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.callers @@ -0,0 +1,4 @@ +callers CONFIRMED report_rs::projection::{Projection}::load_v1 +callers CONFIRMED report_rs::source_graph::pull_into +sites 4 +callers UNKNOWN external-callers-unobserved report_rs::source::{report_rs::source::Ledger}::pull is PUBLIC diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.refs b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.refs new file mode 100644 index 000000000..6273aa05d --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/ledger_pull.refs @@ -0,0 +1,5 @@ +ref CALLS_RESOLVED report_rs::source_graph::pull_into src/source_graph.rs:357 +ref CALLS_RESOLVED report_rs::projection::{Projection}::load_v1 src/projection.rs:408 +ref CALLS_RESOLVED report_rs::projection::{Projection}::load_v1 src/projection.rs:413 +ref CALLS_RESOLVED report_rs::projection::{Projection}::load_v1 src/projection.rs:416 +sites confirmed=4 possible=0 diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.authorize_memberships.report b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.authorize_memberships.report new file mode 100644 index 000000000..72e2a85f8 --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.authorize_memberships.report @@ -0,0 +1,2 @@ +symbol MISSING owner_stored=false lance_graph_rbac::authorize::authorize_memberships +closed_in_scope false diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.maplog.report b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.maplog.report new file mode 100644 index 000000000..42f51924e --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.maplog.report @@ -0,0 +1,2 @@ +symbol MISSING owner_stored=false lance_graph_dt64_lance::MapLog +closed_in_scope false diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.report_rs_iam_authorize.report b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.report_rs_iam_authorize.report new file mode 100644 index 000000000..ed64b7a1b --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/missing.report_rs_iam_authorize.report @@ -0,0 +1,5 @@ +symbol MISSING owner_stored=true report_rs::iam::authorize +GAP TargetsNotExtracted { krate: "report_rs", missing: Targets { lib: false, tests: true, examples: true, benches: true } } +GAP RegionsExcluded { krate: "report_rs", regions: ["opaque:crate::app", "features-off:lance,iam,flow,oidc,projects,projects-pg"] } +GAP SourceFilesUnread { krate: "report_rs", files: ["src/app.rs", "src/app/plan_routes.rs", "src/flow_scratch.rs", "src/iam.rs", "src/login.rs", "src/main.rs", "src/project_plan/calendar.rs", "src/project_plan/engine.rs", "src/project_plan/mod.rs", "src/project_plan/pg.rs", "src/project_plan/projection.rs", "src/project_plan/store.rs", "src/project_plan/view.rs", "src/workbook_delta/dt64/p21_lane_socket_lab.rs"] } +closed_in_scope false diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/poll.callers b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/poll.callers new file mode 100644 index 000000000..7d615582b --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/poll.callers @@ -0,0 +1,2 @@ +sites 0 +callers UNKNOWN external-callers-unobserved report_rs::workbook_delta::source::{report_rs::workbook_delta::source::WorkbookSource[TraitClause0, TraitClause1]}::poll is PUBLIC diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/poll.report b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/poll.report new file mode 100644 index 000000000..b0bc6a00f --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/poll.report @@ -0,0 +1,7 @@ +symbol FOUND 3615 report_rs::workbook_delta::source::{report_rs::workbook_delta::source::WorkbookSource[TraitClause0, TraitClause1]}::poll +GAP ExternalConsumersUnobserved { owner: "report_rs", observed_consumers: [] } +GAP TargetsNotExtracted { krate: "report_rs", missing: Targets { lib: false, tests: true, examples: true, benches: true } } +GAP RegionsExcluded { krate: "report_rs", regions: ["opaque:crate::app", "features-off:lance,iam,flow,oidc,projects,projects-pg"] } +GAP HarvestIncomplete { krate: "report_rs", residuals: ResidualCounts([0, 0, 1, 0, 0]), partial: false, no_residuals_file: false } +GAP SourceFilesUnread { krate: "report_rs", files: ["src/app.rs", "src/app/plan_routes.rs", "src/flow_scratch.rs", "src/iam.rs", "src/login.rs", "src/main.rs", "src/project_plan/calendar.rs", "src/project_plan/engine.rs", "src/project_plan/mod.rs", "src/project_plan/pg.rs", "src/project_plan/projection.rs", "src/project_plan/store.rs", "src/project_plan/view.rs", "src/workbook_delta/dt64/p21_lane_socket_lab.rs"] } +closed_in_scope false diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/pull.callers b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/pull.callers new file mode 100644 index 000000000..72bd19dca --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/pull.callers @@ -0,0 +1,10 @@ +callers CONFIRMED report_rs::source_fake::impl_Source_for_WorkbookSource::pull::{vtable_method} +callers UNKNOWN report_rs::mapping_hydrate::hydrate_artifact +callers UNKNOWN report_rs::mapping_hydrate::publish_artifact +callers UNKNOWN report_rs::mapping_hydrate::publish_artifact::{impl Fn<(&'_2 str, &'_3 [u8], &'_4 str)> for report_rs::mapping_hydrate::publish_artifact::{closure}<'_0, '_1>}::call +callers UNKNOWN report_rs::mapping_hydrate::repoint +callers UNKNOWN report_rs::mapping_hydrate::{Ctx<'_0, T>[TraitClause0]}::fetch_manifest +callers UNKNOWN report_rs::rules::plan::{impl FnMut<(&'_2 Box<(dyn Rule + '_3), Global>[{built_in impl MetaSized for (dyn Rule + '_3)}, {built_in impl Sized for Global}, impl_Allocator_for_Global],)> for report_rs::rules::plan::{closure}<'_0, '_1>}::call_mut +callers UNKNOWN report_rs::source::{report_rs::source::Ledger}::pull +sites 1 +callers UNKNOWN external-callers-unobserved report_rs::source_fake::impl_Source_for_WorkbookSource::pull is PUBLIC diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/pull.report b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/pull.report new file mode 100644 index 000000000..dade573a9 --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/pull.report @@ -0,0 +1,110 @@ +symbol FOUND 1717 report_rs::source_fake::impl_Source_for_WorkbookSource::pull +impact CONFIRMED report_rs::source_fake::impl_Source_for_WorkbookSource::pull::{vtable_method} +impact UNKNOWN report_rs::cli::run +impact UNKNOWN report_rs::cli::run::{impl FnOnce<(S3Client,)> for report_rs::cli::run::{closure#3}<'_0>}::call_once +impact UNKNOWN report_rs::cli::store +impact UNKNOWN report_rs::fixture::{ReportType}::within::{impl FnMut<(&'_1 &'_2 str,)> for report_rs::fixture::{ReportType}::within::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::fixture::{ReportType}::within::{impl FnOnce<(&'_1 &'_2 str,)> for report_rs::fixture::{ReportType}::within::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::lance_adapter::parity +impact UNKNOWN report_rs::mapping_hydrate::hydrate +impact UNKNOWN report_rs::mapping_hydrate::hydrate_artifact +impact UNKNOWN report_rs::mapping_hydrate::hydrate_artifact::{impl FnOnce<(Pointer,)> for report_rs::mapping_hydrate::hydrate_artifact::{closure}<'_0, '_1, T>[TraitClause0, TraitClause1]}::call_once +impact UNKNOWN report_rs::mapping_hydrate::hydrate_from_env +impact UNKNOWN report_rs::mapping_hydrate::hydrate_kind_from_env +impact UNKNOWN report_rs::mapping_hydrate::publish +impact UNKNOWN report_rs::mapping_hydrate::publish_artifact +impact UNKNOWN report_rs::mapping_hydrate::publish_artifact::{impl Fn<(&'_2 str, &'_3 [u8], &'_4 str)> for report_rs::mapping_hydrate::publish_artifact::{closure}<'_0, '_1>}::call +impact UNKNOWN report_rs::mapping_hydrate::publish_artifact::{impl FnMut<(&'_2 str, &'_3 [u8], &'_4 str)> for report_rs::mapping_hydrate::publish_artifact::{closure}<'_0, '_1>}::call_mut +impact UNKNOWN report_rs::mapping_hydrate::publish_artifact::{impl FnOnce<(&'_2 str, &'_3 [u8], &'_4 str)> for report_rs::mapping_hydrate::publish_artifact::{closure}<'_0, '_1>}::call_once +impact UNKNOWN report_rs::mapping_hydrate::repoint +impact UNKNOWN report_rs::mapping_hydrate::store_from_env +impact UNKNOWN report_rs::mapping_hydrate::{Ctx<'_0, T>[TraitClause0]}::fetch_manifest +impact UNKNOWN report_rs::mapping_hydrate::{Ctx<'_0, T>[TraitClause0]}::load_local +impact UNKNOWN report_rs::mapping_hydrate::{Ctx<'_0, T>[TraitClause0]}::publish_local +impact UNKNOWN report_rs::mapping_hydrate::{Ctx<'_0, T>[TraitClause0]}::publish_local::{impl Fn<()> for report_rs::mapping_hydrate::{Ctx<'_0, T>[TraitClause0]}::publish_local::{closure}<'_0, '_1, '_2, '_3, '_4, '_5, '_6, T>[TraitClause0]}::call +impact UNKNOWN report_rs::mapping_hydrate::{Ctx<'_0, T>[TraitClause0]}::publish_local::{impl FnMut<()> for report_rs::mapping_hydrate::{Ctx<'_0, T>[TraitClause0]}::publish_local::{closure}<'_0, '_1, '_2, '_3, '_4, '_5, '_6, T>[TraitClause0]}::call_mut +impact UNKNOWN report_rs::mapping_hydrate::{Ctx<'_0, T>[TraitClause0]}::publish_local::{impl FnOnce<()> for report_rs::mapping_hydrate::{Ctx<'_0, T>[TraitClause0]}::publish_local::{closure}<'_0, '_1, '_2, '_3, '_4, '_5, '_6, T>[TraitClause0]}::call_once +impact UNKNOWN report_rs::mapping_hydrate::{HydrateConfig}::from_vars +impact UNKNOWN report_rs::mapping_hydrate::{HydrateConfig}::from_vars_for +impact UNKNOWN report_rs::mapping_hydrate::{HydrateConfig}::from_vars_for::{impl Fn<(&'_2 str,)> for report_rs::mapping_hydrate::{HydrateConfig}::from_vars_for::{closure}<'_0, '_1, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call +impact UNKNOWN report_rs::mapping_hydrate::{HydrateConfig}::from_vars_for::{impl FnMut<(&'_2 str,)> for report_rs::mapping_hydrate::{HydrateConfig}::from_vars_for::{closure}<'_0, '_1, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::mapping_hydrate::{HydrateConfig}::from_vars_for::{impl FnOnce<(&'_2 str,)> for report_rs::mapping_hydrate::{HydrateConfig}::from_vars_for::{closure}<'_0, '_1, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::mapping_hydrate::{HydrateConfig}::from_vars_for::{impl FnOnce<()> for report_rs::mapping_hydrate::{HydrateConfig}::from_vars_for::{closure#1}<'_0, '_1, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::mobile::render +impact UNKNOWN report_rs::objstore::{S3Config}::from_suffixed_env +impact UNKNOWN report_rs::objstore::{S3Config}::from_vars +impact UNKNOWN report_rs::objstore::{S3Config}::from_vars::{impl Fn<(&'_3 str,)> for report_rs::objstore::{S3Config}::from_vars::{closure}<'_0, '_1, '_2, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call +impact UNKNOWN report_rs::objstore::{S3Config}::from_vars::{impl FnMut<(&'_3 str,)> for report_rs::objstore::{S3Config}::from_vars::{closure}<'_0, '_1, '_2, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::objstore::{S3Config}::from_vars::{impl FnOnce<(&'_3 str,)> for report_rs::objstore::{S3Config}::from_vars::{closure}<'_0, '_1, '_2, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::oracle::summary +impact UNKNOWN report_rs::oracle::summary_where +impact UNKNOWN report_rs::oracle::summary_where::{closure}::{impl FnMut<(&'_1 &'_2 report_rs::fixture::Customer,)> for report_rs::oracle::summary_where::{closure}::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::oracle::summary_where::{closure}::{impl FnOnce<(&'_1 &'_2 report_rs::fixture::Customer,)> for report_rs::oracle::summary_where::{closure}::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::projection::labels_for +impact UNKNOWN report_rs::projection::{Projection}::load_v1 +impact UNKNOWN report_rs::projection::{Projection}::parity +impact UNKNOWN report_rs::projection::{Projection}::summary +impact UNKNOWN report_rs::rules::each_owed +impact UNKNOWN report_rs::rules::impl_Rule_for_ConfiguredButNoRun::propose +impact UNKNOWN report_rs::rules::impl_Rule_for_ConfiguredButNoRun::propose::{vtable_method} +impact UNKNOWN report_rs::rules::impl_Rule_for_DeliveredWithoutEvidence::propose +impact UNKNOWN report_rs::rules::impl_Rule_for_DeliveredWithoutEvidence::propose::{vtable_method} +impact UNKNOWN report_rs::rules::impl_Rule_for_EvidenceStale::propose +impact UNKNOWN report_rs::rules::impl_Rule_for_EvidenceStale::propose::{vtable_method} +impact UNKNOWN report_rs::rules::impl_Rule_for_OwedButNotConfigured::propose +impact UNKNOWN report_rs::rules::impl_Rule_for_OwedButNotConfigured::propose::{vtable_method} +impact UNKNOWN report_rs::rules::impl_Rule_for_RunFailed::propose +impact UNKNOWN report_rs::rules::impl_Rule_for_RunFailed::propose::{vtable_method} +impact UNKNOWN report_rs::rules::plan::{impl FnMut<(&'_2 Box<(dyn Rule + '_3), Global>[{built_in impl MetaSized for (dyn Rule + '_3)}, {built_in impl Sized for Global}, impl_Allocator_for_Global],)> for report_rs::rules::plan::{closure}<'_0, '_1>}::call_mut +impact UNKNOWN report_rs::rules::plan::{impl FnOnce<(&'_2 Box<(dyn Rule + '_3), Global>[{built_in impl MetaSized for (dyn Rule + '_3)}, {built_in impl Sized for Global}, impl_Allocator_for_Global],)> for report_rs::rules::plan::{closure}<'_0, '_1>}::call_once +impact UNKNOWN report_rs::rules::validate::{impl FnMut<(&'_6 Change,)> for report_rs::rules::validate::{closure#1}<'_0, '_1, '_2, '_3, '_4, '_5, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::rules::validate::{impl FnOnce<(&'_6 Change,)> for report_rs::rules::validate::{closure#1}<'_0, '_1, '_2, '_3, '_4, '_5, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::scope::decide_with_fallback::{impl FnMut<(&'_1 String,)> for report_rs::scope::decide_with_fallback::{closure#2}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::scope::decide_with_fallback::{impl FnMut<(&'_1 String,)> for report_rs::scope::decide_with_fallback::{closure#3}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::scope::decide_with_fallback::{impl FnOnce<(&'_1 String,)> for report_rs::scope::decide_with_fallback::{closure#2}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::scope::decide_with_fallback::{impl FnOnce<(&'_1 String,)> for report_rs::scope::decide_with_fallback::{closure#3}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::scope::{ActorSource}::from_env +impact UNKNOWN report_rs::scope::{ActorSource}::from_vars +impact UNKNOWN report_rs::scope::{StaticScope}::from_env +impact UNKNOWN report_rs::scope::{StaticScope}::from_vars +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::pull +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::retain_sources::{impl FnMut<(&'_1 (report_rs::source::SourceId, IngestBatchId), &'_2 mut IngestBatch)> for report_rs::source::{report_rs::source::Ledger}::retain_sources::{closure}<'_0, T0>[TraitClause0, TraitClause1]}::call_mut +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::retain_sources::{impl FnMut<(&'_1 SourceFailure,)> for report_rs::source::{report_rs::source::Ledger}::retain_sources::{closure#1}<'_0, T0>[TraitClause0, TraitClause1]}::call_mut +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::retain_sources::{impl FnMut<(&'_1 report_rs::source::SourceId, &'_2 mut BTreeSet[{built_in impl Sized for ObservationLane}, {built_in impl Sized for Global}, impl_AllocatorClone_for_Global])> for report_rs::source::{report_rs::source::Ledger}::retain_sources::{closure#2}<'_0, T0>[TraitClause0, TraitClause1]}::call_mut +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::retain_sources::{impl FnMut<(&'_1 report_rs::source::SourceId, &'_2 mut SourceScope)> for report_rs::source::{report_rs::source::Ledger}::retain_sources::{closure#3}<'_0, T0>[TraitClause0, TraitClause1]}::call_mut +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::retain_sources::{impl FnMut<(&'_1 report_rs::source::SourceId, &'_2 mut String)> for report_rs::source::{report_rs::source::Ledger}::retain_sources::{closure#4}<'_0, T0>[TraitClause0, TraitClause1]}::call_mut +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::retain_sources::{impl FnOnce<(&'_1 (report_rs::source::SourceId, IngestBatchId), &'_2 mut IngestBatch)> for report_rs::source::{report_rs::source::Ledger}::retain_sources::{closure}<'_0, T0>[TraitClause0, TraitClause1]}::call_once +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::retain_sources::{impl FnOnce<(&'_1 SourceFailure,)> for report_rs::source::{report_rs::source::Ledger}::retain_sources::{closure#1}<'_0, T0>[TraitClause0, TraitClause1]}::call_once +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::retain_sources::{impl FnOnce<(&'_1 report_rs::source::SourceId, &'_2 mut BTreeSet[{built_in impl Sized for ObservationLane}, {built_in impl Sized for Global}, impl_AllocatorClone_for_Global])> for report_rs::source::{report_rs::source::Ledger}::retain_sources::{closure#2}<'_0, T0>[TraitClause0, TraitClause1]}::call_once +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::retain_sources::{impl FnOnce<(&'_1 report_rs::source::SourceId, &'_2 mut SourceScope)> for report_rs::source::{report_rs::source::Ledger}::retain_sources::{closure#3}<'_0, T0>[TraitClause0, TraitClause1]}::call_once +impact UNKNOWN report_rs::source::{report_rs::source::Ledger}::retain_sources::{impl FnOnce<(&'_1 report_rs::source::SourceId, &'_2 mut String)> for report_rs::source::{report_rs::source::Ledger}::retain_sources::{closure#4}<'_0, T0>[TraitClause0, TraitClause1]}::call_once +impact UNKNOWN report_rs::source_graph::pull_into +impact UNKNOWN report_rs::source_graph::{GraphConfig}::from_env +impact UNKNOWN report_rs::source_graph::{GraphConfig}::from_vars +impact UNKNOWN report_rs::source_graph::{GraphConfig}::from_vars::{impl Fn<(&'_1 str,)> for report_rs::source_graph::{GraphConfig}::from_vars::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call +impact UNKNOWN report_rs::source_graph::{GraphConfig}::from_vars::{impl FnMut<(&'_1 str,)> for report_rs::source_graph::{GraphConfig}::from_vars::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::source_graph::{GraphConfig}::from_vars::{impl FnOnce<(&'_1 str,)> for report_rs::source_graph::{GraphConfig}::from_vars::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::source_graph::{GraphConfig}::lab_from_vars +impact UNKNOWN report_rs::surface_fixture::{report_rs::surface_fixture::Surface}::rail_html +impact UNKNOWN report_rs::surface_fixture::{report_rs::surface_fixture::Surface}::rail_html_addressed +impact UNKNOWN report_rs::surface_fixture::{report_rs::surface_fixture::Surface}::rail_html_addressed::{impl Fn<(&'_4 Tool, &'_5 str)> for report_rs::surface_fixture::{report_rs::surface_fixture::Surface}::rail_html_addressed::{closure}<'_0, '_1, '_2, '_3, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call +impact UNKNOWN report_rs::surface_fixture::{report_rs::surface_fixture::Surface}::rail_html_addressed::{impl FnMut<(&'_4 Tool, &'_5 str)> for report_rs::surface_fixture::{report_rs::surface_fixture::Surface}::rail_html_addressed::{closure}<'_0, '_1, '_2, '_3, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::surface_fixture::{report_rs::surface_fixture::Surface}::rail_html_addressed::{impl FnOnce<(&'_4 Tool, &'_5 str)> for report_rs::surface_fixture::{report_rs::surface_fixture::Surface}::rail_html_addressed::{closure}<'_0, '_1, '_2, '_3, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::surface_fixture::{report_rs::surface_fixture::Surface}::rail_html_with +impact UNKNOWN report_rs::surface_fixture::{report_rs::surface_fixture::Surface}::tools_html +impact UNKNOWN report_rs::view::project::{impl FnMut<(&'_1 report_rs::view::Column,)> for report_rs::view::project::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::view::project::{impl FnOnce<(&'_1 report_rs::view::Column,)> for report_rs::view::project::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::view::{Actor}::from_vars +impact UNKNOWN report_rs::workbook_delta::source::{DriveConfig}::from_vars +impact UNKNOWN report_rs::workbook_delta::source::{DriveConfig}::from_vars::{impl Fn<(&'_1 str,)> for report_rs::workbook_delta::source::{DriveConfig}::from_vars::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call +impact UNKNOWN report_rs::workbook_delta::source::{DriveConfig}::from_vars::{impl FnMut<(&'_1 str,)> for report_rs::workbook_delta::source::{DriveConfig}::from_vars::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_mut +impact UNKNOWN report_rs::workbook_delta::source::{DriveConfig}::from_vars::{impl FnOnce<(&'_1 str,)> for report_rs::workbook_delta::source::{DriveConfig}::from_vars::{closure}<'_0, T0>[TraitClause0, for<'_0_1> TraitClause1<'_>]}::call_once +impact UNKNOWN report_rs::xlsx::export +impact UNKNOWN report_rs::xlsx::workbook +GAP ExternalConsumersUnobserved { owner: "report_rs", observed_consumers: [] } +GAP TargetsNotExtracted { krate: "report_rs", missing: Targets { lib: false, tests: true, examples: true, benches: true } } +GAP RegionsExcluded { krate: "report_rs", regions: ["opaque:crate::app", "features-off:lance,iam,flow,oidc,projects,projects-pg"] } +GAP UnresolvedDispatch { dynamic_calls: 17 } +GAP HarvestIncomplete { krate: "report_rs", residuals: ResidualCounts([0, 0, 1, 0, 0]), partial: false, no_residuals_file: false } +GAP SourceFilesUnread { krate: "report_rs", files: ["src/app.rs", "src/app/plan_routes.rs", "src/flow_scratch.rs", "src/iam.rs", "src/login.rs", "src/main.rs", "src/project_plan/calendar.rs", "src/project_plan/engine.rs", "src/project_plan/mod.rs", "src/project_plan/pg.rs", "src/project_plan/projection.rs", "src/project_plan/store.rs", "src/project_plan/view.rs", "src/workbook_delta/dt64/p21_lane_socket_lab.rs"] } +closed_in_scope false diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/store-output/srcpull.report b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/srcpull.report new file mode 100644 index 000000000..145a5bdd9 --- /dev/null +++ b/.claude/probes/2026-11-11-codegraph-recon-2/store-output/srcpull.report @@ -0,0 +1,6 @@ +symbol FOUND 1718 report_rs::source::Source::pull +GAP TargetsNotExtracted { krate: "report_rs", missing: Targets { lib: false, tests: true, examples: true, benches: true } } +GAP RegionsExcluded { krate: "report_rs", regions: ["opaque:crate::app", "features-off:lance,iam,flow,oidc,projects,projects-pg"] } +GAP HarvestIncomplete { krate: "report_rs", residuals: ResidualCounts([0, 0, 1, 0, 0]), partial: false, no_residuals_file: false } +GAP SourceFilesUnread { krate: "report_rs", files: ["src/app.rs", "src/app/plan_routes.rs", "src/flow_scratch.rs", "src/iam.rs", "src/login.rs", "src/main.rs", "src/project_plan/calendar.rs", "src/project_plan/engine.rs", "src/project_plan/mod.rs", "src/project_plan/pg.rs", "src/project_plan/projection.rs", "src/project_plan/store.rs", "src/project_plan/view.rs", "src/workbook_delta/dt64/p21_lane_socket_lab.rs"] } +closed_in_scope false From 87686e8b715384014f53e3941070dbfd3efaee81 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 07:24:12 +0000 Subject: [PATCH 09/11] codegraph: impact_report covers the consumer frontier and missing-symbol harvest External callers of a public caller of the symbol are unobserved too, so the external-consumer gap fires when anything graded is public, not only the symbol. With the consumer set declared closed, every stored crate is checked for coverage, including one whose call sits in code it did not extract. A missing symbol now carries its crate's HarvestIncomplete. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- .../src/impact_report.rs | 50 +++++++--- .../tests/impact_coverage.rs | 91 +++++++++++++++++++ 2 files changed, 126 insertions(+), 15 deletions(-) diff --git a/crates/lance-graph-codegraph/src/impact_report.rs b/crates/lance-graph-codegraph/src/impact_report.rs index 85653cdd7..0709c735b 100644 --- a/crates/lance-graph-codegraph/src/impact_report.rs +++ b/crates/lance-graph-codegraph/src/impact_report.rs @@ -345,6 +345,7 @@ impl Codegraph { let owner = owner_of(symbol); if stored.contains(owner) { scope_gaps(owner, scope, &mut gaps); + self.harvest_gaps(owner, &mut gaps); freshness_gaps([&owner.to_owned()], scope, &mut gaps); } return Ok(ImpactReport { @@ -389,11 +390,24 @@ impl Codegraph { } } - if has(self.public(), g) && !scope.consumers_closed { - gaps.push(Gap::ExternalConsumersUnobserved { - owner: owner.clone(), - observed_consumers: consumers.into_iter().collect(), - }); + // The consumer frontier: the symbol, or anything that reaches it, is + // public. External callers of a public caller are affected too. + let frontier_public = has(self.public(), g) + || [&graded.confirmed, &graded.possible, &graded.unknown] + .iter() + .any(|m| m.iter().zip(self.public()).any(|(a, b)| a & b != 0)); + if frontier_public { + if scope.consumers_closed { + // Every stored crate may be a consumer, including one whose + // calls sit in code it did not extract and so have no + // position here; each one's coverage decides the answer. + involved.extend(stored.iter().map(|k| (*k).to_owned())); + } else { + gaps.push(Gap::ExternalConsumersUnobserved { + owner: owner.clone(), + observed_consumers: consumers.into_iter().collect(), + }); + } } for k in &involved { @@ -407,16 +421,7 @@ impl Codegraph { } for k in &involved { - let (residuals, no_file) = self.residuals_of_crate(k); - let partial = self.crate_status(k) == Some(crate::graph::RunStatus::Partial); - if residuals.total() > 0 || no_file || partial { - gaps.push(Gap::HarvestIncomplete { - krate: k.clone(), - residuals, - partial, - no_residuals_file: no_file, - }); - } + self.harvest_gaps(k, &mut gaps); } freshness_gaps(&involved, scope, &mut gaps); @@ -428,6 +433,21 @@ impl Codegraph { }) } + /// `HarvestIncomplete` for `k` when its harvest recorded residuals, did + /// not finish, or has no residuals file. + fn harvest_gaps(&self, k: &str, gaps: &mut Vec) { + let (residuals, no_file) = self.residuals_of_crate(k); + let partial = self.crate_status(k) == Some(crate::graph::RunStatus::Partial); + if residuals.total() > 0 || no_file || partial { + gaps.push(Gap::HarvestIncomplete { + krate: k.to_owned(), + residuals, + partial, + no_residuals_file: no_file, + }); + } + } + /// Whether a dynamic call may reach `g`: `g` is an impl or referenced. fn dynamic_may_reach(&self, g: Pos) -> bool { has(self.impl_subjects(), g) || has(self.referenced(), g) diff --git a/crates/lance-graph-codegraph/tests/impact_coverage.rs b/crates/lance-graph-codegraph/tests/impact_coverage.rs index 733b98ff8..3985590ad 100644 --- a/crates/lance-graph-codegraph/tests/impact_coverage.rs +++ b/crates/lance-graph-codegraph/tests/impact_coverage.rs @@ -566,3 +566,94 @@ fn unread_source_files_under_a_read_directory_are_a_gap() { r.gaps ); } + +/// Case 12: A private symbol reached by a public caller is affected by that +/// caller's external consumers, so the external-consumer gap fires for it +/// too. A private symbol no public function reaches stays closed. +#[test] +fn a_private_symbol_behind_a_public_caller_has_unobserved_consumers() { + let fx = Fixture::new("frontier", &[lib_crate()]); + let g = fx.open(); + let r = g.impact_report("lib::used", &fx.scope(&["lib"])).unwrap(); + assert!(has(&g, &r.graded.confirmed, "lib::entry")); + assert!( + matches!(r.gaps.as_slice(), [Gap::ExternalConsumersUnobserved { owner, .. }] if owner == "lib"), + "{:?}", + r.gaps + ); + assert!(!r.closed_in_scope()); + // Silence twins: nothing public reaches `lib::helper`; and a closed + // consumer set closes `lib::used`. + assert!(g + .impact_report("lib::helper", &fx.scope(&["lib"])) + .unwrap() + .closed_in_scope()); + let closed = Scope { + consumers_closed: true, + ..fx.scope(&["lib"]) + }; + assert!(g + .impact_report("lib::used", &closed) + .unwrap() + .closed_in_scope()); +} + +/// Case 13: With the consumer set declared closed, every stored crate is a +/// possible consumer. One whose call into the symbol sits in an excluded +/// region contributes no position, and its exclusion must still be reported. +#[test] +fn a_closed_consumer_set_checks_consumers_without_observed_edges() { + let app = Krate { + name: "app", + rows: &[("DEFINES", "app::main", "app::main")], + files: &[("app.rs", "fn main() {}\n")], + }; + let fx = Fixture::new("closed-consumers", &[lib_crate(), app]); + let g = fx.open(); + let base = Scope { + consumers_closed: true, + ..fx.scope(&["lib", "app"]) + }; + // Silence twin: every stored crate fully covered. + assert!(g + .impact_report("lib::entry", &base) + .unwrap() + .closed_in_scope()); + let excluded = Scope { + excluded: vec![("app".into(), vec!["feature plugins".into()])], + ..base + }; + let r = g.impact_report("lib::entry", &excluded).unwrap(); + assert_eq!( + r.gaps, + vec![Gap::RegionsExcluded { + krate: "app".into(), + regions: vec!["feature plugins".into()], + }] + ); +} + +/// Case 14: A missing symbol in a crate whose harvest is incomplete carries +/// `HarvestIncomplete`: the failed harvest may have dropped its definition. +#[test] +fn a_missing_symbol_carries_its_crate_harvest_gap() { + let fx = Fixture::new("missing-harvest", &[lib_crate()]); + let scope = fx.scope(&["lib"]); + assert!(fx + .open() + .impact_report("lib::nope", &scope) + .unwrap() + .gaps + .is_empty()); + std::fs::write( + fx.store.join("lib.residuals.tsv"), + format!("{RES_HEADER}BODY_NOT_STRUCTURED\tlib::nope\n"), + ) + .unwrap(); + let r = fx.open().impact_report("lib::nope", &scope).unwrap(); + assert!( + matches!(r.gaps.as_slice(), [Gap::HarvestIncomplete { krate, .. }] if krate == "lib"), + "{:?}", + r.gaps + ); +} From 1de065327d55431a23d081b9789828b0d379643d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 07:24:29 +0000 Subject: [PATCH 10/11] codegraph: regenerate .codegraph index Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- .codegraph/crates.tsv | 2 +- .codegraph/crates/lance-graph-codegraph.index.md | 2 +- .codegraph/freshness.tsv | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.codegraph/crates.tsv b/.codegraph/crates.tsv index 970282de2..bad656d91 100644 --- a/.codegraph/crates.tsv +++ b/.codegraph/crates.tsv @@ -36,7 +36,7 @@ lance-graph-benches crates/lance-graph-benches member 2f2fb296a08260fb lance-graph-callcenter crates/lance-graph-callcenter member 41a65d38ac70bc87 lance-graph-catalog crates/lance-graph-catalog member 9d0c34f70c28a465 lance-graph-codec-research crates/lance-graph-codec-research excluded 8b8afbd9a6d0f359 -lance-graph-codegraph crates/lance-graph-codegraph excluded 832b307522eeaa24 +lance-graph-codegraph crates/lance-graph-codegraph excluded be1efc44d1d322ae lance-graph-cognitive crates/lance-graph-cognitive excluded 93f956ac0d69ca66 lance-graph-consumer-conformance crates/lance-graph-consumer-conformance member 82e980465d770990 lance-graph-contract crates/lance-graph-contract member 6b4e13ff1d0afadb diff --git a/.codegraph/crates/lance-graph-codegraph.index.md b/.codegraph/crates/lance-graph-codegraph.index.md index c8d71c5c4..c5e83d782 100644 --- a/.codegraph/crates/lance-graph-codegraph.index.md +++ b/.codegraph/crates/lance-graph-codegraph.index.md @@ -3,7 +3,7 @@ crate: lance-graph-codegraph path: crates/lance-graph-codegraph workspace: excluded -digest: 832b307522eeaa24 +digest: be1efc44d1d322ae evidence legend: ../index.md#evidence-legend Generated; the code is the truth. See ../index.md. diff --git a/.codegraph/freshness.tsv b/.codegraph/freshness.tsv index 5fb3e2360..4c14fb2fc 100644 --- a/.codegraph/freshness.tsv +++ b/.codegraph/freshness.tsv @@ -36,7 +36,7 @@ lance-graph-benches 2f2fb296a08260fb Cargo.toml+src (1 files) lance-graph-callcenter 41a65d38ac70bc87 Cargo.toml+src (36 files) lance-graph-catalog 9d0c34f70c28a465 Cargo.toml+src (10 files) lance-graph-codec-research 8b8afbd9a6d0f359 Cargo.toml+src (11 files) -lance-graph-codegraph 832b307522eeaa24 Cargo.toml+src (10 files) +lance-graph-codegraph be1efc44d1d322ae Cargo.toml+src (10 files) lance-graph-cognitive 93f956ac0d69ca66 Cargo.toml+src (61 files) lance-graph-consumer-conformance 82e980465d770990 Cargo.toml+src (3 files) lance-graph-contract 6b4e13ff1d0afadb Cargo.toml+src (176 files) From e436b0c5e2621781289e4b10df5d75d55a332e64 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 07:24:51 +0000 Subject: [PATCH 11/11] probe: record the review fixes in REPORT.md and the board entry Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XAqKMLLhjfT6wad5BaeNBS --- .claude/board/entries/2026-11-11-codegraph-recon-2.md | 2 +- .claude/probes/2026-11-11-codegraph-recon-2/REPORT.md | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.claude/board/entries/2026-11-11-codegraph-recon-2.md b/.claude/board/entries/2026-11-11-codegraph-recon-2.md index acd5ab61b..05db99f13 100644 --- a/.claude/board/entries/2026-11-11-codegraph-recon-2.md +++ b/.claude/board/entries/2026-11-11-codegraph-recon-2.md @@ -7,7 +7,7 @@ external consumers unobserved, targets not extracted or undeclared, excluded regions, unresolved dispatch, incomplete harvest, stale or unrecorded files, and `.rs` files under a read directory that `files.tsv` does not list. Missing coverage never enters `Graded.unknown`. A missing symbol carries -its crate's gaps. 11 tests; every guard disable-verified red. +its crate's gaps. 14 tests; every guard disable-verified red. report-rs `81705d9` through Charon (lib, default features, `crate::app` opaque): CRATE `COMPLETE`, yet 14 of 59 `src/` files unread (`iam.rs`, `main.rs`, `project_plan/*`, …). The store recovers the diff --git a/.claude/probes/2026-11-11-codegraph-recon-2/REPORT.md b/.claude/probes/2026-11-11-codegraph-recon-2/REPORT.md index fa1adebe1..e6376d14b 100644 --- a/.claude/probes/2026-11-11-codegraph-recon-2/REPORT.md +++ b/.claude/probes/2026-11-11-codegraph-recon-2/REPORT.md @@ -19,7 +19,7 @@ store sees one build configuration and one target. | gap | source of the fact | |---|---| -| `ExternalConsumersUnobserved` | `PUBLIC` row, and the consumer set is not declared closed | +| `ExternalConsumersUnobserved` | the symbol or anything that reaches it is `PUBLIC`, and the consumer set is not declared closed; when it is declared closed, every stored crate's coverage is checked | | `TargetsNotExtracted` / `TargetsUndeclared` | declared per crate (the store does not record targets) | | `RegionsExcluded` | declared: opaque modules, features left off | | `UnresolvedDispatch` | `UNRESOLVED_CALL` rows that may reach the symbol | @@ -32,12 +32,14 @@ is a place it may still be defined. `closed_in_scope()` is true only for a found gap, and it claims nothing about code outside the scope. `Coverage::no_known_gap()` alone is not treated as closure: test 2 asserts it is true while the report is not closed. -`tests/impact_coverage.rs`, 11 tests, one per case in the brief plus three found while running -Gate B (excluded regions, target gaps of a missing symbol, unread files). Every guard was disabled +`tests/impact_coverage.rs`, 14 tests: one per case in the brief, three found while running +Gate B (excluded regions, target gaps of a missing symbol, unread files), and three from review +(a private symbol behind a public caller, a closed consumer set checks every stored crate, a +missing symbol's harvest gap). Every guard was disabled and its test went red: external consumers, missing targets, undeclared targets, dispatch fire, dispatch silence, stale source, owner stored, observed consumers, closed symbol, harvest, missing-symbol scope gaps, excluded regions, unread files (fire and silence), missing-symbol file -gaps. +gaps, public frontier, closed consumer set, missing-symbol harvest. ## 2. The report-rs store (Gate B)