mirror of
https://github.com/ultraworkers/claw-code.git
synced 2026-05-30 03:35:20 +08:00
fix(#768): --resume non-slash trailing arg now has error_kind:invalid_resume_argument + hint
This commit is contained in:
parent
89735dbd33
commit
b778d4e3d4
@ -7701,3 +7701,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
|
|||||||
766. **`claw diff <extra>` returned `error_kind:"unknown"` + `hint:null`** — dogfooded 2026-05-27 on `d29a8e21`. `claw diff --bogus --output-format json` emitted bare error string `"unexpected extra arguments after \`claw diff\`: --bogus"` with no `\n` delimiter and no classifier arm. Fix: (1) added `\nUsage: claw diff` to the error format string; (2) added `unexpected_extra_args` classifier arm matching `starts_with("unexpected extra arguments")`; (3) unit test assertion + integration test `diff_extra_args_have_typed_error_kind_and_hint_766` added. 33 CLI contract tests pass. [SCOPE: claw-code] Source: Jobdori probe on `d29a8e21`, 2026-05-27.
|
766. **`claw diff <extra>` returned `error_kind:"unknown"` + `hint:null`** — dogfooded 2026-05-27 on `d29a8e21`. `claw diff --bogus --output-format json` emitted bare error string `"unexpected extra arguments after \`claw diff\`: --bogus"` with no `\n` delimiter and no classifier arm. Fix: (1) added `\nUsage: claw diff` to the error format string; (2) added `unexpected_extra_args` classifier arm matching `starts_with("unexpected extra arguments")`; (3) unit test assertion + integration test `diff_extra_args_have_typed_error_kind_and_hint_766` added. 33 CLI contract tests pass. [SCOPE: claw-code] Source: Jobdori probe on `d29a8e21`, 2026-05-27.
|
||||||
|
|
||||||
767. **`claw session bogus --output-format json` ignores JSON flag and falls through to credential check** — dogfooded 2026-05-27 on `d29a8e21`. `claw --output-format json session bogus` dispatches to the full interactive REPL runtime instead of rejecting `bogus` as an unknown session subcommand. Output is `error_kind:"missing_credentials"` rather than `error_kind:"unknown_session_subcommand"`. Root cause: `session` arg parser has no unknown-subcommand guard before dispatch; `bogus` is silently accepted as a session ID / switch target and reaches the credential-check gate. Fix needed: validate known session subcommands (`list`, `exists`, `switch`, `fork`, `delete`) before dispatch, return structured `unknown_session_subcommand` error for unrecognized tokens. [SCOPE: claw-code] Source: Jobdori probe on `d29a8e21`, 2026-05-27.
|
767. **`claw session bogus --output-format json` ignores JSON flag and falls through to credential check** — dogfooded 2026-05-27 on `d29a8e21`. `claw --output-format json session bogus` dispatches to the full interactive REPL runtime instead of rejecting `bogus` as an unknown session subcommand. Output is `error_kind:"missing_credentials"` rather than `error_kind:"unknown_session_subcommand"`. Root cause: `session` arg parser has no unknown-subcommand guard before dispatch; `bogus` is silently accepted as a session ID / switch target and reaches the credential-check gate. Fix needed: validate known session subcommands (`list`, `exists`, `switch`, `fork`, `delete`) before dispatch, return structured `unknown_session_subcommand` error for unrecognized tokens. [SCOPE: claw-code] Source: Jobdori probe on `d29a8e21`, 2026-05-27.
|
||||||
|
|
||||||
|
768. **`claw --resume latest compact` returned `error_kind:"unknown"` + `hint:null`** — dogfooded 2026-05-27 on `89735dbd` (gaebal-gajae pinpoint against `d29a8e21`, revised ID after #766/#767 landed). Resume trailing-arg validator emitted single-line `"--resume trailing arguments must be slash commands"` with no typed prefix and no `\n` hint. Fix: (1) changed error to `"invalid_resume_argument: \`{token}\` is not a slash command.\nUsage: claw --resume <session-id|latest> /<slash-command>"` so `split_error_hint()` extracts the hint; (2) added `invalid_resume_argument` classifier arm; (3) unit test assertion + integration test `resume_non_slash_trailing_arg_has_typed_error_kind_and_hint_768` added. 34 CLI contract tests pass. [SCOPE: claw-code] Source: Gaebal-gajae + Jobdori probe on `89735dbd`, 2026-05-27.
|
||||||
|
|||||||
@ -331,6 +331,9 @@ fn classify_error_kind(message: &str) -> &'static str {
|
|||||||
} else if message.starts_with("unexpected extra arguments") {
|
} else if message.starts_with("unexpected extra arguments") {
|
||||||
// #766: extra positionals after commands that take no arguments (e.g. claw diff)
|
// #766: extra positionals after commands that take no arguments (e.g. claw diff)
|
||||||
"unexpected_extra_args"
|
"unexpected_extra_args"
|
||||||
|
} else if message.starts_with("invalid_resume_argument:") {
|
||||||
|
// #768: --resume trailing arg is not a slash command
|
||||||
|
"invalid_resume_argument"
|
||||||
} else if message.starts_with("unknown_option:") {
|
} else if message.starts_with("unknown_option:") {
|
||||||
"unknown_option"
|
"unknown_option"
|
||||||
} else if message.contains("is a slash command")
|
} else if message.contains("is a slash command")
|
||||||
@ -2102,7 +2105,10 @@ fn parse_resume_args(args: &[String], output_format: CliOutputFormat) -> Result<
|
|||||||
}
|
}
|
||||||
|
|
||||||
if current_command.is_empty() {
|
if current_command.is_empty() {
|
||||||
return Err("--resume trailing arguments must be slash commands".to_string());
|
// #768: typed prefix + \n hint so split_error_hint() extracts hint into JSON envelope
|
||||||
|
return Err(format!(
|
||||||
|
"invalid_resume_argument: `{token}` is not a slash command.\nUsage: claw --resume <session-id|latest> /<slash-command> (e.g. /compact, /status)"
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
current_command.push(' ');
|
current_command.push(' ');
|
||||||
@ -12957,6 +12963,13 @@ mod tests {
|
|||||||
),
|
),
|
||||||
"removed_subcommand"
|
"removed_subcommand"
|
||||||
);
|
);
|
||||||
|
// #768: invalid resume trailing arg must classify as invalid_resume_argument
|
||||||
|
assert_eq!(
|
||||||
|
classify_error_kind(
|
||||||
|
"invalid_resume_argument: `compact` is not a slash command.\nUsage: claw --resume <session-id|latest> /<slash-command>"
|
||||||
|
),
|
||||||
|
"invalid_resume_argument"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -1940,3 +1940,43 @@ fn diff_extra_args_have_typed_error_kind_and_hint_766() {
|
|||||||
"claw diff --bogus must return non-null hint (#766), got: {hint:?}"
|
"claw diff --bogus must return non-null hint (#766), got: {hint:?}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn resume_non_slash_trailing_arg_has_typed_error_kind_and_hint_768() {
|
||||||
|
// #768: `claw --resume latest compact` (missing leading /) returned
|
||||||
|
// error_kind:"unknown" + hint:null. Resume is orchestration-critical;
|
||||||
|
// wrappers need a machine-readable signal with a recovery hint.
|
||||||
|
let root = unique_temp_dir("resume-invalid-arg-768");
|
||||||
|
fs::create_dir_all(&root).expect("temp dir should exist");
|
||||||
|
|
||||||
|
let output = run_claw(
|
||||||
|
&root,
|
||||||
|
&["--output-format", "json", "--resume", "latest", "compact"],
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!output.status.success(),
|
||||||
|
"claw --resume latest compact 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"], "invalid_resume_argument",
|
||||||
|
"non-slash resume trailing arg must return error_kind:invalid_resume_argument (#768)"
|
||||||
|
);
|
||||||
|
let hint = parsed["hint"].as_str().unwrap_or("");
|
||||||
|
assert!(
|
||||||
|
!hint.is_empty(),
|
||||||
|
"non-slash resume trailing arg must return non-null hint (#768), got: {hint:?}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
hint.contains("/compact") || hint.contains("slash-command"),
|
||||||
|
"hint must reference slash-command usage, got: {hint:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user