claude-mpm 3.9.11__py3-none-any.whl → 4.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +1 -1
- 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 +2 -2
- 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 +79 -51
- claude_mpm/cli/__main__.py +3 -2
- claude_mpm/cli/commands/__init__.py +20 -20
- 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 +140 -905
- 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 +330 -86
- 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 +363 -220
- claude_mpm/cli/parser.py +24 -1156
- 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 +124 -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 +71 -73
- claude_mpm/config/paths.py +94 -208
- claude_mpm/config/socketio_config.py +84 -73
- claude_mpm/constants.py +35 -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/built/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/built/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/built/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/built/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/built/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/built/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/built/dashboard.js +2 -0
- claude_mpm/dashboard/static/built/socket-client.js +2 -0
- 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 +93 -72
- claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +110 -96
- 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 +133 -53
- 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 +233 -199
- 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 +30 -13
- 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 +13 -20
- 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 +87 -84
- claude_mpm/services/mcp_gateway/main.py +287 -137
- claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
- claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
- 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 +109 -119
- 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 +575 -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 +166 -64
- 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 +185 -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 +19 -533
- 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 +2 -2
- claude_mpm/storage/state_storage.py +177 -181
- 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.11.dist-info → claude_mpm-4.0.4.dist-info}/METADATA +90 -22
- claude_mpm-4.0.4.dist-info/RECORD +417 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/entry_points.txt +1 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/licenses/LICENSE +1 -1
- claude_mpm/cli/commands/run_guarded.py +0 -511
- claude_mpm/config/memory_guardian_config.py +0 -325
- claude_mpm/config/memory_guardian_yaml.py +0 -335
- claude_mpm/core/config_paths.py +0 -150
- claude_mpm/core/memory_aware_runner.py +0 -353
- 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/graceful_degradation.py +0 -616
- claude_mpm/services/infrastructure/health_monitor.py +0 -775
- claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
- claude_mpm/services/infrastructure/memory_guardian.py +0 -944
- claude_mpm/services/infrastructure/restart_protection.py +0 -642
- claude_mpm/services/infrastructure/state_manager.py +0 -774
- claude_mpm/services/mcp_gateway/manager.py +0 -334
- 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.11.dist-info/RECORD +0 -306
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/top_level.txt +0 -0
| @@ -19,43 +19,44 @@ This is a consolidated version combining all functionality from the previous | |
| 19 19 | 
             
            multi-file implementation for better maintainability.
         | 
| 20 20 | 
             
            """
         | 
| 21 21 |  | 
| 22 | 
            -
            import os
         | 
| 23 | 
            -
            import json
         | 
| 24 | 
            -
            import logging
         | 
| 25 22 | 
             
            import asyncio
         | 
| 26 23 | 
             
            import hashlib
         | 
| 24 | 
            +
            import json
         | 
| 25 | 
            +
            import logging
         | 
| 26 | 
            +
            import os
         | 
| 27 27 | 
             
            from dataclasses import dataclass, field
         | 
| 28 28 | 
             
            from datetime import datetime
         | 
| 29 29 | 
             
            from enum import Enum
         | 
| 30 30 | 
             
            from pathlib import Path
         | 
| 31 | 
            -
            from typing import Dict, List, Optional,  | 
| 31 | 
            +
            from typing import Any, Dict, List, Optional, Set, Tuple, Union
         | 
| 32 32 |  | 
| 33 33 | 
             
            import yaml
         | 
| 34 34 |  | 
| 35 35 | 
             
            from claude_mpm.core.base_service import BaseService
         | 
| 36 36 | 
             
            from claude_mpm.core.config import Config
         | 
| 37 | 
            -
            from claude_mpm.core. | 
| 38 | 
            -
            from claude_mpm.services.memory.cache.shared_prompt_cache import SharedPromptCache
         | 
| 37 | 
            +
            from claude_mpm.core.unified_paths import get_path_manager
         | 
| 39 38 | 
             
            from claude_mpm.services.agents.registry import AgentRegistry
         | 
| 39 | 
            +
            from claude_mpm.services.memory.cache.shared_prompt_cache import SharedPromptCache
         | 
| 40 40 | 
             
            from claude_mpm.utils.path_operations import path_ops
         | 
| 41 41 |  | 
| 42 | 
            -
             | 
| 43 42 | 
             
            logger = logging.getLogger(__name__)
         | 
| 44 43 |  | 
| 45 | 
            -
             | 
| 46 44 | 
             
            # ============================================================================
         | 
| 47 45 | 
             
            # Data Models
         | 
| 48 46 | 
             
            # ============================================================================
         | 
| 49 47 |  | 
| 48 | 
            +
             | 
| 50 49 | 
             
            class ProfileTier(Enum):
         | 
| 51 50 | 
             
                """Agent profile hierarchy tiers with precedence order."""
         | 
| 51 | 
            +
             | 
| 52 52 | 
             
                PROJECT = "project"  # Highest precedence - project-specific agents
         | 
| 53 | 
            -
                USER = "user" | 
| 54 | 
            -
                SYSTEM = "system" | 
| 53 | 
            +
                USER = "user"  # Medium precedence - user-level agents
         | 
| 54 | 
            +
                SYSTEM = "system"  # Lowest precedence - framework/built-in agents
         | 
| 55 55 |  | 
| 56 56 |  | 
| 57 57 | 
             
            class ProfileStatus(Enum):
         | 
| 58 58 | 
             
                """Profile loading status."""
         | 
| 59 | 
            +
             | 
| 59 60 | 
             
                LOADED = "loaded"
         | 
| 60 61 | 
             
                ERROR = "error"
         | 
| 61 62 | 
             
                NOT_FOUND = "not_found"
         | 
| @@ -65,6 +66,7 @@ class ProfileStatus(Enum): | |
| 65 66 | 
             
            @dataclass
         | 
| 66 67 | 
             
            class ImprovedPrompt:
         | 
| 67 68 | 
             
                """Improved prompt data structure."""
         | 
| 69 | 
            +
             | 
| 68 70 | 
             
                prompt_id: str
         | 
| 69 71 | 
             
                agent_name: str
         | 
| 70 72 | 
             
                version: str
         | 
| @@ -78,6 +80,7 @@ class ImprovedPrompt: | |
| 78 80 | 
             
            @dataclass
         | 
| 79 81 | 
             
            class AgentProfile:
         | 
| 80 82 | 
             
                """Complete agent profile with hierarchy information."""
         | 
| 83 | 
            +
             | 
| 81 84 | 
             
                name: str
         | 
| 82 85 | 
             
                role: str
         | 
| 83 86 | 
             
                description: str
         | 
| @@ -98,57 +101,60 @@ class AgentProfile: | |
| 98 101 | 
             
            # Main Service Class
         | 
| 99 102 | 
             
            # ============================================================================
         | 
| 100 103 |  | 
| 104 | 
            +
             | 
| 101 105 | 
             
            class AgentProfileLoader(BaseService):
         | 
| 102 106 | 
             
                """
         | 
| 103 107 | 
             
                Comprehensive agent profile loading service with enhanced prompt integration.
         | 
| 104 | 
            -
             | 
| 108 | 
            +
             | 
| 105 109 | 
             
                This consolidated version combines all functionality from the previous
         | 
| 106 110 | 
             
                multi-file implementation into a single, maintainable module.
         | 
| 107 111 | 
             
                """
         | 
| 108 | 
            -
             | 
| 112 | 
            +
             | 
| 109 113 | 
             
                def __init__(self, config: Optional[Config] = None):
         | 
| 110 114 | 
             
                    """Initialize the agent profile loader."""
         | 
| 111 115 | 
             
                    super().__init__(name="agent_profile_loader", config=config)
         | 
| 112 | 
            -
             | 
| 116 | 
            +
             | 
| 113 117 | 
             
                    # Core configuration
         | 
| 114 118 | 
             
                    self.working_directory = Path(os.getcwd())
         | 
| 115 119 | 
             
                    self.framework_path = self._detect_framework_path()
         | 
| 116 120 | 
             
                    self.user_home = Path.home()
         | 
| 117 | 
            -
             | 
| 121 | 
            +
             | 
| 118 122 | 
             
                    # Tier paths configuration
         | 
| 119 123 | 
             
                    self.tier_paths = {
         | 
| 120 | 
            -
                        ProfileTier.PROJECT: self.working_directory /  | 
| 121 | 
            -
                        ProfileTier.USER:  | 
| 122 | 
            -
                        ProfileTier.SYSTEM: Path(__file__).parent.parent /  | 
| 124 | 
            +
                        ProfileTier.PROJECT: self.working_directory / "agents",
         | 
| 125 | 
            +
                        ProfileTier.USER: get_path_manager().get_user_agents_dir(),
         | 
| 126 | 
            +
                        ProfileTier.SYSTEM: Path(__file__).parent.parent / "agents" / "templates",
         | 
| 123 127 | 
             
                    }
         | 
| 124 | 
            -
             | 
| 128 | 
            +
             | 
| 125 129 | 
             
                    # Remove None values
         | 
| 126 130 | 
             
                    self.tier_paths = {k: v for k, v in self.tier_paths.items() if v is not None}
         | 
| 127 | 
            -
             | 
| 131 | 
            +
             | 
| 128 132 | 
             
                    # Profile cache
         | 
| 129 133 | 
             
                    self.profile_cache: Dict[str, AgentProfile] = {}
         | 
| 130 134 | 
             
                    self.cache_ttl = 3600  # 1 hour
         | 
| 131 | 
            -
             | 
| 135 | 
            +
             | 
| 132 136 | 
             
                    # Service integrations
         | 
| 133 137 | 
             
                    self.shared_cache: Optional[SharedPromptCache] = None
         | 
| 134 138 | 
             
                    self.agent_registry: Optional[AgentRegistry] = None
         | 
| 135 | 
            -
             | 
| 139 | 
            +
             | 
| 136 140 | 
             
                    # Improved prompts storage
         | 
| 137 | 
            -
                    self.improved_prompts_path =  | 
| 141 | 
            +
                    self.improved_prompts_path = (
         | 
| 142 | 
            +
                        get_path_manager().get_user_config_dir() / "improved_prompts"
         | 
| 143 | 
            +
                    )
         | 
| 138 144 | 
             
                    self.improved_prompts_path.mkdir(parents=True, exist_ok=True)
         | 
| 139 | 
            -
             | 
| 145 | 
            +
             | 
| 140 146 | 
             
                    # Performance tracking
         | 
| 141 147 | 
             
                    self.load_metrics: Dict[str, float] = {}
         | 
| 142 | 
            -
             | 
| 148 | 
            +
             | 
| 143 149 | 
             
                    logger.info(f"AgentProfileLoader initialized successfully")
         | 
| 144 150 | 
             
                    logger.info(f"  Working directory: {self.working_directory}")
         | 
| 145 151 | 
             
                    logger.info(f"  Framework path: {self.framework_path}")
         | 
| 146 152 | 
             
                    logger.info(f"  Tier paths: {list(self.tier_paths.keys())}")
         | 
| 147 | 
            -
             | 
| 153 | 
            +
             | 
| 148 154 | 
             
                async def _initialize(self) -> None:
         | 
| 149 155 | 
             
                    """Initialize the service and its integrations."""
         | 
| 150 156 | 
             
                    logger.info("Initializing AgentProfileLoader service...")
         | 
| 151 | 
            -
             | 
| 157 | 
            +
             | 
| 152 158 | 
             
                    # Initialize service integrations
         | 
| 153 159 | 
             
                    try:
         | 
| 154 160 | 
             
                        self.shared_cache = SharedPromptCache.get_instance()
         | 
| @@ -156,114 +162,122 @@ class AgentProfileLoader(BaseService): | |
| 156 162 | 
             
                        logger.info("Successfully initialized service integrations")
         | 
| 157 163 | 
             
                    except Exception as e:
         | 
| 158 164 | 
             
                        logger.warning(f"Failed to initialize some integrations: {e}")
         | 
| 159 | 
            -
             | 
| 165 | 
            +
             | 
| 160 166 | 
             
                    # Discover and cache initial profiles
         | 
| 161 167 | 
             
                    await self._discover_all_profiles()
         | 
| 162 | 
            -
             | 
| 168 | 
            +
             | 
| 163 169 | 
             
                    logger.info("AgentProfileLoader service initialized successfully")
         | 
| 164 | 
            -
             | 
| 170 | 
            +
             | 
| 165 171 | 
             
                async def _cleanup(self) -> None:
         | 
| 166 172 | 
             
                    """Cleanup service resources."""
         | 
| 167 173 | 
             
                    logger.info("Cleaning up AgentProfileLoader service...")
         | 
| 168 | 
            -
             | 
| 174 | 
            +
             | 
| 169 175 | 
             
                    # Clear caches
         | 
| 170 176 | 
             
                    self.profile_cache.clear()
         | 
| 171 | 
            -
             | 
| 177 | 
            +
             | 
| 172 178 | 
             
                    # Save any pending improved prompts
         | 
| 173 179 | 
             
                    await self._save_improved_prompts()
         | 
| 174 | 
            -
             | 
| 180 | 
            +
             | 
| 175 181 | 
             
                    logger.info("AgentProfileLoader service cleaned up")
         | 
| 176 | 
            -
             | 
| 182 | 
            +
             | 
| 177 183 | 
             
                async def _health_check(self) -> Dict[str, bool]:
         | 
| 178 184 | 
             
                    """Perform service health checks."""
         | 
| 179 185 | 
             
                    checks = {}
         | 
| 180 | 
            -
             | 
| 186 | 
            +
             | 
| 181 187 | 
             
                    try:
         | 
| 182 188 | 
             
                        # Check tier paths
         | 
| 183 189 | 
             
                        checks["tier_paths_accessible"] = all(
         | 
| 184 190 | 
             
                            path.exists() for path in self.tier_paths.values()
         | 
| 185 191 | 
             
                        )
         | 
| 186 | 
            -
             | 
| 192 | 
            +
             | 
| 187 193 | 
             
                        # Check service integrations
         | 
| 188 194 | 
             
                        checks["shared_cache_integration"] = self.shared_cache is not None
         | 
| 189 195 | 
             
                        checks["agent_registry_integration"] = self.agent_registry is not None
         | 
| 190 | 
            -
             | 
| 196 | 
            +
             | 
| 191 197 | 
             
                        # Check profile discovery
         | 
| 192 198 | 
             
                        profile_count = len(self.profile_cache)
         | 
| 193 199 | 
             
                        checks["profiles_loaded"] = profile_count > 0
         | 
| 194 | 
            -
             | 
| 200 | 
            +
             | 
| 195 201 | 
             
                        # Check improved prompts storage
         | 
| 196 202 | 
             
                        checks["improved_prompts_storage"] = self.improved_prompts_path.exists()
         | 
| 197 | 
            -
             | 
| 203 | 
            +
             | 
| 198 204 | 
             
                    except Exception as e:
         | 
| 199 205 | 
             
                        logger.error(f"Health check failed: {e}")
         | 
| 200 206 | 
             
                        checks["health_check_error"] = False
         | 
| 201 | 
            -
             | 
| 207 | 
            +
             | 
| 202 208 | 
             
                    return checks
         | 
| 203 | 
            -
             | 
| 209 | 
            +
             | 
| 204 210 | 
             
                # ========================================================================
         | 
| 205 211 | 
             
                # Core Profile Loading
         | 
| 206 212 | 
             
                # ========================================================================
         | 
| 207 | 
            -
             | 
| 208 | 
            -
                async def load_agent_profile( | 
| 209 | 
            -
             | 
| 213 | 
            +
             | 
| 214 | 
            +
                async def load_agent_profile(
         | 
| 215 | 
            +
                    self, agent_name: str, use_cache: bool = True
         | 
| 216 | 
            +
                ) -> Optional[AgentProfile]:
         | 
| 210 217 | 
             
                    """
         | 
| 211 218 | 
             
                    Load agent profile with three-tier hierarchy precedence.
         | 
| 212 | 
            -
             | 
| 219 | 
            +
             | 
| 213 220 | 
             
                    Args:
         | 
| 214 221 | 
             
                        agent_name: Name of the agent to load
         | 
| 215 222 | 
             
                        use_cache: Whether to use cached profile if available
         | 
| 216 | 
            -
             | 
| 223 | 
            +
             | 
| 217 224 | 
             
                    Returns:
         | 
| 218 225 | 
             
                        AgentProfile or None if not found
         | 
| 219 226 | 
             
                    """
         | 
| 220 227 | 
             
                    start_time = asyncio.get_event_loop().time()
         | 
| 221 | 
            -
             | 
| 228 | 
            +
             | 
| 222 229 | 
             
                    # Check cache first
         | 
| 223 230 | 
             
                    if use_cache and agent_name in self.profile_cache:
         | 
| 224 231 | 
             
                        profile = self.profile_cache[agent_name]
         | 
| 225 232 | 
             
                        if (datetime.now() - profile.loaded_at).seconds < self.cache_ttl:
         | 
| 226 | 
            -
                            self.load_metrics[f"{agent_name}_cache_hit"] =  | 
| 233 | 
            +
                            self.load_metrics[f"{agent_name}_cache_hit"] = (
         | 
| 234 | 
            +
                                asyncio.get_event_loop().time() - start_time
         | 
| 235 | 
            +
                            )
         | 
| 227 236 | 
             
                            return profile
         | 
| 228 | 
            -
             | 
| 237 | 
            +
             | 
| 229 238 | 
             
                    # Load profile with tier precedence
         | 
| 230 239 | 
             
                    profile = await self._load_profile_with_precedence(agent_name)
         | 
| 231 | 
            -
             | 
| 240 | 
            +
             | 
| 232 241 | 
             
                    if profile:
         | 
| 233 242 | 
             
                        # Load improved prompts
         | 
| 234 243 | 
             
                        profile.improved_prompts = await self._load_improved_prompts(agent_name)
         | 
| 235 | 
            -
             | 
| 244 | 
            +
             | 
| 236 245 | 
             
                        # Cache the profile
         | 
| 237 246 | 
             
                        self.profile_cache[agent_name] = profile
         | 
| 238 | 
            -
             | 
| 247 | 
            +
             | 
| 239 248 | 
             
                        # Update metrics
         | 
| 240 | 
            -
                        self.load_metrics[f"{agent_name}_load_time"] =  | 
| 241 | 
            -
             | 
| 249 | 
            +
                        self.load_metrics[f"{agent_name}_load_time"] = (
         | 
| 250 | 
            +
                            asyncio.get_event_loop().time() - start_time
         | 
| 251 | 
            +
                        )
         | 
| 252 | 
            +
             | 
| 242 253 | 
             
                        # Integrate with SharedPromptCache if available
         | 
| 243 254 | 
             
                        if self.shared_cache and profile.status == ProfileStatus.LOADED:
         | 
| 244 255 | 
             
                            cache_key = f"agent_profile_{agent_name}"
         | 
| 245 256 | 
             
                            await self.shared_cache.set_cached_result(cache_key, profile)
         | 
| 246 257 | 
             
                            profile.cache_key = cache_key
         | 
| 247 | 
            -
             | 
| 258 | 
            +
             | 
| 248 259 | 
             
                    return profile
         | 
| 249 | 
            -
             | 
| 250 | 
            -
                async def _load_profile_with_precedence( | 
| 260 | 
            +
             | 
| 261 | 
            +
                async def _load_profile_with_precedence(
         | 
| 262 | 
            +
                    self, agent_name: str
         | 
| 263 | 
            +
                ) -> Optional[AgentProfile]:
         | 
| 251 264 | 
             
                    """Load profile following tier precedence: Project → User → System."""
         | 
| 252 265 | 
             
                    for tier in [ProfileTier.PROJECT, ProfileTier.USER, ProfileTier.SYSTEM]:
         | 
| 253 266 | 
             
                        if tier not in self.tier_paths:
         | 
| 254 267 | 
             
                            continue
         | 
| 255 | 
            -
             | 
| 268 | 
            +
             | 
| 256 269 | 
             
                        profile = await self._load_profile_from_tier(agent_name, tier)
         | 
| 257 270 | 
             
                        if profile and profile.status == ProfileStatus.LOADED:
         | 
| 258 271 | 
             
                            return profile
         | 
| 259 | 
            -
             | 
| 272 | 
            +
             | 
| 260 273 | 
             
                    return None
         | 
| 261 | 
            -
             | 
| 262 | 
            -
                async def _load_profile_from_tier( | 
| 263 | 
            -
             | 
| 274 | 
            +
             | 
| 275 | 
            +
                async def _load_profile_from_tier(
         | 
| 276 | 
            +
                    self, agent_name: str, tier: ProfileTier
         | 
| 277 | 
            +
                ) -> Optional[AgentProfile]:
         | 
| 264 278 | 
             
                    """Load profile from specific tier."""
         | 
| 265 279 | 
             
                    tier_path = self.tier_paths[tier]
         | 
| 266 | 
            -
             | 
| 280 | 
            +
             | 
| 267 281 | 
             
                    # Try different file formats and naming conventions
         | 
| 268 282 | 
             
                    # Check .md files first (Claude Code format), then fall back to YAML/JSON
         | 
| 269 283 | 
             
                    possible_files = [
         | 
| @@ -280,380 +294,396 @@ class AgentProfileLoader(BaseService): | |
| 280 294 | 
             
                        tier_path / f"{agent_name}-agent.yml",
         | 
| 281 295 | 
             
                        tier_path / f"{agent_name}-agent.json",
         | 
| 282 296 | 
             
                    ]
         | 
| 283 | 
            -
             | 
| 297 | 
            +
             | 
| 284 298 | 
             
                    for file_path in possible_files:
         | 
| 285 299 | 
             
                        if file_path.exists():
         | 
| 286 300 | 
             
                            return await self._parse_profile_file(file_path, tier)
         | 
| 287 | 
            -
             | 
| 301 | 
            +
             | 
| 288 302 | 
             
                    return None
         | 
| 289 | 
            -
             | 
| 290 | 
            -
                async def _parse_profile_file( | 
| 291 | 
            -
             | 
| 303 | 
            +
             | 
| 304 | 
            +
                async def _parse_profile_file(
         | 
| 305 | 
            +
                    self, file_path: Path, tier: ProfileTier
         | 
| 306 | 
            +
                ) -> Optional[AgentProfile]:
         | 
| 292 307 | 
             
                    """Parse agent profile from file."""
         | 
| 293 308 | 
             
                    try:
         | 
| 294 309 | 
             
                        # Read file content
         | 
| 295 310 | 
             
                        content = file_path.read_text()
         | 
| 296 | 
            -
             | 
| 311 | 
            +
             | 
| 297 312 | 
             
                        # Parse based on file extension
         | 
| 298 | 
            -
                        if file_path.suffix ==  | 
| 313 | 
            +
                        if file_path.suffix == ".md":
         | 
| 299 314 | 
             
                            # Parse markdown with YAML frontmatter
         | 
| 300 315 | 
             
                            data, instructions = self._parse_markdown_with_frontmatter(content)
         | 
| 301 | 
            -
                        elif file_path.suffix in [ | 
| 316 | 
            +
                        elif file_path.suffix in [".yaml", ".yml"]:
         | 
| 302 317 | 
             
                            data = yaml.safe_load(content)
         | 
| 303 | 
            -
                            instructions = data.get( | 
| 304 | 
            -
                        elif file_path.suffix ==  | 
| 318 | 
            +
                            instructions = data.get("instructions", "")
         | 
| 319 | 
            +
                        elif file_path.suffix == ".json":
         | 
| 305 320 | 
             
                            data = json.loads(content)
         | 
| 306 | 
            -
                            instructions = data.get( | 
| 321 | 
            +
                            instructions = data.get("instructions", "")
         | 
| 307 322 | 
             
                        else:
         | 
| 308 323 | 
             
                            # Try to parse as YAML first, then JSON
         | 
| 309 324 | 
             
                            try:
         | 
| 310 325 | 
             
                                data = yaml.safe_load(content)
         | 
| 311 | 
            -
                                instructions = data.get( | 
| 326 | 
            +
                                instructions = data.get("instructions", "")
         | 
| 312 327 | 
             
                            except:
         | 
| 313 328 | 
             
                                data = json.loads(content)
         | 
| 314 | 
            -
                                instructions = data.get( | 
| 315 | 
            -
             | 
| 329 | 
            +
                                instructions = data.get("instructions", "")
         | 
| 330 | 
            +
             | 
| 316 331 | 
             
                        # Create profile
         | 
| 317 332 | 
             
                        profile = AgentProfile(
         | 
| 318 | 
            -
                            name=data.get( | 
| 319 | 
            -
                            role=data.get( | 
| 320 | 
            -
                            description=data.get( | 
| 333 | 
            +
                            name=data.get("name", file_path.stem),
         | 
| 334 | 
            +
                            role=data.get("role", "agent"),
         | 
| 335 | 
            +
                            description=data.get("description", ""),
         | 
| 321 336 | 
             
                            tier=tier,
         | 
| 322 337 | 
             
                            source_path=str(file_path),
         | 
| 323 338 | 
             
                            instructions=instructions,
         | 
| 324 | 
            -
                            capabilities=data.get( | 
| 325 | 
            -
                            constraints=data.get( | 
| 326 | 
            -
                            metadata=data.get( | 
| 327 | 
            -
                            status=ProfileStatus.LOADED
         | 
| 339 | 
            +
                            capabilities=data.get("capabilities", []),
         | 
| 340 | 
            +
                            constraints=data.get("constraints", []),
         | 
| 341 | 
            +
                            metadata=data.get("metadata", {}),
         | 
| 342 | 
            +
                            status=ProfileStatus.LOADED,
         | 
| 328 343 | 
             
                        )
         | 
| 329 | 
            -
             | 
| 344 | 
            +
             | 
| 330 345 | 
             
                        return profile
         | 
| 331 | 
            -
             | 
| 346 | 
            +
             | 
| 332 347 | 
             
                    except Exception as e:
         | 
| 333 348 | 
             
                        logger.error(f"Error parsing profile {file_path}: {e}")
         | 
| 334 349 | 
             
                        return AgentProfile(
         | 
| 335 350 | 
             
                            name=file_path.stem,
         | 
| 336 | 
            -
                            role= | 
| 337 | 
            -
                            description= | 
| 351 | 
            +
                            role="error",
         | 
| 352 | 
            +
                            description="Failed to load profile",
         | 
| 338 353 | 
             
                            tier=tier,
         | 
| 339 354 | 
             
                            source_path=str(file_path),
         | 
| 340 355 | 
             
                            status=ProfileStatus.ERROR,
         | 
| 341 | 
            -
                            error=str(e)
         | 
| 356 | 
            +
                            error=str(e),
         | 
| 342 357 | 
             
                        )
         | 
| 343 | 
            -
             | 
| 344 | 
            -
                def _parse_markdown_with_frontmatter( | 
| 358 | 
            +
             | 
| 359 | 
            +
                def _parse_markdown_with_frontmatter(
         | 
| 360 | 
            +
                    self, content: str
         | 
| 361 | 
            +
                ) -> Tuple[Dict[str, Any], str]:
         | 
| 345 362 | 
             
                    """
         | 
| 346 363 | 
             
                    Parse markdown file with YAML frontmatter.
         | 
| 347 | 
            -
             | 
| 364 | 
            +
             | 
| 348 365 | 
             
                    Args:
         | 
| 349 366 | 
             
                        content: Markdown content with YAML frontmatter
         | 
| 350 | 
            -
             | 
| 367 | 
            +
             | 
| 351 368 | 
             
                    Returns:
         | 
| 352 369 | 
             
                        Tuple of (frontmatter_data, markdown_content)
         | 
| 353 370 | 
             
                    """
         | 
| 354 371 | 
             
                    import re
         | 
| 355 | 
            -
             | 
| 372 | 
            +
             | 
| 356 373 | 
             
                    # Check if content starts with YAML frontmatter
         | 
| 357 | 
            -
                    if not content.strip().startswith( | 
| 374 | 
            +
                    if not content.strip().startswith("---"):
         | 
| 358 375 | 
             
                        # No frontmatter, treat entire content as instructions
         | 
| 359 | 
            -
                        return { | 
| 360 | 
            -
             | 
| 376 | 
            +
                        return {"name": "unknown", "description": "No frontmatter found"}, content
         | 
| 377 | 
            +
             | 
| 361 378 | 
             
                    # Split frontmatter and content
         | 
| 362 | 
            -
                    parts = re.split(r | 
| 363 | 
            -
             | 
| 379 | 
            +
                    parts = re.split(r"^---\s*$", content, 2, re.MULTILINE)
         | 
| 380 | 
            +
             | 
| 364 381 | 
             
                    if len(parts) < 3:
         | 
| 365 382 | 
             
                        # Invalid frontmatter structure
         | 
| 366 | 
            -
                        return { | 
| 367 | 
            -
             | 
| 383 | 
            +
                        return {"name": "unknown", "description": "Invalid frontmatter"}, content
         | 
| 384 | 
            +
             | 
| 368 385 | 
             
                    # Parse YAML frontmatter
         | 
| 369 386 | 
             
                    frontmatter_text = parts[1].strip()
         | 
| 370 387 | 
             
                    markdown_content = parts[2].strip()
         | 
| 371 | 
            -
             | 
| 388 | 
            +
             | 
| 372 389 | 
             
                    try:
         | 
| 373 390 | 
             
                        frontmatter_data = yaml.safe_load(frontmatter_text)
         | 
| 374 391 | 
             
                        if not isinstance(frontmatter_data, dict):
         | 
| 375 | 
            -
                            frontmatter_data = { | 
| 392 | 
            +
                            frontmatter_data = {
         | 
| 393 | 
            +
                                "name": "unknown",
         | 
| 394 | 
            +
                                "description": "Invalid frontmatter format",
         | 
| 395 | 
            +
                            }
         | 
| 376 396 | 
             
                    except Exception as e:
         | 
| 377 397 | 
             
                        logger.error(f"Error parsing YAML frontmatter: {e}")
         | 
| 378 | 
            -
                        frontmatter_data = { | 
| 379 | 
            -
             | 
| 398 | 
            +
                        frontmatter_data = {
         | 
| 399 | 
            +
                            "name": "unknown",
         | 
| 400 | 
            +
                            "description": f"YAML parse error: {e}",
         | 
| 401 | 
            +
                        }
         | 
| 402 | 
            +
             | 
| 380 403 | 
             
                    return frontmatter_data, markdown_content
         | 
| 381 | 
            -
             | 
| 404 | 
            +
             | 
| 382 405 | 
             
                # ========================================================================
         | 
| 383 406 | 
             
                # Profile Discovery
         | 
| 384 407 | 
             
                # ========================================================================
         | 
| 385 | 
            -
             | 
| 408 | 
            +
             | 
| 386 409 | 
             
                async def _discover_all_profiles(self) -> Dict[ProfileTier, List[str]]:
         | 
| 387 410 | 
             
                    """Discover all available agent profiles across tiers."""
         | 
| 388 411 | 
             
                    discovered = {}
         | 
| 389 | 
            -
             | 
| 412 | 
            +
             | 
| 390 413 | 
             
                    for tier, tier_path in self.tier_paths.items():
         | 
| 391 414 | 
             
                        if not tier_path.exists():
         | 
| 392 415 | 
             
                            continue
         | 
| 393 | 
            -
             | 
| 416 | 
            +
             | 
| 394 417 | 
             
                        agents = []
         | 
| 395 418 | 
             
                        # Check for .md files (Claude Code format) and YAML/JSON files
         | 
| 396 | 
            -
                        file_patterns = [ | 
| 419 | 
            +
                        file_patterns = ["*.md", "*.yaml", "*.yml", "*.json"]
         | 
| 397 420 | 
             
                        for pattern in file_patterns:
         | 
| 398 421 | 
             
                            for file_path in tier_path.glob(pattern):
         | 
| 399 422 | 
             
                                agent_name = file_path.stem
         | 
| 400 423 | 
             
                                # Remove common suffixes
         | 
| 401 | 
            -
                                if agent_name.endswith( | 
| 424 | 
            +
                                if agent_name.endswith("_agent"):
         | 
| 402 425 | 
             
                                    agent_name = agent_name[:-6]
         | 
| 403 | 
            -
                                elif agent_name.endswith( | 
| 426 | 
            +
                                elif agent_name.endswith("-agent"):
         | 
| 404 427 | 
             
                                    agent_name = agent_name[:-6]
         | 
| 405 | 
            -
             | 
| 428 | 
            +
             | 
| 406 429 | 
             
                                if agent_name not in agents:
         | 
| 407 430 | 
             
                                    agents.append(agent_name)
         | 
| 408 | 
            -
             | 
| 431 | 
            +
             | 
| 409 432 | 
             
                        discovered[tier] = agents
         | 
| 410 433 | 
             
                        logger.debug(f"Discovered {len(agents)} agents in {tier.value} tier")
         | 
| 411 | 
            -
             | 
| 434 | 
            +
             | 
| 412 435 | 
             
                    return discovered
         | 
| 413 | 
            -
             | 
| 414 | 
            -
                async def get_available_agents( | 
| 436 | 
            +
             | 
| 437 | 
            +
                async def get_available_agents(
         | 
| 438 | 
            +
                    self, tier: Optional[ProfileTier] = None
         | 
| 439 | 
            +
                ) -> List[str]:
         | 
| 415 440 | 
             
                    """Get list of available agents, optionally filtered by tier."""
         | 
| 416 441 | 
             
                    discovered = await self._discover_all_profiles()
         | 
| 417 | 
            -
             | 
| 442 | 
            +
             | 
| 418 443 | 
             
                    if tier:
         | 
| 419 444 | 
             
                        return discovered.get(tier, [])
         | 
| 420 | 
            -
             | 
| 445 | 
            +
             | 
| 421 446 | 
             
                    # Combine all tiers, removing duplicates
         | 
| 422 447 | 
             
                    all_agents = set()
         | 
| 423 448 | 
             
                    for agents in discovered.values():
         | 
| 424 449 | 
             
                        all_agents.update(agents)
         | 
| 425 | 
            -
             | 
| 450 | 
            +
             | 
| 426 451 | 
             
                    return sorted(list(all_agents))
         | 
| 427 | 
            -
             | 
| 452 | 
            +
             | 
| 428 453 | 
             
                # ========================================================================
         | 
| 429 454 | 
             
                # Improved Prompts Management
         | 
| 430 455 | 
             
                # ========================================================================
         | 
| 431 | 
            -
             | 
| 456 | 
            +
             | 
| 432 457 | 
             
                async def _load_improved_prompts(self, agent_name: str) -> List[ImprovedPrompt]:
         | 
| 433 458 | 
             
                    """Load improved prompts for an agent."""
         | 
| 434 459 | 
             
                    prompts = []
         | 
| 435 460 | 
             
                    prompt_file = self.improved_prompts_path / f"{agent_name}_prompts.json"
         | 
| 436 | 
            -
             | 
| 461 | 
            +
             | 
| 437 462 | 
             
                    if prompt_file.exists():
         | 
| 438 463 | 
             
                        try:
         | 
| 439 | 
            -
                            with open(prompt_file,  | 
| 464 | 
            +
                            with open(prompt_file, "r") as f:
         | 
| 440 465 | 
             
                                data = json.load(f)
         | 
| 441 466 | 
             
                                for prompt_data in data:
         | 
| 442 467 | 
             
                                    prompt = ImprovedPrompt(
         | 
| 443 | 
            -
                                        prompt_id=prompt_data[ | 
| 444 | 
            -
                                        agent_name=prompt_data[ | 
| 445 | 
            -
                                        version=prompt_data[ | 
| 446 | 
            -
                                        content=prompt_data[ | 
| 447 | 
            -
                                        metrics=prompt_data.get( | 
| 448 | 
            -
                                        metadata=prompt_data.get( | 
| 449 | 
            -
                                        created_at=datetime.fromisoformat( | 
| 450 | 
            -
             | 
| 468 | 
            +
                                        prompt_id=prompt_data["prompt_id"],
         | 
| 469 | 
            +
                                        agent_name=prompt_data["agent_name"],
         | 
| 470 | 
            +
                                        version=prompt_data["version"],
         | 
| 471 | 
            +
                                        content=prompt_data["content"],
         | 
| 472 | 
            +
                                        metrics=prompt_data.get("metrics", {}),
         | 
| 473 | 
            +
                                        metadata=prompt_data.get("metadata", {}),
         | 
| 474 | 
            +
                                        created_at=datetime.fromisoformat(
         | 
| 475 | 
            +
                                            prompt_data["created_at"]
         | 
| 476 | 
            +
                                        ),
         | 
| 477 | 
            +
                                        validated=prompt_data.get("validated", False),
         | 
| 451 478 | 
             
                                    )
         | 
| 452 479 | 
             
                                    prompts.append(prompt)
         | 
| 453 480 | 
             
                        except Exception as e:
         | 
| 454 481 | 
             
                            logger.error(f"Error loading improved prompts for {agent_name}: {e}")
         | 
| 455 | 
            -
             | 
| 482 | 
            +
             | 
| 456 483 | 
             
                    return prompts
         | 
| 457 | 
            -
             | 
| 458 | 
            -
                async def save_improved_prompt( | 
| 459 | 
            -
             | 
| 484 | 
            +
             | 
| 485 | 
            +
                async def save_improved_prompt(
         | 
| 486 | 
            +
                    self, agent_name: str, prompt: ImprovedPrompt
         | 
| 487 | 
            +
                ) -> bool:
         | 
| 460 488 | 
             
                    """Save an improved prompt for an agent."""
         | 
| 461 489 | 
             
                    try:
         | 
| 462 490 | 
             
                        # Load existing prompts
         | 
| 463 491 | 
             
                        prompts = await self._load_improved_prompts(agent_name)
         | 
| 464 | 
            -
             | 
| 492 | 
            +
             | 
| 465 493 | 
             
                        # Add or update prompt
         | 
| 466 494 | 
             
                        existing_idx = None
         | 
| 467 495 | 
             
                        for idx, existing in enumerate(prompts):
         | 
| 468 496 | 
             
                            if existing.prompt_id == prompt.prompt_id:
         | 
| 469 497 | 
             
                                existing_idx = idx
         | 
| 470 498 | 
             
                                break
         | 
| 471 | 
            -
             | 
| 499 | 
            +
             | 
| 472 500 | 
             
                        if existing_idx is not None:
         | 
| 473 501 | 
             
                            prompts[existing_idx] = prompt
         | 
| 474 502 | 
             
                        else:
         | 
| 475 503 | 
             
                            prompts.append(prompt)
         | 
| 476 | 
            -
             | 
| 504 | 
            +
             | 
| 477 505 | 
             
                        # Save to file
         | 
| 478 506 | 
             
                        prompt_file = self.improved_prompts_path / f"{agent_name}_prompts.json"
         | 
| 479 | 
            -
                        with open(prompt_file,  | 
| 480 | 
            -
                            json.dump( | 
| 481 | 
            -
                                 | 
| 482 | 
            -
                                     | 
| 483 | 
            -
             | 
| 484 | 
            -
             | 
| 485 | 
            -
             | 
| 486 | 
            -
             | 
| 487 | 
            -
             | 
| 488 | 
            -
             | 
| 489 | 
            -
             | 
| 490 | 
            -
             | 
| 491 | 
            -
             | 
| 492 | 
            -
             | 
| 493 | 
            -
             | 
| 507 | 
            +
                        with open(prompt_file, "w") as f:
         | 
| 508 | 
            +
                            json.dump(
         | 
| 509 | 
            +
                                [
         | 
| 510 | 
            +
                                    {
         | 
| 511 | 
            +
                                        "prompt_id": p.prompt_id,
         | 
| 512 | 
            +
                                        "agent_name": p.agent_name,
         | 
| 513 | 
            +
                                        "version": p.version,
         | 
| 514 | 
            +
                                        "content": p.content,
         | 
| 515 | 
            +
                                        "metrics": p.metrics,
         | 
| 516 | 
            +
                                        "metadata": p.metadata,
         | 
| 517 | 
            +
                                        "created_at": p.created_at.isoformat(),
         | 
| 518 | 
            +
                                        "validated": p.validated,
         | 
| 519 | 
            +
                                    }
         | 
| 520 | 
            +
                                    for p in prompts
         | 
| 521 | 
            +
                                ],
         | 
| 522 | 
            +
                                f,
         | 
| 523 | 
            +
                                indent=2,
         | 
| 524 | 
            +
                            )
         | 
| 525 | 
            +
             | 
| 494 526 | 
             
                        return True
         | 
| 495 | 
            -
             | 
| 527 | 
            +
             | 
| 496 528 | 
             
                    except Exception as e:
         | 
| 497 529 | 
             
                        logger.error(f"Error saving improved prompt: {e}")
         | 
| 498 530 | 
             
                        return False
         | 
| 499 | 
            -
             | 
| 531 | 
            +
             | 
| 500 532 | 
             
                async def _save_improved_prompts(self) -> None:
         | 
| 501 533 | 
             
                    """Save all pending improved prompts."""
         | 
| 502 534 | 
             
                    for agent_name, profile in self.profile_cache.items():
         | 
| 503 535 | 
             
                        if profile.improved_prompts:
         | 
| 504 536 | 
             
                            for prompt in profile.improved_prompts:
         | 
| 505 537 | 
             
                                await self.save_improved_prompt(agent_name, prompt)
         | 
| 506 | 
            -
             | 
| 538 | 
            +
             | 
| 507 539 | 
             
                # ========================================================================
         | 
| 508 540 | 
             
                # Task Integration
         | 
| 509 541 | 
             
                # ========================================================================
         | 
| 510 | 
            -
             | 
| 511 | 
            -
                async def enhance_task_creation( | 
| 512 | 
            -
             | 
| 542 | 
            +
             | 
| 543 | 
            +
                async def enhance_task_creation(
         | 
| 544 | 
            +
                    self, agent_name: str, task_params: Dict[str, Any]
         | 
| 545 | 
            +
                ) -> Dict[str, Any]:
         | 
| 513 546 | 
             
                    """
         | 
| 514 547 | 
             
                    Enhance Task Tool subprocess creation with agent profile data.
         | 
| 515 | 
            -
             | 
| 548 | 
            +
             | 
| 516 549 | 
             
                    Args:
         | 
| 517 550 | 
             
                        agent_name: Name of the agent
         | 
| 518 551 | 
             
                        task_params: Original task parameters
         | 
| 519 | 
            -
             | 
| 552 | 
            +
             | 
| 520 553 | 
             
                    Returns:
         | 
| 521 554 | 
             
                        Enhanced task parameters
         | 
| 522 555 | 
             
                    """
         | 
| 523 556 | 
             
                    profile = await self.load_agent_profile(agent_name)
         | 
| 524 | 
            -
             | 
| 557 | 
            +
             | 
| 525 558 | 
             
                    if not profile:
         | 
| 526 559 | 
             
                        logger.warning(f"No profile found for agent {agent_name}")
         | 
| 527 560 | 
             
                        return task_params
         | 
| 528 | 
            -
             | 
| 561 | 
            +
             | 
| 529 562 | 
             
                    # Enhance with profile data
         | 
| 530 563 | 
             
                    enhanced = task_params.copy()
         | 
| 531 | 
            -
             | 
| 564 | 
            +
             | 
| 532 565 | 
             
                    # Add agent metadata
         | 
| 533 | 
            -
                    enhanced[ | 
| 534 | 
            -
                         | 
| 535 | 
            -
                         | 
| 536 | 
            -
                         | 
| 537 | 
            -
                         | 
| 538 | 
            -
                         | 
| 566 | 
            +
                    enhanced["agent_metadata"] = {
         | 
| 567 | 
            +
                        "name": profile.name,
         | 
| 568 | 
            +
                        "role": profile.role,
         | 
| 569 | 
            +
                        "tier": profile.tier.value,
         | 
| 570 | 
            +
                        "capabilities": profile.capabilities,
         | 
| 571 | 
            +
                        "constraints": profile.constraints,
         | 
| 539 572 | 
             
                    }
         | 
| 540 | 
            -
             | 
| 573 | 
            +
             | 
| 541 574 | 
             
                    # Add improved prompts if available
         | 
| 542 575 | 
             
                    if profile.improved_prompts:
         | 
| 543 576 | 
             
                        best_prompt = max(
         | 
| 544 | 
            -
                            profile.improved_prompts,
         | 
| 545 | 
            -
                            key=lambda p: p.metrics.get('success_rate', 0)
         | 
| 577 | 
            +
                            profile.improved_prompts, key=lambda p: p.metrics.get("success_rate", 0)
         | 
| 546 578 | 
             
                        )
         | 
| 547 | 
            -
                        enhanced[ | 
| 548 | 
            -
                             | 
| 549 | 
            -
                             | 
| 550 | 
            -
                             | 
| 579 | 
            +
                        enhanced["improved_prompt"] = {
         | 
| 580 | 
            +
                            "content": best_prompt.content,
         | 
| 581 | 
            +
                            "version": best_prompt.version,
         | 
| 582 | 
            +
                            "metrics": best_prompt.metrics,
         | 
| 551 583 | 
             
                        }
         | 
| 552 | 
            -
             | 
| 584 | 
            +
             | 
| 553 585 | 
             
                    # Add custom instructions if available
         | 
| 554 586 | 
             
                    if profile.instructions:
         | 
| 555 | 
            -
                        enhanced[ | 
| 556 | 
            -
             | 
| 587 | 
            +
                        enhanced["additional_instructions"] = profile.instructions
         | 
| 588 | 
            +
             | 
| 557 589 | 
             
                    return enhanced
         | 
| 558 | 
            -
             | 
| 590 | 
            +
             | 
| 559 591 | 
             
                # ========================================================================
         | 
| 560 592 | 
             
                # Metrics and Validation
         | 
| 561 593 | 
             
                # ========================================================================
         | 
| 562 | 
            -
             | 
| 594 | 
            +
             | 
| 563 595 | 
             
                async def validate_profile(self, agent_name: str) -> Dict[str, Any]:
         | 
| 564 596 | 
             
                    """Validate agent profile structure and content."""
         | 
| 565 597 | 
             
                    profile = await self.load_agent_profile(agent_name)
         | 
| 566 | 
            -
             | 
| 598 | 
            +
             | 
| 567 599 | 
             
                    if not profile:
         | 
| 568 | 
            -
                        return { | 
| 569 | 
            -
             | 
| 570 | 
            -
                    validation_results = {
         | 
| 571 | 
            -
             | 
| 572 | 
            -
                        'warnings': [],
         | 
| 573 | 
            -
                        'errors': []
         | 
| 574 | 
            -
                    }
         | 
| 575 | 
            -
                    
         | 
| 600 | 
            +
                        return {"valid": False, "error": "Profile not found"}
         | 
| 601 | 
            +
             | 
| 602 | 
            +
                    validation_results = {"valid": True, "warnings": [], "errors": []}
         | 
| 603 | 
            +
             | 
| 576 604 | 
             
                    # Check required fields
         | 
| 577 605 | 
             
                    if not profile.name:
         | 
| 578 | 
            -
                        validation_results[ | 
| 579 | 
            -
                        validation_results[ | 
| 580 | 
            -
             | 
| 606 | 
            +
                        validation_results["errors"].append("Missing agent name")
         | 
| 607 | 
            +
                        validation_results["valid"] = False
         | 
| 608 | 
            +
             | 
| 581 609 | 
             
                    if not profile.role:
         | 
| 582 | 
            -
                        validation_results[ | 
| 583 | 
            -
                        validation_results[ | 
| 584 | 
            -
             | 
| 610 | 
            +
                        validation_results["errors"].append("Missing agent role")
         | 
| 611 | 
            +
                        validation_results["valid"] = False
         | 
| 612 | 
            +
             | 
| 585 613 | 
             
                    # Check profile completeness
         | 
| 586 614 | 
             
                    if not profile.description:
         | 
| 587 | 
            -
                        validation_results[ | 
| 588 | 
            -
             | 
| 615 | 
            +
                        validation_results["warnings"].append("Missing agent description")
         | 
| 616 | 
            +
             | 
| 589 617 | 
             
                    if not profile.capabilities:
         | 
| 590 | 
            -
                        validation_results[ | 
| 591 | 
            -
             | 
| 618 | 
            +
                        validation_results["warnings"].append("No capabilities defined")
         | 
| 619 | 
            +
             | 
| 592 620 | 
             
                    if not profile.constraints:
         | 
| 593 | 
            -
                        validation_results[ | 
| 594 | 
            -
             | 
| 621 | 
            +
                        validation_results["warnings"].append("No constraints defined")
         | 
| 622 | 
            +
             | 
| 595 623 | 
             
                    # Validate improved prompts
         | 
| 596 624 | 
             
                    for prompt in profile.improved_prompts:
         | 
| 597 625 | 
             
                        if not prompt.validated:
         | 
| 598 | 
            -
                            validation_results[ | 
| 599 | 
            -
                                f | 
| 626 | 
            +
                            validation_results["warnings"].append(
         | 
| 627 | 
            +
                                f"Unvalidated prompt: {prompt.prompt_id}"
         | 
| 600 628 | 
             
                            )
         | 
| 601 | 
            -
             | 
| 629 | 
            +
             | 
| 602 630 | 
             
                    return validation_results
         | 
| 603 | 
            -
             | 
| 631 | 
            +
             | 
| 604 632 | 
             
                async def get_profile_metrics(self) -> Dict[str, Any]:
         | 
| 605 633 | 
             
                    """Get comprehensive profile loading metrics."""
         | 
| 606 634 | 
             
                    metrics = {
         | 
| 607 | 
            -
                         | 
| 608 | 
            -
                         | 
| 609 | 
            -
                         | 
| 635 | 
            +
                        "cache_size": len(self.profile_cache),
         | 
| 636 | 
            +
                        "load_metrics": self.load_metrics,
         | 
| 637 | 
            +
                        "tier_stats": {},
         | 
| 610 638 | 
             
                    }
         | 
| 611 | 
            -
             | 
| 639 | 
            +
             | 
| 612 640 | 
             
                    # Count profiles by tier
         | 
| 613 641 | 
             
                    for profile in self.profile_cache.values():
         | 
| 614 642 | 
             
                        tier = profile.tier.value
         | 
| 615 | 
            -
                        metrics[ | 
| 616 | 
            -
             | 
| 643 | 
            +
                        metrics["tier_stats"][tier] = metrics["tier_stats"].get(tier, 0) + 1
         | 
| 644 | 
            +
             | 
| 617 645 | 
             
                    # Calculate average load times
         | 
| 618 646 | 
             
                    if self.load_metrics:
         | 
| 619 | 
            -
                        load_times = [ | 
| 647 | 
            +
                        load_times = [
         | 
| 648 | 
            +
                            v for k, v in self.load_metrics.items() if k.endswith("_load_time")
         | 
| 649 | 
            +
                        ]
         | 
| 620 650 | 
             
                        if load_times:
         | 
| 621 | 
            -
                            metrics[ | 
| 622 | 
            -
             | 
| 651 | 
            +
                            metrics["avg_load_time"] = sum(load_times) / len(load_times)
         | 
| 652 | 
            +
             | 
| 623 653 | 
             
                    # Count improved prompts
         | 
| 624 654 | 
             
                    total_prompts = sum(
         | 
| 625 655 | 
             
                        len(p.improved_prompts) for p in self.profile_cache.values()
         | 
| 626 656 | 
             
                    )
         | 
| 627 | 
            -
                    metrics[ | 
| 628 | 
            -
             | 
| 657 | 
            +
                    metrics["total_improved_prompts"] = total_prompts
         | 
| 658 | 
            +
             | 
| 629 659 | 
             
                    return metrics
         | 
| 630 | 
            -
             | 
| 660 | 
            +
             | 
| 631 661 | 
             
                # ========================================================================
         | 
| 632 662 | 
             
                # Utility Methods
         | 
| 633 663 | 
             
                # ========================================================================
         | 
| 634 | 
            -
             | 
| 664 | 
            +
             | 
| 635 665 | 
             
                def _detect_framework_path(self) -> Optional[Path]:
         | 
| 636 666 | 
             
                    """Detect the framework path for system-level agents."""
         | 
| 637 667 | 
             
                    possible_paths = [
         | 
| 638 | 
            -
                        self.working_directory /  | 
| 639 | 
            -
                        self.working_directory /  | 
| 640 | 
            -
                        Path(__file__).parent.parent /  | 
| 668 | 
            +
                        self.working_directory / "framework",
         | 
| 669 | 
            +
                        self.working_directory / "src" / "claude_mpm" / "framework",
         | 
| 670 | 
            +
                        Path(__file__).parent.parent / "framework",
         | 
| 641 671 | 
             
                    ]
         | 
| 642 | 
            -
             | 
| 672 | 
            +
             | 
| 643 673 | 
             
                    for path in possible_paths:
         | 
| 644 | 
            -
                        if path.exists() and (path /  | 
| 674 | 
            +
                        if path.exists() and (path / "agent-roles").exists():
         | 
| 645 675 | 
             
                            return path
         | 
| 646 | 
            -
             | 
| 676 | 
            +
             | 
| 647 677 | 
             
                    return None
         | 
| 648 | 
            -
             | 
| 678 | 
            +
             | 
| 649 679 | 
             
                def invalidate_cache(self, agent_name: Optional[str] = None) -> None:
         | 
| 650 680 | 
             
                    """Invalidate profile cache."""
         | 
| 651 681 | 
             
                    if agent_name:
         | 
| 652 682 | 
             
                        self.profile_cache.pop(agent_name, None)
         | 
| 653 683 | 
             
                    else:
         | 
| 654 684 | 
             
                        self.profile_cache.clear()
         | 
| 655 | 
            -
             | 
| 685 | 
            +
             | 
| 656 686 | 
             
                async def reload_profile(self, agent_name: str) -> Optional[AgentProfile]:
         | 
| 657 687 | 
             
                    """Force reload of agent profile, bypassing cache."""
         | 
| 658 688 | 
             
                    self.invalidate_cache(agent_name)
         | 
| 659 | 
            -
                    return await self.load_agent_profile(agent_name, use_cache=False)
         | 
| 689 | 
            +
                    return await self.load_agent_profile(agent_name, use_cache=False)
         |