Skip to content

Commit 04eb661

Browse files
committed
test(#747): regression guard for #745 bare slash command hint contract (issue/pr/commit)
1 parent 18e7744 commit 04eb661

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

ROADMAP.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7659,3 +7659,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
76597659
745. **`claw issue --output-format json` and all other direct-CLI slash commands (pr, commit, etc.) returned `hint: null` — the `bare_slash_command_guidance` message strings had no `\n` separator between short error and remediation text, so `split_error_hint` couldn't populate the hint field** — dogfooded 2026-05-26 on `92e053a1`. The #738 fix added `\n` to the `--resume SESSION /cmd` path but missed the direct-CLI path (e.g. `claw issue`, `claw pr`). The `bare_slash_command_guidance` function formats two message variants: resume-supported and non-resume; both lacked `\n`. Fix: add `\n` before the remediation text in both format strings. Source: Jobdori dogfood on `92e053a1`, 2026-05-26.
76607660

76617661
746. **`claw --output-format json` (bare, no TTY, no prompt) returned `hint: null` — the non-TTY interactive-only guard error string had no `\n` separator, so `split_error_hint` couldn't extract the remediation text into `.hint`** — dogfooded 2026-05-26 on `3c5459a3`. The single-string message `"interactive_only: claw requires an interactive terminal (stdin is not a TTY and no prompt was provided \u2014 pipe a prompt or run in a TTY)"` contained the hint inline but no newline, so callers reading `.hint` got null and had to parse the prose `error` string. Fix: split at `\n` — short error `"interactive_only: claw requires an interactive terminal."` + hint `"Stdin is not a TTY…pipe a prompt with \`echo 'task' | claw\` or run \`claw\` in an interactive terminal."`. Source: Jobdori dogfood on `3c5459a3`, 2026-05-26.
7662+
7663+
747. **ROADMAP #745 has no regression test: `claw issue/pr/commit --output-format json hint` could silently regress to null** — confirmed by gaebal-gajae on `3c5459a33`. Same pattern as #737, #742, #744. Fix: add `bare_slash_command_hint_745` test iterating `issue`, `pr`, `commit` and asserting `error_kind:"interactive_only"` + non-empty `hint` field. Source: gaebal-gajae dogfood on `3c5459a33`, fixed on `18e7744e`, 2026-05-26.

rust/crates/rusty-claude-cli/tests/output_format_contract.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,6 +1456,54 @@ fn diff_json_changed_file_count_deduplication_733() {
14561456
);
14571457
}
14581458

1459+
#[test]
1460+
fn bare_slash_command_hint_745() {
1461+
// #747/#745: claw <slash-cmd> --output-format json must return non-null hint.
1462+
// bare_slash_command_guidance() previously had no \n so split_error_hint returned hint:null.
1463+
use std::process::Command;
1464+
let root = unique_temp_dir("bare-slash-hint");
1465+
fs::create_dir_all(&root).expect("temp dir");
1466+
let bin = env!("CARGO_BIN_EXE_claw");
1467+
1468+
// issue and pr are non-resume-supported; commit is resume-supported.
1469+
// All must emit non-null hint in their interactive_only error envelope.
1470+
for cmd in &["issue", "pr", "commit"] {
1471+
let output = Command::new(bin)
1472+
.current_dir(&root)
1473+
.args(["--output-format", "json", cmd])
1474+
.env("ANTHROPIC_API_KEY", "test")
1475+
.output()
1476+
.expect("claw should run");
1477+
assert!(
1478+
!output.status.success(),
1479+
"claw {cmd} outside REPL must exit non-zero"
1480+
);
1481+
// Error envelope is on stderr (type:error path) or stdout
1482+
let stderr = String::from_utf8_lossy(&output.stderr)
1483+
.lines()
1484+
.filter(|l| l.starts_with('{'))
1485+
.collect::<Vec<_>>()
1486+
.join("");
1487+
let stdout = String::from_utf8_lossy(&output.stdout);
1488+
let raw = if !stderr.is_empty() {
1489+
stderr
1490+
} else {
1491+
stdout.trim().to_string()
1492+
};
1493+
let parsed: serde_json::Value = serde_json::from_str(&raw)
1494+
.unwrap_or_else(|_| panic!("claw {cmd} must emit JSON; got: {raw}"));
1495+
assert_eq!(
1496+
parsed["error_kind"], "interactive_only",
1497+
"claw {cmd} must have error_kind:interactive_only (#745)"
1498+
);
1499+
let hint = parsed["hint"].as_str().unwrap_or("");
1500+
assert!(
1501+
!hint.is_empty(),
1502+
"claw {cmd} --output-format json hint must be non-empty (#745); got null"
1503+
);
1504+
}
1505+
}
1506+
14591507
#[test]
14601508
fn config_unsupported_section_json_hint_741() {
14611509
// #744/#741: claw config <unknown-section> --output-format json must return

0 commit comments

Comments
 (0)