From 92e053a1333a65f46fc498c19751254dd8c46a2a Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Tue, 26 May 2026 18:06:35 +0900 Subject: [PATCH] test(#744): regression guard for #741 config unsupported-section hint contract --- ROADMAP.md | 2 + .../tests/output_format_contract.rs | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index 98bafe47..ed181870 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -7653,3 +7653,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed) 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. + +744. **ROADMAP #741 has no regression test: `claw config list/show/bogus --output-format json hint` field could silently regress to null** — confirmed by gaebal-gajae on `2036f0bd`. Pattern same as #736→#737 and #740→#742: implementation fix without a pinning test. Fix: add `config_unsupported_section_json_hint_741` test iterating `[list, show, bogus, help]` and asserting `kind:config`, `status:error`, `error_kind:unsupported_config_section`, `hint` is non-empty string, `supported_sections[]` is non-empty. Source: gaebal-gajae dogfood on `2036f0bd`, 2026-05-26. diff --git a/rust/crates/rusty-claude-cli/tests/output_format_contract.rs b/rust/crates/rusty-claude-cli/tests/output_format_contract.rs index e9ecb216..8a2cf64e 100644 --- a/rust/crates/rusty-claude-cli/tests/output_format_contract.rs +++ b/rust/crates/rusty-claude-cli/tests/output_format_contract.rs @@ -1456,6 +1456,54 @@ fn diff_json_changed_file_count_deduplication_733() { ); } +#[test] +fn config_unsupported_section_json_hint_741() { + // #744/#741: claw config --output-format json must return + // error_kind:unsupported_config_section with a non-null hint and supported_sections[]. + // This is the regression guard for #741 (hint was null before fix). + use std::process::Command; + let root = unique_temp_dir("config-unsupported-section"); + fs::create_dir_all(&root).expect("temp dir"); + let bin = env!("CARGO_BIN_EXE_claw"); + + for section in &["list", "show", "bogus", "help"] { + let output = Command::new(bin) + .current_dir(&root) + .args(["--output-format", "json", "config", section]) + .output() + .expect("claw config should run"); + let stdout = String::from_utf8_lossy(&output.stdout); + let parsed: serde_json::Value = serde_json::from_str(stdout.trim()).unwrap_or_else(|_| { + panic!("claw config {section} --output-format json must emit valid JSON; got: {stdout}") + }); + assert_eq!( + parsed["kind"], "config", + "config {section} JSON must have kind:config (#741)" + ); + assert_eq!( + parsed["status"], "error", + "config {section} must return status:error (#741)" + ); + assert_eq!( + parsed["error_kind"], "unsupported_config_section", + "config {section} must return error_kind:unsupported_config_section (#741)" + ); + // #741: hint must be a non-empty string (was null before fix) + let hint = parsed["hint"].as_str().unwrap_or(""); + assert!( + !hint.is_empty(), + "config {section} --output-format json hint must be non-empty (#741)" + ); + // supported_sections must still be present and non-empty + assert!( + parsed["supported_sections"] + .as_array() + .map_or(false, |a| !a.is_empty()), + "config {section} JSON must include supported_sections (#741)" + ); + } +} + #[test] fn export_json_has_kind_702() { // #458/#702: `claw export --output-format json` must emit kind:export.