use clap::CommandFactory;
use sqlite_graphrag::cli::Cli;
use std::collections::BTreeSet;
const INVENTORY_DOCS: [&str; 17] = [
"README.md",
"README.pt-BR.md",
"docs/HOW_TO_USE.md",
"docs/HOW_TO_USE.pt-BR.md",
"docs/AGENTS.md",
"docs/AGENTS.pt-BR.md",
"docs/COOKBOOK.md",
"docs/COOKBOOK.pt-BR.md",
"docs/HEADLESS_INVOCATION.md",
"docs/HEADLESS_INVOCATION.pt-BR.md",
"INTEGRATIONS.md",
"INTEGRATIONS.pt-BR.md",
"llms.txt",
"llms.pt-BR.txt",
"llms-full.txt",
"skills/sqlite-graphrag-en/SKILL.md",
"skills/sqlite-graphrag-pt/SKILL.md",
];
const NOT_A_PRODUCT_SURFACE: [&str; 1] = ["help"];
fn is_hidden(cmd: &clap::Command) -> bool {
cmd.is_hide_set()
}
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 command_paths() -> Vec<(String, String)> {
fn walk(cmd: &clap::Command, prefix: &str, root: &str, out: &mut Vec<(String, String)>) {
for sub in cmd.get_subcommands() {
let name = sub.get_name();
if NOT_A_PRODUCT_SURFACE.contains(&name) || is_hidden(sub) {
continue;
}
let path = if prefix.is_empty() {
name.to_string()
} else {
format!("{prefix} {name}")
};
let owner = if root.is_empty() { name } else { root };
out.push((owner.to_string(), path.clone()));
walk(sub, &path, owner, out);
}
}
let mut root = Cli::command();
root.build();
let mut out = Vec::new();
walk(&root, "", "", &mut out);
out
}
fn top_level_commands() -> BTreeSet<String> {
command_paths()
.into_iter()
.filter(|(_, path)| !path.contains(' '))
.map(|(_, path)| path)
.collect()
}
fn nested_command_paths() -> Vec<(String, String)> {
command_paths()
.into_iter()
.filter(|(_, path)| path.contains(' '))
.collect()
}
fn documents_command(doc: &str, command: &str) -> bool {
let invocation = format!("sqlite-graphrag {command}");
if doc
.match_indices(&invocation)
.any(|(index, _)| ends_on_boundary(doc, index + invocation.len()))
{
return true;
}
let is_path = command.contains(' ');
let span_start = format!("`{command}");
doc.match_indices(&span_start).any(|(index, _)| {
let rest = &doc[index + span_start.len()..];
match rest.find('`') {
Some(0) => true,
Some(end) => {
let tail = &rest[..end];
if is_path {
return tail.starts_with(' ');
}
tail.starts_with(' ')
&& tail.len() > 1
&& tail[1..]
.chars()
.all(|c| c.is_ascii_lowercase() || c == '-' || c == ' ')
}
None => false,
}
})
}
fn ends_on_boundary(text: &str, at: usize) -> bool {
text[at..]
.chars()
.next()
.is_none_or(|c| !c.is_ascii_alphanumeric() && c != '-' && c != '_')
}
fn is_portuguese(doc: &str) -> bool {
doc.contains("pt-BR") || doc.contains("-pt/")
}
fn commands_in_root_help() -> BTreeSet<String> {
let output = std::process::Command::new(env!("CARGO_BIN_EXE_sqlite-graphrag"))
.arg("--help")
.output()
.expect("cannot run the binary to read its command inventory");
let help = String::from_utf8_lossy(&output.stdout);
let mut names = BTreeSet::new();
let mut inside = false;
for line in help.lines() {
if line.starts_with("Commands:") {
inside = true;
continue;
}
if !inside {
continue;
}
if line.trim().is_empty() || line.starts_with("Options:") {
break;
}
let trimmed = line.trim_start();
if line.len() - trimmed.len() != 2 {
continue;
}
let Some(name) = trimmed.split_whitespace().next() else {
continue;
};
if name.chars().all(|c| c.is_ascii_lowercase() || c == '-')
&& !NOT_A_PRODUCT_SURFACE.contains(&name)
{
names.insert(name.to_string());
}
}
names
}
#[test]
fn the_walked_inventory_matches_what_the_binary_prints() {
let walked = top_level_commands();
let printed = commands_in_root_help();
assert!(
!printed.is_empty(),
"the root help produced no command rows; the layout changed and this \
cross-check would otherwise compare against nothing"
);
assert_eq!(
walked, printed,
"the clap tree walked here and the binary's own `--help` disagree about \
the shipped surface. Hidden commands are already filtered out of both, \
so a difference means the walk broke or a command is printed without \
being reachable in the tree."
);
}
#[test]
fn every_shipped_command_is_named_in_every_inventory_document() {
let commands = top_level_commands();
assert_eq!(
commands,
commands_in_root_help(),
"the inventory disagrees with the binary; see \
`the_walked_inventory_matches_what_the_binary_prints`"
);
for doc in INVENTORY_DOCS {
let text = read_repo_file(doc);
let missing: Vec<&String> = commands
.iter()
.filter(|c| !documents_command(&text, c))
.collect();
assert!(
missing.is_empty(),
"{doc} names {}/{} shipped commands; a reader cannot invoke what it \
cannot find. Missing: {:?}",
commands.len() - missing.len(),
commands.len(),
missing
);
}
}
#[test]
fn every_nested_subcommand_is_reachable_from_the_corpus_in_both_languages() {
let nested = nested_command_paths();
assert!(
nested.len() >= 32,
"read only {} nested subcommands out of the clap tree, below the 32 \
measured on 2026-08-21; the walk stopped at depth one again, which is \
the defect this test exists to close",
nested.len()
);
let corpus: Vec<(&str, String)> = INVENTORY_DOCS
.iter()
.map(|doc| (*doc, read_repo_file(doc)))
.collect();
let mut missing = Vec::new();
for (owner, path) in &nested {
for portuguese in [false, true] {
let named = corpus
.iter()
.filter(|(doc, _)| is_portuguese(doc) == portuguese)
.any(|(_, text)| documents_command(text, path));
if !named {
let side = if portuguese { "pt-BR" } else { "en" };
missing.push(format!("{path} (owner `{owner}`, missing in {side})"));
}
}
}
assert!(
missing.is_empty(),
"{} nested subcommand(s) are named by no inventory document in the \
language shown. Fix by writing the full path — `sqlite-graphrag config \
list-keys` or a `` `config list-keys` `` code span — into ONE document \
of that language; naming only the owning family does not count, because \
a reader who sees `config` still cannot guess the leaf.\n{}",
missing.len(),
missing.join("\n")
);
}
#[test]
fn the_inventory_leaves_hidden_commands_out() {
let commands = top_level_commands();
assert!(
!commands.contains("debug-schema"),
"`debug-schema` is hidden by the parser; a hidden command is not a \
documentation gap"
);
assert!(
commands.contains("remember") && commands.contains("config"),
"the walk lost a visible command"
);
}
#[test]
fn the_command_matcher_rejects_a_bare_english_word() {
let doc = "You can export the graph and read the list of related items.";
assert!(!documents_command(doc, "export"));
assert!(!documents_command(doc, "read"));
assert!(!documents_command(doc, "list"));
assert!(!documents_command(doc, "related"));
}
#[test]
fn the_command_matcher_accepts_an_invocation_and_a_code_span() {
assert!(documents_command(
"run `sqlite-graphrag export --json`",
"export"
));
assert!(documents_command("the `vec` family", "vec"));
assert!(documents_command("call `fts rebuild` first", "fts"));
}
#[test]
fn the_command_matcher_reads_a_nested_path_carrying_arguments() {
assert!(documents_command(
"run `config set embedding.model qwen3`",
"config set"
));
assert!(documents_command(
"see `sqlite-graphrag vec purge-orphan --json`",
"vec purge-orphan"
));
assert!(!documents_command(
"the `config` family exists",
"config set"
));
}
#[test]
fn the_command_matcher_rejects_a_longer_command_that_shares_a_prefix() {
let doc = "use `remember-batch` for bulk writes";
assert!(!documents_command(doc, "remember"));
assert!(documents_command(doc, "remember-batch"));
}
#[test]
fn the_language_split_covers_the_whole_inventory() {
let english = INVENTORY_DOCS.iter().filter(|d| !is_portuguese(d)).count();
let portuguese = INVENTORY_DOCS.iter().filter(|d| is_portuguese(d)).count();
assert_eq!(english + portuguese, INVENTORY_DOCS.len());
assert!(english >= 8 && portuguese >= 8, "the split is lopsided");
assert!(is_portuguese("skills/sqlite-graphrag-pt/SKILL.md"));
assert!(is_portuguese("docs/AGENTS.pt-BR.md"));
assert!(is_portuguese("llms.pt-BR.txt"));
assert!(!is_portuguese("skills/sqlite-graphrag-en/SKILL.md"));
}