claude-mpm 4.1.0__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 (358) 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 +133 -58
  21. claude_mpm/agents/templates/web_ui.json +3 -3
  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 +271 -268
  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 +192 -141
  39. claude_mpm/cli/commands/monitor.py +117 -88
  40. claude_mpm/cli/commands/run.py +120 -84
  41. claude_mpm/cli/commands/run_config_checker.py +4 -5
  42. claude_mpm/cli/commands/socketio_monitor.py +17 -19
  43. claude_mpm/cli/commands/tickets.py +92 -92
  44. claude_mpm/cli/parser.py +1 -5
  45. claude_mpm/cli/parsers/__init__.py +1 -1
  46. claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
  47. claude_mpm/cli/parsers/agents_parser.py +2 -3
  48. claude_mpm/cli/parsers/base_parser.py +7 -5
  49. claude_mpm/cli/parsers/mcp_parser.py +4 -2
  50. claude_mpm/cli/parsers/monitor_parser.py +26 -18
  51. claude_mpm/cli/shared/__init__.py +10 -10
  52. claude_mpm/cli/shared/argument_patterns.py +57 -71
  53. claude_mpm/cli/shared/base_command.py +61 -53
  54. claude_mpm/cli/shared/error_handling.py +62 -58
  55. claude_mpm/cli/shared/output_formatters.py +78 -77
  56. claude_mpm/cli/startup_logging.py +204 -172
  57. claude_mpm/cli/utils.py +10 -11
  58. claude_mpm/cli_module/__init__.py +1 -1
  59. claude_mpm/cli_module/args.py +1 -1
  60. claude_mpm/cli_module/migration_example.py +5 -5
  61. claude_mpm/config/__init__.py +9 -9
  62. claude_mpm/config/agent_config.py +15 -14
  63. claude_mpm/config/experimental_features.py +4 -4
  64. claude_mpm/config/paths.py +0 -1
  65. claude_mpm/config/socketio_config.py +5 -6
  66. claude_mpm/constants.py +1 -2
  67. claude_mpm/core/__init__.py +8 -8
  68. claude_mpm/core/agent_name_normalizer.py +1 -1
  69. claude_mpm/core/agent_registry.py +20 -23
  70. claude_mpm/core/agent_session_manager.py +3 -3
  71. claude_mpm/core/base_service.py +7 -15
  72. claude_mpm/core/cache.py +4 -6
  73. claude_mpm/core/claude_runner.py +85 -113
  74. claude_mpm/core/config.py +43 -28
  75. claude_mpm/core/config_aliases.py +0 -9
  76. claude_mpm/core/config_constants.py +52 -30
  77. claude_mpm/core/constants.py +0 -1
  78. claude_mpm/core/container.py +18 -27
  79. claude_mpm/core/exceptions.py +2 -2
  80. claude_mpm/core/factories.py +10 -12
  81. claude_mpm/core/framework_loader.py +581 -280
  82. claude_mpm/core/hook_manager.py +26 -22
  83. claude_mpm/core/hook_performance_config.py +58 -47
  84. claude_mpm/core/injectable_service.py +1 -1
  85. claude_mpm/core/interactive_session.py +61 -152
  86. claude_mpm/core/interfaces.py +1 -100
  87. claude_mpm/core/lazy.py +5 -5
  88. claude_mpm/core/log_manager.py +587 -0
  89. claude_mpm/core/logger.py +125 -8
  90. claude_mpm/core/logging_config.py +15 -15
  91. claude_mpm/core/minimal_framework_loader.py +5 -8
  92. claude_mpm/core/oneshot_session.py +15 -33
  93. claude_mpm/core/optimized_agent_loader.py +4 -6
  94. claude_mpm/core/optimized_startup.py +2 -1
  95. claude_mpm/core/output_style_manager.py +147 -106
  96. claude_mpm/core/pm_hook_interceptor.py +0 -1
  97. claude_mpm/core/service_registry.py +11 -8
  98. claude_mpm/core/session_manager.py +1 -2
  99. claude_mpm/core/shared/__init__.py +1 -1
  100. claude_mpm/core/shared/config_loader.py +101 -97
  101. claude_mpm/core/shared/path_resolver.py +72 -68
  102. claude_mpm/core/shared/singleton_manager.py +56 -50
  103. claude_mpm/core/socketio_pool.py +26 -6
  104. claude_mpm/core/tool_access_control.py +4 -5
  105. claude_mpm/core/typing_utils.py +50 -59
  106. claude_mpm/core/unified_agent_registry.py +14 -19
  107. claude_mpm/core/unified_config.py +4 -6
  108. claude_mpm/core/unified_paths.py +197 -109
  109. claude_mpm/dashboard/open_dashboard.py +2 -4
  110. claude_mpm/experimental/cli_enhancements.py +51 -36
  111. claude_mpm/generators/agent_profile_generator.py +2 -4
  112. claude_mpm/hooks/base_hook.py +1 -2
  113. claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
  114. claude_mpm/hooks/claude_hooks/event_handlers.py +93 -38
  115. claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
  116. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  117. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  118. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  119. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  120. claude_mpm/hooks/memory_integration_hook.py +5 -5
  121. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  122. claude_mpm/hooks/validation_hooks.py +4 -4
  123. claude_mpm/init.py +4 -9
  124. claude_mpm/models/__init__.py +2 -2
  125. claude_mpm/models/agent_session.py +11 -14
  126. claude_mpm/scripts/mcp_server.py +20 -11
  127. claude_mpm/scripts/mcp_wrapper.py +5 -5
  128. claude_mpm/scripts/mpm_doctor.py +321 -0
  129. claude_mpm/scripts/socketio_daemon.py +28 -25
  130. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  131. claude_mpm/scripts/socketio_server_manager.py +116 -95
  132. claude_mpm/services/__init__.py +49 -49
  133. claude_mpm/services/agent_capabilities_service.py +12 -18
  134. claude_mpm/services/agents/__init__.py +22 -22
  135. claude_mpm/services/agents/agent_builder.py +140 -119
  136. claude_mpm/services/agents/deployment/__init__.py +3 -3
  137. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  138. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  139. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  140. claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
  141. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  142. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  143. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  144. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  145. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  146. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  147. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  148. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  149. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  150. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  151. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  152. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  153. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  154. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  155. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  156. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  157. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  158. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  159. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  160. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  161. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  162. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  163. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  164. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  165. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  166. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  167. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  168. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  169. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  170. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  171. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  172. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  173. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  174. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  175. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  176. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  177. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  178. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  179. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  180. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  181. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  182. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  183. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  184. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  185. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  186. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  187. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  188. claude_mpm/services/agents/loading/__init__.py +1 -1
  189. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  190. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  191. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  192. claude_mpm/services/agents/management/__init__.py +1 -1
  193. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  194. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  195. claude_mpm/services/agents/memory/__init__.py +4 -4
  196. claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
  197. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  198. claude_mpm/services/agents/memory/content_manager.py +44 -38
  199. claude_mpm/services/agents/memory/template_generator.py +4 -6
  200. claude_mpm/services/agents/registry/__init__.py +10 -6
  201. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  202. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  203. claude_mpm/services/async_session_logger.py +1 -2
  204. claude_mpm/services/claude_session_logger.py +1 -2
  205. claude_mpm/services/command_deployment_service.py +173 -0
  206. claude_mpm/services/command_handler_service.py +20 -22
  207. claude_mpm/services/core/__init__.py +25 -25
  208. claude_mpm/services/core/base.py +0 -5
  209. claude_mpm/services/core/interfaces/__init__.py +32 -32
  210. claude_mpm/services/core/interfaces/agent.py +0 -21
  211. claude_mpm/services/core/interfaces/communication.py +0 -27
  212. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  213. claude_mpm/services/core/interfaces/service.py +0 -29
  214. claude_mpm/services/diagnostics/__init__.py +1 -1
  215. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  216. claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
  217. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  218. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  219. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  220. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  221. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  222. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  223. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  224. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  225. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  226. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  227. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  228. claude_mpm/services/diagnostics/models.py +21 -19
  229. claude_mpm/services/event_aggregator.py +10 -17
  230. claude_mpm/services/event_bus/__init__.py +1 -1
  231. claude_mpm/services/event_bus/config.py +54 -35
  232. claude_mpm/services/event_bus/event_bus.py +76 -71
  233. claude_mpm/services/event_bus/relay.py +74 -64
  234. claude_mpm/services/events/__init__.py +11 -11
  235. claude_mpm/services/events/consumers/__init__.py +3 -3
  236. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  237. claude_mpm/services/events/consumers/logging.py +39 -37
  238. claude_mpm/services/events/consumers/metrics.py +56 -57
  239. claude_mpm/services/events/consumers/socketio.py +82 -81
  240. claude_mpm/services/events/core.py +110 -99
  241. claude_mpm/services/events/interfaces.py +56 -72
  242. claude_mpm/services/events/producers/__init__.py +1 -1
  243. claude_mpm/services/events/producers/hook.py +38 -38
  244. claude_mpm/services/events/producers/system.py +46 -44
  245. claude_mpm/services/exceptions.py +81 -80
  246. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  247. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  248. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  249. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  250. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  251. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  252. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  253. claude_mpm/services/hook_service.py +6 -9
  254. claude_mpm/services/infrastructure/__init__.py +1 -1
  255. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  256. claude_mpm/services/infrastructure/monitoring.py +21 -23
  257. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  258. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  259. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  260. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  261. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  262. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  263. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  264. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  265. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  266. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  267. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  268. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  269. claude_mpm/services/mcp_gateway/main.py +2 -1
  270. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  271. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  272. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  273. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  274. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  275. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  276. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  277. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  278. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  279. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  280. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  281. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  282. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  283. claude_mpm/services/memory/__init__.py +3 -3
  284. claude_mpm/services/memory/builder.py +3 -6
  285. claude_mpm/services/memory/cache/__init__.py +1 -1
  286. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  287. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  288. claude_mpm/services/memory/indexed_memory.py +5 -7
  289. claude_mpm/services/memory/optimizer.py +7 -10
  290. claude_mpm/services/memory/router.py +8 -9
  291. claude_mpm/services/memory_hook_service.py +48 -34
  292. claude_mpm/services/monitor_build_service.py +77 -73
  293. claude_mpm/services/port_manager.py +130 -108
  294. claude_mpm/services/project/analyzer.py +12 -10
  295. claude_mpm/services/project/registry.py +11 -11
  296. claude_mpm/services/recovery_manager.py +10 -19
  297. claude_mpm/services/response_tracker.py +0 -1
  298. claude_mpm/services/runner_configuration_service.py +19 -20
  299. claude_mpm/services/session_management_service.py +7 -11
  300. claude_mpm/services/shared/__init__.py +1 -1
  301. claude_mpm/services/shared/async_service_base.py +58 -50
  302. claude_mpm/services/shared/config_service_base.py +73 -67
  303. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  304. claude_mpm/services/shared/manager_base.py +94 -82
  305. claude_mpm/services/shared/service_factory.py +96 -98
  306. claude_mpm/services/socketio/__init__.py +3 -3
  307. claude_mpm/services/socketio/client_proxy.py +5 -5
  308. claude_mpm/services/socketio/event_normalizer.py +199 -181
  309. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  310. claude_mpm/services/socketio/handlers/base.py +5 -4
  311. claude_mpm/services/socketio/handlers/connection.py +163 -136
  312. claude_mpm/services/socketio/handlers/file.py +13 -14
  313. claude_mpm/services/socketio/handlers/git.py +12 -7
  314. claude_mpm/services/socketio/handlers/hook.py +49 -44
  315. claude_mpm/services/socketio/handlers/memory.py +0 -1
  316. claude_mpm/services/socketio/handlers/project.py +0 -1
  317. claude_mpm/services/socketio/handlers/registry.py +37 -19
  318. claude_mpm/services/socketio/migration_utils.py +98 -84
  319. claude_mpm/services/socketio/server/__init__.py +1 -1
  320. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  321. claude_mpm/services/socketio/server/core.py +65 -54
  322. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  323. claude_mpm/services/socketio/server/main.py +64 -38
  324. claude_mpm/services/socketio_client_manager.py +10 -12
  325. claude_mpm/services/subprocess_launcher_service.py +4 -7
  326. claude_mpm/services/system_instructions_service.py +13 -14
  327. claude_mpm/services/ticket_manager.py +2 -2
  328. claude_mpm/services/utility_service.py +5 -13
  329. claude_mpm/services/version_control/__init__.py +16 -16
  330. claude_mpm/services/version_control/branch_strategy.py +5 -8
  331. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  332. claude_mpm/services/version_control/git_operations.py +5 -7
  333. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  334. claude_mpm/services/version_control/version_parser.py +13 -18
  335. claude_mpm/services/version_service.py +10 -11
  336. claude_mpm/storage/__init__.py +1 -1
  337. claude_mpm/storage/state_storage.py +22 -28
  338. claude_mpm/utils/__init__.py +6 -6
  339. claude_mpm/utils/agent_dependency_loader.py +47 -33
  340. claude_mpm/utils/config_manager.py +11 -14
  341. claude_mpm/utils/dependency_cache.py +1 -1
  342. claude_mpm/utils/dependency_manager.py +13 -17
  343. claude_mpm/utils/dependency_strategies.py +8 -10
  344. claude_mpm/utils/environment_context.py +3 -9
  345. claude_mpm/utils/error_handler.py +3 -13
  346. claude_mpm/utils/file_utils.py +1 -1
  347. claude_mpm/utils/path_operations.py +8 -12
  348. claude_mpm/utils/robust_installer.py +110 -33
  349. claude_mpm/utils/subprocess_utils.py +5 -6
  350. claude_mpm/validation/agent_validator.py +3 -6
  351. claude_mpm/validation/frontmatter_validator.py +1 -1
  352. {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
  353. claude_mpm-4.1.2.dist-info/RECORD +498 -0
  354. claude_mpm-4.1.0.dist-info/RECORD +0 -494
  355. {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
  356. {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
  357. {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
  358. {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
claude_mpm/core/logger.py CHANGED
@@ -11,16 +11,22 @@ import json
11
11
  import logging
12
12
  import logging.handlers
13
13
  import sys
14
+ import threading
14
15
  import time
15
16
  from collections import defaultdict
16
17
  from datetime import datetime
17
18
  from enum import Enum
18
19
  from pathlib import Path
19
- from typing import Any, Dict, List, Optional
20
+ from typing import Any, Dict, Optional
21
+
22
+ from claude_mpm.core.unified_paths import get_project_root
20
23
 
21
24
  # Rich support has been removed
22
25
  HAS_RICH = False
23
26
 
27
+ # Thread lock for symlink creation to prevent race conditions
28
+ _symlink_lock = threading.Lock()
29
+
24
30
 
25
31
  class LogLevel(Enum):
26
32
  """Log levels for different verbosity."""
@@ -225,8 +231,6 @@ def setup_logging(
225
231
  # Use default log directory
226
232
  if log_dir is None:
227
233
  # Use deployment root for logs to keep everything centralized
228
- from claude_mpm.core.unified_paths import get_project_root
229
-
230
234
  deployment_root = get_project_root()
231
235
  log_dir = deployment_root / ".claude-mpm" / "logs"
232
236
 
@@ -238,12 +242,59 @@ def setup_logging(
238
242
 
239
243
  file_handler = logging.FileHandler(log_file)
240
244
 
241
- # Also create a symlink to latest log
245
+ # Clean up old MPM logs (using configured retention count)
246
+ try:
247
+ deleted_count = cleanup_old_mpm_logs(log_dir)
248
+ if deleted_count > 0:
249
+ # Log to the new file handler that we're about to add
250
+ pass # Deletion count will be logged when logger is ready
251
+ except Exception:
252
+ pass # Ignore cleanup errors
253
+
254
+ # Also create a symlink to latest log (with thread safety)
242
255
  latest_link = log_dir / "latest.log"
243
- if latest_link.exists() and latest_link.is_symlink():
244
- latest_link.unlink()
245
- if not latest_link.exists():
246
- latest_link.symlink_to(log_file.name)
256
+
257
+ # Use a lock to prevent race conditions in concurrent environments
258
+ with _symlink_lock:
259
+ # Remove existing symlink/file if it exists
260
+ # Note: We need to handle both regular files and symlinks (including broken ones)
261
+ try:
262
+ # unlink() works for both files and symlinks, even broken ones
263
+ # This is more robust than checking exists() which returns False for broken symlinks
264
+ if latest_link.is_symlink() or latest_link.exists():
265
+ latest_link.unlink()
266
+ except (OSError, PermissionError) as e:
267
+ # Log warning but continue - symlink is nice-to-have, not critical
268
+ logger.debug(f"Could not remove existing latest.log: {e}")
269
+ except Exception as e:
270
+ # Catch any other unexpected errors
271
+ logger.debug(f"Unexpected error removing latest.log: {e}")
272
+
273
+ # Create new symlink with proper error handling
274
+ try:
275
+ # Use relative path for better portability
276
+ latest_link.symlink_to(log_file.name)
277
+ except FileExistsError:
278
+ # This can happen in race conditions - try to remove and recreate
279
+ try:
280
+ latest_link.unlink()
281
+ latest_link.symlink_to(log_file.name)
282
+ except Exception as e:
283
+ logger.debug(
284
+ f"Could not recreate latest.log symlink after FileExistsError: {e}"
285
+ )
286
+ except (OSError, NotImplementedError) as e:
287
+ # Handle platforms where symlinks aren't supported (e.g., Windows without admin)
288
+ # or filesystem doesn't support symlinks
289
+ logger.debug(f"Could not create latest.log symlink: {e}")
290
+ # Fallback: try to create a regular file with reference to actual log
291
+ try:
292
+ latest_link.write_text(f"Latest log: {log_file.name}\n")
293
+ except Exception:
294
+ pass # Silently fail - logging should not break the application
295
+ except Exception as e:
296
+ # Catch any other unexpected errors to ensure logging doesn't break
297
+ logger.debug(f"Unexpected error creating latest.log symlink: {e}")
247
298
 
248
299
  file_handler.setLevel(logging.DEBUG)
249
300
  file_handler.setFormatter(formatter if json_format else detailed_formatter)
@@ -255,6 +306,72 @@ def setup_logging(
255
306
  return logger
256
307
 
257
308
 
309
+ def cleanup_old_mpm_logs(
310
+ log_dir: Optional[Path] = None, keep_count: Optional[int] = None
311
+ ) -> int:
312
+ """
313
+ Clean up old MPM log files using time-based retention.
314
+
315
+ WHY: This function now delegates to LogManager for unified log management
316
+ with time-based retention instead of count-based.
317
+
318
+ DESIGN DECISIONS:
319
+ - Delegates to LogManager for consistency
320
+ - Uses time-based retention (48 hours default)
321
+ - Maintains backward compatibility
322
+
323
+ Args:
324
+ log_dir: Directory containing log files (defaults to .claude-mpm/logs)
325
+ keep_count: Ignored (kept for backward compatibility)
326
+
327
+ Returns:
328
+ Number of log files deleted
329
+ """
330
+ try:
331
+ from .log_manager import get_log_manager
332
+
333
+ log_manager = get_log_manager()
334
+
335
+ # Use LogManager's time-based cleanup (48 hours default)
336
+ return log_manager.cleanup_old_mpm_logs(log_dir)
337
+ except ImportError:
338
+ # Fallback to old implementation if LogManager not available
339
+ # Get retention count from configuration if not specified
340
+ if keep_count is None:
341
+ from claude_mpm.core.config_constants import ConfigConstants
342
+
343
+ keep_count = (
344
+ ConfigConstants.get_logging_setting("mpm_logs_retention_count") or 10
345
+ )
346
+ if log_dir is None:
347
+ deployment_root = get_project_root()
348
+ log_dir = deployment_root / ".claude-mpm" / "logs"
349
+
350
+ if not log_dir.exists():
351
+ return 0
352
+
353
+ # Get all MPM log files
354
+ log_files = sorted(
355
+ log_dir.glob("mpm_*.log"), key=lambda p: p.stat().st_mtime, reverse=True
356
+ ) # Newest first
357
+
358
+ if len(log_files) <= keep_count:
359
+ return 0 # Already within limit
360
+
361
+ # Delete older files beyond keep_count
362
+ deleted_count = 0
363
+ for log_file in log_files[
364
+ keep_count:
365
+ ]: # Keep only the most recent keep_count files
366
+ try:
367
+ log_file.unlink()
368
+ deleted_count += 1
369
+ except Exception:
370
+ pass # Ignore deletion errors
371
+
372
+ return deleted_count
373
+
374
+
258
375
  def get_logger(name: str) -> logging.Logger:
259
376
  """Get a logger instance."""
260
377
  return logging.getLogger(f"claude_mpm.{name}")
@@ -18,21 +18,21 @@ while maintaining backwards compatibility.
18
18
  """
19
19
 
20
20
  import functools
21
- import json
22
21
  import logging
23
22
  import time
24
23
  from contextlib import contextmanager
25
- from datetime import datetime
26
24
  from pathlib import Path
27
25
  from typing import Any, Dict, Optional, Union
28
26
 
29
27
  from claude_mpm.core.logger import (
30
28
  JsonFormatter,
31
- StreamingHandler,
32
29
  finalize_streaming_logs,
33
30
  )
34
31
  from claude_mpm.core.logger import get_logger as _get_logger
35
- from claude_mpm.core.logger import log_async_performance, log_performance
32
+ from claude_mpm.core.logger import (
33
+ log_async_performance,
34
+ log_performance,
35
+ )
36
36
  from claude_mpm.core.logger import setup_logging as _setup_logging
37
37
 
38
38
  # Standard log format for consistency
@@ -454,19 +454,19 @@ def log_with_level(
454
454
 
455
455
  # Export main functions and decorators
456
456
  __all__ = [
457
- "get_logger",
458
- "configure_logging",
459
- "log_operation",
460
- "log_performance_context",
461
- "log_function_call",
462
- "log_async_function_call",
463
- "log_with_level",
464
- "LogContext",
465
- "ContextualLogger",
466
457
  "LOGGING_STANDARDS",
467
458
  "LOG_LEVELS",
459
+ "ContextualLogger",
460
+ "LogContext",
461
+ "configure_logging",
462
+ "finalize_streaming_logs",
463
+ "get_logger",
464
+ "log_async_function_call",
465
+ "log_async_performance",
466
+ "log_function_call",
467
+ "log_operation",
468
468
  # Re-export from core.logger for backwards compatibility
469
469
  "log_performance",
470
- "log_async_performance",
471
- "finalize_streaming_logs",
470
+ "log_performance_context",
471
+ "log_with_level",
472
472
  ]
@@ -1,7 +1,8 @@
1
1
  """Minimal framework loader for better performance."""
2
2
 
3
+ import contextlib
3
4
  from pathlib import Path
4
- from typing import Any, Dict, Optional
5
+ from typing import Optional
5
6
 
6
7
  try:
7
8
  from ..core.logger import get_logger
@@ -45,18 +46,14 @@ class MinimalFrameworkLoader:
45
46
  working_claude_path = Path.cwd() / "CLAUDE.md" # Legacy support
46
47
 
47
48
  if working_instructions_path.exists():
48
- try:
49
+ with contextlib.suppress(Exception):
49
50
  working_claude = working_instructions_path.read_text()
50
- except:
51
- pass
52
51
  elif working_claude_path.exists():
53
- try:
52
+ with contextlib.suppress(Exception):
54
53
  working_claude = working_claude_path.read_text()
55
- except:
56
- pass
57
54
 
58
55
  # Build minimal framework
59
- framework = f"""# Claude MPM Framework
56
+ framework = """# Claude MPM Framework
60
57
 
61
58
  You are a multi-agent orchestrator in the Claude MPM framework.
62
59
 
@@ -4,30 +4,14 @@ This module encapsulates the logic for running one-time Claude commands,
4
4
  breaking down the monolithic run_oneshot method into focused, testable components.
5
5
  """
6
6
 
7
+ import contextlib
7
8
  import os
8
9
  import subprocess
9
10
  import time
10
11
  import uuid
11
- from logging import Logger
12
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
12
+ from typing import Any, Dict, Optional, Tuple
13
13
 
14
14
  from claude_mpm.core.logger import get_logger
15
- from claude_mpm.core.typing_utils import (
16
- ErrorResult,
17
- SessionConfig,
18
- SessionEvent,
19
- SessionId,
20
- SessionResult,
21
- SessionStatus,
22
- SuccessResult,
23
- )
24
-
25
- if TYPE_CHECKING:
26
- from claude_mpm.agents.memory.ticket_manager import TicketManager
27
- from claude_mpm.core.claude_runner import ClaudeRunner
28
- from claude_mpm.core.logger import ProjectLogger
29
- from claude_mpm.services.response_logger import ResponseLogger
30
- from claude_mpm.services.socketio_server import SocketIOClientProxy
31
15
 
32
16
 
33
17
  class OneshotSession:
@@ -154,13 +138,13 @@ class OneshotSession:
154
138
 
155
139
  # Add system instructions if available
156
140
  system_prompt = self.runner._create_system_prompt()
157
-
141
+
158
142
  # Debug: log the system prompt to check for issues
159
143
  if system_prompt:
160
144
  self.logger.debug(f"System prompt length: {len(system_prompt)}")
161
145
  if "Path.cwd()" in system_prompt or "Path(" in system_prompt:
162
146
  self.logger.warning("System prompt contains Python code references!")
163
-
147
+
164
148
  if system_prompt and system_prompt != self._get_simple_context():
165
149
  # The problem might be with insert positioning
166
150
  # Let's add system prompt differently
@@ -189,17 +173,18 @@ class OneshotSession:
189
173
  self.logger.debug(f"Running command: {' '.join(cmd[:5])}...")
190
174
  if len(cmd) > 5:
191
175
  self.logger.debug(f"Command has {len(cmd)} arguments total")
192
-
193
- result = subprocess.run(cmd, capture_output=True, text=True, env=env)
176
+
177
+ result = subprocess.run(
178
+ cmd, capture_output=True, text=True, env=env, check=False
179
+ )
194
180
 
195
181
  if result.returncode == 0:
196
182
  response = result.stdout.strip()
197
183
  self._handle_successful_response(response, prompt)
198
184
  return (True, response)
199
- else:
200
- error_msg = result.stderr or "Unknown error"
201
- self._handle_error_response(error_msg, result.returncode)
202
- return (False, error_msg)
185
+ error_msg = result.stderr or "Unknown error"
186
+ self._handle_error_response(error_msg, result.returncode)
187
+ return (False, error_msg)
203
188
 
204
189
  except subprocess.TimeoutExpired as e:
205
190
  return self._handle_timeout(e)
@@ -218,10 +203,8 @@ class OneshotSession:
218
203
  """Clean up the session and restore state."""
219
204
  # Restore original working directory
220
205
  if self.original_cwd:
221
- try:
206
+ with contextlib.suppress(Exception):
222
207
  os.chdir(self.original_cwd)
223
- except Exception:
224
- pass
225
208
 
226
209
  # Log session summary
227
210
  if self.runner.project_logger:
@@ -268,11 +251,11 @@ class OneshotSession:
268
251
  def _prepare_environment(self) -> Dict[str, str]:
269
252
  """Prepare the execution environment."""
270
253
  env = os.environ.copy()
271
-
254
+
272
255
  # Disable telemetry for Claude Code
273
256
  # This ensures Claude Code doesn't send telemetry data during runtime
274
257
  env["DISABLE_TELEMETRY"] = "1"
275
-
258
+
276
259
  return env
277
260
 
278
261
  def _build_command(self) -> list:
@@ -342,9 +325,8 @@ class OneshotSession:
342
325
  def _handle_error_response(self, error_msg: str, return_code: int) -> None:
343
326
  """Handle an error response from Claude."""
344
327
  print(f"Error: {error_msg}")
345
-
328
+
346
329
  # Debug: print full traceback if available
347
- import traceback
348
330
  if "Traceback" in error_msg or "Error:" in error_msg:
349
331
  self.logger.debug(f"Full error output:\n{error_msg}")
350
332
 
@@ -17,14 +17,13 @@ WHY optimized agent loading:
17
17
  """
18
18
 
19
19
  import asyncio
20
- import hashlib
21
20
  import json
22
21
  import threading
23
22
  import time
24
23
  from concurrent.futures import ThreadPoolExecutor, as_completed
25
- from dataclasses import dataclass, field
24
+ from dataclasses import dataclass
26
25
  from datetime import datetime
27
- from typing import Any, Dict, List, Optional, Set, Tuple
26
+ from typing import Any, Dict, List, Optional
28
27
 
29
28
  try:
30
29
  import aiofiles
@@ -34,8 +33,7 @@ except ImportError:
34
33
  AIOFILES_AVAILABLE = False
35
34
 
36
35
  from ..core.logger import get_logger
37
- from .cache import FileSystemCache, get_file_cache
38
- from .lazy import LazyService
36
+ from .cache import get_file_cache
39
37
 
40
38
 
41
39
  @dataclass
@@ -308,7 +306,7 @@ class OptimizedAgentLoader:
308
306
  self.metrics.cache_misses += 1
309
307
 
310
308
  # Read file asynchronously
311
- async with aiofiles.open(file_path, "r", encoding="utf-8") as f:
309
+ async with aiofiles.open(file_path, encoding="utf-8") as f:
312
310
  content = await f.read()
313
311
 
314
312
  # Parse in executor to avoid blocking
@@ -20,7 +20,8 @@ import sys
20
20
  import time
21
21
  from concurrent.futures import ThreadPoolExecutor
22
22
  from dataclasses import dataclass, field
23
- from typing import Any, Callable, Dict, List, Optional, Set, Tuple
23
+ from pathlib import Path
24
+ from typing import Any, Dict, List, Optional, Set
24
25
 
25
26
  from ..core.logger import get_logger
26
27
  from .cache import get_file_cache