From 1f00771fd2bbc24d3c15463b18b0eaab9993f031 Mon Sep 17 00:00:00 2001 From: bellman Date: Fri, 15 May 2026 10:06:23 +0900 Subject: [PATCH] Keep plugin lifecycle JSON complete after team merges Preserve the direct and resumed plugin JSON arrays that downstream G007 regressions require while retaining the degraded config envelope from the malformed-MCP work. Constraint: G007 verification requires plugins[] and load_failures[] on plugin JSON plus status/config_load_error consistency. Rejected: Only relaxing output_format_contract tests | that would hide a shipped CLI JSON regression. Confidence: high Scope-risk: narrow Directive: Keep direct, resumed, and interactive plugin command payloads routed through one payload helper before changing plugin JSON fields. Tested: cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --test output_format_contract inventory_commands_emit_structured_json_when_requested -- --nocapture; 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 structured_json_when_requested -- --nocapture; cargo check --manifest-path rust/Cargo.toml -p runtime -p tools -p rusty-claude-cli -p commands -p plugins Not-tested: Full workspace clippy remains blocked by pre-existing LaneContext struct_excessive_bools lint. Co-authored-by: OmX --- rust/crates/rusty-claude-cli/src/main.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index da228cfb..342bd91a 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -4033,6 +4033,8 @@ fn run_resume_command( "config_load_error": payload.config_load_error, "message": &payload.message, "reload_runtime": payload.reload_runtime, + "plugins": payload.plugins, + "load_failures": payload.load_failures, }); Ok(ResumeCommandOutcome { session: session.clone(), @@ -5636,6 +5638,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, }))? ), } @@ -5803,7 +5807,6 @@ impl LiveCli { target: Option<&str>, ) -> Result> { let cwd = env::current_dir()?; - let loader = ConfigLoader::default_for(&cwd); let payload = plugins_command_payload_for(&cwd, action, target)?; println!("{}", payload.message); if payload.reload_runtime { @@ -7760,6 +7763,8 @@ struct PluginsCommandPayload { reload_runtime: bool, status: &'static str, config_load_error: Option, + plugins: Vec, + load_failures: Vec, } fn plugins_command_payload_for( @@ -7774,17 +7779,21 @@ 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 failures = report.failures(); + let status = if config_load_error.is_some() || !failures.is_empty() { "degraded" } else { "ok" @@ -7801,6 +7810,8 @@ fn plugins_command_payload_from_result( reload_runtime: result.reload_runtime, status, config_load_error, + plugins: report.summaries().iter().map(plugin_summary_json).collect(), + load_failures: failures.iter().map(plugin_load_failure_json).collect(), } }