Skip to content

Commit 32c9276

Browse files
committed
fix(#782): acp unsupported invocation now returns non-null hint with newline-delimited remediation text
1 parent 16c1117 commit 32c9276

3 files changed

Lines changed: 38 additions & 1 deletion

File tree

ROADMAP.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7729,3 +7729,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
77297729
780. **`classify_error_kind` arm ordering bug: `"failed to restore session: legacy session is missing workspace binding: ..."` classified as `session_load_failed` instead of `legacy_session_no_workspace_binding`** — dogfooded 2026-05-27 on `364e7909`. The full error message from `resume_session` prepends `"failed to restore session: "` before `"legacy session is missing workspace binding: ..."`. The `contains("failed to restore session")` arm at line 278 matched first, returning `session_load_failed`; the more specific `legacy_session_no_workspace_binding` arm at line 282 was never reached. Same shadowing existed for `no_managed_sessions`. Fix: reordered the three arms — specific cases (`no_managed_sessions`, `legacy_session_no_workspace_binding`) before the generic `session_load_failed` catch-all. Unit test updated to assert corrected discriminants, plus new assertion covering the full prefixed message that exposed the bug. 40 CLI contract tests pass. [SCOPE: claw-code] Source: Jobdori classifier-ordering probe on `364e7909`, 2026-05-27.
77307730

77317731
781. **`api_http_error` was a single bucket for all HTTP errors; 401 auth and 429 rate-limit returned `hint:null` with no distinction** — dogfooded 2026-05-27 on `d9844cfe`. `classify_error_kind` had a single `api_http_error` arm for all API failures. 401 Unauthorized and 429 rate-limit errors emitted `error_kind:"api_http_error"` + `hint:null`, making it impossible for automation to distinguish auth misconfiguration from transient rate-limiting. Fixes: (1) added `api_auth_error` sub-classifier arm for 401/Unauthorized/authentication_error messages; (2) added `api_rate_limit_error` arm for 429/rate_limit messages; (3) added `fallback_hint_for_error_kind()` that derives a stable hint from the error kind when `split_error_hint` returns `None` (API layer never emits `\n`-delimited hints); (4) main JSON error emission path now calls `fallback_hint_for_error_kind` as fallback. Auth errors now return `api_auth_error` + env-var hint; rate-limit returns `api_rate_limit_error` + retry hint. Unit tests updated. 40 CLI contract tests pass. [SCOPE: claw-code] Source: Jobdori API error opacity probe on `d9844cfe`, 2026-05-27.
7732+
7733+
782. **`claw acp start` returned `error_kind:"unsupported_acp_invocation"` + `hint:null` — remediation text was on same line** — dogfooded 2026-05-27 on `16c1117a` (pinpoint by Gaebal-gajae). The error message `"unsupported ACP invocation. Use `claw acp`, `claw acp serve`, `claw --acp`, or `claw -acp`."` had no `\n` delimiter, so `split_error_hint` returned `hint:null`. Automation could tell ACP was unsupported but could not read the remediation structurally. Fix: inserted a `\n` before the remediation text: `"unsupported ACP invocation. Use ... claw -acp.\nACP/Zed editor integration is currently a discoverability alias only; ..."`. Integration test `acp_unsupported_invocation_has_hint_782` added. 41 CLI contract tests pass. [SCOPE: claw-code] Source: Gaebal-gajae pinpoint + Jobdori implementation on `16c1117a`, 2026-05-27.

rust/crates/rusty-claude-cli/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,7 @@ fn parse_acp_args(args: &[String], output_format: CliOutputFormat) -> Result<Cli
15931593
[] => Ok(CliAction::Acp { output_format }),
15941594
[subcommand] if subcommand == "serve" => Ok(CliAction::Acp { output_format }),
15951595
_ => Err(String::from(
1596-
"unsupported ACP invocation. Use `claw acp`, `claw acp serve`, `claw --acp`, or `claw -acp`.",
1596+
"unsupported ACP invocation. Use `claw acp`, `claw acp serve`, `claw --acp`, or `claw -acp`.\nACP/Zed editor integration is currently a discoverability alias only; a real daemon and JSON-RPC endpoint are in ROADMAP tracking.",
15971597
)),
15981598
}
15991599
}

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2329,3 +2329,38 @@ fn resume_skills_invocation_is_typed_interactive_only_779() {
23292329
"hint must reference live session or CLI, got: {hint:?}"
23302330
);
23312331
}
2332+
2333+
#[test]
2334+
fn acp_unsupported_invocation_has_hint_782() {
2335+
// #782: `claw acp start` returned error_kind:unsupported_acp_invocation but hint:null
2336+
// because the remediation text was on the same line as the error message.
2337+
// Fix: add \n-delimited hint so split_error_hint extracts it.
2338+
let root = unique_temp_dir("acp-unsupported-782");
2339+
fs::create_dir_all(&root).expect("temp dir");
2340+
std::process::Command::new("git")
2341+
.args(["init", "-q"])
2342+
.current_dir(&root)
2343+
.output()
2344+
.ok();
2345+
2346+
let output = run_claw(&root, &["--output-format", "json", "acp", "start"], &[]);
2347+
assert!(!output.status.success(), "acp start should fail");
2348+
let stderr = String::from_utf8_lossy(&output.stderr);
2349+
let json_line = stderr
2350+
.lines()
2351+
.find(|l| l.trim_start().starts_with('{'))
2352+
.expect("should emit JSON error");
2353+
let parsed: serde_json::Value = serde_json::from_str(json_line).unwrap();
2354+
assert_eq!(
2355+
parsed["error_kind"], "unsupported_acp_invocation",
2356+
"unsupported ACP invocation should be classified correctly"
2357+
);
2358+
let hint = parsed["hint"]
2359+
.as_str()
2360+
.expect("hint must be non-null (#782)");
2361+
assert!(!hint.is_empty(), "hint must not be empty");
2362+
assert!(
2363+
hint.contains("discoverability") || hint.contains("ROADMAP"),
2364+
"hint should explain the discoverability-only status, got: {hint:?}"
2365+
);
2366+
}

0 commit comments

Comments
 (0)