claude-mpm 4.1.0__py3-none-any.whl → 4.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/__main__.py +1 -1
  4. claude_mpm/agents/BASE_PM.md +74 -46
  5. claude_mpm/agents/INSTRUCTIONS.md +11 -153
  6. claude_mpm/agents/WORKFLOW.md +61 -321
  7. claude_mpm/agents/__init__.py +11 -11
  8. claude_mpm/agents/agent_loader.py +23 -20
  9. claude_mpm/agents/agent_loader_integration.py +1 -1
  10. claude_mpm/agents/agents_metadata.py +27 -0
  11. claude_mpm/agents/async_agent_loader.py +5 -8
  12. claude_mpm/agents/base_agent_loader.py +36 -25
  13. claude_mpm/agents/frontmatter_validator.py +6 -6
  14. claude_mpm/agents/schema/agent_schema.json +1 -1
  15. claude_mpm/agents/system_agent_config.py +9 -9
  16. claude_mpm/agents/templates/api_qa.json +47 -2
  17. claude_mpm/agents/templates/imagemagick.json +256 -0
  18. claude_mpm/agents/templates/qa.json +41 -2
  19. claude_mpm/agents/templates/ticketing.json +5 -5
  20. claude_mpm/agents/templates/web_qa.json +133 -58
  21. claude_mpm/agents/templates/web_ui.json +3 -3
  22. claude_mpm/cli/__init__.py +51 -46
  23. claude_mpm/cli/__main__.py +1 -1
  24. claude_mpm/cli/commands/__init__.py +10 -12
  25. claude_mpm/cli/commands/agent_manager.py +186 -181
  26. claude_mpm/cli/commands/agents.py +271 -268
  27. claude_mpm/cli/commands/aggregate.py +30 -29
  28. claude_mpm/cli/commands/cleanup.py +50 -44
  29. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  30. claude_mpm/cli/commands/config.py +162 -127
  31. claude_mpm/cli/commands/doctor.py +52 -62
  32. claude_mpm/cli/commands/info.py +37 -25
  33. claude_mpm/cli/commands/mcp.py +3 -7
  34. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  35. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  36. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  37. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  38. claude_mpm/cli/commands/memory.py +192 -141
  39. claude_mpm/cli/commands/monitor.py +117 -88
  40. claude_mpm/cli/commands/run.py +120 -84
  41. claude_mpm/cli/commands/run_config_checker.py +4 -5
  42. claude_mpm/cli/commands/socketio_monitor.py +17 -19
  43. claude_mpm/cli/commands/tickets.py +92 -92
  44. claude_mpm/cli/parser.py +1 -5
  45. claude_mpm/cli/parsers/__init__.py +1 -1
  46. claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
  47. claude_mpm/cli/parsers/agents_parser.py +2 -3
  48. claude_mpm/cli/parsers/base_parser.py +7 -5
  49. claude_mpm/cli/parsers/mcp_parser.py +4 -2
  50. claude_mpm/cli/parsers/monitor_parser.py +26 -18
  51. claude_mpm/cli/shared/__init__.py +10 -10
  52. claude_mpm/cli/shared/argument_patterns.py +57 -71
  53. claude_mpm/cli/shared/base_command.py +61 -53
  54. claude_mpm/cli/shared/error_handling.py +62 -58
  55. claude_mpm/cli/shared/output_formatters.py +78 -77
  56. claude_mpm/cli/startup_logging.py +204 -172
  57. claude_mpm/cli/utils.py +10 -11
  58. claude_mpm/cli_module/__init__.py +1 -1
  59. claude_mpm/cli_module/args.py +1 -1
  60. claude_mpm/cli_module/migration_example.py +5 -5
  61. claude_mpm/config/__init__.py +9 -9
  62. claude_mpm/config/agent_config.py +15 -14
  63. claude_mpm/config/experimental_features.py +4 -4
  64. claude_mpm/config/paths.py +0 -1
  65. claude_mpm/config/socketio_config.py +5 -6
  66. claude_mpm/constants.py +1 -2
  67. claude_mpm/core/__init__.py +8 -8
  68. claude_mpm/core/agent_name_normalizer.py +1 -1
  69. claude_mpm/core/agent_registry.py +20 -23
  70. claude_mpm/core/agent_session_manager.py +3 -3
  71. claude_mpm/core/base_service.py +7 -15
  72. claude_mpm/core/cache.py +4 -6
  73. claude_mpm/core/claude_runner.py +85 -113
  74. claude_mpm/core/config.py +43 -28
  75. claude_mpm/core/config_aliases.py +0 -9
  76. claude_mpm/core/config_constants.py +52 -30
  77. claude_mpm/core/constants.py +0 -1
  78. claude_mpm/core/container.py +18 -27
  79. claude_mpm/core/exceptions.py +2 -2
  80. claude_mpm/core/factories.py +10 -12
  81. claude_mpm/core/framework_loader.py +581 -280
  82. claude_mpm/core/hook_manager.py +26 -22
  83. claude_mpm/core/hook_performance_config.py +58 -47
  84. claude_mpm/core/injectable_service.py +1 -1
  85. claude_mpm/core/interactive_session.py +61 -152
  86. claude_mpm/core/interfaces.py +1 -100
  87. claude_mpm/core/lazy.py +5 -5
  88. claude_mpm/core/log_manager.py +587 -0
  89. claude_mpm/core/logger.py +125 -8
  90. claude_mpm/core/logging_config.py +15 -15
  91. claude_mpm/core/minimal_framework_loader.py +5 -8
  92. claude_mpm/core/oneshot_session.py +15 -33
  93. claude_mpm/core/optimized_agent_loader.py +4 -6
  94. claude_mpm/core/optimized_startup.py +2 -1
  95. claude_mpm/core/output_style_manager.py +147 -106
  96. claude_mpm/core/pm_hook_interceptor.py +0 -1
  97. claude_mpm/core/service_registry.py +11 -8
  98. claude_mpm/core/session_manager.py +1 -2
  99. claude_mpm/core/shared/__init__.py +1 -1
  100. claude_mpm/core/shared/config_loader.py +101 -97
  101. claude_mpm/core/shared/path_resolver.py +72 -68
  102. claude_mpm/core/shared/singleton_manager.py +56 -50
  103. claude_mpm/core/socketio_pool.py +26 -6
  104. claude_mpm/core/tool_access_control.py +4 -5
  105. claude_mpm/core/typing_utils.py +50 -59
  106. claude_mpm/core/unified_agent_registry.py +14 -19
  107. claude_mpm/core/unified_config.py +4 -6
  108. claude_mpm/core/unified_paths.py +197 -109
  109. claude_mpm/dashboard/open_dashboard.py +2 -4
  110. claude_mpm/experimental/cli_enhancements.py +51 -36
  111. claude_mpm/generators/agent_profile_generator.py +2 -4
  112. claude_mpm/hooks/base_hook.py +1 -2
  113. claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
  114. claude_mpm/hooks/claude_hooks/event_handlers.py +93 -38
  115. claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
  116. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  117. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  118. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  119. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  120. claude_mpm/hooks/memory_integration_hook.py +5 -5
  121. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  122. claude_mpm/hooks/validation_hooks.py +4 -4
  123. claude_mpm/init.py +4 -9
  124. claude_mpm/models/__init__.py +2 -2
  125. claude_mpm/models/agent_session.py +11 -14
  126. claude_mpm/scripts/mcp_server.py +20 -11
  127. claude_mpm/scripts/mcp_wrapper.py +5 -5
  128. claude_mpm/scripts/mpm_doctor.py +321 -0
  129. claude_mpm/scripts/socketio_daemon.py +28 -25
  130. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  131. claude_mpm/scripts/socketio_server_manager.py +116 -95
  132. claude_mpm/services/__init__.py +49 -49
  133. claude_mpm/services/agent_capabilities_service.py +12 -18
  134. claude_mpm/services/agents/__init__.py +22 -22
  135. claude_mpm/services/agents/agent_builder.py +140 -119
  136. claude_mpm/services/agents/deployment/__init__.py +3 -3
  137. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  138. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  139. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  140. claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
  141. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  142. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  143. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  144. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  145. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  146. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  147. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  148. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  149. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  150. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  151. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  152. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  153. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  154. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  155. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  156. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  157. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  158. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  159. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  160. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  161. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  162. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  163. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  164. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  165. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  166. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  167. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  168. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  169. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  170. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  171. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  172. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  173. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  174. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  175. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  176. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  177. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  178. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  179. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  180. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  181. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  182. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  183. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  184. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  185. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  186. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  187. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  188. claude_mpm/services/agents/loading/__init__.py +1 -1
  189. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  190. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  191. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  192. claude_mpm/services/agents/management/__init__.py +1 -1
  193. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  194. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  195. claude_mpm/services/agents/memory/__init__.py +4 -4
  196. claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
  197. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  198. claude_mpm/services/agents/memory/content_manager.py +44 -38
  199. claude_mpm/services/agents/memory/template_generator.py +4 -6
  200. claude_mpm/services/agents/registry/__init__.py +10 -6
  201. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  202. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  203. claude_mpm/services/async_session_logger.py +1 -2
  204. claude_mpm/services/claude_session_logger.py +1 -2
  205. claude_mpm/services/command_deployment_service.py +173 -0
  206. claude_mpm/services/command_handler_service.py +20 -22
  207. claude_mpm/services/core/__init__.py +25 -25
  208. claude_mpm/services/core/base.py +0 -5
  209. claude_mpm/services/core/interfaces/__init__.py +32 -32
  210. claude_mpm/services/core/interfaces/agent.py +0 -21
  211. claude_mpm/services/core/interfaces/communication.py +0 -27
  212. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  213. claude_mpm/services/core/interfaces/service.py +0 -29
  214. claude_mpm/services/diagnostics/__init__.py +1 -1
  215. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  216. claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
  217. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  218. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  219. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  220. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  221. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  222. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  223. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  224. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  225. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  226. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  227. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  228. claude_mpm/services/diagnostics/models.py +21 -19
  229. claude_mpm/services/event_aggregator.py +10 -17
  230. claude_mpm/services/event_bus/__init__.py +1 -1
  231. claude_mpm/services/event_bus/config.py +54 -35
  232. claude_mpm/services/event_bus/event_bus.py +76 -71
  233. claude_mpm/services/event_bus/relay.py +74 -64
  234. claude_mpm/services/events/__init__.py +11 -11
  235. claude_mpm/services/events/consumers/__init__.py +3 -3
  236. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  237. claude_mpm/services/events/consumers/logging.py +39 -37
  238. claude_mpm/services/events/consumers/metrics.py +56 -57
  239. claude_mpm/services/events/consumers/socketio.py +82 -81
  240. claude_mpm/services/events/core.py +110 -99
  241. claude_mpm/services/events/interfaces.py +56 -72
  242. claude_mpm/services/events/producers/__init__.py +1 -1
  243. claude_mpm/services/events/producers/hook.py +38 -38
  244. claude_mpm/services/events/producers/system.py +46 -44
  245. claude_mpm/services/exceptions.py +81 -80
  246. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  247. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  248. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  249. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  250. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  251. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  252. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  253. claude_mpm/services/hook_service.py +6 -9
  254. claude_mpm/services/infrastructure/__init__.py +1 -1
  255. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  256. claude_mpm/services/infrastructure/monitoring.py +21 -23
  257. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  258. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  259. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  260. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  261. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  262. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  263. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  264. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  265. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  266. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  267. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  268. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  269. claude_mpm/services/mcp_gateway/main.py +2 -1
  270. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  271. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  272. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  273. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  274. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  275. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  276. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  277. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  278. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  279. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  280. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  281. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  282. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  283. claude_mpm/services/memory/__init__.py +3 -3
  284. claude_mpm/services/memory/builder.py +3 -6
  285. claude_mpm/services/memory/cache/__init__.py +1 -1
  286. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  287. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  288. claude_mpm/services/memory/indexed_memory.py +5 -7
  289. claude_mpm/services/memory/optimizer.py +7 -10
  290. claude_mpm/services/memory/router.py +8 -9
  291. claude_mpm/services/memory_hook_service.py +48 -34
  292. claude_mpm/services/monitor_build_service.py +77 -73
  293. claude_mpm/services/port_manager.py +130 -108
  294. claude_mpm/services/project/analyzer.py +12 -10
  295. claude_mpm/services/project/registry.py +11 -11
  296. claude_mpm/services/recovery_manager.py +10 -19
  297. claude_mpm/services/response_tracker.py +0 -1
  298. claude_mpm/services/runner_configuration_service.py +19 -20
  299. claude_mpm/services/session_management_service.py +7 -11
  300. claude_mpm/services/shared/__init__.py +1 -1
  301. claude_mpm/services/shared/async_service_base.py +58 -50
  302. claude_mpm/services/shared/config_service_base.py +73 -67
  303. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  304. claude_mpm/services/shared/manager_base.py +94 -82
  305. claude_mpm/services/shared/service_factory.py +96 -98
  306. claude_mpm/services/socketio/__init__.py +3 -3
  307. claude_mpm/services/socketio/client_proxy.py +5 -5
  308. claude_mpm/services/socketio/event_normalizer.py +199 -181
  309. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  310. claude_mpm/services/socketio/handlers/base.py +5 -4
  311. claude_mpm/services/socketio/handlers/connection.py +163 -136
  312. claude_mpm/services/socketio/handlers/file.py +13 -14
  313. claude_mpm/services/socketio/handlers/git.py +12 -7
  314. claude_mpm/services/socketio/handlers/hook.py +49 -44
  315. claude_mpm/services/socketio/handlers/memory.py +0 -1
  316. claude_mpm/services/socketio/handlers/project.py +0 -1
  317. claude_mpm/services/socketio/handlers/registry.py +37 -19
  318. claude_mpm/services/socketio/migration_utils.py +98 -84
  319. claude_mpm/services/socketio/server/__init__.py +1 -1
  320. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  321. claude_mpm/services/socketio/server/core.py +65 -54
  322. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  323. claude_mpm/services/socketio/server/main.py +64 -38
  324. claude_mpm/services/socketio_client_manager.py +10 -12
  325. claude_mpm/services/subprocess_launcher_service.py +4 -7
  326. claude_mpm/services/system_instructions_service.py +13 -14
  327. claude_mpm/services/ticket_manager.py +2 -2
  328. claude_mpm/services/utility_service.py +5 -13
  329. claude_mpm/services/version_control/__init__.py +16 -16
  330. claude_mpm/services/version_control/branch_strategy.py +5 -8
  331. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  332. claude_mpm/services/version_control/git_operations.py +5 -7
  333. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  334. claude_mpm/services/version_control/version_parser.py +13 -18
  335. claude_mpm/services/version_service.py +10 -11
  336. claude_mpm/storage/__init__.py +1 -1
  337. claude_mpm/storage/state_storage.py +22 -28
  338. claude_mpm/utils/__init__.py +6 -6
  339. claude_mpm/utils/agent_dependency_loader.py +47 -33
  340. claude_mpm/utils/config_manager.py +11 -14
  341. claude_mpm/utils/dependency_cache.py +1 -1
  342. claude_mpm/utils/dependency_manager.py +13 -17
  343. claude_mpm/utils/dependency_strategies.py +8 -10
  344. claude_mpm/utils/environment_context.py +3 -9
  345. claude_mpm/utils/error_handler.py +3 -13
  346. claude_mpm/utils/file_utils.py +1 -1
  347. claude_mpm/utils/path_operations.py +8 -12
  348. claude_mpm/utils/robust_installer.py +110 -33
  349. claude_mpm/utils/subprocess_utils.py +5 -6
  350. claude_mpm/validation/agent_validator.py +3 -6
  351. claude_mpm/validation/frontmatter_validator.py +1 -1
  352. {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
  353. claude_mpm-4.1.2.dist-info/RECORD +498 -0
  354. claude_mpm-4.1.0.dist-info/RECORD +0 -494
  355. {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
  356. {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
  357. {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
  358. {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
@@ -24,6 +24,7 @@ import time
24
24
  from collections import deque
25
25
  from datetime import datetime
26
26
  from pathlib import Path
27
+ from typing import Optional
27
28
 
28
29
  # Add parent path for imports
29
30
  sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
@@ -31,6 +32,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
31
32
  # Import EventBus
32
33
  try:
33
34
  from claude_mpm.services.event_bus import EventBus
35
+
34
36
  EVENTBUS_AVAILABLE = True
35
37
  except ImportError:
36
38
  EVENTBUS_AVAILABLE = False
@@ -44,16 +46,23 @@ except ImportError:
44
46
  class EventNormalizer:
45
47
  def normalize(self, event_data, source="hook"):
46
48
  """Simple fallback normalizer that returns event as-is."""
47
- return type('NormalizedEvent', (), {
48
- 'to_dict': lambda: {
49
- 'event': 'claude_event',
50
- 'type': event_data.get('type', 'unknown'),
51
- 'subtype': event_data.get('subtype', 'generic'),
52
- 'timestamp': event_data.get('timestamp', datetime.now().isoformat()),
53
- 'data': event_data.get('data', event_data),
54
- 'source': source
55
- }
56
- })
49
+ return type(
50
+ "NormalizedEvent",
51
+ (),
52
+ {
53
+ "to_dict": lambda: {
54
+ "event": "claude_event",
55
+ "type": event_data.get("type", "unknown"),
56
+ "subtype": event_data.get("subtype", "generic"),
57
+ "timestamp": event_data.get(
58
+ "timestamp", datetime.now().isoformat()
59
+ ),
60
+ "data": event_data.get("data", event_data),
61
+ "source": source,
62
+ }
63
+ },
64
+ )
65
+
57
66
 
58
67
  # Import constants for configuration
59
68
  try:
@@ -63,16 +72,17 @@ except ImportError:
63
72
  class TimeoutConfig:
64
73
  QUICK_TIMEOUT = 2.0
65
74
 
75
+
66
76
  # Import other handler modules
67
77
  try:
78
+ from .event_handlers import EventHandlers
68
79
  from .memory_integration import MemoryHookManager
69
80
  from .response_tracking import ResponseTrackingManager
70
- from .event_handlers import EventHandlers
71
81
  except ImportError:
72
82
  # Fallback for direct execution
83
+ from event_handlers import EventHandlers
73
84
  from memory_integration import MemoryHookManager
74
85
  from response_tracking import ResponseTrackingManager
75
- from event_handlers import EventHandlers
76
86
 
77
87
  # Debug mode is enabled by default for better visibility into hook processing
78
88
  DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "true").lower() != "false"
@@ -88,74 +98,77 @@ _events_lock = threading.Lock()
88
98
 
89
99
  class HookHandler:
90
100
  """Main hook handler class using EventBus for event emission.
91
-
101
+
92
102
  WHY EventBus integration:
93
103
  - Replaces direct Socket.IO connections with EventBus publishing
94
104
  - Events are published once and consumed by multiple listeners
95
105
  - Failures in one consumer don't affect others
96
106
  - Simplified testing without Socket.IO dependencies
97
107
  """
98
-
108
+
99
109
  # Tracking dictionaries with size limits
100
110
  MAX_DELEGATION_TRACKING = 100
101
111
  MAX_PROMPT_TRACKING = 50
102
112
  MAX_CACHE_AGE_SECONDS = 1800 # 30 minutes
103
-
113
+
104
114
  def __init__(self):
105
115
  """Initialize the hook handler with EventBus."""
106
116
  # Initialize EventBus if available
107
117
  self.event_bus = EventBus.get_instance() if EVENTBUS_AVAILABLE else None
108
118
  self.event_normalizer = EventNormalizer()
109
-
119
+
110
120
  # Initialize tracking managers
111
121
  self.memory_manager = MemoryHookManager()
112
122
  self.response_tracker = ResponseTrackingManager()
113
123
  self.event_handlers = EventHandlers(self)
114
-
124
+
115
125
  # Delegation tracking
116
126
  self.active_delegations = {}
117
127
  self.delegation_requests = {}
118
128
  self.delegation_history = deque(maxlen=20)
119
-
129
+
120
130
  # Prompt tracking
121
131
  self.pending_prompts = {}
122
-
132
+
123
133
  # Git branch caching
124
134
  self._git_branch_cache = {}
125
135
  self._git_branch_cache_time = {}
126
-
136
+
127
137
  # Session tracking
128
138
  self.current_session_id = None
129
-
139
+
130
140
  # Cleanup old entries periodically
131
141
  self._last_cleanup = time.time()
132
-
142
+
133
143
  if self.event_bus:
134
144
  logger_msg = "HookHandler initialized with EventBus"
135
145
  else:
136
146
  logger_msg = "HookHandler initialized (EventBus not available)"
137
-
147
+
138
148
  if DEBUG:
139
149
  print(f"🚀 {logger_msg}", file=sys.stderr)
140
-
150
+
141
151
  def _emit_event(self, event_type: str, data: dict):
142
152
  """Emit an event through the EventBus.
143
-
153
+
144
154
  WHY this approach:
145
155
  - Single point of event emission
146
156
  - Consistent event normalization
147
157
  - Graceful fallback if EventBus unavailable
148
158
  - Easy to add metrics and monitoring
149
-
159
+
150
160
  Args:
151
161
  event_type: The event type (e.g., 'pre_tool', 'subagent_stop')
152
162
  data: The event data
153
163
  """
154
164
  if not self.event_bus:
155
165
  if DEBUG:
156
- print(f"EventBus not available, cannot emit: hook.{event_type}", file=sys.stderr)
166
+ print(
167
+ f"EventBus not available, cannot emit: hook.{event_type}",
168
+ file=sys.stderr,
169
+ )
157
170
  return
158
-
171
+
159
172
  try:
160
173
  # Create event data for normalization
161
174
  raw_event = {
@@ -164,86 +177,99 @@ class HookHandler:
164
177
  "timestamp": datetime.now().isoformat(),
165
178
  "data": data,
166
179
  "source": "claude_hooks",
167
- "session_id": data.get("sessionId", self.current_session_id)
180
+ "session_id": data.get("sessionId", self.current_session_id),
168
181
  }
169
-
182
+
170
183
  # Normalize the event
171
184
  normalized_event = self.event_normalizer.normalize(raw_event, source="hook")
172
185
  event_data = normalized_event.to_dict()
173
-
186
+
174
187
  # Publish to EventBus
175
188
  success = self.event_bus.publish(f"hook.{event_type}", event_data)
176
-
189
+
177
190
  if DEBUG:
178
191
  if success:
179
- print(f"✅ Published to EventBus: hook.{event_type}", file=sys.stderr)
192
+ print(
193
+ f"✅ Published to EventBus: hook.{event_type}", file=sys.stderr
194
+ )
180
195
  else:
181
- print(f"⚠️ EventBus rejected event: hook.{event_type}", file=sys.stderr)
182
-
196
+ print(
197
+ f"⚠️ EventBus rejected event: hook.{event_type}", file=sys.stderr
198
+ )
199
+
183
200
  # Log important events
184
201
  if DEBUG and event_type in ["subagent_stop", "pre_tool"]:
185
202
  if event_type == "subagent_stop":
186
203
  agent_type = data.get("agent_type", "unknown")
187
- print(f"📤 Published SubagentStop for agent '{agent_type}'", file=sys.stderr)
204
+ print(
205
+ f"📤 Published SubagentStop for agent '{agent_type}'",
206
+ file=sys.stderr,
207
+ )
188
208
  elif event_type == "pre_tool" and data.get("tool_name") == "Task":
189
209
  delegation = data.get("delegation_details", {})
190
210
  agent_type = delegation.get("agent_type", "unknown")
191
- print(f"📤 Published Task delegation to agent '{agent_type}'", file=sys.stderr)
192
-
211
+ print(
212
+ f"📤 Published Task delegation to agent '{agent_type}'",
213
+ file=sys.stderr,
214
+ )
215
+
193
216
  except Exception as e:
194
217
  if DEBUG:
195
- print(f"❌ Failed to publish event hook.{event_type}: {e}", file=sys.stderr)
196
-
197
- def _get_git_branch(self, working_dir: str = None) -> str:
218
+ print(
219
+ f"❌ Failed to publish event hook.{event_type}: {e}",
220
+ file=sys.stderr,
221
+ )
222
+
223
+ def _get_git_branch(self, working_dir: Optional[str] = None) -> str:
198
224
  """Get git branch for the given directory with caching."""
199
225
  # Use current working directory if not specified
200
226
  if not working_dir:
201
227
  working_dir = os.getcwd()
202
-
228
+
203
229
  # Check cache first (cache for 30 seconds)
204
230
  current_time = time.time()
205
231
  cache_key = working_dir
206
-
232
+
207
233
  if (
208
234
  cache_key in self._git_branch_cache
209
235
  and cache_key in self._git_branch_cache_time
210
236
  and current_time - self._git_branch_cache_time[cache_key] < 30
211
237
  ):
212
238
  return self._git_branch_cache[cache_key]
213
-
239
+
214
240
  # Try to get git branch
215
241
  try:
216
242
  # Change to the working directory temporarily
217
243
  original_cwd = os.getcwd()
218
244
  os.chdir(working_dir)
219
-
245
+
220
246
  # Run git command to get current branch
221
247
  result = subprocess.run(
222
248
  ["git", "branch", "--show-current"],
223
249
  capture_output=True,
224
250
  text=True,
225
- timeout=TimeoutConfig.QUICK_TIMEOUT
251
+ timeout=TimeoutConfig.QUICK_TIMEOUT,
252
+ check=False,
226
253
  )
227
-
254
+
228
255
  # Restore original directory
229
256
  os.chdir(original_cwd)
230
-
257
+
231
258
  if result.returncode == 0 and result.stdout.strip():
232
259
  branch = result.stdout.strip()
233
260
  # Cache the result
234
261
  self._git_branch_cache[cache_key] = branch
235
262
  self._git_branch_cache_time[cache_key] = current_time
236
263
  return branch
237
- else:
238
- return "unknown"
239
-
264
+ return "unknown"
265
+
240
266
  except Exception:
241
267
  return "unknown"
242
-
268
+
243
269
  def _cleanup_old_entries(self):
244
270
  """Clean up old entries to prevent memory growth."""
245
- cutoff_time = time.time() - self.MAX_CACHE_AGE_SECONDS
246
-
271
+ time.time() - self.MAX_CACHE_AGE_SECONDS
272
+
247
273
  # Clean up delegation tracking dictionaries
248
274
  for storage in [self.active_delegations, self.delegation_requests]:
249
275
  if len(storage) > self.MAX_DELEGATION_TRACKING:
@@ -252,14 +278,14 @@ class HookHandler:
252
278
  excess = len(storage) - self.MAX_DELEGATION_TRACKING
253
279
  for key in sorted_keys[:excess]:
254
280
  del storage[key]
255
-
281
+
256
282
  # Clean up pending prompts
257
283
  if len(self.pending_prompts) > self.MAX_PROMPT_TRACKING:
258
284
  sorted_keys = sorted(self.pending_prompts.keys())
259
285
  excess = len(self.pending_prompts) - self.MAX_PROMPT_TRACKING
260
286
  for key in sorted_keys[:excess]:
261
287
  del self.pending_prompts[key]
262
-
288
+
263
289
  # Clean up git branch cache
264
290
  expired_keys = [
265
291
  key
@@ -269,10 +295,10 @@ class HookHandler:
269
295
  for key in expired_keys:
270
296
  self._git_branch_cache.pop(key, None)
271
297
  self._git_branch_cache_time.pop(key, None)
272
-
298
+
273
299
  def handle_event(self, event: dict):
274
300
  """Process an event from Claude Code.
275
-
301
+
276
302
  Args:
277
303
  event: The event dictionary from Claude
278
304
  """
@@ -281,24 +307,26 @@ class HookHandler:
281
307
  if current_time - self._last_cleanup > 300: # Every 5 minutes
282
308
  self._cleanup_old_entries()
283
309
  self._last_cleanup = current_time
284
-
310
+
285
311
  # Extract event details
286
312
  event_type = event.get("type", "")
287
313
  event_name = event.get("name", "")
288
-
314
+
289
315
  # Update session ID if present
290
316
  if "sessionId" in event:
291
317
  self.current_session_id = event["sessionId"]
292
-
318
+
293
319
  # Detect duplicate events
294
- event_signature = f"{event_type}:{event_name}:{json.dumps(event.get('data', ''))[:100]}"
320
+ event_signature = (
321
+ f"{event_type}:{event_name}:{json.dumps(event.get('data', ''))[:100]}"
322
+ )
295
323
  with _events_lock:
296
324
  if event_signature in _recent_events:
297
325
  if DEBUG:
298
326
  print(f"Skipping duplicate event: {event_type}", file=sys.stderr)
299
327
  return
300
328
  _recent_events.append(event_signature)
301
-
329
+
302
330
  # Route to appropriate handler
303
331
  if event_type == "Start":
304
332
  self.event_handlers.handle_start(event)
@@ -321,15 +349,14 @@ class HookHandler:
321
349
  elif event_type == "PromptCachingBetaStats":
322
350
  # Ignore caching stats events
323
351
  pass
324
- else:
325
- # Log unhandled events in debug mode
326
- if DEBUG:
327
- print(f"Unhandled event type: {event_type}", file=sys.stderr)
352
+ # Log unhandled events in debug mode
353
+ elif DEBUG:
354
+ print(f"Unhandled event type: {event_type}", file=sys.stderr)
328
355
 
329
356
 
330
357
  def get_handler() -> HookHandler:
331
358
  """Get or create the global hook handler instance.
332
-
359
+
333
360
  Returns:
334
361
  HookHandler: The singleton handler instance
335
362
  """
@@ -345,18 +372,18 @@ def main():
345
372
  """Main entry point for the hook handler."""
346
373
  if DEBUG:
347
374
  print("🎯 EventBus Hook Handler starting...", file=sys.stderr)
348
-
375
+
349
376
  handler = get_handler()
350
-
377
+
351
378
  # Set up signal handling for clean shutdown
352
379
  def signal_handler(signum, frame):
353
380
  if DEBUG:
354
381
  print("\n👋 Hook handler shutting down...", file=sys.stderr)
355
382
  sys.exit(0)
356
-
383
+
357
384
  signal.signal(signal.SIGINT, signal_handler)
358
385
  signal.signal(signal.SIGTERM, signal_handler)
359
-
386
+
360
387
  # Process events from stdin
361
388
  try:
362
389
  while True:
@@ -366,15 +393,15 @@ def main():
366
393
  line = sys.stdin.readline()
367
394
  if not line:
368
395
  break
369
-
396
+
370
397
  try:
371
398
  event = json.loads(line.strip())
372
399
  handler.handle_event(event)
373
-
400
+
374
401
  # Acknowledge event
375
402
  print(json.dumps({"status": "ok"}))
376
403
  sys.stdout.flush()
377
-
404
+
378
405
  except json.JSONDecodeError as e:
379
406
  if DEBUG:
380
407
  print(f"Invalid JSON: {e}", file=sys.stderr)
@@ -385,7 +412,7 @@ def main():
385
412
  print(f"Error processing event: {e}", file=sys.stderr)
386
413
  print(json.dumps({"status": "error", "message": str(e)}))
387
414
  sys.stdout.flush()
388
-
415
+
389
416
  except KeyboardInterrupt:
390
417
  if DEBUG:
391
418
  print("\n👋 Hook handler interrupted", file=sys.stderr)
@@ -395,4 +422,4 @@ def main():
395
422
 
396
423
 
397
424
  if __name__ == "__main__":
398
- main()
425
+ main()
@@ -8,7 +8,7 @@ including pre and post delegation hooks.
8
8
  import os
9
9
  import sys
10
10
  from datetime import datetime
11
- from typing import Any, Dict, Optional
11
+ from typing import Optional
12
12
 
13
13
  # Debug mode
14
14
  DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "true").lower() != "false"
@@ -21,14 +21,12 @@ try:
21
21
 
22
22
  paths.ensure_in_path()
23
23
 
24
- from claude_mpm.core.config import Config
25
24
  from claude_mpm.core.shared.config_loader import ConfigLoader
26
25
  from claude_mpm.hooks.base_hook import HookContext, HookType
27
26
  from claude_mpm.hooks.memory_integration_hook import (
28
27
  MemoryPostDelegationHook,
29
28
  MemoryPreDelegationHook,
30
29
  )
31
- from claude_mpm.services.hook_service import HookService
32
30
 
33
31
  MEMORY_HOOKS_AVAILABLE = True
34
32
  except Exception as e:
@@ -181,7 +179,7 @@ class MemoryHookManager:
181
179
  if output:
182
180
  result_content = str(output)
183
181
  elif error:
184
- result_content = f"Error: {str(error)}"
182
+ result_content = f"Error: {error!s}"
185
183
  else:
186
184
  result_content = f"Task completed with exit code: {exit_code}"
187
185
 
@@ -10,7 +10,7 @@ import os
10
10
  import re
11
11
  import sys
12
12
  from datetime import datetime
13
- from typing import Any, Dict, Optional
13
+ from typing import Optional
14
14
 
15
15
  # Debug mode
16
16
  DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "true").lower() != "false"
@@ -53,7 +53,6 @@ class ResponseTrackingManager:
53
53
  try:
54
54
  # Create configuration with optional config file using ConfigLoader
55
55
  config_file = os.environ.get("CLAUDE_PM_CONFIG_FILE")
56
- from claude_mpm.core.config import Config
57
56
  from claude_mpm.core.shared.config_loader import ConfigLoader, ConfigPattern
58
57
 
59
58
  config_loader = ConfigLoader()
@@ -62,9 +61,11 @@ class ResponseTrackingManager:
62
61
  pattern = ConfigPattern(
63
62
  filenames=[os.path.basename(config_file)],
64
63
  search_paths=[os.path.dirname(config_file)],
65
- env_prefix="CLAUDE_MPM_"
64
+ env_prefix="CLAUDE_MPM_",
65
+ )
66
+ config = config_loader.load_config(
67
+ pattern, cache_key=f"response_tracking_{config_file}"
66
68
  )
67
- config = config_loader.load_config(pattern, cache_key=f"response_tracking_{config_file}")
68
69
  else:
69
70
  config = config_loader.load_main_config()
70
71
 
@@ -101,7 +102,9 @@ class ResponseTrackingManager:
101
102
 
102
103
  except Exception as e:
103
104
  if DEBUG:
104
- print(f"❌ Failed to initialize response tracking: {e}", file=sys.stderr)
105
+ print(
106
+ f"❌ Failed to initialize response tracking: {e}", file=sys.stderr
107
+ )
105
108
  # Don't fail the entire handler - response tracking is optional
106
109
 
107
110
  def track_agent_response(
@@ -203,11 +206,13 @@ class ResponseTrackingManager:
203
206
  "files_modified": structured_response.get("files_modified", []),
204
207
  "tools_used": structured_response.get("tools_used", []),
205
208
  "remember": structured_response.get("remember"),
206
- "MEMORIES": structured_response.get("MEMORIES"), # Complete memory replacement
209
+ "MEMORIES": structured_response.get(
210
+ "MEMORIES"
211
+ ), # Complete memory replacement
207
212
  }
208
-
209
- # Log if MEMORIES field is present
210
- if "MEMORIES" in structured_response and structured_response["MEMORIES"]:
213
+
214
+ # Log if MEMORIES field is present
215
+ if structured_response.get("MEMORIES"):
211
216
  if DEBUG:
212
217
  memories_count = len(structured_response["MEMORIES"])
213
218
  print(
@@ -247,8 +252,7 @@ class ResponseTrackingManager:
247
252
  )
248
253
 
249
254
  # Clean up the request data after successful tracking
250
- if session_id in delegation_requests:
251
- del delegation_requests[session_id]
255
+ delegation_requests.pop(session_id, None)
252
256
 
253
257
  except Exception as e:
254
258
  if DEBUG:
@@ -5,8 +5,6 @@ This module provides utilities for analyzing tool usage, extracting parameters,
5
5
  and assessing security risks.
6
6
  """
7
7
 
8
- from typing import Any, Dict, List
9
-
10
8
 
11
9
  def extract_tool_parameters(tool_name: str, tool_input: dict) -> dict:
12
10
  """Extract relevant parameters based on tool type.
@@ -99,7 +97,7 @@ def extract_tool_parameters(tool_name: str, tool_input: dict) -> dict:
99
97
  "has_in_progress": any(t.get("status") == "in_progress" for t in todos),
100
98
  "has_pending": any(t.get("status") == "pending" for t in todos),
101
99
  "has_completed": any(t.get("status") == "completed" for t in todos),
102
- "priorities": list(set(t.get("priority", "medium") for t in todos)),
100
+ "priorities": list({t.get("priority", "medium") for t in todos}),
103
101
  }
104
102
  )
105
103
 
@@ -144,18 +142,17 @@ def classify_tool_operation(tool_name: str, tool_input: dict) -> str:
144
142
  """Classify the type of operation being performed."""
145
143
  if tool_name in ["Read", "LS", "Glob", "Grep", "NotebookRead"]:
146
144
  return "read"
147
- elif tool_name in ["Write", "Edit", "MultiEdit", "NotebookEdit"]:
145
+ if tool_name in ["Write", "Edit", "MultiEdit", "NotebookEdit"]:
148
146
  return "write"
149
- elif tool_name == "Bash":
147
+ if tool_name == "Bash":
150
148
  return "execute"
151
- elif tool_name in ["WebFetch", "WebSearch"]:
149
+ if tool_name in ["WebFetch", "WebSearch"]:
152
150
  return "network"
153
- elif tool_name == "TodoWrite":
151
+ if tool_name == "TodoWrite":
154
152
  return "task_management"
155
- elif tool_name == "Task":
153
+ if tool_name == "Task":
156
154
  return "delegation"
157
- else:
158
- return "other"
155
+ return "other"
159
156
 
160
157
 
161
158
  def assess_security_risk(tool_name: str, tool_input: dict) -> str:
@@ -174,21 +171,18 @@ def assess_security_risk(tool_name: str, tool_input: dict) -> str:
174
171
  ]
175
172
  if any(pattern in command for pattern in dangerous_patterns):
176
173
  return "high"
177
- elif any(word in command for word in ["install", "delete", "format", "kill"]):
174
+ if any(word in command for word in ["install", "delete", "format", "kill"]):
178
175
  return "medium"
179
- else:
180
- return "low"
181
- elif tool_name in ["Write", "Edit", "MultiEdit"]:
176
+ return "low"
177
+ if tool_name in ["Write", "Edit", "MultiEdit"]:
182
178
  file_path = tool_input.get("file_path", "")
183
179
  # Check for system file modifications
184
180
  if any(path in file_path for path in ["/etc/", "/usr/", "/var/", "/sys/"]):
185
181
  return "high"
186
- elif file_path.startswith("/"):
182
+ if file_path.startswith("/"):
187
183
  return "medium"
188
- else:
189
- return "low"
190
- else:
191
184
  return "low"
185
+ return "low"
192
186
 
193
187
 
194
188
  def extract_tool_results(event: dict) -> dict:
@@ -13,7 +13,7 @@ agent outputs because:
13
13
  """
14
14
 
15
15
  import re
16
- from typing import Any, Dict, List
16
+ from typing import Dict, List
17
17
 
18
18
  from claude_mpm.core.config import Config
19
19
  from claude_mpm.core.logger import get_logger
@@ -162,7 +162,7 @@ INSTRUCTIONS: Review your memory above before proceeding. Apply learned patterns
162
162
  success=True,
163
163
  data=context.data,
164
164
  modified=False,
165
- error=f"Memory injection failed: {str(e)}",
165
+ error=f"Memory injection failed: {e!s}",
166
166
  )
167
167
 
168
168
 
@@ -319,7 +319,7 @@ class MemoryPostDelegationHook(PostDelegationHook):
319
319
  success=True,
320
320
  data=context.data,
321
321
  modified=False,
322
- error=f"Learning extraction failed: {str(e)}",
322
+ error=f"Learning extraction failed: {e!s}",
323
323
  )
324
324
 
325
325
  def _extract_learnings(self, text: str) -> Dict[str, List[str]]:
@@ -339,7 +339,7 @@ class MemoryPostDelegationHook(PostDelegationHook):
339
339
  Returns:
340
340
  Dictionary mapping learning types to lists of extracted learnings
341
341
  """
342
- learnings = {learning_type: [] for learning_type in self.type_mapping.keys()}
342
+ learnings = {learning_type: [] for learning_type in self.type_mapping}
343
343
  seen_learnings = set() # Avoid duplicates
344
344
 
345
345
  # Pattern to find memory blocks with multiple trigger phrases
@@ -394,7 +394,7 @@ class MemoryPostDelegationHook(PostDelegationHook):
394
394
  f"Unsupported learning type: {learning_type}. Supported types: {list(self.type_mapping.keys())}"
395
395
  )
396
396
  else:
397
- logger.debug(f"Invalid memory block format - missing Type or Content")
397
+ logger.debug("Invalid memory block format - missing Type or Content")
398
398
 
399
399
  # Log summary of extracted learnings
400
400
  total_learnings = sum(len(items) for items in learnings.values())
@@ -6,7 +6,7 @@ from datetime import datetime
6
6
  from typing import Any, Dict, List, Optional
7
7
 
8
8
  from claude_mpm.core.logger import get_logger
9
- from claude_mpm.hooks.base_hook import BaseHook, HookContext, HookResult, HookType
9
+ from claude_mpm.hooks.base_hook import BaseHook, HookContext, HookType
10
10
 
11
11
  logger = get_logger(__name__)
12
12