fix(#743): plugins help --output-format json now emits usage envelope matching agents/mcp/skills help shape; resolves #420

This commit is contained in:
YeonGyu-Kim
2026-05-26 18:04:04 +09:00
parent 2036f0bd4c
commit 1d5db5f77d
3 changed files with 26 additions and 0 deletions

View File

@@ -7651,3 +7651,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
741. **`claw config list`, `claw config show`, `claw config bogus` --output-format json returned `hint: null` — the unsupported_config_section error envelope had no `hint` field populated, so callers reading `.hint` get null with no actionable guidance** — dogfooded 2026-05-26 on `5d072d21`. The `render_config_json` unsupported-section branch returned a JSON object with `error` (contains the section list) but no `hint` field. Notably `config list` and `config show` are natural verb patterns that users type expecting a list/show subcommand, but claw config uses `claw config` (no args) for list and `claw config <section>` for show — the error gave no indication of this. Fix: add `hint` field to unsupported_config_section error; verbs (`list`, `show`, `help`, `info`) get a hint explaining the correct idiom (`claw config` / `claw config <section>`); other unknown sections get a "not a config section" hint listing valid values. Source: Jobdori dogfood on `5d072d21`, 2026-05-26. 741. **`claw config list`, `claw config show`, `claw config bogus` --output-format json returned `hint: null` — the unsupported_config_section error envelope had no `hint` field populated, so callers reading `.hint` get null with no actionable guidance** — dogfooded 2026-05-26 on `5d072d21`. The `render_config_json` unsupported-section branch returned a JSON object with `error` (contains the section list) but no `hint` field. Notably `config list` and `config show` are natural verb patterns that users type expecting a list/show subcommand, but claw config uses `claw config` (no args) for list and `claw config <section>` for show — the error gave no indication of this. Fix: add `hint` field to unsupported_config_section error; verbs (`list`, `show`, `help`, `info`) get a hint explaining the correct idiom (`claw config` / `claw config <section>`); other unknown sections get a "not a config section" hint listing valid values. Source: Jobdori dogfood on `5d072d21`, 2026-05-26.
742. **ROADMAP #740 test coverage gap: the new `changed_file_count` branch for git repos was unreachable — the fixture is a plain `unique_temp_dir` (no `git init`), so the test always exercises the `no_git_repo` path and never proves the numeric contract or deduplication behavior** — confirmed by gaebal-gajae on `5d072d21`, fixed on `6e78c1fc`. Fix: add `diff_json_changed_file_count_deduplication_733` test that (a) `git init`s a temp repo, (b) commits a file, (c) asserts `result:"clean"` + `changed_file_count:0`, (d) stages an edit + makes an unstaged edit to the same file, (e) asserts `result:"changes"` + `changed_file_count:1` — proving the BTreeSet deduplication actually works. Source: gaebal-gajae dogfood on `5d072d21`, 2026-05-26. 742. **ROADMAP #740 test coverage gap: the new `changed_file_count` branch for git repos was unreachable — the fixture is a plain `unique_temp_dir` (no `git init`), so the test always exercises the `no_git_repo` path and never proves the numeric contract or deduplication behavior** — confirmed by gaebal-gajae on `5d072d21`, fixed on `6e78c1fc`. Fix: add `diff_json_changed_file_count_deduplication_733` test that (a) `git init`s a temp repo, (b) commits a file, (c) asserts `result:"clean"` + `changed_file_count:0`, (d) stages an edit + makes an unstaged edit to the same file, (e) asserts `result:"changes"` + `changed_file_count:1` — proving the BTreeSet deduplication actually works. Source: gaebal-gajae dogfood on `5d072d21`, 2026-05-26.
743. **`claw plugins help --output-format json` returned `error_kind:"unknown_plugins_action"` with `hint:null` instead of the usage envelope (`action:"help", status:"ok", unexpected:null, usage:{...}`) that `agents help`, `mcp help`, and `skills help` all emit — schema drift within the same command family (ROADMAP #420)** — dogfooded 2026-05-26 on `2036f0bd`. Fix: (a) added `Some("help" | "-h" | "--help")` arm to `handle_plugins_slash_command` returning a text usage message (text path parity); (b) added early-return JSON help envelope in `print_plugins` JSON path matching shape of agents/mcp help: `{action:"help", kind:"plugin", status:"ok", unexpected:null, usage:{direct_cli, slash_command}}`. Source: Jobdori dogfood on `2036f0bd`, 2026-05-26.

View File

@@ -2334,6 +2334,13 @@ pub fn handle_plugins_slash_command(
reload_runtime: false, reload_runtime: false,
}) })
} }
// #743/#420: "help" was caught by Some(other) → unknown_plugins_action error with hint:null.
// agents/mcp/skills all return a help envelope; plugins must match that parity.
Some("help" | "-h" | "--help") => Ok(PluginsCommandResult {
message: "Plugins\n Usage /plugins [list|show <id>|install <id>|enable <id>|disable <id>|uninstall <id>|update <id>|help]\n Subcommands list show install enable disable uninstall update help"
.to_string(),
reload_runtime: false,
}),
Some(other) => Err(PluginError::CommandFailed(format!( Some(other) => Err(PluginError::CommandFailed(format!(
"unknown_plugins_action: '{other}' is not a supported /plugins action. Use list, show, install, enable, disable, uninstall, or update." "unknown_plugins_action: '{other}' is not a supported /plugins action. Use list, show, install, enable, disable, uninstall, or update."
))), ))),

View File

@@ -6108,6 +6108,23 @@ impl LiveCli {
CliOutputFormat::Text => println!("{}", payload.message), CliOutputFormat::Text => println!("{}", payload.message),
CliOutputFormat::Json => { CliOutputFormat::Json => {
let action_str = action.unwrap_or("list"); let action_str = action.unwrap_or("list");
// #743/#420: plugins help must return a usage envelope matching agents/mcp/skills help shape.
if matches!(action_str, "help" | "-h" | "--help") {
let cwd_str = cwd.display().to_string();
let obj = json!({
"kind": "plugin",
"action": "help",
"status": "ok",
"unexpected": null,
"usage": {
"direct_cli": "claw plugins [list|show <id>|install <id>|enable <id>|disable <id>|uninstall <id>|update <id>|help]",
"slash_command": "/plugins [list|show <id>|install <id>|enable <id>|disable <id>|uninstall <id>|update <id>|help]",
},
"cwd": cwd_str,
});
println!("{}", serde_json::to_string_pretty(&obj)?);
return Ok(());
}
// For show/info/describe, filter to the named plugin (exact match). // For show/info/describe, filter to the named plugin (exact match).
// For list with a target, treat target as a substring filter. // For list with a target, treat target as a substring filter.
let is_show_action = matches!(action_str, "show" | "info" | "describe"); let is_show_action = matches!(action_str, "show" | "info" | "describe");