claude-mpm 4.1.1__py3-none-any.whl → 4.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (389) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/__main__.py +1 -1
  4. claude_mpm/agents/BASE_PM.md +74 -46
  5. claude_mpm/agents/INSTRUCTIONS.md +11 -153
  6. claude_mpm/agents/WORKFLOW.md +61 -321
  7. claude_mpm/agents/__init__.py +11 -11
  8. claude_mpm/agents/agent_loader.py +23 -20
  9. claude_mpm/agents/agent_loader_integration.py +1 -1
  10. claude_mpm/agents/agents_metadata.py +27 -0
  11. claude_mpm/agents/async_agent_loader.py +5 -8
  12. claude_mpm/agents/base_agent_loader.py +36 -25
  13. claude_mpm/agents/frontmatter_validator.py +6 -6
  14. claude_mpm/agents/schema/agent_schema.json +1 -1
  15. claude_mpm/agents/system_agent_config.py +9 -9
  16. claude_mpm/agents/templates/api_qa.json +47 -2
  17. claude_mpm/agents/templates/engineer.json +33 -11
  18. claude_mpm/agents/templates/imagemagick.json +256 -0
  19. claude_mpm/agents/templates/qa.json +41 -2
  20. claude_mpm/agents/templates/ticketing.json +5 -5
  21. claude_mpm/agents/templates/web_qa.json +50 -2
  22. claude_mpm/cli/__init__.py +51 -46
  23. claude_mpm/cli/__main__.py +1 -1
  24. claude_mpm/cli/commands/__init__.py +10 -12
  25. claude_mpm/cli/commands/agent_manager.py +186 -181
  26. claude_mpm/cli/commands/agents.py +648 -1098
  27. claude_mpm/cli/commands/aggregate.py +30 -29
  28. claude_mpm/cli/commands/cleanup.py +50 -44
  29. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  30. claude_mpm/cli/commands/config.py +162 -127
  31. claude_mpm/cli/commands/doctor.py +52 -62
  32. claude_mpm/cli/commands/info.py +37 -25
  33. claude_mpm/cli/commands/mcp.py +3 -7
  34. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  35. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  36. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  37. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  38. claude_mpm/cli/commands/memory.py +339 -967
  39. claude_mpm/cli/commands/monitor.py +117 -88
  40. claude_mpm/cli/commands/run.py +233 -542
  41. claude_mpm/cli/commands/socketio_monitor.py +17 -19
  42. claude_mpm/cli/commands/tickets.py +92 -92
  43. claude_mpm/cli/parser.py +1 -5
  44. claude_mpm/cli/parsers/__init__.py +1 -1
  45. claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
  46. claude_mpm/cli/parsers/agents_parser.py +2 -3
  47. claude_mpm/cli/parsers/base_parser.py +7 -5
  48. claude_mpm/cli/parsers/mcp_parser.py +4 -2
  49. claude_mpm/cli/parsers/monitor_parser.py +26 -18
  50. claude_mpm/cli/shared/__init__.py +10 -10
  51. claude_mpm/cli/shared/argument_patterns.py +57 -71
  52. claude_mpm/cli/shared/base_command.py +61 -53
  53. claude_mpm/cli/shared/error_handling.py +62 -58
  54. claude_mpm/cli/shared/output_formatters.py +78 -77
  55. claude_mpm/cli/startup_logging.py +280 -172
  56. claude_mpm/cli/utils.py +10 -11
  57. claude_mpm/cli_module/__init__.py +1 -1
  58. claude_mpm/cli_module/args.py +1 -1
  59. claude_mpm/cli_module/migration_example.py +5 -5
  60. claude_mpm/config/__init__.py +9 -9
  61. claude_mpm/config/agent_config.py +15 -14
  62. claude_mpm/config/experimental_features.py +4 -4
  63. claude_mpm/config/paths.py +0 -1
  64. claude_mpm/config/socketio_config.py +5 -6
  65. claude_mpm/constants.py +1 -2
  66. claude_mpm/core/__init__.py +8 -8
  67. claude_mpm/core/agent_name_normalizer.py +1 -1
  68. claude_mpm/core/agent_registry.py +22 -29
  69. claude_mpm/core/agent_session_manager.py +3 -3
  70. claude_mpm/core/base_service.py +7 -15
  71. claude_mpm/core/cache.py +4 -6
  72. claude_mpm/core/claude_runner.py +85 -113
  73. claude_mpm/core/config.py +43 -28
  74. claude_mpm/core/config_aliases.py +0 -9
  75. claude_mpm/core/config_constants.py +52 -30
  76. claude_mpm/core/constants.py +0 -1
  77. claude_mpm/core/container.py +18 -27
  78. claude_mpm/core/exceptions.py +2 -2
  79. claude_mpm/core/factories.py +10 -12
  80. claude_mpm/core/framework_loader.py +500 -680
  81. claude_mpm/core/hook_manager.py +26 -22
  82. claude_mpm/core/hook_performance_config.py +58 -47
  83. claude_mpm/core/injectable_service.py +1 -1
  84. claude_mpm/core/interactive_session.py +61 -152
  85. claude_mpm/core/interfaces.py +1 -100
  86. claude_mpm/core/lazy.py +5 -5
  87. claude_mpm/core/log_manager.py +587 -0
  88. claude_mpm/core/logger.py +125 -8
  89. claude_mpm/core/logging_config.py +15 -17
  90. claude_mpm/core/minimal_framework_loader.py +5 -8
  91. claude_mpm/core/oneshot_session.py +15 -33
  92. claude_mpm/core/optimized_agent_loader.py +4 -6
  93. claude_mpm/core/optimized_startup.py +2 -1
  94. claude_mpm/core/output_style_manager.py +147 -106
  95. claude_mpm/core/pm_hook_interceptor.py +0 -1
  96. claude_mpm/core/service_registry.py +11 -8
  97. claude_mpm/core/session_manager.py +1 -2
  98. claude_mpm/core/shared/__init__.py +1 -1
  99. claude_mpm/core/shared/config_loader.py +101 -97
  100. claude_mpm/core/shared/path_resolver.py +72 -68
  101. claude_mpm/core/shared/singleton_manager.py +56 -50
  102. claude_mpm/core/socketio_pool.py +26 -6
  103. claude_mpm/core/tool_access_control.py +4 -5
  104. claude_mpm/core/typing_utils.py +50 -59
  105. claude_mpm/core/unified_agent_registry.py +14 -19
  106. claude_mpm/core/unified_config.py +4 -6
  107. claude_mpm/core/unified_paths.py +197 -109
  108. claude_mpm/dashboard/open_dashboard.py +2 -4
  109. claude_mpm/experimental/cli_enhancements.py +51 -36
  110. claude_mpm/generators/agent_profile_generator.py +2 -4
  111. claude_mpm/hooks/base_hook.py +1 -2
  112. claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
  113. claude_mpm/hooks/claude_hooks/event_handlers.py +99 -154
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +110 -720
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
  117. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
  118. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  119. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  120. claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
  121. claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
  122. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  123. claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
  124. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  125. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  126. claude_mpm/hooks/memory_integration_hook.py +5 -5
  127. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  128. claude_mpm/hooks/validation_hooks.py +4 -4
  129. claude_mpm/init.py +4 -9
  130. claude_mpm/models/__init__.py +2 -2
  131. claude_mpm/models/agent_session.py +11 -14
  132. claude_mpm/scripts/mcp_server.py +20 -11
  133. claude_mpm/scripts/mcp_wrapper.py +5 -5
  134. claude_mpm/scripts/mpm_doctor.py +321 -0
  135. claude_mpm/scripts/socketio_daemon.py +28 -25
  136. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  137. claude_mpm/scripts/socketio_server_manager.py +116 -95
  138. claude_mpm/services/__init__.py +49 -49
  139. claude_mpm/services/agent_capabilities_service.py +12 -18
  140. claude_mpm/services/agents/__init__.py +22 -22
  141. claude_mpm/services/agents/agent_builder.py +140 -119
  142. claude_mpm/services/agents/deployment/__init__.py +3 -3
  143. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  144. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  145. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  146. claude_mpm/services/agents/deployment/agent_deployment.py +129 -511
  147. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  148. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  149. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  150. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  151. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  152. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  153. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  154. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  155. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  156. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  157. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  158. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  159. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  160. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  161. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  162. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  163. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  164. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  165. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  166. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  167. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  168. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  169. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  170. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  171. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  172. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  173. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  174. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  175. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  176. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  177. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  178. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  179. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  180. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  181. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  182. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  183. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  184. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  185. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  186. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  187. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  188. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  189. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  190. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  191. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  192. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  193. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  194. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  195. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  196. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  197. claude_mpm/services/agents/loading/__init__.py +1 -1
  198. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  199. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  200. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  201. claude_mpm/services/agents/management/__init__.py +1 -1
  202. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  203. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  204. claude_mpm/services/agents/memory/__init__.py +4 -4
  205. claude_mpm/services/agents/memory/agent_memory_manager.py +157 -503
  206. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  207. claude_mpm/services/agents/memory/content_manager.py +44 -38
  208. claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
  209. claude_mpm/services/agents/memory/memory_file_service.py +103 -0
  210. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  211. claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
  212. claude_mpm/services/agents/memory/template_generator.py +4 -6
  213. claude_mpm/services/agents/registry/__init__.py +11 -7
  214. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  215. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  216. claude_mpm/services/async_session_logger.py +1 -2
  217. claude_mpm/services/claude_session_logger.py +1 -2
  218. claude_mpm/services/cli/__init__.py +18 -0
  219. claude_mpm/services/cli/agent_cleanup_service.py +407 -0
  220. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  221. claude_mpm/services/cli/agent_listing_service.py +463 -0
  222. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  223. claude_mpm/services/cli/agent_validation_service.py +589 -0
  224. claude_mpm/services/cli/dashboard_launcher.py +424 -0
  225. claude_mpm/services/cli/memory_crud_service.py +617 -0
  226. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  227. claude_mpm/services/cli/session_manager.py +513 -0
  228. claude_mpm/services/cli/socketio_manager.py +498 -0
  229. claude_mpm/services/cli/startup_checker.py +370 -0
  230. claude_mpm/services/command_deployment_service.py +173 -0
  231. claude_mpm/services/command_handler_service.py +20 -22
  232. claude_mpm/services/core/__init__.py +25 -25
  233. claude_mpm/services/core/base.py +0 -5
  234. claude_mpm/services/core/cache_manager.py +311 -0
  235. claude_mpm/services/core/interfaces/__init__.py +32 -32
  236. claude_mpm/services/core/interfaces/agent.py +0 -21
  237. claude_mpm/services/core/interfaces/communication.py +0 -27
  238. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  239. claude_mpm/services/core/interfaces/service.py +0 -29
  240. claude_mpm/services/core/memory_manager.py +637 -0
  241. claude_mpm/services/core/path_resolver.py +498 -0
  242. claude_mpm/services/core/service_container.py +520 -0
  243. claude_mpm/services/core/service_interfaces.py +436 -0
  244. claude_mpm/services/diagnostics/__init__.py +1 -1
  245. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  246. claude_mpm/services/diagnostics/checks/agent_check.py +152 -97
  247. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  248. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  249. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  250. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  251. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  252. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  253. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  254. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  255. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  256. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  257. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  258. claude_mpm/services/diagnostics/models.py +21 -19
  259. claude_mpm/services/event_aggregator.py +10 -17
  260. claude_mpm/services/event_bus/__init__.py +1 -1
  261. claude_mpm/services/event_bus/config.py +54 -35
  262. claude_mpm/services/event_bus/event_bus.py +76 -71
  263. claude_mpm/services/event_bus/relay.py +74 -64
  264. claude_mpm/services/events/__init__.py +11 -11
  265. claude_mpm/services/events/consumers/__init__.py +3 -3
  266. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  267. claude_mpm/services/events/consumers/logging.py +39 -37
  268. claude_mpm/services/events/consumers/metrics.py +56 -57
  269. claude_mpm/services/events/consumers/socketio.py +82 -81
  270. claude_mpm/services/events/core.py +110 -99
  271. claude_mpm/services/events/interfaces.py +56 -72
  272. claude_mpm/services/events/producers/__init__.py +1 -1
  273. claude_mpm/services/events/producers/hook.py +38 -38
  274. claude_mpm/services/events/producers/system.py +46 -44
  275. claude_mpm/services/exceptions.py +81 -80
  276. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  277. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  278. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  279. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  280. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  281. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  283. claude_mpm/services/hook_service.py +6 -9
  284. claude_mpm/services/infrastructure/__init__.py +1 -1
  285. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  286. claude_mpm/services/infrastructure/monitoring.py +21 -23
  287. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  288. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  289. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  290. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  291. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  292. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  293. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  294. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  295. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  296. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  297. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  298. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  299. claude_mpm/services/mcp_gateway/main.py +2 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  302. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  309. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  310. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  311. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  312. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  313. claude_mpm/services/memory/__init__.py +3 -3
  314. claude_mpm/services/memory/builder.py +3 -6
  315. claude_mpm/services/memory/cache/__init__.py +1 -1
  316. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  317. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  318. claude_mpm/services/memory/indexed_memory.py +5 -7
  319. claude_mpm/services/memory/optimizer.py +7 -10
  320. claude_mpm/services/memory/router.py +8 -9
  321. claude_mpm/services/memory_hook_service.py +48 -34
  322. claude_mpm/services/monitor_build_service.py +77 -73
  323. claude_mpm/services/port_manager.py +130 -108
  324. claude_mpm/services/project/analyzer.py +12 -10
  325. claude_mpm/services/project/registry.py +11 -11
  326. claude_mpm/services/recovery_manager.py +10 -19
  327. claude_mpm/services/response_tracker.py +0 -1
  328. claude_mpm/services/runner_configuration_service.py +19 -20
  329. claude_mpm/services/session_management_service.py +7 -11
  330. claude_mpm/services/shared/__init__.py +1 -1
  331. claude_mpm/services/shared/async_service_base.py +58 -50
  332. claude_mpm/services/shared/config_service_base.py +73 -67
  333. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  334. claude_mpm/services/shared/manager_base.py +94 -82
  335. claude_mpm/services/shared/service_factory.py +96 -98
  336. claude_mpm/services/socketio/__init__.py +3 -3
  337. claude_mpm/services/socketio/client_proxy.py +5 -5
  338. claude_mpm/services/socketio/event_normalizer.py +199 -181
  339. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  340. claude_mpm/services/socketio/handlers/base.py +5 -4
  341. claude_mpm/services/socketio/handlers/connection.py +163 -136
  342. claude_mpm/services/socketio/handlers/file.py +13 -14
  343. claude_mpm/services/socketio/handlers/git.py +12 -7
  344. claude_mpm/services/socketio/handlers/hook.py +49 -44
  345. claude_mpm/services/socketio/handlers/memory.py +0 -1
  346. claude_mpm/services/socketio/handlers/project.py +0 -1
  347. claude_mpm/services/socketio/handlers/registry.py +37 -19
  348. claude_mpm/services/socketio/migration_utils.py +98 -84
  349. claude_mpm/services/socketio/server/__init__.py +1 -1
  350. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  351. claude_mpm/services/socketio/server/core.py +65 -54
  352. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  353. claude_mpm/services/socketio/server/main.py +64 -38
  354. claude_mpm/services/socketio_client_manager.py +10 -12
  355. claude_mpm/services/subprocess_launcher_service.py +4 -7
  356. claude_mpm/services/system_instructions_service.py +13 -14
  357. claude_mpm/services/ticket_manager.py +2 -2
  358. claude_mpm/services/utility_service.py +5 -13
  359. claude_mpm/services/version_control/__init__.py +16 -16
  360. claude_mpm/services/version_control/branch_strategy.py +5 -8
  361. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  362. claude_mpm/services/version_control/git_operations.py +5 -7
  363. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  364. claude_mpm/services/version_control/version_parser.py +13 -18
  365. claude_mpm/services/version_service.py +10 -11
  366. claude_mpm/storage/__init__.py +1 -1
  367. claude_mpm/storage/state_storage.py +22 -28
  368. claude_mpm/utils/__init__.py +6 -6
  369. claude_mpm/utils/agent_dependency_loader.py +47 -33
  370. claude_mpm/utils/config_manager.py +11 -14
  371. claude_mpm/utils/dependency_cache.py +1 -1
  372. claude_mpm/utils/dependency_manager.py +13 -17
  373. claude_mpm/utils/dependency_strategies.py +8 -10
  374. claude_mpm/utils/environment_context.py +3 -9
  375. claude_mpm/utils/error_handler.py +3 -13
  376. claude_mpm/utils/file_utils.py +1 -1
  377. claude_mpm/utils/path_operations.py +8 -12
  378. claude_mpm/utils/robust_installer.py +110 -33
  379. claude_mpm/utils/subprocess_utils.py +5 -6
  380. claude_mpm/validation/agent_validator.py +3 -6
  381. claude_mpm/validation/frontmatter_validator.py +1 -1
  382. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
  383. claude_mpm-4.1.3.dist-info/RECORD +528 -0
  384. claude_mpm/cli/commands/run_config_checker.py +0 -160
  385. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  386. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
  387. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
  388. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
  389. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
@@ -15,28 +15,76 @@ DESIGN DECISIONS:
15
15
  """
16
16
 
17
17
  import logging
18
- import os
19
18
  import shutil
20
19
  import subprocess
21
20
  import sys
22
21
  from datetime import datetime
23
22
  from pathlib import Path
24
- from typing import Any, Dict, Optional, Tuple
23
+ from typing import Any, Dict, Optional
24
+
25
+ try:
26
+ import psutil
27
+
28
+ PSUTIL_AVAILABLE = True
29
+ except ImportError:
30
+ PSUTIL_AVAILABLE = False
25
31
 
26
32
  from ..core.logger import get_logger
27
33
 
28
34
 
35
+ def log_memory_stats(logger=None, prefix="Memory Usage"):
36
+ """
37
+ Log current memory statistics.
38
+
39
+ Args:
40
+ logger: Logger to use (defaults to 'cli' logger)
41
+ prefix: Prefix for the log message
42
+
43
+ Returns:
44
+ Dict with memory stats or None if psutil unavailable
45
+ """
46
+ if not PSUTIL_AVAILABLE:
47
+ return None
48
+
49
+ if logger is None:
50
+ logger = get_logger("cli")
51
+
52
+ try:
53
+ process = psutil.Process()
54
+ memory_info = process.memory_info()
55
+
56
+ # Convert to MB for readability
57
+ rss_mb = memory_info.rss / (1024 * 1024)
58
+ vms_mb = memory_info.vms / (1024 * 1024)
59
+
60
+ # Get percentage of system memory if available
61
+ try:
62
+ memory_percent = process.memory_percent()
63
+ logger.info(
64
+ f"{prefix}: RSS={rss_mb:.1f}MB, VMS={vms_mb:.1f}MB, "
65
+ f"System={memory_percent:.1f}%"
66
+ )
67
+ return {"rss_mb": rss_mb, "vms_mb": vms_mb, "percent": memory_percent}
68
+ except:
69
+ logger.info(f"{prefix}: RSS={rss_mb:.1f}MB, VMS={vms_mb:.1f}MB")
70
+ return {"rss_mb": rss_mb, "vms_mb": vms_mb, "percent": None}
71
+
72
+ except Exception as e:
73
+ logger.debug(f"Failed to get memory info: {e}")
74
+ return None
75
+
76
+
29
77
  class StartupStatusLogger:
30
78
  """Logs MCP server and monitor setup status during startup."""
31
-
79
+
32
80
  def __init__(self, logger_name: str = "startup_status"):
33
81
  """Initialize the startup status logger."""
34
82
  self.logger = get_logger(logger_name)
35
-
83
+
36
84
  def log_mcp_server_status(self) -> None:
37
85
  """
38
86
  Log MCP server installation and configuration status.
39
-
87
+
40
88
  Checks:
41
89
  - MCP server executable availability
42
90
  - MCP server version if available
@@ -48,7 +96,7 @@ class StartupStatusLogger:
48
96
  mcp_executable = self._find_mcp_executable()
49
97
  if mcp_executable:
50
98
  self.logger.info(f"MCP Server: Installed at {mcp_executable}")
51
-
99
+
52
100
  # Try to get version
53
101
  version = self._get_mcp_version(mcp_executable)
54
102
  if version:
@@ -57,20 +105,22 @@ class StartupStatusLogger:
57
105
  self.logger.info("MCP Server: Version unknown")
58
106
  else:
59
107
  self.logger.info("MCP Server: Not found in PATH")
60
-
108
+
61
109
  # Check MCP configuration in ~/.claude.json
62
110
  config_status = self._check_mcp_configuration()
63
111
  if config_status["found"]:
64
112
  self.logger.info("MCP Server: Configuration found in ~/.claude.json")
65
113
  if config_status["servers_count"] > 0:
66
- self.logger.info(f"MCP Server: {config_status['servers_count']} server(s) configured")
114
+ self.logger.info(
115
+ f"MCP Server: {config_status['servers_count']} server(s) configured"
116
+ )
67
117
  else:
68
118
  self.logger.info("MCP Server: No servers configured")
69
119
  self._log_mcp_setup_hint()
70
120
  else:
71
121
  self.logger.info("MCP Server: No configuration found in ~/.claude.json")
72
122
  self._log_mcp_setup_hint()
73
-
123
+
74
124
  # Check for claude-mpm MCP gateway status
75
125
  gateway_status = self._check_mcp_gateway_status()
76
126
  if gateway_status["configured"]:
@@ -78,20 +128,40 @@ class StartupStatusLogger:
78
128
  else:
79
129
  self.logger.info("MCP Gateway: Claude MPM gateway not configured")
80
130
  # Check if this is a pipx installation that could benefit from auto-config
81
- if self._is_pipx_installation() and not self._has_auto_config_preference():
82
- self.logger.info("MCP Gateway: Auto-configuration available for pipx users")
83
-
131
+ if (
132
+ self._is_pipx_installation()
133
+ and not self._has_auto_config_preference()
134
+ ):
135
+ self.logger.info(
136
+ "MCP Gateway: Auto-configuration available for pipx users"
137
+ )
138
+
84
139
  except Exception as e:
85
140
  self.logger.warning(f"MCP Server: Status check failed - {e}")
86
-
87
- def log_monitor_setup_status(self, monitor_mode: bool = False, websocket_port: int = 8765) -> None:
141
+
142
+ def log_memory_status(self) -> None:
143
+ """
144
+ Log current process memory usage.
145
+
146
+ Logs both RSS (Resident Set Size) and VMS (Virtual Memory Size)
147
+ to help track memory consumption and potential leaks.
148
+ """
149
+ stats = log_memory_stats(self.logger, "Memory Usage")
150
+
151
+ # Log warning if memory usage is high
152
+ if stats and stats.get("rss_mb", 0) > 500: # Warn if using more than 500MB
153
+ self.logger.warning(f"High memory usage detected: {stats['rss_mb']:.1f}MB")
154
+
155
+ def log_monitor_setup_status(
156
+ self, monitor_mode: bool = False, websocket_port: int = 8765
157
+ ) -> None:
88
158
  """
89
159
  Log monitor service initialization status.
90
-
160
+
91
161
  Args:
92
162
  monitor_mode: Whether monitor mode is enabled
93
163
  websocket_port: WebSocket port for monitoring
94
-
164
+
95
165
  Checks:
96
166
  - Monitor service initialization status
97
167
  - Which monitors are enabled/disabled
@@ -101,235 +171,246 @@ class StartupStatusLogger:
101
171
  try:
102
172
  if monitor_mode:
103
173
  self.logger.info("Monitor: Mode enabled")
104
-
174
+
105
175
  # Check SocketIO dependencies
106
176
  socketio_status = self._check_socketio_dependencies()
107
177
  if socketio_status["available"]:
108
178
  self.logger.info("Monitor: Socket.IO dependencies available")
109
179
  else:
110
- self.logger.info(f"Monitor: Socket.IO dependencies missing - {socketio_status['error']}")
111
-
180
+ self.logger.info(
181
+ f"Monitor: Socket.IO dependencies missing - {socketio_status['error']}"
182
+ )
183
+
112
184
  # Check if server is running
113
185
  server_running = self._check_socketio_server_running(websocket_port)
114
186
  if server_running:
115
- self.logger.info(f"Monitor: Socket.IO server running on port {websocket_port}")
187
+ self.logger.info(
188
+ f"Monitor: Socket.IO server running on port {websocket_port}"
189
+ )
116
190
  else:
117
- self.logger.info(f"Monitor: Socket.IO server will start on port {websocket_port}")
118
-
191
+ self.logger.info(
192
+ f"Monitor: Socket.IO server will start on port {websocket_port}"
193
+ )
194
+
119
195
  # Check response logging configuration
120
196
  logging_config = self._check_response_logging_config()
121
197
  if logging_config["enabled"]:
122
- self.logger.info(f"Monitor: Response logging enabled to {logging_config['directory']}")
198
+ self.logger.info(
199
+ f"Monitor: Response logging enabled to {logging_config['directory']}"
200
+ )
123
201
  else:
124
202
  self.logger.info("Monitor: Response logging disabled")
125
-
203
+
126
204
  else:
127
205
  self.logger.info("Monitor: Mode disabled")
128
-
206
+
129
207
  # Still check if there's an existing server running
130
208
  server_running = self._check_socketio_server_running(websocket_port)
131
209
  if server_running:
132
- self.logger.info(f"Monitor: Background Socket.IO server detected on port {websocket_port}")
133
-
210
+ self.logger.info(
211
+ f"Monitor: Background Socket.IO server detected on port {websocket_port}"
212
+ )
213
+
134
214
  except Exception as e:
135
215
  self.logger.warning(f"Monitor: Status check failed - {e}")
136
-
216
+
137
217
  def _find_mcp_executable(self) -> Optional[str]:
138
218
  """Find MCP server executable in PATH."""
139
219
  # Common MCP executable names
140
220
  executables = ["claude-mpm-mcp", "mcp", "claude-mcp"]
141
-
221
+
142
222
  for exe_name in executables:
143
223
  exe_path = shutil.which(exe_name)
144
224
  if exe_path:
145
225
  return exe_path
146
-
226
+
147
227
  # Check if it's installed as a Python package
148
228
  try:
149
229
  result = subprocess.run(
150
230
  [sys.executable, "-m", "claude_mpm.scripts.mcp_server", "--version"],
151
231
  capture_output=True,
152
232
  text=True,
153
- timeout=5
233
+ timeout=5,
234
+ check=False,
154
235
  )
155
236
  if result.returncode == 0:
156
237
  return f"{sys.executable} -m claude_mpm.scripts.mcp_server"
157
238
  except Exception:
158
239
  pass
159
-
240
+
160
241
  return None
161
-
242
+
162
243
  def _get_mcp_version(self, executable: str) -> Optional[str]:
163
244
  """Get MCP server version."""
164
245
  try:
165
246
  # Try --version flag
166
247
  result = subprocess.run(
167
- executable.split() + ["--version"],
248
+ [*executable.split(), "--version"],
168
249
  capture_output=True,
169
250
  text=True,
170
- timeout=5
251
+ timeout=5,
252
+ check=False,
171
253
  )
172
254
  if result.returncode == 0:
173
255
  # Extract version from output
174
256
  output = result.stdout.strip()
175
257
  if output:
176
258
  return output
177
-
259
+
178
260
  # Try version command
179
261
  result = subprocess.run(
180
- executable.split() + ["version"],
262
+ [*executable.split(), "version"],
181
263
  capture_output=True,
182
264
  text=True,
183
- timeout=5
265
+ timeout=5,
266
+ check=False,
184
267
  )
185
268
  if result.returncode == 0:
186
269
  output = result.stdout.strip()
187
270
  if output:
188
271
  return output
189
-
272
+
190
273
  except Exception:
191
274
  pass
192
-
275
+
193
276
  return None
194
-
277
+
195
278
  def _check_mcp_configuration(self) -> Dict[str, Any]:
196
279
  """Check MCP configuration in ~/.claude.json."""
197
280
  claude_json_path = Path.home() / ".claude.json"
198
-
199
- result = {
200
- "found": False,
201
- "servers_count": 0,
202
- "error": None
203
- }
204
-
281
+
282
+ result = {"found": False, "servers_count": 0, "error": None}
283
+
205
284
  try:
206
285
  if not claude_json_path.exists():
207
286
  return result
208
-
287
+
209
288
  import json
210
- with open(claude_json_path, 'r') as f:
289
+
290
+ with open(claude_json_path) as f:
211
291
  config = json.load(f)
212
-
292
+
213
293
  result["found"] = True
214
-
294
+
215
295
  # Check for MCP servers configuration
216
296
  mcp_config = config.get("mcpServers", {})
217
297
  result["servers_count"] = len(mcp_config)
218
-
298
+
219
299
  except Exception as e:
220
300
  result["error"] = str(e)
221
-
301
+
222
302
  return result
223
-
303
+
224
304
  def _check_mcp_gateway_status(self) -> Dict[str, Any]:
225
305
  """Check Claude MPM MCP gateway configuration status."""
226
- result = {
227
- "configured": False,
228
- "error": None
229
- }
230
-
306
+ result = {"configured": False, "error": None}
307
+
231
308
  try:
232
309
  # Check if MCP gateway startup verification is available
233
- from ..services.mcp_gateway.core.startup_verification import is_mcp_gateway_configured
310
+ from ..services.mcp_gateway.core.startup_verification import (
311
+ is_mcp_gateway_configured,
312
+ )
313
+
234
314
  result["configured"] = is_mcp_gateway_configured()
235
315
  except ImportError:
236
316
  # MCP gateway not available
237
317
  pass
238
318
  except Exception as e:
239
319
  result["error"] = str(e)
240
-
320
+
241
321
  return result
242
-
322
+
243
323
  def _check_socketio_dependencies(self) -> Dict[str, Any]:
244
324
  """Check if Socket.IO dependencies are available."""
245
- result = {
246
- "available": False,
247
- "error": None
248
- }
249
-
325
+ result = {"available": False, "error": None}
326
+
250
327
  try:
251
- import socketio
252
328
  import aiohttp
253
329
  import engineio
330
+ import socketio
331
+
254
332
  result["available"] = True
255
333
  except ImportError as e:
256
334
  result["error"] = f"Missing dependencies: {e}"
257
335
  except Exception as e:
258
336
  result["error"] = str(e)
259
-
337
+
260
338
  return result
261
-
339
+
262
340
  def _check_socketio_server_running(self, port: int) -> bool:
263
341
  """Check if Socket.IO server is running on specified port."""
264
342
  try:
265
343
  import socket
344
+
266
345
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
267
346
  s.settimeout(1)
268
- result = s.connect_ex(('localhost', port))
347
+ result = s.connect_ex(("localhost", port))
269
348
  return result == 0
270
349
  except Exception:
271
350
  return False
272
-
351
+
273
352
  def _check_response_logging_config(self) -> Dict[str, Any]:
274
353
  """Check response logging configuration."""
275
- result = {
276
- "enabled": False,
277
- "directory": None,
278
- "error": None
279
- }
280
-
354
+ result = {"enabled": False, "directory": None, "error": None}
355
+
281
356
  try:
282
357
  from ..core.shared.config_loader import ConfigLoader
283
-
358
+
284
359
  config_loader = ConfigLoader()
285
360
  config = config_loader.load_main_config()
286
-
361
+
287
362
  # Check response logging configuration
288
363
  response_logging = config.get("response_logging", {})
289
364
  result["enabled"] = response_logging.get("enabled", False)
290
-
365
+
291
366
  if result["enabled"]:
292
- log_dir = response_logging.get("session_directory", ".claude-mpm/responses")
367
+ log_dir = response_logging.get(
368
+ "session_directory", ".claude-mpm/responses"
369
+ )
293
370
  if not Path(log_dir).is_absolute():
294
371
  log_dir = Path.cwd() / log_dir
295
372
  result["directory"] = str(log_dir)
296
-
373
+
297
374
  except Exception as e:
298
375
  result["error"] = str(e)
299
-
376
+
300
377
  return result
301
-
378
+
302
379
  def _is_pipx_installation(self) -> bool:
303
380
  """Check if this is a pipx installation."""
304
381
  try:
305
382
  # Check if running from pipx
306
383
  if "pipx" in sys.executable.lower():
307
384
  return True
308
-
385
+
309
386
  # Check module path
310
387
  import claude_mpm
388
+
311
389
  module_path = Path(claude_mpm.__file__).parent
312
390
  if "pipx" in str(module_path):
313
391
  return True
314
392
  except Exception:
315
393
  pass
316
-
394
+
317
395
  return False
318
-
396
+
319
397
  def _has_auto_config_preference(self) -> bool:
320
398
  """Check if user has already been asked about auto-configuration."""
321
399
  try:
322
400
  from ..config.paths import paths
323
- preference_file = paths.claude_mpm_dir_hidden / "mcp_auto_config_preference.json"
401
+
402
+ preference_file = (
403
+ paths.claude_mpm_dir_hidden / "mcp_auto_config_preference.json"
404
+ )
324
405
  return preference_file.exists()
325
406
  except Exception:
326
407
  return False
327
-
408
+
328
409
  def _log_mcp_setup_hint(self) -> None:
329
410
  """Log helpful hints for MCP setup."""
330
411
  # Check if installed via pipx
331
412
  is_pipx = self._check_pipx_installation()
332
-
413
+
333
414
  if is_pipx:
334
415
  self.logger.info("💡 TIP: It looks like you installed claude-mpm via pipx")
335
416
  self.logger.info(" To configure MCP for Claude Code with pipx:")
@@ -341,198 +422,225 @@ class StartupStatusLogger:
341
422
  self.logger.info(" 1. See docs/MCP_SETUP.md for setup instructions")
342
423
  self.logger.info(" 2. Run: claude-mpm doctor --check mcp to verify")
343
424
  self.logger.info(" 3. Restart Claude Code after configuration")
344
-
425
+
345
426
  def _check_pipx_installation(self) -> bool:
346
427
  """Check if claude-mpm was installed via pipx."""
347
428
  try:
348
429
  # Check if running from a pipx venv
349
430
  if "pipx" in sys.executable.lower():
350
431
  return True
351
-
432
+
352
433
  # Check if claude-mpm-mcp command exists and is from pipx
353
434
  mcp_cmd = shutil.which("claude-mpm-mcp")
354
435
  if mcp_cmd and "pipx" in mcp_cmd.lower():
355
436
  return True
356
-
437
+
357
438
  # Try to check pipx list
358
439
  result = subprocess.run(
359
- ["pipx", "list"],
360
- capture_output=True,
361
- text=True,
362
- timeout=2
440
+ ["pipx", "list"], capture_output=True, text=True, timeout=2, check=False
363
441
  )
364
442
  if result.returncode == 0 and "claude-mpm" in result.stdout:
365
443
  return True
366
-
444
+
367
445
  except Exception:
368
446
  pass
369
-
447
+
370
448
  return False
371
449
 
372
450
 
373
451
  def setup_startup_logging(project_root: Optional[Path] = None) -> Path:
374
452
  """
375
453
  Set up logging to both console and file for startup.
376
-
454
+
377
455
  WHY: Capture all startup logs (INFO, WARNING, ERROR, DEBUG) to timestamped
378
456
  files for later analysis by the doctor command. This helps diagnose
379
457
  startup issues that users may not notice in the console output.
380
-
458
+
381
459
  DESIGN DECISIONS:
382
460
  - Use ISO-like timestamp format for easy sorting and reading
383
461
  - Store in .claude-mpm/logs/startup/ directory
384
462
  - Keep all historical startup logs for pattern analysis
385
463
  - Add file handler to root logger to capture ALL module logs
386
-
464
+
387
465
  Args:
388
466
  project_root: Root directory for the project (defaults to cwd)
389
-
467
+
390
468
  Returns:
391
469
  Path to the created log file
392
470
  """
393
471
  if project_root is None:
394
472
  project_root = Path.cwd()
395
-
473
+
396
474
  # Create log directory
397
475
  log_dir = project_root / ".claude-mpm" / "logs" / "startup"
398
476
  log_dir.mkdir(parents=True, exist_ok=True)
399
-
477
+
400
478
  # Generate timestamp for log file
401
479
  timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
402
480
  log_file = log_dir / f"startup-{timestamp}.log"
403
-
481
+
404
482
  # Create file handler with detailed formatting
405
- file_handler = logging.FileHandler(log_file, encoding='utf-8')
483
+ file_handler = logging.FileHandler(log_file, encoding="utf-8")
406
484
  file_handler.setLevel(logging.DEBUG) # Capture all levels to file
407
-
485
+
408
486
  # Format with timestamp, logger name, level, and message
409
487
  formatter = logging.Formatter(
410
- '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
411
- datefmt='%Y-%m-%d %H:%M:%S'
488
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
489
+ datefmt="%Y-%m-%d %H:%M:%S",
412
490
  )
413
491
  file_handler.setFormatter(formatter)
414
-
492
+
415
493
  # Add to claude_mpm logger to capture all our logs
416
494
  # (Don't add to root logger to avoid duplicates from propagation)
417
495
  claude_logger = logging.getLogger("claude_mpm")
418
496
  claude_logger.addHandler(file_handler)
419
497
  claude_logger.setLevel(logging.DEBUG) # Ensure all levels are captured
420
-
498
+
421
499
  # Log startup header
422
500
  logger = get_logger("startup")
423
- logger.info("="*60)
501
+ logger.info("=" * 60)
424
502
  logger.info(f"Claude MPM Startup - {datetime.now().isoformat()}")
425
503
  logger.info(f"Log file: {log_file}")
426
- logger.info("="*60)
427
-
504
+ logger.info("=" * 60)
505
+
428
506
  # Log system information
429
507
  logger.info(f"Python: {sys.version}")
430
508
  logger.info(f"Platform: {sys.platform}")
431
509
  logger.info(f"CWD: {Path.cwd()}")
432
510
  logger.info(f"Project root: {project_root}")
433
-
511
+
512
+ # Log initial memory usage
513
+ if PSUTIL_AVAILABLE:
514
+ try:
515
+ process = psutil.Process()
516
+ memory_info = process.memory_info()
517
+ rss_mb = memory_info.rss / (1024 * 1024)
518
+ vms_mb = memory_info.vms / (1024 * 1024)
519
+ logger.info(f"Initial Memory: RSS={rss_mb:.1f}MB, VMS={vms_mb:.1f}MB")
520
+ except Exception as e:
521
+ logger.debug(f"Failed to get initial memory info: {e}")
522
+
434
523
  return log_file
435
524
 
436
525
 
437
- def cleanup_old_startup_logs(project_root: Optional[Path] = None,
438
- keep_days: int = 7,
439
- keep_min_count: int = 10) -> int:
526
+ def cleanup_old_startup_logs(
527
+ project_root: Optional[Path] = None, keep_count: Optional[int] = None
528
+ ) -> int:
440
529
  """
441
- Clean up old startup log files.
442
-
443
- WHY: Prevent unbounded growth of startup logs while keeping enough
444
- history for debugging patterns.
445
-
530
+ Clean up old startup log files using time-based retention.
531
+
532
+ WHY: This function now delegates to LogManager for unified log management
533
+ with time-based retention instead of count-based.
534
+
446
535
  DESIGN DECISIONS:
447
- - Keep logs from last N days
448
- - Always keep minimum count regardless of age
449
- - Return count of deleted files for reporting
450
-
536
+ - Delegates to LogManager for consistency
537
+ - Converts count to hours (48 hours default)
538
+ - Maintains backward compatibility
539
+
451
540
  Args:
452
541
  project_root: Root directory for the project
453
- keep_days: Number of days to keep logs
454
- keep_min_count: Minimum number of logs to keep regardless of age
455
-
542
+ keep_count: Ignored (kept for backward compatibility)
543
+
456
544
  Returns:
457
545
  Number of log files deleted
458
546
  """
459
- if project_root is None:
460
- project_root = Path.cwd()
461
-
462
- log_dir = project_root / ".claude-mpm" / "logs" / "startup"
463
-
464
- if not log_dir.exists():
465
- return 0
466
-
467
- # Get all startup log files
468
- log_files = sorted(log_dir.glob("startup-*.log"),
469
- key=lambda p: p.stat().st_mtime,
470
- reverse=True) # Newest first
471
-
472
- if len(log_files) <= keep_min_count:
473
- return 0 # Keep minimum count
474
-
475
- # Calculate cutoff time
476
- cutoff_time = datetime.now().timestamp() - (keep_days * 24 * 60 * 60)
477
-
478
- deleted_count = 0
479
- for log_file in log_files[keep_min_count:]: # Skip minimum count
480
- if log_file.stat().st_mtime < cutoff_time:
547
+ try:
548
+ from ..core.log_manager import get_log_manager
549
+
550
+ log_manager = get_log_manager()
551
+
552
+ # Use LogManager's time-based cleanup (48 hours default)
553
+ return log_manager.cleanup_old_startup_logs(project_root)
554
+ except ImportError:
555
+ # Fallback to old implementation if LogManager not available
556
+ # Get retention count from configuration if not specified
557
+ if keep_count is None:
558
+ from claude_mpm.core.config_constants import ConfigConstants
559
+
560
+ keep_count = (
561
+ ConfigConstants.get_logging_setting("startup_logs_retention_count")
562
+ or 10
563
+ )
564
+
565
+ if project_root is None:
566
+ project_root = Path.cwd()
567
+
568
+ log_dir = project_root / ".claude-mpm" / "logs" / "startup"
569
+
570
+ if not log_dir.exists():
571
+ return 0
572
+
573
+ # Get all startup log files
574
+ log_files = sorted(
575
+ log_dir.glob("startup-*.log"), key=lambda p: p.stat().st_mtime, reverse=True
576
+ ) # Newest first
577
+
578
+ if len(log_files) <= keep_count:
579
+ return 0 # Already within limit
580
+
581
+ # Delete older files beyond keep_count
582
+ deleted_count = 0
583
+ for log_file in log_files[
584
+ keep_count:
585
+ ]: # Keep only the most recent keep_count files
481
586
  try:
482
587
  log_file.unlink()
483
588
  deleted_count += 1
484
589
  except Exception:
485
590
  pass # Ignore deletion errors
486
-
487
- return deleted_count
591
+
592
+ return deleted_count
488
593
 
489
594
 
490
595
  def get_latest_startup_log(project_root: Optional[Path] = None) -> Optional[Path]:
491
596
  """
492
597
  Get the path to the most recent startup log file.
493
-
598
+
494
599
  Args:
495
600
  project_root: Root directory for the project
496
-
601
+
497
602
  Returns:
498
603
  Path to latest log file or None if no logs exist
499
604
  """
500
605
  if project_root is None:
501
606
  project_root = Path.cwd()
502
-
607
+
503
608
  log_dir = project_root / ".claude-mpm" / "logs" / "startup"
504
-
609
+
505
610
  if not log_dir.exists():
506
611
  return None
507
-
508
- log_files = sorted(log_dir.glob("startup-*.log"),
509
- key=lambda p: p.stat().st_mtime,
510
- reverse=True)
511
-
612
+
613
+ log_files = sorted(
614
+ log_dir.glob("startup-*.log"), key=lambda p: p.stat().st_mtime, reverse=True
615
+ )
616
+
512
617
  return log_files[0] if log_files else None
513
618
 
514
619
 
515
620
  def log_startup_status(monitor_mode: bool = False, websocket_port: int = 8765) -> None:
516
621
  """
517
622
  Log comprehensive startup status for MCP server and monitor setup.
518
-
623
+
519
624
  This function should be called during application startup to provide
520
625
  detailed information about MCP and monitor setup status.
521
-
626
+
522
627
  Args:
523
628
  monitor_mode: Whether monitor mode is enabled
524
629
  websocket_port: WebSocket port for monitoring
525
630
  """
526
631
  try:
527
632
  status_logger = StartupStatusLogger("cli")
528
-
633
+
634
+ # Log memory status at startup
635
+ status_logger.log_memory_status()
636
+
529
637
  # Log MCP server status
530
638
  status_logger.log_mcp_server_status()
531
-
639
+
532
640
  # Log monitor setup status
533
641
  status_logger.log_monitor_setup_status(monitor_mode, websocket_port)
534
-
642
+
535
643
  except Exception as e:
536
644
  # Don't let logging failures prevent startup
537
645
  logger = get_logger("cli")
538
- logger.debug(f"Startup status logging failed: {e}")
646
+ logger.debug(f"Startup status logging failed: {e}")