feat(cli): one table drives both dispatch and --help - #443
Open
avrabe wants to merge 1 commit into
Open
Conversation
REQ-CLI-SURFACE-001. `--help` documented 16 commands; `main.rs` dispatched 20.
The four missing ones were `sysml2`, `extract`, `generate` and `version` —
which made the entire SysML v2 surface, 8378 LOC and 276 tests, undiscoverable
to anyone who had not read the source.
## Not a guard — a single source
The obvious fix is a checker that diffs the two lists. This removes the second
list instead: `main` and `print_usage` now read the same `COMMANDS` table, so a
command that dispatches is documented by construction and the description
column is computed from the longest name rather than hand-padded.
That turns out to be stronger than a test. Deleting an entry from `COMMANDS`
does not fail a check — it does not COMPILE, because the command's entry point
becomes dead code under `-D warnings`:
error: function `cmd_sysml2` is never used
error: could not compile `spar` (bin "spar")
`version`, `help` and their flag spellings stay out of the table deliberately:
they short-circuit before it and are not operations over a model, so listing
them under `Commands:` would imply `spar version <file>`. They get their own
lines in the help instead.
## The gap mutation found
Three mutations were run against the new tests. Two were killed. The third —
adding `"secret" => cmd_parse(&args[2..])` to the fallback match — SURVIVED
every test in the file.
That is not a hypothetical: a hand-written arm beside the table is exactly how
the four undocumented commands came to exist. The table makes the commands IN
it consistent; it cannot stop one being added next to it.
So `no_command_dispatches_outside_the_table` reads the dispatcher's source via
`include_str!` and asserts every literal match arm is one of the six allowed
short-circuit spellings. That is modelling rather than measuring, which this
repo normally avoids — but the thing being guarded against is a source edit,
and the alternative is enumerating every string a user might type. It now
reports `these dispatch around COMMANDS: ["secret"]` and fails.
## Verification
- `cargo test -p spar` under `-D warnings`: 26 test binaries green, 0 failed.
The dispatcher change is the real risk here and the 300+ existing CLI
integration tests cover it.
- `cargo clippy -p spar --all-targets` under `-D warnings`: clean.
- `cargo fmt --all --check`: clean, run BEFORE staging and re-checked after.
- Mutations: entry removed -> does not compile; `Commands:` header renamed ->
blindness guard fires; arm added outside the table -> new test fails;
restored -> 6 passed.
Every test runs the REAL binary via `CARGO_BIN_EXE_spar`, as `cli_version.rs`
does, so what is graded is the artifact users get.
NOT CLAIMED: that every command is well documented. This is about existence,
not quality — the per-command `Options:` block is still hand-written and a
command may still be listed with a poor description.
Refs #441.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rivet verification gate✅ 20/20 passed
Filter: Failed artifacts(none) Updated automatically by |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second item of v0.43.0 "stop grading ourselves" —
REQ-CLI-SURFACE-001(proposed in #441).
--helpdocumented 16 commands.main.rsdispatched 20. The fourmissing:
sysml2,extract,generate,version— so the entire SysML v2surface, 8378 LOC and 276 tests, was undiscoverable to anyone who had not read
the source.
Not a guard — a single source
The obvious fix is a checker that diffs the two lists. This deletes the second
list instead.
mainandprint_usageread the sameCOMMANDStable:Dispatch does a table lookup;
print_usageiterates the same slice and pads thedescription column to the longest name. A command that dispatches is documented
by construction.
That is stronger than a test. Deleting an entry does not fail a check — it
does not compile, because the entry point becomes dead code under
-D warnings:version/helpand their flag spellings stay out of the table deliberately —they short-circuit before it and are not operations over a model, so listing them
under
Commands:would implyspar version <file>. They get their own lines.The gap mutation testing found
Three mutations, two killed. The third survived every test in the file:
That is not hypothetical — a hand-written arm beside the table is exactly how
the four undocumented commands came to exist. The table makes the commands in
it consistent; it cannot stop one being added next to it.
So
no_command_dispatches_outside_the_tablereads the dispatcher viainclude_str!and asserts every literal arm is one of the six allowedshort-circuit spellings. That is modelling rather than measuring, which this repo
normally avoids — but the thing guarded against is a source edit, and the
alternative is enumerating every string a user might type. It now reports:
A companion test asserts the scan can see the known arms at all, so an empty
result means "clean" and never "read nothing".
Before / after
Verification
The dispatcher rewrite is the real risk here; the 300+ existing spar-cli
integration tests cover it and all pass. Every new test runs the real binary
via
CARGO_BIN_EXE_spar, ascli_version.rsdoes.Not claimed
That every command is well documented. This is about existence, not quality —
the per-command
Options:block is still hand-written, and a command can stillbe listed with a poor description.
Refs #441.
🤖 Generated with Claude Code