use std::collections::BTreeSet;
use std::process::Command;
fn skill_md() -> String {
let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../plugin/skills/cliban/SKILL.md");
std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {}: {e}", path.display()))
}
fn documented_paths(md: &str) -> BTreeSet<Vec<String>> {
let mut out = BTreeSet::new();
let mut in_code = false;
for line in md.lines() {
if line.trim_start().starts_with("```") {
in_code = !in_code;
continue;
}
if !in_code {
continue;
}
let line = line.trim();
let Some(rest) = line.strip_prefix("cliban ") else {
continue;
};
let path: Vec<String> = rest
.split_whitespace()
.take_while(|w| !w.starts_with(['-', '#', '<', '>', '|', '$']))
.take(2)
.map(str::to_string)
.collect();
if !path.is_empty() {
out.insert(path);
}
}
out
}
fn feature_gated(path: &[String]) -> bool {
let gated = cfg!(not(feature = "linear")) && matches!(path[0].as_str(), "import" | "push");
gated && path.len() > 1
}
#[test]
fn every_command_the_skill_names_exists() {
let md = skill_md();
let paths = documented_paths(&md);
assert!(
paths.len() > 20,
"expected the skill to document a real command surface, found {}",
paths.len()
);
let mut missing = Vec::new();
for path in paths.iter().filter(|p| !feature_gated(p)) {
let out = Command::new(env!("CARGO_BIN_EXE_cliban"))
.args(path)
.arg("--help")
.output()
.expect("run cliban --help");
if !out.status.success() {
missing.push(path.join(" "));
}
}
assert!(
missing.is_empty(),
"SKILL.md documents commands that no longer exist: {missing:?}"
);
}
#[test]
fn the_skill_names_every_top_level_command() {
let md = skill_md();
let out = Command::new(env!("CARGO_BIN_EXE_cliban"))
.arg("--help")
.output()
.unwrap();
let help = String::from_utf8_lossy(&out.stdout);
let commands: Vec<&str> = help
.lines()
.skip_while(|l| !l.starts_with("Commands:"))
.skip(1)
.take_while(|l| l.starts_with(" ") && !l.trim().is_empty())
.filter_map(|l| l.split_whitespace().next())
.filter(|c| !matches!(*c, "help" | "migrate-legacy"))
.collect();
assert!(!commands.is_empty(), "could not parse `cliban --help`");
let undocumented: Vec<&str> = commands
.iter()
.copied()
.filter(|c| !md.contains(&format!("`{c}")) && !md.contains(&format!("cliban {c}")))
.collect();
assert!(
undocumented.is_empty(),
"these commands exist but SKILL.md never mentions them: {undocumented:?}"
);
}