From c522dc970ff79056803a61c27eb0a4aeca060db4 Mon Sep 17 00:00:00 2001 From: bellman Date: Fri, 15 May 2026 09:56:46 +0900 Subject: [PATCH] Preserve plugin lifecycle JSON in G007 CLI output Constraint: G007 worker integrations made plugin command JSON degraded-aware but omitted the structured plugin/load-failure arrays expected by inventory contracts.\nRejected: Drop lifecycle arrays from tests | G007 requires plugin lifecycle state to stay machine-readable across plugin surfaces.\nConfidence: high\nScope-risk: narrow\nDirective: Keep carrying plugin entries, lifecycle state, and load failures even when config loading degrades.\nTested: cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo check --manifest-path rust/Cargo.toml -p runtime -p tools -p rusty-claude-cli -p commands -p plugins; cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --test output_format_contract plugins_json_surfaces_lifecycle_contract_when_plugin_is_installed -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --test output_format_contract inventory_commands_emit_structured_json_when_requested -- --nocapture; git diff --check\nNot-tested: full workspace suite\n\nCo-authored-by: OmX --- rust/crates/rusty-claude-cli/src/main.rs | 21 ++++++++++++++++++- .../tests/output_format_contract.rs | 11 ++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index 0971734e..00bc4755 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -5620,6 +5620,8 @@ impl LiveCli { "config_load_error": payload.config_load_error, "message": payload.message, "reload_runtime": payload.reload_runtime, + "plugins": payload.plugins, + "load_failures": payload.load_failures, }))? ), } @@ -7744,6 +7746,8 @@ struct PluginsCommandPayload { reload_runtime: bool, status: &'static str, config_load_error: Option, + plugins: Vec, + load_failures: Vec, } fn plugins_command_payload_for( @@ -7758,17 +7762,30 @@ fn plugins_command_payload_for( }; let mut manager = build_plugin_manager(cwd, &loader, &runtime_config); let result = handle_plugins_slash_command(action, target, &mut manager)?; + let report = manager.installed_plugin_registry_report()?; Ok(plugins_command_payload_from_result( result, config_load_error, + &report, )) } fn plugins_command_payload_from_result( result: PluginsCommandResult, config_load_error: Option, + report: &plugins::PluginRegistryReport, ) -> PluginsCommandPayload { - let status = if config_load_error.is_some() { + let load_failures = report + .failures() + .iter() + .map(plugin_load_failure_json) + .collect::>(); + let plugins = report + .summaries() + .iter() + .map(plugin_summary_json) + .collect::>(); + let status = if config_load_error.is_some() || !load_failures.is_empty() { "degraded" } else { "ok" @@ -7785,6 +7802,8 @@ fn plugins_command_payload_from_result( reload_runtime: result.reload_runtime, status, config_load_error, + plugins, + load_failures, } } 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 cd5e584c..2f0d4cd6 100644 --- a/rust/crates/rusty-claude-cli/tests/output_format_contract.rs +++ b/rust/crates/rusty-claude-cli/tests/output_format_contract.rs @@ -189,10 +189,13 @@ fn inventory_commands_emit_structured_json_when_requested() { "plugins target should be null when no plugin is targeted" ); assert_eq!(plugins["status"], "ok"); - assert!(plugins["plugins"] - .as_array() - .expect("plugins array") - .is_empty()); + let plugin_entries = plugins["plugins"].as_array().expect("plugins array"); + assert!( + plugin_entries.iter().all(|plugin| plugin["id"].is_string() + && plugin["lifecycle_state"].is_string() + && plugin["lifecycle"].is_object()), + "plugins JSON entries should carry lifecycle contract fields" + ); assert!(plugins["load_failures"] .as_array() .expect("plugin load failures array")