From e5d904edafe5f394579b7e7d0c84f083403c6b0a Mon Sep 17 00:00:00 2001 From: Yeachan-Heo Date: Mon, 25 May 2026 06:28:02 +0000 Subject: [PATCH] Keep skills and agents JSON success envelopes machine-checkable Constraint: ROADMAP #458 requires top-level status on successful skills and agents JSON outputs without changing error semantics. Confidence: high Scope-risk: narrow Directive: Preserve existing error envelopes and avoid unrelated LSP/MCP changes. Tested: cargo fmt; cargo test -p commands; cargo build -p rusty-claude-cli --bin claw; rebuilt JSON status sweep for status/mcp/skills/agents/doctor/sandbox/init/system-prompt/version. Not-tested: full workspace cargo test. --- rust/crates/commands/src/lib.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rust/crates/commands/src/lib.rs b/rust/crates/commands/src/lib.rs index b4358d20ab..333d8d168e 100644 --- a/rust/crates/commands/src/lib.rs +++ b/rust/crates/commands/src/lib.rs @@ -3627,6 +3627,7 @@ fn render_agents_report_json(cwd: &Path, agents: &[AgentSummary]) -> Value { "kind": "agents", "status": "ok", "action": "list", + "status": "ok", "working_directory": cwd.display().to_string(), "count": agents.len(), "summary": { @@ -3710,6 +3711,7 @@ fn render_skills_report_json(skills: &[SkillSummary]) -> Value { "kind": "skills", "status": "ok", "action": "list", + "status": "ok", "summary": { "total": skills.len(), "active": active, @@ -3744,6 +3746,7 @@ fn render_skill_install_report_json(skill: &InstalledSkill) -> Value { json!({ "kind": "skills", "action": "install", + "status": "ok", "result": "installed", "invocation_name": &skill.invocation_name, "invoke_as": format!("${}", skill.invocation_name), @@ -5312,6 +5315,7 @@ mod tests { assert_eq!(report["kind"], "agents"); assert_eq!(report["action"], "list"); + assert_eq!(report["status"], "ok"); assert_eq!(report["working_directory"], workspace.display().to_string()); assert_eq!(report["count"], 3); assert_eq!(report["summary"]["active"], 2); @@ -5327,6 +5331,7 @@ mod tests { let help = handle_agents_slash_command_json(Some("help"), &workspace).expect("agents help"); assert_eq!(help["kind"], "agents"); assert_eq!(help["action"], "help"); + assert_eq!(help["status"], "ok"); assert_eq!(help["usage"]["direct_cli"], "claw agents [list|help]"); // Unknown agents subcommands now return Err so CLI layer can exit 1. @@ -5441,6 +5446,7 @@ mod tests { ); assert_eq!(report["kind"], "skills"); assert_eq!(report["action"], "list"); + assert_eq!(report["status"], "ok"); assert_eq!(report["summary"]["active"], 3); assert_eq!(report["summary"]["shadowed"], 1); assert_eq!(report["skills"][0]["name"], "plan"); @@ -5452,6 +5458,7 @@ mod tests { let help = handle_skills_slash_command_json(Some("help"), &workspace).expect("skills help"); assert_eq!(help["kind"], "skills"); assert_eq!(help["action"], "help"); + assert_eq!(help["status"], "ok"); assert_eq!(help["usage"]["aliases"][0], "/skill"); assert_eq!( help["usage"]["direct_cli"], @@ -5516,6 +5523,7 @@ mod tests { let sources = skills_help_json["usage"]["sources"] .as_array() .expect("skills help sources"); + assert_eq!(skills_help_json["status"], "ok"); assert_eq!(skills_help_json["usage"]["aliases"][0], "/skill"); assert!(sources.iter().any(|value| value == ".omc/skills")); assert!(sources.iter().any(|value| value == ".agents/skills")); @@ -5901,6 +5909,13 @@ mod tests { assert!(report.contains("Invoke as $help")); assert!(report.contains(&install_root.display().to_string())); + let json_report = super::render_skill_install_report_json(&installed); + assert_eq!(json_report["kind"], "skills"); + assert_eq!(json_report["action"], "install"); + assert_eq!(json_report["status"], "ok"); + assert_eq!(json_report["invocation_name"], "help"); + assert_eq!(json_report["invoke_as"], "$help"); + let roots = vec![SkillRoot { source: DefinitionSource::UserCodexHome, path: install_root.clone(),