claude-mpm 3.9.9__py3-none-any.whl → 4.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +2 -2
- claude_mpm/__main__.py +3 -2
- claude_mpm/agents/__init__.py +85 -79
- claude_mpm/agents/agent_loader.py +464 -1003
- claude_mpm/agents/agent_loader_integration.py +45 -45
- claude_mpm/agents/agents_metadata.py +29 -30
- claude_mpm/agents/async_agent_loader.py +156 -138
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/base_agent_loader.py +179 -151
- claude_mpm/agents/frontmatter_validator.py +229 -130
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +213 -147
- claude_mpm/agents/templates/__init__.py +13 -13
- claude_mpm/agents/templates/code_analyzer.json +2 -2
- claude_mpm/agents/templates/data_engineer.json +1 -1
- claude_mpm/agents/templates/documentation.json +23 -11
- claude_mpm/agents/templates/engineer.json +22 -6
- claude_mpm/agents/templates/memory_manager.json +155 -0
- claude_mpm/agents/templates/ops.json +2 -2
- claude_mpm/agents/templates/project_organizer.json +1 -1
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/refactoring_engineer.json +222 -0
- claude_mpm/agents/templates/research.json +20 -14
- claude_mpm/agents/templates/security.json +1 -1
- claude_mpm/agents/templates/ticketing.json +1 -1
- claude_mpm/agents/templates/version_control.json +1 -1
- claude_mpm/agents/templates/web_qa.json +3 -1
- claude_mpm/agents/templates/web_ui.json +2 -2
- claude_mpm/cli/__init__.py +90 -49
- claude_mpm/cli/__main__.py +3 -2
- claude_mpm/cli/commands/__init__.py +21 -18
- claude_mpm/cli/commands/agents.py +279 -247
- claude_mpm/cli/commands/aggregate.py +138 -157
- claude_mpm/cli/commands/cleanup.py +147 -147
- claude_mpm/cli/commands/config.py +93 -76
- claude_mpm/cli/commands/info.py +17 -16
- claude_mpm/cli/commands/mcp.py +143 -762
- claude_mpm/cli/commands/mcp_command_router.py +139 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_install_commands.py +20 -0
- claude_mpm/cli/commands/mcp_server_commands.py +175 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +239 -203
- claude_mpm/cli/commands/monitor.py +203 -81
- claude_mpm/cli/commands/run.py +380 -429
- claude_mpm/cli/commands/run_config_checker.py +160 -0
- claude_mpm/cli/commands/socketio_monitor.py +235 -0
- claude_mpm/cli/commands/tickets.py +305 -197
- claude_mpm/cli/parser.py +24 -1150
- claude_mpm/cli/parsers/__init__.py +29 -0
- claude_mpm/cli/parsers/agents_parser.py +136 -0
- claude_mpm/cli/parsers/base_parser.py +331 -0
- claude_mpm/cli/parsers/config_parser.py +85 -0
- claude_mpm/cli/parsers/mcp_parser.py +152 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +104 -0
- claude_mpm/cli/parsers/run_parser.py +147 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/ticket_cli.py +7 -3
- claude_mpm/cli/utils.py +55 -37
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +38 -60
- claude_mpm/config/__init__.py +32 -25
- claude_mpm/config/agent_config.py +151 -119
- claude_mpm/config/experimental_features.py +217 -0
- claude_mpm/config/paths.py +94 -208
- claude_mpm/config/socketio_config.py +84 -73
- claude_mpm/constants.py +36 -18
- claude_mpm/core/__init__.py +9 -6
- claude_mpm/core/agent_name_normalizer.py +68 -71
- claude_mpm/core/agent_registry.py +372 -521
- claude_mpm/core/agent_session_manager.py +74 -63
- claude_mpm/core/base_service.py +116 -87
- claude_mpm/core/cache.py +119 -153
- claude_mpm/core/claude_runner.py +425 -1120
- claude_mpm/core/config.py +263 -168
- claude_mpm/core/config_aliases.py +69 -61
- claude_mpm/core/config_constants.py +292 -0
- claude_mpm/core/constants.py +57 -99
- claude_mpm/core/container.py +211 -178
- claude_mpm/core/exceptions.py +233 -89
- claude_mpm/core/factories.py +92 -54
- claude_mpm/core/framework_loader.py +378 -220
- claude_mpm/core/hook_manager.py +198 -83
- claude_mpm/core/hook_performance_config.py +136 -0
- claude_mpm/core/injectable_service.py +61 -55
- claude_mpm/core/interactive_session.py +165 -155
- claude_mpm/core/interfaces.py +221 -195
- claude_mpm/core/lazy.py +96 -96
- claude_mpm/core/logger.py +133 -107
- claude_mpm/core/logging_config.py +185 -157
- claude_mpm/core/minimal_framework_loader.py +20 -15
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +215 -181
- claude_mpm/core/optimized_agent_loader.py +134 -138
- claude_mpm/core/optimized_startup.py +159 -157
- claude_mpm/core/pm_hook_interceptor.py +85 -72
- claude_mpm/core/service_registry.py +103 -101
- claude_mpm/core/session_manager.py +97 -87
- claude_mpm/core/socketio_pool.py +212 -158
- claude_mpm/core/tool_access_control.py +58 -51
- claude_mpm/core/types.py +46 -24
- claude_mpm/core/typing_utils.py +166 -82
- claude_mpm/core/unified_agent_registry.py +721 -0
- claude_mpm/core/unified_config.py +550 -0
- claude_mpm/core/unified_paths.py +549 -0
- claude_mpm/dashboard/index.html +1 -1
- claude_mpm/dashboard/open_dashboard.py +51 -17
- claude_mpm/dashboard/static/css/dashboard.css +27 -8
- claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/dist/dashboard.js +2 -0
- claude_mpm/dashboard/static/dist/socket-client.js +2 -0
- claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
- claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
- claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
- claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
- claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
- claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
- claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
- claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
- claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
- claude_mpm/dashboard/static/js/dashboard.js +178 -453
- claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/js/socket-client.js +120 -54
- claude_mpm/dashboard/templates/index.html +40 -50
- claude_mpm/experimental/cli_enhancements.py +60 -58
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +75 -65
- claude_mpm/hooks/__init__.py +1 -1
- claude_mpm/hooks/base_hook.py +33 -28
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
- claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
- claude_mpm/hooks/memory_integration_hook.py +140 -100
- claude_mpm/hooks/tool_call_interceptor.py +89 -76
- claude_mpm/hooks/validation_hooks.py +57 -49
- claude_mpm/init.py +145 -121
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +33 -23
- claude_mpm/models/agent_session.py +228 -200
- claude_mpm/scripts/__init__.py +1 -1
- claude_mpm/scripts/socketio_daemon.py +192 -75
- claude_mpm/scripts/socketio_server_manager.py +328 -0
- claude_mpm/scripts/start_activity_logging.py +25 -22
- claude_mpm/services/__init__.py +68 -43
- claude_mpm/services/agent_capabilities_service.py +271 -0
- claude_mpm/services/agents/__init__.py +23 -32
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
- claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
- claude_mpm/services/agents/deployment/agent_validator.py +352 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
- claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
- claude_mpm/services/agents/loading/__init__.py +2 -2
- claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
- claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
- claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
- claude_mpm/services/agents/management/__init__.py +2 -2
- claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
- claude_mpm/services/agents/management/agent_management_service.py +209 -156
- claude_mpm/services/agents/memory/__init__.py +9 -6
- claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
- claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
- claude_mpm/services/agents/memory/analyzer.py +430 -0
- claude_mpm/services/agents/memory/content_manager.py +376 -0
- claude_mpm/services/agents/memory/template_generator.py +468 -0
- claude_mpm/services/agents/registry/__init__.py +7 -10
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
- claude_mpm/services/agents/registry/modification_tracker.py +351 -285
- claude_mpm/services/async_session_logger.py +187 -153
- claude_mpm/services/claude_session_logger.py +87 -72
- claude_mpm/services/command_handler_service.py +217 -0
- claude_mpm/services/communication/__init__.py +3 -2
- claude_mpm/services/core/__init__.py +50 -97
- claude_mpm/services/core/base.py +60 -53
- claude_mpm/services/core/interfaces/__init__.py +188 -0
- claude_mpm/services/core/interfaces/agent.py +351 -0
- claude_mpm/services/core/interfaces/communication.py +343 -0
- claude_mpm/services/core/interfaces/infrastructure.py +413 -0
- claude_mpm/services/core/interfaces/service.py +434 -0
- claude_mpm/services/core/interfaces.py +19 -944
- claude_mpm/services/event_aggregator.py +208 -170
- claude_mpm/services/exceptions.py +387 -308
- claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
- claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
- claude_mpm/services/hook_service.py +106 -114
- claude_mpm/services/infrastructure/__init__.py +7 -5
- claude_mpm/services/infrastructure/context_preservation.py +571 -0
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +83 -76
- claude_mpm/services/infrastructure/monitoring.py +547 -404
- claude_mpm/services/mcp_gateway/__init__.py +40 -23
- claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
- claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
- claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
- claude_mpm/services/mcp_gateway/core/__init__.py +14 -21
- claude_mpm/services/mcp_gateway/core/base.py +80 -67
- claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
- claude_mpm/services/mcp_gateway/core/interfaces.py +97 -93
- claude_mpm/services/mcp_gateway/main.py +307 -127
- claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +100 -101
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
- claude_mpm/services/mcp_gateway/server/__init__.py +4 -4
- claude_mpm/services/mcp_gateway/server/{mcp_server.py → mcp_gateway.py} +149 -153
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
- claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
- claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +110 -121
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
- claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
- claude_mpm/services/memory/__init__.py +2 -2
- claude_mpm/services/memory/builder.py +451 -362
- claude_mpm/services/memory/cache/__init__.py +2 -2
- claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
- claude_mpm/services/memory/cache/simple_cache.py +107 -93
- claude_mpm/services/memory/indexed_memory.py +195 -193
- claude_mpm/services/memory/optimizer.py +267 -234
- claude_mpm/services/memory/router.py +571 -263
- claude_mpm/services/memory_hook_service.py +237 -0
- claude_mpm/services/port_manager.py +223 -0
- claude_mpm/services/project/__init__.py +3 -3
- claude_mpm/services/project/analyzer.py +451 -305
- claude_mpm/services/project/registry.py +262 -240
- claude_mpm/services/recovery_manager.py +287 -231
- claude_mpm/services/response_tracker.py +87 -67
- claude_mpm/services/runner_configuration_service.py +587 -0
- claude_mpm/services/session_management_service.py +304 -0
- claude_mpm/services/socketio/__init__.py +4 -4
- claude_mpm/services/socketio/client_proxy.py +174 -0
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +44 -30
- claude_mpm/services/socketio/handlers/connection.py +145 -65
- claude_mpm/services/socketio/handlers/file.py +123 -108
- claude_mpm/services/socketio/handlers/git.py +607 -373
- claude_mpm/services/socketio/handlers/hook.py +170 -0
- claude_mpm/services/socketio/handlers/memory.py +4 -4
- claude_mpm/services/socketio/handlers/project.py +4 -4
- claude_mpm/services/socketio/handlers/registry.py +53 -38
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +252 -0
- claude_mpm/services/socketio/server/core.py +399 -0
- claude_mpm/services/socketio/server/main.py +323 -0
- claude_mpm/services/socketio_client_manager.py +160 -133
- claude_mpm/services/socketio_server.py +36 -1885
- claude_mpm/services/subprocess_launcher_service.py +316 -0
- claude_mpm/services/system_instructions_service.py +258 -0
- claude_mpm/services/ticket_manager.py +20 -534
- claude_mpm/services/utility_service.py +285 -0
- claude_mpm/services/version_control/__init__.py +18 -21
- claude_mpm/services/version_control/branch_strategy.py +20 -10
- claude_mpm/services/version_control/conflict_resolution.py +37 -13
- claude_mpm/services/version_control/git_operations.py +52 -21
- claude_mpm/services/version_control/semantic_versioning.py +92 -53
- claude_mpm/services/version_control/version_parser.py +145 -125
- claude_mpm/services/version_service.py +270 -0
- claude_mpm/storage/__init__.py +9 -0
- claude_mpm/storage/state_storage.py +552 -0
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/utils/__init__.py +2 -2
- claude_mpm/utils/agent_dependency_loader.py +453 -243
- claude_mpm/utils/config_manager.py +157 -118
- claude_mpm/utils/console.py +1 -1
- claude_mpm/utils/dependency_cache.py +102 -107
- claude_mpm/utils/dependency_manager.py +52 -47
- claude_mpm/utils/dependency_strategies.py +131 -96
- claude_mpm/utils/environment_context.py +110 -102
- claude_mpm/utils/error_handler.py +75 -55
- claude_mpm/utils/file_utils.py +80 -67
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/path_operations.py +100 -93
- claude_mpm/utils/robust_installer.py +172 -164
- claude_mpm/utils/session_logging.py +30 -23
- claude_mpm/utils/subprocess_utils.py +99 -61
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +151 -111
- claude_mpm/validation/frontmatter_validator.py +92 -71
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +51 -2
- claude_mpm-4.0.3.dist-info/RECORD +402 -0
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
- claude_mpm/config/memory_guardian_config.py +0 -325
- claude_mpm/core/config_paths.py +0 -150
- claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
- claude_mpm/models/state_models.py +0 -433
- claude_mpm/services/agent/__init__.py +0 -24
- claude_mpm/services/agent/deployment.py +0 -2548
- claude_mpm/services/agent/management.py +0 -598
- claude_mpm/services/agent/registry.py +0 -813
- claude_mpm/services/agents/registry/agent_registry.py +0 -813
- claude_mpm/services/communication/socketio.py +0 -1935
- claude_mpm/services/communication/websocket.py +0 -479
- claude_mpm/services/framework_claude_md_generator.py +0 -624
- claude_mpm/services/health_monitor.py +0 -893
- claude_mpm/services/infrastructure/memory_guardian.py +0 -770
- claude_mpm/services/mcp_gateway/server/mcp_server_simple.py +0 -444
- claude_mpm/services/optimized_hook_service.py +0 -542
- claude_mpm/services/project_analyzer.py +0 -864
- claude_mpm/services/project_registry.py +0 -608
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -510
- claude_mpm/utils/paths.py +0 -395
- claude_mpm/utils/platform_memory.py +0 -524
- claude_mpm-3.9.9.dist-info/RECORD +0 -293
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.9.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 | 
             
            """
         | 
| 2 4 | 
             
            Version management for framework CLAUDE.md templates.
         | 
| 3 5 |  | 
| @@ -5,28 +7,27 @@ Handles version parsing, incrementing, and comparison operations. | |
| 5 7 | 
             
            """
         | 
| 6 8 |  | 
| 7 9 | 
             
            import re
         | 
| 8 | 
            -
            from typing import  | 
| 9 | 
            -
            from pathlib import Path
         | 
| 10 | 
            +
            from typing import Optional, Tuple
         | 
| 10 11 |  | 
| 11 12 |  | 
| 12 13 | 
             
            class VersionManager:
         | 
| 13 14 | 
             
                """Manages version numbering for framework CLAUDE.md templates."""
         | 
| 14 | 
            -
             | 
| 15 | 
            +
             | 
| 15 16 | 
             
                def __init__(self):
         | 
| 16 17 | 
             
                    """Initialize version manager."""
         | 
| 17 18 | 
             
                    self.framework_version = self._get_framework_version()
         | 
| 18 | 
            -
             | 
| 19 | 
            +
             | 
| 19 20 | 
             
                def _get_framework_version(self) -> str:
         | 
| 20 21 | 
             
                    """
         | 
| 21 22 | 
             
                    Get the current framework version from framework/VERSION file.
         | 
| 22 | 
            -
             | 
| 23 | 
            +
             | 
| 23 24 | 
             
                    Returns:
         | 
| 24 25 | 
             
                        str: Framework version (e.g., "015")
         | 
| 25 26 | 
             
                    """
         | 
| 26 27 | 
             
                    # Check if we're in a wheel installation
         | 
| 27 28 | 
             
                    package_path = Path(__file__).parent.parent.parent
         | 
| 28 29 | 
             
                    path_str = str(package_path.resolve())
         | 
| 29 | 
            -
                    if  | 
| 30 | 
            +
                    if "site-packages" in path_str or "dist-packages" in path_str:
         | 
| 30 31 | 
             
                        # For wheel installations, check data directory
         | 
| 31 32 | 
             
                        version_path = package_path / "data" / "framework" / "VERSION"
         | 
| 32 33 | 
             
                        if not version_path.exists():
         | 
| @@ -35,87 +36,88 @@ class VersionManager: | |
| 35 36 | 
             
                    else:
         | 
| 36 37 | 
             
                        # Source installation
         | 
| 37 38 | 
             
                        version_path = package_path.parent / "framework" / "VERSION"
         | 
| 38 | 
            -
             | 
| 39 | 
            +
             | 
| 39 40 | 
             
                    if version_path.exists():
         | 
| 40 | 
            -
                        with open(version_path,  | 
| 41 | 
            +
                        with open(version_path, "r") as f:
         | 
| 41 42 | 
             
                            version_content = f.read().strip()
         | 
| 42 43 | 
             
                            # Framework VERSION file contains just the framework version number
         | 
| 43 44 | 
             
                            try:
         | 
| 44 45 | 
             
                                return f"{int(version_content):03d}"
         | 
| 45 46 | 
             
                            except ValueError:
         | 
| 46 47 | 
             
                                # If not a plain number, try to extract from version string
         | 
| 47 | 
            -
                                match = re.match(r | 
| 48 | 
            +
                                match = re.match(r"(\d+)", version_content)
         | 
| 48 49 | 
             
                                if match:
         | 
| 49 50 | 
             
                                    return f"{int(match.group(1)):03d}"
         | 
| 50 51 | 
             
                    return "014"  # Default fallback
         | 
| 51 | 
            -
             | 
| 52 | 
            +
             | 
| 52 53 | 
             
                def parse_current_version(self, content: str) -> str:
         | 
| 53 54 | 
             
                    """
         | 
| 54 55 | 
             
                    Parse the current CLAUDE_MD_VERSION from existing content.
         | 
| 55 | 
            -
             | 
| 56 | 
            +
             | 
| 56 57 | 
             
                    Args:
         | 
| 57 58 | 
             
                        content: Existing CLAUDE.md content
         | 
| 58 | 
            -
             | 
| 59 | 
            +
             | 
| 59 60 | 
             
                    Returns:
         | 
| 60 61 | 
             
                        str: Version number (e.g., "016")
         | 
| 61 62 | 
             
                    """
         | 
| 62 63 | 
             
                    # First try simple serial format
         | 
| 63 | 
            -
                    match = re.search(r | 
| 64 | 
            +
                    match = re.search(r"CLAUDE_MD_VERSION:\s*(\d+)(?!-)", content)
         | 
| 64 65 | 
             
                    if match:
         | 
| 65 66 | 
             
                        return match.group(1)
         | 
| 66 | 
            -
             | 
| 67 | 
            +
             | 
| 67 68 | 
             
                    # Handle old format for backward compatibility
         | 
| 68 | 
            -
                    match = re.search(r | 
| 69 | 
            +
                    match = re.search(r"CLAUDE_MD_VERSION:\s*(\d+)-(\d+)", content)
         | 
| 69 70 | 
             
                    if match:
         | 
| 70 71 | 
             
                        return match.group(1)  # Return just the framework part
         | 
| 71 | 
            -
             | 
| 72 | 
            +
             | 
| 72 73 | 
             
                    return self.framework_version
         | 
| 73 | 
            -
             | 
| 74 | 
            +
             | 
| 74 75 | 
             
                def auto_increment_version(self, current_content: Optional[str] = None) -> str:
         | 
| 75 76 | 
             
                    """
         | 
| 76 77 | 
             
                    Get the current framework version (no auto-increment for simple serial numbers).
         | 
| 77 | 
            -
             | 
| 78 | 
            +
             | 
| 78 79 | 
             
                    Args:
         | 
| 79 80 | 
             
                        current_content: Current CLAUDE.md content (unused with simple serials)
         | 
| 80 | 
            -
             | 
| 81 | 
            +
             | 
| 81 82 | 
             
                    Returns:
         | 
| 82 83 | 
             
                        str: Current framework version (e.g., "016")
         | 
| 83 84 | 
             
                    """
         | 
| 84 85 | 
             
                    # With simple serial numbers, we just use the framework version
         | 
| 85 86 | 
             
                    # Incrementing is done by updating the framework/VERSION file
         | 
| 86 87 | 
             
                    return self.framework_version
         | 
| 87 | 
            -
             | 
| 88 | 
            +
             | 
| 88 89 | 
             
                def compare_versions(self, version1: str, version2: str) -> int:
         | 
| 89 90 | 
             
                    """
         | 
| 90 91 | 
             
                    Compare two version strings.
         | 
| 91 | 
            -
             | 
| 92 | 
            +
             | 
| 92 93 | 
             
                    Args:
         | 
| 93 94 | 
             
                        version1: First version string (e.g., "016")
         | 
| 94 95 | 
             
                        version2: Second version string (e.g., "017")
         | 
| 95 | 
            -
             | 
| 96 | 
            +
             | 
| 96 97 | 
             
                    Returns:
         | 
| 97 98 | 
             
                        int: -1 if version1 < version2, 0 if equal, 1 if version1 > version2
         | 
| 98 99 | 
             
                    """
         | 
| 100 | 
            +
             | 
| 99 101 | 
             
                    def parse_version(v: str) -> int:
         | 
| 100 102 | 
             
                        # Handle simple serial format
         | 
| 101 | 
            -
                        if  | 
| 103 | 
            +
                        if "-" not in v:
         | 
| 102 104 | 
             
                            try:
         | 
| 103 105 | 
             
                                return int(v)
         | 
| 104 106 | 
             
                            except ValueError:
         | 
| 105 107 | 
             
                                return 0
         | 
| 106 | 
            -
             | 
| 108 | 
            +
             | 
| 107 109 | 
             
                        # Handle old format for backward compatibility
         | 
| 108 | 
            -
                        match = re.match(r | 
| 110 | 
            +
                        match = re.match(r"(\d+)-(\d+)", v)
         | 
| 109 111 | 
             
                        if match:
         | 
| 110 112 | 
             
                            return int(match.group(1))  # Just compare framework part
         | 
| 111 113 | 
             
                        return 0
         | 
| 112 | 
            -
             | 
| 114 | 
            +
             | 
| 113 115 | 
             
                    v1 = parse_version(version1)
         | 
| 114 116 | 
             
                    v2 = parse_version(version2)
         | 
| 115 | 
            -
             | 
| 117 | 
            +
             | 
| 116 118 | 
             
                    if v1 < v2:
         | 
| 117 119 | 
             
                        return -1
         | 
| 118 120 | 
             
                    elif v1 > v2:
         | 
| 119 121 | 
             
                        return 1
         | 
| 120 122 | 
             
                    else:
         | 
| 121 | 
            -
                        return 0
         | 
| 123 | 
            +
                        return 0
         | 
| @@ -11,65 +11,65 @@ rather than a single list with type checking because: | |
| 11 11 | 
             
            - It prevents accidentally mixing hook types
         | 
| 12 12 | 
             
            """
         | 
| 13 13 |  | 
| 14 | 
            -
            from typing import List, Optional, Dict, Any
         | 
| 15 14 | 
             
            import time
         | 
| 16 15 | 
             
            from datetime import datetime
         | 
| 16 | 
            +
            from typing import Any, Dict, List, Optional
         | 
| 17 17 |  | 
| 18 18 | 
             
            from claude_mpm.core.config import Config
         | 
| 19 | 
            +
            from claude_mpm.core.interfaces import HookServiceInterface
         | 
| 19 20 | 
             
            from claude_mpm.core.logging_config import get_logger, log_operation
         | 
| 20 21 | 
             
            from claude_mpm.hooks.base_hook import (
         | 
| 21 22 | 
             
                BaseHook,
         | 
| 22 | 
            -
                PreDelegationHook,
         | 
| 23 | 
            -
                PostDelegationHook,
         | 
| 24 23 | 
             
                HookContext,
         | 
| 25 24 | 
             
                HookResult,
         | 
| 26 | 
            -
                HookType
         | 
| 25 | 
            +
                HookType,
         | 
| 26 | 
            +
                PostDelegationHook,
         | 
| 27 | 
            +
                PreDelegationHook,
         | 
| 27 28 | 
             
            )
         | 
| 28 | 
            -
            from claude_mpm.core.interfaces import HookServiceInterface
         | 
| 29 29 |  | 
| 30 30 |  | 
| 31 31 | 
             
            class HookService(HookServiceInterface):
         | 
| 32 32 | 
             
                """Service for managing and executing hooks in the delegation workflow.
         | 
| 33 | 
            -
             | 
| 33 | 
            +
             | 
| 34 34 | 
             
                WHY: Provides a centralized place to register and execute hooks, ensuring
         | 
| 35 35 | 
             
                they run in the correct order and that failures in individual hooks don't
         | 
| 36 36 | 
             
                break the entire delegation flow.
         | 
| 37 | 
            -
             | 
| 37 | 
            +
             | 
| 38 38 | 
             
                DESIGN DECISION: We execute hooks even if previous ones fail because:
         | 
| 39 39 | 
             
                - Hooks should be independent and not rely on each other
         | 
| 40 40 | 
             
                - A logging hook failure shouldn't prevent memory hooks from running
         | 
| 41 41 | 
             
                - We log all failures for debugging but keep the system resilient
         | 
| 42 42 | 
             
                """
         | 
| 43 | 
            -
             | 
| 43 | 
            +
             | 
| 44 44 | 
             
                def __init__(self, config: Optional[Config] = None):
         | 
| 45 45 | 
             
                    """Initialize the hook service.
         | 
| 46 | 
            -
             | 
| 46 | 
            +
             | 
| 47 47 | 
             
                    Args:
         | 
| 48 48 | 
             
                        config: Optional configuration object for controlling hook behavior
         | 
| 49 49 | 
             
                    """
         | 
| 50 50 | 
             
                    self.config = config or Config()
         | 
| 51 51 | 
             
                    self.logger = get_logger(__name__)
         | 
| 52 | 
            -
             | 
| 52 | 
            +
             | 
| 53 53 | 
             
                    # Separate lists for different hook types for performance
         | 
| 54 54 | 
             
                    self.pre_delegation_hooks: List[PreDelegationHook] = []
         | 
| 55 55 | 
             
                    self.post_delegation_hooks: List[PostDelegationHook] = []
         | 
| 56 | 
            -
             | 
| 56 | 
            +
             | 
| 57 57 | 
             
                    # Track execution statistics for monitoring
         | 
| 58 58 | 
             
                    self.stats = {
         | 
| 59 59 | 
             
                        "pre_delegation_executed": 0,
         | 
| 60 60 | 
             
                        "post_delegation_executed": 0,
         | 
| 61 | 
            -
                        "errors": 0
         | 
| 61 | 
            +
                        "errors": 0,
         | 
| 62 62 | 
             
                    }
         | 
| 63 | 
            -
             | 
| 63 | 
            +
             | 
| 64 64 | 
             
                def register_hook(self, hook: BaseHook) -> bool:
         | 
| 65 65 | 
             
                    """Register a hook with the service.
         | 
| 66 | 
            -
             | 
| 66 | 
            +
             | 
| 67 67 | 
             
                    WHY: We need a way to add hooks dynamically, and we validate the hook
         | 
| 68 68 | 
             
                    type to ensure it goes into the correct execution list.
         | 
| 69 | 
            -
             | 
| 69 | 
            +
             | 
| 70 70 | 
             
                    Args:
         | 
| 71 71 | 
             
                        hook: The hook to register
         | 
| 72 | 
            -
             | 
| 72 | 
            +
             | 
| 73 73 | 
             
                    Returns:
         | 
| 74 74 | 
             
                        True if successfully registered, False otherwise
         | 
| 75 75 | 
             
                    """
         | 
| @@ -78,64 +78,66 @@ class HookService(HookServiceInterface): | |
| 78 78 | 
             
                            self.pre_delegation_hooks.append(hook)
         | 
| 79 79 | 
             
                            # Sort by priority (lower number = higher priority = executes first)
         | 
| 80 80 | 
             
                            self.pre_delegation_hooks.sort(key=lambda h: h.priority)
         | 
| 81 | 
            -
                            self.logger.info( | 
| 81 | 
            +
                            self.logger.info(
         | 
| 82 | 
            +
                                f"Registered pre-delegation hook: {hook.name} (priority: {hook.priority})"
         | 
| 83 | 
            +
                            )
         | 
| 82 84 | 
             
                            return True
         | 
| 83 | 
            -
             | 
| 85 | 
            +
             | 
| 84 86 | 
             
                        elif isinstance(hook, PostDelegationHook):
         | 
| 85 87 | 
             
                            self.post_delegation_hooks.append(hook)
         | 
| 86 88 | 
             
                            # Sort by priority
         | 
| 87 89 | 
             
                            self.post_delegation_hooks.sort(key=lambda h: h.priority)
         | 
| 88 | 
            -
                            self.logger.info( | 
| 90 | 
            +
                            self.logger.info(
         | 
| 91 | 
            +
                                f"Registered post-delegation hook: {hook.name} (priority: {hook.priority})"
         | 
| 92 | 
            +
                            )
         | 
| 89 93 | 
             
                            return True
         | 
| 90 | 
            -
             | 
| 94 | 
            +
             | 
| 91 95 | 
             
                        else:
         | 
| 92 | 
            -
                            self.logger.warning( | 
| 96 | 
            +
                            self.logger.warning(
         | 
| 97 | 
            +
                                f"Attempted to register unsupported hook type: {type(hook).__name__}"
         | 
| 98 | 
            +
                            )
         | 
| 93 99 | 
             
                            return False
         | 
| 94 | 
            -
             | 
| 100 | 
            +
             | 
| 95 101 | 
             
                    except Exception as e:
         | 
| 96 102 | 
             
                        self.logger.error(f"Failed to register hook {hook.name}: {e}")
         | 
| 97 103 | 
             
                        return False
         | 
| 98 | 
            -
             | 
| 104 | 
            +
             | 
| 99 105 | 
             
                def execute_pre_delegation_hooks(self, context: HookContext) -> HookResult:
         | 
| 100 106 | 
             
                    """Execute all pre-delegation hooks in priority order.
         | 
| 101 | 
            -
             | 
| 107 | 
            +
             | 
| 102 108 | 
             
                    WHY: Pre-delegation hooks need to modify the context before it's sent
         | 
| 103 109 | 
             
                    to the agent. Each hook can add or modify context data.
         | 
| 104 | 
            -
             | 
| 110 | 
            +
             | 
| 105 111 | 
             
                    DESIGN DECISION: We pass the context through all hooks sequentially,
         | 
| 106 112 | 
             
                    allowing each to modify it. This enables powerful composition patterns.
         | 
| 107 | 
            -
             | 
| 113 | 
            +
             | 
| 108 114 | 
             
                    Args:
         | 
| 109 115 | 
             
                        context: The HookContext to be processed by hooks
         | 
| 110 | 
            -
             | 
| 116 | 
            +
             | 
| 111 117 | 
             
                    Returns:
         | 
| 112 118 | 
             
                        HookResult containing the final processed data
         | 
| 113 119 | 
             
                    """
         | 
| 114 120 | 
             
                    # Check if hooks are enabled via config
         | 
| 115 121 | 
             
                    if not self._are_hooks_enabled("pre_delegation"):
         | 
| 116 | 
            -
                        return HookResult(
         | 
| 117 | 
            -
             | 
| 118 | 
            -
                            data=context.data,
         | 
| 119 | 
            -
                            modified=False
         | 
| 120 | 
            -
                        )
         | 
| 121 | 
            -
                        
         | 
| 122 | 
            +
                        return HookResult(success=True, data=context.data, modified=False)
         | 
| 123 | 
            +
             | 
| 122 124 | 
             
                    # Create a working copy of the data to preserve original
         | 
| 123 125 | 
             
                    working_data = context.data.copy()
         | 
| 124 | 
            -
             | 
| 126 | 
            +
             | 
| 125 127 | 
             
                    executed_count = 0
         | 
| 126 128 | 
             
                    has_modifications = False
         | 
| 127 | 
            -
             | 
| 129 | 
            +
             | 
| 128 130 | 
             
                    for hook in self.pre_delegation_hooks:
         | 
| 129 131 | 
             
                        if not hook.enabled:
         | 
| 130 132 | 
             
                            self.logger.debug(f"Skipping disabled hook: {hook.name}")
         | 
| 131 133 | 
             
                            continue
         | 
| 132 | 
            -
             | 
| 134 | 
            +
             | 
| 133 135 | 
             
                        try:
         | 
| 134 136 | 
             
                            # Validate if hook should run
         | 
| 135 137 | 
             
                            if not hook.validate(context):
         | 
| 136 138 | 
             
                                self.logger.debug(f"Hook {hook.name} validation failed, skipping")
         | 
| 137 139 | 
             
                                continue
         | 
| 138 | 
            -
             | 
| 140 | 
            +
             | 
| 139 141 | 
             
                            # Create a hook context with the current working data
         | 
| 140 142 | 
             
                            hook_context = HookContext(
         | 
| 141 143 | 
             
                                hook_type=context.hook_type,
         | 
| @@ -143,21 +145,21 @@ class HookService(HookServiceInterface): | |
| 143 145 | 
             
                                metadata=context.metadata,
         | 
| 144 146 | 
             
                                timestamp=context.timestamp,
         | 
| 145 147 | 
             
                                session_id=context.session_id,
         | 
| 146 | 
            -
                                user_id=context.user_id
         | 
| 148 | 
            +
                                user_id=context.user_id,
         | 
| 147 149 | 
             
                            )
         | 
| 148 | 
            -
             | 
| 150 | 
            +
             | 
| 149 151 | 
             
                            # Execute with timing
         | 
| 150 152 | 
             
                            start_time = time.time()
         | 
| 151 153 | 
             
                            result = hook.execute(hook_context)
         | 
| 152 154 | 
             
                            execution_time = (time.time() - start_time) * 1000  # ms
         | 
| 153 | 
            -
             | 
| 155 | 
            +
             | 
| 154 156 | 
             
                            if result.success:
         | 
| 155 157 | 
             
                                if result.modified and result.data:
         | 
| 156 158 | 
             
                                    # Update working data with modified data
         | 
| 157 159 | 
             
                                    working_data.update(result.data)
         | 
| 158 160 | 
             
                                    has_modifications = True
         | 
| 159 161 | 
             
                                    self.logger.debug(f"Hook {hook.name} modified context")
         | 
| 160 | 
            -
             | 
| 162 | 
            +
             | 
| 161 163 | 
             
                                self.logger.info(
         | 
| 162 164 | 
             
                                    f"Executed pre-delegation hook {hook.name} "
         | 
| 163 165 | 
             
                                    f"(took {execution_time:.2f}ms)"
         | 
| @@ -165,60 +167,52 @@ class HookService(HookServiceInterface): | |
| 165 167 | 
             
                            else:
         | 
| 166 168 | 
             
                                self.logger.warning(f"Hook {hook.name} failed: {result.error}")
         | 
| 167 169 | 
             
                                self.stats["errors"] += 1
         | 
| 168 | 
            -
             | 
| 170 | 
            +
             | 
| 169 171 | 
             
                            executed_count += 1
         | 
| 170 | 
            -
             | 
| 172 | 
            +
             | 
| 171 173 | 
             
                        except Exception as e:
         | 
| 172 174 | 
             
                            # Log error but continue with other hooks
         | 
| 173 175 | 
             
                            self.logger.error(f"Exception in hook {hook.name}: {e}", exc_info=True)
         | 
| 174 176 | 
             
                            self.stats["errors"] += 1
         | 
| 175 | 
            -
             | 
| 177 | 
            +
             | 
| 176 178 | 
             
                    self.stats["pre_delegation_executed"] += executed_count
         | 
| 177 179 | 
             
                    self.logger.info(f"Executed {executed_count} pre-delegation hooks")
         | 
| 178 | 
            -
             | 
| 179 | 
            -
                    return HookResult(
         | 
| 180 | 
            -
             | 
| 181 | 
            -
                        data=working_data,
         | 
| 182 | 
            -
                        modified=has_modifications
         | 
| 183 | 
            -
                    )
         | 
| 184 | 
            -
                
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                    return HookResult(success=True, data=working_data, modified=has_modifications)
         | 
| 182 | 
            +
             | 
| 185 183 | 
             
                def execute_post_delegation_hooks(self, context: HookContext) -> HookResult:
         | 
| 186 184 | 
             
                    """Execute all post-delegation hooks in priority order.
         | 
| 187 | 
            -
             | 
| 185 | 
            +
             | 
| 188 186 | 
             
                    WHY: Post-delegation hooks need to process agent results, extract learnings,
         | 
| 189 187 | 
             
                    log outcomes, or perform other post-processing tasks.
         | 
| 190 | 
            -
             | 
| 188 | 
            +
             | 
| 191 189 | 
             
                    Args:
         | 
| 192 190 | 
             
                        context: The HookContext containing delegation results
         | 
| 193 | 
            -
             | 
| 191 | 
            +
             | 
| 194 192 | 
             
                    Returns:
         | 
| 195 193 | 
             
                        HookResult containing the final processed data
         | 
| 196 194 | 
             
                    """
         | 
| 197 195 | 
             
                    # Check if hooks are enabled via config
         | 
| 198 196 | 
             
                    if not self._are_hooks_enabled("post_delegation"):
         | 
| 199 | 
            -
                        return HookResult(
         | 
| 200 | 
            -
             | 
| 201 | 
            -
                            data=context.data,
         | 
| 202 | 
            -
                            modified=False
         | 
| 203 | 
            -
                        )
         | 
| 204 | 
            -
                        
         | 
| 197 | 
            +
                        return HookResult(success=True, data=context.data, modified=False)
         | 
| 198 | 
            +
             | 
| 205 199 | 
             
                    # Create a working copy of the data to preserve original
         | 
| 206 200 | 
             
                    working_data = context.data.copy()
         | 
| 207 | 
            -
             | 
| 201 | 
            +
             | 
| 208 202 | 
             
                    executed_count = 0
         | 
| 209 203 | 
             
                    has_modifications = False
         | 
| 210 | 
            -
             | 
| 204 | 
            +
             | 
| 211 205 | 
             
                    for hook in self.post_delegation_hooks:
         | 
| 212 206 | 
             
                        if not hook.enabled:
         | 
| 213 207 | 
             
                            self.logger.debug(f"Skipping disabled hook: {hook.name}")
         | 
| 214 208 | 
             
                            continue
         | 
| 215 | 
            -
             | 
| 209 | 
            +
             | 
| 216 210 | 
             
                        try:
         | 
| 217 211 | 
             
                            # Validate if hook should run
         | 
| 218 212 | 
             
                            if not hook.validate(context):
         | 
| 219 213 | 
             
                                self.logger.debug(f"Hook {hook.name} validation failed, skipping")
         | 
| 220 214 | 
             
                                continue
         | 
| 221 | 
            -
             | 
| 215 | 
            +
             | 
| 222 216 | 
             
                            # Create a hook context with the current working data
         | 
| 223 217 | 
             
                            hook_context = HookContext(
         | 
| 224 218 | 
             
                                hook_type=context.hook_type,
         | 
| @@ -226,21 +220,21 @@ class HookService(HookServiceInterface): | |
| 226 220 | 
             
                                metadata=context.metadata,
         | 
| 227 221 | 
             
                                timestamp=context.timestamp,
         | 
| 228 222 | 
             
                                session_id=context.session_id,
         | 
| 229 | 
            -
                                user_id=context.user_id
         | 
| 223 | 
            +
                                user_id=context.user_id,
         | 
| 230 224 | 
             
                            )
         | 
| 231 | 
            -
             | 
| 225 | 
            +
             | 
| 232 226 | 
             
                            # Execute with timing
         | 
| 233 227 | 
             
                            start_time = time.time()
         | 
| 234 228 | 
             
                            result = hook.execute(hook_context)
         | 
| 235 229 | 
             
                            execution_time = (time.time() - start_time) * 1000  # ms
         | 
| 236 | 
            -
             | 
| 230 | 
            +
             | 
| 237 231 | 
             
                            if result.success:
         | 
| 238 232 | 
             
                                if result.modified and result.data:
         | 
| 239 233 | 
             
                                    # Update working data with modified data
         | 
| 240 234 | 
             
                                    working_data.update(result.data)
         | 
| 241 235 | 
             
                                    has_modifications = True
         | 
| 242 236 | 
             
                                    self.logger.debug(f"Hook {hook.name} modified context")
         | 
| 243 | 
            -
             | 
| 237 | 
            +
             | 
| 244 238 | 
             
                                self.logger.info(
         | 
| 245 239 | 
             
                                    f"Executed post-delegation hook {hook.name} "
         | 
| 246 240 | 
             
                                    f"(took {execution_time:.2f}ms)"
         | 
| @@ -248,32 +242,28 @@ class HookService(HookServiceInterface): | |
| 248 242 | 
             
                            else:
         | 
| 249 243 | 
             
                                self.logger.warning(f"Hook {hook.name} failed: {result.error}")
         | 
| 250 244 | 
             
                                self.stats["errors"] += 1
         | 
| 251 | 
            -
             | 
| 245 | 
            +
             | 
| 252 246 | 
             
                            executed_count += 1
         | 
| 253 | 
            -
             | 
| 247 | 
            +
             | 
| 254 248 | 
             
                        except Exception as e:
         | 
| 255 249 | 
             
                            # Log error but continue with other hooks
         | 
| 256 250 | 
             
                            self.logger.error(f"Exception in hook {hook.name}: {e}", exc_info=True)
         | 
| 257 251 | 
             
                            self.stats["errors"] += 1
         | 
| 258 | 
            -
             | 
| 252 | 
            +
             | 
| 259 253 | 
             
                    self.stats["post_delegation_executed"] += executed_count
         | 
| 260 254 | 
             
                    self.logger.info(f"Executed {executed_count} post-delegation hooks")
         | 
| 261 | 
            -
             | 
| 262 | 
            -
                    return HookResult(
         | 
| 263 | 
            -
             | 
| 264 | 
            -
                        data=working_data,
         | 
| 265 | 
            -
                        modified=has_modifications
         | 
| 266 | 
            -
                    )
         | 
| 267 | 
            -
                
         | 
| 255 | 
            +
             | 
| 256 | 
            +
                    return HookResult(success=True, data=working_data, modified=has_modifications)
         | 
| 257 | 
            +
             | 
| 268 258 | 
             
                def _are_hooks_enabled(self, hook_type: str) -> bool:
         | 
| 269 259 | 
             
                    """Check if hooks are enabled in configuration.
         | 
| 270 | 
            -
             | 
| 260 | 
            +
             | 
| 271 261 | 
             
                    WHY: We need fine-grained control over hook execution. This allows
         | 
| 272 262 | 
             
                    disabling hooks for debugging or in specific environments.
         | 
| 273 | 
            -
             | 
| 263 | 
            +
             | 
| 274 264 | 
             
                    Args:
         | 
| 275 265 | 
             
                        hook_type: Type of hooks to check (pre_delegation, post_delegation)
         | 
| 276 | 
            -
             | 
| 266 | 
            +
             | 
| 277 267 | 
             
                    Returns:
         | 
| 278 268 | 
             
                        True if hooks are enabled
         | 
| 279 269 | 
             
                    """
         | 
| @@ -281,67 +271,69 @@ class HookService(HookServiceInterface): | |
| 281 271 | 
             
                    if not self.config.get("hooks.enabled", True):
         | 
| 282 272 | 
             
                        self.logger.debug("All hooks disabled via configuration")
         | 
| 283 273 | 
             
                        return False
         | 
| 284 | 
            -
             | 
| 274 | 
            +
             | 
| 285 275 | 
             
                    # Check specific hook type enable flag
         | 
| 286 276 | 
             
                    if not self.config.get(f"hooks.{hook_type}.enabled", True):
         | 
| 287 277 | 
             
                        self.logger.debug(f"{hook_type} hooks disabled via configuration")
         | 
| 288 278 | 
             
                        return False
         | 
| 289 | 
            -
             | 
| 279 | 
            +
             | 
| 290 280 | 
             
                    # Special check for memory hooks if they depend on memory system
         | 
| 291 281 | 
             
                    if hook_type in ["pre_delegation", "post_delegation"]:
         | 
| 292 282 | 
             
                        # If any registered hooks are memory-related, check memory.enabled
         | 
| 293 283 | 
             
                        for hook in getattr(self, f"{hook_type}_hooks", []):
         | 
| 294 284 | 
             
                            if "memory" in hook.name.lower():
         | 
| 295 285 | 
             
                                if not self.config.get("memory.enabled", True):
         | 
| 296 | 
            -
                                    self.logger.debug( | 
| 286 | 
            +
                                    self.logger.debug(
         | 
| 287 | 
            +
                                        "Memory hooks disabled via memory.enabled config"
         | 
| 288 | 
            +
                                    )
         | 
| 297 289 | 
             
                                    return False
         | 
| 298 | 
            -
             | 
| 290 | 
            +
             | 
| 299 291 | 
             
                    return True
         | 
| 300 | 
            -
             | 
| 292 | 
            +
             | 
| 301 293 | 
             
                def get_stats(self) -> Dict[str, int]:
         | 
| 302 294 | 
             
                    """Get execution statistics.
         | 
| 303 | 
            -
             | 
| 295 | 
            +
             | 
| 304 296 | 
             
                    WHY: Monitoring hook execution helps identify performance issues
         | 
| 305 297 | 
             
                    and debug problems in production.
         | 
| 306 | 
            -
             | 
| 298 | 
            +
             | 
| 307 299 | 
             
                    Returns:
         | 
| 308 300 | 
             
                        Dictionary of execution statistics
         | 
| 309 301 | 
             
                    """
         | 
| 310 302 | 
             
                    return self.stats.copy()
         | 
| 311 | 
            -
             | 
| 303 | 
            +
             | 
| 312 304 | 
             
                def reset_stats(self):
         | 
| 313 305 | 
             
                    """Reset execution statistics.
         | 
| 314 | 
            -
             | 
| 306 | 
            +
             | 
| 315 307 | 
             
                    WHY: Allows periodic cleanup of stats for long-running services.
         | 
| 316 308 | 
             
                    """
         | 
| 317 309 | 
             
                    self.stats = {
         | 
| 318 310 | 
             
                        "pre_delegation_executed": 0,
         | 
| 319 311 | 
             
                        "post_delegation_executed": 0,
         | 
| 320 | 
            -
                        "errors": 0
         | 
| 312 | 
            +
                        "errors": 0,
         | 
| 321 313 | 
             
                    }
         | 
| 322 | 
            -
             | 
| 314 | 
            +
             | 
| 323 315 | 
             
                def list_hooks(self) -> Dict[str, List[str]]:
         | 
| 324 316 | 
             
                    """List all registered hooks by type.
         | 
| 325 | 
            -
             | 
| 317 | 
            +
             | 
| 326 318 | 
             
                    WHY: Useful for debugging and understanding what hooks are active.
         | 
| 327 | 
            -
             | 
| 319 | 
            +
             | 
| 328 320 | 
             
                    Returns:
         | 
| 329 321 | 
             
                        Dictionary mapping hook type to list of hook names
         | 
| 330 322 | 
             
                    """
         | 
| 331 323 | 
             
                    return {
         | 
| 332 324 | 
             
                        "pre_delegation": [h.name for h in self.pre_delegation_hooks],
         | 
| 333 | 
            -
                        "post_delegation": [h.name for h in self.post_delegation_hooks]
         | 
| 325 | 
            +
                        "post_delegation": [h.name for h in self.post_delegation_hooks],
         | 
| 334 326 | 
             
                    }
         | 
| 335 | 
            -
             | 
| 327 | 
            +
             | 
| 336 328 | 
             
                def remove_hook(self, hook_name: str) -> bool:
         | 
| 337 329 | 
             
                    """Remove a hook by name.
         | 
| 338 | 
            -
             | 
| 330 | 
            +
             | 
| 339 331 | 
             
                    WHY: Allows dynamic hook management, useful for testing or
         | 
| 340 332 | 
             
                    conditional hook usage.
         | 
| 341 | 
            -
             | 
| 333 | 
            +
             | 
| 342 334 | 
             
                    Args:
         | 
| 343 335 | 
             
                        hook_name: Name of the hook to remove
         | 
| 344 | 
            -
             | 
| 336 | 
            +
             | 
| 345 337 | 
             
                    Returns:
         | 
| 346 338 | 
             
                        True if hook was found and removed
         | 
| 347 339 | 
             
                    """
         | 
| @@ -351,28 +343,28 @@ class HookService(HookServiceInterface): | |
| 351 343 | 
             
                            self.pre_delegation_hooks.pop(i)
         | 
| 352 344 | 
             
                            self.logger.info(f"Removed pre-delegation hook: {hook_name}")
         | 
| 353 345 | 
             
                            return True
         | 
| 354 | 
            -
             | 
| 346 | 
            +
             | 
| 355 347 | 
             
                    # Check post-delegation hooks
         | 
| 356 348 | 
             
                    for i, hook in enumerate(self.post_delegation_hooks):
         | 
| 357 349 | 
             
                        if hook.name == hook_name:
         | 
| 358 350 | 
             
                            self.post_delegation_hooks.pop(i)
         | 
| 359 351 | 
             
                            self.logger.info(f"Removed post-delegation hook: {hook_name}")
         | 
| 360 352 | 
             
                            return True
         | 
| 361 | 
            -
             | 
| 353 | 
            +
             | 
| 362 354 | 
             
                    self.logger.warning(f"Hook not found: {hook_name}")
         | 
| 363 355 | 
             
                    return False
         | 
| 364 | 
            -
             | 
| 356 | 
            +
             | 
| 365 357 | 
             
                # ================================================================================
         | 
| 366 358 | 
             
                # Interface Adapter Methods
         | 
| 367 359 | 
             
                # ================================================================================
         | 
| 368 360 | 
             
                # These methods are added to comply with HookServiceInterface
         | 
| 369 | 
            -
             | 
| 361 | 
            +
             | 
| 370 362 | 
             
                def get_registered_hooks(self) -> Dict[str, List[Any]]:
         | 
| 371 363 | 
             
                    """Get all registered hooks by type.
         | 
| 372 | 
            -
             | 
| 364 | 
            +
             | 
| 373 365 | 
             
                    WHY: This method provides interface compliance by exposing the
         | 
| 374 366 | 
             
                    registered hooks for inspection and debugging purposes.
         | 
| 375 | 
            -
             | 
| 367 | 
            +
             | 
| 376 368 | 
             
                    Returns:
         | 
| 377 369 | 
             
                        Dictionary mapping hook types to lists of hooks
         | 
| 378 370 | 
             
                    """
         | 
| @@ -382,7 +374,7 @@ class HookService(HookServiceInterface): | |
| 382 374 | 
             
                                "name": hook.name,
         | 
| 383 375 | 
             
                                "priority": hook.priority,
         | 
| 384 376 | 
             
                                "enabled": hook.enabled,
         | 
| 385 | 
            -
                                "type": "pre_delegation"
         | 
| 377 | 
            +
                                "type": "pre_delegation",
         | 
| 386 378 | 
             
                            }
         | 
| 387 379 | 
             
                            for hook in self.pre_delegation_hooks
         | 
| 388 380 | 
             
                        ],
         | 
| @@ -391,18 +383,18 @@ class HookService(HookServiceInterface): | |
| 391 383 | 
             
                                "name": hook.name,
         | 
| 392 384 | 
             
                                "priority": hook.priority,
         | 
| 393 385 | 
             
                                "enabled": hook.enabled,
         | 
| 394 | 
            -
                                "type": "post_delegation"
         | 
| 386 | 
            +
                                "type": "post_delegation",
         | 
| 395 387 | 
             
                            }
         | 
| 396 388 | 
             
                            for hook in self.post_delegation_hooks
         | 
| 397 | 
            -
                        ]
         | 
| 389 | 
            +
                        ],
         | 
| 398 390 | 
             
                    }
         | 
| 399 | 
            -
             | 
| 391 | 
            +
             | 
| 400 392 | 
             
                def clear_hooks(self, hook_type: Optional[str] = None) -> None:
         | 
| 401 393 | 
             
                    """Clear registered hooks.
         | 
| 402 | 
            -
             | 
| 394 | 
            +
             | 
| 403 395 | 
             
                    WHY: This method provides interface compliance by allowing bulk
         | 
| 404 396 | 
             
                    removal of hooks, useful for testing and cleanup scenarios.
         | 
| 405 | 
            -
             | 
| 397 | 
            +
             | 
| 406 398 | 
             
                    Args:
         | 
| 407 399 | 
             
                        hook_type: Optional specific hook type to clear, or None for all
         | 
| 408 400 | 
             
                    """
         | 
| @@ -411,12 +403,12 @@ class HookService(HookServiceInterface): | |
| 411 403 | 
             
                        self.pre_delegation_hooks.clear()
         | 
| 412 404 | 
             
                        if count > 0:
         | 
| 413 405 | 
             
                            self.logger.info(f"Cleared {count} pre-delegation hooks")
         | 
| 414 | 
            -
             | 
| 406 | 
            +
             | 
| 415 407 | 
             
                    if hook_type is None or hook_type == "post_delegation":
         | 
| 416 408 | 
             
                        count = len(self.post_delegation_hooks)
         | 
| 417 409 | 
             
                        self.post_delegation_hooks.clear()
         | 
| 418 410 | 
             
                        if count > 0:
         | 
| 419 411 | 
             
                            self.logger.info(f"Cleared {count} post-delegation hooks")
         | 
| 420 | 
            -
             | 
| 412 | 
            +
             | 
| 421 413 | 
             
                    if hook_type and hook_type not in ["pre_delegation", "post_delegation"]:
         | 
| 422 | 
            -
                        self.logger.warning(f"Unknown hook type: {hook_type}")
         | 
| 414 | 
            +
                        self.logger.warning(f"Unknown hook type: {hook_type}")
         | 
| @@ -13,12 +13,14 @@ Services: | |
| 13 13 | 
             
            - MemoryGuardian: Memory monitoring and process restart management
         | 
| 14 14 | 
             
            """
         | 
| 15 15 |  | 
| 16 | 
            +
            from .health_monitor import HealthMonitor
         | 
| 16 17 | 
             
            from .logging import LoggingService
         | 
| 17 | 
            -
            from .monitoring import AdvancedHealthMonitor as HealthMonitor
         | 
| 18 18 | 
             
            from .memory_guardian import MemoryGuardian
         | 
| 19 | 
            +
            from .monitoring import AdvancedHealthMonitor
         | 
| 19 20 |  | 
| 20 21 | 
             
            __all__ = [
         | 
| 21 | 
            -
                 | 
| 22 | 
            -
                 | 
| 23 | 
            -
                 | 
| 24 | 
            -
             | 
| 22 | 
            +
                "LoggingService",
         | 
| 23 | 
            +
                "AdvancedHealthMonitor",  # For SocketIO server monitoring
         | 
| 24 | 
            +
                "HealthMonitor",  # For Memory Guardian system monitoring
         | 
| 25 | 
            +
                "MemoryGuardian",
         | 
| 26 | 
            +
            ]
         |