claude-mpm 3.9.11__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 (419) 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 +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 +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 +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 -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 +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 +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/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 +233 -199
  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 +30 -13
  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 +13 -20
  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 +87 -84
  298. claude_mpm/services/mcp_gateway/main.py +287 -137
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
  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 +109 -119
  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 +19 -533
  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 +2 -2
  358. claude_mpm/storage/state_storage.py +177 -181
  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.11.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +27 -1
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/cli/commands/run_guarded.py +0 -511
  385. claude_mpm/config/memory_guardian_config.py +0 -325
  386. claude_mpm/config/memory_guardian_yaml.py +0 -335
  387. claude_mpm/core/config_paths.py +0 -150
  388. claude_mpm/core/memory_aware_runner.py +0 -353
  389. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  390. claude_mpm/deployment_paths.py +0 -261
  391. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  392. claude_mpm/models/state_models.py +0 -433
  393. claude_mpm/services/agent/__init__.py +0 -24
  394. claude_mpm/services/agent/deployment.py +0 -2548
  395. claude_mpm/services/agent/management.py +0 -598
  396. claude_mpm/services/agent/registry.py +0 -813
  397. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  398. claude_mpm/services/communication/socketio.py +0 -1935
  399. claude_mpm/services/communication/websocket.py +0 -479
  400. claude_mpm/services/framework_claude_md_generator.py +0 -624
  401. claude_mpm/services/health_monitor.py +0 -893
  402. claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
  403. claude_mpm/services/infrastructure/health_monitor.py +0 -775
  404. claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
  405. claude_mpm/services/infrastructure/memory_guardian.py +0 -944
  406. claude_mpm/services/infrastructure/restart_protection.py +0 -642
  407. claude_mpm/services/infrastructure/state_manager.py +0 -774
  408. claude_mpm/services/mcp_gateway/manager.py +0 -334
  409. claude_mpm/services/optimized_hook_service.py +0 -542
  410. claude_mpm/services/project_analyzer.py +0 -864
  411. claude_mpm/services/project_registry.py +0 -608
  412. claude_mpm/services/standalone_socketio_server.py +0 -1300
  413. claude_mpm/services/ticket_manager_di.py +0 -318
  414. claude_mpm/services/ticketing_service_original.py +0 -510
  415. claude_mpm/utils/paths.py +0 -395
  416. claude_mpm/utils/platform_memory.py +0 -524
  417. claude_mpm-3.9.11.dist-info/RECORD +0 -306
  418. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  419. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,5 @@
1
+ from pathlib import Path
2
+
1
3
  #!/usr/bin/env python3
2
4
  """
3
5
  Agent Modification Tracker - Consolidated Service
@@ -28,29 +30,29 @@ import os
28
30
  import shutil
29
31
  import time
30
32
  import uuid
31
- from dataclasses import dataclass, field, asdict
33
+ from dataclasses import asdict, dataclass, field
32
34
  from datetime import datetime
33
35
  from enum import Enum
34
- from pathlib import Path
35
- from typing import Dict, List, Optional, Any, Callable, Tuple, Set
36
+ from typing import Any, Callable, Dict, List, Optional, Set, Tuple
36
37
 
38
+ from watchdog.events import FileSystemEvent, FileSystemEventHandler
37
39
  from watchdog.observers import Observer
38
- from watchdog.events import FileSystemEventHandler, FileSystemEvent
39
40
 
40
41
  from claude_mpm.core.base_service import BaseService
41
- from claude_mpm.core.config_paths import ConfigPaths
42
+ from claude_mpm.core.unified_agent_registry import UnifiedAgentRegistry as AgentRegistry
43
+ from claude_mpm.core.unified_paths import get_path_manager
42
44
  from claude_mpm.services.memory.cache.shared_prompt_cache import SharedPromptCache
43
- from .agent_registry import AgentRegistry
44
- from claude_mpm.utils.path_operations import path_ops
45
45
  from claude_mpm.utils.config_manager import ConfigurationManager
46
-
46
+ from claude_mpm.utils.path_operations import path_ops
47
47
 
48
48
  # ============================================================================
49
49
  # Data Models
50
50
  # ============================================================================
51
51
 
52
+
52
53
  class ModificationType(Enum):
53
54
  """Types of agent modifications."""
55
+
54
56
  CREATE = "create"
55
57
  MODIFY = "modify"
56
58
  DELETE = "delete"
@@ -60,6 +62,7 @@ class ModificationType(Enum):
60
62
 
61
63
  class ModificationTier(Enum):
62
64
  """Agent hierarchy tiers for modification tracking."""
65
+
63
66
  PROJECT = "project"
64
67
  USER = "user"
65
68
  SYSTEM = "system"
@@ -68,7 +71,7 @@ class ModificationTier(Enum):
68
71
  @dataclass
69
72
  class AgentModification:
70
73
  """Agent modification record with comprehensive metadata."""
71
-
74
+
72
75
  modification_id: str
73
76
  agent_name: str
74
77
  modification_type: ModificationType
@@ -86,58 +89,60 @@ class AgentModification:
86
89
  validation_errors: List[str] = field(default_factory=list)
87
90
  related_modifications: List[str] = field(default_factory=list)
88
91
  metadata: Dict[str, Any] = field(default_factory=dict)
89
-
92
+
90
93
  @property
91
94
  def modification_datetime(self) -> datetime:
92
95
  """Get modification timestamp as datetime."""
93
96
  return datetime.fromtimestamp(self.timestamp)
94
-
97
+
95
98
  @property
96
99
  def age_seconds(self) -> float:
97
100
  """Get age of modification in seconds."""
98
101
  return time.time() - self.timestamp
99
-
102
+
100
103
  def to_dict(self) -> Dict[str, Any]:
101
104
  """Convert to dictionary for serialization."""
102
105
  data = asdict(self)
103
- data['modification_type'] = self.modification_type.value
104
- data['tier'] = self.tier.value
106
+ data["modification_type"] = self.modification_type.value
107
+ data["tier"] = self.tier.value
105
108
  return data
106
-
109
+
107
110
  @classmethod
108
- def from_dict(cls, data: Dict[str, Any]) -> 'AgentModification':
111
+ def from_dict(cls, data: Dict[str, Any]) -> "AgentModification":
109
112
  """Create from dictionary."""
110
- data['modification_type'] = ModificationType(data['modification_type'])
111
- data['tier'] = ModificationTier(data['tier'])
113
+ data["modification_type"] = ModificationType(data["modification_type"])
114
+ data["tier"] = ModificationTier(data["tier"])
112
115
  return cls(**data)
113
116
 
114
117
 
115
118
  @dataclass
116
119
  class ModificationHistory:
117
120
  """Complete modification history for an agent."""
118
-
121
+
119
122
  agent_name: str
120
123
  modifications: List[AgentModification] = field(default_factory=list)
121
124
  current_version: Optional[str] = None
122
125
  total_modifications: int = 0
123
126
  first_seen: Optional[float] = None
124
127
  last_modified: Optional[float] = None
125
-
128
+
126
129
  def add_modification(self, modification: AgentModification) -> None:
127
130
  """Add a modification to history."""
128
131
  self.modifications.append(modification)
129
132
  self.total_modifications += 1
130
133
  self.last_modified = modification.timestamp
131
-
134
+
132
135
  if self.first_seen is None:
133
136
  self.first_seen = modification.timestamp
134
-
137
+
135
138
  def get_recent_modifications(self, hours: int = 24) -> List[AgentModification]:
136
139
  """Get modifications within specified hours."""
137
140
  cutoff = time.time() - (hours * 3600)
138
141
  return [mod for mod in self.modifications if mod.timestamp >= cutoff]
139
-
140
- def get_modifications_by_type(self, mod_type: ModificationType) -> List[AgentModification]:
142
+
143
+ def get_modifications_by_type(
144
+ self, mod_type: ModificationType
145
+ ) -> List[AgentModification]:
141
146
  """Get modifications by type."""
142
147
  return [mod for mod in self.modifications if mod.modification_type == mod_type]
143
148
 
@@ -146,37 +151,52 @@ class ModificationHistory:
146
151
  # File System Monitoring
147
152
  # ============================================================================
148
153
 
154
+
149
155
  class AgentFileSystemHandler(FileSystemEventHandler):
150
156
  """Handles file system events for agent files."""
151
-
152
- def __init__(self, tracker: 'AgentModificationTracker'):
157
+
158
+ def __init__(self, tracker: "AgentModificationTracker"):
153
159
  self.tracker = tracker
154
160
  self.logger = logging.getLogger(__name__)
155
-
161
+
156
162
  def on_created(self, event: FileSystemEvent) -> None:
157
163
  """Handle file creation events."""
158
- if not event.is_directory and event.src_path.endswith(('.md', '.json', '.yaml')):
164
+ if not event.is_directory and event.src_path.endswith(
165
+ (".md", ".json", ".yaml")
166
+ ):
159
167
  asyncio.create_task(
160
- self.tracker._handle_file_modification(event.src_path, ModificationType.CREATE)
168
+ self.tracker._handle_file_modification(
169
+ event.src_path, ModificationType.CREATE
170
+ )
161
171
  )
162
-
172
+
163
173
  def on_modified(self, event: FileSystemEvent) -> None:
164
174
  """Handle file modification events."""
165
- if not event.is_directory and event.src_path.endswith(('.md', '.json', '.yaml')):
175
+ if not event.is_directory and event.src_path.endswith(
176
+ (".md", ".json", ".yaml")
177
+ ):
166
178
  asyncio.create_task(
167
- self.tracker._handle_file_modification(event.src_path, ModificationType.MODIFY)
179
+ self.tracker._handle_file_modification(
180
+ event.src_path, ModificationType.MODIFY
181
+ )
168
182
  )
169
-
183
+
170
184
  def on_deleted(self, event: FileSystemEvent) -> None:
171
185
  """Handle file deletion events."""
172
- if not event.is_directory and event.src_path.endswith(('.md', '.json', '.yaml')):
186
+ if not event.is_directory and event.src_path.endswith(
187
+ (".md", ".json", ".yaml")
188
+ ):
173
189
  asyncio.create_task(
174
- self.tracker._handle_file_modification(event.src_path, ModificationType.DELETE)
190
+ self.tracker._handle_file_modification(
191
+ event.src_path, ModificationType.DELETE
192
+ )
175
193
  )
176
-
194
+
177
195
  def on_moved(self, event: FileSystemEvent) -> None:
178
196
  """Handle file move events."""
179
- if not event.is_directory and event.src_path.endswith(('.md', '.json', '.yaml')):
197
+ if not event.is_directory and event.src_path.endswith(
198
+ (".md", ".json", ".yaml")
199
+ ):
180
200
  asyncio.create_task(
181
201
  self.tracker._handle_file_move(event.src_path, event.dest_path)
182
202
  )
@@ -186,170 +206,183 @@ class AgentFileSystemHandler(FileSystemEventHandler):
186
206
  # Main Service Class
187
207
  # ============================================================================
188
208
 
209
+
189
210
  class AgentModificationTracker(BaseService):
190
211
  """
191
212
  Agent Modification Tracker - Comprehensive modification tracking and persistence system.
192
-
213
+
193
214
  This consolidated service combines all functionality from the previous multi-file
194
215
  implementation into a single, maintainable module.
195
216
  """
196
-
217
+
197
218
  def __init__(self, config: Optional[Dict[str, Any]] = None):
198
219
  """Initialize the agent modification tracker."""
199
220
  super().__init__("agent_modification_tracker", config)
200
-
221
+
201
222
  # Configuration
202
223
  self.enable_monitoring = self.get_config("enable_monitoring", True)
203
224
  self.backup_enabled = self.get_config("backup_enabled", True)
204
225
  self.max_history_days = self.get_config("max_history_days", 30)
205
226
  self.validation_enabled = self.get_config("validation_enabled", True)
206
227
  self.persistence_interval = self.get_config("persistence_interval", 300)
207
-
228
+
208
229
  # Core components
209
230
  self.shared_cache: Optional[SharedPromptCache] = None
210
231
  self.agent_registry: Optional[AgentRegistry] = None
211
-
232
+
212
233
  # Tracking data structures
213
234
  self.modification_history: Dict[str, ModificationHistory] = {}
214
235
  self.active_modifications: Dict[str, AgentModification] = {}
215
-
236
+
216
237
  # File monitoring
217
238
  self.file_observer: Optional[Observer] = None
218
239
  self.watched_paths: Set[Path] = set()
219
-
240
+
220
241
  # Persistence paths
221
- self.persistence_root = ConfigPaths.get_tracking_dir()
222
- self.backup_root = self.persistence_root / 'backups'
223
- self.history_root = self.persistence_root / 'history'
224
-
242
+ self.persistence_root = get_path_manager().get_tracking_dir()
243
+ self.backup_root = self.persistence_root / "backups"
244
+ self.history_root = self.persistence_root / "history"
245
+
225
246
  # Create directories
226
247
  self.persistence_root.mkdir(parents=True, exist_ok=True)
227
248
  self.backup_root.mkdir(parents=True, exist_ok=True)
228
249
  self.history_root.mkdir(parents=True, exist_ok=True)
229
-
250
+
230
251
  # Background tasks
231
252
  self._persistence_task: Optional[asyncio.Task] = None
232
253
  self._cleanup_task: Optional[asyncio.Task] = None
233
-
254
+
234
255
  # Callbacks
235
256
  self.modification_callbacks: List[Callable[[AgentModification], None]] = []
236
-
257
+
237
258
  self.logger.info(
238
259
  f"AgentModificationTracker initialized with monitoring="
239
260
  f"{'enabled' if self.enable_monitoring else 'disabled'}"
240
261
  )
241
-
262
+
242
263
  async def _initialize(self) -> None:
243
264
  """Initialize the modification tracker service."""
244
265
  self.logger.info("Initializing AgentModificationTracker service...")
245
-
266
+
246
267
  # Initialize cache and registry integration
247
268
  await self._initialize_integrations()
248
-
269
+
249
270
  # Load existing modification history
250
271
  await self._load_modification_history()
251
-
272
+
252
273
  # Set up file system monitoring
253
274
  if self.enable_monitoring:
254
275
  await self._setup_file_monitoring()
255
-
276
+
256
277
  # Start background tasks
257
278
  self._persistence_task = asyncio.create_task(self._persistence_loop())
258
279
  self._cleanup_task = asyncio.create_task(self._cleanup_loop())
259
-
280
+
260
281
  self.logger.info("AgentModificationTracker service initialized successfully")
261
-
282
+
262
283
  async def _cleanup(self) -> None:
263
284
  """Cleanup modification tracker resources."""
264
285
  self.logger.info("Cleaning up AgentModificationTracker service...")
265
-
286
+
266
287
  # Stop file system monitoring
267
288
  if self.enable_monitoring and self.file_observer:
268
289
  self.file_observer.stop()
269
290
  self.file_observer.join()
270
-
291
+
271
292
  # Cancel background tasks
272
293
  if self._persistence_task:
273
294
  self._persistence_task.cancel()
274
295
  if self._cleanup_task:
275
296
  self._cleanup_task.cancel()
276
-
297
+
277
298
  # Save final state
278
299
  await self._save_modification_history()
279
-
300
+
280
301
  self.logger.info("AgentModificationTracker service cleaned up")
281
-
302
+
282
303
  async def _health_check(self) -> Dict[str, bool]:
283
304
  """Perform modification tracker health checks."""
284
305
  checks = {}
285
-
306
+
286
307
  try:
287
308
  # Check persistence directories
288
- checks["persistence_directories"] = all([
289
- self.persistence_root.exists(),
290
- self.backup_root.exists(),
291
- self.history_root.exists()
292
- ])
293
-
309
+ checks["persistence_directories"] = all(
310
+ [
311
+ self.persistence_root.exists(),
312
+ self.backup_root.exists(),
313
+ self.history_root.exists(),
314
+ ]
315
+ )
316
+
294
317
  # Check file system monitoring
295
318
  checks["file_monitoring"] = (
296
- self.file_observer is not None and
297
- self.file_observer.is_alive()
298
- ) if self.enable_monitoring else True
299
-
319
+ (self.file_observer is not None and self.file_observer.is_alive())
320
+ if self.enable_monitoring
321
+ else True
322
+ )
323
+
300
324
  # Check integration components
301
325
  checks["cache_integration"] = self.shared_cache is not None
302
326
  checks["registry_integration"] = self.agent_registry is not None
303
-
327
+
304
328
  # Check background tasks
305
329
  checks["persistence_task"] = (
306
- self._persistence_task is not None and
307
- not self._persistence_task.done()
330
+ self._persistence_task is not None and not self._persistence_task.done()
308
331
  )
309
332
  checks["cleanup_task"] = (
310
- self._cleanup_task is not None and
311
- not self._cleanup_task.done()
333
+ self._cleanup_task is not None and not self._cleanup_task.done()
312
334
  )
313
-
335
+
314
336
  checks["modification_tracking"] = True
315
-
337
+
316
338
  except Exception as e:
317
339
  self.logger.error(f"Modification tracker health check failed: {e}")
318
340
  checks["health_check_error"] = False
319
-
341
+
320
342
  return checks
321
-
343
+
322
344
  # ========================================================================
323
345
  # Core Functionality
324
346
  # ========================================================================
325
-
326
- async def track_modification(self,
327
- agent_name: str,
328
- modification_type: ModificationType,
329
- file_path: str,
330
- tier: ModificationTier,
331
- **kwargs) -> AgentModification:
347
+
348
+ async def track_modification(
349
+ self,
350
+ agent_name: str,
351
+ modification_type: ModificationType,
352
+ file_path: str,
353
+ tier: ModificationTier,
354
+ **kwargs,
355
+ ) -> AgentModification:
332
356
  """Track an agent modification with comprehensive metadata collection."""
333
357
  # Generate modification ID
334
- modification_id = f"{agent_name}_{modification_type.value}_{uuid.uuid4().hex[:8]}"
335
-
358
+ modification_id = (
359
+ f"{agent_name}_{modification_type.value}_{uuid.uuid4().hex[:8]}"
360
+ )
361
+
336
362
  # Collect file metadata
337
363
  file_metadata = await self._collect_file_metadata(file_path, modification_type)
338
-
364
+
339
365
  # Create backup if enabled
340
366
  backup_path = None
341
- if self.backup_enabled and modification_type in [ModificationType.MODIFY, ModificationType.DELETE]:
367
+ if self.backup_enabled and modification_type in [
368
+ ModificationType.MODIFY,
369
+ ModificationType.DELETE,
370
+ ]:
342
371
  backup_path = await self._create_backup(file_path, modification_id)
343
-
372
+
344
373
  # Create modification record
345
374
  # Only include valid AgentModification fields from file_metadata
346
- valid_metadata_fields = {'file_hash_after', 'file_size_after'}
347
- filtered_metadata = {k: v for k, v in file_metadata.items() if k in valid_metadata_fields}
348
-
375
+ valid_metadata_fields = {"file_hash_after", "file_size_after"}
376
+ filtered_metadata = {
377
+ k: v for k, v in file_metadata.items() if k in valid_metadata_fields
378
+ }
379
+
349
380
  # Add other metadata to the metadata field
350
- extra_metadata = {k: v for k, v in file_metadata.items() if k not in valid_metadata_fields}
381
+ extra_metadata = {
382
+ k: v for k, v in file_metadata.items() if k not in valid_metadata_fields
383
+ }
351
384
  extra_metadata.update(kwargs)
352
-
385
+
353
386
  modification = AgentModification(
354
387
  modification_id=modification_id,
355
388
  agent_name=agent_name,
@@ -359,39 +392,41 @@ class AgentModificationTracker(BaseService):
359
392
  timestamp=time.time(),
360
393
  backup_path=backup_path,
361
394
  metadata=extra_metadata,
362
- **filtered_metadata
395
+ **filtered_metadata,
363
396
  )
364
-
397
+
365
398
  # Validate modification if enabled
366
399
  if self.validation_enabled:
367
400
  await self._validate_modification(modification)
368
-
401
+
369
402
  # Store in active modifications
370
403
  self.active_modifications[modification_id] = modification
371
-
404
+
372
405
  # Add to history
373
406
  if agent_name not in self.modification_history:
374
- self.modification_history[agent_name] = ModificationHistory(agent_name=agent_name)
375
-
407
+ self.modification_history[agent_name] = ModificationHistory(
408
+ agent_name=agent_name
409
+ )
410
+
376
411
  self.modification_history[agent_name].add_modification(modification)
377
-
412
+
378
413
  # Invalidate cache
379
414
  if self.shared_cache:
380
415
  await self._invalidate_agent_cache(agent_name)
381
-
416
+
382
417
  # Trigger callbacks
383
418
  await self._trigger_modification_callbacks(modification)
384
-
419
+
385
420
  self.logger.info(
386
421
  f"Tracked {modification_type.value} modification for agent '{agent_name}': {modification_id}"
387
422
  )
388
-
423
+
389
424
  return modification
390
-
425
+
391
426
  # ========================================================================
392
427
  # Helper Methods
393
428
  # ========================================================================
394
-
429
+
395
430
  async def _initialize_integrations(self) -> None:
396
431
  """Initialize cache and registry integrations."""
397
432
  try:
@@ -400,115 +435,125 @@ class AgentModificationTracker(BaseService):
400
435
  self.logger.info("Successfully initialized cache and registry integrations")
401
436
  except Exception as e:
402
437
  self.logger.warning(f"Failed to initialize integrations: {e}")
403
-
438
+
404
439
  async def _setup_file_monitoring(self) -> None:
405
440
  """Set up file system monitoring for agent files."""
406
441
  try:
407
442
  self.file_observer = Observer()
408
443
  event_handler = AgentFileSystemHandler(self)
409
-
444
+
410
445
  # Monitor standard agent directories
411
446
  agent_dirs = [
412
447
  Path("agents"),
413
448
  Path("src/claude_mpm/agents"),
414
- ConfigPaths.get_user_agents_dir()
449
+ get_path_manager().get_user_agents_dir(),
415
450
  ]
416
-
451
+
417
452
  for agent_dir in agent_dirs:
418
453
  if agent_dir.exists():
419
- self.file_observer.schedule(event_handler, str(agent_dir), recursive=True)
454
+ self.file_observer.schedule(
455
+ event_handler, str(agent_dir), recursive=True
456
+ )
420
457
  self.watched_paths.add(agent_dir)
421
458
  self.logger.info(f"Monitoring agent directory: {agent_dir}")
422
-
459
+
423
460
  self.file_observer.start()
424
-
461
+
425
462
  except Exception as e:
426
463
  self.logger.error(f"Failed to setup file monitoring: {e}")
427
-
428
- async def _collect_file_metadata(self, file_path: str, modification_type: ModificationType) -> Dict[str, Any]:
464
+
465
+ async def _collect_file_metadata(
466
+ self, file_path: str, modification_type: ModificationType
467
+ ) -> Dict[str, Any]:
429
468
  """Collect comprehensive file metadata."""
430
469
  metadata = {}
431
-
470
+
432
471
  try:
433
472
  path = Path(file_path)
434
-
473
+
435
474
  if path.exists() and modification_type != ModificationType.DELETE:
436
475
  # File size
437
- metadata['file_size_after'] = path.stat().st_size
438
-
476
+ metadata["file_size_after"] = path.stat().st_size
477
+
439
478
  # File hash
440
- with open(path, 'rb') as f:
441
- metadata['file_hash_after'] = hashlib.sha256(f.read()).hexdigest()
442
-
479
+ with open(path, "rb") as f:
480
+ metadata["file_hash_after"] = hashlib.sha256(f.read()).hexdigest()
481
+
443
482
  # File type
444
- metadata['file_type'] = path.suffix
445
-
483
+ metadata["file_type"] = path.suffix
484
+
446
485
  # Modification time
447
- metadata['mtime'] = path.stat().st_mtime
448
-
486
+ metadata["mtime"] = path.stat().st_mtime
487
+
449
488
  except Exception as e:
450
489
  self.logger.error(f"Error collecting file metadata: {e}")
451
-
490
+
452
491
  return metadata
453
-
454
- async def _create_backup(self, file_path: str, modification_id: str) -> Optional[str]:
492
+
493
+ async def _create_backup(
494
+ self, file_path: str, modification_id: str
495
+ ) -> Optional[str]:
455
496
  """Create backup of agent file."""
456
497
  try:
457
498
  source = Path(file_path)
458
499
  if not source.exists():
459
500
  return None
460
-
501
+
461
502
  # Create backup directory for this modification
462
503
  backup_dir = self.backup_root / modification_id
463
504
  backup_dir.mkdir(parents=True, exist_ok=True)
464
-
505
+
465
506
  # Create backup file
466
507
  backup_path = backup_dir / source.name
467
508
  shutil.copy2(source, backup_path)
468
-
509
+
469
510
  # Save backup metadata
470
511
  metadata = {
471
- 'original_path': str(file_path),
472
- 'backup_time': time.time(),
473
- 'modification_id': modification_id
512
+ "original_path": str(file_path),
513
+ "backup_time": time.time(),
514
+ "modification_id": modification_id,
474
515
  }
475
-
476
- metadata_path = backup_dir / 'metadata.json'
477
- with open(metadata_path, 'w') as f:
516
+
517
+ metadata_path = backup_dir / "metadata.json"
518
+ with open(metadata_path, "w") as f:
478
519
  json.dump(metadata, f, indent=2)
479
-
520
+
480
521
  return str(backup_path)
481
-
522
+
482
523
  except Exception as e:
483
524
  self.logger.error(f"Failed to create backup: {e}")
484
525
  return None
485
-
526
+
486
527
  async def _validate_modification(self, modification: AgentModification) -> None:
487
528
  """Validate agent modification."""
488
529
  errors = []
489
-
530
+
490
531
  try:
491
532
  # Check for conflicts
492
533
  for mod_id, active_mod in self.active_modifications.items():
493
- if (active_mod.agent_name == modification.agent_name and
494
- active_mod.modification_id != modification.modification_id and
495
- active_mod.age_seconds < 60): # Recent modification
496
- errors.append(f"Potential conflict with recent modification: {mod_id}")
497
-
534
+ if (
535
+ active_mod.agent_name == modification.agent_name
536
+ and active_mod.modification_id != modification.modification_id
537
+ and active_mod.age_seconds < 60
538
+ ): # Recent modification
539
+ errors.append(
540
+ f"Potential conflict with recent modification: {mod_id}"
541
+ )
542
+
498
543
  # Validate file path
499
544
  if modification.modification_type != ModificationType.DELETE:
500
545
  if not Path(modification.file_path).exists():
501
546
  errors.append(f"File does not exist: {modification.file_path}")
502
-
547
+
503
548
  # Update validation status
504
549
  modification.validation_status = "failed" if errors else "passed"
505
550
  modification.validation_errors = errors
506
-
551
+
507
552
  except Exception as e:
508
553
  self.logger.error(f"Validation error: {e}")
509
554
  modification.validation_status = "error"
510
555
  modification.validation_errors.append(str(e))
511
-
556
+
512
557
  async def _invalidate_agent_cache(self, agent_name: str) -> None:
513
558
  """Invalidate cache entries for modified agent."""
514
559
  if self.shared_cache:
@@ -518,34 +563,36 @@ class AgentModificationTracker(BaseService):
518
563
  self.logger.debug(f"Invalidated cache for agent: {agent_name}")
519
564
  except Exception as e:
520
565
  self.logger.error(f"Failed to invalidate cache: {e}")
521
-
522
- async def _handle_file_modification(self, file_path: str, modification_type: ModificationType) -> None:
566
+
567
+ async def _handle_file_modification(
568
+ self, file_path: str, modification_type: ModificationType
569
+ ) -> None:
523
570
  """Handle file system modification events."""
524
571
  try:
525
572
  # Extract agent information from path
526
573
  agent_info = self._extract_agent_info_from_path(file_path)
527
574
  if not agent_info:
528
575
  return
529
-
576
+
530
577
  agent_name, tier = agent_info
531
-
578
+
532
579
  # Track the modification
533
580
  await self.track_modification(
534
581
  agent_name=agent_name,
535
582
  modification_type=modification_type,
536
583
  file_path=file_path,
537
584
  tier=tier,
538
- source="file_system_monitor"
585
+ source="file_system_monitor",
539
586
  )
540
-
587
+
541
588
  except Exception as e:
542
589
  self.logger.error(f"Error handling file modification {file_path}: {e}")
543
-
590
+
544
591
  async def _handle_file_move(self, src_path: str, dest_path: str) -> None:
545
592
  """Handle file move events."""
546
593
  try:
547
594
  src_info = self._extract_agent_info_from_path(src_path)
548
-
595
+
549
596
  if src_info:
550
597
  agent_name, tier = src_info
551
598
  await self.track_modification(
@@ -555,39 +602,48 @@ class AgentModificationTracker(BaseService):
555
602
  tier=tier,
556
603
  source="file_system_monitor",
557
604
  move_source=src_path,
558
- move_destination=dest_path
605
+ move_destination=dest_path,
559
606
  )
560
-
607
+
561
608
  except Exception as e:
562
- self.logger.error(f"Error handling file move {src_path} -> {dest_path}: {e}")
563
-
564
- def _extract_agent_info_from_path(self, file_path: str) -> Optional[Tuple[str, ModificationTier]]:
609
+ self.logger.error(
610
+ f"Error handling file move {src_path} -> {dest_path}: {e}"
611
+ )
612
+
613
+ def _extract_agent_info_from_path(
614
+ self, file_path: str
615
+ ) -> Optional[Tuple[str, ModificationTier]]:
565
616
  """Extract agent name and tier from file path."""
566
617
  try:
567
618
  path = Path(file_path)
568
-
619
+
569
620
  # Extract agent name from filename
570
621
  agent_name = path.stem
571
- if agent_name.endswith('_agent'):
622
+ if agent_name.endswith("_agent"):
572
623
  agent_name = agent_name[:-6] # Remove _agent suffix
573
- elif agent_name.endswith('-agent'):
624
+ elif agent_name.endswith("-agent"):
574
625
  agent_name = agent_name[:-6] # Remove -agent suffix
575
-
626
+
576
627
  # Determine tier based on path
577
628
  path_str = str(path).lower()
578
- if 'system' in path_str or '/claude_mpm/agents/' in path_str:
629
+ if "system" in path_str or "/claude_mpm/agents/" in path_str:
579
630
  tier = ModificationTier.SYSTEM
580
- elif ConfigPaths.CONFIG_DIR.lower() in path_str or str(Path.home()) in path_str:
631
+ elif (
632
+ get_path_manager().CONFIG_DIR.lower() in path_str
633
+ or str(Path.home()) in path_str
634
+ ):
581
635
  tier = ModificationTier.USER
582
636
  else:
583
637
  tier = ModificationTier.PROJECT
584
-
638
+
585
639
  return agent_name, tier
586
-
640
+
587
641
  except Exception:
588
642
  return None
589
-
590
- async def _trigger_modification_callbacks(self, modification: AgentModification) -> None:
643
+
644
+ async def _trigger_modification_callbacks(
645
+ self, modification: AgentModification
646
+ ) -> None:
591
647
  """Trigger registered modification callbacks."""
592
648
  for callback in self.modification_callbacks:
593
649
  try:
@@ -597,78 +653,78 @@ class AgentModificationTracker(BaseService):
597
653
  callback(modification)
598
654
  except Exception as e:
599
655
  self.logger.error(f"Modification callback failed: {e}")
600
-
656
+
601
657
  # ========================================================================
602
658
  # Persistence Methods
603
659
  # ========================================================================
604
-
660
+
605
661
  async def _load_modification_history(self) -> None:
606
662
  """Load modification history from disk."""
607
663
  try:
608
664
  # Load active modifications
609
- active_path = self.persistence_root / 'active_modifications.json'
665
+ active_path = self.persistence_root / "active_modifications.json"
610
666
  if active_path.exists():
611
- with open(active_path, 'r') as f:
667
+ with open(active_path, "r") as f:
612
668
  data = json.load(f)
613
669
  self.active_modifications = {
614
670
  k: AgentModification.from_dict(v) for k, v in data.items()
615
671
  }
616
-
672
+
617
673
  # Load modification history
618
- for history_file in self.history_root.glob('*.json'):
619
- with open(history_file, 'r') as f:
674
+ for history_file in self.history_root.glob("*.json"):
675
+ with open(history_file, "r") as f:
620
676
  data = json.load(f)
621
- agent_name = data['agent_name']
677
+ agent_name = data["agent_name"]
622
678
  history = ModificationHistory(agent_name=agent_name)
623
-
679
+
624
680
  # Recreate modifications
625
- for mod_data in data.get('modifications', []):
681
+ for mod_data in data.get("modifications", []):
626
682
  history.add_modification(AgentModification.from_dict(mod_data))
627
-
628
- history.current_version = data.get('current_version')
629
- history.first_seen = data.get('first_seen')
630
- history.last_modified = data.get('last_modified')
631
-
683
+
684
+ history.current_version = data.get("current_version")
685
+ history.first_seen = data.get("first_seen")
686
+ history.last_modified = data.get("last_modified")
687
+
632
688
  self.modification_history[agent_name] = history
633
-
689
+
634
690
  self.logger.info(
635
691
  f"Loaded {len(self.active_modifications)} active modifications and "
636
692
  f"{len(self.modification_history)} agent histories"
637
693
  )
638
-
694
+
639
695
  except Exception as e:
640
696
  self.logger.error(f"Failed to load modification history: {e}")
641
-
697
+
642
698
  async def _save_modification_history(self) -> None:
643
699
  """Save modification history to disk."""
644
700
  try:
645
701
  # Save active modifications
646
702
  active_data = {k: v.to_dict() for k, v in self.active_modifications.items()}
647
- active_path = self.persistence_root / 'active_modifications.json'
648
-
649
- with open(active_path, 'w') as f:
703
+ active_path = self.persistence_root / "active_modifications.json"
704
+
705
+ with open(active_path, "w") as f:
650
706
  json.dump(active_data, f, indent=2)
651
-
707
+
652
708
  # Save modification history
653
709
  for agent_name, history in self.modification_history.items():
654
710
  history_data = {
655
- 'agent_name': history.agent_name,
656
- 'modifications': [mod.to_dict() for mod in history.modifications],
657
- 'current_version': history.current_version,
658
- 'total_modifications': history.total_modifications,
659
- 'first_seen': history.first_seen,
660
- 'last_modified': history.last_modified
711
+ "agent_name": history.agent_name,
712
+ "modifications": [mod.to_dict() for mod in history.modifications],
713
+ "current_version": history.current_version,
714
+ "total_modifications": history.total_modifications,
715
+ "first_seen": history.first_seen,
716
+ "last_modified": history.last_modified,
661
717
  }
662
-
718
+
663
719
  history_path = self.history_root / f"{agent_name}_history.json"
664
- with open(history_path, 'w') as f:
720
+ with open(history_path, "w") as f:
665
721
  json.dump(history_data, f, indent=2)
666
-
722
+
667
723
  self.logger.debug("Saved modification history to disk")
668
-
724
+
669
725
  except Exception as e:
670
726
  self.logger.error(f"Failed to save modification history: {e}")
671
-
727
+
672
728
  async def _persistence_loop(self) -> None:
673
729
  """Background task to persist modification history."""
674
730
  while not self._stop_event.is_set():
@@ -680,7 +736,7 @@ class AgentModificationTracker(BaseService):
680
736
  except Exception as e:
681
737
  self.logger.error(f"Persistence loop error: {e}")
682
738
  await asyncio.sleep(self.persistence_interval)
683
-
739
+
684
740
  async def _cleanup_loop(self) -> None:
685
741
  """Background task to cleanup old modifications and backups."""
686
742
  while not self._stop_event.is_set():
@@ -692,159 +748,169 @@ class AgentModificationTracker(BaseService):
692
748
  except Exception as e:
693
749
  self.logger.error(f"Cleanup loop error: {e}")
694
750
  await asyncio.sleep(3600)
695
-
751
+
696
752
  async def _cleanup_old_data(self) -> None:
697
753
  """Clean up old modifications and backups."""
698
754
  try:
699
755
  cutoff_time = time.time() - (self.max_history_days * 24 * 3600)
700
-
756
+
701
757
  # Clean up old modifications from active list
702
758
  old_active = [
703
- mod_id for mod_id, mod in self.active_modifications.items()
759
+ mod_id
760
+ for mod_id, mod in self.active_modifications.items()
704
761
  if mod.timestamp < cutoff_time
705
762
  ]
706
-
763
+
707
764
  for mod_id in old_active:
708
765
  del self.active_modifications[mod_id]
709
-
766
+
710
767
  # Clean up old backups
711
768
  backup_count = 0
712
769
  for backup_dir in self.backup_root.iterdir():
713
770
  if backup_dir.is_dir():
714
- metadata_path = backup_dir / 'metadata.json'
771
+ metadata_path = backup_dir / "metadata.json"
715
772
  if metadata_path.exists():
716
- with open(metadata_path, 'r') as f:
773
+ with open(metadata_path, "r") as f:
717
774
  metadata = json.load(f)
718
- if metadata.get('backup_time', 0) < cutoff_time:
775
+ if metadata.get("backup_time", 0) < cutoff_time:
719
776
  shutil.rmtree(backup_dir)
720
777
  backup_count += 1
721
-
778
+
722
779
  if old_active or backup_count > 0:
723
780
  self.logger.info(
724
781
  f"Cleaned up {len(old_active)} old modifications and {backup_count} old backups"
725
782
  )
726
-
783
+
727
784
  except Exception as e:
728
785
  self.logger.error(f"Failed to cleanup old data: {e}")
729
-
786
+
730
787
  # ========================================================================
731
788
  # Public API Methods
732
789
  # ========================================================================
733
-
734
- async def get_modification_history(self, agent_name: str) -> Optional[ModificationHistory]:
790
+
791
+ async def get_modification_history(
792
+ self, agent_name: str
793
+ ) -> Optional[ModificationHistory]:
735
794
  """Get modification history for specific agent."""
736
795
  return self.modification_history.get(agent_name)
737
-
738
- async def get_recent_modifications(self, hours: int = 24) -> List[AgentModification]:
796
+
797
+ async def get_recent_modifications(
798
+ self, hours: int = 24
799
+ ) -> List[AgentModification]:
739
800
  """Get all recent modifications across all agents."""
740
801
  cutoff = time.time() - (hours * 3600)
741
802
  recent = []
742
-
803
+
743
804
  for history in self.modification_history.values():
744
- recent.extend([
745
- mod for mod in history.modifications
746
- if mod.timestamp >= cutoff
747
- ])
748
-
805
+ recent.extend(
806
+ [mod for mod in history.modifications if mod.timestamp >= cutoff]
807
+ )
808
+
749
809
  return sorted(recent, key=lambda x: x.timestamp, reverse=True)
750
-
810
+
751
811
  async def restore_agent_backup(self, modification_id: str) -> bool:
752
812
  """Restore agent from backup."""
753
813
  try:
754
814
  modification = self.active_modifications.get(modification_id)
755
815
  if not modification or not modification.backup_path:
756
816
  return False
757
-
817
+
758
818
  # Restore from backup
759
819
  backup_path = Path(modification.backup_path)
760
820
  if not backup_path.exists():
761
821
  return False
762
-
822
+
763
823
  original_path = Path(modification.file_path)
764
824
  shutil.copy2(backup_path, original_path)
765
-
825
+
766
826
  # Track restore operation
767
827
  await self.track_modification(
768
828
  agent_name=modification.agent_name,
769
829
  modification_type=ModificationType.RESTORE,
770
830
  file_path=modification.file_path,
771
831
  tier=modification.tier,
772
- restored_from=modification_id
832
+ restored_from=modification_id,
773
833
  )
774
-
834
+
775
835
  return True
776
-
836
+
777
837
  except Exception as e:
778
838
  self.logger.error(f"Failed to restore agent backup: {e}")
779
839
  return False
780
-
840
+
781
841
  async def get_modification_stats(self) -> Dict[str, Any]:
782
842
  """Get comprehensive modification statistics."""
783
843
  stats = {
784
- 'total_agents_tracked': len(self.modification_history),
785
- 'total_modifications': sum(h.total_modifications for h in self.modification_history.values()),
786
- 'active_modifications': len(self.active_modifications),
787
- 'watched_paths': len(self.watched_paths),
788
- 'monitoring_enabled': self.enable_monitoring,
789
- 'backup_enabled': self.backup_enabled,
790
- 'validation_enabled': self.validation_enabled
844
+ "total_agents_tracked": len(self.modification_history),
845
+ "total_modifications": sum(
846
+ h.total_modifications for h in self.modification_history.values()
847
+ ),
848
+ "active_modifications": len(self.active_modifications),
849
+ "watched_paths": len(self.watched_paths),
850
+ "monitoring_enabled": self.enable_monitoring,
851
+ "backup_enabled": self.backup_enabled,
852
+ "validation_enabled": self.validation_enabled,
791
853
  }
792
-
854
+
793
855
  # Modification type breakdown
794
856
  type_counts = {}
795
857
  for history in self.modification_history.values():
796
858
  for mod in history.modifications:
797
- type_counts[mod.modification_type.value] = type_counts.get(mod.modification_type.value, 0) + 1
798
-
799
- stats['modifications_by_type'] = type_counts
800
-
859
+ type_counts[mod.modification_type.value] = (
860
+ type_counts.get(mod.modification_type.value, 0) + 1
861
+ )
862
+
863
+ stats["modifications_by_type"] = type_counts
864
+
801
865
  # Tier breakdown
802
866
  tier_counts = {}
803
867
  for history in self.modification_history.values():
804
868
  for mod in history.modifications:
805
869
  tier_counts[mod.tier.value] = tier_counts.get(mod.tier.value, 0) + 1
806
-
807
- stats['modifications_by_tier'] = tier_counts
808
-
870
+
871
+ stats["modifications_by_tier"] = tier_counts
872
+
809
873
  # Recent activity
810
874
  recent_24h = await self.get_recent_modifications(24)
811
875
  recent_7d = await self.get_recent_modifications(24 * 7)
812
-
813
- stats['recent_activity'] = {
814
- 'last_24_hours': len(recent_24h),
815
- 'last_7_days': len(recent_7d)
876
+
877
+ stats["recent_activity"] = {
878
+ "last_24_hours": len(recent_24h),
879
+ "last_7_days": len(recent_7d),
816
880
  }
817
-
881
+
818
882
  # Validation stats
819
- validation_stats = {
820
- 'passed': 0,
821
- 'failed': 0,
822
- 'pending': 0,
823
- 'error': 0
824
- }
825
-
883
+ validation_stats = {"passed": 0, "failed": 0, "pending": 0, "error": 0}
884
+
826
885
  for mod in self.active_modifications.values():
827
- validation_stats[mod.validation_status] = validation_stats.get(mod.validation_status, 0) + 1
828
-
829
- stats['validation_stats'] = validation_stats
830
-
886
+ validation_stats[mod.validation_status] = (
887
+ validation_stats.get(mod.validation_status, 0) + 1
888
+ )
889
+
890
+ stats["validation_stats"] = validation_stats
891
+
831
892
  # Backup stats
832
893
  backup_stats = {
833
- 'total_backups': len(list(self.backup_root.iterdir())),
834
- 'backup_size_mb': sum(
835
- f.stat().st_size for f in self.backup_root.rglob('*') if f.is_file()
836
- ) / (1024 * 1024)
894
+ "total_backups": len(list(self.backup_root.iterdir())),
895
+ "backup_size_mb": sum(
896
+ f.stat().st_size for f in self.backup_root.rglob("*") if f.is_file()
897
+ )
898
+ / (1024 * 1024),
837
899
  }
838
-
839
- stats['backup_stats'] = backup_stats
840
-
900
+
901
+ stats["backup_stats"] = backup_stats
902
+
841
903
  return stats
842
-
843
- def register_modification_callback(self, callback: Callable[[AgentModification], None]) -> None:
904
+
905
+ def register_modification_callback(
906
+ self, callback: Callable[[AgentModification], None]
907
+ ) -> None:
844
908
  """Register callback for modification events."""
845
909
  self.modification_callbacks.append(callback)
846
-
847
- def unregister_modification_callback(self, callback: Callable[[AgentModification], None]) -> None:
910
+
911
+ def unregister_modification_callback(
912
+ self, callback: Callable[[AgentModification], None]
913
+ ) -> None:
848
914
  """Unregister modification callback."""
849
915
  if callback in self.modification_callbacks:
850
- self.modification_callbacks.remove(callback)
916
+ self.modification_callbacks.remove(callback)