traits/tests/manifest_metadata_guard.rs
//! **holger's crate-discovery guard** — the `description` of a publishable holger crate
//! must say what THAT crate does.
//!
//! ## Why this file exists
//!
//! On 2026-08-01 a recount found **17 of holger's crates sharing one string**:
//!
//! ```text
//! description = "Holger guards your artifacts at rest. May Allfather Odin watch over every bit."
//! ```
//!
//! …including every single `znippy-<ecosystem>` backend. It is a nice line, and as
//! crate-discovery metadata it carries **zero bits**: the whole surface a person searching
//! crates.io (or `cargo search`, or a `cargo metadata` dump, or the crates.io sidebar) sees
//! could not tell them which of the seventeen serves PyPI, which serves APT, or that
//! `holger-rust-file-repository` is the *writable* Cargo one. holger's own `CLAUDE.md`
//! warns that "THE CRATE NAME IS OFTEN NOT THE NAME YOU SEARCHED FOR" — which makes the
//! description the only place left to say it, and it said nothing.
//!
//! That cost real time twice (SK330 / SK332): ~2 h hunting for holger's PEP 503
//! implementation, which very nearly ended in a duplicate of it being written.
//!
//! ## What this guard asserts
//!
//! For every **publishable** crate in the workspace (`publish = false` crates are internal
//! and exempt):
//!
//! 1. it HAS a `description`;
//! 2. that description is not the retired boilerplate;
//! 3. no two crates share a description — a shared string is by definition not describing
//! either crate; and
//! 4. it is long enough to be a sentence about a specific thing.
//!
//! ## What this guard does NOT prove
//!
//! That a description is TRUE, or that it names the right ecosystem. Prose cannot be
//! checked by string length. The ecosystem-naming half is asserted separately against
//! `ArtifactFormat::home()` — the format→crate map — because that has a machine-readable
//! source of truth and prose does not.
//!
//! ## Seeing it red
//!
//! Put the boilerplate line back in any one manifest and this fails, naming that manifest
//! and quoting the string.
use std::path::{Path, PathBuf};
/// The exact string 17 crates shared. Kept here so it can never quietly return.
const RETIRED_BOILERPLATE: &str =
"Holger guards your artifacts at rest. May Allfather Odin watch over every bit.";
/// A description shorter than this cannot distinguish one backend from sixteen siblings.
const MIN_DESCRIPTION_CHARS: usize = 40;
fn repo_root() -> PathBuf {
// traits → <repo root>
Path::new(env!("CARGO_MANIFEST_DIR"))
.ancestors()
.nth(1)
.unwrap()
.to_path_buf()
}
/// Every `Cargo.toml` in the workspace tree, `target/` pruned.
fn manifests(root: &Path) -> Vec<PathBuf> {
let mut out = Vec::new();
let mut stack = vec![root.to_path_buf()];
while let Some(dir) = stack.pop() {
let Ok(rd) = std::fs::read_dir(&dir) else {
continue;
};
for e in rd.flatten() {
let p = e.path();
let name = e.file_name().to_string_lossy().to_string();
if p.is_dir() {
if name != "target" && !name.starts_with('.') {
stack.push(p);
}
} else if name == "Cargo.toml" {
out.push(p);
}
}
}
out.sort();
out
}
/// The value of a top-level `key = "…"` in the `[package]` table.
///
/// A hand-rolled scan rather than a `toml` dep: xtask has no toml crate and this needs to
/// read `[package]` only. It stops at the next table header so a `description` under some
/// other table can never be mistaken for the package's.
fn package_str(text: &str, key: &str) -> Option<String> {
let mut in_package = false;
for line in text.lines() {
let t = line.trim();
if t.starts_with('[') {
in_package = t == "[package]";
continue;
}
if !in_package {
continue;
}
if let Some(rest) = t.strip_prefix(key) {
let rest = rest.trim_start();
if let Some(v) = rest.strip_prefix('=') {
return Some(v.trim().trim_matches('"').to_string());
}
}
}
None
}
/// Whether the manifest declares `publish = false` (internal crate, exempt).
fn is_unpublished(text: &str) -> bool {
package_str(text, "publish").as_deref() == Some("false")
}
#[test]
fn every_publishable_crate_describes_itself() {
let root = repo_root();
let all = manifests(&root);
// Never let a broken walk pass for a clean result: an empty list would make every
// assertion below trivially true.
assert!(
all.len() > 20,
"the guard found only {} Cargo.toml files under {} — it is reading the wrong tree",
all.len(),
root.display()
);
let mut problems: Vec<String> = Vec::new();
// description → the manifests carrying it, so a duplicate names BOTH offenders.
let mut by_desc: std::collections::BTreeMap<String, Vec<String>> = Default::default();
let mut checked = 0usize;
for m in &all {
let Ok(text) = std::fs::read_to_string(m) else {
continue;
};
// A virtual manifest (the workspace root) has no `[package]`.
let Some(name) = package_str(&text, "name") else {
continue;
};
if is_unpublished(&text) {
continue;
}
checked += 1;
let rel = m.strip_prefix(&root).unwrap_or(m).display().to_string();
let Some(desc) = package_str(&text, "description") else {
problems.push(format!(
"{rel} ({name}) declares NO description — the crate-discovery surface says \
nothing about it"
));
continue;
};
if desc == RETIRED_BOILERPLATE {
problems.push(format!(
"{rel} ({name}) carries the RETIRED boilerplate description {desc:?} — 17 \
crates shared it and it identified none of them. Say what THIS crate serves."
));
continue;
}
if desc.chars().count() < MIN_DESCRIPTION_CHARS {
problems.push(format!(
"{rel} ({name}) description is {} chars, under the {MIN_DESCRIPTION_CHARS} \
floor: {desc:?}",
desc.chars().count()
));
}
by_desc
.entry(desc)
.or_default()
.push(format!("{name} ({rel})"));
}
assert!(
checked > 15,
"the guard only inspected {checked} publishable crates — holger has more than that, \
so the `[package]`/publish parse must have broken"
);
for (desc, crates) in &by_desc {
if crates.len() > 1 {
problems.push(format!(
"{} crates SHARE one description — a shared string describes none of them:\n \
{desc:?}\n · {}",
crates.len(),
crates.join("\n · ")
));
}
}
assert!(
problems.is_empty(),
"{} crate-description problem(s) across {checked} publishable crates:\n · {}",
problems.len(),
problems.join("\n · ")
);
}
// ─────────────────────────────────────────────────────────────────────────────────
// SK332 / D1 — the capability a search must be able to FIND
// ─────────────────────────────────────────────────────────────────────────────────
/// Aliases that exist only to catch a MISSPELLING, not to name the capability. They are
/// deliberately not required as keywords: `snippy` is a typo-catcher for `znippy`, and
/// spending one of crates.io's five keyword slots on a typo helps nobody.
const TYPO_ALIASES: &[&str] = &["snippy"];
/// Aliases that cannot legally be a crates.io keyword (keywords are ASCII
/// alphanumeric + `_ - +` and must start alphanumeric — `crates.io` has a dot).
/// Recorded here rather than silently skipped, so the exemption is a decision on
/// the record.
const UNKEYWORDABLE_ALIASES: &[&str] = &["crates.io"];
/// The `keywords = [...]` array of a manifest, lowercased.
fn package_keywords(text: &str) -> Vec<String> {
let mut in_package = false;
for line in text.lines() {
let t = line.trim();
if t.starts_with('[') {
in_package = t == "[package]";
continue;
}
if !in_package {
continue;
}
if let Some(rest) = t.strip_prefix("keywords") {
if let Some(v) = rest.trim_start().strip_prefix('=') {
return v
.trim()
.trim_start_matches('[')
.trim_end_matches(']')
.split(',')
.map(|s| s.trim().trim_matches('"').to_lowercase())
.filter(|s| !s.is_empty())
.collect();
}
}
}
Vec::new()
}
/// **The SK332 guard** — every ecosystem holger serves is findable by the names people
/// actually use.
///
/// ## The defect this closes
///
/// holger's PyPI capability answers to a stack of unrelated names, and none of them
/// matched what was on the crate:
///
/// | the name | where it is used |
/// |---|---|
/// | `PyPI` | the docs, the UI, and what a human calls it |
/// | `pip` | the `ron_repo_type` an operator writes in RON — the CONFIG key |
/// | `ArtifactFormat::Pip` / `PipRepoZnippy` | the code |
/// | `znippy-python` / `holger-znippy-python-repository` | the directory and the package |
///
/// Four names, one capability, and (measured 2026-08-01) **zero** `pypi` or `pep503`
/// keywords anywhere in the workspace — all 17 publishable crates carried the same
/// `["znippy", "artifacts", "blake3", "cli", "airgap"]`. So a search for the ecosystem
/// found nothing, which cost ~2 h and nearly produced a SECOND PEP 503 implementation
/// alongside the one that already exists.
///
/// ## What it asserts
///
/// Read off `ArtifactFormat::home()` — the format→crate map — so there is ONE list of
/// formats and this checks against it rather than keeping a copy:
///
/// 1. the `config_key` (the string an operator types) IS a keyword on that format's
/// crate; and
/// 2. **every** real ALIAS is too.
///
/// Rule 2 is deliberately EVERY alias, not "at least one". The first draft of this guard
/// asked for at least one, and it was HOLLOW: dropping `"pypi"` from znippy-python still
/// passed, because the sibling alias `"python"` satisfied the check — so the guard was
/// blind to the exact defect it was written for. Requiring every alias is also feasible
/// rather than aspirational: the widest format (`maven3`, with `maven`/`maven2`/`java`)
/// needs 4 of crates.io's 5 keyword slots, so no format is forced to choose.
///
/// Both the primary crate and a format's `also` peer (the file-backed twin) are checked.
///
/// ## Seeing it red
///
/// Drop `"pypi"` from `server/repository/znippy-python/Cargo.toml` and this fails naming
/// that crate, the format, and the aliases it no longer answers to.
#[test]
fn every_format_is_findable_by_the_names_it_answers_to() {
let root = repo_root();
let mut problems: Vec<String> = Vec::new();
let mut checked = 0usize;
for format in holger_traits::ALL_ARTIFACT_FORMATS {
let home = format.home();
// `Raw` has no repository crate of its own (the backend is server/lib/src/raw.rs).
if home.crate_dir.is_empty() {
continue;
}
let mut targets = vec![(home.crate_dir, home.package)];
if let Some(also) = home.also {
targets.push(also);
}
for (dir, package) in targets {
let rel = format!("server/repository/{dir}/Cargo.toml");
let path = root.join(&rel);
let Ok(text) = std::fs::read_to_string(&path) else {
problems.push(format!(
"{:?}'s home names {rel}, which does not exist",
home.format
));
continue;
};
checked += 1;
let kws = package_keywords(&text);
if kws.is_empty() {
problems.push(format!("{rel} ({package}) declares NO keywords"));
continue;
}
if !kws.iter().any(|k| k == home.config_key) {
problems.push(format!(
"{rel} ({package}) has no {:?} keyword — that is the ron_repo_type an \
operator WRITES, so it is the first thing they search. Got {kws:?}",
home.config_key
));
}
let real_aliases: Vec<&str> = home
.aliases
.iter()
.copied()
.filter(|a| !TYPO_ALIASES.contains(a) && !UNKEYWORDABLE_ALIASES.contains(a))
.collect();
let absent: Vec<&str> = real_aliases
.iter()
.copied()
.filter(|a| !kws.iter().any(|k| k == a))
.collect();
if !absent.is_empty() {
problems.push(format!(
"{rel} ({package}) is missing {:?}'s alias(es) {absent:?} as keyword(s) — \
each is a name someone searches for, and the config key {:?} alone does \
not answer them (this is the PyPI-vs-pip trap). Got {kws:?}",
home.format, home.config_key
));
}
}
}
// A broken enumeration must not read as a clean result.
assert!(
checked >= 15,
"the guard only inspected {checked} repository crates — ALL_ARTIFACT_FORMATS or the \
home() map must have changed shape"
);
assert!(
problems.is_empty(),
"{} format(s) not findable by the names they answer to (checked {checked} crates):\n · {}",
problems.len(),
problems.join("\n · ")
);
}
/// The Rosetta doc SK332 asks for must EXIST and must name every format. A mapping table
/// nobody maintains is worse than none, so the guard reads it: every `config_key` and every
/// real alias has to appear in it, and so does every crate it points at.
#[test]
fn the_capability_name_map_doc_covers_every_format() {
let root = repo_root();
let path = root.join(".nornir/capability-name-map.md");
let doc = std::fs::read_to_string(&path).unwrap_or_else(|e| {
panic!(
"{} is missing ({e}) — the four-name trap needs a written Rosetta stone, not \
just keywords",
path.display()
)
});
let doc = doc.to_lowercase();
let mut missing: Vec<String> = Vec::new();
for format in holger_traits::ALL_ARTIFACT_FORMATS {
let home = format.home();
for name in home.all_names() {
if !doc.contains(&name.to_lowercase()) {
missing.push(format!("name {name:?} ({:?})", home.format));
}
}
if !home.package.is_empty() && !doc.contains(&home.package.to_lowercase()) {
missing.push(format!("package {:?} ({:?})", home.package, home.format));
}
if let Some((_, pkg)) = home.also {
if !doc.contains(&pkg.to_lowercase()) {
missing.push(format!("also-package {pkg:?} ({:?})", home.format));
}
}
}
assert!(
missing.is_empty(),
"the capability name map is missing {} entr(ies) — every name a capability answers \
to must be in it, or the map does not do its one job:\n · {}",
missing.len(),
missing.join("\n · ")
);
}