claude-mpm 3.9.11__py3-none-any.whl → 4.0.4__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 (434) 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 +1 -1
  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 +2 -2
  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 +79 -51
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +20 -20
  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 +140 -905
  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 +330 -86
  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 +363 -220
  50. claude_mpm/cli/parser.py +24 -1156
  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 +124 -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 +71 -73
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +35 -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/built/components/agent-inference.js +2 -0
  113. claude_mpm/dashboard/static/built/components/event-processor.js +2 -0
  114. claude_mpm/dashboard/static/built/components/event-viewer.js +2 -0
  115. claude_mpm/dashboard/static/built/components/export-manager.js +2 -0
  116. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +2 -0
  117. claude_mpm/dashboard/static/built/components/hud-library-loader.js +2 -0
  118. claude_mpm/dashboard/static/built/components/hud-manager.js +2 -0
  119. claude_mpm/dashboard/static/built/components/hud-visualizer.js +2 -0
  120. claude_mpm/dashboard/static/built/components/module-viewer.js +2 -0
  121. claude_mpm/dashboard/static/built/components/session-manager.js +2 -0
  122. claude_mpm/dashboard/static/built/components/socket-manager.js +2 -0
  123. claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -0
  124. claude_mpm/dashboard/static/built/components/working-directory.js +2 -0
  125. claude_mpm/dashboard/static/built/dashboard.js +2 -0
  126. claude_mpm/dashboard/static/built/socket-client.js +2 -0
  127. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  128. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  129. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  130. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  131. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  132. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  133. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  134. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  135. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  136. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  137. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  138. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  139. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  140. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  141. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  142. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  143. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  144. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  145. claude_mpm/dashboard/static/js/components/event-viewer.js +93 -72
  146. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  147. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +110 -96
  148. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  149. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  150. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  151. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  152. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  153. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  154. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  155. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  156. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  157. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  158. claude_mpm/dashboard/static/js/socket-client.js +133 -53
  159. claude_mpm/dashboard/templates/index.html +40 -50
  160. claude_mpm/experimental/cli_enhancements.py +60 -58
  161. claude_mpm/generators/__init__.py +1 -1
  162. claude_mpm/generators/agent_profile_generator.py +75 -65
  163. claude_mpm/hooks/__init__.py +1 -1
  164. claude_mpm/hooks/base_hook.py +33 -28
  165. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  166. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  167. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  168. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  169. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  170. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  171. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  172. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  173. claude_mpm/hooks/memory_integration_hook.py +140 -100
  174. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  175. claude_mpm/hooks/validation_hooks.py +57 -49
  176. claude_mpm/init.py +145 -121
  177. claude_mpm/models/__init__.py +9 -9
  178. claude_mpm/models/agent_definition.py +33 -23
  179. claude_mpm/models/agent_session.py +228 -200
  180. claude_mpm/scripts/__init__.py +1 -1
  181. claude_mpm/scripts/socketio_daemon.py +192 -75
  182. claude_mpm/scripts/socketio_server_manager.py +328 -0
  183. claude_mpm/scripts/start_activity_logging.py +25 -22
  184. claude_mpm/services/__init__.py +68 -43
  185. claude_mpm/services/agent_capabilities_service.py +271 -0
  186. claude_mpm/services/agents/__init__.py +23 -32
  187. claude_mpm/services/agents/deployment/__init__.py +3 -3
  188. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  189. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  190. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  191. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  192. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  193. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  194. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  195. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  196. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  197. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  198. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  199. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  200. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  201. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  202. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  203. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  204. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  205. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  206. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  207. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  208. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  209. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  210. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  211. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  212. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  213. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  214. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  215. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  216. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  217. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  218. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  219. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  220. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  221. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  222. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  223. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  224. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  225. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  226. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  227. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  228. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  229. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  230. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  231. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  232. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  233. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  234. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  235. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  236. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  237. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  238. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  239. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  240. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  241. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  242. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  243. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  244. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  245. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  246. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  247. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  248. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  249. claude_mpm/services/agents/loading/__init__.py +2 -2
  250. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  251. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  252. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  253. claude_mpm/services/agents/management/__init__.py +2 -2
  254. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  255. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  256. claude_mpm/services/agents/memory/__init__.py +9 -6
  257. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  258. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  259. claude_mpm/services/agents/memory/analyzer.py +430 -0
  260. claude_mpm/services/agents/memory/content_manager.py +376 -0
  261. claude_mpm/services/agents/memory/template_generator.py +468 -0
  262. claude_mpm/services/agents/registry/__init__.py +7 -10
  263. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  264. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  265. claude_mpm/services/async_session_logger.py +187 -153
  266. claude_mpm/services/claude_session_logger.py +87 -72
  267. claude_mpm/services/command_handler_service.py +217 -0
  268. claude_mpm/services/communication/__init__.py +3 -2
  269. claude_mpm/services/core/__init__.py +50 -97
  270. claude_mpm/services/core/base.py +60 -53
  271. claude_mpm/services/core/interfaces/__init__.py +188 -0
  272. claude_mpm/services/core/interfaces/agent.py +351 -0
  273. claude_mpm/services/core/interfaces/communication.py +343 -0
  274. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  275. claude_mpm/services/core/interfaces/service.py +434 -0
  276. claude_mpm/services/core/interfaces.py +19 -944
  277. claude_mpm/services/event_aggregator.py +208 -170
  278. claude_mpm/services/exceptions.py +387 -308
  279. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  280. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  281. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  282. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  283. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  284. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  285. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  286. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  287. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  288. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  289. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  290. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  291. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  292. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  293. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  294. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  295. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  296. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  297. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  298. claude_mpm/services/hook_service.py +106 -114
  299. claude_mpm/services/infrastructure/__init__.py +7 -5
  300. claude_mpm/services/infrastructure/context_preservation.py +233 -199
  301. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  302. claude_mpm/services/infrastructure/logging.py +83 -76
  303. claude_mpm/services/infrastructure/monitoring.py +547 -404
  304. claude_mpm/services/mcp_gateway/__init__.py +30 -13
  305. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  306. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  307. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  308. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  309. claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
  310. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  311. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  312. claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
  313. claude_mpm/services/mcp_gateway/main.py +287 -137
  314. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  315. claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
  316. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  317. claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
  318. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
  319. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  320. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  321. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  322. claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
  323. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  324. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  325. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  326. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  327. claude_mpm/services/memory/__init__.py +2 -2
  328. claude_mpm/services/memory/builder.py +451 -362
  329. claude_mpm/services/memory/cache/__init__.py +2 -2
  330. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  331. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  332. claude_mpm/services/memory/indexed_memory.py +195 -193
  333. claude_mpm/services/memory/optimizer.py +267 -234
  334. claude_mpm/services/memory/router.py +571 -263
  335. claude_mpm/services/memory_hook_service.py +237 -0
  336. claude_mpm/services/port_manager.py +575 -0
  337. claude_mpm/services/project/__init__.py +3 -3
  338. claude_mpm/services/project/analyzer.py +451 -305
  339. claude_mpm/services/project/registry.py +262 -240
  340. claude_mpm/services/recovery_manager.py +287 -231
  341. claude_mpm/services/response_tracker.py +87 -67
  342. claude_mpm/services/runner_configuration_service.py +587 -0
  343. claude_mpm/services/session_management_service.py +304 -0
  344. claude_mpm/services/socketio/__init__.py +4 -4
  345. claude_mpm/services/socketio/client_proxy.py +174 -0
  346. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  347. claude_mpm/services/socketio/handlers/base.py +44 -30
  348. claude_mpm/services/socketio/handlers/connection.py +166 -64
  349. claude_mpm/services/socketio/handlers/file.py +123 -108
  350. claude_mpm/services/socketio/handlers/git.py +607 -373
  351. claude_mpm/services/socketio/handlers/hook.py +185 -0
  352. claude_mpm/services/socketio/handlers/memory.py +4 -4
  353. claude_mpm/services/socketio/handlers/project.py +4 -4
  354. claude_mpm/services/socketio/handlers/registry.py +53 -38
  355. claude_mpm/services/socketio/server/__init__.py +18 -0
  356. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  357. claude_mpm/services/socketio/server/core.py +399 -0
  358. claude_mpm/services/socketio/server/main.py +323 -0
  359. claude_mpm/services/socketio_client_manager.py +160 -133
  360. claude_mpm/services/socketio_server.py +36 -1885
  361. claude_mpm/services/subprocess_launcher_service.py +316 -0
  362. claude_mpm/services/system_instructions_service.py +258 -0
  363. claude_mpm/services/ticket_manager.py +19 -533
  364. claude_mpm/services/utility_service.py +285 -0
  365. claude_mpm/services/version_control/__init__.py +18 -21
  366. claude_mpm/services/version_control/branch_strategy.py +20 -10
  367. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  368. claude_mpm/services/version_control/git_operations.py +52 -21
  369. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  370. claude_mpm/services/version_control/version_parser.py +145 -125
  371. claude_mpm/services/version_service.py +270 -0
  372. claude_mpm/storage/__init__.py +2 -2
  373. claude_mpm/storage/state_storage.py +177 -181
  374. claude_mpm/ticket_wrapper.py +2 -2
  375. claude_mpm/utils/__init__.py +2 -2
  376. claude_mpm/utils/agent_dependency_loader.py +453 -243
  377. claude_mpm/utils/config_manager.py +157 -118
  378. claude_mpm/utils/console.py +1 -1
  379. claude_mpm/utils/dependency_cache.py +102 -107
  380. claude_mpm/utils/dependency_manager.py +52 -47
  381. claude_mpm/utils/dependency_strategies.py +131 -96
  382. claude_mpm/utils/environment_context.py +110 -102
  383. claude_mpm/utils/error_handler.py +75 -55
  384. claude_mpm/utils/file_utils.py +80 -67
  385. claude_mpm/utils/framework_detection.py +12 -11
  386. claude_mpm/utils/import_migration_example.py +12 -60
  387. claude_mpm/utils/imports.py +48 -45
  388. claude_mpm/utils/path_operations.py +100 -93
  389. claude_mpm/utils/robust_installer.py +172 -164
  390. claude_mpm/utils/session_logging.py +30 -23
  391. claude_mpm/utils/subprocess_utils.py +99 -61
  392. claude_mpm/validation/__init__.py +1 -1
  393. claude_mpm/validation/agent_validator.py +151 -111
  394. claude_mpm/validation/frontmatter_validator.py +92 -71
  395. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/METADATA +90 -22
  396. claude_mpm-4.0.4.dist-info/RECORD +417 -0
  397. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/entry_points.txt +1 -0
  398. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/licenses/LICENSE +1 -1
  399. claude_mpm/cli/commands/run_guarded.py +0 -511
  400. claude_mpm/config/memory_guardian_config.py +0 -325
  401. claude_mpm/config/memory_guardian_yaml.py +0 -335
  402. claude_mpm/core/config_paths.py +0 -150
  403. claude_mpm/core/memory_aware_runner.py +0 -353
  404. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  405. claude_mpm/deployment_paths.py +0 -261
  406. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  407. claude_mpm/models/state_models.py +0 -433
  408. claude_mpm/services/agent/__init__.py +0 -24
  409. claude_mpm/services/agent/deployment.py +0 -2548
  410. claude_mpm/services/agent/management.py +0 -598
  411. claude_mpm/services/agent/registry.py +0 -813
  412. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  413. claude_mpm/services/communication/socketio.py +0 -1935
  414. claude_mpm/services/communication/websocket.py +0 -479
  415. claude_mpm/services/framework_claude_md_generator.py +0 -624
  416. claude_mpm/services/health_monitor.py +0 -893
  417. claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
  418. claude_mpm/services/infrastructure/health_monitor.py +0 -775
  419. claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
  420. claude_mpm/services/infrastructure/memory_guardian.py +0 -944
  421. claude_mpm/services/infrastructure/restart_protection.py +0 -642
  422. claude_mpm/services/infrastructure/state_manager.py +0 -774
  423. claude_mpm/services/mcp_gateway/manager.py +0 -334
  424. claude_mpm/services/optimized_hook_service.py +0 -542
  425. claude_mpm/services/project_analyzer.py +0 -864
  426. claude_mpm/services/project_registry.py +0 -608
  427. claude_mpm/services/standalone_socketio_server.py +0 -1300
  428. claude_mpm/services/ticket_manager_di.py +0 -318
  429. claude_mpm/services/ticketing_service_original.py +0 -510
  430. claude_mpm/utils/paths.py +0 -395
  431. claude_mpm/utils/platform_memory.py +0 -524
  432. claude_mpm-3.9.11.dist-info/RECORD +0 -306
  433. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/WHEEL +0 -0
  434. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,5 @@
1
+ from pathlib import Path
2
+
1
3
  """
2
4
  Enhanced version parsing system with multiple source support and fallback mechanisms.
3
5
 
@@ -14,26 +16,26 @@ The system includes caching for performance and validation for data integrity.
14
16
  """
15
17
 
16
18
  import json
19
+ import logging
17
20
  import re
18
21
  import subprocess
19
22
  from datetime import datetime, timedelta
20
- from pathlib import Path
21
- from typing import Dict, List, Optional, Tuple, Union
22
23
  from functools import lru_cache
23
- import logging
24
+ from typing import Dict, List, Optional, Tuple, Union
24
25
 
25
26
  from claude_mpm.services.version_control.semantic_versioning import SemanticVersion
26
27
 
27
28
 
28
29
  class VersionSource:
29
30
  """Enumeration of version sources with priority ordering."""
31
+
30
32
  GIT_TAGS = "git_tags"
31
33
  CHANGELOG = "changelog"
32
34
  VERSION_FILE = "version_file"
33
35
  PACKAGE_JSON = "package_json"
34
36
  PYPROJECT_TOML = "pyproject_toml"
35
37
  SETUP_PY = "setup_py"
36
-
38
+
37
39
  # Priority order for fallback mechanism
38
40
  PRIORITY_ORDER = [
39
41
  GIT_TAGS,
@@ -41,13 +43,13 @@ class VersionSource:
41
43
  VERSION_FILE,
42
44
  PACKAGE_JSON,
43
45
  PYPROJECT_TOML,
44
- SETUP_PY
46
+ SETUP_PY,
45
47
  ]
46
48
 
47
49
 
48
50
  class VersionMetadata:
49
51
  """Extended metadata for version information."""
50
-
52
+
51
53
  def __init__(
52
54
  self,
53
55
  version: str,
@@ -56,7 +58,7 @@ class VersionMetadata:
56
58
  commit_hash: Optional[str] = None,
57
59
  author: Optional[str] = None,
58
60
  message: Optional[str] = None,
59
- changes: Optional[List[str]] = None
61
+ changes: Optional[List[str]] = None,
60
62
  ):
61
63
  self.version = version
62
64
  self.source = source
@@ -65,24 +67,26 @@ class VersionMetadata:
65
67
  self.author = author
66
68
  self.message = message
67
69
  self.changes = changes or []
68
-
70
+
69
71
  def to_dict(self) -> Dict:
70
72
  """Convert metadata to dictionary format."""
71
73
  return {
72
74
  "version": self.version,
73
75
  "source": self.source,
74
- "release_date": self.release_date.isoformat() if self.release_date else None,
76
+ "release_date": self.release_date.isoformat()
77
+ if self.release_date
78
+ else None,
75
79
  "commit_hash": self.commit_hash,
76
80
  "author": self.author,
77
81
  "message": self.message,
78
- "changes": self.changes
82
+ "changes": self.changes,
79
83
  }
80
84
 
81
85
 
82
86
  class EnhancedVersionParser:
83
87
  """
84
88
  Enhanced version parser with multiple source support and intelligent fallback.
85
-
89
+
86
90
  This parser provides:
87
91
  - Multiple version source support
88
92
  - Intelligent fallback mechanisms
@@ -90,11 +94,11 @@ class EnhancedVersionParser:
90
94
  - Validation and error handling
91
95
  - Comprehensive version history retrieval
92
96
  """
93
-
97
+
94
98
  def __init__(self, project_root: Optional[Path] = None, cache_ttl: int = 300):
95
99
  """
96
100
  Initialize the enhanced version parser.
97
-
101
+
98
102
  Args:
99
103
  project_root: Root directory of the project (defaults to current directory)
100
104
  cache_ttl: Cache time-to-live in seconds (default: 5 minutes)
@@ -103,11 +107,15 @@ class EnhancedVersionParser:
103
107
  self.cache_ttl = cache_ttl
104
108
  self.logger = logging.getLogger(__name__)
105
109
  self._cache: Dict[str, Tuple[datetime, any]] = {}
106
-
110
+
107
111
  # Compile regex patterns once for efficiency
108
- self._version_pattern = re.compile(r'(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9\-\.]+))?(?:\+([a-zA-Z0-9\-\.]+))?')
109
- self._changelog_version_pattern = re.compile(r'##\s*\[?([0-9]+\.[0-9]+\.[0-9]+[^\]]*)\]?\s*[-–]\s*(\d{4}-\d{2}-\d{2})?')
110
-
112
+ self._version_pattern = re.compile(
113
+ r"(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9\-\.]+))?(?:\+([a-zA-Z0-9\-\.]+))?"
114
+ )
115
+ self._changelog_version_pattern = re.compile(
116
+ r"##\s*\[?([0-9]+\.[0-9]+\.[0-9]+[^\]]*)\]?\s*[-–]\s*(\d{4}-\d{2}-\d{2})?"
117
+ )
118
+
111
119
  def _get_cached(self, key: str) -> Optional[any]:
112
120
  """Get cached value if still valid."""
113
121
  if key in self._cache:
@@ -116,19 +124,21 @@ class EnhancedVersionParser:
116
124
  return value
117
125
  del self._cache[key]
118
126
  return None
119
-
127
+
120
128
  def _set_cached(self, key: str, value: any) -> any:
121
129
  """Set cached value with timestamp."""
122
130
  self._cache[key] = (datetime.now(), value)
123
131
  return value
124
-
125
- def get_current_version(self, prefer_source: Optional[str] = None) -> Optional[VersionMetadata]:
132
+
133
+ def get_current_version(
134
+ self, prefer_source: Optional[str] = None
135
+ ) -> Optional[VersionMetadata]:
126
136
  """
127
137
  Get the current version from the most reliable available source.
128
-
138
+
129
139
  Args:
130
140
  prefer_source: Preferred source to check first (optional)
131
-
141
+
132
142
  Returns:
133
143
  VersionMetadata with current version information, or None if not found
134
144
  """
@@ -136,12 +146,12 @@ class EnhancedVersionParser:
136
146
  cached = self._get_cached(cache_key)
137
147
  if cached:
138
148
  return cached
139
-
149
+
140
150
  sources = VersionSource.PRIORITY_ORDER.copy()
141
151
  if prefer_source and prefer_source in sources:
142
152
  sources.remove(prefer_source)
143
153
  sources.insert(0, prefer_source)
144
-
154
+
145
155
  for source in sources:
146
156
  try:
147
157
  version = self._get_version_from_source(source, latest_only=True)
@@ -149,21 +159,19 @@ class EnhancedVersionParser:
149
159
  return self._set_cached(cache_key, version)
150
160
  except Exception as e:
151
161
  self.logger.debug(f"Failed to get version from {source}: {e}")
152
-
162
+
153
163
  return None
154
-
164
+
155
165
  def get_version_history(
156
- self,
157
- include_prereleases: bool = False,
158
- limit: Optional[int] = None
166
+ self, include_prereleases: bool = False, limit: Optional[int] = None
159
167
  ) -> List[VersionMetadata]:
160
168
  """
161
169
  Get complete version history from all available sources.
162
-
170
+
163
171
  Args:
164
172
  include_prereleases: Include pre-release versions (alpha, beta, rc)
165
173
  limit: Maximum number of versions to return
166
-
174
+
167
175
  Returns:
168
176
  List of VersionMetadata objects sorted by version (descending)
169
177
  """
@@ -171,9 +179,9 @@ class EnhancedVersionParser:
171
179
  cached = self._get_cached(cache_key)
172
180
  if cached:
173
181
  return cached
174
-
182
+
175
183
  all_versions: Dict[str, VersionMetadata] = {}
176
-
184
+
177
185
  # Try each source and merge results
178
186
  for source in VersionSource.PRIORITY_ORDER:
179
187
  try:
@@ -184,25 +192,23 @@ class EnhancedVersionParser:
184
192
  all_versions[version.version] = version
185
193
  except Exception as e:
186
194
  self.logger.debug(f"Failed to get versions from {source}: {e}")
187
-
195
+
188
196
  # Filter and sort versions
189
197
  result = list(all_versions.values())
190
-
198
+
191
199
  if not include_prereleases:
192
200
  result = [v for v in result if not self._is_prerelease(v.version)]
193
-
201
+
194
202
  # Sort by semantic version
195
203
  result.sort(key=lambda v: self._parse_semver(v.version), reverse=True)
196
-
204
+
197
205
  if limit:
198
206
  result = result[:limit]
199
-
207
+
200
208
  return self._set_cached(cache_key, result)
201
-
209
+
202
210
  def _get_version_from_source(
203
- self,
204
- source: str,
205
- latest_only: bool = False
211
+ self, source: str, latest_only: bool = False
206
212
  ) -> Optional[VersionMetadata]:
207
213
  """Get version(s) from a specific source."""
208
214
  if source == VersionSource.GIT_TAGS:
@@ -217,20 +223,26 @@ class EnhancedVersionParser:
217
223
  versions = self._get_versions_from_changelog()
218
224
  return versions[0] if versions else None
219
225
  return None
220
-
226
+
221
227
  def _get_versions_from_source(self, source: str) -> List[VersionMetadata]:
222
228
  """Get all versions from a specific source."""
223
229
  if source == VersionSource.GIT_TAGS:
224
230
  return self._get_all_versions_from_git()
225
231
  elif source == VersionSource.CHANGELOG:
226
232
  return self._get_versions_from_changelog()
227
- elif source in [VersionSource.VERSION_FILE, VersionSource.PACKAGE_JSON, VersionSource.PYPROJECT_TOML]:
233
+ elif source in [
234
+ VersionSource.VERSION_FILE,
235
+ VersionSource.PACKAGE_JSON,
236
+ VersionSource.PYPROJECT_TOML,
237
+ ]:
228
238
  # These sources only provide current version
229
239
  version = self._get_version_from_source(source, latest_only=True)
230
240
  return [version] if version else []
231
241
  return []
232
-
233
- def _get_version_from_git(self, latest_only: bool = True) -> Optional[VersionMetadata]:
242
+
243
+ def _get_version_from_git(
244
+ self, latest_only: bool = True
245
+ ) -> Optional[VersionMetadata]:
234
246
  """Get version information from git tags."""
235
247
  try:
236
248
  if latest_only:
@@ -240,70 +252,77 @@ class EnhancedVersionParser:
240
252
  capture_output=True,
241
253
  text=True,
242
254
  cwd=self.project_root,
243
- check=False
255
+ check=False,
244
256
  )
245
257
  if result.returncode == 0:
246
258
  tag = result.stdout.strip()
247
259
  return self._parse_git_tag(tag)
248
260
  else:
249
- return self._get_all_versions_from_git()[0] if self._get_all_versions_from_git() else None
261
+ return (
262
+ self._get_all_versions_from_git()[0]
263
+ if self._get_all_versions_from_git()
264
+ else None
265
+ )
250
266
  except Exception as e:
251
267
  self.logger.debug(f"Failed to get git version: {e}")
252
268
  return None
253
-
269
+
254
270
  def _get_all_versions_from_git(self) -> List[VersionMetadata]:
255
271
  """Get all versions from git tags with metadata."""
256
272
  versions = []
257
273
  try:
258
274
  # Get all tags with dates and messages
259
275
  result = subprocess.run(
260
- ["git", "for-each-ref", "--sort=-version:refname", "--format=%(refname:short)|%(creatordate:iso)|%(subject)", "refs/tags"],
276
+ [
277
+ "git",
278
+ "for-each-ref",
279
+ "--sort=-version:refname",
280
+ "--format=%(refname:short)|%(creatordate:iso)|%(subject)",
281
+ "refs/tags",
282
+ ],
261
283
  capture_output=True,
262
284
  text=True,
263
285
  cwd=self.project_root,
264
- check=False
286
+ check=False,
265
287
  )
266
-
288
+
267
289
  if result.returncode == 0:
268
- for line in result.stdout.strip().split('\n'):
290
+ for line in result.stdout.strip().split("\n"):
269
291
  if line:
270
- parts = line.split('|', 2)
292
+ parts = line.split("|", 2)
271
293
  if len(parts) >= 1:
272
294
  tag = parts[0]
273
295
  date_str = parts[1] if len(parts) > 1 else None
274
296
  message = parts[2] if len(parts) > 2 else None
275
-
297
+
276
298
  # Parse the tag
277
299
  metadata = self._parse_git_tag(tag, date_str, message)
278
300
  if metadata:
279
301
  versions.append(metadata)
280
302
  except Exception as e:
281
303
  self.logger.debug(f"Failed to get git versions: {e}")
282
-
304
+
283
305
  return versions
284
-
306
+
285
307
  def _parse_git_tag(
286
- self,
287
- tag: str,
288
- date_str: Optional[str] = None,
289
- message: Optional[str] = None
308
+ self, tag: str, date_str: Optional[str] = None, message: Optional[str] = None
290
309
  ) -> Optional[VersionMetadata]:
291
310
  """Parse a git tag into VersionMetadata."""
292
311
  # Remove 'v' prefix if present
293
- version = tag[1:] if tag.startswith('v') else tag
294
-
312
+ version = tag[1:] if tag.startswith("v") else tag
313
+
295
314
  # Validate version format
296
315
  if not self._version_pattern.match(version):
297
316
  return None
298
-
317
+
299
318
  # Parse date if provided
300
319
  release_date = None
301
320
  if date_str:
302
321
  try:
303
- release_date = datetime.fromisoformat(date_str.replace(' ', 'T'))
322
+ release_date = datetime.fromisoformat(date_str.replace(" ", "T"))
304
323
  except:
305
324
  pass
306
-
325
+
307
326
  # Get commit hash for this tag
308
327
  commit_hash = None
309
328
  try:
@@ -312,21 +331,21 @@ class EnhancedVersionParser:
312
331
  capture_output=True,
313
332
  text=True,
314
333
  cwd=self.project_root,
315
- check=False
334
+ check=False,
316
335
  )
317
336
  if result.returncode == 0:
318
337
  commit_hash = result.stdout.strip()[:7]
319
338
  except:
320
339
  pass
321
-
340
+
322
341
  return VersionMetadata(
323
342
  version=version,
324
343
  source=VersionSource.GIT_TAGS,
325
344
  release_date=release_date,
326
345
  commit_hash=commit_hash,
327
- message=message
346
+ message=message,
328
347
  )
329
-
348
+
330
349
  def _get_version_from_file(self) -> Optional[VersionMetadata]:
331
350
  """Get version from VERSION file."""
332
351
  version_file = self.project_root / "VERSION"
@@ -335,13 +354,12 @@ class EnhancedVersionParser:
335
354
  version = version_file.read_text().strip()
336
355
  if self._version_pattern.match(version):
337
356
  return VersionMetadata(
338
- version=version,
339
- source=VersionSource.VERSION_FILE
357
+ version=version, source=VersionSource.VERSION_FILE
340
358
  )
341
359
  except Exception as e:
342
360
  self.logger.debug(f"Failed to read VERSION file: {e}")
343
361
  return None
344
-
362
+
345
363
  def _get_version_from_package_json(self) -> Optional[VersionMetadata]:
346
364
  """Get version from package.json."""
347
365
  package_file = self.project_root / "package.json"
@@ -352,13 +370,12 @@ class EnhancedVersionParser:
352
370
  version = data.get("version")
353
371
  if version and self._version_pattern.match(version):
354
372
  return VersionMetadata(
355
- version=version,
356
- source=VersionSource.PACKAGE_JSON
373
+ version=version, source=VersionSource.PACKAGE_JSON
357
374
  )
358
375
  except Exception as e:
359
376
  self.logger.debug(f"Failed to read package.json: {e}")
360
377
  return None
361
-
378
+
362
379
  def _get_version_from_pyproject(self) -> Optional[VersionMetadata]:
363
380
  """Get version from pyproject.toml."""
364
381
  pyproject_file = self.project_root / "pyproject.toml"
@@ -368,41 +385,40 @@ class EnhancedVersionParser:
368
385
  # Look for version in [tool.poetry] or [project] sections
369
386
  patterns = [
370
387
  r'version\s*=\s*["\']([^"\']+)["\']',
371
- r'version\s*=\s*\{[^}]*\}', # Dynamic version
388
+ r"version\s*=\s*\{[^}]*\}", # Dynamic version
372
389
  ]
373
-
390
+
374
391
  for pattern in patterns:
375
392
  match = re.search(pattern, content)
376
393
  if match:
377
394
  version = match.group(1) if match.lastindex else None
378
395
  if version and self._version_pattern.match(version):
379
396
  return VersionMetadata(
380
- version=version,
381
- source=VersionSource.PYPROJECT_TOML
397
+ version=version, source=VersionSource.PYPROJECT_TOML
382
398
  )
383
399
  except Exception as e:
384
400
  self.logger.debug(f"Failed to read pyproject.toml: {e}")
385
401
  return None
386
-
402
+
387
403
  def _get_versions_from_changelog(self) -> List[VersionMetadata]:
388
404
  """Parse version history from CHANGELOG.md."""
389
405
  versions = []
390
406
  changelog_paths = [
391
407
  self.project_root / "CHANGELOG.md",
392
408
  self.project_root / "docs" / "CHANGELOG.md",
393
- self.project_root / "HISTORY.md"
409
+ self.project_root / "HISTORY.md",
394
410
  ]
395
-
411
+
396
412
  for changelog_path in changelog_paths:
397
413
  if changelog_path.exists():
398
414
  try:
399
415
  content = changelog_path.read_text()
400
-
416
+
401
417
  # Find all version entries
402
418
  for match in self._changelog_version_pattern.finditer(content):
403
419
  version = match.group(1).strip()
404
420
  date_str = match.group(2) if match.lastindex >= 2 else None
405
-
421
+
406
422
  # Parse release date
407
423
  release_date = None
408
424
  if date_str:
@@ -410,63 +426,67 @@ class EnhancedVersionParser:
410
426
  release_date = datetime.strptime(date_str, "%Y-%m-%d")
411
427
  except:
412
428
  pass
413
-
429
+
414
430
  # Extract changes for this version
415
- changes = self._extract_changelog_changes(content, match.start())
416
-
417
- versions.append(VersionMetadata(
418
- version=version,
419
- source=VersionSource.CHANGELOG,
420
- release_date=release_date,
421
- changes=changes
422
- ))
423
-
431
+ changes = self._extract_changelog_changes(
432
+ content, match.start()
433
+ )
434
+
435
+ versions.append(
436
+ VersionMetadata(
437
+ version=version,
438
+ source=VersionSource.CHANGELOG,
439
+ release_date=release_date,
440
+ changes=changes,
441
+ )
442
+ )
443
+
424
444
  if versions:
425
445
  break
426
446
  except Exception as e:
427
447
  self.logger.debug(f"Failed to parse changelog: {e}")
428
-
448
+
429
449
  return versions
430
-
450
+
431
451
  def _extract_changelog_changes(self, content: str, start_pos: int) -> List[str]:
432
452
  """Extract change entries for a specific version from changelog."""
433
453
  changes = []
434
- lines = content[start_pos:].split('\n')
435
-
454
+ lines = content[start_pos:].split("\n")
455
+
436
456
  in_changes = False
437
457
  for line in lines[1:]: # Skip the version header line
438
458
  # Stop at next version header
439
- if line.startswith('##'):
459
+ if line.startswith("##"):
440
460
  break
441
-
461
+
442
462
  # Collect change lines (usually start with -, *, or +)
443
- if line.strip().startswith(('-', '*', '+')):
463
+ if line.strip().startswith(("-", "*", "+")):
444
464
  changes.append(line.strip()[1:].strip())
445
465
  in_changes = True
446
- elif in_changes and line.strip() and not line.startswith('#'):
466
+ elif in_changes and line.strip() and not line.startswith("#"):
447
467
  # Continuation of previous change
448
468
  if changes:
449
- changes[-1] += ' ' + line.strip()
450
-
469
+ changes[-1] += " " + line.strip()
470
+
451
471
  return changes
452
-
472
+
453
473
  def _is_prerelease(self, version: str) -> bool:
454
474
  """Check if a version is a pre-release."""
455
475
  prerelease_patterns = [
456
- r'-(?:alpha|beta|rc|dev|pre)',
457
- r'\.(?:alpha|beta|rc|dev|pre)',
458
- r'(?:a|b|rc)\d+$'
476
+ r"-(?:alpha|beta|rc|dev|pre)",
477
+ r"\.(?:alpha|beta|rc|dev|pre)",
478
+ r"(?:a|b|rc)\d+$",
459
479
  ]
460
-
480
+
461
481
  for pattern in prerelease_patterns:
462
482
  if re.search(pattern, version, re.IGNORECASE):
463
483
  return True
464
484
  return False
465
-
485
+
466
486
  def _parse_semver(self, version: str) -> Tuple[int, int, int, str, str]:
467
487
  """
468
488
  Parse semantic version for sorting.
469
-
489
+
470
490
  Returns tuple of (major, minor, patch, prerelease, build)
471
491
  """
472
492
  match = self._version_pattern.match(version)
@@ -474,20 +494,20 @@ class EnhancedVersionParser:
474
494
  major = int(match.group(1))
475
495
  minor = int(match.group(2))
476
496
  patch = int(match.group(3))
477
- prerelease = match.group(4) or ''
478
- build = match.group(5) or ''
497
+ prerelease = match.group(4) or ""
498
+ build = match.group(5) or ""
479
499
  return (major, minor, patch, prerelease, build)
480
- return (0, 0, 0, '', '')
481
-
500
+ return (0, 0, 0, "", "")
501
+
482
502
  def validate_version_consistency(self) -> Dict[str, str]:
483
503
  """
484
504
  Validate version consistency across all sources.
485
-
505
+
486
506
  Returns:
487
507
  Dictionary mapping source names to versions found
488
508
  """
489
509
  versions = {}
490
-
510
+
491
511
  for source in VersionSource.PRIORITY_ORDER:
492
512
  try:
493
513
  version = self._get_version_from_source(source, latest_only=True)
@@ -495,16 +515,16 @@ class EnhancedVersionParser:
495
515
  versions[source] = version.version
496
516
  except Exception as e:
497
517
  self.logger.debug(f"Failed to check {source}: {e}")
498
-
518
+
499
519
  return versions
500
-
520
+
501
521
  def get_version_for_release(self) -> Optional[str]:
502
522
  """
503
523
  Get the version that should be used for the next release.
504
-
524
+
505
525
  This prioritizes git tags as the source of truth, falling back
506
526
  to VERSION file if no git tags exist.
507
-
527
+
508
528
  Returns:
509
529
  Version string for release, or None if no version found
510
530
  """
@@ -512,12 +532,12 @@ class EnhancedVersionParser:
512
532
  git_version = self._get_version_from_git(latest_only=True)
513
533
  if git_version:
514
534
  return git_version.version
515
-
535
+
516
536
  # Fall back to VERSION file
517
537
  file_version = self._get_version_from_file()
518
538
  if file_version:
519
539
  return file_version.version
520
-
540
+
521
541
  return None
522
542
 
523
543
 
@@ -525,4 +545,4 @@ class EnhancedVersionParser:
525
545
  @lru_cache(maxsize=1)
526
546
  def get_version_parser(project_root: Optional[Path] = None) -> EnhancedVersionParser:
527
547
  """Get a singleton instance of the version parser."""
528
- return EnhancedVersionParser(project_root)
548
+ return EnhancedVersionParser(project_root)