use std::collections::BTreeSet;
const ENTRY_MARKER: &str = "SettingKey {";
const KEY_FIELD: &str = "key: \"";
const REFERENCE_DOCS: [&str; 2] = ["README.md", "README.pt-BR.md"];
fn key_namespaces() -> BTreeSet<String> {
registry_keys()
.iter()
.filter_map(|key| key.split_once('.').map(|(head, _)| format!("{head}.")))
.collect()
}
fn in_a_known_namespace(candidate: &str) -> bool {
key_namespaces().iter().any(|ns| candidate.starts_with(ns))
}
const DELIBERATE_LEGACY_MENTIONS: [&str; 4] = [
"db.default_path",
"enrich.preserve_threshold",
"enrich.entity_connect.max_runtime_secs",
"llm.concurrency",
];
fn read_repo_file(relative: &str) -> String {
let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join(relative);
std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("cannot read {}: {e}", path.display()))
}
fn registry_keys() -> BTreeSet<String> {
let source = read_repo_file("src/config/registry.rs");
let mut keys = BTreeSet::new();
for entry in source.split(ENTRY_MARKER).skip(1) {
let Some(start) = entry.find(KEY_FIELD) else {
continue;
};
let rest = &entry[start + KEY_FIELD.len()..];
let Some(end) = rest.find('"') else {
continue;
};
keys.insert(rest[..end].to_string());
}
keys
}
fn documented_keys(markdown: &str) -> BTreeSet<String> {
let mut found = BTreeSet::new();
for token in markdown.split('`').skip(1).step_by(2) {
let candidate = token.trim();
if !in_a_known_namespace(candidate) {
continue;
}
if candidate.ends_with(".rs") || candidate.contains(' ') || candidate.contains('*') {
continue;
}
found.insert(candidate.trim_end_matches(['.', ',']).to_string());
}
found
}
#[test]
fn every_registry_key_appears_in_both_reference_documents() {
let registry = registry_keys();
assert!(
registry.len() >= 61,
"registry shrank to {} keys; update this floor deliberately, never to make the guard pass",
registry.len()
);
for doc in REFERENCE_DOCS {
let documented = documented_keys(&read_repo_file(doc));
let missing: Vec<&String> = registry.difference(&documented).collect();
assert!(
missing.is_empty(),
"{doc} documents {}/{} config keys; {} are invisible to the reader: {:?}",
registry.len() - missing.len(),
registry.len(),
missing.len(),
missing
);
}
}
#[test]
fn no_reference_document_advertises_a_key_the_binary_rejects() {
let registry = registry_keys();
let allowed: BTreeSet<String> = DELIBERATE_LEGACY_MENTIONS
.iter()
.map(|s| (*s).to_string())
.collect();
for doc in REFERENCE_DOCS {
let documented = documented_keys(&read_repo_file(doc));
let ghosts: Vec<&String> = documented
.difference(®istry)
.filter(|key| !allowed.contains(*key))
.collect();
assert!(
ghosts.is_empty(),
"{doc} names {} config key(s) absent from src/config/registry.rs; \
`config set` answers exit 1 for each: {:?}",
ghosts.len(),
ghosts
);
}
}
const DENIAL_MARKERS: [&str; 10] = [
"never existed",
"nunca existiram",
"nunca foi",
"reject",
"rejeit",
"exit 1",
"legac",
"legad",
"removed",
"não é alias",
];
#[test]
fn every_legacy_mention_sits_on_a_line_that_denies_the_key() {
for doc in REFERENCE_DOCS {
let text = read_repo_file(doc);
for legacy in DELIBERATE_LEGACY_MENTIONS {
for (index, line) in text.lines().enumerate() {
if !line.contains(&format!("`{legacy}`")) {
continue;
}
let lowered = line.to_lowercase();
assert!(
DENIAL_MARKERS.iter().any(|m| lowered.contains(m)),
"{doc}:{} names `{legacy}` without denying it; \
the binary answers exit 1 for that key, so the line reads as a lie:\n{line}",
index + 1
);
}
}
}
}
#[test]
fn the_key_scanner_separates_a_config_key_from_a_module_path() {
let sample = "See `src/commands/enrich.rs` and `retry.rs` for `enrich.scan_page_size`.";
let found = documented_keys(sample);
assert!(found.contains("enrich.scan_page_size"));
assert!(!found.contains("retry.rs"));
assert_eq!(found.len(), 1, "unexpected extraction: {found:?}");
}
#[test]
fn the_key_scanner_ignores_a_family_glob() {
let sample = "URLs come from XDG `network.openrouter.*`, not `network.chat_url`.";
let found = documented_keys(sample);
assert!(!found.contains("network.openrouter.*"));
assert!(found.contains("network.chat_url"));
}
#[test]
fn the_key_scanner_survives_a_trailing_separator_inside_the_backticks() {
let sample = "Set `log.level`, `log.format`, and `display.tz`.";
let found = documented_keys(sample);
assert!(found.contains("log.level"));
assert!(found.contains("log.format"));
assert!(found.contains("display.tz"));
}
const ENVELOPE_FIELDS_NOT_KEYS: [&str; 2] = [
"agent_surface.content_truncated",
"agent_surface.output_truncated",
];
#[test]
fn every_xdg_key_promised_by_help_exists_in_the_registry() {
let registry = registry_keys();
let mut promised: BTreeSet<String> = BTreeSet::new();
for scope in help_texts() {
for key in xdg_keys_in_help(&scope) {
if ENVELOPE_FIELDS_NOT_KEYS.contains(&key.as_str()) {
continue;
}
promised.insert(key);
}
}
assert!(
!promised.is_empty(),
"extracted zero XDG keys from --help; the scanner is broken, not the docs"
);
let ghosts: Vec<&String> = promised.difference(®istry).collect();
assert!(
ghosts.is_empty(),
"`--help` promises {} XDG key(s) that `config set` rejects with exit 1: {:?}\n\
Either register the key in src/config/registry.rs and resolve it in \
src/runtime_config.rs, or correct the help text to name the key that exists.",
ghosts.len(),
ghosts
);
}
fn help_texts() -> Vec<String> {
let bin = env!("CARGO_BIN_EXE_sqlite-graphrag");
let root = run_help(bin, &[]);
let mut out = vec![root.clone()];
for name in subcommand_names(&root) {
let level_one = run_help(bin, &[&name]);
for leaf in subcommand_names(&level_one) {
out.push(run_help(bin, &[&name, &leaf]));
}
out.push(level_one);
}
out
}
fn subcommand_names(help: &str) -> Vec<String> {
let mut out = Vec::new();
for line in help.lines() {
let trimmed = line.trim_start();
if line.len() - trimmed.len() != 2 {
continue;
}
let Some(name) = trimmed.split_whitespace().next() else {
continue;
};
if name.is_empty() || !name.chars().all(|c| c.is_ascii_lowercase() || c == '-') {
continue;
}
if name == "help" {
continue;
}
out.push(name.to_string());
}
out
}
fn run_help(bin: &str, path: &[&str]) -> String {
let mut cmd = std::process::Command::new(bin);
cmd.args(path);
let output = cmd
.arg("--help")
.output()
.expect("failed to run the built binary with --help");
let mut text = String::from_utf8_lossy(&output.stdout).into_owned();
text.push_str(&String::from_utf8_lossy(&output.stderr));
text
}
fn xdg_keys_in_help(help: &str) -> BTreeSet<String> {
let mut found = BTreeSet::new();
for token in help.split([' ', '\n', '\t', '`', '\r']) {
let candidate = token.trim_matches(['`', '"', '(', ')', ',', '.', ';', ':', '\'']);
if !in_a_known_namespace(candidate) {
continue;
}
if candidate.contains('*') || candidate.ends_with(".rs") {
continue;
}
found.insert(candidate.to_string());
}
found
}
#[test]
fn the_help_scanner_finds_a_key_behind_either_spelling() {
let a = xdg_keys_in_help("Prefer the flag; optional XDG `embedding.model` here.");
assert!(
a.contains("embedding.model"),
"backticked XDG spelling missed"
);
let b = xdg_keys_in_help("Prefer the flag; optional XDG `config set embedding.backend`.");
assert!(
b.contains("embedding.backend"),
"`config set` spelling missed"
);
let c = xdg_keys_in_help("falls back to XDG `network.openrouter.*` for the family");
assert!(c.is_empty(), "a family glob is not a settable key");
}