test(cli): walk the nested verbs when checking the reference for flags

`the_reference_documents_every_flag_of_the_verbs_it_covers` read one level:
`cli.get_subcommands()`, then that verb's own arguments. Two things followed.

It never descended, so every flag a level down was unchecked — `tab new --cwd`,
`pane ls --all`, `pane split --ratio`, `pane close --orphans`,
`server restart --hard`. And its gate for "is this verb documented" looked only
for ``` `tty7 <name> ```, which the page uses for leaf verbs; a group is headed
``` ## `pane` — panes ```. So `ws`, `tab`, `pane`, `machine` and `server` were
skipped whole, taking their children with them. Fifteen flags were checked
where there are twenty-two.

Both fixed: the walk recurses, and the gate accepts either heading shape. The
reference turns out to be complete — nothing was actually undocumented, which
is worth knowing rather than assuming.

The matching rule was too strict as well, and the extension is what showed it:
requiring a backtick immediately before the dashes reported
`server restart --hard` missing when it has its own table row, written as
``` `server restart --hard` ```. It now looks for the flag anywhere on the
page.

The floor is five named nested flags rather than a count, because a count
drifts with the surface and what has to hold is that the walk went down.
Verified both ways: dropping `--orphans` from the page is reported, and
stopping the recursion is reported by name.
This commit is contained in:
l0ng-ai
2026-08-23 07:28:52 +08:00
parent 76929eb8df
commit 9e49b6a412
+69 -13
View File
@@ -688,29 +688,85 @@ mod tests {
// Global flags have their own table, and `--help` is clap's.
const EVERYWHERE: [&str; 4] = ["json", "quiet", "machine", "help"];
// Recursive, because most of the flags are a level down: `ws rename`,
// `pane split`, `tab close`, `machine ls`, `server restart`. Walking
// only the top level pinned `run` and `wait` and left the rest of the
// surface free to drift — and the reference is what an agent reads
// before it ever runs `--help`.
fn walk(
cmd: &clap::Command,
path: &str,
doc: &str,
everywhere: &[&str],
missing: &mut Vec<String>,
checked: &mut Vec<String>,
) {
for arg in cmd.get_arguments() {
let Some(long) = arg.get_long() else { continue };
if everywhere.contains(&long) {
continue;
}
checked.push(format!("{path} --{long}"));
// The flag anywhere on the page, not only at the start of a
// code span. The page writes some of them inside a whole
// command — ``| `server restart --hard` | …`` — and requiring
// a backtick immediately before the dashes called that one
// undocumented when it has its own table row.
if !doc.contains(&format!("--{long}")) {
missing.push(format!("{path} --{long}"));
}
}
for sub in cmd.get_subcommands() {
if sub.get_name() == "help" {
continue;
}
walk(
sub,
&format!("{path} {}", sub.get_name()),
doc,
everywhere,
missing,
checked,
);
}
}
let cli = Cli::command();
let mut missing: Vec<String> = Vec::new();
let (mut covered, mut checked) = (0usize, 0usize);
let mut covered = 0usize;
let mut checked: Vec<String> = Vec::new();
for verb in cli.get_subcommands() {
let name = verb.get_name();
if !DOC.contains(&format!("`tty7 {name}")) {
// Two heading shapes, because the page uses both: a leaf verb gets
// ``### `tty7 capture …` `` and a group gets ``## `pane` — panes``.
// Matching only the first skipped `ws`, `tab`, `pane`, `machine`
// and `server` — every group, and with them every nested verb.
let documented =
DOC.contains(&format!("`tty7 {name}")) || DOC.contains(&format!("\n## `{name}`"));
if !documented {
continue;
}
covered += 1;
for arg in verb.get_arguments() {
let Some(long) = arg.get_long() else { continue };
if EVERYWHERE.contains(&long) {
continue;
}
checked += 1;
if !DOC.contains(&format!("`--{long}")) {
missing.push(format!("{name} --{long}"));
}
}
walk(verb, name, DOC, &EVERYWHERE, &mut missing, &mut checked);
}
// Or the loop could pass by matching nothing at all.
assert!(covered >= 10, "only {covered} documented verbs were found");
assert!(checked >= 5, "only {checked} verb flags were checked");
// Named rather than counted: a count drifts with the surface, and what
// has to hold is that the walk went a level *down*. These five live
// under `tab`, `pane` and `server`, and a one-level walk reaches none
// of them — which is exactly the state this test was in.
for nested in [
"tab new --cwd",
"pane ls --all",
"pane split --ratio",
"pane close --orphans",
"server restart --hard",
] {
assert!(
checked.iter().any(|c| c == nested),
"`{nested}` was never reached, so the walk is not descending: {checked:?}"
);
}
assert!(
missing.is_empty(),
"the command reference does not mention these flags: {missing:?}"