diff --git a/ROADMAP.md b/ROADMAP.md index 275a52bb..05fdd44f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -7597,3 +7597,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed) 714. **`help --output-format json` missing `action` field; resume `/help` JSON path also missing `action` and `status`** — dogfooded 2026-05-26 on `7d6b2044`. Top-level `claw help --output-format json` returned `{kind:"help", status:"ok"}` with no `action`. The `render_export_help_json` and `render_help_topic_json` resume-path helpers were also missing `action`. The resume REPL help JSON object had neither `action` nor `status`. Fix: added `action:"help"` (and `status:"ok"` where missing) to all 4 help JSON sites. Source: Jobdori dogfood on `7d6b2044`, 2026-05-26. 715. **Resume-path slash commands (`/compact`, `/clear`, `/cost`, `/stats`, `/history`, `/session exists`, `/session delete`, `memory`) JSON responses missing `action` and `status` fields** — dogfooded 2026-05-26 on `590b5b61`. The `assert_non_empty_action` guardrail added by #3109 only covers `assert_json_command` (top-level CLI surfaces); resume-path commands that emit JSON via `ResumeCommandOutcome.json` were not covered. 8 resume-path JSON sites all lacked `action` and `status`. Fix: added `action` + `status:"ok"` to `compact`, `clear`, `cost`, `stats`, `history`, `session_exists`, `session_delete`, `memory`, and `restored`. Source: Jobdori dogfood on `590b5b61`, 2026-05-26. + +716. **Resume-path error JSON used legacy `{type:"error", error:...}` shape instead of standard `{kind, action, status:"error", error_kind, exit_code}` envelope — 5 error paths affected** — dogfooded 2026-05-26 on `76c8d480`. Session load failure, unsupported command, unsupported resumed command, SlashCommand parse error, and broad-cwd abort all emitted the old two-key shape. Fix: aligned all 5 to `{kind, action:"resume"|"abort", status:"error", error_kind, error, exit_code}`. Updated `resumed_stub_command_emits_not_implemented_json` test to assert `status:"error"` + `kind:"unsupported_command"`. Source: Jobdori dogfood on `76c8d480`, 2026-05-26. diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index 57650668..7deccd71 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -3006,9 +3006,12 @@ fn resume_session(session_path: &Path, commands: &[String], output_format: CliOu eprintln!( "{}", serde_json::json!({ - "type": "error", - "error": short_reason, "kind": kind, + "action": "restore", + "status": "error", + "error_kind": kind, + "error": short_reason, + "exit_code": 1, "hint": hint, }) ); @@ -3061,9 +3064,12 @@ fn resume_session(session_path: &Path, commands: &[String], output_format: CliOu eprintln!( "{}", serde_json::json!({ - "type": "error", - "error": format!("/{cmd_root} is not yet implemented in this build"), "kind": "unsupported_command", + "action": "resume", + "status": "error", + "error_kind": "unsupported_command", + "error": format!("/{cmd_root} is not yet implemented in this build"), + "exit_code": 2, "command": raw_command, }) ); @@ -3080,9 +3086,12 @@ fn resume_session(session_path: &Path, commands: &[String], output_format: CliOu eprintln!( "{}", serde_json::json!({ - "type": "error", - "error": format!("unsupported resumed command: {raw_command}"), "kind": "unsupported_resumed_command", + "action": "resume", + "status": "error", + "error_kind": "unsupported_resumed_command", + "error": format!("unsupported resumed command: {raw_command}"), + "exit_code": 2, "command": raw_command, }) ); @@ -3096,8 +3105,12 @@ fn resume_session(session_path: &Path, commands: &[String], output_format: CliOu eprintln!( "{}", serde_json::json!({ - "type": "error", + "kind": "cli_parse", + "action": "resume", + "status": "error", + "error_kind": "cli_parse", "error": error.to_string(), + "exit_code": 2, "command": raw_command, }) ); @@ -3133,8 +3146,12 @@ fn resume_session(session_path: &Path, commands: &[String], output_format: CliOu eprintln!( "{}", serde_json::json!({ - "type": "error", + "kind": "resume_command_error", + "action": "resume", + "status": "error", + "error_kind": "resume_command_error", "error": error.to_string(), + "exit_code": 2, "command": raw_command, }) ); @@ -4434,8 +4451,12 @@ fn enforce_broad_cwd_policy( eprintln!( "{}", serde_json::json!({ - "type": "error", + "kind": "broad_cwd", + "action": "abort", + "status": "error", + "error_kind": "broad_cwd", "error": message, + "exit_code": 1, }) ); } diff --git a/rust/crates/rusty-claude-cli/tests/resume_slash_commands.rs b/rust/crates/rusty-claude-cli/tests/resume_slash_commands.rs index 496b29b0..be6c3fad 100644 --- a/rust/crates/rusty-claude-cli/tests/resume_slash_commands.rs +++ b/rust/crates/rusty-claude-cli/tests/resume_slash_commands.rs @@ -523,7 +523,14 @@ fn resumed_stub_command_emits_not_implemented_json() { assert!(!output.status.success()); let stderr = String::from_utf8(output.stderr).expect("utf8"); let parsed: Value = serde_json::from_str(stderr.trim()).expect("should be json"); - assert_eq!(parsed["type"], "error"); + assert_eq!( + parsed["status"], "error", + "stub command should emit status:error" + ); + assert_eq!( + parsed["kind"], "unsupported_command", + "stub command should emit kind:unsupported_command" + ); assert!( parsed["error"] .as_str()