fix(#766): claw diff extra args now classified as unexpected_extra_args with hint; track #767 session subcommand gap

This commit is contained in:
YeonGyu-Kim
2026-05-27 01:33:24 +09:00
parent d29a8e216b
commit 89735dbd33
3 changed files with 52 additions and 1 deletions

View File

@@ -328,6 +328,9 @@ fn classify_error_kind(message: &str) -> &'static str {
} else if message.contains("has been removed.") {
// #765: removed subcommands (login, logout) — hint contains migration guidance
"removed_subcommand"
} else if message.starts_with("unexpected extra arguments") {
// #766: extra positionals after commands that take no arguments (e.g. claw diff)
"unexpected_extra_args"
} else if message.starts_with("unknown_option:") {
"unknown_option"
} else if message.contains("is a slash command")
@@ -1145,7 +1148,7 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
"diff" => {
if rest.len() > 1 {
return Err(format!(
"unexpected extra arguments after `claw diff`: {}",
"unexpected extra arguments after `claw diff`: {}\nUsage: claw diff",
rest[1..].join(" ")
));
}
@@ -12941,6 +12944,13 @@ mod tests {
),
"removed_subcommand"
);
// #766: unexpected extra arguments must classify as unexpected_extra_args
assert_eq!(
classify_error_kind(
"unexpected extra arguments after `claw diff`: --bogus\nUsage: claw diff"
),
"unexpected_extra_args"
);
assert_eq!(
classify_error_kind(
"`claw logout` has been removed.\nSet ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN instead."

View File

@@ -1903,3 +1903,40 @@ fn login_logout_removed_subcommands_have_error_kind_and_hint_765() {
);
}
}
#[test]
fn diff_extra_args_have_typed_error_kind_and_hint_766() {
// #766: `claw diff --bogus` returned error_kind:"unknown" + hint:null.
// `diff` takes no arguments; extra args were unclassified with no remediation.
let root = unique_temp_dir("diff-extra-args-766");
fs::create_dir_all(&root).expect("temp dir should exist");
// Need a git repo for diff to parse past arg validation
std::process::Command::new("git")
.args(["init", "-q"])
.current_dir(&root)
.output()
.ok();
let output = run_claw(&root, &["--output-format", "json", "diff", "--bogus"], &[]);
assert!(
!output.status.success(),
"claw diff --bogus should exit non-zero"
);
let stderr = String::from_utf8_lossy(&output.stderr);
let json_line = stderr
.lines()
.find(|l| l.trim_start().starts_with('{'))
.expect("stderr should contain a JSON error envelope");
let parsed: serde_json::Value =
serde_json::from_str(json_line).expect("error envelope should be valid JSON");
assert_eq!(
parsed["error_kind"], "unexpected_extra_args",
"claw diff --bogus must return error_kind:unexpected_extra_args (#766)"
);
let hint = parsed["hint"].as_str().unwrap_or("");
assert!(
!hint.is_empty(),
"claw diff --bogus must return non-null hint (#766), got: {hint:?}"
);
}