Help must be able to guide an agent: an overview index, and a --help on every command that prints instead of executing #463
Labels
No labels
agent-ready
bug
contract
documentation
duplicate
enhancement
good first issue
help wanted
invalid
needs-human
needs-input
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
iterative-works/iw-cli#463
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
iwhelp cannot guide anyone today — not a person at a shell, not an agent driving the CLI. Four things are wrong, and they have to be fixed together: the first makes the next two unreachable, and the fourth is what stops all three from rotting again.Supersedes #439 (a
--helpflag must never execute a command; reject unknown flags across subcommands) and #202 (review-state updateshould support--help). Both are carried into this issue in full. Close them in favour of this one.1. The help flag never reaches a help printer
Only 4 of 34 commands handle it:
dashboard,feedback,issue,review-state. Everything else either runs, or fails on an unrelated error:The worst case is recorded in #439:
./iw phase-merge --helpmerged pull request 434. The command that performed the merge was a request for documentation.phase-mergehas no required argument, so an unrecognised flag falls through to the action.phase-prlooks correct only by accident — its required-argument check happens to run first.The other half of #439 matters beyond help: unknown flags are silently discarded on every subcommand, so a typo'd flag becomes "run with defaults" instead of an error. A related case from the same family:
./iw issue create --titlewhose value begins with two dashes is swallowed by the arg parser, and the API rejects the request with a bare 422.Required:
2. There is no overview worth reading
iw --helpprints six lines and sends the reader elsewhere:iw --listthen prints 34 flatPurpose:/Usage:pairs with no grouping and no sense of which command to reach for when. Both are scraped out of two comment lines in each command script byiw-run(parse_command_header,iw-run:261-265).Required: an overview that is an index of the tool. Every command listed, grouped by what it is for (worktree lifecycle, phase lifecycle, review state, server and dashboard, project setup, diagnostics), one line each that says what the command does — enough for a reader who has never used
iwto pick the right one without running three of them to find out.3. The text says nothing that can be acted on
This is the part neither #439 nor #202 covers, and it is the reason help is useless even where it exists. Take the most-used command:
That is the whole of it. It never says:
--timeout,--poll-intervaland--poll-windoware allDUR. The difference between the total budget, the cadence of one poll and how long one invocation blocks is the entire model of the gate, and none of it is here.--timeoutis 30m,--poll-window8m,--poll-interval30s. All invisible.phase-prandphase-mergereturn 3 for "the wait is unfinished, run me again"; 1 for "CI refused the phase". That contract is the single most important thing a caller must know, and it exists only in the kanon skill text. A person at a shell, or an agent that does not have that skill loaded, cannot find it.An agent reading this help cannot drive the command correctly. That is the bar: the help text must be instructive enough that an agent with no other documentation can use the command correctly on the first try.
Required, per command:
4. The help must be inherent to the command, not built beside it
This is a requirement on the design, not a nicety. Any arrangement where the help text lives somewhere other than the command will drift, because every added command and every changed flag then needs a second edit that nothing forces. We have that today in four independent copies of the same facts — the
// USAGE:comment headers, the ad-hocprintHelpbodies in four commands,docs/commands/review-state.md, and the kanon skill text — and they already disagree.Each command must declare its own help, in code, and that declaration must be load-bearing.
Load-bearing is the part that makes it stick. If the declaration is only a doc string, an author can add a flag and not document it. So derive the argument parsing from the declaration: an undeclared flag cannot be read, and a declared flag cannot be undocumented. Then adding a flag without describing it does not compile or does not work, and changing a flag changes its help in the same edit. Nothing else has to be remembered. This also delivers requirement 1 for free — a parser that knows its own flags rejects the ones it does not know, and a help request is dispatched from the same declaration before any action runs.
Make the declaration's shape put the author in the caller's position. The type should ask for what a caller needs, in fields the author cannot leave blank:
description— what this command does, and when to reach for it.Required fields with no defaults, so the compiler refuses a command that declares no intent or no exit codes. An author writing a new command should be answering "how does the caller understand this?" while writing it, not filling in a form afterwards.
The
// USAGE:header scrape iniw-run(parse_command_header,iw-run:261-265, used bylist_commandsat:337) is the external mechanism this replaces. It must be deleted, not kept alongside, or it becomes a fifth copy. (The// PURPOSE:file-header convention stays — it applies to every source file in the project and is not the help.)docs/commands/review-state.mdand the publishediw-cli-opsskill must both be generated from the same declaration rather than maintained beside it. Thebuild-iw-cli-skillsskill already regenerates the skill from command source and is the natural consumer.The one real constraint
iw --listis a bash loop that greps two comment lines per file and never starts a JVM (iw-run:337-360). It also lists plugin commands from directories iw-cli does not own, by the same scrape. Moving the source of truth into compiled Scala has to answer both:helpentry point incorecan hold the registry of every command's declaration and print the whole index in one JVM start.iw --listbecomes as slow as any otheriwcommand, which is the price and is probably right — but decide it deliberately rather than discover it.Related, not superseded
./iwinvocations in commands and skills againstiw --list. Reads the same source.docs/apiandllms.txtfor the undocumented core modules.build-iw-cli-skillsskill regenerates the publishediw-cli-opsskill from command source. It must consume the same declaration (see section 4).#439 recorded during IW-423; see
project-management/issues/IW-423/LESSONS.mdentry 11.Concrete site for the "reject unknown flags" half, found during IW-436.
ReviewStateCliParser.extractFlag(core/model/ReviewStateCliParser.scala:19-22) returnsSome(args(idx + 1))without checking whether that token starts with--. Its siblingextractRepeatedFlag(:24-30) does check:So
./iw review-state update --status --commitsilently setsstatusto the string"--commit"and drops the--commitbehaviour. The card then holds an invalid status.Note for whoever fixes this: this is a second mechanism, not the one this issue's remedy covers.
--commitis a known flag, so an unknown-flag check does not catch it — the guard needed is "a flag's value must not itself be flag-shaped", the same guardextractRepeatedFlagalready has andextractFlaglacks. It is the same shape as the./iw issue create --titlecase already noted above. A full fix needs an inventory of which flags take values, including the flags consumed incore/commands/ReviewState.scalathat the parser never sees.Recorded during IW-436; see
project-management/issues/IW-436/LESSONS.mdentry 1.