fix(#806): plugins show <not-found> in text mode returned empty success instead of error

This commit is contained in:
YeonGyu-Kim
2026-05-27 22:34:10 +09:00
parent ae6a207d4e
commit 87b7e74770
2 changed files with 25 additions and 2 deletions

View File

@@ -7776,3 +7776,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
804. **`claw agents show <name> <extra>` and `claw skills show <name> <extra>` in text mode returned wrong `agent_not_found`/silent empty instead of catching extra args** — dogfooded 2026-05-27 on `bad1b97f`. Parity gap with JSON-mode fix #796: the text-mode show handlers in `commands/src/lib.rs` still used single-split `split_once(' ')` without checking for spaces in the extracted name. Fix: added `contains(' ')` guard to both text-mode show arms; extra tokens now return `unexpected extra arguments` with usage hint. 62 CLI contract tests pass. [SCOPE: claw-code]
805. **`claw skills show <not-found>` in text mode silently returned "No skills found." instead of an error** — dogfooded 2026-05-27 on `2c3c0f60`. The text-mode show handler in `handle_skills_slash_command` returned `render_skills_report(&matched)` with an empty vec instead of checking for empty match and returning an error. JSON mode already returned `skill_not_found` since #706. Fix: added `matched.is_empty()` guard with `skill_not_found` error + `\n` hint suggesting `claw skills list`. 62 CLI contract tests pass. [SCOPE: claw-code]
806. **`claw plugins show <not-found>` in text mode returned "No plugins installed." instead of an error** — dogfooded 2026-05-27 on `ae6a207d`. The text-mode path in `print_plugins` printed `payload.message` (the full list render) without checking if the requested plugin existed. JSON mode correctly returned `plugin_not_found`. Fix: added show-action filtering + not-found guard to text-mode path; added `starts_with("plugin_not_found:")` arm to classifier for the new error prefix. 63 CLI contract tests pass. [SCOPE: claw-code]

View File

@@ -335,7 +335,7 @@ fn classify_error_kind(message: &str) -> &'static str {
"unknown_agents_subcommand"
} else if message.starts_with("agent not found:") {
"agent_not_found"
} else if message.contains("is not installed") {
} else if message.contains("is not installed") || message.starts_with("plugin_not_found:") {
"plugin_not_found"
} else if message.contains("plugin source") && message.contains("was not found") {
// #794: `plugins install /nonexistent/path` → "plugin source ... was not found"
@@ -6406,7 +6406,28 @@ impl LiveCli {
}
let payload = plugins_command_payload_for(&cwd, action, target)?;
match output_format {
CliOutputFormat::Text => println!("{}", payload.message),
CliOutputFormat::Text => {
// #806: text-mode show must return error when plugin not found (parity with JSON)
let action_str = action.unwrap_or("list");
if matches!(action_str, "show" | "info" | "describe") {
if let Some(name) = target {
let needle = name.to_lowercase();
let found = payload.plugins.iter().any(|p| {
p.get("id")
.and_then(|v| v.as_str())
.map(|id| id.to_lowercase() == needle)
.unwrap_or(false)
});
if !found {
return Err(format!(
"plugin_not_found: plugin '{}' not found\nRun `claw plugins list` to see available plugins.",
name
).into());
}
}
}
println!("{}", payload.message);
}
CliOutputFormat::Json => {
let action_str = action.unwrap_or("list");
// #743/#420: plugins help must return a usage envelope matching agents/mcp/skills help shape.