claude-mpm 3.9.9__py3-none-any.whl → 4.0.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 (411) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +2 -2
  3. claude_mpm/__main__.py +3 -2
  4. claude_mpm/agents/__init__.py +85 -79
  5. claude_mpm/agents/agent_loader.py +464 -1003
  6. claude_mpm/agents/agent_loader_integration.py +45 -45
  7. claude_mpm/agents/agents_metadata.py +29 -30
  8. claude_mpm/agents/async_agent_loader.py +156 -138
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/base_agent_loader.py +179 -151
  11. claude_mpm/agents/frontmatter_validator.py +229 -130
  12. claude_mpm/agents/schema/agent_schema.json +1 -1
  13. claude_mpm/agents/system_agent_config.py +213 -147
  14. claude_mpm/agents/templates/__init__.py +13 -13
  15. claude_mpm/agents/templates/code_analyzer.json +2 -2
  16. claude_mpm/agents/templates/data_engineer.json +1 -1
  17. claude_mpm/agents/templates/documentation.json +23 -11
  18. claude_mpm/agents/templates/engineer.json +22 -6
  19. claude_mpm/agents/templates/memory_manager.json +155 -0
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +1 -1
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +90 -49
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +21 -18
  33. claude_mpm/cli/commands/agents.py +279 -247
  34. claude_mpm/cli/commands/aggregate.py +138 -157
  35. claude_mpm/cli/commands/cleanup.py +147 -147
  36. claude_mpm/cli/commands/config.py +93 -76
  37. claude_mpm/cli/commands/info.py +17 -16
  38. claude_mpm/cli/commands/mcp.py +143 -762
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +203 -81
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +305 -197
  50. claude_mpm/cli/parser.py +24 -1150
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +104 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +217 -0
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +36 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +571 -0
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +40 -23
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +14 -21
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +97 -93
  298. claude_mpm/services/mcp_gateway/main.py +307 -127
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +100 -101
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +4 -4
  303. claude_mpm/services/mcp_gateway/server/{mcp_server.py → mcp_gateway.py} +149 -153
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +110 -121
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +20 -534
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +9 -0
  358. claude_mpm/storage/state_storage.py +552 -0
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +51 -2
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/config/memory_guardian_config.py +0 -325
  385. claude_mpm/core/config_paths.py +0 -150
  386. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  387. claude_mpm/deployment_paths.py +0 -261
  388. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  389. claude_mpm/models/state_models.py +0 -433
  390. claude_mpm/services/agent/__init__.py +0 -24
  391. claude_mpm/services/agent/deployment.py +0 -2548
  392. claude_mpm/services/agent/management.py +0 -598
  393. claude_mpm/services/agent/registry.py +0 -813
  394. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  395. claude_mpm/services/communication/socketio.py +0 -1935
  396. claude_mpm/services/communication/websocket.py +0 -479
  397. claude_mpm/services/framework_claude_md_generator.py +0 -624
  398. claude_mpm/services/health_monitor.py +0 -893
  399. claude_mpm/services/infrastructure/memory_guardian.py +0 -770
  400. claude_mpm/services/mcp_gateway/server/mcp_server_simple.py +0 -444
  401. claude_mpm/services/optimized_hook_service.py +0 -542
  402. claude_mpm/services/project_analyzer.py +0 -864
  403. claude_mpm/services/project_registry.py +0 -608
  404. claude_mpm/services/standalone_socketio_server.py +0 -1300
  405. claude_mpm/services/ticket_manager_di.py +0 -318
  406. claude_mpm/services/ticketing_service_original.py +0 -510
  407. claude_mpm/utils/paths.py +0 -395
  408. claude_mpm/utils/platform_memory.py +0 -524
  409. claude_mpm-3.9.9.dist-info/RECORD +0 -293
  410. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  411. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -1,608 +0,0 @@
1
- """
2
- Project Registry Service.
3
-
4
- WHY: This service manages a persistent registry of claude-mpm projects to enable
5
- project identification, tracking, and metadata management. The registry stores
6
- comprehensive project information including git status, environment details,
7
- runtime information, and project characteristics.
8
-
9
- DESIGN DECISION: Uses YAML for human-readable registry files stored in the
10
- user's home directory (~/.claude-mpm/registry/). Each project
11
- gets a unique UUID-based registry file to avoid conflicts and enable easy project
12
- identification. Registry is user-specific for better isolation and persistence.
13
-
14
- The registry captures both static project information (paths, git info) and
15
- dynamic runtime information (startup times, process IDs, command line args)
16
- to provide complete project lifecycle tracking.
17
- """
18
-
19
- import os
20
- import sys
21
- import uuid
22
- import subprocess
23
- import platform
24
- import shutil
25
- from datetime import datetime, timezone, timedelta
26
- from pathlib import Path
27
- from typing import Dict, Any, Optional, List
28
- import yaml
29
-
30
- from claude_mpm.core.logger import get_logger
31
- from claude_mpm.deployment_paths import get_project_root
32
-
33
-
34
- class ProjectRegistryError(Exception):
35
- """Base exception for project registry operations."""
36
- pass
37
-
38
-
39
- class ProjectRegistry:
40
- """
41
- Manages the project registry for claude-mpm installations.
42
-
43
- WHY: The project registry provides persistent project tracking across sessions,
44
- enabling project identification, metadata collection, and usage analytics.
45
- This is crucial for multi-project environments where users switch between
46
- different codebases.
47
-
48
- DESIGN DECISION: Registry files are stored in ~/.claude-mpm/registry/
49
- with UUID-based filenames to ensure uniqueness and avoid conflicts. The registry
50
- uses YAML for human readability and ease of manual inspection/editing.
51
- Registry is stored in the user's home directory for persistence across projects.
52
- """
53
-
54
- def __init__(self):
55
- """
56
- Initialize the project registry.
57
-
58
- WHY: Sets up the registry directory and logger. The registry directory
59
- is created in the user's home directory to keep registry data user-specific
60
- and persistent across different projects and sessions.
61
- """
62
- self.logger = get_logger("project_registry")
63
- # Use user's home directory for registry to avoid project-specific contamination
64
- # This ensures registry persists across all projects for the user
65
- user_home = Path.home()
66
- self.registry_dir = user_home / ".claude-mpm" / "registry"
67
- self.current_project_path = Path.cwd().resolve()
68
-
69
- # Ensure registry directory exists
70
- try:
71
- self.registry_dir.mkdir(parents=True, exist_ok=True)
72
- except Exception as e:
73
- self.logger.error(f"Failed to create registry directory: {e}")
74
- raise ProjectRegistryError(f"Cannot create registry directory: {e}")
75
-
76
- def get_or_create_project_entry(self) -> Dict[str, Any]:
77
- """
78
- Get existing project registry entry or create a new one.
79
-
80
- WHY: This is the main entry point for project registration. It handles
81
- both new project registration and existing project updates, ensuring
82
- that every claude-mpm session is properly tracked.
83
-
84
- DESIGN DECISION: Matching is done by normalized absolute path to handle
85
- symbolic links and different path representations consistently.
86
-
87
- Returns:
88
- Dictionary containing the project registry data
89
-
90
- Raises:
91
- ProjectRegistryError: If registry operations fail
92
- """
93
- try:
94
- # Look for existing registry entry
95
- existing_entry = self._find_existing_entry()
96
-
97
- if existing_entry:
98
- self.logger.debug(f"Found existing project entry: {existing_entry['project_id']}")
99
- # Update existing entry with current session info
100
- return self._update_existing_entry(existing_entry)
101
- else:
102
- self.logger.debug("Creating new project registry entry")
103
- # Create new entry
104
- return self._create_new_entry()
105
-
106
- except Exception as e:
107
- self.logger.error(f"Failed to get or create project entry: {e}")
108
- raise ProjectRegistryError(f"Registry operation failed: {e}")
109
-
110
- def _find_existing_entry(self) -> Optional[Dict[str, Any]]:
111
- """
112
- Search for existing registry entry matching current project path.
113
-
114
- WHY: We need to match projects by their absolute path to avoid creating
115
- duplicate entries when the same project is accessed from different
116
- working directories or via different path representations.
117
-
118
- Returns:
119
- Existing registry data if found, None otherwise
120
- """
121
- try:
122
- # Normalize current path for consistent matching
123
- current_path_str = str(self.current_project_path)
124
-
125
- # Search all registry files
126
- for registry_file in self.registry_dir.glob("*.yaml"):
127
- try:
128
- with open(registry_file, 'r', encoding='utf-8') as f:
129
- data = yaml.safe_load(f) or {}
130
-
131
- # Check if project_path matches
132
- if data.get('project_path') == current_path_str:
133
- data['_registry_file'] = registry_file # Add file reference
134
- return data
135
-
136
- except Exception as e:
137
- self.logger.warning(f"Failed to read registry file {registry_file}: {e}")
138
- continue
139
-
140
- return None
141
-
142
- except Exception as e:
143
- self.logger.error(f"Error searching for existing entry: {e}")
144
- return None
145
-
146
- def _create_new_entry(self) -> Dict[str, Any]:
147
- """
148
- Create a new project registry entry.
149
-
150
- WHY: New projects need to be registered with comprehensive metadata
151
- including project information, environment details, and initial runtime
152
- data. This creates a complete snapshot of the project at first access.
153
-
154
- Returns:
155
- Newly created registry data
156
- """
157
- project_id = str(uuid.uuid4())
158
- registry_file = self.registry_dir / f"{project_id}.yaml"
159
-
160
- # Build comprehensive project data
161
- project_data = {
162
- 'project_id': project_id,
163
- 'project_path': str(self.current_project_path),
164
- 'project_name': self.current_project_path.name,
165
- 'metadata': self._build_metadata(is_new=True),
166
- 'runtime': self._build_runtime_info(),
167
- 'environment': self._build_environment_info(),
168
- 'git': self._build_git_info(),
169
- 'session': self._build_session_info(),
170
- 'project_info': self._build_project_info()
171
- }
172
-
173
- # Save to registry file
174
- self._save_registry_data(registry_file, project_data)
175
- project_data['_registry_file'] = registry_file
176
-
177
- self.logger.info(f"Created new project registry entry: {project_id}")
178
- return project_data
179
-
180
- def _update_existing_entry(self, existing_data: Dict[str, Any]) -> Dict[str, Any]:
181
- """
182
- Update existing project registry entry with current session information.
183
-
184
- WHY: Existing projects need their metadata updated to reflect current
185
- access patterns, runtime information, and any changes in project state.
186
- This maintains accurate usage tracking and project state history.
187
-
188
- Args:
189
- existing_data: The existing registry data to update
190
-
191
- Returns:
192
- Updated registry data
193
- """
194
- registry_file = existing_data.get('_registry_file')
195
- if not registry_file:
196
- raise ProjectRegistryError("Registry file reference missing from existing data")
197
-
198
- # Update timestamps and counters
199
- metadata = existing_data.get('metadata', {})
200
- access_count = metadata.get('access_count', 0) + 1
201
- now = datetime.now(timezone.utc).isoformat()
202
-
203
- existing_data['metadata'].update({
204
- 'updated_at': now,
205
- 'last_accessed': now,
206
- 'access_count': access_count
207
- })
208
-
209
- # Update runtime information
210
- existing_data['runtime'] = self._build_runtime_info()
211
-
212
- # Update session information
213
- existing_data['session'] = self._build_session_info()
214
-
215
- # Update git information (may have changed)
216
- existing_data['git'] = self._build_git_info()
217
-
218
- # Update project info (may have changed)
219
- existing_data['project_info'] = self._build_project_info()
220
-
221
- # Save updated data
222
- self._save_registry_data(registry_file, existing_data)
223
-
224
- self.logger.debug(f"Updated project registry entry (access #{access_count})")
225
- return existing_data
226
-
227
- def _build_metadata(self, is_new: bool = False) -> Dict[str, Any]:
228
- """
229
- Build metadata section for registry entry.
230
-
231
- WHY: Metadata tracks creation, modification, and access patterns for
232
- analytics and project lifecycle management.
233
- """
234
- now = datetime.now(timezone.utc).isoformat()
235
-
236
- metadata = {
237
- 'updated_at': now,
238
- 'last_accessed': now,
239
- 'access_count': 1
240
- }
241
-
242
- if is_new:
243
- metadata['created_at'] = now
244
-
245
- return metadata
246
-
247
- def _build_runtime_info(self) -> Dict[str, Any]:
248
- """
249
- Build runtime information section.
250
-
251
- WHY: Runtime information helps track session lifecycle, process management,
252
- and system state. This is valuable for debugging session issues and
253
- understanding usage patterns.
254
- """
255
- # Get claude-mpm version
256
- try:
257
- from claude_mpm import __version__ as claude_mpm_version
258
- except ImportError:
259
- claude_mpm_version = "unknown"
260
-
261
- return {
262
- 'startup_time': datetime.now(timezone.utc).isoformat(),
263
- 'pid': os.getpid(),
264
- 'python_version': f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
265
- 'claude_mpm_version': claude_mpm_version,
266
- 'command_line': ' '.join(sys.argv),
267
- 'launch_method': 'subprocess' # Default, could be detected based on parent process
268
- }
269
-
270
- def _build_environment_info(self) -> Dict[str, Any]:
271
- """
272
- Build environment information section.
273
-
274
- WHY: Environment information helps with debugging, platform-specific
275
- behavior analysis, and provides context for project usage patterns
276
- across different systems and user setups.
277
- """
278
- return {
279
- 'user': os.getenv('USER') or os.getenv('USERNAME', 'unknown'),
280
- 'hostname': platform.node(),
281
- 'os': platform.system(),
282
- 'os_version': platform.release(),
283
- 'shell': os.getenv('SHELL', 'unknown'),
284
- 'terminal': os.getenv('TERM', 'unknown'),
285
- 'cwd': str(Path.cwd())
286
- }
287
-
288
- def _build_git_info(self) -> Dict[str, Any]:
289
- """
290
- Build git repository information.
291
-
292
- WHY: Git information is crucial for project identification and tracking
293
- changes across different branches and commits. This helps understand
294
- project state and enables better project management features.
295
- """
296
- git_info = {
297
- 'is_repo': False,
298
- 'branch': None,
299
- 'remote_url': None,
300
- 'last_commit': None,
301
- 'has_uncommitted': False
302
- }
303
-
304
- try:
305
- # Check if we're in a git repository
306
- result = subprocess.run(
307
- ['git', 'rev-parse', '--git-dir'],
308
- cwd=self.current_project_path,
309
- capture_output=True,
310
- text=True,
311
- timeout=5
312
- )
313
-
314
- if result.returncode == 0:
315
- git_info['is_repo'] = True
316
-
317
- # Get current branch
318
- try:
319
- result = subprocess.run(
320
- ['git', 'branch', '--show-current'],
321
- cwd=self.current_project_path,
322
- capture_output=True,
323
- text=True,
324
- timeout=5
325
- )
326
- if result.returncode == 0:
327
- git_info['branch'] = result.stdout.strip()
328
- except Exception:
329
- pass
330
-
331
- # Get remote URL
332
- try:
333
- result = subprocess.run(
334
- ['git', 'remote', 'get-url', 'origin'],
335
- cwd=self.current_project_path,
336
- capture_output=True,
337
- text=True,
338
- timeout=5
339
- )
340
- if result.returncode == 0:
341
- git_info['remote_url'] = result.stdout.strip()
342
- except Exception:
343
- pass
344
-
345
- # Get last commit
346
- try:
347
- result = subprocess.run(
348
- ['git', 'rev-parse', 'HEAD'],
349
- cwd=self.current_project_path,
350
- capture_output=True,
351
- text=True,
352
- timeout=5
353
- )
354
- if result.returncode == 0:
355
- git_info['last_commit'] = result.stdout.strip()
356
- except Exception:
357
- pass
358
-
359
- # Check for uncommitted changes
360
- try:
361
- result = subprocess.run(
362
- ['git', 'status', '--porcelain'],
363
- cwd=self.current_project_path,
364
- capture_output=True,
365
- text=True,
366
- timeout=5
367
- )
368
- if result.returncode == 0:
369
- git_info['has_uncommitted'] = bool(result.stdout.strip())
370
- except Exception:
371
- pass
372
-
373
- except Exception as e:
374
- self.logger.debug(f"Failed to get git info: {e}")
375
-
376
- return git_info
377
-
378
- def _build_session_info(self) -> Dict[str, Any]:
379
- """
380
- Build session information.
381
-
382
- WHY: Session information tracks the current claude-mpm session state,
383
- including active components and configuration. This helps with session
384
- management and debugging.
385
- """
386
- # These would be populated by the actual session manager
387
- # For now, we provide placeholders that can be updated by the caller
388
- return {
389
- 'session_id': None, # Could be set by session manager
390
- 'ticket_count': 0, # Could be updated by ticket manager
391
- 'agent_count': 0, # Could be updated by agent manager
392
- 'hooks_enabled': False, # Could be detected from configuration
393
- 'monitor_enabled': False # Could be detected from process state
394
- }
395
-
396
- def _build_project_info(self) -> Dict[str, Any]:
397
- """
398
- Build project information section.
399
-
400
- WHY: Project information helps identify the type of project and its
401
- characteristics, enabling better tool selection and project-specific
402
- optimizations.
403
- """
404
- project_info = {
405
- 'has_claude_config': False,
406
- 'has_claude_md': False,
407
- 'has_pyproject': False,
408
- 'has_package_json': False,
409
- 'project_type': 'unknown'
410
- }
411
-
412
- # Check for various project files
413
- claude_files = ['.claude', 'claude.toml', '.claude.toml']
414
- for claude_file in claude_files:
415
- if (self.current_project_path / claude_file).exists():
416
- project_info['has_claude_config'] = True
417
- break
418
-
419
- claude_md_files = ['CLAUDE.md', 'claude.md', '.claude.md']
420
- for claude_md in claude_md_files:
421
- if (self.current_project_path / claude_md).exists():
422
- project_info['has_claude_md'] = True
423
- break
424
-
425
- if (self.current_project_path / 'pyproject.toml').exists():
426
- project_info['has_pyproject'] = True
427
-
428
- if (self.current_project_path / 'package.json').exists():
429
- project_info['has_package_json'] = True
430
-
431
- # Determine project type
432
- if project_info['has_pyproject'] or (self.current_project_path / 'setup.py').exists():
433
- project_info['project_type'] = 'python'
434
- elif project_info['has_package_json']:
435
- project_info['project_type'] = 'javascript'
436
- elif (self.current_project_path / 'Cargo.toml').exists():
437
- project_info['project_type'] = 'rust'
438
- elif (self.current_project_path / 'go.mod').exists():
439
- project_info['project_type'] = 'go'
440
- elif (self.current_project_path / 'pom.xml').exists():
441
- project_info['project_type'] = 'java'
442
- elif any((self.current_project_path / ext).exists() for ext in ['*.c', '*.cpp', '*.h', '*.hpp']):
443
- project_info['project_type'] = 'c/cpp'
444
- elif project_info['has_claude_config'] or project_info['has_claude_md']:
445
- project_info['project_type'] = 'claude'
446
- else:
447
- # Try to detect by file extensions
448
- common_files = list(self.current_project_path.iterdir())[:20] # Check first 20 files
449
- extensions = {f.suffix.lower() for f in common_files if f.is_file()}
450
-
451
- if '.py' in extensions:
452
- project_info['project_type'] = 'python'
453
- elif any(ext in extensions for ext in ['.js', '.ts', '.jsx', '.tsx']):
454
- project_info['project_type'] = 'javascript'
455
- elif any(ext in extensions for ext in ['.rs']):
456
- project_info['project_type'] = 'rust'
457
- elif any(ext in extensions for ext in ['.go']):
458
- project_info['project_type'] = 'go'
459
- elif any(ext in extensions for ext in ['.java', '.scala', '.kt']):
460
- project_info['project_type'] = 'jvm'
461
- elif any(ext in extensions for ext in ['.c', '.cpp', '.cc', '.h', '.hpp']):
462
- project_info['project_type'] = 'c/cpp'
463
- elif any(ext in extensions for ext in ['.md', '.txt', '.rst']):
464
- project_info['project_type'] = 'documentation'
465
-
466
- return project_info
467
-
468
- def _save_registry_data(self, registry_file: Path, data: Dict[str, Any]) -> None:
469
- """
470
- Save registry data to YAML file.
471
-
472
- WHY: Centralized saving logic ensures consistent formatting and error
473
- handling across all registry operations. YAML format provides human
474
- readability for debugging and manual inspection.
475
-
476
- Args:
477
- registry_file: Path to the registry file
478
- data: Registry data to save
479
- """
480
- try:
481
- # Remove internal fields before saving
482
- save_data = {k: v for k, v in data.items() if not k.startswith('_')}
483
-
484
- with open(registry_file, 'w', encoding='utf-8') as f:
485
- yaml.dump(save_data, f, default_flow_style=False, sort_keys=False, indent=2)
486
-
487
- self.logger.debug(f"Saved registry data to {registry_file}")
488
-
489
- except Exception as e:
490
- self.logger.error(f"Failed to save registry data: {e}")
491
- raise ProjectRegistryError(f"Failed to save registry: {e}")
492
-
493
- def list_projects(self) -> List[Dict[str, Any]]:
494
- """
495
- List all registered projects.
496
-
497
- WHY: Provides visibility into all projects managed by claude-mpm,
498
- useful for project management and analytics.
499
-
500
- Returns:
501
- List of project registry data dictionaries
502
- """
503
- projects = []
504
-
505
- try:
506
- for registry_file in self.registry_dir.glob("*.yaml"):
507
- try:
508
- with open(registry_file, 'r', encoding='utf-8') as f:
509
- data = yaml.safe_load(f) or {}
510
- projects.append(data)
511
- except Exception as e:
512
- self.logger.warning(f"Failed to read registry file {registry_file}: {e}")
513
- continue
514
-
515
- except Exception as e:
516
- self.logger.error(f"Failed to list projects: {e}")
517
-
518
- return projects
519
-
520
- def cleanup_old_entries(self, max_age_days: int = 90) -> int:
521
- """
522
- Clean up old registry entries that haven't been accessed recently.
523
-
524
- WHY: Prevents registry directory from growing indefinitely with old
525
- project entries. Keeps the registry focused on active projects.
526
-
527
- Args:
528
- max_age_days: Maximum age in days for keeping entries
529
-
530
- Returns:
531
- Number of entries cleaned up
532
- """
533
- if max_age_days <= 0:
534
- return 0
535
-
536
- cleaned_count = 0
537
- cutoff_date = datetime.now(timezone.utc) - timedelta(days=max_age_days)
538
-
539
- try:
540
- for registry_file in self.registry_dir.glob("*.yaml"):
541
- try:
542
- with open(registry_file, 'r', encoding='utf-8') as f:
543
- data = yaml.safe_load(f) or {}
544
-
545
- # Check last accessed time
546
- last_accessed_str = data.get('metadata', {}).get('last_accessed')
547
- if last_accessed_str:
548
- last_accessed = datetime.fromisoformat(last_accessed_str.replace('Z', '+00:00'))
549
- if last_accessed < cutoff_date:
550
- registry_file.unlink()
551
- cleaned_count += 1
552
- self.logger.debug(f"Cleaned up old registry entry: {registry_file}")
553
-
554
- except Exception as e:
555
- self.logger.warning(f"Failed to process registry file {registry_file}: {e}")
556
- continue
557
-
558
- except Exception as e:
559
- self.logger.error(f"Failed to cleanup old entries: {e}")
560
-
561
- if cleaned_count > 0:
562
- self.logger.info(f"Cleaned up {cleaned_count} old registry entries")
563
-
564
- return cleaned_count
565
-
566
- def update_session_info(self, session_updates: Dict[str, Any]) -> bool:
567
- """
568
- Update session information for the current project.
569
-
570
- WHY: Allows other components (session manager, ticket manager, etc.)
571
- to update the registry with current session state information.
572
-
573
- Args:
574
- session_updates: Dictionary of session updates to apply
575
-
576
- Returns:
577
- True if update was successful, False otherwise
578
- """
579
- try:
580
- existing_entry = self._find_existing_entry()
581
- if not existing_entry:
582
- self.logger.warning("No existing registry entry found for session update")
583
- return False
584
-
585
- registry_file = existing_entry.get('_registry_file')
586
- if not registry_file:
587
- self.logger.error("Registry file reference missing")
588
- return False
589
-
590
- # Update session information
591
- if 'session' not in existing_entry:
592
- existing_entry['session'] = {}
593
-
594
- existing_entry['session'].update(session_updates)
595
-
596
- # Update metadata timestamp
597
- now = datetime.now(timezone.utc).isoformat()
598
- existing_entry['metadata']['updated_at'] = now
599
-
600
- # Save updated data
601
- self._save_registry_data(registry_file, existing_entry)
602
-
603
- self.logger.debug(f"Updated session info: {session_updates}")
604
- return True
605
-
606
- except Exception as e:
607
- self.logger.error(f"Failed to update session info: {e}")
608
- return False