claude-mpm 4.1.1__py3-none-any.whl → 4.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/BUILD_NUMBER +1 -1
- claude_mpm/VERSION +1 -1
- claude_mpm/__main__.py +1 -1
- claude_mpm/agents/BASE_PM.md +74 -46
- claude_mpm/agents/INSTRUCTIONS.md +11 -153
- claude_mpm/agents/WORKFLOW.md +61 -321
- claude_mpm/agents/__init__.py +11 -11
- claude_mpm/agents/agent_loader.py +23 -20
- claude_mpm/agents/agent_loader_integration.py +1 -1
- claude_mpm/agents/agents_metadata.py +27 -0
- claude_mpm/agents/async_agent_loader.py +5 -8
- claude_mpm/agents/base_agent_loader.py +36 -25
- claude_mpm/agents/frontmatter_validator.py +6 -6
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +9 -9
- claude_mpm/agents/templates/api_qa.json +47 -2
- claude_mpm/agents/templates/imagemagick.json +256 -0
- claude_mpm/agents/templates/qa.json +41 -2
- claude_mpm/agents/templates/ticketing.json +5 -5
- claude_mpm/agents/templates/web_qa.json +50 -2
- claude_mpm/cli/__init__.py +51 -46
- claude_mpm/cli/__main__.py +1 -1
- claude_mpm/cli/commands/__init__.py +10 -12
- claude_mpm/cli/commands/agent_manager.py +186 -181
- claude_mpm/cli/commands/agents.py +271 -268
- claude_mpm/cli/commands/aggregate.py +30 -29
- claude_mpm/cli/commands/cleanup.py +50 -44
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
- claude_mpm/cli/commands/config.py +162 -127
- claude_mpm/cli/commands/doctor.py +52 -62
- claude_mpm/cli/commands/info.py +37 -25
- claude_mpm/cli/commands/mcp.py +3 -7
- claude_mpm/cli/commands/mcp_command_router.py +14 -18
- claude_mpm/cli/commands/mcp_install_commands.py +28 -23
- claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
- claude_mpm/cli/commands/mcp_server_commands.py +23 -17
- claude_mpm/cli/commands/memory.py +192 -141
- claude_mpm/cli/commands/monitor.py +117 -88
- claude_mpm/cli/commands/run.py +120 -84
- claude_mpm/cli/commands/run_config_checker.py +4 -5
- claude_mpm/cli/commands/socketio_monitor.py +17 -19
- claude_mpm/cli/commands/tickets.py +92 -92
- claude_mpm/cli/parser.py +1 -5
- claude_mpm/cli/parsers/__init__.py +1 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
- claude_mpm/cli/parsers/agents_parser.py +2 -3
- claude_mpm/cli/parsers/base_parser.py +7 -5
- claude_mpm/cli/parsers/mcp_parser.py +4 -2
- claude_mpm/cli/parsers/monitor_parser.py +26 -18
- claude_mpm/cli/shared/__init__.py +10 -10
- claude_mpm/cli/shared/argument_patterns.py +57 -71
- claude_mpm/cli/shared/base_command.py +61 -53
- claude_mpm/cli/shared/error_handling.py +62 -58
- claude_mpm/cli/shared/output_formatters.py +78 -77
- claude_mpm/cli/startup_logging.py +204 -172
- claude_mpm/cli/utils.py +10 -11
- claude_mpm/cli_module/__init__.py +1 -1
- claude_mpm/cli_module/args.py +1 -1
- claude_mpm/cli_module/migration_example.py +5 -5
- claude_mpm/config/__init__.py +9 -9
- claude_mpm/config/agent_config.py +15 -14
- claude_mpm/config/experimental_features.py +4 -4
- claude_mpm/config/paths.py +0 -1
- claude_mpm/config/socketio_config.py +5 -6
- claude_mpm/constants.py +1 -2
- claude_mpm/core/__init__.py +8 -8
- claude_mpm/core/agent_name_normalizer.py +1 -1
- claude_mpm/core/agent_registry.py +20 -23
- claude_mpm/core/agent_session_manager.py +3 -3
- claude_mpm/core/base_service.py +7 -15
- claude_mpm/core/cache.py +4 -6
- claude_mpm/core/claude_runner.py +85 -113
- claude_mpm/core/config.py +43 -28
- claude_mpm/core/config_aliases.py +0 -9
- claude_mpm/core/config_constants.py +52 -30
- claude_mpm/core/constants.py +0 -1
- claude_mpm/core/container.py +18 -27
- claude_mpm/core/exceptions.py +2 -2
- claude_mpm/core/factories.py +10 -12
- claude_mpm/core/framework_loader.py +581 -280
- claude_mpm/core/hook_manager.py +26 -22
- claude_mpm/core/hook_performance_config.py +58 -47
- claude_mpm/core/injectable_service.py +1 -1
- claude_mpm/core/interactive_session.py +61 -152
- claude_mpm/core/interfaces.py +1 -100
- claude_mpm/core/lazy.py +5 -5
- claude_mpm/core/log_manager.py +587 -0
- claude_mpm/core/logger.py +125 -8
- claude_mpm/core/logging_config.py +15 -15
- claude_mpm/core/minimal_framework_loader.py +5 -8
- claude_mpm/core/oneshot_session.py +15 -33
- claude_mpm/core/optimized_agent_loader.py +4 -6
- claude_mpm/core/optimized_startup.py +2 -1
- claude_mpm/core/output_style_manager.py +147 -106
- claude_mpm/core/pm_hook_interceptor.py +0 -1
- claude_mpm/core/service_registry.py +11 -8
- claude_mpm/core/session_manager.py +1 -2
- claude_mpm/core/shared/__init__.py +1 -1
- claude_mpm/core/shared/config_loader.py +101 -97
- claude_mpm/core/shared/path_resolver.py +72 -68
- claude_mpm/core/shared/singleton_manager.py +56 -50
- claude_mpm/core/socketio_pool.py +26 -6
- claude_mpm/core/tool_access_control.py +4 -5
- claude_mpm/core/typing_utils.py +50 -59
- claude_mpm/core/unified_agent_registry.py +14 -19
- claude_mpm/core/unified_config.py +4 -6
- claude_mpm/core/unified_paths.py +197 -109
- claude_mpm/dashboard/open_dashboard.py +2 -4
- claude_mpm/experimental/cli_enhancements.py +51 -36
- claude_mpm/generators/agent_profile_generator.py +2 -4
- claude_mpm/hooks/base_hook.py +1 -2
- claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
- claude_mpm/hooks/claude_hooks/event_handlers.py +93 -38
- claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
- claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
- claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
- claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
- claude_mpm/hooks/memory_integration_hook.py +5 -5
- claude_mpm/hooks/tool_call_interceptor.py +1 -1
- claude_mpm/hooks/validation_hooks.py +4 -4
- claude_mpm/init.py +4 -9
- claude_mpm/models/__init__.py +2 -2
- claude_mpm/models/agent_session.py +11 -14
- claude_mpm/scripts/mcp_server.py +20 -11
- claude_mpm/scripts/mcp_wrapper.py +5 -5
- claude_mpm/scripts/mpm_doctor.py +321 -0
- claude_mpm/scripts/socketio_daemon.py +28 -25
- claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
- claude_mpm/scripts/socketio_server_manager.py +116 -95
- claude_mpm/services/__init__.py +49 -49
- claude_mpm/services/agent_capabilities_service.py +12 -18
- claude_mpm/services/agents/__init__.py +22 -22
- claude_mpm/services/agents/agent_builder.py +140 -119
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
- claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
- claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
- claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
- claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
- claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
- claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
- claude_mpm/services/agents/deployment/agent_validator.py +0 -1
- claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
- claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
- claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
- claude_mpm/services/agents/deployment/config/__init__.py +1 -1
- claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
- claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
- claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
- claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
- claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
- claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
- claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
- claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
- claude_mpm/services/agents/deployment/results/__init__.py +1 -1
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
- claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
- claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
- claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
- claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
- claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
- claude_mpm/services/agents/loading/__init__.py +1 -1
- claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
- claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
- claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
- claude_mpm/services/agents/management/__init__.py +1 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
- claude_mpm/services/agents/management/agent_management_service.py +5 -9
- claude_mpm/services/agents/memory/__init__.py +4 -4
- claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
- claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
- claude_mpm/services/agents/memory/content_manager.py +44 -38
- claude_mpm/services/agents/memory/template_generator.py +4 -6
- claude_mpm/services/agents/registry/__init__.py +10 -6
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
- claude_mpm/services/agents/registry/modification_tracker.py +3 -6
- claude_mpm/services/async_session_logger.py +1 -2
- claude_mpm/services/claude_session_logger.py +1 -2
- claude_mpm/services/command_deployment_service.py +173 -0
- claude_mpm/services/command_handler_service.py +20 -22
- claude_mpm/services/core/__init__.py +25 -25
- claude_mpm/services/core/base.py +0 -5
- claude_mpm/services/core/interfaces/__init__.py +32 -32
- claude_mpm/services/core/interfaces/agent.py +0 -21
- claude_mpm/services/core/interfaces/communication.py +0 -27
- claude_mpm/services/core/interfaces/infrastructure.py +0 -56
- claude_mpm/services/core/interfaces/service.py +0 -29
- claude_mpm/services/diagnostics/__init__.py +1 -1
- claude_mpm/services/diagnostics/checks/__init__.py +6 -6
- claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
- claude_mpm/services/diagnostics/checks/base_check.py +12 -16
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
- claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
- claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
- claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
- claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
- claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
- claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
- claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
- claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
- claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
- claude_mpm/services/diagnostics/models.py +21 -19
- claude_mpm/services/event_aggregator.py +10 -17
- claude_mpm/services/event_bus/__init__.py +1 -1
- claude_mpm/services/event_bus/config.py +54 -35
- claude_mpm/services/event_bus/event_bus.py +76 -71
- claude_mpm/services/event_bus/relay.py +74 -64
- claude_mpm/services/events/__init__.py +11 -11
- claude_mpm/services/events/consumers/__init__.py +3 -3
- claude_mpm/services/events/consumers/dead_letter.py +71 -63
- claude_mpm/services/events/consumers/logging.py +39 -37
- claude_mpm/services/events/consumers/metrics.py +56 -57
- claude_mpm/services/events/consumers/socketio.py +82 -81
- claude_mpm/services/events/core.py +110 -99
- claude_mpm/services/events/interfaces.py +56 -72
- claude_mpm/services/events/producers/__init__.py +1 -1
- claude_mpm/services/events/producers/hook.py +38 -38
- claude_mpm/services/events/producers/system.py +46 -44
- claude_mpm/services/exceptions.py +81 -80
- claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
- claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
- claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
- claude_mpm/services/hook_service.py +6 -9
- claude_mpm/services/infrastructure/__init__.py +1 -1
- claude_mpm/services/infrastructure/context_preservation.py +8 -12
- claude_mpm/services/infrastructure/monitoring.py +21 -23
- claude_mpm/services/mcp_gateway/__init__.py +37 -37
- claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
- claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
- claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
- claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
- claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
- claude_mpm/services/mcp_gateway/core/base.py +0 -3
- claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
- claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
- claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
- claude_mpm/services/mcp_gateway/main.py +2 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
- claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
- claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
- claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
- claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
- claude_mpm/services/memory/__init__.py +3 -3
- claude_mpm/services/memory/builder.py +3 -6
- claude_mpm/services/memory/cache/__init__.py +1 -1
- claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
- claude_mpm/services/memory/cache/simple_cache.py +1 -1
- claude_mpm/services/memory/indexed_memory.py +5 -7
- claude_mpm/services/memory/optimizer.py +7 -10
- claude_mpm/services/memory/router.py +8 -9
- claude_mpm/services/memory_hook_service.py +48 -34
- claude_mpm/services/monitor_build_service.py +77 -73
- claude_mpm/services/port_manager.py +130 -108
- claude_mpm/services/project/analyzer.py +12 -10
- claude_mpm/services/project/registry.py +11 -11
- claude_mpm/services/recovery_manager.py +10 -19
- claude_mpm/services/response_tracker.py +0 -1
- claude_mpm/services/runner_configuration_service.py +19 -20
- claude_mpm/services/session_management_service.py +7 -11
- claude_mpm/services/shared/__init__.py +1 -1
- claude_mpm/services/shared/async_service_base.py +58 -50
- claude_mpm/services/shared/config_service_base.py +73 -67
- claude_mpm/services/shared/lifecycle_service_base.py +82 -78
- claude_mpm/services/shared/manager_base.py +94 -82
- claude_mpm/services/shared/service_factory.py +96 -98
- claude_mpm/services/socketio/__init__.py +3 -3
- claude_mpm/services/socketio/client_proxy.py +5 -5
- claude_mpm/services/socketio/event_normalizer.py +199 -181
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +5 -4
- claude_mpm/services/socketio/handlers/connection.py +163 -136
- claude_mpm/services/socketio/handlers/file.py +13 -14
- claude_mpm/services/socketio/handlers/git.py +12 -7
- claude_mpm/services/socketio/handlers/hook.py +49 -44
- claude_mpm/services/socketio/handlers/memory.py +0 -1
- claude_mpm/services/socketio/handlers/project.py +0 -1
- claude_mpm/services/socketio/handlers/registry.py +37 -19
- claude_mpm/services/socketio/migration_utils.py +98 -84
- claude_mpm/services/socketio/server/__init__.py +1 -1
- claude_mpm/services/socketio/server/broadcaster.py +81 -87
- claude_mpm/services/socketio/server/core.py +65 -54
- claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
- claude_mpm/services/socketio/server/main.py +64 -38
- claude_mpm/services/socketio_client_manager.py +10 -12
- claude_mpm/services/subprocess_launcher_service.py +4 -7
- claude_mpm/services/system_instructions_service.py +13 -14
- claude_mpm/services/ticket_manager.py +2 -2
- claude_mpm/services/utility_service.py +5 -13
- claude_mpm/services/version_control/__init__.py +16 -16
- claude_mpm/services/version_control/branch_strategy.py +5 -8
- claude_mpm/services/version_control/conflict_resolution.py +9 -23
- claude_mpm/services/version_control/git_operations.py +5 -7
- claude_mpm/services/version_control/semantic_versioning.py +16 -17
- claude_mpm/services/version_control/version_parser.py +13 -18
- claude_mpm/services/version_service.py +10 -11
- claude_mpm/storage/__init__.py +1 -1
- claude_mpm/storage/state_storage.py +22 -28
- claude_mpm/utils/__init__.py +6 -6
- claude_mpm/utils/agent_dependency_loader.py +47 -33
- claude_mpm/utils/config_manager.py +11 -14
- claude_mpm/utils/dependency_cache.py +1 -1
- claude_mpm/utils/dependency_manager.py +13 -17
- claude_mpm/utils/dependency_strategies.py +8 -10
- claude_mpm/utils/environment_context.py +3 -9
- claude_mpm/utils/error_handler.py +3 -13
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/path_operations.py +8 -12
- claude_mpm/utils/robust_installer.py +110 -33
- claude_mpm/utils/subprocess_utils.py +5 -6
- claude_mpm/validation/agent_validator.py +3 -6
- claude_mpm/validation/frontmatter_validator.py +1 -1
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
- claude_mpm-4.1.2.dist-info/RECORD +498 -0
- claude_mpm-4.1.1.dist-info/RECORD +0 -494
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
|
@@ -61,7 +61,7 @@ class ValidationHooks:
|
|
|
61
61
|
result.is_valid = False
|
|
62
62
|
except Exception as e:
|
|
63
63
|
logger.error(f"Pre-load hook failed: {e}")
|
|
64
|
-
result.warnings.append(f"Pre-load hook failed: {
|
|
64
|
+
result.warnings.append(f"Pre-load hook failed: {e!s}")
|
|
65
65
|
|
|
66
66
|
return result
|
|
67
67
|
|
|
@@ -79,7 +79,7 @@ class ValidationHooks:
|
|
|
79
79
|
result.warnings.extend(hook_result.warnings)
|
|
80
80
|
except Exception as e:
|
|
81
81
|
logger.error(f"Post-load hook failed: {e}")
|
|
82
|
-
result.warnings.append(f"Post-load hook failed: {
|
|
82
|
+
result.warnings.append(f"Post-load hook failed: {e!s}")
|
|
83
83
|
|
|
84
84
|
return result
|
|
85
85
|
|
|
@@ -107,7 +107,7 @@ class ValidationHooks:
|
|
|
107
107
|
result.is_valid = False
|
|
108
108
|
except Exception as e:
|
|
109
109
|
logger.error(f"Pre-execute hook failed: {e}")
|
|
110
|
-
result.warnings.append(f"Pre-execute hook failed: {
|
|
110
|
+
result.warnings.append(f"Pre-execute hook failed: {e!s}")
|
|
111
111
|
|
|
112
112
|
return result
|
|
113
113
|
|
|
@@ -118,7 +118,7 @@ async def validate_agent_dependencies(profile_path: Path) -> ValidationResult:
|
|
|
118
118
|
result = ValidationResult(is_valid=True)
|
|
119
119
|
|
|
120
120
|
try:
|
|
121
|
-
with open(profile_path
|
|
121
|
+
with open(profile_path) as f:
|
|
122
122
|
profile_data = yaml.safe_load(f)
|
|
123
123
|
|
|
124
124
|
# Check for circular dependencies
|
claude_mpm/init.py
CHANGED
|
@@ -8,7 +8,8 @@ Handles creation of necessary directories and configuration files.
|
|
|
8
8
|
import json
|
|
9
9
|
import os
|
|
10
10
|
import shutil
|
|
11
|
-
|
|
11
|
+
import sys
|
|
12
|
+
from typing import Dict, Optional
|
|
12
13
|
|
|
13
14
|
import yaml
|
|
14
15
|
|
|
@@ -142,12 +143,10 @@ class ProjectInitializer:
|
|
|
142
143
|
|
|
143
144
|
# Log successful creation with details
|
|
144
145
|
self.logger.info(f"Initialized project directory at {self.project_dir}")
|
|
145
|
-
self.logger.debug(
|
|
146
|
+
self.logger.debug("Created directories: agents, config, responses, logs")
|
|
146
147
|
|
|
147
148
|
# Print appropriate message to console for visibility during startup
|
|
148
149
|
# BUT: Don't print to stdout when running MCP server (interferes with JSON-RPC)
|
|
149
|
-
import sys
|
|
150
|
-
|
|
151
150
|
is_mcp_mode = "mcp" in sys.argv and "start" in sys.argv
|
|
152
151
|
|
|
153
152
|
if not is_mcp_mode:
|
|
@@ -216,8 +215,6 @@ class ProjectInitializer:
|
|
|
216
215
|
|
|
217
216
|
if migrated_count > 0:
|
|
218
217
|
# Don't print to stdout when running MCP server
|
|
219
|
-
import sys
|
|
220
|
-
|
|
221
218
|
is_mcp_mode = "mcp" in sys.argv and "start" in sys.argv
|
|
222
219
|
if not is_mcp_mode:
|
|
223
220
|
print(
|
|
@@ -254,7 +251,7 @@ class ProjectInitializer:
|
|
|
254
251
|
"""
|
|
255
252
|
try:
|
|
256
253
|
# Read existing JSON configuration
|
|
257
|
-
with open(old_file
|
|
254
|
+
with open(old_file) as f:
|
|
258
255
|
config = json.load(f)
|
|
259
256
|
|
|
260
257
|
# Write as YAML
|
|
@@ -327,8 +324,6 @@ class ProjectInitializer:
|
|
|
327
324
|
dependencies = {}
|
|
328
325
|
|
|
329
326
|
# Check Python version
|
|
330
|
-
import sys
|
|
331
|
-
|
|
332
327
|
dependencies["python"] = sys.version_info >= (3, 8)
|
|
333
328
|
|
|
334
329
|
# Check Claude CLI
|
claude_mpm/models/__init__.py
CHANGED
|
@@ -12,7 +12,6 @@ chronological order for session replay and analysis.
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
import json
|
|
15
|
-
import os
|
|
16
15
|
from dataclasses import asdict, dataclass, field
|
|
17
16
|
from datetime import datetime
|
|
18
17
|
from enum import Enum
|
|
@@ -241,29 +240,28 @@ class AgentSession:
|
|
|
241
240
|
# Check event type patterns
|
|
242
241
|
if "prompt" in event_type.lower() or event_type == "user_input":
|
|
243
242
|
return EventCategory.PROMPT
|
|
244
|
-
|
|
243
|
+
if "delegation" in event_type.lower() or event_type == "Task":
|
|
245
244
|
return EventCategory.DELEGATION
|
|
246
|
-
|
|
245
|
+
if "tool" in event_type.lower() or event_type in [
|
|
247
246
|
"PreToolUse",
|
|
248
247
|
"PostToolUse",
|
|
249
248
|
]:
|
|
250
249
|
return EventCategory.TOOL
|
|
251
|
-
|
|
250
|
+
if (
|
|
252
251
|
"file" in event_type.lower()
|
|
253
252
|
or "write" in event_type.lower()
|
|
254
253
|
or "read" in event_type.lower()
|
|
255
254
|
):
|
|
256
255
|
return EventCategory.FILE
|
|
257
|
-
|
|
256
|
+
if "todo" in event_type.lower():
|
|
258
257
|
return EventCategory.TODO
|
|
259
|
-
|
|
258
|
+
if "response" in event_type.lower() or event_type in ["Stop", "SubagentStop"]:
|
|
260
259
|
return EventCategory.RESPONSE
|
|
261
|
-
|
|
260
|
+
if "memory" in event_type.lower():
|
|
262
261
|
return EventCategory.MEMORY
|
|
263
|
-
|
|
262
|
+
if "status" in event_type.lower() or "session" in event_type.lower():
|
|
264
263
|
return EventCategory.STATUS
|
|
265
|
-
|
|
266
|
-
return EventCategory.SYSTEM
|
|
264
|
+
return EventCategory.SYSTEM
|
|
267
265
|
|
|
268
266
|
def _process_event(self, event: SessionEvent):
|
|
269
267
|
"""Process specific event types to update session state.
|
|
@@ -376,9 +374,8 @@ class AgentSession:
|
|
|
376
374
|
self.active_delegation.todos_modified.append(data["todos"])
|
|
377
375
|
|
|
378
376
|
# Track memory updates
|
|
379
|
-
elif event.category == EventCategory.MEMORY:
|
|
380
|
-
|
|
381
|
-
self.active_delegation.memory_updates.append(data)
|
|
377
|
+
elif event.category == EventCategory.MEMORY and self.active_delegation:
|
|
378
|
+
self.active_delegation.memory_updates.append(data)
|
|
382
379
|
|
|
383
380
|
def finalize(self):
|
|
384
381
|
"""Finalize the session by calculating final metrics.
|
|
@@ -534,6 +531,6 @@ class AgentSession:
|
|
|
534
531
|
|
|
535
532
|
WHY: Enables analysis of historical sessions.
|
|
536
533
|
"""
|
|
537
|
-
with open(filepath,
|
|
534
|
+
with open(filepath, encoding="utf-8") as f:
|
|
538
535
|
data = json.load(f)
|
|
539
536
|
return cls.from_dict(data)
|
claude_mpm/scripts/mcp_server.py
CHANGED
|
@@ -5,14 +5,17 @@ This script launches the MCP gateway server for Claude Code integration.
|
|
|
5
5
|
It handles proper Python path setup and error reporting to stderr.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import sys
|
|
9
|
-
import os
|
|
10
8
|
import logging
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
11
|
|
|
12
12
|
# Since we're now in src/claude_mpm/scripts/, we need to go up 3 levels to reach the project root
|
|
13
13
|
# Then down into src to add it to the path
|
|
14
|
-
project_root = os.path.abspath(
|
|
15
|
-
|
|
14
|
+
project_root = os.path.abspath(
|
|
15
|
+
os.path.join(os.path.dirname(__file__), "..", "..", "..")
|
|
16
|
+
)
|
|
17
|
+
sys.path.insert(0, os.path.join(project_root, "src"))
|
|
18
|
+
|
|
16
19
|
|
|
17
20
|
def setup_logging():
|
|
18
21
|
"""Configure logging to stderr to avoid interfering with stdio protocol."""
|
|
@@ -22,25 +25,29 @@ def setup_logging():
|
|
|
22
25
|
stream=sys.stderr,
|
|
23
26
|
)
|
|
24
27
|
|
|
28
|
+
|
|
25
29
|
def main():
|
|
26
30
|
"""Main entry point for the MCP server launcher."""
|
|
27
31
|
try:
|
|
28
32
|
# Setup logging first
|
|
29
33
|
setup_logging()
|
|
30
34
|
logger = logging.getLogger("MCPLauncher")
|
|
31
|
-
|
|
35
|
+
|
|
32
36
|
# Import modules after path setup
|
|
33
37
|
try:
|
|
34
|
-
from claude_mpm.services.mcp_gateway.server.stdio_server import SimpleMCPServer
|
|
35
38
|
import asyncio
|
|
39
|
+
|
|
40
|
+
from claude_mpm.services.mcp_gateway.server.stdio_server import (
|
|
41
|
+
SimpleMCPServer,
|
|
42
|
+
)
|
|
36
43
|
except ImportError as e:
|
|
37
44
|
logger.error(f"Failed to import required modules: {e}")
|
|
38
45
|
logger.error("Make sure claude-mpm is properly installed")
|
|
39
46
|
sys.exit(1)
|
|
40
|
-
|
|
47
|
+
|
|
41
48
|
# Create and run server
|
|
42
49
|
logger.info("Starting MCP Gateway Server...")
|
|
43
|
-
|
|
50
|
+
|
|
44
51
|
async def run_server():
|
|
45
52
|
"""Async function to run the server."""
|
|
46
53
|
try:
|
|
@@ -49,10 +56,10 @@ def main():
|
|
|
49
56
|
except Exception as e:
|
|
50
57
|
logger.error(f"Server runtime error: {e}")
|
|
51
58
|
raise
|
|
52
|
-
|
|
59
|
+
|
|
53
60
|
# Run the async server
|
|
54
61
|
asyncio.run(run_server())
|
|
55
|
-
|
|
62
|
+
|
|
56
63
|
except KeyboardInterrupt:
|
|
57
64
|
# Clean shutdown on Ctrl+C
|
|
58
65
|
logger.info("Server shutdown requested")
|
|
@@ -61,8 +68,10 @@ def main():
|
|
|
61
68
|
# Log any unexpected errors
|
|
62
69
|
logger.error(f"Unexpected error: {e}")
|
|
63
70
|
import traceback
|
|
71
|
+
|
|
64
72
|
traceback.print_exc(file=sys.stderr)
|
|
65
73
|
sys.exit(1)
|
|
66
74
|
|
|
75
|
+
|
|
67
76
|
if __name__ == "__main__":
|
|
68
|
-
main()
|
|
77
|
+
main()
|
|
@@ -10,7 +10,6 @@ for the pyproject.toml scripts configuration.
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
import sys
|
|
13
|
-
import os
|
|
14
13
|
from pathlib import Path
|
|
15
14
|
|
|
16
15
|
|
|
@@ -20,20 +19,21 @@ def entry_point():
|
|
|
20
19
|
current_file = Path(__file__).resolve()
|
|
21
20
|
project_root = current_file.parent.parent.parent.parent
|
|
22
21
|
wrapper_script = project_root / "scripts" / "mcp_wrapper.py"
|
|
23
|
-
|
|
22
|
+
|
|
24
23
|
if not wrapper_script.exists():
|
|
25
24
|
print(f"Error: Wrapper script not found at {wrapper_script}", file=sys.stderr)
|
|
26
25
|
sys.exit(1)
|
|
27
|
-
|
|
26
|
+
|
|
28
27
|
# Add the scripts directory to path and import the wrapper
|
|
29
28
|
scripts_dir = str(wrapper_script.parent)
|
|
30
29
|
if scripts_dir not in sys.path:
|
|
31
30
|
sys.path.insert(0, scripts_dir)
|
|
32
|
-
|
|
31
|
+
|
|
33
32
|
# Import and run the wrapper
|
|
34
33
|
import mcp_wrapper
|
|
34
|
+
|
|
35
35
|
mcp_wrapper.main()
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
if __name__ == "__main__":
|
|
39
|
-
entry_point()
|
|
39
|
+
entry_point()
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
MPM Doctor operational script.
|
|
4
|
+
|
|
5
|
+
WHY: This script provides the core functionality for the /mpm-doctor slash command.
|
|
6
|
+
All operational logic is contained here, while the CLI integration remains in the
|
|
7
|
+
command parser and interactive session handler.
|
|
8
|
+
|
|
9
|
+
DESIGN DECISIONS:
|
|
10
|
+
- Centralized diagnostic execution
|
|
11
|
+
- Support for multiple output formats
|
|
12
|
+
- Configurable check selection
|
|
13
|
+
- Lightweight wrapper around DiagnosticRunner
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import argparse
|
|
17
|
+
import logging
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any, Dict, List, Optional
|
|
21
|
+
|
|
22
|
+
from ..services.diagnostics import DiagnosticRunner, DoctorReporter
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def run_diagnostics(
|
|
26
|
+
verbose: bool = False,
|
|
27
|
+
fix: bool = False,
|
|
28
|
+
checks: Optional[List[str]] = None,
|
|
29
|
+
parallel: bool = False,
|
|
30
|
+
output_format: str = "terminal",
|
|
31
|
+
no_color: bool = False,
|
|
32
|
+
) -> Dict[str, Any]:
|
|
33
|
+
"""
|
|
34
|
+
Execute MPM diagnostics with the specified configuration.
|
|
35
|
+
|
|
36
|
+
WHY: Provides a single entry point for all diagnostic operations,
|
|
37
|
+
whether called from CLI, interactive mode, or programmatically.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
verbose: Show detailed diagnostic information
|
|
41
|
+
fix: Attempt to fix issues automatically
|
|
42
|
+
checks: List of specific checks to run (None for all)
|
|
43
|
+
parallel: Run checks in parallel for faster execution
|
|
44
|
+
output_format: Output format ("terminal", "json", "markdown")
|
|
45
|
+
no_color: Disable colored output
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Dictionary containing:
|
|
49
|
+
- success: bool - whether diagnostics completed successfully
|
|
50
|
+
- summary: DiagnosticSummary object
|
|
51
|
+
- error_count: int - number of errors found
|
|
52
|
+
- warning_count: int - number of warnings found
|
|
53
|
+
- message: str - optional error message if failed
|
|
54
|
+
"""
|
|
55
|
+
logger = logging.getLogger(__name__)
|
|
56
|
+
|
|
57
|
+
# Create diagnostic runner
|
|
58
|
+
runner = DiagnosticRunner(verbose=verbose, fix=fix)
|
|
59
|
+
|
|
60
|
+
# Run diagnostics
|
|
61
|
+
try:
|
|
62
|
+
if checks:
|
|
63
|
+
logger.info(f"Running specific checks: {', '.join(checks)}")
|
|
64
|
+
summary = runner.run_specific_checks(checks)
|
|
65
|
+
elif parallel:
|
|
66
|
+
logger.info("Running diagnostics in parallel mode")
|
|
67
|
+
summary = runner.run_diagnostics_parallel()
|
|
68
|
+
else:
|
|
69
|
+
logger.info("Running comprehensive diagnostics")
|
|
70
|
+
summary = runner.run_diagnostics()
|
|
71
|
+
|
|
72
|
+
except KeyboardInterrupt:
|
|
73
|
+
return {
|
|
74
|
+
"success": False,
|
|
75
|
+
"summary": None,
|
|
76
|
+
"error_count": 0,
|
|
77
|
+
"warning_count": 0,
|
|
78
|
+
"message": "Diagnostics interrupted by user",
|
|
79
|
+
}
|
|
80
|
+
except Exception as e:
|
|
81
|
+
logger.error(f"Diagnostic failed: {e}")
|
|
82
|
+
return {
|
|
83
|
+
"success": False,
|
|
84
|
+
"summary": None,
|
|
85
|
+
"error_count": 1,
|
|
86
|
+
"warning_count": 0,
|
|
87
|
+
"message": f"Diagnostic failed: {e!s}",
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Return success with summary
|
|
91
|
+
return {
|
|
92
|
+
"success": True,
|
|
93
|
+
"summary": summary,
|
|
94
|
+
"error_count": summary.error_count,
|
|
95
|
+
"warning_count": summary.warning_count,
|
|
96
|
+
"message": None,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def format_output(
|
|
101
|
+
summary,
|
|
102
|
+
output_format: str = "terminal",
|
|
103
|
+
verbose: bool = False,
|
|
104
|
+
no_color: bool = False,
|
|
105
|
+
) -> str:
|
|
106
|
+
"""
|
|
107
|
+
Format diagnostic summary for output.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
summary: DiagnosticSummary object
|
|
111
|
+
output_format: Output format ("terminal", "json", "markdown")
|
|
112
|
+
verbose: Show detailed information
|
|
113
|
+
no_color: Disable colored output
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Formatted output string
|
|
117
|
+
"""
|
|
118
|
+
# Create reporter
|
|
119
|
+
reporter = DoctorReporter(use_color=not no_color, verbose=verbose)
|
|
120
|
+
|
|
121
|
+
# Capture output as string for non-terminal formats
|
|
122
|
+
if output_format != "terminal":
|
|
123
|
+
import io
|
|
124
|
+
import sys
|
|
125
|
+
|
|
126
|
+
# Capture stdout
|
|
127
|
+
old_stdout = sys.stdout
|
|
128
|
+
sys.stdout = buffer = io.StringIO()
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
reporter.report(summary, format=output_format)
|
|
132
|
+
output = buffer.getvalue()
|
|
133
|
+
finally:
|
|
134
|
+
sys.stdout = old_stdout
|
|
135
|
+
|
|
136
|
+
return output
|
|
137
|
+
# For terminal format, just report directly
|
|
138
|
+
reporter.report(summary, format=output_format)
|
|
139
|
+
return ""
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def run_doctor_slash_command(args: List[str]) -> bool:
|
|
143
|
+
"""
|
|
144
|
+
Execute the /mpm-doctor slash command.
|
|
145
|
+
|
|
146
|
+
WHY: Provides a simplified interface for the interactive mode slash command,
|
|
147
|
+
parsing basic arguments and returning a simple success/failure result.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
args: Command arguments (e.g., ['--verbose', '--no-color'])
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
bool: True if successful, False otherwise
|
|
154
|
+
"""
|
|
155
|
+
# Parse arguments
|
|
156
|
+
verbose = "--verbose" in args or "-v" in args
|
|
157
|
+
no_color = "--no-color" in args
|
|
158
|
+
fix = "--fix" in args
|
|
159
|
+
parallel = "--parallel" in args
|
|
160
|
+
|
|
161
|
+
# Extract specific checks if provided
|
|
162
|
+
checks = None
|
|
163
|
+
if "--checks" in args:
|
|
164
|
+
try:
|
|
165
|
+
idx = args.index("--checks")
|
|
166
|
+
if idx + 1 < len(args):
|
|
167
|
+
# Get all arguments after --checks until next flag
|
|
168
|
+
checks = []
|
|
169
|
+
for i in range(idx + 1, len(args)):
|
|
170
|
+
if args[i].startswith("-"):
|
|
171
|
+
break
|
|
172
|
+
checks.append(args[i])
|
|
173
|
+
except (ValueError, IndexError):
|
|
174
|
+
pass
|
|
175
|
+
|
|
176
|
+
# Print header
|
|
177
|
+
print("\n" + "=" * 60)
|
|
178
|
+
print("Claude MPM Doctor Report")
|
|
179
|
+
print("=" * 60)
|
|
180
|
+
|
|
181
|
+
# Run diagnostics
|
|
182
|
+
result = run_diagnostics(
|
|
183
|
+
verbose=verbose,
|
|
184
|
+
fix=fix,
|
|
185
|
+
checks=checks,
|
|
186
|
+
parallel=parallel,
|
|
187
|
+
output_format="terminal",
|
|
188
|
+
no_color=no_color,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Handle results
|
|
192
|
+
if not result["success"]:
|
|
193
|
+
print(f"\n❌ {result['message']}")
|
|
194
|
+
if verbose and result.get("message", "").startswith("Diagnostic failed"):
|
|
195
|
+
import traceback
|
|
196
|
+
|
|
197
|
+
traceback.print_exc()
|
|
198
|
+
return False
|
|
199
|
+
|
|
200
|
+
# Format and display output
|
|
201
|
+
format_output(
|
|
202
|
+
result["summary"], output_format="terminal", verbose=verbose, no_color=no_color
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# Return based on status
|
|
206
|
+
return result["error_count"] == 0
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def main():
|
|
210
|
+
"""
|
|
211
|
+
Main entry point for standalone execution.
|
|
212
|
+
|
|
213
|
+
WHY: Allows the script to be run directly for testing or debugging.
|
|
214
|
+
"""
|
|
215
|
+
parser = argparse.ArgumentParser(
|
|
216
|
+
description="Claude MPM Doctor - Diagnostic Tool",
|
|
217
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
parser.add_argument(
|
|
221
|
+
"--verbose",
|
|
222
|
+
"-v",
|
|
223
|
+
action="store_true",
|
|
224
|
+
help="Show detailed diagnostic information",
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
parser.add_argument(
|
|
228
|
+
"--json", action="store_true", help="Output results in JSON format"
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
parser.add_argument(
|
|
232
|
+
"--markdown", action="store_true", help="Output results in Markdown format"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
parser.add_argument(
|
|
236
|
+
"--fix",
|
|
237
|
+
action="store_true",
|
|
238
|
+
help="Attempt to fix issues automatically (experimental)",
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
parser.add_argument(
|
|
242
|
+
"--checks",
|
|
243
|
+
nargs="+",
|
|
244
|
+
choices=[
|
|
245
|
+
"installation",
|
|
246
|
+
"configuration",
|
|
247
|
+
"filesystem",
|
|
248
|
+
"claude",
|
|
249
|
+
"agents",
|
|
250
|
+
"mcp",
|
|
251
|
+
"monitor",
|
|
252
|
+
"common",
|
|
253
|
+
],
|
|
254
|
+
help="Run only specific checks",
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
parser.add_argument(
|
|
258
|
+
"--parallel",
|
|
259
|
+
action="store_true",
|
|
260
|
+
help="Run checks in parallel for faster execution",
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
parser.add_argument(
|
|
264
|
+
"--no-color", action="store_true", help="Disable colored output"
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
parser.add_argument("--output", "-o", type=Path, help="Save output to file")
|
|
268
|
+
|
|
269
|
+
args = parser.parse_args()
|
|
270
|
+
|
|
271
|
+
# Determine output format
|
|
272
|
+
if args.json:
|
|
273
|
+
output_format = "json"
|
|
274
|
+
elif args.markdown:
|
|
275
|
+
output_format = "markdown"
|
|
276
|
+
else:
|
|
277
|
+
output_format = "terminal"
|
|
278
|
+
|
|
279
|
+
# Run diagnostics
|
|
280
|
+
result = run_diagnostics(
|
|
281
|
+
verbose=args.verbose,
|
|
282
|
+
fix=args.fix,
|
|
283
|
+
checks=args.checks,
|
|
284
|
+
parallel=args.parallel,
|
|
285
|
+
output_format=output_format,
|
|
286
|
+
no_color=args.no_color,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
# Handle failure
|
|
290
|
+
if not result["success"]:
|
|
291
|
+
print(f"\n❌ {result['message']}")
|
|
292
|
+
sys.exit(2)
|
|
293
|
+
|
|
294
|
+
# Format output
|
|
295
|
+
output = format_output(
|
|
296
|
+
result["summary"],
|
|
297
|
+
output_format=output_format,
|
|
298
|
+
verbose=args.verbose,
|
|
299
|
+
no_color=args.no_color,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
# Save to file if requested
|
|
303
|
+
if args.output:
|
|
304
|
+
try:
|
|
305
|
+
args.output.write_text(output)
|
|
306
|
+
print(f"Report saved to: {args.output}")
|
|
307
|
+
except Exception as e:
|
|
308
|
+
print(f"❌ Failed to save report: {e!s}")
|
|
309
|
+
sys.exit(2)
|
|
310
|
+
|
|
311
|
+
# Determine exit code
|
|
312
|
+
if result["error_count"] > 0:
|
|
313
|
+
sys.exit(2) # Errors found
|
|
314
|
+
elif result["warning_count"] > 0:
|
|
315
|
+
sys.exit(1) # Warnings found
|
|
316
|
+
else:
|
|
317
|
+
sys.exit(0) # All OK
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
if __name__ == "__main__":
|
|
321
|
+
main()
|