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.
Files changed (357) 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/imagemagick.json +256 -0
  18. claude_mpm/agents/templates/qa.json +41 -2
  19. claude_mpm/agents/templates/ticketing.json +5 -5
  20. claude_mpm/agents/templates/web_qa.json +50 -2
  21. claude_mpm/cli/__init__.py +51 -46
  22. claude_mpm/cli/__main__.py +1 -1
  23. claude_mpm/cli/commands/__init__.py +10 -12
  24. claude_mpm/cli/commands/agent_manager.py +186 -181
  25. claude_mpm/cli/commands/agents.py +271 -268
  26. claude_mpm/cli/commands/aggregate.py +30 -29
  27. claude_mpm/cli/commands/cleanup.py +50 -44
  28. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  29. claude_mpm/cli/commands/config.py +162 -127
  30. claude_mpm/cli/commands/doctor.py +52 -62
  31. claude_mpm/cli/commands/info.py +37 -25
  32. claude_mpm/cli/commands/mcp.py +3 -7
  33. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  34. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  35. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  36. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  37. claude_mpm/cli/commands/memory.py +192 -141
  38. claude_mpm/cli/commands/monitor.py +117 -88
  39. claude_mpm/cli/commands/run.py +120 -84
  40. claude_mpm/cli/commands/run_config_checker.py +4 -5
  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 +204 -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 +20 -23
  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 +581 -280
  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 -15
  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 +93 -38
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  117. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  118. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  119. claude_mpm/hooks/memory_integration_hook.py +5 -5
  120. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  121. claude_mpm/hooks/validation_hooks.py +4 -4
  122. claude_mpm/init.py +4 -9
  123. claude_mpm/models/__init__.py +2 -2
  124. claude_mpm/models/agent_session.py +11 -14
  125. claude_mpm/scripts/mcp_server.py +20 -11
  126. claude_mpm/scripts/mcp_wrapper.py +5 -5
  127. claude_mpm/scripts/mpm_doctor.py +321 -0
  128. claude_mpm/scripts/socketio_daemon.py +28 -25
  129. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  130. claude_mpm/scripts/socketio_server_manager.py +116 -95
  131. claude_mpm/services/__init__.py +49 -49
  132. claude_mpm/services/agent_capabilities_service.py +12 -18
  133. claude_mpm/services/agents/__init__.py +22 -22
  134. claude_mpm/services/agents/agent_builder.py +140 -119
  135. claude_mpm/services/agents/deployment/__init__.py +3 -3
  136. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  137. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  138. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  139. claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
  140. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  141. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  142. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  143. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  144. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  145. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  146. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  147. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  148. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  149. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  150. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  151. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  152. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  153. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  154. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  155. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  156. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  157. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  158. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  159. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  160. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  161. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  162. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  163. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  164. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  165. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  166. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  167. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  168. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  169. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  170. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  171. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  172. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  173. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  174. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  175. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  176. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  177. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  178. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  179. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  180. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  181. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  182. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  183. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  184. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  185. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  186. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  187. claude_mpm/services/agents/loading/__init__.py +1 -1
  188. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  189. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  190. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  191. claude_mpm/services/agents/management/__init__.py +1 -1
  192. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  193. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  194. claude_mpm/services/agents/memory/__init__.py +4 -4
  195. claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
  196. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  197. claude_mpm/services/agents/memory/content_manager.py +44 -38
  198. claude_mpm/services/agents/memory/template_generator.py +4 -6
  199. claude_mpm/services/agents/registry/__init__.py +10 -6
  200. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  201. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  202. claude_mpm/services/async_session_logger.py +1 -2
  203. claude_mpm/services/claude_session_logger.py +1 -2
  204. claude_mpm/services/command_deployment_service.py +173 -0
  205. claude_mpm/services/command_handler_service.py +20 -22
  206. claude_mpm/services/core/__init__.py +25 -25
  207. claude_mpm/services/core/base.py +0 -5
  208. claude_mpm/services/core/interfaces/__init__.py +32 -32
  209. claude_mpm/services/core/interfaces/agent.py +0 -21
  210. claude_mpm/services/core/interfaces/communication.py +0 -27
  211. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  212. claude_mpm/services/core/interfaces/service.py +0 -29
  213. claude_mpm/services/diagnostics/__init__.py +1 -1
  214. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  215. claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
  216. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  217. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  218. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  219. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  220. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  221. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  222. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  223. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  224. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  225. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  226. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  227. claude_mpm/services/diagnostics/models.py +21 -19
  228. claude_mpm/services/event_aggregator.py +10 -17
  229. claude_mpm/services/event_bus/__init__.py +1 -1
  230. claude_mpm/services/event_bus/config.py +54 -35
  231. claude_mpm/services/event_bus/event_bus.py +76 -71
  232. claude_mpm/services/event_bus/relay.py +74 -64
  233. claude_mpm/services/events/__init__.py +11 -11
  234. claude_mpm/services/events/consumers/__init__.py +3 -3
  235. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  236. claude_mpm/services/events/consumers/logging.py +39 -37
  237. claude_mpm/services/events/consumers/metrics.py +56 -57
  238. claude_mpm/services/events/consumers/socketio.py +82 -81
  239. claude_mpm/services/events/core.py +110 -99
  240. claude_mpm/services/events/interfaces.py +56 -72
  241. claude_mpm/services/events/producers/__init__.py +1 -1
  242. claude_mpm/services/events/producers/hook.py +38 -38
  243. claude_mpm/services/events/producers/system.py +46 -44
  244. claude_mpm/services/exceptions.py +81 -80
  245. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  246. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  247. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  248. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  249. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  250. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  251. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  252. claude_mpm/services/hook_service.py +6 -9
  253. claude_mpm/services/infrastructure/__init__.py +1 -1
  254. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  255. claude_mpm/services/infrastructure/monitoring.py +21 -23
  256. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  257. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  258. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  259. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  260. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  261. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  262. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  263. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  264. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  265. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  266. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  267. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  268. claude_mpm/services/mcp_gateway/main.py +2 -1
  269. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  270. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  271. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  272. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  273. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  274. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  275. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  276. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  277. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  278. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  279. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  280. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  281. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  282. claude_mpm/services/memory/__init__.py +3 -3
  283. claude_mpm/services/memory/builder.py +3 -6
  284. claude_mpm/services/memory/cache/__init__.py +1 -1
  285. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  286. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  287. claude_mpm/services/memory/indexed_memory.py +5 -7
  288. claude_mpm/services/memory/optimizer.py +7 -10
  289. claude_mpm/services/memory/router.py +8 -9
  290. claude_mpm/services/memory_hook_service.py +48 -34
  291. claude_mpm/services/monitor_build_service.py +77 -73
  292. claude_mpm/services/port_manager.py +130 -108
  293. claude_mpm/services/project/analyzer.py +12 -10
  294. claude_mpm/services/project/registry.py +11 -11
  295. claude_mpm/services/recovery_manager.py +10 -19
  296. claude_mpm/services/response_tracker.py +0 -1
  297. claude_mpm/services/runner_configuration_service.py +19 -20
  298. claude_mpm/services/session_management_service.py +7 -11
  299. claude_mpm/services/shared/__init__.py +1 -1
  300. claude_mpm/services/shared/async_service_base.py +58 -50
  301. claude_mpm/services/shared/config_service_base.py +73 -67
  302. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  303. claude_mpm/services/shared/manager_base.py +94 -82
  304. claude_mpm/services/shared/service_factory.py +96 -98
  305. claude_mpm/services/socketio/__init__.py +3 -3
  306. claude_mpm/services/socketio/client_proxy.py +5 -5
  307. claude_mpm/services/socketio/event_normalizer.py +199 -181
  308. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  309. claude_mpm/services/socketio/handlers/base.py +5 -4
  310. claude_mpm/services/socketio/handlers/connection.py +163 -136
  311. claude_mpm/services/socketio/handlers/file.py +13 -14
  312. claude_mpm/services/socketio/handlers/git.py +12 -7
  313. claude_mpm/services/socketio/handlers/hook.py +49 -44
  314. claude_mpm/services/socketio/handlers/memory.py +0 -1
  315. claude_mpm/services/socketio/handlers/project.py +0 -1
  316. claude_mpm/services/socketio/handlers/registry.py +37 -19
  317. claude_mpm/services/socketio/migration_utils.py +98 -84
  318. claude_mpm/services/socketio/server/__init__.py +1 -1
  319. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  320. claude_mpm/services/socketio/server/core.py +65 -54
  321. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  322. claude_mpm/services/socketio/server/main.py +64 -38
  323. claude_mpm/services/socketio_client_manager.py +10 -12
  324. claude_mpm/services/subprocess_launcher_service.py +4 -7
  325. claude_mpm/services/system_instructions_service.py +13 -14
  326. claude_mpm/services/ticket_manager.py +2 -2
  327. claude_mpm/services/utility_service.py +5 -13
  328. claude_mpm/services/version_control/__init__.py +16 -16
  329. claude_mpm/services/version_control/branch_strategy.py +5 -8
  330. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  331. claude_mpm/services/version_control/git_operations.py +5 -7
  332. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  333. claude_mpm/services/version_control/version_parser.py +13 -18
  334. claude_mpm/services/version_service.py +10 -11
  335. claude_mpm/storage/__init__.py +1 -1
  336. claude_mpm/storage/state_storage.py +22 -28
  337. claude_mpm/utils/__init__.py +6 -6
  338. claude_mpm/utils/agent_dependency_loader.py +47 -33
  339. claude_mpm/utils/config_manager.py +11 -14
  340. claude_mpm/utils/dependency_cache.py +1 -1
  341. claude_mpm/utils/dependency_manager.py +13 -17
  342. claude_mpm/utils/dependency_strategies.py +8 -10
  343. claude_mpm/utils/environment_context.py +3 -9
  344. claude_mpm/utils/error_handler.py +3 -13
  345. claude_mpm/utils/file_utils.py +1 -1
  346. claude_mpm/utils/path_operations.py +8 -12
  347. claude_mpm/utils/robust_installer.py +110 -33
  348. claude_mpm/utils/subprocess_utils.py +5 -6
  349. claude_mpm/validation/agent_validator.py +3 -6
  350. claude_mpm/validation/frontmatter_validator.py +1 -1
  351. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
  352. claude_mpm-4.1.2.dist-info/RECORD +498 -0
  353. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  354. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
  355. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
  356. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
  357. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
@@ -7,26 +7,25 @@ formatting for terminal display and JSON export.
7
7
 
8
8
  import json
9
9
  import sys
10
- from typing import Dict, List, Optional
11
10
 
12
11
  from .models import DiagnosticResult, DiagnosticStatus, DiagnosticSummary
13
12
 
14
13
 
15
14
  class DoctorReporter:
16
15
  """Format and display diagnostic results.
17
-
16
+
18
17
  WHY: Consistent, user-friendly output that clearly shows system health
19
18
  status and provides actionable fixes for any issues.
20
19
  """
21
-
20
+
22
21
  # Status symbols and colors
23
22
  STATUS_SYMBOLS = {
24
23
  DiagnosticStatus.OK: "✅",
25
24
  DiagnosticStatus.WARNING: "⚠️ ",
26
25
  DiagnosticStatus.ERROR: "❌",
27
- DiagnosticStatus.SKIPPED: "⏭️ "
26
+ DiagnosticStatus.SKIPPED: "⏭️ ",
28
27
  }
29
-
28
+
30
29
  # ANSI color codes
31
30
  COLORS = {
32
31
  "reset": "\033[0m",
@@ -35,22 +34,22 @@ class DoctorReporter:
35
34
  "green": "\033[92m",
36
35
  "yellow": "\033[93m",
37
36
  "blue": "\033[94m",
38
- "gray": "\033[90m"
37
+ "gray": "\033[90m",
39
38
  }
40
-
39
+
41
40
  def __init__(self, use_color: bool = True, verbose: bool = False):
42
41
  """Initialize reporter.
43
-
42
+
44
43
  Args:
45
44
  use_color: Whether to use ANSI color codes
46
45
  verbose: Whether to include detailed information
47
46
  """
48
47
  self.use_color = use_color and sys.stdout.isatty()
49
48
  self.verbose = verbose
50
-
49
+
51
50
  def report(self, summary: DiagnosticSummary, format: str = "terminal"):
52
51
  """Generate and output diagnostic report.
53
-
52
+
54
53
  Args:
55
54
  summary: DiagnosticSummary with all results
56
55
  format: Output format ("terminal", "json", "markdown")
@@ -61,40 +60,40 @@ class DoctorReporter:
61
60
  self._report_markdown(summary)
62
61
  else:
63
62
  self._report_terminal(summary)
64
-
63
+
65
64
  def _report_terminal(self, summary: DiagnosticSummary):
66
65
  """Generate terminal-formatted report."""
67
66
  # Header
68
67
  self._print_header()
69
-
68
+
70
69
  # Results by category
71
70
  for result in summary.results:
72
71
  self._print_result(result)
73
-
72
+
74
73
  # Summary
75
74
  self._print_summary(summary)
76
-
75
+
77
76
  # Fix suggestions
78
77
  self._print_fixes(summary)
79
-
78
+
80
79
  def _print_header(self):
81
80
  """Print report header."""
82
81
  print()
83
82
  print(self._color("Claude MPM Doctor Report", "bold"))
84
83
  print("=" * 40)
85
84
  print()
86
-
85
+
87
86
  def _print_result(self, result: DiagnosticResult, indent: int = 0):
88
87
  """Print a single diagnostic result."""
89
88
  indent_str = " " * indent
90
-
89
+
91
90
  # Status symbol and category
92
91
  symbol = self.STATUS_SYMBOLS.get(result.status, "?")
93
92
  color = self._get_status_color(result.status)
94
-
93
+
95
94
  # Main result line
96
95
  line = f"{indent_str}{symbol} {result.category}: "
97
-
96
+
98
97
  if result.status == DiagnosticStatus.OK:
99
98
  line += self._color("OK", color)
100
99
  elif result.status == DiagnosticStatus.WARNING:
@@ -103,115 +102,149 @@ class DoctorReporter:
103
102
  line += self._color("Error", color)
104
103
  else:
105
104
  line += self._color("Skipped", color)
106
-
105
+
107
106
  print(line)
108
-
107
+
109
108
  # Message
110
109
  message_indent = " " + indent_str
111
110
  print(f"{message_indent}{result.message}")
112
-
111
+
113
112
  # Details (in verbose mode)
114
113
  if self.verbose and result.details:
115
114
  for key, value in result.details.items():
116
115
  if key not in ["error", "issues"]: # Skip complex fields
117
116
  print(f"{message_indent}{self._color(key, 'gray')}: {value}")
118
-
117
+
119
118
  # Fix suggestion
120
119
  if result.fix_command:
121
120
  fix_indent = " " + indent_str
122
- print(f"{fix_indent}{self._color('→ Fix:', 'blue')} Run '{result.fix_command}'")
121
+ print(
122
+ f"{fix_indent}{self._color('→ Fix:', 'blue')} Run '{result.fix_command}'"
123
+ )
123
124
  if result.fix_description:
124
125
  print(f"{fix_indent} {self._color(result.fix_description, 'gray')}")
125
-
126
+
126
127
  # Sub-results (in verbose mode)
127
128
  if self.verbose and result.sub_results:
128
129
  for sub_result in result.sub_results:
129
130
  self._print_result(sub_result, indent + 1)
130
-
131
+
131
132
  if indent == 0:
132
133
  print() # Extra line between top-level results
133
-
134
+
134
135
  def _print_summary(self, summary: DiagnosticSummary):
135
136
  """Print summary statistics."""
136
137
  print(self._color("─" * 40, "gray"))
137
-
138
- status_line = f"Summary: "
138
+
139
+ status_line = "Summary: "
139
140
  parts = []
140
-
141
+
141
142
  if summary.ok_count > 0:
142
143
  parts.append(self._color(f"{summary.ok_count} OK", "green"))
143
144
  if summary.warning_count > 0:
144
- parts.append(self._color(f"{summary.warning_count} Warning{'s' if summary.warning_count != 1 else ''}", "yellow"))
145
+ parts.append(
146
+ self._color(
147
+ f"{summary.warning_count} Warning{'s' if summary.warning_count != 1 else ''}",
148
+ "yellow",
149
+ )
150
+ )
145
151
  if summary.error_count > 0:
146
- parts.append(self._color(f"{summary.error_count} Error{'s' if summary.error_count != 1 else ''}", "red"))
152
+ parts.append(
153
+ self._color(
154
+ f"{summary.error_count} Error{'s' if summary.error_count != 1 else ''}",
155
+ "red",
156
+ )
157
+ )
147
158
  if summary.skipped_count > 0:
148
159
  parts.append(self._color(f"{summary.skipped_count} Skipped", "gray"))
149
-
160
+
150
161
  status_line += " | ".join(parts)
151
162
  print(status_line)
152
-
163
+
153
164
  # Overall health
154
165
  overall = summary.overall_status
155
166
  if overall == DiagnosticStatus.OK:
156
167
  print(self._color("\n✅ System is healthy!", "green"))
157
168
  elif overall == DiagnosticStatus.WARNING:
158
- print(self._color("\n⚠️ System has minor issues that should be addressed.", "yellow"))
169
+ print(
170
+ self._color(
171
+ "\n⚠️ System has minor issues that should be addressed.", "yellow"
172
+ )
173
+ )
159
174
  else:
160
- print(self._color("\n❌ System has critical issues that need immediate attention!", "red"))
161
-
175
+ print(
176
+ self._color(
177
+ "\n❌ System has critical issues that need immediate attention!",
178
+ "red",
179
+ )
180
+ )
181
+
162
182
  def _print_fixes(self, summary: DiagnosticSummary):
163
183
  """Print consolidated fix suggestions."""
164
184
  fixes = []
165
-
185
+
166
186
  for result in summary.results:
167
187
  if result.fix_command and result.has_issues:
168
- fixes.append((result.category, result.fix_command, result.fix_description))
169
-
188
+ fixes.append(
189
+ (result.category, result.fix_command, result.fix_description)
190
+ )
191
+
170
192
  if fixes:
171
193
  print()
172
194
  print(self._color("Suggested Fixes:", "bold"))
173
195
  print(self._color("─" * 40, "gray"))
174
-
196
+
175
197
  for i, (category, command, description) in enumerate(fixes, 1):
176
198
  print(f"{i}. {category}:")
177
199
  print(f" {self._color(command, 'blue')}")
178
200
  if description:
179
201
  print(f" {self._color(description, 'gray')}")
180
202
  print()
181
-
203
+
182
204
  if self.verbose:
183
- print(self._color("Run 'claude-mpm doctor --fix' to attempt automatic fixes", "gray"))
205
+ print(
206
+ self._color(
207
+ "Run 'claude-mpm doctor --fix' to attempt automatic fixes",
208
+ "gray",
209
+ )
210
+ )
184
211
  else:
185
- print(self._color("Run 'claude-mpm doctor --verbose' for more details", "gray"))
186
-
212
+ print(
213
+ self._color(
214
+ "Run 'claude-mpm doctor --verbose' for more details", "gray"
215
+ )
216
+ )
217
+
187
218
  def _report_json(self, summary: DiagnosticSummary):
188
219
  """Generate JSON-formatted report."""
189
220
  output = summary.to_dict()
190
-
221
+
191
222
  # Add metadata
192
223
  output["metadata"] = {
193
224
  "tool": "claude-mpm doctor",
194
225
  "version": self._get_version(),
195
- "verbose": self.verbose
226
+ "verbose": self.verbose,
196
227
  }
197
-
228
+
198
229
  # Add fix suggestions
199
230
  fixes = []
200
231
  for result in summary.results:
201
232
  if result.fix_command and result.has_issues:
202
- fixes.append({
203
- "category": result.category,
204
- "command": result.fix_command,
205
- "description": result.fix_description
206
- })
233
+ fixes.append(
234
+ {
235
+ "category": result.category,
236
+ "command": result.fix_command,
237
+ "description": result.fix_description,
238
+ }
239
+ )
207
240
  output["fixes"] = fixes
208
-
241
+
209
242
  print(json.dumps(output, indent=2))
210
-
243
+
211
244
  def _report_markdown(self, summary: DiagnosticSummary):
212
245
  """Generate Markdown-formatted report."""
213
246
  print("# Claude MPM Doctor Report\n")
214
-
247
+
215
248
  # Summary table
216
249
  print("## Summary\n")
217
250
  print("| Status | Count |")
@@ -221,31 +254,34 @@ class DoctorReporter:
221
254
  print(f"| ❌ Error | {summary.error_count} |")
222
255
  print(f"| ⏭️ Skipped | {summary.skipped_count} |")
223
256
  print()
224
-
257
+
225
258
  # Detailed results
226
259
  print("## Diagnostic Results\n")
227
-
260
+
228
261
  for result in summary.results:
229
262
  symbol = self.STATUS_SYMBOLS.get(result.status, "?")
230
263
  print(f"### {symbol} {result.category}\n")
231
264
  print(f"**Status:** {result.status.value}")
232
265
  print(f"**Message:** {result.message}\n")
233
-
266
+
234
267
  if result.fix_command:
235
268
  print(f"**Fix:** `{result.fix_command}`")
236
269
  if result.fix_description:
237
270
  print(f"_{result.fix_description}_\n")
238
-
271
+
239
272
  if self.verbose and result.details:
240
273
  print("**Details:**")
241
274
  for key, value in result.details.items():
242
275
  print(f"- {key}: {value}")
243
276
  print()
244
-
277
+
245
278
  # Fixes section
246
- fixes = [(r.category, r.fix_command, r.fix_description)
247
- for r in summary.results if r.fix_command and r.has_issues]
248
-
279
+ fixes = [
280
+ (r.category, r.fix_command, r.fix_description)
281
+ for r in summary.results
282
+ if r.fix_command and r.has_issues
283
+ ]
284
+
249
285
  if fixes:
250
286
  print("## Suggested Fixes\n")
251
287
  for category, command, description in fixes:
@@ -253,31 +289,32 @@ class DoctorReporter:
253
289
  if description:
254
290
  print(f" - {description}")
255
291
  print()
256
-
292
+
257
293
  def _color(self, text: str, color: str) -> str:
258
294
  """Apply color to text if colors are enabled."""
259
295
  if not self.use_color:
260
296
  return text
261
-
297
+
262
298
  color_code = self.COLORS.get(color, "")
263
299
  reset_code = self.COLORS["reset"]
264
300
  return f"{color_code}{text}{reset_code}"
265
-
301
+
266
302
  def _get_status_color(self, status: DiagnosticStatus) -> str:
267
303
  """Get color for a status."""
268
304
  color_map = {
269
305
  DiagnosticStatus.OK: "green",
270
306
  DiagnosticStatus.WARNING: "yellow",
271
307
  DiagnosticStatus.ERROR: "red",
272
- DiagnosticStatus.SKIPPED: "gray"
308
+ DiagnosticStatus.SKIPPED: "gray",
273
309
  }
274
310
  return color_map.get(status, "reset")
275
-
311
+
276
312
  def _get_version(self) -> str:
277
313
  """Get claude-mpm version."""
278
314
  try:
279
315
  from ..version_service import VersionService
316
+
280
317
  service = VersionService()
281
318
  return service.get_version()
282
319
  except Exception:
283
- return "unknown"
320
+ return "unknown"
@@ -12,6 +12,7 @@ from typing import Any, Dict, List, Optional
12
12
 
13
13
  class DiagnosticStatus(Enum):
14
14
  """Status levels for diagnostic results."""
15
+
15
16
  OK = "ok"
16
17
  WARNING = "warning"
17
18
  ERROR = "error"
@@ -21,18 +22,19 @@ class DiagnosticStatus(Enum):
21
22
  @dataclass
22
23
  class DiagnosticResult:
23
24
  """Result from a diagnostic check.
24
-
25
+
25
26
  WHY: Standardized result format ensures consistent reporting
26
27
  and makes it easy to aggregate and display results.
27
28
  """
29
+
28
30
  category: str # e.g., "Installation", "Agents", "MCP Server"
29
31
  status: DiagnosticStatus
30
32
  message: str
31
33
  details: Dict[str, Any] = field(default_factory=dict)
32
34
  fix_command: Optional[str] = None
33
35
  fix_description: Optional[str] = None
34
- sub_results: List['DiagnosticResult'] = field(default_factory=list)
35
-
36
+ sub_results: List["DiagnosticResult"] = field(default_factory=list)
37
+
36
38
  def to_dict(self) -> Dict[str, Any]:
37
39
  """Convert to dictionary for JSON serialization."""
38
40
  return {
@@ -42,14 +44,14 @@ class DiagnosticResult:
42
44
  "details": self.details,
43
45
  "fix_command": self.fix_command,
44
46
  "fix_description": self.fix_description,
45
- "sub_results": [r.to_dict() for r in self.sub_results]
47
+ "sub_results": [r.to_dict() for r in self.sub_results],
46
48
  }
47
-
49
+
48
50
  @property
49
51
  def has_issues(self) -> bool:
50
52
  """Check if this result indicates any issues."""
51
53
  return self.status in (DiagnosticStatus.WARNING, DiagnosticStatus.ERROR)
52
-
54
+
53
55
  @property
54
56
  def severity_level(self) -> int:
55
57
  """Get numeric severity level for sorting."""
@@ -57,7 +59,7 @@ class DiagnosticResult:
57
59
  DiagnosticStatus.OK: 0,
58
60
  DiagnosticStatus.SKIPPED: 1,
59
61
  DiagnosticStatus.WARNING: 2,
60
- DiagnosticStatus.ERROR: 3
62
+ DiagnosticStatus.ERROR: 3,
61
63
  }
62
64
  return severity_map.get(self.status, 0)
63
65
 
@@ -65,22 +67,23 @@ class DiagnosticResult:
65
67
  @dataclass
66
68
  class DiagnosticSummary:
67
69
  """Summary of all diagnostic results.
68
-
70
+
69
71
  WHY: Provides a high-level overview of system health
70
72
  and quick access to issues that need attention.
71
73
  """
74
+
72
75
  total_checks: int = 0
73
76
  ok_count: int = 0
74
77
  warning_count: int = 0
75
78
  error_count: int = 0
76
79
  skipped_count: int = 0
77
80
  results: List[DiagnosticResult] = field(default_factory=list)
78
-
81
+
79
82
  def add_result(self, result: DiagnosticResult):
80
83
  """Add a result to the summary."""
81
84
  self.results.append(result)
82
85
  self.total_checks += 1
83
-
86
+
84
87
  if result.status == DiagnosticStatus.OK:
85
88
  self.ok_count += 1
86
89
  elif result.status == DiagnosticStatus.WARNING:
@@ -89,22 +92,21 @@ class DiagnosticSummary:
89
92
  self.error_count += 1
90
93
  elif result.status == DiagnosticStatus.SKIPPED:
91
94
  self.skipped_count += 1
92
-
95
+
93
96
  @property
94
97
  def has_issues(self) -> bool:
95
98
  """Check if there are any warnings or errors."""
96
99
  return self.warning_count > 0 or self.error_count > 0
97
-
100
+
98
101
  @property
99
102
  def overall_status(self) -> DiagnosticStatus:
100
103
  """Get overall system status."""
101
104
  if self.error_count > 0:
102
105
  return DiagnosticStatus.ERROR
103
- elif self.warning_count > 0:
106
+ if self.warning_count > 0:
104
107
  return DiagnosticStatus.WARNING
105
- else:
106
- return DiagnosticStatus.OK
107
-
108
+ return DiagnosticStatus.OK
109
+
108
110
  def to_dict(self) -> Dict[str, Any]:
109
111
  """Convert to dictionary for JSON serialization."""
110
112
  return {
@@ -114,7 +116,7 @@ class DiagnosticSummary:
114
116
  "warnings": self.warning_count,
115
117
  "errors": self.error_count,
116
118
  "skipped": self.skipped_count,
117
- "overall_status": self.overall_status.value
119
+ "overall_status": self.overall_status.value,
118
120
  },
119
- "results": [r.to_dict() for r in self.results]
120
- }
121
+ "results": [r.to_dict() for r in self.results],
122
+ }
@@ -13,7 +13,6 @@ aggregator to run alongside the dashboard without any conflicts.
13
13
 
14
14
  import asyncio
15
15
  import json
16
- import os
17
16
  import signal
18
17
  import sys
19
18
  import threading
@@ -30,8 +29,10 @@ except ImportError:
30
29
  SOCKETIO_AVAILABLE = False
31
30
  socketio = None
32
31
 
32
+ import contextlib
33
+
33
34
  from ..core.logger import get_logger
34
- from ..models.agent_session import AgentSession, EventCategory
35
+ from ..models.agent_session import AgentSession
35
36
 
36
37
 
37
38
  class EventAggregator:
@@ -61,7 +62,6 @@ class EventAggregator:
61
62
  self.logger = get_logger("event_aggregator")
62
63
 
63
64
  # Load configuration using ConfigLoader
64
- from claude_mpm.core.config import Config
65
65
  from claude_mpm.core.shared.config_loader import ConfigLoader
66
66
 
67
67
  config_loader = ConfigLoader()
@@ -136,10 +136,9 @@ class EventAggregator:
136
136
  if self.connected:
137
137
  self.logger.info("Event Aggregator started successfully")
138
138
  return True
139
- else:
140
- self.logger.error("Failed to connect to Socket.IO server")
141
- self.running = False
142
- return False
139
+ self.logger.error("Failed to connect to Socket.IO server")
140
+ self.running = False
141
+ return False
143
142
 
144
143
  def stop(self):
145
144
  """Stop the aggregator service."""
@@ -151,12 +150,10 @@ class EventAggregator:
151
150
 
152
151
  # Disconnect Socket.IO client
153
152
  if self.sio_client and self.connected:
154
- try:
153
+ with contextlib.suppress(Exception):
155
154
  asyncio.run_coroutine_threadsafe(
156
155
  self.sio_client.disconnect(), self.client_loop
157
156
  ).result(timeout=2)
158
- except:
159
- pass
160
157
 
161
158
  # Stop the client thread
162
159
  if self.client_thread and self.client_thread.is_alive():
@@ -207,10 +204,8 @@ class EventAggregator:
207
204
  # Cancel cleanup task
208
205
  if self.cleanup_task:
209
206
  self.cleanup_task.cancel()
210
- try:
207
+ with contextlib.suppress(asyncio.CancelledError):
211
208
  await self.cleanup_task
212
- except asyncio.CancelledError:
213
- pass
214
209
 
215
210
  except Exception as e:
216
211
  self.logger.error(f"Connection error: {e}")
@@ -470,9 +465,7 @@ class EventAggregator:
470
465
  "sessions_completed": self.sessions_completed,
471
466
  "total_events": self.total_events_captured,
472
467
  "events_by_type": dict(self.events_by_type),
473
- "active_session_ids": [
474
- sid[:8] + "..." for sid in self.active_sessions.keys()
475
- ],
468
+ "active_session_ids": [sid[:8] + "..." for sid in self.active_sessions],
476
469
  }
477
470
 
478
471
  def list_sessions(self, limit: int = 10) -> List[Dict[str, Any]]:
@@ -496,7 +489,7 @@ class EventAggregator:
496
489
  for filepath in session_files:
497
490
  try:
498
491
  # Load just the metadata, not the full session
499
- with open(filepath, "r") as f:
492
+ with open(filepath) as f:
500
493
  data = json.load(f)
501
494
 
502
495
  sessions.append(
@@ -15,4 +15,4 @@ WHY event bus architecture:
15
15
  from .event_bus import EventBus
16
16
  from .relay import SocketIORelay
17
17
 
18
- __all__ = ["EventBus", "SocketIORelay"]
18
+ __all__ = ["EventBus", "SocketIORelay"]