claude-mpm 4.1.1__py3-none-any.whl → 4.1.3__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.
Files changed (389) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/__main__.py +1 -1
  4. claude_mpm/agents/BASE_PM.md +74 -46
  5. claude_mpm/agents/INSTRUCTIONS.md +11 -153
  6. claude_mpm/agents/WORKFLOW.md +61 -321
  7. claude_mpm/agents/__init__.py +11 -11
  8. claude_mpm/agents/agent_loader.py +23 -20
  9. claude_mpm/agents/agent_loader_integration.py +1 -1
  10. claude_mpm/agents/agents_metadata.py +27 -0
  11. claude_mpm/agents/async_agent_loader.py +5 -8
  12. claude_mpm/agents/base_agent_loader.py +36 -25
  13. claude_mpm/agents/frontmatter_validator.py +6 -6
  14. claude_mpm/agents/schema/agent_schema.json +1 -1
  15. claude_mpm/agents/system_agent_config.py +9 -9
  16. claude_mpm/agents/templates/api_qa.json +47 -2
  17. claude_mpm/agents/templates/engineer.json +33 -11
  18. claude_mpm/agents/templates/imagemagick.json +256 -0
  19. claude_mpm/agents/templates/qa.json +41 -2
  20. claude_mpm/agents/templates/ticketing.json +5 -5
  21. claude_mpm/agents/templates/web_qa.json +50 -2
  22. claude_mpm/cli/__init__.py +51 -46
  23. claude_mpm/cli/__main__.py +1 -1
  24. claude_mpm/cli/commands/__init__.py +10 -12
  25. claude_mpm/cli/commands/agent_manager.py +186 -181
  26. claude_mpm/cli/commands/agents.py +648 -1098
  27. claude_mpm/cli/commands/aggregate.py +30 -29
  28. claude_mpm/cli/commands/cleanup.py +50 -44
  29. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  30. claude_mpm/cli/commands/config.py +162 -127
  31. claude_mpm/cli/commands/doctor.py +52 -62
  32. claude_mpm/cli/commands/info.py +37 -25
  33. claude_mpm/cli/commands/mcp.py +3 -7
  34. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  35. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  36. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  37. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  38. claude_mpm/cli/commands/memory.py +339 -967
  39. claude_mpm/cli/commands/monitor.py +117 -88
  40. claude_mpm/cli/commands/run.py +233 -542
  41. claude_mpm/cli/commands/socketio_monitor.py +17 -19
  42. claude_mpm/cli/commands/tickets.py +92 -92
  43. claude_mpm/cli/parser.py +1 -5
  44. claude_mpm/cli/parsers/__init__.py +1 -1
  45. claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
  46. claude_mpm/cli/parsers/agents_parser.py +2 -3
  47. claude_mpm/cli/parsers/base_parser.py +7 -5
  48. claude_mpm/cli/parsers/mcp_parser.py +4 -2
  49. claude_mpm/cli/parsers/monitor_parser.py +26 -18
  50. claude_mpm/cli/shared/__init__.py +10 -10
  51. claude_mpm/cli/shared/argument_patterns.py +57 -71
  52. claude_mpm/cli/shared/base_command.py +61 -53
  53. claude_mpm/cli/shared/error_handling.py +62 -58
  54. claude_mpm/cli/shared/output_formatters.py +78 -77
  55. claude_mpm/cli/startup_logging.py +280 -172
  56. claude_mpm/cli/utils.py +10 -11
  57. claude_mpm/cli_module/__init__.py +1 -1
  58. claude_mpm/cli_module/args.py +1 -1
  59. claude_mpm/cli_module/migration_example.py +5 -5
  60. claude_mpm/config/__init__.py +9 -9
  61. claude_mpm/config/agent_config.py +15 -14
  62. claude_mpm/config/experimental_features.py +4 -4
  63. claude_mpm/config/paths.py +0 -1
  64. claude_mpm/config/socketio_config.py +5 -6
  65. claude_mpm/constants.py +1 -2
  66. claude_mpm/core/__init__.py +8 -8
  67. claude_mpm/core/agent_name_normalizer.py +1 -1
  68. claude_mpm/core/agent_registry.py +22 -29
  69. claude_mpm/core/agent_session_manager.py +3 -3
  70. claude_mpm/core/base_service.py +7 -15
  71. claude_mpm/core/cache.py +4 -6
  72. claude_mpm/core/claude_runner.py +85 -113
  73. claude_mpm/core/config.py +43 -28
  74. claude_mpm/core/config_aliases.py +0 -9
  75. claude_mpm/core/config_constants.py +52 -30
  76. claude_mpm/core/constants.py +0 -1
  77. claude_mpm/core/container.py +18 -27
  78. claude_mpm/core/exceptions.py +2 -2
  79. claude_mpm/core/factories.py +10 -12
  80. claude_mpm/core/framework_loader.py +500 -680
  81. claude_mpm/core/hook_manager.py +26 -22
  82. claude_mpm/core/hook_performance_config.py +58 -47
  83. claude_mpm/core/injectable_service.py +1 -1
  84. claude_mpm/core/interactive_session.py +61 -152
  85. claude_mpm/core/interfaces.py +1 -100
  86. claude_mpm/core/lazy.py +5 -5
  87. claude_mpm/core/log_manager.py +587 -0
  88. claude_mpm/core/logger.py +125 -8
  89. claude_mpm/core/logging_config.py +15 -17
  90. claude_mpm/core/minimal_framework_loader.py +5 -8
  91. claude_mpm/core/oneshot_session.py +15 -33
  92. claude_mpm/core/optimized_agent_loader.py +4 -6
  93. claude_mpm/core/optimized_startup.py +2 -1
  94. claude_mpm/core/output_style_manager.py +147 -106
  95. claude_mpm/core/pm_hook_interceptor.py +0 -1
  96. claude_mpm/core/service_registry.py +11 -8
  97. claude_mpm/core/session_manager.py +1 -2
  98. claude_mpm/core/shared/__init__.py +1 -1
  99. claude_mpm/core/shared/config_loader.py +101 -97
  100. claude_mpm/core/shared/path_resolver.py +72 -68
  101. claude_mpm/core/shared/singleton_manager.py +56 -50
  102. claude_mpm/core/socketio_pool.py +26 -6
  103. claude_mpm/core/tool_access_control.py +4 -5
  104. claude_mpm/core/typing_utils.py +50 -59
  105. claude_mpm/core/unified_agent_registry.py +14 -19
  106. claude_mpm/core/unified_config.py +4 -6
  107. claude_mpm/core/unified_paths.py +197 -109
  108. claude_mpm/dashboard/open_dashboard.py +2 -4
  109. claude_mpm/experimental/cli_enhancements.py +51 -36
  110. claude_mpm/generators/agent_profile_generator.py +2 -4
  111. claude_mpm/hooks/base_hook.py +1 -2
  112. claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
  113. claude_mpm/hooks/claude_hooks/event_handlers.py +99 -154
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +110 -720
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
  117. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
  118. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  119. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  120. claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
  121. claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
  122. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  123. claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
  124. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  125. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  126. claude_mpm/hooks/memory_integration_hook.py +5 -5
  127. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  128. claude_mpm/hooks/validation_hooks.py +4 -4
  129. claude_mpm/init.py +4 -9
  130. claude_mpm/models/__init__.py +2 -2
  131. claude_mpm/models/agent_session.py +11 -14
  132. claude_mpm/scripts/mcp_server.py +20 -11
  133. claude_mpm/scripts/mcp_wrapper.py +5 -5
  134. claude_mpm/scripts/mpm_doctor.py +321 -0
  135. claude_mpm/scripts/socketio_daemon.py +28 -25
  136. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  137. claude_mpm/scripts/socketio_server_manager.py +116 -95
  138. claude_mpm/services/__init__.py +49 -49
  139. claude_mpm/services/agent_capabilities_service.py +12 -18
  140. claude_mpm/services/agents/__init__.py +22 -22
  141. claude_mpm/services/agents/agent_builder.py +140 -119
  142. claude_mpm/services/agents/deployment/__init__.py +3 -3
  143. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  144. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  145. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  146. claude_mpm/services/agents/deployment/agent_deployment.py +129 -511
  147. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  148. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  149. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  150. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  151. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  152. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  153. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  154. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  155. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  156. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  157. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  158. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  159. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  160. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  161. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  162. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  163. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  164. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  165. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  166. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  167. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  168. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  169. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  170. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  171. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  172. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  173. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  174. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  175. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  176. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  177. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  178. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  179. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  180. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  181. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  182. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  183. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  184. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  185. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  186. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  187. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  188. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  189. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  190. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  191. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  192. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  193. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  194. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  195. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  196. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  197. claude_mpm/services/agents/loading/__init__.py +1 -1
  198. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  199. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  200. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  201. claude_mpm/services/agents/management/__init__.py +1 -1
  202. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  203. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  204. claude_mpm/services/agents/memory/__init__.py +4 -4
  205. claude_mpm/services/agents/memory/agent_memory_manager.py +157 -503
  206. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  207. claude_mpm/services/agents/memory/content_manager.py +44 -38
  208. claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
  209. claude_mpm/services/agents/memory/memory_file_service.py +103 -0
  210. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  211. claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
  212. claude_mpm/services/agents/memory/template_generator.py +4 -6
  213. claude_mpm/services/agents/registry/__init__.py +11 -7
  214. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  215. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  216. claude_mpm/services/async_session_logger.py +1 -2
  217. claude_mpm/services/claude_session_logger.py +1 -2
  218. claude_mpm/services/cli/__init__.py +18 -0
  219. claude_mpm/services/cli/agent_cleanup_service.py +407 -0
  220. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  221. claude_mpm/services/cli/agent_listing_service.py +463 -0
  222. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  223. claude_mpm/services/cli/agent_validation_service.py +589 -0
  224. claude_mpm/services/cli/dashboard_launcher.py +424 -0
  225. claude_mpm/services/cli/memory_crud_service.py +617 -0
  226. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  227. claude_mpm/services/cli/session_manager.py +513 -0
  228. claude_mpm/services/cli/socketio_manager.py +498 -0
  229. claude_mpm/services/cli/startup_checker.py +370 -0
  230. claude_mpm/services/command_deployment_service.py +173 -0
  231. claude_mpm/services/command_handler_service.py +20 -22
  232. claude_mpm/services/core/__init__.py +25 -25
  233. claude_mpm/services/core/base.py +0 -5
  234. claude_mpm/services/core/cache_manager.py +311 -0
  235. claude_mpm/services/core/interfaces/__init__.py +32 -32
  236. claude_mpm/services/core/interfaces/agent.py +0 -21
  237. claude_mpm/services/core/interfaces/communication.py +0 -27
  238. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  239. claude_mpm/services/core/interfaces/service.py +0 -29
  240. claude_mpm/services/core/memory_manager.py +637 -0
  241. claude_mpm/services/core/path_resolver.py +498 -0
  242. claude_mpm/services/core/service_container.py +520 -0
  243. claude_mpm/services/core/service_interfaces.py +436 -0
  244. claude_mpm/services/diagnostics/__init__.py +1 -1
  245. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  246. claude_mpm/services/diagnostics/checks/agent_check.py +152 -97
  247. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  248. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  249. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  250. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  251. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  252. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  253. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  254. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  255. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  256. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  257. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  258. claude_mpm/services/diagnostics/models.py +21 -19
  259. claude_mpm/services/event_aggregator.py +10 -17
  260. claude_mpm/services/event_bus/__init__.py +1 -1
  261. claude_mpm/services/event_bus/config.py +54 -35
  262. claude_mpm/services/event_bus/event_bus.py +76 -71
  263. claude_mpm/services/event_bus/relay.py +74 -64
  264. claude_mpm/services/events/__init__.py +11 -11
  265. claude_mpm/services/events/consumers/__init__.py +3 -3
  266. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  267. claude_mpm/services/events/consumers/logging.py +39 -37
  268. claude_mpm/services/events/consumers/metrics.py +56 -57
  269. claude_mpm/services/events/consumers/socketio.py +82 -81
  270. claude_mpm/services/events/core.py +110 -99
  271. claude_mpm/services/events/interfaces.py +56 -72
  272. claude_mpm/services/events/producers/__init__.py +1 -1
  273. claude_mpm/services/events/producers/hook.py +38 -38
  274. claude_mpm/services/events/producers/system.py +46 -44
  275. claude_mpm/services/exceptions.py +81 -80
  276. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  277. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  278. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  279. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  280. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  281. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  283. claude_mpm/services/hook_service.py +6 -9
  284. claude_mpm/services/infrastructure/__init__.py +1 -1
  285. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  286. claude_mpm/services/infrastructure/monitoring.py +21 -23
  287. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  288. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  289. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  290. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  291. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  292. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  293. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  294. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  295. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  296. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  297. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  298. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  299. claude_mpm/services/mcp_gateway/main.py +2 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  302. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  309. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  310. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  311. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  312. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  313. claude_mpm/services/memory/__init__.py +3 -3
  314. claude_mpm/services/memory/builder.py +3 -6
  315. claude_mpm/services/memory/cache/__init__.py +1 -1
  316. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  317. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  318. claude_mpm/services/memory/indexed_memory.py +5 -7
  319. claude_mpm/services/memory/optimizer.py +7 -10
  320. claude_mpm/services/memory/router.py +8 -9
  321. claude_mpm/services/memory_hook_service.py +48 -34
  322. claude_mpm/services/monitor_build_service.py +77 -73
  323. claude_mpm/services/port_manager.py +130 -108
  324. claude_mpm/services/project/analyzer.py +12 -10
  325. claude_mpm/services/project/registry.py +11 -11
  326. claude_mpm/services/recovery_manager.py +10 -19
  327. claude_mpm/services/response_tracker.py +0 -1
  328. claude_mpm/services/runner_configuration_service.py +19 -20
  329. claude_mpm/services/session_management_service.py +7 -11
  330. claude_mpm/services/shared/__init__.py +1 -1
  331. claude_mpm/services/shared/async_service_base.py +58 -50
  332. claude_mpm/services/shared/config_service_base.py +73 -67
  333. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  334. claude_mpm/services/shared/manager_base.py +94 -82
  335. claude_mpm/services/shared/service_factory.py +96 -98
  336. claude_mpm/services/socketio/__init__.py +3 -3
  337. claude_mpm/services/socketio/client_proxy.py +5 -5
  338. claude_mpm/services/socketio/event_normalizer.py +199 -181
  339. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  340. claude_mpm/services/socketio/handlers/base.py +5 -4
  341. claude_mpm/services/socketio/handlers/connection.py +163 -136
  342. claude_mpm/services/socketio/handlers/file.py +13 -14
  343. claude_mpm/services/socketio/handlers/git.py +12 -7
  344. claude_mpm/services/socketio/handlers/hook.py +49 -44
  345. claude_mpm/services/socketio/handlers/memory.py +0 -1
  346. claude_mpm/services/socketio/handlers/project.py +0 -1
  347. claude_mpm/services/socketio/handlers/registry.py +37 -19
  348. claude_mpm/services/socketio/migration_utils.py +98 -84
  349. claude_mpm/services/socketio/server/__init__.py +1 -1
  350. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  351. claude_mpm/services/socketio/server/core.py +65 -54
  352. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  353. claude_mpm/services/socketio/server/main.py +64 -38
  354. claude_mpm/services/socketio_client_manager.py +10 -12
  355. claude_mpm/services/subprocess_launcher_service.py +4 -7
  356. claude_mpm/services/system_instructions_service.py +13 -14
  357. claude_mpm/services/ticket_manager.py +2 -2
  358. claude_mpm/services/utility_service.py +5 -13
  359. claude_mpm/services/version_control/__init__.py +16 -16
  360. claude_mpm/services/version_control/branch_strategy.py +5 -8
  361. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  362. claude_mpm/services/version_control/git_operations.py +5 -7
  363. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  364. claude_mpm/services/version_control/version_parser.py +13 -18
  365. claude_mpm/services/version_service.py +10 -11
  366. claude_mpm/storage/__init__.py +1 -1
  367. claude_mpm/storage/state_storage.py +22 -28
  368. claude_mpm/utils/__init__.py +6 -6
  369. claude_mpm/utils/agent_dependency_loader.py +47 -33
  370. claude_mpm/utils/config_manager.py +11 -14
  371. claude_mpm/utils/dependency_cache.py +1 -1
  372. claude_mpm/utils/dependency_manager.py +13 -17
  373. claude_mpm/utils/dependency_strategies.py +8 -10
  374. claude_mpm/utils/environment_context.py +3 -9
  375. claude_mpm/utils/error_handler.py +3 -13
  376. claude_mpm/utils/file_utils.py +1 -1
  377. claude_mpm/utils/path_operations.py +8 -12
  378. claude_mpm/utils/robust_installer.py +110 -33
  379. claude_mpm/utils/subprocess_utils.py +5 -6
  380. claude_mpm/validation/agent_validator.py +3 -6
  381. claude_mpm/validation/frontmatter_validator.py +1 -1
  382. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
  383. claude_mpm-4.1.3.dist-info/RECORD +528 -0
  384. claude_mpm/cli/commands/run_config_checker.py +0 -160
  385. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  386. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
  387. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
  388. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
  389. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
@@ -15,7 +15,7 @@ DESIGN DECISIONS:
15
15
  import re
16
16
  from datetime import datetime
17
17
  from pathlib import Path
18
- from typing import Dict, Any, List, Optional, Tuple
18
+ from typing import Any, Dict, Optional
19
19
 
20
20
  from ..models import DiagnosticResult, DiagnosticStatus
21
21
  from .base_check import BaseDiagnosticCheck
@@ -23,51 +23,51 @@ from .base_check import BaseDiagnosticCheck
23
23
 
24
24
  class StartupLogCheck(BaseDiagnosticCheck):
25
25
  """Analyze startup logs for errors and issues."""
26
-
26
+
27
27
  # Common error patterns and their fixes
28
28
  ERROR_PATTERNS = {
29
29
  r"Agent deployment.*failed": (
30
30
  "Agent deployment failure",
31
- "Check agent configuration in .claude/agents/ and run 'claude-mpm deploy'"
31
+ "Check agent configuration in .claude/agents/ and run 'claude-mpm deploy'",
32
32
  ),
33
33
  r"MCP.*not found": (
34
34
  "MCP server not found",
35
- "Install MCP server: npm install -g @modelcontextprotocol/server"
35
+ "Install MCP server: npm install -g @modelcontextprotocol/server",
36
36
  ),
37
37
  r"Port \d+ .*in use": (
38
38
  "Port binding conflict",
39
- "Kill the process using the port or use --websocket-port to specify a different port"
39
+ "Kill the process using the port or use --websocket-port to specify a different port",
40
40
  ),
41
41
  r"Memory loading.*error": (
42
42
  "Memory loading failure",
43
- "Check .claude-mpm/memory/ permissions and run 'claude-mpm memory validate'"
43
+ "Check .claude-mpm/memory/ permissions and run 'claude-mpm memory validate'",
44
44
  ),
45
45
  r"Permission denied": (
46
46
  "Permission error",
47
- "Check file permissions in project directory and .claude-mpm/"
47
+ "Check file permissions in project directory and .claude-mpm/",
48
48
  ),
49
49
  r"ModuleNotFoundError|ImportError": (
50
50
  "Missing Python dependency",
51
- "Install missing dependencies: pip install -e . or pip install claude-mpm[agents]"
51
+ "Install missing dependencies: pip install -e . or pip install claude-mpm[agents]",
52
52
  ),
53
53
  r"Socket\.IO.*failed|socketio.*error": (
54
54
  "Socket.IO initialization failure",
55
- "Install monitor dependencies: pip install claude-mpm[monitor]"
55
+ "Install monitor dependencies: pip install claude-mpm[monitor]",
56
56
  ),
57
57
  r"Configuration.*invalid|yaml.*error": (
58
58
  "Configuration file error",
59
- "Validate configuration: claude-mpm config validate"
59
+ "Validate configuration: claude-mpm config validate",
60
60
  ),
61
61
  r"claude\.json.*large|memory.*issue": (
62
62
  "Large .claude.json file",
63
- "Run 'claude-mpm cleanup-memory' to archive old conversations"
63
+ "Run 'claude-mpm cleanup-memory' to archive old conversations",
64
64
  ),
65
65
  r"Failed to start.*daemon": (
66
66
  "Daemon startup failure",
67
- "Check system resources and try: claude-mpm monitor stop && claude-mpm monitor start"
67
+ "Check system resources and try: claude-mpm monitor stop && claude-mpm monitor start",
68
68
  ),
69
69
  }
70
-
70
+
71
71
  # Warning patterns that should be noted
72
72
  WARNING_PATTERNS = {
73
73
  r"agent.*source.*tracking": "Agent source tracking warning",
@@ -76,21 +76,21 @@ class StartupLogCheck(BaseDiagnosticCheck):
76
76
  r"Socket\.IO.*not available": "Monitor mode unavailable",
77
77
  r"Response logging.*disabled": "Response logging is disabled",
78
78
  }
79
-
79
+
80
80
  @property
81
81
  def name(self) -> str:
82
82
  return "startup_log_check"
83
-
83
+
84
84
  @property
85
85
  def category(self) -> str:
86
86
  return "Startup Log"
87
-
87
+
88
88
  def run(self) -> DiagnosticResult:
89
89
  """Run startup log diagnostics."""
90
90
  try:
91
91
  # Find the latest startup log
92
92
  log_file = self._find_latest_log()
93
-
93
+
94
94
  if not log_file:
95
95
  return DiagnosticResult(
96
96
  category=self.category,
@@ -98,16 +98,16 @@ class StartupLogCheck(BaseDiagnosticCheck):
98
98
  message="No startup logs found",
99
99
  details={
100
100
  "recommendation": "Startup logging will be created on next run"
101
- }
101
+ },
102
102
  )
103
-
103
+
104
104
  # Parse the log file
105
105
  analysis = self._analyze_log_file(log_file)
106
-
106
+
107
107
  # Determine status based on findings
108
108
  status = self._determine_status(analysis)
109
109
  message = self._create_message(analysis)
110
-
110
+
111
111
  # Build details
112
112
  details = {
113
113
  "log_file": str(log_file),
@@ -116,18 +116,18 @@ class StartupLogCheck(BaseDiagnosticCheck):
116
116
  "warnings": analysis["warning_count"],
117
117
  "info_messages": analysis["info_count"],
118
118
  }
119
-
119
+
120
120
  # Add specific issues found
121
121
  if analysis["errors_found"]:
122
122
  details["errors_found"] = analysis["errors_found"]
123
-
123
+
124
124
  if analysis["warnings_found"]:
125
125
  details["warnings_found"] = analysis["warnings_found"]
126
-
126
+
127
127
  # Add recommendations
128
128
  if analysis["recommendations"]:
129
129
  details["recommendations"] = analysis["recommendations"]
130
-
130
+
131
131
  # Create sub-results if verbose
132
132
  sub_results = []
133
133
  if self.verbose and analysis["errors_found"]:
@@ -137,42 +137,40 @@ class StartupLogCheck(BaseDiagnosticCheck):
137
137
  category="Error",
138
138
  status=DiagnosticStatus.ERROR,
139
139
  message=error_type,
140
- details={"fix": fix}
140
+ details={"fix": fix},
141
141
  )
142
142
  )
143
-
143
+
144
144
  return DiagnosticResult(
145
145
  category=self.category,
146
146
  status=status,
147
147
  message=message,
148
148
  details=details,
149
149
  sub_results=sub_results if self.verbose else [],
150
- fix_command=self._get_fix_command(analysis)
150
+ fix_command=self._get_fix_command(analysis),
151
151
  )
152
-
152
+
153
153
  except Exception as e:
154
154
  return DiagnosticResult(
155
155
  category=self.category,
156
156
  status=DiagnosticStatus.ERROR,
157
- message=f"Startup log check failed: {str(e)}",
158
- details={"error": str(e)}
157
+ message=f"Startup log check failed: {e!s}",
158
+ details={"error": str(e)},
159
159
  )
160
-
160
+
161
161
  def _find_latest_log(self) -> Optional[Path]:
162
162
  """Find the most recent startup log file."""
163
163
  log_dir = Path.cwd() / ".claude-mpm" / "logs" / "startup"
164
-
164
+
165
165
  if not log_dir.exists():
166
166
  return None
167
-
167
+
168
168
  log_files = sorted(
169
- log_dir.glob("startup-*.log"),
170
- key=lambda p: p.stat().st_mtime,
171
- reverse=True
169
+ log_dir.glob("startup-*.log"), key=lambda p: p.stat().st_mtime, reverse=True
172
170
  )
173
-
171
+
174
172
  return log_files[0] if log_files else None
175
-
173
+
176
174
  def _analyze_log_file(self, log_file: Path) -> Dict[str, Any]:
177
175
  """Analyze the contents of a startup log file."""
178
176
  analysis = {
@@ -186,19 +184,19 @@ class StartupLogCheck(BaseDiagnosticCheck):
186
184
  "recommendations": [],
187
185
  "startup_successful": False,
188
186
  }
189
-
187
+
190
188
  try:
191
- with open(log_file, 'r', encoding='utf-8') as f:
189
+ with open(log_file, encoding="utf-8") as f:
192
190
  lines = f.readlines()
193
-
191
+
194
192
  # Extract timestamp from filename or first line
195
- match = re.search(r'(\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2})', log_file.name)
193
+ match = re.search(r"(\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2})", log_file.name)
196
194
  if match:
197
195
  timestamp_str = match.group(1)
198
196
  # Convert to readable format
199
197
  dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H-%M-%S")
200
198
  analysis["timestamp"] = dt.strftime("%Y-%m-%d %H:%M:%S")
201
-
199
+
202
200
  # Process each line
203
201
  for line in lines:
204
202
  # Count log levels
@@ -212,22 +210,22 @@ class StartupLogCheck(BaseDiagnosticCheck):
212
210
  analysis["info_count"] += 1
213
211
  elif " - DEBUG - " in line:
214
212
  analysis["debug_count"] += 1
215
-
213
+
216
214
  # Check for successful startup indicators
217
215
  if "Claude session completed successfully" in line:
218
216
  analysis["startup_successful"] = True
219
217
  elif "Starting Claude MPM session" in line:
220
218
  analysis["startup_successful"] = True # At least startup began
221
-
219
+
222
220
  # Generate recommendations based on findings
223
221
  self._generate_recommendations(analysis)
224
-
222
+
225
223
  except Exception as e:
226
224
  analysis["error_count"] += 1
227
225
  analysis["errors_found"].append(("Failed to parse log", str(e)))
228
-
226
+
229
227
  return analysis
230
-
228
+
231
229
  def _check_error_patterns(self, line: str, analysis: Dict[str, Any]) -> None:
232
230
  """Check line for known error patterns."""
233
231
  for pattern, (error_type, fix) in self.ERROR_PATTERNS.items():
@@ -236,7 +234,7 @@ class StartupLogCheck(BaseDiagnosticCheck):
236
234
  if (error_type, fix) not in analysis["errors_found"]:
237
235
  analysis["errors_found"].append((error_type, fix))
238
236
  break
239
-
237
+
240
238
  def _check_warning_patterns(self, line: str, analysis: Dict[str, Any]) -> None:
241
239
  """Check line for known warning patterns."""
242
240
  for pattern, warning_type in self.WARNING_PATTERNS.items():
@@ -245,70 +243,66 @@ class StartupLogCheck(BaseDiagnosticCheck):
245
243
  if warning_type not in analysis["warnings_found"]:
246
244
  analysis["warnings_found"].append(warning_type)
247
245
  break
248
-
246
+
249
247
  def _generate_recommendations(self, analysis: Dict[str, Any]) -> None:
250
248
  """Generate recommendations based on analysis."""
251
249
  recommendations = []
252
-
250
+
253
251
  # High error count
254
252
  if analysis["error_count"] > 5:
255
253
  recommendations.append(
256
254
  "High error count detected. Review full log for systematic issues."
257
255
  )
258
-
256
+
259
257
  # No successful startup
260
258
  if not analysis["startup_successful"] and analysis["error_count"] > 0:
261
259
  recommendations.append(
262
260
  "Startup may have failed. Check error messages above."
263
261
  )
264
-
262
+
265
263
  # Specific error recommendations
266
264
  if any("MCP" in error[0] for error in analysis["errors_found"]):
267
265
  recommendations.append(
268
266
  "MCP issues detected. Run 'claude-mpm doctor' for full diagnostics."
269
267
  )
270
-
268
+
271
269
  if any("Agent" in error[0] for error in analysis["errors_found"]):
272
270
  recommendations.append(
273
271
  "Agent issues detected. Run 'claude-mpm agents validate' to check agents."
274
272
  )
275
-
273
+
276
274
  if any("memory" in error[0].lower() for error in analysis["errors_found"]):
277
275
  recommendations.append(
278
276
  "Memory issues detected. Run 'claude-mpm cleanup-memory' to free space."
279
277
  )
280
-
278
+
281
279
  analysis["recommendations"] = recommendations
282
-
280
+
283
281
  def _determine_status(self, analysis: Dict[str, Any]) -> DiagnosticStatus:
284
282
  """Determine overall status based on analysis."""
285
283
  if analysis["error_count"] > 0:
286
284
  return DiagnosticStatus.ERROR
287
- elif analysis["warning_count"] > 3:
285
+ if analysis["warning_count"] > 3 or analysis["warning_count"] > 0:
288
286
  return DiagnosticStatus.WARNING
289
- elif analysis["warning_count"] > 0:
290
- return DiagnosticStatus.WARNING
291
- else:
292
- return DiagnosticStatus.OK
293
-
287
+ return DiagnosticStatus.OK
288
+
294
289
  def _create_message(self, analysis: Dict[str, Any]) -> str:
295
290
  """Create summary message based on analysis."""
296
291
  if analysis["error_count"] > 0:
297
292
  return f"Startup has {analysis['error_count']} error(s)"
298
- elif analysis["warning_count"] > 0:
293
+ if analysis["warning_count"] > 0:
299
294
  return f"Startup successful with {analysis['warning_count']} warning(s)"
300
- elif analysis["startup_successful"]:
295
+ if analysis["startup_successful"]:
301
296
  return "Last startup was successful"
302
- else:
303
- return "Startup log is clean"
304
-
297
+ return "Startup log is clean"
298
+
305
299
  def _get_fix_command(self, analysis: Dict[str, Any]) -> Optional[str]:
306
300
  """Get the most relevant fix command based on errors found."""
307
301
  if not analysis["errors_found"]:
308
302
  return None
309
-
303
+
310
304
  # Priority order for fix commands
311
- for error_type, fix in analysis["errors_found"]:
305
+ for _error_type, fix in analysis["errors_found"]:
312
306
  if "claude-mpm" in fix:
313
307
  # Extract claude-mpm command from fix suggestion
314
308
  match = re.search(r'(claude-mpm [^\'"\n]+)', fix)
@@ -318,5 +312,5 @@ class StartupLogCheck(BaseDiagnosticCheck):
318
312
  match = re.search(r'(pip install [^\'"\n]+)', fix)
319
313
  if match:
320
314
  return match.group(1)
321
-
322
- return None
315
+
316
+ return None
@@ -8,7 +8,7 @@ and aggregate results for reporting.
8
8
  import asyncio
9
9
  import logging
10
10
  from concurrent.futures import ThreadPoolExecutor, as_completed
11
- from typing import List, Optional, Type
11
+ from typing import List, Type
12
12
 
13
13
  from .checks import (
14
14
  AgentCheck,
@@ -27,14 +27,14 @@ from .models import DiagnosticResult, DiagnosticStatus, DiagnosticSummary
27
27
 
28
28
  class DiagnosticRunner:
29
29
  """Orchestrate diagnostic checks and aggregate results.
30
-
30
+
31
31
  WHY: Provides a single entry point for running all diagnostics with
32
32
  proper error handling, parallel execution, and result aggregation.
33
33
  """
34
-
34
+
35
35
  def __init__(self, verbose: bool = False, fix: bool = False):
36
36
  """Initialize diagnostic runner.
37
-
37
+
38
38
  Args:
39
39
  verbose: Include detailed information in results
40
40
  fix: Attempt to fix issues automatically (future feature)
@@ -42,7 +42,7 @@ class DiagnosticRunner:
42
42
  self.verbose = verbose
43
43
  self.fix = fix
44
44
  self.logger = logging.getLogger(__name__)
45
-
45
+
46
46
  # Define check order (dependencies first)
47
47
  self.check_classes: List[Type[BaseDiagnosticCheck]] = [
48
48
  InstallationCheck,
@@ -55,56 +55,56 @@ class DiagnosticRunner:
55
55
  StartupLogCheck, # Check startup logs for recent issues
56
56
  CommonIssuesCheck,
57
57
  ]
58
-
58
+
59
59
  def run_diagnostics(self) -> DiagnosticSummary:
60
60
  """Run all diagnostic checks synchronously.
61
-
61
+
62
62
  Returns:
63
63
  DiagnosticSummary with all results
64
64
  """
65
65
  summary = DiagnosticSummary()
66
-
66
+
67
67
  # Run checks in order
68
68
  for check_class in self.check_classes:
69
69
  try:
70
70
  check = check_class(verbose=self.verbose)
71
-
71
+
72
72
  # Skip if check shouldn't run
73
73
  if not check.should_run():
74
74
  self.logger.debug(f"Skipping {check.name}")
75
75
  continue
76
-
76
+
77
77
  self.logger.debug(f"Running {check.name}")
78
78
  result = check.run()
79
79
  summary.add_result(result)
80
-
80
+
81
81
  # If fix mode is enabled and there's a fix available
82
82
  if self.fix and result.has_issues and result.fix_command:
83
83
  self._attempt_fix(result)
84
-
84
+
85
85
  except Exception as e:
86
86
  self.logger.error(f"Check {check_class.__name__} failed: {e}")
87
87
  error_result = DiagnosticResult(
88
88
  category=check_class.__name__.replace("Check", ""),
89
89
  status=DiagnosticStatus.ERROR,
90
- message=f"Check failed: {str(e)}",
91
- details={"error": str(e)}
90
+ message=f"Check failed: {e!s}",
91
+ details={"error": str(e)},
92
92
  )
93
93
  summary.add_result(error_result)
94
-
94
+
95
95
  return summary
96
-
96
+
97
97
  def run_diagnostics_parallel(self) -> DiagnosticSummary:
98
98
  """Run diagnostic checks in parallel for faster execution.
99
-
99
+
100
100
  WHY: Some checks may involve I/O or network operations, running them
101
101
  in parallel can significantly speed up the overall diagnostic process.
102
-
102
+
103
103
  Returns:
104
104
  DiagnosticSummary with all results
105
105
  """
106
106
  summary = DiagnosticSummary()
107
-
107
+
108
108
  # Group checks by dependency level
109
109
  # Level 1: No dependencies
110
110
  level1 = [InstallationCheck, FilesystemCheck, ConfigurationCheck]
@@ -112,28 +112,30 @@ class DiagnosticRunner:
112
112
  level2 = [ClaudeDesktopCheck, AgentCheck, MCPCheck, MonitorCheck]
113
113
  # Level 3: Depends on others
114
114
  level3 = [CommonIssuesCheck]
115
-
115
+
116
116
  for level in [level1, level2, level3]:
117
117
  level_results = self._run_level_parallel(level)
118
118
  for result in level_results:
119
119
  summary.add_result(result)
120
-
120
+
121
121
  return summary
122
-
123
- def _run_level_parallel(self, check_classes: List[Type[BaseDiagnosticCheck]]) -> List[DiagnosticResult]:
122
+
123
+ def _run_level_parallel(
124
+ self, check_classes: List[Type[BaseDiagnosticCheck]]
125
+ ) -> List[DiagnosticResult]:
124
126
  """Run a group of checks in parallel.
125
-
127
+
126
128
  Args:
127
129
  check_classes: List of check classes to run
128
-
130
+
129
131
  Returns:
130
132
  List of DiagnosticResults
131
133
  """
132
134
  results = []
133
-
135
+
134
136
  with ThreadPoolExecutor(max_workers=len(check_classes)) as executor:
135
137
  future_to_check = {}
136
-
138
+
137
139
  for check_class in check_classes:
138
140
  try:
139
141
  check = check_class(verbose=self.verbose)
@@ -141,14 +143,18 @@ class DiagnosticRunner:
141
143
  future = executor.submit(check.run)
142
144
  future_to_check[future] = check_class.__name__
143
145
  except Exception as e:
144
- self.logger.error(f"Failed to create check {check_class.__name__}: {e}")
145
- results.append(DiagnosticResult(
146
- category=check_class.__name__.replace("Check", ""),
147
- status=DiagnosticStatus.ERROR,
148
- message=f"Check initialization failed: {str(e)}",
149
- details={"error": str(e)}
150
- ))
151
-
146
+ self.logger.error(
147
+ f"Failed to create check {check_class.__name__}: {e}"
148
+ )
149
+ results.append(
150
+ DiagnosticResult(
151
+ category=check_class.__name__.replace("Check", ""),
152
+ status=DiagnosticStatus.ERROR,
153
+ message=f"Check initialization failed: {e!s}",
154
+ details={"error": str(e)},
155
+ )
156
+ )
157
+
152
158
  for future in as_completed(future_to_check):
153
159
  check_name = future_to_check[future]
154
160
  try:
@@ -156,26 +162,28 @@ class DiagnosticRunner:
156
162
  results.append(result)
157
163
  except Exception as e:
158
164
  self.logger.error(f"Check {check_name} failed: {e}")
159
- results.append(DiagnosticResult(
160
- category=check_name.replace("Check", ""),
161
- status=DiagnosticStatus.ERROR,
162
- message=f"Check execution failed: {str(e)}",
163
- details={"error": str(e)}
164
- ))
165
-
165
+ results.append(
166
+ DiagnosticResult(
167
+ category=check_name.replace("Check", ""),
168
+ status=DiagnosticStatus.ERROR,
169
+ message=f"Check execution failed: {e!s}",
170
+ details={"error": str(e)},
171
+ )
172
+ )
173
+
166
174
  return results
167
-
175
+
168
176
  def run_specific_checks(self, check_names: List[str]) -> DiagnosticSummary:
169
177
  """Run only specific diagnostic checks.
170
-
178
+
171
179
  Args:
172
180
  check_names: List of check names to run (e.g., ["installation", "agents"])
173
-
181
+
174
182
  Returns:
175
183
  DiagnosticSummary with results from specified checks
176
184
  """
177
185
  summary = DiagnosticSummary()
178
-
186
+
179
187
  # Map check names to classes
180
188
  check_map = {
181
189
  "installation": InstallationCheck,
@@ -193,13 +201,13 @@ class DiagnosticRunner:
193
201
  "common": CommonIssuesCheck,
194
202
  "issues": CommonIssuesCheck,
195
203
  }
196
-
204
+
197
205
  for name in check_names:
198
206
  check_class = check_map.get(name.lower())
199
207
  if not check_class:
200
208
  self.logger.warning(f"Unknown check: {name}")
201
209
  continue
202
-
210
+
203
211
  try:
204
212
  check = check_class(verbose=self.verbose)
205
213
  if check.should_run():
@@ -210,38 +218,38 @@ class DiagnosticRunner:
210
218
  error_result = DiagnosticResult(
211
219
  category=check_class.__name__.replace("Check", ""),
212
220
  status=DiagnosticStatus.ERROR,
213
- message=f"Check failed: {str(e)}",
214
- details={"error": str(e)}
221
+ message=f"Check failed: {e!s}",
222
+ details={"error": str(e)},
215
223
  )
216
224
  summary.add_result(error_result)
217
-
225
+
218
226
  return summary
219
-
227
+
220
228
  def _attempt_fix(self, result: DiagnosticResult):
221
229
  """Attempt to fix an issue automatically.
222
-
230
+
223
231
  Args:
224
232
  result: DiagnosticResult with fix_command
225
233
  """
226
234
  if not result.fix_command:
227
235
  return
228
-
236
+
229
237
  self.logger.info(f"Attempting to fix: {result.message}")
230
238
  self.logger.info(f"Running: {result.fix_command}")
231
-
239
+
232
240
  # In a real implementation, this would execute the fix command
233
241
  # For now, we just log it
234
242
  # TODO: Implement actual fix execution with proper safeguards
235
-
243
+
236
244
  async def run_diagnostics_async(self) -> DiagnosticSummary:
237
245
  """Run diagnostics asynchronously (future enhancement).
238
-
246
+
239
247
  WHY: For integration with async frameworks and better performance
240
248
  with I/O-bound checks.
241
-
249
+
242
250
  Returns:
243
251
  DiagnosticSummary with all results
244
252
  """
245
253
  # Convert sync execution to async for now
246
254
  loop = asyncio.get_event_loop()
247
- return await loop.run_in_executor(None, self.run_diagnostics)
255
+ return await loop.run_in_executor(None, self.run_diagnostics)