crates/nornir-testmatrix/src/citations.rs
//! **A cited guard must exist** — the phantom-citation audit.
//!
//! Comments justify code by naming the test that covers it: *"(Integration tests
//! against a live FalkorDB instance live in the integration test file.)"*. That
//! sentence is load-bearing — a reader who sees it stops looking for coverage.
//! When the named file does not exist the comment is a **phantom guard**, and a
//! pointer to an imaginary guard is *indistinguishable from a real one*. It reads
//! as green.
//!
//! This is the sibling of [`crate::gatedtests`]: that one catches tests that can
//! never RUN, this one catches tests that never EXISTED.
//!
//! ## Found in the wild
//!
//! * knut's `graphar-falkordb/src/tests.rs` cited an integration-test file that has
//! never existed in that repo — directly above a `#[tokio::test]` whose name promised query
//! verification and whose body asserted only that its own fixture had three rows.
//! Under both sat a row-render loop written out twice, tested on one copy only:
//! dropping `_gar_id` from the untested copy left all 42 tests green while the
//! loader silently stopped emitting the property every edge insert matches on.
//! * facett's `saga.proto` header cited a `test_saga_wire` python file as proof
//! the wire subset could not drift. No file of that name has ever existed in any
//! repo. (Named without its path on purpose — this audit reads its own source,
//! and a post-mortem is indistinguishable from a claim.)
//!
//! ## Why it is quiet enough to keep
//!
//! A guard that cries wolf gets switched off, so this one refuses to guess:
//!
//! * **Comments only.** `classify(…, "tests/foo.rs")` passes a *fixture name* to
//! a parser; it does not claim a file exists. String literals are stripped.
//! (Written with a placeholder stem on purpose — this audit runs over its own
//! source, and it is right to.)
//! * **Siblings resolve.** A comment in edda naming `tests/viz_surface.rs` means
//! nornir's file. Pass the sibling checkouts and cross-repo citations resolve
//! instead of being reported as missing.
//! * **Placeholders are not citations.** `<c>/tests/foo.rs → "<c>::tests::foo"`
//! illustrates a path→module mapping. Stems in [`PLACEHOLDER_STEMS`], and any
//! stem of one or two characters (`src/a.rs`, `src/a/b.rs`), are skipped.
//! * **`.nornir/` is not scanned.** That is the design/planning dir; a proposal
//! naming the file it intends to add is a plan, not a false coverage claim.
//! * **A visible escape hatch.** `.nornir/citation-allow.txt` (one path per line,
//! `#` comments) suppresses the rest — enumerable, reviewable, and burnable,
//! the same shape as autonom's allowlist.
//!
//! Measured on the fleet before those three rules existed, ~4 of every 5 hits were
//! illustrative or cross-repo rather than defects. The rules are the difference
//! between a finding and a nuisance.
//!
//! ```no_run
//! let rep = nornir_testmatrix::audit_citations(std::path::Path::new("."), &[]);
//! assert!(rep.phantoms.is_empty(), "{}", rep.summary());
//! ```
use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
use std::process::Command;
/// The allowlist a repo may keep to suppress a citation this audit cannot resolve.
pub const ALLOW_FILE: &str = ".nornir/citation-allow.txt";
/// File stems that are universally illustrative, never a real coverage claim.
pub const PLACEHOLDER_STEMS: &[&str] =
&["foo", "bar", "baz", "qux", "t", "x", "y", "example", "my_test", "some_test"];
/// First path segments a citation must start with to be considered repo-relative.
/// Anything else is a URL path or another project's layout — not ours to guess at.
const OURS: &[&str] = &["tests", "src", "crates", "xtask", "benches", "py", "server"];
/// Extensions a comment can cite as coverage.
const CITED_EXT: &[&str] = &["rs", "py", "js", "ts", "go", "sh"];
/// One comment that names a file which does not exist.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PhantomCitation {
/// Repo-relative path of the file holding the comment.
pub file: String,
/// 1-based line of the citation.
pub line: usize,
/// The cited path, exactly as written.
pub cited: String,
}
/// The audit's verdict for one repo.
#[derive(Debug, Clone, Default)]
pub struct CitationReport {
/// Citations that resolve to nothing, here or in any sibling passed in.
pub phantoms: Vec<PhantomCitation>,
/// How many citations were examined (a zero here means the scan is broken,
/// not that the repo is clean — [`CitationReport::is_trustworthy`]).
pub checked: usize,
/// Entries read from [`ALLOW_FILE`].
pub allowed: usize,
}
impl CitationReport {
/// A scan that examined nothing proves nothing.
pub fn is_trustworthy(&self) -> bool {
self.checked > 0
}
/// A one-block, paste-into-a-failure summary.
pub fn summary(&self) -> String {
if self.phantoms.is_empty() {
return format!(
"{} citation(s) checked, {} allowlisted, 0 phantom",
self.checked, self.allowed
);
}
let mut s = String::from(
"PHANTOM GUARD CITATIONS — a comment names a test file that does not exist.\n\
A pointer to an imaginary guard reads exactly like a real one; a reader who\n\
sees it stops looking for coverage. Fix the path, or delete the claim.\n\n",
);
for p in &self.phantoms {
s.push_str(&format!(" {}:{} cites {} — NO SUCH FILE\n", p.file, p.line, p.cited));
}
s.push_str(&format!(
"\n({} checked, {} allowlisted via {})",
self.checked, self.allowed, ALLOW_FILE
));
s
}
}
fn tracked(root: &Path) -> Vec<String> {
let Ok(out) = Command::new("git").arg("-C").arg(root).arg("ls-files").output() else {
return Vec::new();
};
if !out.status.success() {
return Vec::new();
}
String::from_utf8_lossy(&out.stdout).lines().map(str::to_string).collect()
}
/// Everything that is a comment in Rust source, with string literals removed so a
/// fixture NAME passed as an argument is never mistaken for a claim of coverage.
/// Newlines are preserved so line numbers survive.
fn rust_comments(src: &str) -> String {
let b = src.as_bytes();
let mut out = String::with_capacity(src.len());
let (mut i, mut in_str, mut in_raw, mut esc) = (0usize, false, false, false);
while i < b.len() {
let c = b[i] as char;
if in_str {
if in_raw {
if c == '"' {
in_str = false;
in_raw = false;
}
} else if esc {
esc = false;
} else if c == '\\' {
esc = true;
} else if c == '"' {
in_str = false;
}
if c == '\n' {
out.push('\n');
}
i += 1;
continue;
}
if c == 'r' && i + 1 < b.len() && (b[i + 1] == b'"' || b[i + 1] == b'#') {
let mut j = i + 1;
while j < b.len() && b[j] == b'#' {
j += 1;
}
if j < b.len() && b[j] == b'"' {
in_str = true;
in_raw = true;
i = j + 1;
continue;
}
}
if c == '"' {
in_str = true;
i += 1;
continue;
}
if c == '/' && i + 1 < b.len() && b[i + 1] == b'/' {
let end = src[i..].find('\n').map(|n| i + n).unwrap_or(b.len());
out.push_str(&src[i..end]);
i = end;
continue;
}
if c == '/' && i + 1 < b.len() && b[i + 1] == b'*' {
let end = src[i + 2..].find("*/").map(|n| i + 2 + n + 2).unwrap_or(b.len());
out.push_str(&src[i..end]);
i = end;
continue;
}
if c == '\n' {
out.push('\n');
}
i += 1;
}
out
}
/// Pull `a/b/c.rs`-shaped tokens, with their 1-based line numbers, out of prose.
fn citations(text: &str) -> Vec<(usize, String)> {
let mut found = Vec::new();
for (idx, line) in text.lines().enumerate() {
let mut seen = BTreeSet::new();
for raw in line.split(|c: char| !(c.is_alphanumeric() || matches!(c, '_' | '-' | '.' | '/')))
{
let tok = raw.trim_matches(|c| c == '.' || c == '/');
if !tok.contains('/') || tok.contains("..") {
continue;
}
// The stem half is deliberately dropped: the placeholder rule below
// is applied per SEGMENT, so there is nothing left for it to do.
let Some((_, ext)) = tok.rsplit_once('.') else { continue };
if !CITED_EXT.contains(&ext) {
continue;
}
// The placeholder rule applies to EVERY SEGMENT, not only the stem.
// It used to read the last one alone, and that let two whole classes
// of illustration through — measured on edda 2026-08-27:
//
// src/a/index.ts, src/b/index.ts git's own rename-detection example
// paths, in a doc comment ABOUT path
// hashing (gunnar-delta/name_hash.rs)
// src/foo/mod.rs a path→module mapping illustration
// (nornir-docgen/apidoc.rs)
//
// In each the stem (`index`, `mod`) is perfectly ordinary and the
// illustration lives in a DIRECTORY segment. A single-letter or
// universally-placeholder segment anywhere in a path is the same
// signal wherever it sits, so the test is applied per segment.
let illustrative = |seg: &str| {
let stem = seg.rsplit_once('.').map(|(s, _)| s).unwrap_or(seg);
PLACEHOLDER_STEMS.contains(&stem) || stem.chars().count() <= 2
};
if tok.split('/').any(illustrative) {
continue;
}
if !OURS.contains(&tok.split('/').next().unwrap_or("")) {
continue;
}
if seen.insert(tok.to_string()) {
found.push((idx + 1, tok.to_string()));
}
}
}
found
}
/// The crate directory a file belongs to (nearest ancestor holding a Cargo.toml).
fn crate_dir_of(root: &Path, file: &str) -> Option<String> {
let mut cur = Path::new(file).parent()?;
loop {
if root.join(cur).join("Cargo.toml").is_file() {
let s = cur.to_string_lossy().to_string();
return Some(if s.is_empty() { s } else { format!("{s}/") });
}
cur = cur.parent()?;
}
}
fn resolves(cited: &str, citing: &str, root: &Path, own: &BTreeSet<String>, sib: &BTreeSet<String>) -> bool {
if own.contains(cited) {
return true;
}
if let Some(dir) = crate_dir_of(root, citing) {
if own.contains(&format!("{dir}{cited}")) {
return true;
}
}
// In a SIBLING checkout the citation is that repo's root-relative path, so an
// exact hit counts as well as a suffix hit. (Missing this made every legitimate
// cross-repo pointer look like a phantom.)
if sib.contains(cited) {
return true;
}
let suffix = format!("/{cited}");
own.iter().any(|f| f.ends_with(&suffix)) || sib.iter().any(|f| f.ends_with(&suffix))
}
/// Audit one repo's comments for citations of files that do not exist.
///
/// `siblings` are other checkouts whose files may legitimately be cited (a comment
/// in edda naming `tests/viz_surface.rs` means nornir's). Pass `&[]` to require
/// every citation to resolve inside `repo_root` alone.
pub fn audit_citations(repo_root: &Path, siblings: &[PathBuf]) -> CitationReport {
let own_files = tracked(repo_root);
let own: BTreeSet<String> = own_files.iter().cloned().collect();
let mut sib: BTreeSet<String> = BTreeSet::new();
for s in siblings {
sib.extend(tracked(s));
}
let allow: BTreeSet<String> = std::fs::read_to_string(repo_root.join(ALLOW_FILE))
.unwrap_or_default()
.lines()
.map(|l| l.split('#').next().unwrap_or("").trim().to_string())
.filter(|l| !l.is_empty())
.collect();
let mut rep = CitationReport { allowed: allow.len(), ..Default::default() };
for f in &own_files {
if f.starts_with("vendor/") || f.contains("/vendor/") {
continue;
}
// The design/planning dir: a proposal naming the file it intends to add is
// a plan, not a claim that coverage already exists.
if f.starts_with(".nornir/") || f.contains("/.nornir/") {
continue;
}
// QUARANTINE. `parked-gix*` trees are the owner's standing quarantine
// rule: never read from, cite from, or build from them unless he points at
// one himself. A quarantined tree therefore makes no claims about this
// repo, and auditing its claims is auditing something that was set aside
// precisely so nobody would rely on it. Measured 2026-08-27: 4 of the 19
// phantoms this audit reported on edda came from
// `crates/storage-git-gix/parked-gix{,2}/`, which is 4 rows of noise
// in a report whose whole value is that every row is actionable.
if f.split('/').any(|seg| seg.starts_with("parked-gix")) {
continue;
}
let is_rs = f.ends_with(".rs");
let is_prose = f.ends_with(".md") || f.ends_with(".proto");
if !is_rs && !is_prose {
continue;
}
let Ok(src) = std::fs::read_to_string(repo_root.join(f)) else { continue };
let text = if is_rs { rust_comments(&src) } else { src };
for (line, cited) in citations(&text) {
if allow.contains(&cited) {
continue;
}
rep.checked += 1;
if !resolves(&cited, f, repo_root, &own, &sib) {
rep.phantoms.push(PhantomCitation { file: f.clone(), line, cited });
}
}
}
rep
}
/// The repository's **main** working tree, which for a linked `git worktree` is
/// somewhere else entirely.
///
/// `--git-common-dir` is the one that points at the shared `.git` of the main
/// checkout; plain `--git-dir` would answer `<main>/.git/worktrees/<name>` and
/// lead back to the worktree. A bare repo has no working tree and gets `None`.
fn main_worktree_of(repo_root: &Path) -> Option<PathBuf> {
let out = Command::new("git")
.arg("-C")
.arg(repo_root)
.args(["rev-parse", "--path-format=absolute", "--git-common-dir"])
.output()
.ok()?;
if !out.status.success() {
return None;
}
let common = PathBuf::from(String::from_utf8_lossy(&out.stdout).trim());
(common.file_name()? == ".git").then(|| common.parent())?.map(Path::to_path_buf)
}
/// Sibling checkouts of `repo_root` — every directory beside the repository's
/// **main working tree** that is itself a git repo. The nordisk layout is one
/// flat parent dir of sibling repos.
///
/// # Why the main working tree and not `repo_root`'s own parent
///
/// MEASURED on oden 2026-09-12. This read `repo_root.parent()`, so the audit's
/// verdict was a property of **where the checkout sits on disk** rather than of
/// the repository. The same commit of edda gave three different answers:
///
/// | root | siblings found | phantoms |
/// |---|---|---|
/// | `~/git/edda` | 73 | 0 |
/// | `~/scratch/wt-e-gc` (a `git worktree` of it) | 32 | 1 |
/// | a CI clone with nothing beside it | 0 | 44 |
///
/// A citation in `crates/jera/src/jobs.rs` naming dwarves' `src/brokkr/engine.rs`
/// is a legitimate cross-repo pointer; dwarves is beside `~/git/edda` and is not
/// beside a worktree in `~/scratch`, so the guard went red on the worktree and
/// green on main for source that is byte-identical. A guard that flips on
/// `git worktree add` teaches people to ignore it.
///
/// A linked worktree IS the repository, so it gets the repository's neighbours.
/// This changes no verdict for a normal checkout — `--git-common-dir` there is
/// its own `.git` — and it cannot widen a CI clone, which still has none.
pub fn sibling_checkouts(repo_root: &Path) -> Vec<PathBuf> {
let base = main_worktree_of(repo_root).unwrap_or_else(|| repo_root.to_path_buf());
let Some(parent) = base.parent() else { return Vec::new() };
let Ok(rd) = std::fs::read_dir(parent) else { return Vec::new() };
// Exclude BOTH the root we were handed and the main checkout it belongs to:
// a worktree's own repo is not a sibling of itself, and letting it in would
// resolve every citation against the very files being audited.
let me = repo_root.canonicalize().ok();
let main = base.canonicalize().ok();
rd.filter_map(|e| e.ok())
.map(|e| e.path())
.filter(|p| {
let c = p.canonicalize().ok();
p.is_dir() && p.join(".git").exists() && c != me && c != main
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
/// Run `git` in `dir` with an identity supplied on the command line — a
/// container or build agent has no `~/.gitconfig`, and `git commit` there
/// fails with "Please tell me who you are" rather than skipping.
fn git(dir: &Path, args: &[&str]) {
let out = Command::new("git")
.arg("-C")
.arg(dir)
.args(["-c", "user.name=t", "-c", "user.email=t@t", "-c", "commit.gpgsign=false"])
.args(args)
.output()
.expect("spawn git");
assert!(
out.status.success(),
"git {args:?} in {} failed: {}",
dir.display(),
String::from_utf8_lossy(&out.stderr)
);
}
fn seed_repo(dir: &Path, files: &[(&str, &str)]) {
std::fs::create_dir_all(dir).expect("mkdir");
git(dir, &["init", "-q", "-b", "main"]);
for (rel, body) in files {
let p = dir.join(rel);
std::fs::create_dir_all(p.parent().expect("parent")).expect("mkdir");
std::fs::write(&p, body).expect("write");
}
git(dir, &["add", "-A"]);
git(dir, &["commit", "-q", "-m", "seed"]);
}
/// THE RED PROOF for [`sibling_checkouts`]: a linked `git worktree` must get
/// the SAME verdict as the checkout it belongs to, however far away it sits.
///
/// The fixture is the exact shape that was flipping on oden: a repo whose
/// comment cites a file living in a sibling repo, and a worktree of that
/// repo created in a directory with no siblings at all. Before the fix the
/// worktree reported the citation as a phantom and the main checkout
/// reported nothing — same commit, same bytes, two answers.
#[test]
fn a_linked_worktree_sees_the_repositorys_siblings_not_its_own_neighbours() {
let td = tempfile::tempdir().expect("tempdir");
let fleet = td.path().join("fleet");
let elsewhere = td.path().join("elsewhere");
std::fs::create_dir_all(&elsewhere).expect("mkdir elsewhere");
// The neighbour that owns the cited file.
seed_repo(&fleet.join("neighbour"), &[("tests/cross_repo_proof.rs", "// nothing\n")]);
// The repo under audit, citing it.
let main = fleet.join("under-audit");
seed_repo(
&main,
&[("src/lib.rs", "//! covered by tests/cross_repo_proof.rs next door\n")],
);
// A worktree of the SAME repo, parked where it has no neighbours.
let wt = elsewhere.join("lane");
git(&main, &["worktree", "add", "-q", "-b", "lane", wt.to_str().expect("utf-8")]);
let from_main = audit_citations(&main, &sibling_checkouts(&main));
let from_worktree = audit_citations(&wt, &sibling_checkouts(&wt));
assert!(
from_main.is_trustworthy() && from_worktree.is_trustworthy(),
"both scans must examine something: main {} / worktree {}",
from_main.checked,
from_worktree.checked
);
assert!(
from_main.phantoms.is_empty(),
"the citation resolves in the neighbour, so the main checkout must be clean: {}",
from_main.summary()
);
assert_eq!(
from_worktree.phantoms, from_main.phantoms,
"a `git worktree` of the same commit reported a different verdict: {}\n\
The audit must be a property of the repository, not of the directory it was \
checked out beside.",
from_worktree.summary()
);
}
/// NON-VACUITY PROBE for the test above: with the neighbour genuinely gone,
/// the citation IS a phantom from both roots. Without this, the equality
/// assertion would pass just as happily against a `sibling_checkouts` that
/// returned everything, or an audit that reported nothing.
#[test]
fn the_cross_repo_citation_is_a_phantom_when_the_neighbour_does_not_exist() {
let td = tempfile::tempdir().expect("tempdir");
let main = td.path().join("fleet").join("under-audit");
seed_repo(
&main,
&[("src/lib.rs", "//! covered by tests/cross_repo_proof.rs next door\n")],
);
let rep = audit_citations(&main, &sibling_checkouts(&main));
assert_eq!(
rep.phantoms.len(),
1,
"with no neighbour the citation has no referent anywhere: {}",
rep.summary()
);
assert_eq!(rep.phantoms[0].cited, "tests/cross_repo_proof.rs");
}
/// A worktree's own repository is not one of its siblings.
///
/// It sits right beside the neighbours, so the widened search would sweep it
/// in — and then every citation would "resolve" against the very files being
/// audited, which is the blindest possible green.
#[test]
fn the_main_checkout_is_not_its_own_worktrees_sibling() {
let td = tempfile::tempdir().expect("tempdir");
let fleet = td.path().join("fleet");
let elsewhere = td.path().join("elsewhere");
std::fs::create_dir_all(&elsewhere).expect("mkdir elsewhere");
seed_repo(&fleet.join("neighbour"), &[("tests/cross_repo_proof.rs", "// nothing\n")]);
let main = fleet.join("under-audit");
seed_repo(&main, &[("src/lib.rs", "//! nothing cited here\n")]);
let wt = elsewhere.join("lane");
git(&main, &["worktree", "add", "-q", "-b", "lane", wt.to_str().expect("utf-8")]);
let sibs = sibling_checkouts(&wt);
let canon: Vec<PathBuf> = sibs.iter().filter_map(|p| p.canonicalize().ok()).collect();
assert!(
canon.contains(&fleet.join("neighbour").canonicalize().expect("canon")),
"the neighbour must be found: {sibs:?}"
);
assert!(
!canon.contains(&main.canonicalize().expect("canon")),
"the worktree's OWN repository was returned as a sibling: {sibs:?}"
);
}
#[test]
fn string_literals_are_not_citations() {
let src = "let f = classify(src, \"tests/dark.rs\");\n// see tests/real.rs\n";
let c = rust_comments(src);
assert!(!c.contains("tests/dark.rs"), "a fixture name in a literal is not a claim");
assert!(c.contains("tests/real.rs"));
}
#[test]
fn line_numbers_survive_literal_stripping() {
let src = "let a = \"tests/x.rs\";\n\n// covered by tests/three.rs\n";
let hits = citations(&rust_comments(src));
assert_eq!(hits, vec![(3, "tests/three.rs".to_string())]);
}
#[test]
fn placeholders_are_not_citations() {
let hits = citations("// `<c>/tests/foo.rs` -> `<c>::tests::foo`; also tests/t.rs\n");
assert!(hits.is_empty(), "illustrative stems must not be reported: {hits:?}");
}
#[test]
fn another_projects_layout_is_not_ours_to_guess() {
let hits = citations("// mirrors facett-demo/tests/robot_demo.rs\n");
assert!(hits.is_empty(), "cross-project paths are skipped, not guessed: {hits:?}");
}
#[test]
fn a_real_citation_is_found_with_its_line() {
let hits = citations("//! header\n//! see tests/support/mcp_harness.rs for the template\n");
assert_eq!(hits, vec![(2, "tests/support/mcp_harness.rs".to_string())]);
}
#[test]
fn an_empty_scan_is_not_trustworthy() {
let rep = CitationReport::default();
assert!(!rep.is_trustworthy(), "zero checked means broken, not clean");
}
}