From fbb0ab4be7ae78677be291cfc0951d77daa06e48 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 23 Apr 2026 08:02:12 +0900 Subject: [PATCH] fix(#171): classify `unexpected extra arguments` errors as cli_parse Pinpoint #171: typed-error classifier gap discovered during #141 probe cycle #97. `claw list-sessions --help` emits: error: unexpected extra arguments after `claw list-sessions`: --help This format is used by multiple verbs that reject trailing positional args: - list-sessions - plugins (subcommands) - config (subcommands) - diff - load-session Before fix: {"error": "unexpected extra arguments after `claw list-sessions`: --help", "hint": null, "kind": "unknown", "type": "error"} After fix: {"error": "unexpected extra arguments after `claw list-sessions`: --help", "hint": "Run `claw --help` for usage.", "kind": "cli_parse", "type": "error"} The pattern `unexpected extra arguments after \`claw` is specific enough that it won't hijack generic prose mentioning "unexpected extra arguments" in other contexts (sanity test included). Side benefit: like #169/#170, correctly classified cli_parse errors now auto-trigger the #247 hint synthesizer. Related #141 gap not yet closed: `claw list-sessions --help` still errors instead of showing help (requires separate parser fix to recognize --help as a distinct path). This classifier fix at least makes the error surface typed correctly so consumers can distinguish "parse failure" from "unknown" and potentially retry without the --help flag. Test added: - `classify_error_kind_covers_unexpected_extra_args_171` (4 positive cases + 1 sanity guard) Tests: 226/226 pass (+1 from #171). Typed-error family: #121, #127, #129, #130, #164, #169, #170, #247. --- rust/crates/rusty-claude-cli/src/main.rs | 59 ++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index 060837d..6ba8bd7 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -321,6 +321,17 @@ fn classify_error_kind(message: &str) -> &'static str { // misuse — more specific than cli_parse, give it its own kind so // consumers can offer REPL-launch guidance. "slash_command_requires_repl" + } else if message.contains("unexpected extra arguments after `claw") { + // #171: `claw --help` where doesn't accept suffix args + // (e.g., `claw list-sessions --help`, `claw plugins list --foo`). + // This is a parse error. Message template: + // `unexpected extra arguments after \`claw \`: ` + // + // Covers: plugins, config, diff, list-sessions, load-session. + // #141-related: `claw list-sessions --help` specifically fails here + // instead of showing help. Classifier fix unblocks typed-error + // handling even while the help-for-that-verb gap remains open. + "cli_parse" } else if message.contains("invalid model syntax") { "invalid_model_syntax" } else if message.contains("is not yet implemented") { @@ -11215,6 +11226,54 @@ mod tests { ); } + #[test] + fn classify_error_kind_covers_unexpected_extra_args_171() { + // #171: `claw ` where the verb doesn't accept + // trailing positional args (e.g., `claw list-sessions --help`, + // `claw plugins list --foo`). Message template is: + // `unexpected extra arguments after \`claw \`: ` + // + // Affects: list-sessions, plugins, config, diff, load-session. + // Before #171, these were classified `unknown`, breaking typed-error + // consumer dispatch on what is clearly a CLI parse error. + assert_eq!( + classify_error_kind( + "unexpected extra arguments after `claw list-sessions`: --help" + ), + "cli_parse", + "list-sessions extra args must classify as cli_parse" + ); + assert_eq!( + classify_error_kind( + "unexpected extra arguments after `claw plugins list`: --foo" + ), + "cli_parse", + "plugins subcommand extra args must classify as cli_parse" + ); + assert_eq!( + classify_error_kind("unexpected extra arguments after `claw diff`: --bar"), + "cli_parse", + "diff extra args must classify as cli_parse" + ); + assert_eq!( + classify_error_kind( + "unexpected extra arguments after `claw config show`: --baz" + ), + "cli_parse", + "config subcommand extra args must classify as cli_parse" + ); + // Sanity: the pattern requires the exact `after \`claw` prefix to + // match, so unrelated prose with "unexpected extra arguments" in a + // different structure falls through. + assert_eq!( + classify_error_kind( + "the API returned unexpected extra arguments in some response" + ), + "unknown", + "generic prose with 'unexpected extra arguments' should fall through" + ); + } + #[test] fn split_error_hint_separates_reason_from_runbook() { // #77: short reason / hint separation for JSON error payloads