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
@@ -29,11 +29,9 @@ class MemoryHookService(BaseService, MemoryHookInterface):
29
29
 
30
30
  async def _initialize(self) -> None:
31
31
  """Initialize the service. No special initialization needed."""
32
- pass
33
32
 
34
33
  async def _cleanup(self) -> None:
35
34
  """Cleanup service resources. No cleanup needed."""
36
- pass
37
35
 
38
36
  def register_memory_hooks(self):
39
37
  """Register memory-related hooks with the hook service.
@@ -144,68 +142,86 @@ class MemoryHookService(BaseService, MemoryHookInterface):
144
142
  """
145
143
  try:
146
144
  from claude_mpm.hooks.base_hook import HookResult
147
-
145
+
148
146
  # Extract agent_id and response from context
149
147
  agent_id = None
150
148
  response_text = None
151
-
149
+
152
150
  # Try to get agent_id from various possible locations in context
153
- if hasattr(context, 'data') and context.data:
151
+ if hasattr(context, "data") and context.data:
154
152
  data = context.data
155
-
153
+
156
154
  # Check for agent_id in various locations
157
155
  if isinstance(data, dict):
158
156
  # Try direct agent_id field
159
- agent_id = data.get('agent_id')
160
-
157
+ agent_id = data.get("agent_id")
158
+
161
159
  # Try agent_type field
162
160
  if not agent_id:
163
- agent_id = data.get('agent_type')
164
-
161
+ agent_id = data.get("agent_type")
162
+
165
163
  # Try subagent_type (for Task delegations)
166
164
  if not agent_id:
167
- agent_id = data.get('subagent_type')
168
-
165
+ agent_id = data.get("subagent_type")
166
+
169
167
  # Try tool_parameters for Task delegations
170
- if not agent_id and 'tool_parameters' in data:
171
- params = data.get('tool_parameters', {})
168
+ if not agent_id and "tool_parameters" in data:
169
+ params = data.get("tool_parameters", {})
172
170
  if isinstance(params, dict):
173
- agent_id = params.get('subagent_type')
174
-
171
+ agent_id = params.get("subagent_type")
172
+
175
173
  # Extract response text
176
- response_text = data.get('response') or data.get('result') or data.get('output')
177
-
174
+ response_text = (
175
+ data.get("response") or data.get("result") or data.get("output")
176
+ )
177
+
178
178
  # If response_text is a dict, try to get text from it
179
179
  if isinstance(response_text, dict):
180
- response_text = response_text.get('text') or response_text.get('content') or str(response_text)
181
-
180
+ response_text = (
181
+ response_text.get("text")
182
+ or response_text.get("content")
183
+ or str(response_text)
184
+ )
185
+
182
186
  # Default to PM if no agent_id found
183
187
  if not agent_id:
184
188
  agent_id = "PM"
185
189
  self.logger.debug("No agent_id found in context, defaulting to PM")
186
-
190
+
187
191
  # Only process if we have response text
188
192
  if response_text and isinstance(response_text, str):
189
193
  self.logger.debug(f"Processing memory extraction for agent: {agent_id}")
190
-
194
+
191
195
  # Import and use the memory manager
192
- from claude_mpm.services.agents.memory.agent_memory_manager import get_memory_manager
193
-
196
+ from claude_mpm.services.agents.memory.agent_memory_manager import (
197
+ get_memory_manager,
198
+ )
199
+
194
200
  try:
195
201
  memory_manager = get_memory_manager()
196
-
202
+
197
203
  # Extract and update memory
198
- success = memory_manager.extract_and_update_memory(agent_id, response_text)
199
-
204
+ success = memory_manager.extract_and_update_memory(
205
+ agent_id, response_text
206
+ )
207
+
200
208
  if success:
201
- self.logger.info(f"Successfully extracted and saved memories for {agent_id}")
209
+ self.logger.info(
210
+ f"Successfully extracted and saved memories for {agent_id}"
211
+ )
202
212
  else:
203
- self.logger.debug(f"No memories found to extract for {agent_id}")
204
-
213
+ self.logger.debug(
214
+ f"No memories found to extract for {agent_id}"
215
+ )
216
+
205
217
  except Exception as mem_error:
206
- self.logger.warning(f"Failed to extract/save memories for {agent_id}: {mem_error}")
218
+ self.logger.warning(
219
+ f"Failed to extract/save memories for {agent_id}: {mem_error}"
220
+ )
207
221
  else:
208
- self.logger.debug("No response text found in context for memory extraction")
222
+ self.logger.debug(
223
+ "No response text found in context for memory extraction"
224
+ )
209
225
 
210
226
  return HookResult(success=True, data=context.data, modified=False)
211
227
 
@@ -291,5 +307,3 @@ class MemoryHookService(BaseService, MemoryHookInterface):
291
307
  "total_hooks": len(self.registered_hooks),
292
308
  "status": "active" if self.registered_hooks else "inactive",
293
309
  }
294
-
295
-
@@ -3,7 +3,7 @@
3
3
  WHY: The Monitor UI needs its own build tracking separate from the main MPM build
4
4
  number to track UI-specific changes and deployments independently.
5
5
 
6
- DESIGN DECISION:
6
+ DESIGN DECISION:
7
7
  - Uses atomic file operations for thread-safe build number management
8
8
  - Stores build number in MONITOR_BUILD file at project root
9
9
  - Formats as 4-digit zero-padded strings (0001, 0002, etc.)
@@ -11,7 +11,6 @@ DESIGN DECISION:
11
11
  """
12
12
 
13
13
  import asyncio
14
- import fcntl
15
14
  import json
16
15
  import os
17
16
  import tempfile
@@ -24,67 +23,68 @@ from claude_mpm.core.logger import get_logger
24
23
 
25
24
  class MonitorBuildService(BaseService):
26
25
  """Service for managing Monitor UI build numbers.
27
-
26
+
28
27
  WHY: Separate build tracking allows the Monitor UI to evolve independently
29
28
  of the main MPM framework, enabling rapid UI iterations without affecting
30
29
  core framework versioning.
31
30
  """
32
-
31
+
33
32
  # Default values
34
33
  DEFAULT_BUILD_NUMBER = 1
35
34
  DEFAULT_VERSION = "1.0.0"
36
35
  BUILD_FILE_NAME = "MONITOR_BUILD"
37
-
36
+
38
37
  def __init__(self):
39
38
  """Initialize the monitor build service."""
40
39
  super().__init__(name="monitor_build_service")
41
40
  self.logger = get_logger(self.__class__.__name__)
42
-
41
+
43
42
  # Determine build file location
44
43
  self._build_file_path = self._get_build_file_path()
45
-
44
+
46
45
  # Cache for build info to reduce file I/O
47
46
  self._cached_build_info: Optional[Dict[str, Any]] = None
48
47
  self._cache_lock = asyncio.Lock()
49
-
48
+
50
49
  def _get_build_file_path(self) -> Path:
51
50
  """Get the path to the MONITOR_BUILD file.
52
-
51
+
53
52
  WHY: Centralizes build file location logic, checking multiple
54
53
  possible locations to support different installation scenarios.
55
-
54
+
56
55
  Returns:
57
56
  Path to the MONITOR_BUILD file
58
57
  """
59
58
  # Try project root first (development)
60
59
  try:
61
60
  from claude_mpm.config.paths import paths
61
+
62
62
  build_file = paths.project_root / self.BUILD_FILE_NAME
63
63
  if build_file.parent.exists():
64
64
  return build_file
65
65
  except ImportError:
66
66
  pass
67
-
67
+
68
68
  # Fallback to package root
69
69
  package_root = Path(__file__).parent.parent.parent
70
70
  return package_root / self.BUILD_FILE_NAME
71
-
71
+
72
72
  async def _initialize(self) -> None:
73
73
  """Initialize the service and ensure build file exists.
74
-
74
+
75
75
  WHY: Ensures the build file exists with default values on first run,
76
76
  preventing errors and providing a clean starting point.
77
77
  """
78
78
  await self._ensure_build_file_exists()
79
79
  await self._load_build_info()
80
-
80
+
81
81
  async def _cleanup(self) -> None:
82
82
  """Cleanup service resources."""
83
83
  self._cached_build_info = None
84
-
84
+
85
85
  async def _ensure_build_file_exists(self) -> None:
86
86
  """Ensure the MONITOR_BUILD file exists with default values.
87
-
87
+
88
88
  WHY: Atomic file creation prevents race conditions when multiple
89
89
  processes might try to create the file simultaneously.
90
90
  """
@@ -92,17 +92,17 @@ class MonitorBuildService(BaseService):
92
92
  default_info = {
93
93
  "build_number": self.DEFAULT_BUILD_NUMBER,
94
94
  "version": self.DEFAULT_VERSION,
95
- "last_updated": None
95
+ "last_updated": None,
96
96
  }
97
97
  await self._write_build_info(default_info)
98
98
  self.logger.info(f"Created MONITOR_BUILD file at {self._build_file_path}")
99
-
99
+
100
100
  async def _load_build_info(self) -> Dict[str, Any]:
101
101
  """Load build information from file.
102
-
102
+
103
103
  WHY: Centralizes file reading with error handling and caching
104
104
  to improve performance and reliability.
105
-
105
+
106
106
  Returns:
107
107
  Dictionary with build information
108
108
  """
@@ -110,7 +110,7 @@ class MonitorBuildService(BaseService):
110
110
  try:
111
111
  if self._build_file_path.exists():
112
112
  content = self._build_file_path.read_text().strip()
113
-
113
+
114
114
  # Try to parse as JSON first
115
115
  try:
116
116
  self._cached_build_info = json.loads(content)
@@ -121,95 +121,94 @@ class MonitorBuildService(BaseService):
121
121
  self._cached_build_info = {
122
122
  "build_number": build_num,
123
123
  "version": self.DEFAULT_VERSION,
124
- "last_updated": None
124
+ "last_updated": None,
125
125
  }
126
126
  except ValueError:
127
127
  # Invalid content, use defaults
128
128
  self._cached_build_info = {
129
129
  "build_number": self.DEFAULT_BUILD_NUMBER,
130
130
  "version": self.DEFAULT_VERSION,
131
- "last_updated": None
131
+ "last_updated": None,
132
132
  }
133
133
  else:
134
134
  self._cached_build_info = {
135
135
  "build_number": self.DEFAULT_BUILD_NUMBER,
136
136
  "version": self.DEFAULT_VERSION,
137
- "last_updated": None
137
+ "last_updated": None,
138
138
  }
139
139
  except Exception as e:
140
140
  self.logger.error(f"Error loading build info: {e}")
141
141
  self._cached_build_info = {
142
142
  "build_number": self.DEFAULT_BUILD_NUMBER,
143
143
  "version": self.DEFAULT_VERSION,
144
- "last_updated": None
144
+ "last_updated": None,
145
145
  }
146
-
146
+
147
147
  return self._cached_build_info
148
-
148
+
149
149
  async def _write_build_info(self, info: Dict[str, Any]) -> None:
150
150
  """Write build information to file atomically.
151
-
151
+
152
152
  WHY: Atomic writes prevent file corruption if the process is
153
153
  interrupted during the write operation.
154
-
154
+
155
155
  Args:
156
156
  info: Build information dictionary
157
157
  """
158
158
  # Add timestamp
159
159
  from datetime import datetime
160
+
160
161
  info["last_updated"] = datetime.utcnow().isoformat()
161
-
162
+
162
163
  # Write atomically using temp file and rename
163
164
  temp_fd, temp_path = tempfile.mkstemp(
164
- dir=self._build_file_path.parent,
165
- prefix=".monitor_build_",
166
- suffix=".tmp"
165
+ dir=self._build_file_path.parent, prefix=".monitor_build_", suffix=".tmp"
167
166
  )
168
-
167
+
169
168
  try:
170
169
  # Write JSON content
171
- with os.fdopen(temp_fd, 'w') as f:
170
+ with os.fdopen(temp_fd, "w") as f:
172
171
  json.dump(info, f, indent=2)
173
-
172
+
174
173
  # Atomic rename
175
174
  Path(temp_path).replace(self._build_file_path)
176
-
175
+
177
176
  # Update cache
178
177
  async with self._cache_lock:
179
178
  self._cached_build_info = info
180
-
179
+
181
180
  except Exception as e:
182
181
  # Clean up temp file on error
183
182
  Path(temp_path).unlink(missing_ok=True)
184
183
  raise e
185
-
184
+
186
185
  async def get_build_number(self) -> int:
187
186
  """Get the current monitor build number.
188
-
187
+
189
188
  Returns:
190
189
  Current build number as integer
191
190
  """
192
191
  info = await self._load_build_info()
193
192
  return info.get("build_number", self.DEFAULT_BUILD_NUMBER)
194
-
193
+
195
194
  async def get_formatted_build_number(self) -> str:
196
195
  """Get the current build number as a 4-digit string.
197
-
196
+
198
197
  WHY: Consistent 4-digit formatting ensures proper sorting
199
198
  and display alignment in the UI.
200
-
199
+
201
200
  Returns:
202
201
  Build number as 4-digit zero-padded string
203
202
  """
204
203
  build_num = await self.get_build_number()
205
204
  return f"{build_num:04d}"
206
-
205
+
207
206
  async def increment_build_number(self) -> int:
208
207
  """Increment and return the new build number.
209
-
208
+
210
209
  WHY: Atomic increment operation ensures no build numbers are
211
210
  skipped or duplicated even with concurrent access.
212
-
211
+
213
212
  Returns:
214
213
  New build number after incrementing
215
214
  """
@@ -217,22 +216,22 @@ class MonitorBuildService(BaseService):
217
216
  new_build = info.get("build_number", self.DEFAULT_BUILD_NUMBER) + 1
218
217
  info["build_number"] = new_build
219
218
  await self._write_build_info(info)
220
-
219
+
221
220
  self.logger.info(f"Monitor build number incremented to {new_build:04d}")
222
221
  return new_build
223
-
222
+
224
223
  async def get_monitor_version(self) -> str:
225
224
  """Get the monitor UI version.
226
-
225
+
227
226
  Returns:
228
227
  Monitor UI semantic version string
229
228
  """
230
229
  info = await self._load_build_info()
231
230
  return info.get("version", self.DEFAULT_VERSION)
232
-
231
+
233
232
  async def set_monitor_version(self, version: str) -> None:
234
233
  """Set the monitor UI version.
235
-
234
+
236
235
  Args:
237
236
  version: New semantic version string
238
237
  """
@@ -240,67 +239,72 @@ class MonitorBuildService(BaseService):
240
239
  info["version"] = version
241
240
  await self._write_build_info(info)
242
241
  self.logger.info(f"Monitor version updated to {version}")
243
-
242
+
244
243
  async def get_full_version_string(self) -> str:
245
244
  """Get the full version string for display.
246
-
245
+
247
246
  WHY: Combines semantic version with build number for complete
248
247
  version identification in the UI.
249
-
248
+
250
249
  Returns:
251
250
  Full version string (e.g., "v1.0.0-0001")
252
251
  """
253
252
  version = await self.get_monitor_version()
254
253
  build = await self.get_formatted_build_number()
255
254
  return f"v{version}-{build}"
256
-
255
+
257
256
  async def get_build_info(self) -> Dict[str, Any]:
258
257
  """Get complete build information.
259
-
258
+
260
259
  WHY: Provides all build metadata in a single call for
261
260
  efficient transmission to the UI via SocketIO.
262
-
261
+
263
262
  Returns:
264
263
  Dictionary with all build information
265
264
  """
266
265
  info = await self._load_build_info()
267
-
266
+
268
267
  # Get MPM version info
269
268
  mpm_version = "unknown"
270
269
  mpm_build = "unknown"
271
-
270
+
272
271
  try:
273
272
  from claude_mpm.services.version_service import VersionService
273
+
274
274
  version_service = VersionService()
275
275
  version_info = version_service.get_version_info()
276
276
  mpm_version = version_info.get("base_version", "unknown")
277
277
  mpm_build = version_info.get("build_number", "unknown")
278
278
  except Exception as e:
279
279
  self.logger.debug(f"Could not get MPM version info: {e}")
280
-
280
+
281
281
  return {
282
282
  "monitor": {
283
283
  "version": info.get("version", self.DEFAULT_VERSION),
284
284
  "build": info.get("build_number", self.DEFAULT_BUILD_NUMBER),
285
285
  "formatted_build": f"{info.get('build_number', self.DEFAULT_BUILD_NUMBER):04d}",
286
286
  "full_version": await self.get_full_version_string(),
287
- "last_updated": info.get("last_updated")
287
+ "last_updated": info.get("last_updated"),
288
288
  },
289
289
  "mpm": {
290
290
  "version": mpm_version,
291
291
  "build": mpm_build,
292
- "full_version": f"v{mpm_version}-build.{mpm_build}" if mpm_build != "unknown" else f"v{mpm_version}"
293
- }
292
+ "full_version": (
293
+ f"v{mpm_version}-build.{mpm_build}"
294
+ if mpm_build != "unknown"
295
+ else f"v{mpm_version}"
296
+ ),
297
+ },
294
298
  }
295
-
299
+
296
300
  # Synchronous convenience methods for non-async contexts
297
-
301
+
298
302
  def get_build_number_sync(self) -> int:
299
303
  """Synchronous version of get_build_number.
300
-
304
+
301
305
  WHY: Some contexts (like SocketIO handlers) may not support
302
306
  async operations directly.
303
-
307
+
304
308
  Returns:
305
309
  Current build number as integer
306
310
  """
@@ -309,13 +313,13 @@ class MonitorBuildService(BaseService):
309
313
  return loop.run_until_complete(self.get_build_number())
310
314
  finally:
311
315
  loop.close()
312
-
316
+
313
317
  def get_build_info_sync(self) -> Dict[str, Any]:
314
318
  """Synchronous version of get_build_info.
315
-
319
+
316
320
  WHY: SocketIO connection handlers often need synchronous
317
321
  access to build information.
318
-
322
+
319
323
  Returns:
320
324
  Dictionary with all build information
321
325
  """
@@ -332,14 +336,14 @@ _monitor_build_service: Optional[MonitorBuildService] = None
332
336
 
333
337
  def get_monitor_build_service() -> MonitorBuildService:
334
338
  """Get or create the global monitor build service instance.
335
-
339
+
336
340
  WHY: Singleton pattern ensures consistent build number management
337
341
  across the application.
338
-
342
+
339
343
  Returns:
340
344
  The global MonitorBuildService instance
341
345
  """
342
346
  global _monitor_build_service
343
347
  if _monitor_build_service is None:
344
348
  _monitor_build_service = MonitorBuildService()
345
- return _monitor_build_service
349
+ return _monitor_build_service