fix(cli): move command suggestions into hints and drop the dry-run hint on CLI-raised validation errors

AS
2d ago
+1096-42

Why

Two leftovers from the flag-suggestion work in #59.

A mistyped command embedded cobra's whole suggestion block in the error message. In agent mode and -o json that put raw newlines and tabs inside the error and message strings instead of a hint a tool can act on:

{"error": "unknown command \"genreate\" for \"cli\"\n\nDid you mean this?\n\tgenerate\n", ...}

A typo under a command group got no suggestion at all, because cobra only checks for unknown subcommands at the root. A typo followed by the intended leaf's flags (errors status-get-erro --status-code 200) failed on the first unknown flag instead, so it got no suggestion either.

Every validation error carried "Use --dry-run to preview the request and check parameters", including errors the CLI raised before building any request: a missing required flag, a positional given twice, a bare configure or auth login with no terminal. --dry-run fails those the same way, so the hint cannot apply.

What changed

  • exitcodes.go.stmpl: the root and every synthesized group get cobra.NoArgs as before (the root now explicitly, which retires cobra's root-only legacyArgs check). The Args wrapper runs the command's own validator first and, only when it rejects and the command has subcommands, reports the first positional through UnknownSubcommandError. A hand-written parent that accepts positionals keeps accepting them. The message is cobra's one-line form, unknown command "x" for "cli errors". The nearest commands become a hint (Did you mean generate?, or Did you mean one of list, lint?), using cobra's suggestion policy (DisableSuggestions, minimum distance 2). A Run '<command> --help' to list available commands pointer is added and the built-in validation hints are omitted, matching the flag error handler. When a group's flag parse fails after a positional, the flag error handler validates the positionals it already has through the same Args path, so errors status-get-erro --status-code 200 reports the command typo rather than the flag. Because the check runs inside cobra's normal execution, --help after a typo prints help and shell completion (__complete) is unaffected.
  • classify.go.stmpl: the built-in validation hints drop the dry-run line when the error originated in the CLI (ErrorOriginCLI). Server-side validation (an HTTP 400) keeps it.

Before and after, plain output:

$ cli genreate
Error (validation_error): unknown command "genreate" for "cli"

Did you mean this?
	generate

Reason: CLI_VALIDATION
Fix:
  - Use --dry-run to preview the request and check parameters
  - Run the command with --help for runnable examples, or --usage for the machine-readable surface
$ cli genreate
Error (validation_error): unknown command "genreate" for "cli"
Reason: CLI_VALIDATION
Fix:
  - Did you mean generate?
  - Run 'cli --help' to list available commands, or --usage for the machine-readable surface

Behaviour changes: the suggestion block no longer appears in the error message or on plain stderr; the help hint on unknown commands has new wording; a mistyped root command followed by --help prints help with exit 0, as it already did under a group; a suggestion is made when the typo precedes its flags (a typo after an unknown flag still reports the flag). Exit code for the error is unchanged (2).

Tests

  • clierrors_test.go.stmpl: a mistyped command in agent mode yields a single-line error and a Did you mean errors? hint; plain mode prints the same hint and the help pointer without --dry-run; a typo under a group, with and without the leaf's flags, suggests the sibling command; --help after a typo prints help; __complete still completes; a name with no near match gets no suggestion. A missing required flag (CLI-origin validation) carries no dry-run hint, while a server 400 still does.
  • exitcodes_test.go.stmpl: the root unknown-command test expects the one-line message.
  • output_test.go.stmpl: unit tests build a real cobra tree and run it through Execute, covering root typos, typos behind global flags, typos under a group with and without trailing flags, a real name and a typo after --, invocations that resolve cleanly, a parent command that accepts its own positional, --help after a typo, __complete, and DisableSuggestions.
  • Review SDK regenerated.

Public-safety checklist

  • No customer, product, or spec names, hostnames, model ids, or verbatim customer error payloads
  • No private paths, private tracker ids, or internal document references
  • No workflow provenance