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
| @@ -12,18 +12,18 @@ if [ -d "$SCRIPT_DIR/../../../../venv" ]; then | |
| 12 12 | 
             
                # Development environment - script is in src/claude_mpm/hooks/claude_hooks/
         | 
| 13 13 | 
             
                PROJECT_ROOT="$( cd "$SCRIPT_DIR/../../../.." && pwd )"
         | 
| 14 14 | 
             
                PYTHON_CMD="python"
         | 
| 15 | 
            -
             | 
| 15 | 
            +
             | 
| 16 16 | 
             
                # Activate the virtual environment if it exists
         | 
| 17 17 | 
             
                if [ -f "$PROJECT_ROOT/venv/bin/activate" ]; then
         | 
| 18 18 | 
             
                    source "$PROJECT_ROOT/venv/bin/activate"
         | 
| 19 19 | 
             
                fi
         | 
| 20 | 
            -
             | 
| 20 | 
            +
             | 
| 21 21 | 
             
                # Set PYTHONPATH for development
         | 
| 22 22 | 
             
                export PYTHONPATH="$PROJECT_ROOT/src:$PYTHONPATH"
         | 
| 23 23 | 
             
            else
         | 
| 24 24 | 
             
                # Installed package - use system Python and installed claude_mpm
         | 
| 25 25 | 
             
                PYTHON_CMD="python3"
         | 
| 26 | 
            -
             | 
| 26 | 
            +
             | 
| 27 27 | 
             
                # Try to detect if we're in a virtual environment
         | 
| 28 28 | 
             
                if [ -n "$VIRTUAL_ENV" ]; then
         | 
| 29 29 | 
             
                    PYTHON_CMD="$VIRTUAL_ENV/bin/python"
         | 
| @@ -56,4 +56,4 @@ if ! "$PYTHON_CMD" "$SCRIPT_DIR/hook_handler.py" "$@" 2>/tmp/hook-error.log; the | |
| 56 56 | 
             
                # Log the error for debugging
         | 
| 57 57 | 
             
                echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Hook handler failed, see /tmp/hook-error.log" >> /tmp/hook-wrapper.log
         | 
| 58 58 | 
             
                exit 0
         | 
| 59 | 
            -
            fi
         | 
| 59 | 
            +
            fi
         | 
| @@ -0,0 +1,221 @@ | |
| 1 | 
            +
            #!/usr/bin/env python3
         | 
| 2 | 
            +
            """Memory integration utilities for Claude Code hook handler.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            This module provides utilities for integrating with the memory system,
         | 
| 5 | 
            +
            including pre and post delegation hooks.
         | 
| 6 | 
            +
            """
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            import os
         | 
| 9 | 
            +
            import sys
         | 
| 10 | 
            +
            from datetime import datetime
         | 
| 11 | 
            +
            from typing import Any, Dict, Optional
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            # Debug mode
         | 
| 14 | 
            +
            DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "true").lower() != "false"
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            # Memory hooks integration
         | 
| 17 | 
            +
            MEMORY_HOOKS_AVAILABLE = False
         | 
| 18 | 
            +
            try:
         | 
| 19 | 
            +
                # Use centralized path management for adding src to path
         | 
| 20 | 
            +
                from claude_mpm.config.paths import paths
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                paths.ensure_in_path()
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                from claude_mpm.core.config import Config
         | 
| 25 | 
            +
                from claude_mpm.hooks.base_hook import HookContext, HookType
         | 
| 26 | 
            +
                from claude_mpm.hooks.memory_integration_hook import (
         | 
| 27 | 
            +
                    MemoryPostDelegationHook,
         | 
| 28 | 
            +
                    MemoryPreDelegationHook,
         | 
| 29 | 
            +
                )
         | 
| 30 | 
            +
                from claude_mpm.services.hook_service import HookService
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                MEMORY_HOOKS_AVAILABLE = True
         | 
| 33 | 
            +
            except Exception as e:
         | 
| 34 | 
            +
                # Catch all exceptions to prevent any import errors from breaking the handler
         | 
| 35 | 
            +
                if DEBUG:
         | 
| 36 | 
            +
                    print(f"Memory hooks not available: {e}", file=sys.stderr)
         | 
| 37 | 
            +
                MEMORY_HOOKS_AVAILABLE = False
         | 
| 38 | 
            +
             | 
| 39 | 
            +
             | 
| 40 | 
            +
            class MemoryHookManager:
         | 
| 41 | 
            +
                """Manager for memory hook integration."""
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def __init__(self):
         | 
| 44 | 
            +
                    self.memory_hooks_initialized = False
         | 
| 45 | 
            +
                    self.pre_delegation_hook: Optional[MemoryPreDelegationHook] = None
         | 
| 46 | 
            +
                    self.post_delegation_hook: Optional[MemoryPostDelegationHook] = None
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    if MEMORY_HOOKS_AVAILABLE:
         | 
| 49 | 
            +
                        self._initialize_memory_hooks()
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def _initialize_memory_hooks(self):
         | 
| 52 | 
            +
                    """Initialize memory hooks for automatic agent memory management.
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    WHY: This activates the memory system by connecting Claude Code hook events
         | 
| 55 | 
            +
                    to our memory integration hooks. This enables automatic memory injection
         | 
| 56 | 
            +
                    before delegations and learning extraction after delegations.
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                    DESIGN DECISION: We initialize hooks here in the Claude hook handler because
         | 
| 59 | 
            +
                    this is where Claude Code events are processed. This ensures memory hooks
         | 
| 60 | 
            +
                    are triggered at the right times during agent delegation.
         | 
| 61 | 
            +
                    """
         | 
| 62 | 
            +
                    try:
         | 
| 63 | 
            +
                        # Create configuration
         | 
| 64 | 
            +
                        config = Config()
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                        # Only initialize if memory system is enabled
         | 
| 67 | 
            +
                        if not config.get("memory.enabled", True):
         | 
| 68 | 
            +
                            if DEBUG:
         | 
| 69 | 
            +
                                print(
         | 
| 70 | 
            +
                                    "Memory system disabled - skipping hook initialization",
         | 
| 71 | 
            +
                                    file=sys.stderr,
         | 
| 72 | 
            +
                                )
         | 
| 73 | 
            +
                            return
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                        # Initialize pre-delegation hook for memory injection
         | 
| 76 | 
            +
                        self.pre_delegation_hook = MemoryPreDelegationHook(config)
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                        # Initialize post-delegation hook if auto-learning is enabled
         | 
| 79 | 
            +
                        if config.get("memory.auto_learning", True):  # Default to True now
         | 
| 80 | 
            +
                            self.post_delegation_hook = MemoryPostDelegationHook(config)
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                        self.memory_hooks_initialized = True
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                        if DEBUG:
         | 
| 85 | 
            +
                            hooks_info = []
         | 
| 86 | 
            +
                            if self.pre_delegation_hook:
         | 
| 87 | 
            +
                                hooks_info.append("pre-delegation")
         | 
| 88 | 
            +
                            if self.post_delegation_hook:
         | 
| 89 | 
            +
                                hooks_info.append("post-delegation")
         | 
| 90 | 
            +
                            print(
         | 
| 91 | 
            +
                                f"✅ Memory hooks initialized: {', '.join(hooks_info)}",
         | 
| 92 | 
            +
                                file=sys.stderr,
         | 
| 93 | 
            +
                            )
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                    except Exception as e:
         | 
| 96 | 
            +
                        if DEBUG:
         | 
| 97 | 
            +
                            print(f"❌ Failed to initialize memory hooks: {e}", file=sys.stderr)
         | 
| 98 | 
            +
                        # Don't fail the entire handler - memory system is optional
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                def trigger_pre_delegation_hook(
         | 
| 101 | 
            +
                    self, agent_type: str, tool_input: dict, session_id: str
         | 
| 102 | 
            +
                ):
         | 
| 103 | 
            +
                    """Trigger memory pre-delegation hook for agent memory injection.
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                    WHY: This connects Claude Code's Task delegation events to our memory system.
         | 
| 106 | 
            +
                    When Claude is about to delegate to an agent, we inject the agent's memory
         | 
| 107 | 
            +
                    into the delegation context so the agent has access to accumulated knowledge.
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                    DESIGN DECISION: We modify the tool_input in place to inject memory context.
         | 
| 110 | 
            +
                    This ensures the agent receives the memory as part of their initial context.
         | 
| 111 | 
            +
                    """
         | 
| 112 | 
            +
                    if not self.memory_hooks_initialized or not self.pre_delegation_hook:
         | 
| 113 | 
            +
                        return
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                    try:
         | 
| 116 | 
            +
                        # Create hook context for memory injection
         | 
| 117 | 
            +
                        hook_context = HookContext(
         | 
| 118 | 
            +
                            hook_type=HookType.PRE_DELEGATION,
         | 
| 119 | 
            +
                            data={
         | 
| 120 | 
            +
                                "agent": agent_type,
         | 
| 121 | 
            +
                                "context": tool_input,
         | 
| 122 | 
            +
                                "session_id": session_id,
         | 
| 123 | 
            +
                            },
         | 
| 124 | 
            +
                            metadata={"source": "claude_hook_handler", "tool_name": "Task"},
         | 
| 125 | 
            +
                            timestamp=datetime.now().isoformat(),
         | 
| 126 | 
            +
                            session_id=session_id,
         | 
| 127 | 
            +
                        )
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                        # Execute pre-delegation hook
         | 
| 130 | 
            +
                        result = self.pre_delegation_hook.execute(hook_context)
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                        if result.success and result.modified and result.data:
         | 
| 133 | 
            +
                            # Update tool_input with memory-enhanced context
         | 
| 134 | 
            +
                            enhanced_context = result.data.get("context", {})
         | 
| 135 | 
            +
                            if enhanced_context and "agent_memory" in enhanced_context:
         | 
| 136 | 
            +
                                # Inject memory into the task prompt/description
         | 
| 137 | 
            +
                                original_prompt = tool_input.get("prompt", "")
         | 
| 138 | 
            +
                                memory_section = enhanced_context["agent_memory"]
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                                # Prepend memory to the original prompt
         | 
| 141 | 
            +
                                enhanced_prompt = f"{memory_section}\n\n{original_prompt}"
         | 
| 142 | 
            +
                                tool_input["prompt"] = enhanced_prompt
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                                if DEBUG:
         | 
| 145 | 
            +
                                    memory_size = len(memory_section.encode("utf-8"))
         | 
| 146 | 
            +
                                    print(
         | 
| 147 | 
            +
                                        f"✅ Injected {memory_size} bytes of memory for agent '{agent_type}'",
         | 
| 148 | 
            +
                                        file=sys.stderr,
         | 
| 149 | 
            +
                                    )
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                    except Exception as e:
         | 
| 152 | 
            +
                        if DEBUG:
         | 
| 153 | 
            +
                            print(f"❌ Memory pre-delegation hook failed: {e}", file=sys.stderr)
         | 
| 154 | 
            +
                        # Don't fail the delegation - memory is optional
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                def trigger_post_delegation_hook(
         | 
| 157 | 
            +
                    self, agent_type: str, event: dict, session_id: str
         | 
| 158 | 
            +
                ):
         | 
| 159 | 
            +
                    """Trigger memory post-delegation hook for learning extraction.
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                    WHY: This connects Claude Code's Task completion events to our memory system.
         | 
| 162 | 
            +
                    When an agent completes a task, we extract learnings from the result and
         | 
| 163 | 
            +
                    store them in the agent's memory for future use.
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                    DESIGN DECISION: We extract learnings from both the tool output and any
         | 
| 166 | 
            +
                    error messages, providing comprehensive context for the memory system.
         | 
| 167 | 
            +
                    """
         | 
| 168 | 
            +
                    if not self.memory_hooks_initialized or not self.post_delegation_hook:
         | 
| 169 | 
            +
                        return
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                    try:
         | 
| 172 | 
            +
                        # Extract result content from the event
         | 
| 173 | 
            +
                        result_content = ""
         | 
| 174 | 
            +
                        output = event.get("output", "")
         | 
| 175 | 
            +
                        error = event.get("error", "")
         | 
| 176 | 
            +
                        exit_code = event.get("exit_code", 0)
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                        # Build result content
         | 
| 179 | 
            +
                        if output:
         | 
| 180 | 
            +
                            result_content = str(output)
         | 
| 181 | 
            +
                        elif error:
         | 
| 182 | 
            +
                            result_content = f"Error: {str(error)}"
         | 
| 183 | 
            +
                        else:
         | 
| 184 | 
            +
                            result_content = f"Task completed with exit code: {exit_code}"
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                        # Create hook context for learning extraction
         | 
| 187 | 
            +
                        hook_context = HookContext(
         | 
| 188 | 
            +
                            hook_type=HookType.POST_DELEGATION,
         | 
| 189 | 
            +
                            data={
         | 
| 190 | 
            +
                                "agent": agent_type,
         | 
| 191 | 
            +
                                "result": {
         | 
| 192 | 
            +
                                    "content": result_content,
         | 
| 193 | 
            +
                                    "success": exit_code == 0,
         | 
| 194 | 
            +
                                    "exit_code": exit_code,
         | 
| 195 | 
            +
                                },
         | 
| 196 | 
            +
                                "session_id": session_id,
         | 
| 197 | 
            +
                            },
         | 
| 198 | 
            +
                            metadata={
         | 
| 199 | 
            +
                                "source": "claude_hook_handler",
         | 
| 200 | 
            +
                                "tool_name": "Task",
         | 
| 201 | 
            +
                                "duration_ms": event.get("duration_ms", 0),
         | 
| 202 | 
            +
                            },
         | 
| 203 | 
            +
                            timestamp=datetime.now().isoformat(),
         | 
| 204 | 
            +
                            session_id=session_id,
         | 
| 205 | 
            +
                        )
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                        # Execute post-delegation hook
         | 
| 208 | 
            +
                        result = self.post_delegation_hook.execute(hook_context)
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                        if result.success and result.metadata:
         | 
| 211 | 
            +
                            learnings_extracted = result.metadata.get("learnings_extracted", 0)
         | 
| 212 | 
            +
                            if learnings_extracted > 0 and DEBUG:
         | 
| 213 | 
            +
                                print(
         | 
| 214 | 
            +
                                    f"✅ Extracted {learnings_extracted} learnings for agent '{agent_type}'",
         | 
| 215 | 
            +
                                    file=sys.stderr,
         | 
| 216 | 
            +
                                )
         | 
| 217 | 
            +
             | 
| 218 | 
            +
                    except Exception as e:
         | 
| 219 | 
            +
                        if DEBUG:
         | 
| 220 | 
            +
                            print(f"❌ Memory post-delegation hook failed: {e}", file=sys.stderr)
         | 
| 221 | 
            +
                        # Don't fail the delegation result - memory is optional
         | 
| @@ -0,0 +1,348 @@ | |
| 1 | 
            +
            #!/usr/bin/env python3
         | 
| 2 | 
            +
            """Response tracking utilities for Claude Code hook handler.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            This module provides utilities for tracking and correlating agent responses
         | 
| 5 | 
            +
            with their original requests.
         | 
| 6 | 
            +
            """
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            import json
         | 
| 9 | 
            +
            import os
         | 
| 10 | 
            +
            import re
         | 
| 11 | 
            +
            import sys
         | 
| 12 | 
            +
            from datetime import datetime
         | 
| 13 | 
            +
            from typing import Any, Dict, Optional
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            # Debug mode
         | 
| 16 | 
            +
            DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "true").lower() != "false"
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            # Response tracking integration
         | 
| 19 | 
            +
            RESPONSE_TRACKING_AVAILABLE = False
         | 
| 20 | 
            +
            try:
         | 
| 21 | 
            +
                from claude_mpm.services.response_tracker import ResponseTracker
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                RESPONSE_TRACKING_AVAILABLE = True
         | 
| 24 | 
            +
            except Exception as e:
         | 
| 25 | 
            +
                if DEBUG:
         | 
| 26 | 
            +
                    print(f"Response tracking not available: {e}", file=sys.stderr)
         | 
| 27 | 
            +
                RESPONSE_TRACKING_AVAILABLE = False
         | 
| 28 | 
            +
             | 
| 29 | 
            +
             | 
| 30 | 
            +
            class ResponseTrackingManager:
         | 
| 31 | 
            +
                """Manager for response tracking functionality."""
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def __init__(self):
         | 
| 34 | 
            +
                    self.response_tracker: Optional[ResponseTracker] = None
         | 
| 35 | 
            +
                    self.response_tracking_enabled = False
         | 
| 36 | 
            +
                    self.track_all_interactions = (
         | 
| 37 | 
            +
                        False  # Track all Claude interactions, not just delegations
         | 
| 38 | 
            +
                    )
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    if RESPONSE_TRACKING_AVAILABLE:
         | 
| 41 | 
            +
                        self._initialize_response_tracking()
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def _initialize_response_tracking(self):
         | 
| 44 | 
            +
                    """Initialize response tracking if enabled in configuration.
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    WHY: This enables automatic capture and storage of agent responses
         | 
| 47 | 
            +
                    for analysis, debugging, and learning purposes. Integration into the
         | 
| 48 | 
            +
                    existing hook handler avoids duplicate event capture.
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    DESIGN DECISION: Check configuration to allow enabling/disabling
         | 
| 51 | 
            +
                    response tracking without code changes.
         | 
| 52 | 
            +
                    """
         | 
| 53 | 
            +
                    try:
         | 
| 54 | 
            +
                        # Create configuration with optional config file
         | 
| 55 | 
            +
                        config_file = os.environ.get("CLAUDE_PM_CONFIG_FILE")
         | 
| 56 | 
            +
                        from claude_mpm.core.config import Config
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                        config = Config(config_file=config_file) if config_file else Config()
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                        # Check if response tracking is enabled (check both sections for compatibility)
         | 
| 61 | 
            +
                        response_tracking_enabled = config.get("response_tracking.enabled", False)
         | 
| 62 | 
            +
                        response_logging_enabled = config.get("response_logging.enabled", False)
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                        if not (response_tracking_enabled or response_logging_enabled):
         | 
| 65 | 
            +
                            if DEBUG:
         | 
| 66 | 
            +
                                print(
         | 
| 67 | 
            +
                                    "Response tracking disabled - skipping initialization",
         | 
| 68 | 
            +
                                    file=sys.stderr,
         | 
| 69 | 
            +
                                )
         | 
| 70 | 
            +
                            return
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                        # Initialize response tracker with config
         | 
| 73 | 
            +
                        self.response_tracker = ResponseTracker(config=config)
         | 
| 74 | 
            +
                        self.response_tracking_enabled = self.response_tracker.is_enabled()
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                        # Check if we should track all interactions (not just delegations)
         | 
| 77 | 
            +
                        self.track_all_interactions = config.get(
         | 
| 78 | 
            +
                            "response_tracking.track_all_interactions", False
         | 
| 79 | 
            +
                        ) or config.get("response_logging.track_all_interactions", False)
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                        if DEBUG:
         | 
| 82 | 
            +
                            mode = (
         | 
| 83 | 
            +
                                "all interactions"
         | 
| 84 | 
            +
                                if self.track_all_interactions
         | 
| 85 | 
            +
                                else "Task delegations only"
         | 
| 86 | 
            +
                            )
         | 
| 87 | 
            +
                            print(
         | 
| 88 | 
            +
                                f"✅ Response tracking initialized (mode: {mode})", file=sys.stderr
         | 
| 89 | 
            +
                            )
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                    except Exception as e:
         | 
| 92 | 
            +
                        if DEBUG:
         | 
| 93 | 
            +
                            print(f"❌ Failed to initialize response tracking: {e}", file=sys.stderr)
         | 
| 94 | 
            +
                        # Don't fail the entire handler - response tracking is optional
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                def track_agent_response(
         | 
| 97 | 
            +
                    self, session_id: str, agent_type: str, event: dict, delegation_requests: dict
         | 
| 98 | 
            +
                ):
         | 
| 99 | 
            +
                    """Track agent response by correlating with original request and saving response.
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                    WHY: This integrates response tracking into the existing hook flow,
         | 
| 102 | 
            +
                    capturing agent responses when Task delegations complete. It correlates
         | 
| 103 | 
            +
                    the response with the original request stored during pre-tool processing.
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                    DESIGN DECISION: Only track responses if response tracking is enabled
         | 
| 106 | 
            +
                    and we have the original request data. Graceful error handling ensures
         | 
| 107 | 
            +
                    response tracking failures don't break hook processing.
         | 
| 108 | 
            +
                    """
         | 
| 109 | 
            +
                    if not self.response_tracking_enabled or not self.response_tracker:
         | 
| 110 | 
            +
                        return
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                    try:
         | 
| 113 | 
            +
                        # Get the original request data stored during pre-tool
         | 
| 114 | 
            +
                        request_info = delegation_requests.get(session_id)
         | 
| 115 | 
            +
                        if not request_info:
         | 
| 116 | 
            +
                            if DEBUG:
         | 
| 117 | 
            +
                                print(
         | 
| 118 | 
            +
                                    f"No request data found for session {session_id}, skipping response tracking",
         | 
| 119 | 
            +
                                    file=sys.stderr,
         | 
| 120 | 
            +
                                )
         | 
| 121 | 
            +
                            return
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                        # Extract response from event output
         | 
| 124 | 
            +
                        response = event.get("output", "")
         | 
| 125 | 
            +
                        if not response:
         | 
| 126 | 
            +
                            # If no output, use error or construct a basic response
         | 
| 127 | 
            +
                            error = event.get("error", "")
         | 
| 128 | 
            +
                            exit_code = event.get("exit_code", 0)
         | 
| 129 | 
            +
                            if error:
         | 
| 130 | 
            +
                                response = f"Error: {error}"
         | 
| 131 | 
            +
                            else:
         | 
| 132 | 
            +
                                response = f"Task completed with exit code: {exit_code}"
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                        # Convert response to string if it's not already
         | 
| 135 | 
            +
                        response_text = str(response)
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                        # Try to extract structured JSON response from agent output
         | 
| 138 | 
            +
                        structured_response = None
         | 
| 139 | 
            +
                        try:
         | 
| 140 | 
            +
                            # Look for JSON block in the response (agents should return JSON at the end)
         | 
| 141 | 
            +
                            json_match = re.search(
         | 
| 142 | 
            +
                                r"```json\s*(\{.*?\})\s*```", response_text, re.DOTALL
         | 
| 143 | 
            +
                            )
         | 
| 144 | 
            +
                            if json_match:
         | 
| 145 | 
            +
                                structured_response = json.loads(json_match.group(1))
         | 
| 146 | 
            +
                                if DEBUG:
         | 
| 147 | 
            +
                                    print(
         | 
| 148 | 
            +
                                        f"Extracted structured response from {agent_type} agent",
         | 
| 149 | 
            +
                                        file=sys.stderr,
         | 
| 150 | 
            +
                                    )
         | 
| 151 | 
            +
                        except (json.JSONDecodeError, AttributeError) as e:
         | 
| 152 | 
            +
                            if DEBUG:
         | 
| 153 | 
            +
                                print(
         | 
| 154 | 
            +
                                    f"No structured JSON response found in {agent_type} agent output: {e}",
         | 
| 155 | 
            +
                                    file=sys.stderr,
         | 
| 156 | 
            +
                                )
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                        # Get the original request (prompt + description)
         | 
| 159 | 
            +
                        original_request = request_info.get("request", {})
         | 
| 160 | 
            +
                        prompt = original_request.get("prompt", "")
         | 
| 161 | 
            +
                        description = original_request.get("description", "")
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                        # Combine prompt and description for the full request
         | 
| 164 | 
            +
                        full_request = prompt
         | 
| 165 | 
            +
                        if description and description != prompt:
         | 
| 166 | 
            +
                            if full_request:
         | 
| 167 | 
            +
                                full_request += f"\n\nDescription: {description}"
         | 
| 168 | 
            +
                            else:
         | 
| 169 | 
            +
                                full_request = description
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                        if not full_request:
         | 
| 172 | 
            +
                            full_request = f"Task delegation to {agent_type} agent"
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                        # Prepare metadata with structured response data if available
         | 
| 175 | 
            +
                        metadata = {
         | 
| 176 | 
            +
                            "exit_code": event.get("exit_code", 0),
         | 
| 177 | 
            +
                            "success": event.get("exit_code", 0) == 0,
         | 
| 178 | 
            +
                            "has_error": bool(event.get("error")),
         | 
| 179 | 
            +
                            "duration_ms": event.get("duration_ms"),
         | 
| 180 | 
            +
                            "working_directory": event.get("cwd", ""),
         | 
| 181 | 
            +
                            "timestamp": datetime.now().isoformat(),
         | 
| 182 | 
            +
                            "tool_name": "Task",
         | 
| 183 | 
            +
                            "original_request_timestamp": request_info.get("timestamp"),
         | 
| 184 | 
            +
                        }
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                        # Add structured response data to metadata if available
         | 
| 187 | 
            +
                        if structured_response:
         | 
| 188 | 
            +
                            metadata["structured_response"] = {
         | 
| 189 | 
            +
                                "task_completed": structured_response.get("task_completed", False),
         | 
| 190 | 
            +
                                "instructions": structured_response.get("instructions", ""),
         | 
| 191 | 
            +
                                "results": structured_response.get("results", ""),
         | 
| 192 | 
            +
                                "files_modified": structured_response.get("files_modified", []),
         | 
| 193 | 
            +
                                "tools_used": structured_response.get("tools_used", []),
         | 
| 194 | 
            +
                                "remember": structured_response.get("remember"),
         | 
| 195 | 
            +
                            }
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                            # Check if task was completed for logging purposes
         | 
| 198 | 
            +
                            if structured_response.get("task_completed"):
         | 
| 199 | 
            +
                                metadata["task_completed"] = True
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                            # Log files modified for debugging
         | 
| 202 | 
            +
                            if DEBUG and structured_response.get("files_modified"):
         | 
| 203 | 
            +
                                files = [f["file"] for f in structured_response["files_modified"]]
         | 
| 204 | 
            +
                                print(
         | 
| 205 | 
            +
                                    f"Agent {agent_type} modified files: {files}", file=sys.stderr
         | 
| 206 | 
            +
                                )
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                        # Track the response
         | 
| 209 | 
            +
                        file_path = self.response_tracker.track_response(
         | 
| 210 | 
            +
                            agent_name=agent_type,
         | 
| 211 | 
            +
                            request=full_request,
         | 
| 212 | 
            +
                            response=response_text,
         | 
| 213 | 
            +
                            session_id=session_id,
         | 
| 214 | 
            +
                            metadata=metadata,
         | 
| 215 | 
            +
                        )
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                        if file_path and DEBUG:
         | 
| 218 | 
            +
                            print(
         | 
| 219 | 
            +
                                f"✅ Tracked response for {agent_type} agent in session {session_id}: {file_path.name}",
         | 
| 220 | 
            +
                                file=sys.stderr,
         | 
| 221 | 
            +
                            )
         | 
| 222 | 
            +
                        elif DEBUG and not file_path:
         | 
| 223 | 
            +
                            print(
         | 
| 224 | 
            +
                                f"Response tracking returned None for {agent_type} agent (might be excluded or disabled)",
         | 
| 225 | 
            +
                                file=sys.stderr,
         | 
| 226 | 
            +
                            )
         | 
| 227 | 
            +
             | 
| 228 | 
            +
                        # Clean up the request data after successful tracking
         | 
| 229 | 
            +
                        if session_id in delegation_requests:
         | 
| 230 | 
            +
                            del delegation_requests[session_id]
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                    except Exception as e:
         | 
| 233 | 
            +
                        if DEBUG:
         | 
| 234 | 
            +
                            print(f"❌ Failed to track agent response: {e}", file=sys.stderr)
         | 
| 235 | 
            +
                        # Don't fail the hook processing - response tracking is optional
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                def track_stop_response(
         | 
| 238 | 
            +
                    self, event: dict, session_id: str, metadata: dict, pending_prompts: dict
         | 
| 239 | 
            +
                ):
         | 
| 240 | 
            +
                    """Track response for stop events."""
         | 
| 241 | 
            +
                    if not (self.response_tracking_enabled and self.response_tracker):
         | 
| 242 | 
            +
                        return
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                    try:
         | 
| 245 | 
            +
                        # Extract output from event
         | 
| 246 | 
            +
                        output = (
         | 
| 247 | 
            +
                            event.get("output", "")
         | 
| 248 | 
            +
                            or event.get("final_output", "")
         | 
| 249 | 
            +
                            or event.get("response", "")
         | 
| 250 | 
            +
                        )
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                        # Check if we have a pending prompt for this session
         | 
| 253 | 
            +
                        prompt_data = pending_prompts.get(session_id)
         | 
| 254 | 
            +
             | 
| 255 | 
            +
                        if DEBUG:
         | 
| 256 | 
            +
                            print(
         | 
| 257 | 
            +
                                f"  - output present: {bool(output)} (length: {len(str(output)) if output else 0})",
         | 
| 258 | 
            +
                                file=sys.stderr,
         | 
| 259 | 
            +
                            )
         | 
| 260 | 
            +
                            print(f"  - prompt_data present: {bool(prompt_data)}", file=sys.stderr)
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                        if output and prompt_data:
         | 
| 263 | 
            +
                            # Add prompt timestamp to metadata
         | 
| 264 | 
            +
                            metadata["prompt_timestamp"] = prompt_data.get("timestamp")
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                            # Track the main Claude response
         | 
| 267 | 
            +
                            file_path = self.response_tracker.track_response(
         | 
| 268 | 
            +
                                agent_name="claude_main",
         | 
| 269 | 
            +
                                request=prompt_data["prompt"],
         | 
| 270 | 
            +
                                response=str(output),
         | 
| 271 | 
            +
                                session_id=session_id,
         | 
| 272 | 
            +
                                metadata=metadata,
         | 
| 273 | 
            +
                            )
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                            if file_path and DEBUG:
         | 
| 276 | 
            +
                                print(f"  - Response tracked to: {file_path}", file=sys.stderr)
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                            # Clean up pending prompt
         | 
| 279 | 
            +
                            del pending_prompts[session_id]
         | 
| 280 | 
            +
             | 
| 281 | 
            +
                    except Exception as e:
         | 
| 282 | 
            +
                        if DEBUG:
         | 
| 283 | 
            +
                            print(f"Error tracking stop response: {e}", file=sys.stderr)
         | 
| 284 | 
            +
             | 
| 285 | 
            +
                def track_assistant_response(self, event: dict, pending_prompts: dict):
         | 
| 286 | 
            +
                    """Handle assistant response events for comprehensive response tracking."""
         | 
| 287 | 
            +
                    if not self.response_tracking_enabled or not self.track_all_interactions:
         | 
| 288 | 
            +
                        return
         | 
| 289 | 
            +
             | 
| 290 | 
            +
                    session_id = event.get("session_id", "")
         | 
| 291 | 
            +
                    if not session_id:
         | 
| 292 | 
            +
                        return
         | 
| 293 | 
            +
             | 
| 294 | 
            +
                    # Get the stored prompt for this session
         | 
| 295 | 
            +
                    prompt_data = pending_prompts.get(session_id)
         | 
| 296 | 
            +
                    if not prompt_data:
         | 
| 297 | 
            +
                        if DEBUG:
         | 
| 298 | 
            +
                            print(
         | 
| 299 | 
            +
                                f"No stored prompt for session {session_id[:8]}..., skipping response tracking",
         | 
| 300 | 
            +
                                file=sys.stderr,
         | 
| 301 | 
            +
                            )
         | 
| 302 | 
            +
                        return
         | 
| 303 | 
            +
             | 
| 304 | 
            +
                    try:
         | 
| 305 | 
            +
                        # Extract response content from event
         | 
| 306 | 
            +
                        response_content = (
         | 
| 307 | 
            +
                            event.get("response", "")
         | 
| 308 | 
            +
                            or event.get("content", "")
         | 
| 309 | 
            +
                            or event.get("text", "")
         | 
| 310 | 
            +
                        )
         | 
| 311 | 
            +
             | 
| 312 | 
            +
                        if not response_content:
         | 
| 313 | 
            +
                            if DEBUG:
         | 
| 314 | 
            +
                                print(
         | 
| 315 | 
            +
                                    f"No response content in event for session {session_id[:8]}...",
         | 
| 316 | 
            +
                                    file=sys.stderr,
         | 
| 317 | 
            +
                                )
         | 
| 318 | 
            +
                            return
         | 
| 319 | 
            +
             | 
| 320 | 
            +
                        # Track the response
         | 
| 321 | 
            +
                        metadata = {
         | 
| 322 | 
            +
                            "timestamp": datetime.now().isoformat(),
         | 
| 323 | 
            +
                            "prompt_timestamp": prompt_data.get("timestamp"),
         | 
| 324 | 
            +
                            "working_directory": prompt_data.get("working_directory", ""),
         | 
| 325 | 
            +
                            "event_type": "assistant_response",
         | 
| 326 | 
            +
                            "session_type": "interactive",
         | 
| 327 | 
            +
                        }
         | 
| 328 | 
            +
             | 
| 329 | 
            +
                        file_path = self.response_tracker.track_response(
         | 
| 330 | 
            +
                            agent_name="claude",
         | 
| 331 | 
            +
                            request=prompt_data["prompt"],
         | 
| 332 | 
            +
                            response=response_content,
         | 
| 333 | 
            +
                            session_id=session_id,
         | 
| 334 | 
            +
                            metadata=metadata,
         | 
| 335 | 
            +
                        )
         | 
| 336 | 
            +
             | 
| 337 | 
            +
                        if file_path and DEBUG:
         | 
| 338 | 
            +
                            print(
         | 
| 339 | 
            +
                                f"✅ Tracked Claude response for session {session_id[:8]}...: {file_path.name}",
         | 
| 340 | 
            +
                                file=sys.stderr,
         | 
| 341 | 
            +
                            )
         | 
| 342 | 
            +
             | 
| 343 | 
            +
                        # Clean up the stored prompt
         | 
| 344 | 
            +
                        del pending_prompts[session_id]
         | 
| 345 | 
            +
             | 
| 346 | 
            +
                    except Exception as e:
         | 
| 347 | 
            +
                        if DEBUG:
         | 
| 348 | 
            +
                            print(f"❌ Failed to track assistant response: {e}", file=sys.stderr)
         |