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
| @@ -5,53 +5,51 @@ WHY: This module manages Claude Code native agents, including listing, deploying | |
| 5 5 | 
             
            and cleaning agent deployments.
         | 
| 6 6 | 
             
            """
         | 
| 7 7 |  | 
| 8 | 
            -
            from pathlib import Path
         | 
| 9 8 | 
             
            import json
         | 
| 9 | 
            +
            from typing import Any, Dict, Optional
         | 
| 10 | 
            +
             | 
| 10 11 | 
             
            import yaml
         | 
| 11 | 
            -
            from typing import Dict, Any, Optional
         | 
| 12 12 |  | 
| 13 | 
            -
            from ... | 
| 13 | 
            +
            from ...agents.frontmatter_validator import FrontmatterValidator
         | 
| 14 14 | 
             
            from ...constants import AgentCommands
         | 
| 15 | 
            -
            from ..utils import get_agent_versions_display
         | 
| 16 15 | 
             
            from ...core.agent_registry import AgentRegistryAdapter
         | 
| 17 | 
            -
            from ...agents.frontmatter_validator import FrontmatterValidator
         | 
| 18 16 | 
             
            from ...core.config import Config
         | 
| 17 | 
            +
            from ...core.logger import get_logger
         | 
| 18 | 
            +
            from ..utils import get_agent_versions_display
         | 
| 19 19 |  | 
| 20 20 |  | 
| 21 21 | 
             
            def manage_agents(args):
         | 
| 22 22 | 
             
                """
         | 
| 23 23 | 
             
                Manage Claude Code native agents.
         | 
| 24 | 
            -
             | 
| 24 | 
            +
             | 
| 25 25 | 
             
                WHY: Claude Code agents need to be deployed and managed. This command provides
         | 
| 26 26 | 
             
                a unified interface for all agent-related operations.
         | 
| 27 | 
            -
             | 
| 27 | 
            +
             | 
| 28 28 | 
             
                DESIGN DECISION: When no subcommand is provided, we show the current agent
         | 
| 29 29 | 
             
                versions as a quick status check. This matches the behavior users see at startup.
         | 
| 30 | 
            -
             | 
| 30 | 
            +
             | 
| 31 31 | 
             
                Args:
         | 
| 32 32 | 
             
                    args: Parsed command line arguments with agents_command attribute
         | 
| 33 33 | 
             
                """
         | 
| 34 34 | 
             
                logger = get_logger("cli")
         | 
| 35 | 
            -
             | 
| 35 | 
            +
             | 
| 36 36 | 
             
                try:
         | 
| 37 | 
            -
                    from ...services import AgentDeploymentService
         | 
| 38 37 | 
             
                    import os
         | 
| 39 38 | 
             
                    from pathlib import Path
         | 
| 40 | 
            -
             | 
| 39 | 
            +
             | 
| 40 | 
            +
                    from ...services import AgentDeploymentService
         | 
| 41 | 
            +
             | 
| 41 42 | 
             
                    # Determine the user's working directory from environment
         | 
| 42 43 | 
             
                    # This ensures agents are deployed to the correct directory
         | 
| 43 44 | 
             
                    user_working_dir = None
         | 
| 44 | 
            -
                    if  | 
| 45 | 
            -
                        user_working_dir = Path(os.environ[ | 
| 46 | 
            -
             | 
| 45 | 
            +
                    if "CLAUDE_MPM_USER_PWD" in os.environ:
         | 
| 46 | 
            +
                        user_working_dir = Path(os.environ["CLAUDE_MPM_USER_PWD"])
         | 
| 47 | 
            +
             | 
| 47 48 | 
             
                    # For system agents, don't pass working_directory so they deploy to ~/.claude/agents/
         | 
| 48 49 | 
             
                    # The service will determine the correct path based on the agent source
         | 
| 49 50 | 
             
                    deployment_service = AgentDeploymentService()
         | 
| 50 | 
            -
             | 
| 51 | 
            +
             | 
| 51 52 | 
             
                    if not args.agents_command:
         | 
| 52 | 
            -
                        # No subcommand - show agent versions
         | 
| 53 | 
            -
                        # WHY: This provides a quick way for users to check deployed agent versions
         | 
| 54 | 
            -
                        # without needing to specify additional subcommands
         | 
| 55 53 | 
             
                        agent_versions = get_agent_versions_display()
         | 
| 56 54 | 
             
                        if agent_versions:
         | 
| 57 55 | 
             
                            print(agent_versions)
         | 
| @@ -59,37 +57,37 @@ def manage_agents(args): | |
| 59 57 | 
             
                            print("No deployed agents found")
         | 
| 60 58 | 
             
                            print("\nTo deploy agents, run: claude-mpm --mpm:agents deploy")
         | 
| 61 59 | 
             
                        return
         | 
| 62 | 
            -
             | 
| 60 | 
            +
             | 
| 63 61 | 
             
                    if args.agents_command == AgentCommands.LIST.value:
         | 
| 64 62 | 
             
                        _list_agents(args, deployment_service)
         | 
| 65 | 
            -
             | 
| 63 | 
            +
             | 
| 66 64 | 
             
                    elif args.agents_command == AgentCommands.DEPLOY.value:
         | 
| 67 65 | 
             
                        _deploy_agents(args, deployment_service, force=False)
         | 
| 68 | 
            -
             | 
| 66 | 
            +
             | 
| 69 67 | 
             
                    elif args.agents_command == AgentCommands.FORCE_DEPLOY.value:
         | 
| 70 68 | 
             
                        _deploy_agents(args, deployment_service, force=True)
         | 
| 71 | 
            -
             | 
| 69 | 
            +
             | 
| 72 70 | 
             
                    elif args.agents_command == AgentCommands.CLEAN.value:
         | 
| 73 71 | 
             
                        _clean_agents(args, deployment_service)
         | 
| 74 | 
            -
             | 
| 72 | 
            +
             | 
| 75 73 | 
             
                    elif args.agents_command == AgentCommands.VIEW.value:
         | 
| 76 74 | 
             
                        _view_agent(args)
         | 
| 77 | 
            -
             | 
| 75 | 
            +
             | 
| 78 76 | 
             
                    elif args.agents_command == AgentCommands.FIX.value:
         | 
| 79 77 | 
             
                        _fix_agents(args)
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                    elif args.agents_command ==  | 
| 78 | 
            +
             | 
| 79 | 
            +
                    elif args.agents_command == "deps-check":
         | 
| 82 80 | 
             
                        _check_agent_dependencies(args)
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                    elif args.agents_command ==  | 
| 81 | 
            +
             | 
| 82 | 
            +
                    elif args.agents_command == "deps-install":
         | 
| 85 83 | 
             
                        _install_agent_dependencies(args)
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                    elif args.agents_command ==  | 
| 84 | 
            +
             | 
| 85 | 
            +
                    elif args.agents_command == "deps-list":
         | 
| 88 86 | 
             
                        _list_agent_dependencies(args)
         | 
| 89 | 
            -
             | 
| 90 | 
            -
                    elif args.agents_command ==  | 
| 87 | 
            +
             | 
| 88 | 
            +
                    elif args.agents_command == "deps-fix":
         | 
| 91 89 | 
             
                        _fix_agent_dependencies(args)
         | 
| 92 | 
            -
             | 
| 90 | 
            +
             | 
| 93 91 | 
             
                except ImportError:
         | 
| 94 92 | 
             
                    logger.error("Agent deployment service not available")
         | 
| 95 93 | 
             
                    print("Error: Agent deployment service not available")
         | 
| @@ -101,15 +99,15 @@ def manage_agents(args): | |
| 101 99 | 
             
            def _list_agents(args, deployment_service):
         | 
| 102 100 | 
             
                """
         | 
| 103 101 | 
             
                List available or deployed agents.
         | 
| 104 | 
            -
             | 
| 102 | 
            +
             | 
| 105 103 | 
             
                WHY: Users need to see what agents are available in the system and what's
         | 
| 106 104 | 
             
                currently deployed. This helps them understand the agent ecosystem.
         | 
| 107 | 
            -
             | 
| 105 | 
            +
             | 
| 108 106 | 
             
                Args:
         | 
| 109 107 | 
             
                    args: Command arguments with 'system', 'deployed', and 'by_tier' flags
         | 
| 110 108 | 
             
                    deployment_service: Agent deployment service instance
         | 
| 111 109 | 
             
                """
         | 
| 112 | 
            -
                if hasattr(args,  | 
| 110 | 
            +
                if hasattr(args, "by_tier") and args.by_tier:
         | 
| 113 111 | 
             
                    # List agents grouped by tier
         | 
| 114 112 | 
             
                    _list_agents_by_tier()
         | 
| 115 113 | 
             
                elif args.system:
         | 
| @@ -122,14 +120,14 @@ def _list_agents(args, deployment_service): | |
| 122 120 | 
             
                    else:
         | 
| 123 121 | 
             
                        for agent in agents:
         | 
| 124 122 | 
             
                            print(f"📄 {agent['file']}")
         | 
| 125 | 
            -
                            if  | 
| 123 | 
            +
                            if "name" in agent:
         | 
| 126 124 | 
             
                                print(f"   Name: {agent['name']}")
         | 
| 127 | 
            -
                            if  | 
| 125 | 
            +
                            if "description" in agent:
         | 
| 128 126 | 
             
                                print(f"   Description: {agent['description']}")
         | 
| 129 | 
            -
                            if  | 
| 127 | 
            +
                            if "version" in agent:
         | 
| 130 128 | 
             
                                print(f"   Version: {agent['version']}")
         | 
| 131 129 | 
             
                            print()
         | 
| 132 | 
            -
             | 
| 130 | 
            +
             | 
| 133 131 | 
             
                elif args.deployed:
         | 
| 134 132 | 
             
                    # List deployed agents
         | 
| 135 133 | 
             
                    print("Deployed Agents:")
         | 
| @@ -140,28 +138,30 @@ def _list_agents(args, deployment_service): | |
| 140 138 | 
             
                    else:
         | 
| 141 139 | 
             
                        for agent in verification["agents_found"]:
         | 
| 142 140 | 
             
                            print(f"📄 {agent['file']}")
         | 
| 143 | 
            -
                            if  | 
| 141 | 
            +
                            if "name" in agent:
         | 
| 144 142 | 
             
                                print(f"   Name: {agent['name']}")
         | 
| 145 143 | 
             
                            print(f"   Path: {agent['path']}")
         | 
| 146 144 | 
             
                            print()
         | 
| 147 | 
            -
             | 
| 145 | 
            +
             | 
| 148 146 | 
             
                    if verification["warnings"]:
         | 
| 149 147 | 
             
                        print("\nWarnings:")
         | 
| 150 148 | 
             
                        for warning in verification["warnings"]:
         | 
| 151 149 | 
             
                            print(f"  ⚠️  {warning}")
         | 
| 152 | 
            -
             | 
| 150 | 
            +
             | 
| 153 151 | 
             
                else:
         | 
| 154 152 | 
             
                    # Default: show usage
         | 
| 155 | 
            -
                    print( | 
| 153 | 
            +
                    print(
         | 
| 154 | 
            +
                        "Use --system to list system agents, --deployed to list deployed agents, or --by-tier to group by precedence"
         | 
| 155 | 
            +
                    )
         | 
| 156 156 |  | 
| 157 157 |  | 
| 158 158 | 
             
            def _deploy_agents(args, deployment_service, force=False):
         | 
| 159 159 | 
             
                """
         | 
| 160 160 | 
             
                Deploy both system and project agents.
         | 
| 161 | 
            -
             | 
| 161 | 
            +
             | 
| 162 162 | 
             
                WHY: Agents need to be deployed to the working directory for Claude Code to use them.
         | 
| 163 163 | 
             
                This function handles both regular and forced deployment, including project-specific agents.
         | 
| 164 | 
            -
             | 
| 164 | 
            +
             | 
| 165 165 | 
             
                Args:
         | 
| 166 166 | 
             
                    args: Command arguments with optional 'target' path
         | 
| 167 167 | 
             
                    deployment_service: Agent deployment service instance
         | 
| @@ -169,97 +169,109 @@ def _deploy_agents(args, deployment_service, force=False): | |
| 169 169 | 
             
                """
         | 
| 170 170 | 
             
                # Load configuration to get exclusion settings
         | 
| 171 171 | 
             
                config = Config()
         | 
| 172 | 
            -
             | 
| 172 | 
            +
             | 
| 173 173 | 
             
                # Check if user wants to override exclusions
         | 
| 174 | 
            -
                if hasattr(args,  | 
| 174 | 
            +
                if hasattr(args, "include_all") and args.include_all:
         | 
| 175 175 | 
             
                    # Clear exclusion list if --include-all flag is set
         | 
| 176 | 
            -
                    config.set( | 
| 176 | 
            +
                    config.set("agent_deployment.excluded_agents", [])
         | 
| 177 177 | 
             
                    print("✅ Including all agents (exclusion configuration overridden)\n")
         | 
| 178 178 | 
             
                else:
         | 
| 179 | 
            -
                    excluded_agents = config.get( | 
| 180 | 
            -
             | 
| 179 | 
            +
                    excluded_agents = config.get("agent_deployment.excluded_agents", [])
         | 
| 180 | 
            +
             | 
| 181 181 | 
             
                    # Display exclusion information if agents are being excluded
         | 
| 182 182 | 
             
                    if excluded_agents:
         | 
| 183 183 | 
             
                        logger = get_logger("cli")
         | 
| 184 184 | 
             
                        logger.info(f"Configured agent exclusions: {excluded_agents}")
         | 
| 185 | 
            -
                        print( | 
| 186 | 
            -
             | 
| 185 | 
            +
                        print(
         | 
| 186 | 
            +
                            f"\n⚠️  Excluding agents from deployment: {', '.join(excluded_agents)}"
         | 
| 187 | 
            +
                        )
         | 
| 188 | 
            +
             | 
| 187 189 | 
             
                        # Warn if commonly used agents are being excluded
         | 
| 188 | 
            -
                        common_agents = { | 
| 190 | 
            +
                        common_agents = {"engineer", "qa", "security", "documentation"}
         | 
| 189 191 | 
             
                        excluded_common = set(a.lower() for a in excluded_agents) & common_agents
         | 
| 190 192 | 
             
                        if excluded_common:
         | 
| 191 | 
            -
                            print( | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 193 | 
            +
                            print(
         | 
| 194 | 
            +
                                f"⚠️  Warning: Common agents are being excluded: {', '.join(excluded_common)}"
         | 
| 195 | 
            +
                            )
         | 
| 196 | 
            +
                            print(
         | 
| 197 | 
            +
                                "   This may affect normal operations. Use 'claude-mpm agents deploy --include-all' to override.\n"
         | 
| 198 | 
            +
                            )
         | 
| 199 | 
            +
             | 
| 194 200 | 
             
                # Deploy system agents first
         | 
| 195 201 | 
             
                if force:
         | 
| 196 202 | 
             
                    print("Force deploying all system agents...")
         | 
| 197 203 | 
             
                else:
         | 
| 198 204 | 
             
                    print("Deploying system agents...")
         | 
| 199 | 
            -
             | 
| 200 | 
            -
                # Pass configuration to deployment service
         | 
| 201 | 
            -
                # Don't pass args.target for system agents - let the service determine the correct path
         | 
| 202 | 
            -
                # based on whether it's system, user, or project agents
         | 
| 205 | 
            +
             | 
| 203 206 | 
             
                results = deployment_service.deploy_agents(None, force_rebuild=force, config=config)
         | 
| 204 | 
            -
             | 
| 207 | 
            +
             | 
| 205 208 | 
             
                # Also deploy project agents if they exist
         | 
| 206 | 
            -
                from pathlib import Path
         | 
| 207 209 | 
             
                import os
         | 
| 208 | 
            -
                
         | 
| 210 | 
            +
                from pathlib import Path
         | 
| 211 | 
            +
             | 
| 209 212 | 
             
                # Use the user's working directory if available
         | 
| 210 | 
            -
                if  | 
| 211 | 
            -
                    project_dir = Path(os.environ[ | 
| 213 | 
            +
                if "CLAUDE_MPM_USER_PWD" in os.environ:
         | 
| 214 | 
            +
                    project_dir = Path(os.environ["CLAUDE_MPM_USER_PWD"])
         | 
| 212 215 | 
             
                else:
         | 
| 213 216 | 
             
                    project_dir = Path.cwd()
         | 
| 214 | 
            -
             | 
| 215 | 
            -
                project_agents_dir = project_dir /  | 
| 217 | 
            +
             | 
| 218 | 
            +
                project_agents_dir = project_dir / ".claude-mpm" / "agents"
         | 
| 216 219 | 
             
                if project_agents_dir.exists():
         | 
| 217 | 
            -
                    json_files = list(project_agents_dir.glob( | 
| 220 | 
            +
                    json_files = list(project_agents_dir.glob("*.json"))
         | 
| 218 221 | 
             
                    if json_files:
         | 
| 219 222 | 
             
                        print(f"\nDeploying {len(json_files)} project agents...")
         | 
| 220 | 
            -
                        from claude_mpm.services.agents.deployment.agent_deployment import  | 
| 223 | 
            +
                        from claude_mpm.services.agents.deployment.agent_deployment import (
         | 
| 224 | 
            +
                            AgentDeploymentService,
         | 
| 225 | 
            +
                        )
         | 
| 226 | 
            +
             | 
| 221 227 | 
             
                        project_service = AgentDeploymentService(
         | 
| 222 228 | 
             
                            templates_dir=project_agents_dir,
         | 
| 223 | 
            -
                            base_agent_path= | 
| 224 | 
            -
             | 
| 229 | 
            +
                            base_agent_path=(
         | 
| 230 | 
            +
                                project_agents_dir / "base_agent.json"
         | 
| 231 | 
            +
                                if (project_agents_dir / "base_agent.json").exists()
         | 
| 232 | 
            +
                                else None
         | 
| 233 | 
            +
                            ),
         | 
| 234 | 
            +
                            working_directory=project_dir,  # Pass the project directory
         | 
| 225 235 | 
             
                        )
         | 
| 226 236 | 
             
                        # Pass the same configuration to project agent deployment
         | 
| 227 237 | 
             
                        # For project agents, let the service determine they should stay in project directory
         | 
| 228 238 | 
             
                        project_results = project_service.deploy_agents(
         | 
| 229 239 | 
             
                            target_dir=None,  # Let service detect it's a project deployment
         | 
| 230 240 | 
             
                            force_rebuild=force,
         | 
| 231 | 
            -
                            deployment_mode= | 
| 232 | 
            -
                            config=config
         | 
| 241 | 
            +
                            deployment_mode="project",
         | 
| 242 | 
            +
                            config=config,
         | 
| 233 243 | 
             
                        )
         | 
| 234 | 
            -
             | 
| 244 | 
            +
             | 
| 235 245 | 
             
                        # Merge project results into main results
         | 
| 236 | 
            -
                        if project_results.get( | 
| 237 | 
            -
                            results[ | 
| 246 | 
            +
                        if project_results.get("deployed"):
         | 
| 247 | 
            +
                            results["deployed"].extend(project_results["deployed"])
         | 
| 238 248 | 
             
                            print(f"✓ Deployed {len(project_results['deployed'])} project agents")
         | 
| 239 | 
            -
                        if project_results.get( | 
| 240 | 
            -
                            results[ | 
| 249 | 
            +
                        if project_results.get("updated"):
         | 
| 250 | 
            +
                            results["updated"].extend(project_results["updated"])
         | 
| 241 251 | 
             
                            print(f"✓ Updated {len(project_results['updated'])} project agents")
         | 
| 242 | 
            -
                        if project_results.get( | 
| 243 | 
            -
                            results[ | 
| 244 | 
            -
             | 
| 252 | 
            +
                        if project_results.get("errors"):
         | 
| 253 | 
            +
                            results["errors"].extend(project_results["errors"])
         | 
| 254 | 
            +
             | 
| 245 255 | 
             
                if results["deployed"]:
         | 
| 246 | 
            -
                    print( | 
| 256 | 
            +
                    print(
         | 
| 257 | 
            +
                        f"\n✓ Successfully deployed {len(results['deployed'])} agents to {results['target_dir']}"
         | 
| 258 | 
            +
                    )
         | 
| 247 259 | 
             
                    for agent in results["deployed"]:
         | 
| 248 260 | 
             
                        print(f"  - {agent['name']}")
         | 
| 249 | 
            -
             | 
| 261 | 
            +
             | 
| 250 262 | 
             
                if force and results.get("updated", []):
         | 
| 251 263 | 
             
                    print(f"\n✓ Updated {len(results['updated'])} agents")
         | 
| 252 264 | 
             
                    for agent in results["updated"]:
         | 
| 253 265 | 
             
                        print(f"  - {agent['name']}")
         | 
| 254 | 
            -
             | 
| 266 | 
            +
             | 
| 255 267 | 
             
                if force and results.get("skipped", []):
         | 
| 256 268 | 
             
                    print(f"\n✓ Skipped {len(results['skipped'])} up-to-date agents")
         | 
| 257 | 
            -
             | 
| 269 | 
            +
             | 
| 258 270 | 
             
                if results["errors"]:
         | 
| 259 271 | 
             
                    print("\n❌ Errors during deployment:")
         | 
| 260 272 | 
             
                    for error in results["errors"]:
         | 
| 261 273 | 
             
                        print(f"  - {error}")
         | 
| 262 | 
            -
             | 
| 274 | 
            +
             | 
| 263 275 | 
             
                if force:
         | 
| 264 276 | 
             
                    # Set environment for force deploy
         | 
| 265 277 | 
             
                    env_vars = deployment_service.set_claude_environment(
         | 
| @@ -273,24 +285,24 @@ def _deploy_agents(args, deployment_service, force=False): | |
| 273 285 | 
             
            def _clean_agents(args, deployment_service):
         | 
| 274 286 | 
             
                """
         | 
| 275 287 | 
             
                Clean deployed system agents.
         | 
| 276 | 
            -
             | 
| 288 | 
            +
             | 
| 277 289 | 
             
                WHY: Users may want to remove deployed agents to start fresh or clean up
         | 
| 278 290 | 
             
                their working directory.
         | 
| 279 | 
            -
             | 
| 291 | 
            +
             | 
| 280 292 | 
             
                Args:
         | 
| 281 293 | 
             
                    args: Command arguments with optional 'target' path
         | 
| 282 294 | 
             
                    deployment_service: Agent deployment service instance
         | 
| 283 295 | 
             
                """
         | 
| 284 296 | 
             
                print("Cleaning deployed system agents...")
         | 
| 285 297 | 
             
                results = deployment_service.clean_deployment(args.target)
         | 
| 286 | 
            -
             | 
| 298 | 
            +
             | 
| 287 299 | 
             
                if results["removed"]:
         | 
| 288 300 | 
             
                    print(f"\n✓ Removed {len(results['removed'])} agents")
         | 
| 289 301 | 
             
                    for path in results["removed"]:
         | 
| 290 302 | 
             
                        print(f"  - {Path(path).name}")
         | 
| 291 303 | 
             
                else:
         | 
| 292 304 | 
             
                    print("No system agents found to remove")
         | 
| 293 | 
            -
             | 
| 305 | 
            +
             | 
| 294 306 | 
             
                if results["errors"]:
         | 
| 295 307 | 
             
                    print("\n❌ Errors during cleanup:")
         | 
| 296 308 | 
             
                    for error in results["errors"]:
         | 
| @@ -300,7 +312,7 @@ def _clean_agents(args, deployment_service): | |
| 300 312 | 
             
            def _list_agents_by_tier():
         | 
| 301 313 | 
             
                """
         | 
| 302 314 | 
             
                List agents grouped by precedence tier.
         | 
| 303 | 
            -
             | 
| 315 | 
            +
             | 
| 304 316 | 
             
                WHY: Users need to understand which agents are active across different tiers
         | 
| 305 317 | 
             
                and which version takes precedence when multiple versions exist.
         | 
| 306 318 | 
             
                """
         | 
| @@ -309,71 +321,75 @@ def _list_agents_by_tier(): | |
| 309 321 | 
             
                    if not adapter.registry:
         | 
| 310 322 | 
             
                        print("❌ Could not initialize agent registry")
         | 
| 311 323 | 
             
                        return
         | 
| 312 | 
            -
             | 
| 324 | 
            +
             | 
| 313 325 | 
             
                    # Get all agents and group by tier
         | 
| 314 326 | 
             
                    all_agents = adapter.registry.list_agents()
         | 
| 315 | 
            -
             | 
| 327 | 
            +
             | 
| 316 328 | 
             
                    # Group agents by tier and name
         | 
| 317 | 
            -
                    tiers = { | 
| 329 | 
            +
                    tiers = {"project": {}, "user": {}, "system": {}}
         | 
| 318 330 | 
             
                    agent_names = set()
         | 
| 319 | 
            -
             | 
| 331 | 
            +
             | 
| 320 332 | 
             
                    for agent_id, metadata in all_agents.items():
         | 
| 321 | 
            -
                        tier = metadata.get( | 
| 333 | 
            +
                        tier = metadata.get("tier", "system")
         | 
| 322 334 | 
             
                        if tier in tiers:
         | 
| 323 335 | 
             
                            tiers[tier][agent_id] = metadata
         | 
| 324 336 | 
             
                            agent_names.add(agent_id)
         | 
| 325 | 
            -
             | 
| 337 | 
            +
             | 
| 326 338 | 
             
                    # Display header
         | 
| 327 339 | 
             
                    print("\n" + "=" * 80)
         | 
| 328 340 | 
             
                    print(" " * 25 + "AGENT HIERARCHY BY TIER")
         | 
| 329 341 | 
             
                    print("=" * 80)
         | 
| 330 342 | 
             
                    print("\nPrecedence: PROJECT > USER > SYSTEM")
         | 
| 331 343 | 
             
                    print("(Agents in higher tiers override those in lower tiers)\n")
         | 
| 332 | 
            -
             | 
| 344 | 
            +
             | 
| 333 345 | 
             
                    # Display each tier
         | 
| 334 | 
            -
                    tier_order = [( | 
| 335 | 
            -
             | 
| 346 | 
            +
                    tier_order = [("PROJECT", "project"), ("USER", "user"), ("SYSTEM", "system")]
         | 
| 347 | 
            +
             | 
| 336 348 | 
             
                    for tier_display, tier_key in tier_order:
         | 
| 337 349 | 
             
                        agents = tiers[tier_key]
         | 
| 338 350 | 
             
                        print(f"\n{'─' * 35} {tier_display} TIER {'─' * 35}")
         | 
| 339 | 
            -
             | 
| 351 | 
            +
             | 
| 340 352 | 
             
                        if not agents:
         | 
| 341 353 | 
             
                            print(f"  No agents at {tier_key} level")
         | 
| 342 354 | 
             
                        else:
         | 
| 343 355 | 
             
                            # Check paths to determine actual locations
         | 
| 344 | 
            -
                            if tier_key ==  | 
| 356 | 
            +
                            if tier_key == "project":
         | 
| 345 357 | 
             
                                print(f"  Location: .claude-mpm/agents/ (in current project)")
         | 
| 346 | 
            -
                            elif tier_key ==  | 
| 358 | 
            +
                            elif tier_key == "user":
         | 
| 347 359 | 
             
                                print(f"  Location: ~/.claude-mpm/agents/")
         | 
| 348 360 | 
             
                            else:
         | 
| 349 361 | 
             
                                print(f"  Location: Built-in framework agents")
         | 
| 350 | 
            -
             | 
| 362 | 
            +
             | 
| 351 363 | 
             
                            print(f"\n  Found {len(agents)} agent(s):\n")
         | 
| 352 | 
            -
             | 
| 364 | 
            +
             | 
| 353 365 | 
             
                            for agent_id, metadata in sorted(agents.items()):
         | 
| 354 366 | 
             
                                # Check if this agent is overridden by higher tiers
         | 
| 355 367 | 
             
                                is_active = True
         | 
| 356 368 | 
             
                                overridden_by = []
         | 
| 357 | 
            -
             | 
| 369 | 
            +
             | 
| 358 370 | 
             
                                for check_tier_display, check_tier_key in tier_order:
         | 
| 359 371 | 
             
                                    if check_tier_key == tier_key:
         | 
| 360 372 | 
             
                                        break
         | 
| 361 373 | 
             
                                    if agent_id in tiers[check_tier_key]:
         | 
| 362 374 | 
             
                                        is_active = False
         | 
| 363 375 | 
             
                                        overridden_by.append(check_tier_display)
         | 
| 364 | 
            -
             | 
| 376 | 
            +
             | 
| 365 377 | 
             
                                # Display agent info
         | 
| 366 | 
            -
                                status =  | 
| 378 | 
            +
                                status = (
         | 
| 379 | 
            +
                                    "✓ ACTIVE"
         | 
| 380 | 
            +
                                    if is_active
         | 
| 381 | 
            +
                                    else f"⊗ OVERRIDDEN by {', '.join(overridden_by)}"
         | 
| 382 | 
            +
                                )
         | 
| 367 383 | 
             
                                print(f"    📄 {agent_id:<20} [{status}]")
         | 
| 368 | 
            -
             | 
| 384 | 
            +
             | 
| 369 385 | 
             
                                # Show metadata
         | 
| 370 | 
            -
                                if  | 
| 386 | 
            +
                                if "description" in metadata:
         | 
| 371 387 | 
             
                                    print(f"       Description: {metadata['description']}")
         | 
| 372 | 
            -
                                if  | 
| 373 | 
            -
                                    path = Path(metadata[ | 
| 388 | 
            +
                                if "path" in metadata:
         | 
| 389 | 
            +
                                    path = Path(metadata["path"])
         | 
| 374 390 | 
             
                                    print(f"       File: {path.name}")
         | 
| 375 391 | 
             
                                print()
         | 
| 376 | 
            -
             | 
| 392 | 
            +
             | 
| 377 393 | 
             
                    # Summary
         | 
| 378 394 | 
             
                    print("\n" + "=" * 80)
         | 
| 379 395 | 
             
                    print("SUMMARY:")
         | 
| @@ -382,7 +398,7 @@ def _list_agents_by_tier(): | |
| 382 398 | 
             
                    print(f"  User agents: {len(tiers['user'])}")
         | 
| 383 399 | 
             
                    print(f"  System agents: {len(tiers['system'])}")
         | 
| 384 400 | 
             
                    print("=" * 80 + "\n")
         | 
| 385 | 
            -
             | 
| 401 | 
            +
             | 
| 386 402 | 
             
                except Exception as e:
         | 
| 387 403 | 
             
                    print(f"❌ Error listing agents by tier: {e}")
         | 
| 388 404 |  | 
| @@ -390,24 +406,24 @@ def _list_agents_by_tier(): | |
| 390 406 | 
             
            def _view_agent(args):
         | 
| 391 407 | 
             
                """
         | 
| 392 408 | 
             
                View detailed information about a specific agent.
         | 
| 393 | 
            -
             | 
| 409 | 
            +
             | 
| 394 410 | 
             
                WHY: Users need to inspect agent configurations, frontmatter, and instructions
         | 
| 395 411 | 
             
                to understand what an agent does and how it's configured.
         | 
| 396 | 
            -
             | 
| 412 | 
            +
             | 
| 397 413 | 
             
                Args:
         | 
| 398 414 | 
             
                    args: Command arguments with 'agent_name' attribute
         | 
| 399 415 | 
             
                """
         | 
| 400 | 
            -
                if not hasattr(args,  | 
| 416 | 
            +
                if not hasattr(args, "agent_name") or not args.agent_name:
         | 
| 401 417 | 
             
                    print("❌ Please specify an agent name to view")
         | 
| 402 418 | 
             
                    print("Usage: claude-mpm agents view <agent_name>")
         | 
| 403 419 | 
             
                    return
         | 
| 404 | 
            -
             | 
| 420 | 
            +
             | 
| 405 421 | 
             
                try:
         | 
| 406 422 | 
             
                    adapter = AgentRegistryAdapter()
         | 
| 407 423 | 
             
                    if not adapter.registry:
         | 
| 408 424 | 
             
                        print("❌ Could not initialize agent registry")
         | 
| 409 425 | 
             
                        return
         | 
| 410 | 
            -
             | 
| 426 | 
            +
             | 
| 411 427 | 
             
                    # Get the agent
         | 
| 412 428 | 
             
                    agent = adapter.registry.get_agent(args.agent_name)
         | 
| 413 429 | 
             
                    if not agent:
         | 
| @@ -417,21 +433,21 @@ def _view_agent(args): | |
| 417 433 | 
             
                        for agent_id in sorted(all_agents.keys()):
         | 
| 418 434 | 
             
                            print(f"  - {agent_id}")
         | 
| 419 435 | 
             
                        return
         | 
| 420 | 
            -
             | 
| 436 | 
            +
             | 
| 421 437 | 
             
                    # Read the agent file
         | 
| 422 438 | 
             
                    agent_path = Path(agent.path)
         | 
| 423 439 | 
             
                    if not agent_path.exists():
         | 
| 424 440 | 
             
                        print(f"❌ Agent file not found: {agent_path}")
         | 
| 425 441 | 
             
                        return
         | 
| 426 | 
            -
             | 
| 427 | 
            -
                    with open(agent_path,  | 
| 442 | 
            +
             | 
| 443 | 
            +
                    with open(agent_path, "r") as f:
         | 
| 428 444 | 
             
                        content = f.read()
         | 
| 429 | 
            -
             | 
| 445 | 
            +
             | 
| 430 446 | 
             
                    # Display agent information
         | 
| 431 447 | 
             
                    print("\n" + "=" * 80)
         | 
| 432 448 | 
             
                    print(f" AGENT: {agent.name}")
         | 
| 433 449 | 
             
                    print("=" * 80)
         | 
| 434 | 
            -
             | 
| 450 | 
            +
             | 
| 435 451 | 
             
                    # Basic info
         | 
| 436 452 | 
             
                    print(f"\n📋 BASIC INFORMATION:")
         | 
| 437 453 | 
             
                    print(f"  Name: {agent.name}")
         | 
| @@ -442,18 +458,18 @@ def _view_agent(args): | |
| 442 458 | 
             
                        print(f"  Description: {agent.description}")
         | 
| 443 459 | 
             
                    if agent.specializations:
         | 
| 444 460 | 
             
                        print(f"  Specializations: {', '.join(agent.specializations)}")
         | 
| 445 | 
            -
             | 
| 461 | 
            +
             | 
| 446 462 | 
             
                    # Extract and display frontmatter
         | 
| 447 463 | 
             
                    if content.startswith("---"):
         | 
| 448 464 | 
             
                        try:
         | 
| 449 465 | 
             
                            end_marker = content.find("\n---\n", 4)
         | 
| 450 466 | 
             
                            if end_marker == -1:
         | 
| 451 467 | 
             
                                end_marker = content.find("\n---\r\n", 4)
         | 
| 452 | 
            -
             | 
| 468 | 
            +
             | 
| 453 469 | 
             
                            if end_marker != -1:
         | 
| 454 470 | 
             
                                frontmatter_str = content[4:end_marker]
         | 
| 455 471 | 
             
                                frontmatter = yaml.safe_load(frontmatter_str)
         | 
| 456 | 
            -
             | 
| 472 | 
            +
             | 
| 457 473 | 
             
                                print(f"\n📝 FRONTMATTER:")
         | 
| 458 474 | 
             
                                for key, value in frontmatter.items():
         | 
| 459 475 | 
             
                                    if isinstance(value, list):
         | 
| @@ -464,37 +480,41 @@ def _view_agent(args): | |
| 464 480 | 
             
                                            print(f"    {k}: {v}")
         | 
| 465 481 | 
             
                                    else:
         | 
| 466 482 | 
             
                                        print(f"  {key}: {value}")
         | 
| 467 | 
            -
             | 
| 483 | 
            +
             | 
| 468 484 | 
             
                                # Extract instructions preview
         | 
| 469 485 | 
             
                                instructions_start = end_marker + 5
         | 
| 470 486 | 
             
                                instructions = content[instructions_start:].strip()
         | 
| 471 | 
            -
             | 
| 487 | 
            +
             | 
| 472 488 | 
             
                                if instructions:
         | 
| 473 489 | 
             
                                    print(f"\n📖 INSTRUCTIONS PREVIEW (first 500 chars):")
         | 
| 474 490 | 
             
                                    print("  " + "-" * 76)
         | 
| 475 491 | 
             
                                    preview = instructions[:500]
         | 
| 476 492 | 
             
                                    if len(instructions) > 500:
         | 
| 477 | 
            -
                                        preview += "...\n\n  [Truncated - {:.1f}KB total]".format( | 
| 478 | 
            -
             | 
| 479 | 
            -
             | 
| 493 | 
            +
                                        preview += "...\n\n  [Truncated - {:.1f}KB total]".format(
         | 
| 494 | 
            +
                                            len(instructions) / 1024
         | 
| 495 | 
            +
                                        )
         | 
| 496 | 
            +
             | 
| 497 | 
            +
                                    for line in preview.split("\n"):
         | 
| 480 498 | 
             
                                        print(f"  {line}")
         | 
| 481 499 | 
             
                                    print("  " + "-" * 76)
         | 
| 482 500 | 
             
                        except Exception as e:
         | 
| 483 501 | 
             
                            print(f"\n⚠️  Could not parse frontmatter: {e}")
         | 
| 484 502 | 
             
                    else:
         | 
| 485 503 | 
             
                        print(f"\n⚠️  No frontmatter found in agent file")
         | 
| 486 | 
            -
             | 
| 504 | 
            +
             | 
| 487 505 | 
             
                    # File stats
         | 
| 488 506 | 
             
                    import os
         | 
| 507 | 
            +
             | 
| 489 508 | 
             
                    stat = os.stat(agent_path)
         | 
| 490 509 | 
             
                    from datetime import datetime
         | 
| 510 | 
            +
             | 
| 491 511 | 
             
                    modified = datetime.fromtimestamp(stat.st_mtime).strftime("%Y-%m-%d %H:%M:%S")
         | 
| 492 512 | 
             
                    print(f"\n📊 FILE STATS:")
         | 
| 493 513 | 
             
                    print(f"  Size: {stat.st_size:,} bytes")
         | 
| 494 514 | 
             
                    print(f"  Last modified: {modified}")
         | 
| 495 | 
            -
             | 
| 515 | 
            +
             | 
| 496 516 | 
             
                    print("\n" + "=" * 80 + "\n")
         | 
| 497 | 
            -
             | 
| 517 | 
            +
             | 
| 498 518 | 
             
                except Exception as e:
         | 
| 499 519 | 
             
                    print(f"❌ Error viewing agent: {e}")
         | 
| 500 520 |  | 
| @@ -502,31 +522,33 @@ def _view_agent(args): | |
| 502 522 | 
             
            def _fix_agents(args):
         | 
| 503 523 | 
             
                """
         | 
| 504 524 | 
             
                Fix agent frontmatter issues using FrontmatterValidator.
         | 
| 505 | 
            -
             | 
| 525 | 
            +
             | 
| 506 526 | 
             
                WHY: Agent files may have formatting issues in their frontmatter that prevent
         | 
| 507 527 | 
             
                proper loading. This command automatically fixes common issues.
         | 
| 508 | 
            -
             | 
| 528 | 
            +
             | 
| 509 529 | 
             
                Args:
         | 
| 510 530 | 
             
                    args: Command arguments with 'agent_name', 'dry_run', and 'all' flags
         | 
| 511 531 | 
             
                """
         | 
| 512 532 | 
             
                validator = FrontmatterValidator()
         | 
| 513 | 
            -
             | 
| 533 | 
            +
             | 
| 514 534 | 
             
                try:
         | 
| 515 535 | 
             
                    adapter = AgentRegistryAdapter()
         | 
| 516 536 | 
             
                    if not adapter.registry:
         | 
| 517 537 | 
             
                        print("❌ Could not initialize agent registry")
         | 
| 518 538 | 
             
                        return
         | 
| 519 | 
            -
             | 
| 539 | 
            +
             | 
| 520 540 | 
             
                    # Determine which agents to fix
         | 
| 521 541 | 
             
                    agents_to_fix = []
         | 
| 522 | 
            -
             | 
| 523 | 
            -
                    if hasattr(args,  | 
| 542 | 
            +
             | 
| 543 | 
            +
                    if hasattr(args, "all") and args.all:
         | 
| 524 544 | 
             
                        # Fix all agents
         | 
| 525 545 | 
             
                        all_agents = adapter.registry.list_agents()
         | 
| 526 546 | 
             
                        for agent_id, metadata in all_agents.items():
         | 
| 527 | 
            -
                            agents_to_fix.append((agent_id, metadata[ | 
| 528 | 
            -
                        print( | 
| 529 | 
            -
             | 
| 547 | 
            +
                            agents_to_fix.append((agent_id, metadata["path"]))
         | 
| 548 | 
            +
                        print(
         | 
| 549 | 
            +
                            f"\n🔧 Checking {len(agents_to_fix)} agent(s) for frontmatter issues...\n"
         | 
| 550 | 
            +
                        )
         | 
| 551 | 
            +
                    elif hasattr(args, "agent_name") and args.agent_name:
         | 
| 530 552 | 
             
                        # Fix specific agent
         | 
| 531 553 | 
             
                        agent = adapter.registry.get_agent(args.agent_name)
         | 
| 532 554 | 
             
                        if not agent:
         | 
| @@ -538,26 +560,26 @@ def _fix_agents(args): | |
| 538 560 | 
             
                        print("❌ Please specify an agent name or use --all to fix all agents")
         | 
| 539 561 | 
             
                        print("Usage: claude-mpm agents fix [agent_name] [--dry-run] [--all]")
         | 
| 540 562 | 
             
                        return
         | 
| 541 | 
            -
             | 
| 542 | 
            -
                    dry_run = hasattr(args,  | 
| 563 | 
            +
             | 
| 564 | 
            +
                    dry_run = hasattr(args, "dry_run") and args.dry_run
         | 
| 543 565 | 
             
                    if dry_run:
         | 
| 544 566 | 
             
                        print("🔍 DRY RUN MODE - No changes will be made\n")
         | 
| 545 | 
            -
             | 
| 567 | 
            +
             | 
| 546 568 | 
             
                    # Process each agent
         | 
| 547 569 | 
             
                    total_issues = 0
         | 
| 548 570 | 
             
                    total_fixed = 0
         | 
| 549 | 
            -
             | 
| 571 | 
            +
             | 
| 550 572 | 
             
                    for agent_name, agent_path in agents_to_fix:
         | 
| 551 573 | 
             
                        path = Path(agent_path)
         | 
| 552 574 | 
             
                        if not path.exists():
         | 
| 553 575 | 
             
                            print(f"⚠️  Skipping {agent_name}: File not found at {path}")
         | 
| 554 576 | 
             
                            continue
         | 
| 555 | 
            -
             | 
| 577 | 
            +
             | 
| 556 578 | 
             
                        print(f"📄 {agent_name}:")
         | 
| 557 | 
            -
             | 
| 579 | 
            +
             | 
| 558 580 | 
             
                        # Validate and potentially fix
         | 
| 559 581 | 
             
                        result = validator.correct_file(path, dry_run=dry_run)
         | 
| 560 | 
            -
             | 
| 582 | 
            +
             | 
| 561 583 | 
             
                        if result.is_valid and not result.corrections:
         | 
| 562 584 | 
             
                            print("  ✓ No issues found")
         | 
| 563 585 | 
             
                        else:
         | 
| @@ -566,13 +588,13 @@ def _fix_agents(args): | |
| 566 588 | 
             
                                for error in result.errors:
         | 
| 567 589 | 
             
                                    print(f"    - {error}")
         | 
| 568 590 | 
             
                                total_issues += len(result.errors)
         | 
| 569 | 
            -
             | 
| 591 | 
            +
             | 
| 570 592 | 
             
                            if result.warnings:
         | 
| 571 593 | 
             
                                print("  ⚠️  Warnings:")
         | 
| 572 594 | 
             
                                for warning in result.warnings:
         | 
| 573 595 | 
             
                                    print(f"    - {warning}")
         | 
| 574 596 | 
             
                                total_issues += len(result.warnings)
         | 
| 575 | 
            -
             | 
| 597 | 
            +
             | 
| 576 598 | 
             
                            if result.corrections:
         | 
| 577 599 | 
             
                                if dry_run:
         | 
| 578 600 | 
             
                                    print("  🔧 Would fix:")
         | 
| @@ -581,23 +603,25 @@ def _fix_agents(args): | |
| 581 603 | 
             
                                    total_fixed += len(result.corrections)
         | 
| 582 604 | 
             
                                for correction in result.corrections:
         | 
| 583 605 | 
             
                                    print(f"    - {correction}")
         | 
| 584 | 
            -
             | 
| 606 | 
            +
             | 
| 585 607 | 
             
                        print()
         | 
| 586 | 
            -
             | 
| 608 | 
            +
             | 
| 587 609 | 
             
                    # Summary
         | 
| 588 610 | 
             
                    print("=" * 80)
         | 
| 589 611 | 
             
                    print("SUMMARY:")
         | 
| 590 612 | 
             
                    print(f"  Agents checked: {len(agents_to_fix)}")
         | 
| 591 613 | 
             
                    print(f"  Total issues found: {total_issues}")
         | 
| 592 614 | 
             
                    if dry_run:
         | 
| 593 | 
            -
                        print( | 
| 615 | 
            +
                        print(
         | 
| 616 | 
            +
                            f"  Issues that would be fixed: {sum(1 for _, path in agents_to_fix if validator.validate_file(Path(path)).corrections)}"
         | 
| 617 | 
            +
                        )
         | 
| 594 618 | 
             
                        print("\n💡 Run without --dry-run to apply fixes")
         | 
| 595 619 | 
             
                    else:
         | 
| 596 620 | 
             
                        print(f"  Issues fixed: {total_fixed}")
         | 
| 597 621 | 
             
                        if total_fixed > 0:
         | 
| 598 622 | 
             
                            print("\n✓ Frontmatter issues have been fixed!")
         | 
| 599 623 | 
             
                    print("=" * 80 + "\n")
         | 
| 600 | 
            -
             | 
| 624 | 
            +
             | 
| 601 625 | 
             
                except Exception as e:
         | 
| 602 626 | 
             
                    print(f"❌ Error fixing agents: {e}")
         | 
| 603 627 |  | 
| @@ -605,20 +629,20 @@ def _fix_agents(args): | |
| 605 629 | 
             
            def _check_agent_dependencies(args):
         | 
| 606 630 | 
             
                """
         | 
| 607 631 | 
             
                Check dependencies for deployed agents.
         | 
| 608 | 
            -
             | 
| 632 | 
            +
             | 
| 609 633 | 
             
                Args:
         | 
| 610 634 | 
             
                    args: Parsed command line arguments
         | 
| 611 635 | 
             
                """
         | 
| 612 636 | 
             
                from ...utils.agent_dependency_loader import AgentDependencyLoader
         | 
| 613 | 
            -
             | 
| 614 | 
            -
                verbose = getattr(args,  | 
| 615 | 
            -
                specific_agent = getattr(args,  | 
| 616 | 
            -
             | 
| 637 | 
            +
             | 
| 638 | 
            +
                verbose = getattr(args, "verbose", False)
         | 
| 639 | 
            +
                specific_agent = getattr(args, "agent", None)
         | 
| 640 | 
            +
             | 
| 617 641 | 
             
                loader = AgentDependencyLoader(auto_install=False)
         | 
| 618 | 
            -
             | 
| 642 | 
            +
             | 
| 619 643 | 
             
                # Discover deployed agents
         | 
| 620 644 | 
             
                loader.discover_deployed_agents()
         | 
| 621 | 
            -
             | 
| 645 | 
            +
             | 
| 622 646 | 
             
                # Filter to specific agent if requested
         | 
| 623 647 | 
             
                if specific_agent:
         | 
| 624 648 | 
             
                    if specific_agent not in loader.deployed_agents:
         | 
| @@ -626,12 +650,14 @@ def _check_agent_dependencies(args): | |
| 626 650 | 
             
                        print(f"   Available agents: {', '.join(loader.deployed_agents.keys())}")
         | 
| 627 651 | 
             
                        return
         | 
| 628 652 | 
             
                    # Keep only the specified agent
         | 
| 629 | 
            -
                    loader.deployed_agents = { | 
| 630 | 
            -
             | 
| 653 | 
            +
                    loader.deployed_agents = {
         | 
| 654 | 
            +
                        specific_agent: loader.deployed_agents[specific_agent]
         | 
| 655 | 
            +
                    }
         | 
| 656 | 
            +
             | 
| 631 657 | 
             
                # Load dependencies and check
         | 
| 632 658 | 
             
                loader.load_agent_dependencies()
         | 
| 633 659 | 
             
                results = loader.analyze_dependencies()
         | 
| 634 | 
            -
             | 
| 660 | 
            +
             | 
| 635 661 | 
             
                # Print report
         | 
| 636 662 | 
             
                report = loader.format_report(results)
         | 
| 637 663 | 
             
                print(report)
         | 
| @@ -640,59 +666,64 @@ def _check_agent_dependencies(args): | |
| 640 666 | 
             
            def _install_agent_dependencies(args):
         | 
| 641 667 | 
             
                """
         | 
| 642 668 | 
             
                Install missing dependencies for deployed agents.
         | 
| 643 | 
            -
             | 
| 669 | 
            +
             | 
| 644 670 | 
             
                Args:
         | 
| 645 671 | 
             
                    args: Parsed command line arguments
         | 
| 646 672 | 
             
                """
         | 
| 647 | 
            -
                from ...utils.agent_dependency_loader import AgentDependencyLoader
         | 
| 648 673 | 
             
                import sys
         | 
| 649 | 
            -
             | 
| 650 | 
            -
                 | 
| 651 | 
            -
             | 
| 652 | 
            -
                
         | 
| 674 | 
            +
             | 
| 675 | 
            +
                from ...utils.agent_dependency_loader import AgentDependencyLoader
         | 
| 676 | 
            +
             | 
| 677 | 
            +
                specific_agent = getattr(args, "agent", None)
         | 
| 678 | 
            +
                dry_run = getattr(args, "dry_run", False)
         | 
| 679 | 
            +
             | 
| 653 680 | 
             
                loader = AgentDependencyLoader(auto_install=not dry_run)
         | 
| 654 | 
            -
             | 
| 681 | 
            +
             | 
| 655 682 | 
             
                # Discover deployed agents
         | 
| 656 683 | 
             
                loader.discover_deployed_agents()
         | 
| 657 | 
            -
             | 
| 684 | 
            +
             | 
| 658 685 | 
             
                # Filter to specific agent if requested
         | 
| 659 686 | 
             
                if specific_agent:
         | 
| 660 687 | 
             
                    if specific_agent not in loader.deployed_agents:
         | 
| 661 688 | 
             
                        print(f"❌ Agent '{specific_agent}' is not deployed")
         | 
| 662 689 | 
             
                        print(f"   Available agents: {', '.join(loader.deployed_agents.keys())}")
         | 
| 663 690 | 
             
                        return
         | 
| 664 | 
            -
                    loader.deployed_agents = { | 
| 665 | 
            -
             | 
| 691 | 
            +
                    loader.deployed_agents = {
         | 
| 692 | 
            +
                        specific_agent: loader.deployed_agents[specific_agent]
         | 
| 693 | 
            +
                    }
         | 
| 694 | 
            +
             | 
| 666 695 | 
             
                # Load dependencies
         | 
| 667 696 | 
             
                loader.load_agent_dependencies()
         | 
| 668 697 | 
             
                results = loader.analyze_dependencies()
         | 
| 669 | 
            -
             | 
| 670 | 
            -
                missing_deps = results[ | 
| 671 | 
            -
             | 
| 698 | 
            +
             | 
| 699 | 
            +
                missing_deps = results["summary"]["missing_python"]
         | 
| 700 | 
            +
             | 
| 672 701 | 
             
                if not missing_deps:
         | 
| 673 702 | 
             
                    print("✅ All Python dependencies are already installed")
         | 
| 674 703 | 
             
                    return
         | 
| 675 | 
            -
             | 
| 704 | 
            +
             | 
| 676 705 | 
             
                print(f"Found {len(missing_deps)} missing dependencies:")
         | 
| 677 706 | 
             
                for dep in missing_deps:
         | 
| 678 707 | 
             
                    print(f"  - {dep}")
         | 
| 679 | 
            -
             | 
| 708 | 
            +
             | 
| 680 709 | 
             
                if dry_run:
         | 
| 681 710 | 
             
                    print("\n--dry-run specified, not installing anything")
         | 
| 682 711 | 
             
                    print(f"Would install: pip install {' '.join(missing_deps)}")
         | 
| 683 712 | 
             
                else:
         | 
| 684 713 | 
             
                    print(f"\nInstalling {len(missing_deps)} dependencies...")
         | 
| 685 714 | 
             
                    success, error = loader.install_missing_dependencies(missing_deps)
         | 
| 686 | 
            -
             | 
| 715 | 
            +
             | 
| 687 716 | 
             
                    if success:
         | 
| 688 717 | 
             
                        print("✅ Successfully installed all dependencies")
         | 
| 689 | 
            -
             | 
| 718 | 
            +
             | 
| 690 719 | 
             
                        # Re-check after installation
         | 
| 691 720 | 
             
                        loader.checked_packages.clear()
         | 
| 692 721 | 
             
                        results = loader.analyze_dependencies()
         | 
| 693 | 
            -
             | 
| 694 | 
            -
                        if results[ | 
| 695 | 
            -
                            print( | 
| 722 | 
            +
             | 
| 723 | 
            +
                        if results["summary"]["missing_python"]:
         | 
| 724 | 
            +
                            print(
         | 
| 725 | 
            +
                                f"⚠️  {len(results['summary']['missing_python'])} dependencies still missing after installation"
         | 
| 726 | 
            +
                            )
         | 
| 696 727 | 
             
                        else:
         | 
| 697 728 | 
             
                            print("✅ All dependencies verified after installation")
         | 
| 698 729 | 
             
                    else:
         | 
| @@ -702,74 +733,75 @@ def _install_agent_dependencies(args): | |
| 702 733 | 
             
            def _list_agent_dependencies(args):
         | 
| 703 734 | 
             
                """
         | 
| 704 735 | 
             
                List all dependencies from deployed agents.
         | 
| 705 | 
            -
             | 
| 736 | 
            +
             | 
| 706 737 | 
             
                Args:
         | 
| 707 738 | 
             
                    args: Parsed command line arguments
         | 
| 708 739 | 
             
                """
         | 
| 709 | 
            -
                from ...utils.agent_dependency_loader import AgentDependencyLoader
         | 
| 710 740 | 
             
                import json
         | 
| 711 | 
            -
             | 
| 712 | 
            -
                 | 
| 713 | 
            -
             | 
| 741 | 
            +
             | 
| 742 | 
            +
                from ...utils.agent_dependency_loader import AgentDependencyLoader
         | 
| 743 | 
            +
             | 
| 744 | 
            +
                output_format = getattr(args, "format", "text")
         | 
| 745 | 
            +
             | 
| 714 746 | 
             
                loader = AgentDependencyLoader(auto_install=False)
         | 
| 715 | 
            -
             | 
| 747 | 
            +
             | 
| 716 748 | 
             
                # Discover and load
         | 
| 717 749 | 
             
                loader.discover_deployed_agents()
         | 
| 718 750 | 
             
                loader.load_agent_dependencies()
         | 
| 719 | 
            -
             | 
| 751 | 
            +
             | 
| 720 752 | 
             
                # Collect all unique dependencies
         | 
| 721 753 | 
             
                all_python_deps = set()
         | 
| 722 754 | 
             
                all_system_deps = set()
         | 
| 723 | 
            -
             | 
| 755 | 
            +
             | 
| 724 756 | 
             
                for agent_id, deps in loader.agent_dependencies.items():
         | 
| 725 | 
            -
                    if  | 
| 726 | 
            -
                        all_python_deps.update(deps[ | 
| 727 | 
            -
                    if  | 
| 728 | 
            -
                        all_system_deps.update(deps[ | 
| 729 | 
            -
             | 
| 757 | 
            +
                    if "python" in deps:
         | 
| 758 | 
            +
                        all_python_deps.update(deps["python"])
         | 
| 759 | 
            +
                    if "system" in deps:
         | 
| 760 | 
            +
                        all_system_deps.update(deps["system"])
         | 
| 761 | 
            +
             | 
| 730 762 | 
             
                # Format output based on requested format
         | 
| 731 | 
            -
                if output_format ==  | 
| 763 | 
            +
                if output_format == "pip":
         | 
| 732 764 | 
             
                    # Output pip-installable format
         | 
| 733 765 | 
             
                    for dep in sorted(all_python_deps):
         | 
| 734 766 | 
             
                        print(dep)
         | 
| 735 | 
            -
             | 
| 736 | 
            -
                elif output_format ==  | 
| 767 | 
            +
             | 
| 768 | 
            +
                elif output_format == "json":
         | 
| 737 769 | 
             
                    # Output JSON format
         | 
| 738 770 | 
             
                    output = {
         | 
| 739 | 
            -
                         | 
| 740 | 
            -
                         | 
| 741 | 
            -
                         | 
| 771 | 
            +
                        "python": sorted(list(all_python_deps)),
         | 
| 772 | 
            +
                        "system": sorted(list(all_system_deps)),
         | 
| 773 | 
            +
                        "agents": {},
         | 
| 742 774 | 
             
                    }
         | 
| 743 775 | 
             
                    for agent_id, deps in loader.agent_dependencies.items():
         | 
| 744 | 
            -
                        output[ | 
| 776 | 
            +
                        output["agents"][agent_id] = deps
         | 
| 745 777 | 
             
                    print(json.dumps(output, indent=2))
         | 
| 746 | 
            -
             | 
| 778 | 
            +
             | 
| 747 779 | 
             
                else:  # text format
         | 
| 748 780 | 
             
                    print("=" * 60)
         | 
| 749 781 | 
             
                    print("DEPENDENCIES FROM DEPLOYED AGENTS")
         | 
| 750 782 | 
             
                    print("=" * 60)
         | 
| 751 783 | 
             
                    print()
         | 
| 752 | 
            -
             | 
| 784 | 
            +
             | 
| 753 785 | 
             
                    if all_python_deps:
         | 
| 754 786 | 
             
                        print(f"Python Dependencies ({len(all_python_deps)}):")
         | 
| 755 787 | 
             
                        print("-" * 30)
         | 
| 756 788 | 
             
                        for dep in sorted(all_python_deps):
         | 
| 757 789 | 
             
                            print(f"  {dep}")
         | 
| 758 790 | 
             
                        print()
         | 
| 759 | 
            -
             | 
| 791 | 
            +
             | 
| 760 792 | 
             
                    if all_system_deps:
         | 
| 761 793 | 
             
                        print(f"System Dependencies ({len(all_system_deps)}):")
         | 
| 762 794 | 
             
                        print("-" * 30)
         | 
| 763 795 | 
             
                        for dep in sorted(all_system_deps):
         | 
| 764 796 | 
             
                            print(f"  {dep}")
         | 
| 765 797 | 
             
                        print()
         | 
| 766 | 
            -
             | 
| 798 | 
            +
             | 
| 767 799 | 
             
                    print("Per-Agent Dependencies:")
         | 
| 768 800 | 
             
                    print("-" * 30)
         | 
| 769 801 | 
             
                    for agent_id in sorted(loader.agent_dependencies.keys()):
         | 
| 770 802 | 
             
                        deps = loader.agent_dependencies[agent_id]
         | 
| 771 | 
            -
                        python_count = len(deps.get( | 
| 772 | 
            -
                        system_count = len(deps.get( | 
| 803 | 
            +
                        python_count = len(deps.get("python", []))
         | 
| 804 | 
            +
                        system_count = len(deps.get("system", []))
         | 
| 773 805 | 
             
                        if python_count or system_count:
         | 
| 774 806 | 
             
                            print(f"  {agent_id}: {python_count} Python, {system_count} System")
         | 
| 775 807 |  | 
| @@ -777,47 +809,47 @@ def _list_agent_dependencies(args): | |
| 777 809 | 
             
            def _fix_agent_dependencies(args):
         | 
| 778 810 | 
             
                """
         | 
| 779 811 | 
             
                Fix missing agent dependencies with robust retry logic.
         | 
| 780 | 
            -
             | 
| 812 | 
            +
             | 
| 781 813 | 
             
                WHY: Network issues and temporary package unavailability can cause
         | 
| 782 814 | 
             
                dependency installation to fail. This command uses robust retry logic
         | 
| 783 815 | 
             
                to maximize success rate.
         | 
| 784 | 
            -
             | 
| 816 | 
            +
             | 
| 785 817 | 
             
                Args:
         | 
| 786 818 | 
             
                    args: Parsed command line arguments
         | 
| 787 819 | 
             
                """
         | 
| 788 820 | 
             
                from ...utils.agent_dependency_loader import AgentDependencyLoader
         | 
| 789 821 | 
             
                from ...utils.robust_installer import RobustPackageInstaller
         | 
| 790 | 
            -
             | 
| 791 | 
            -
                max_retries = getattr(args,  | 
| 792 | 
            -
             | 
| 822 | 
            +
             | 
| 823 | 
            +
                max_retries = getattr(args, "max_retries", 3)
         | 
| 824 | 
            +
             | 
| 793 825 | 
             
                print("=" * 70)
         | 
| 794 826 | 
             
                print("FIXING AGENT DEPENDENCIES WITH RETRY LOGIC")
         | 
| 795 827 | 
             
                print("=" * 70)
         | 
| 796 828 | 
             
                print()
         | 
| 797 | 
            -
             | 
| 829 | 
            +
             | 
| 798 830 | 
             
                loader = AgentDependencyLoader(auto_install=False)
         | 
| 799 | 
            -
             | 
| 831 | 
            +
             | 
| 800 832 | 
             
                # Discover and analyze
         | 
| 801 833 | 
             
                print("Discovering deployed agents...")
         | 
| 802 834 | 
             
                loader.discover_deployed_agents()
         | 
| 803 | 
            -
             | 
| 835 | 
            +
             | 
| 804 836 | 
             
                if not loader.deployed_agents:
         | 
| 805 837 | 
             
                    print("No deployed agents found")
         | 
| 806 838 | 
             
                    return
         | 
| 807 | 
            -
             | 
| 839 | 
            +
             | 
| 808 840 | 
             
                print(f"Found {len(loader.deployed_agents)} deployed agents")
         | 
| 809 841 | 
             
                print("Analyzing dependencies...")
         | 
| 810 | 
            -
             | 
| 842 | 
            +
             | 
| 811 843 | 
             
                loader.load_agent_dependencies()
         | 
| 812 844 | 
             
                results = loader.analyze_dependencies()
         | 
| 813 | 
            -
             | 
| 814 | 
            -
                missing_python = results[ | 
| 815 | 
            -
                missing_system = results[ | 
| 816 | 
            -
             | 
| 845 | 
            +
             | 
| 846 | 
            +
                missing_python = results["summary"]["missing_python"]
         | 
| 847 | 
            +
                missing_system = results["summary"]["missing_system"]
         | 
| 848 | 
            +
             | 
| 817 849 | 
             
                if not missing_python and not missing_system:
         | 
| 818 850 | 
             
                    print("\n✅ All dependencies are already satisfied!")
         | 
| 819 851 | 
             
                    return
         | 
| 820 | 
            -
             | 
| 852 | 
            +
             | 
| 821 853 | 
             
                # Show what's missing
         | 
| 822 854 | 
             
                if missing_python:
         | 
| 823 855 | 
             
                    print(f"\n❌ Missing Python packages: {len(missing_python)}")
         | 
| @@ -825,7 +857,7 @@ def _fix_agent_dependencies(args): | |
| 825 857 | 
             
                        print(f"   - {pkg}")
         | 
| 826 858 | 
             
                    if len(missing_python) > 10:
         | 
| 827 859 | 
             
                        print(f"   ... and {len(missing_python) - 10} more")
         | 
| 828 | 
            -
             | 
| 860 | 
            +
             | 
| 829 861 | 
             
                if missing_system:
         | 
| 830 862 | 
             
                    print(f"\n❌ Missing system commands: {len(missing_system)}")
         | 
| 831 863 | 
             
                    for cmd in missing_system:
         | 
| @@ -833,56 +865,56 @@ def _fix_agent_dependencies(args): | |
| 833 865 | 
             
                    print("\n⚠️  System dependencies must be installed manually:")
         | 
| 834 866 | 
             
                    print(f"  macOS:  brew install {' '.join(missing_system)}")
         | 
| 835 867 | 
             
                    print(f"  Ubuntu: apt-get install {' '.join(missing_system)}")
         | 
| 836 | 
            -
             | 
| 868 | 
            +
             | 
| 837 869 | 
             
                # Fix Python dependencies with robust installer
         | 
| 838 870 | 
             
                if missing_python:
         | 
| 839 | 
            -
                    print( | 
| 840 | 
            -
             | 
| 871 | 
            +
                    print(
         | 
| 872 | 
            +
                        f"\n🔧 Fixing Python dependencies with {max_retries} retries per package..."
         | 
| 873 | 
            +
                    )
         | 
| 874 | 
            +
             | 
| 841 875 | 
             
                    # Check compatibility
         | 
| 842 876 | 
             
                    compatible, incompatible = loader.check_python_compatibility(missing_python)
         | 
| 843 | 
            -
             | 
| 877 | 
            +
             | 
| 844 878 | 
             
                    if incompatible:
         | 
| 845 879 | 
             
                        print(f"\n⚠️  Skipping {len(incompatible)} incompatible packages:")
         | 
| 846 880 | 
             
                        for pkg in incompatible[:5]:
         | 
| 847 881 | 
             
                            print(f"   - {pkg}")
         | 
| 848 882 | 
             
                        if len(incompatible) > 5:
         | 
| 849 883 | 
             
                            print(f"   ... and {len(incompatible) - 5} more")
         | 
| 850 | 
            -
             | 
| 884 | 
            +
             | 
| 851 885 | 
             
                    if compatible:
         | 
| 852 886 | 
             
                        installer = RobustPackageInstaller(
         | 
| 853 | 
            -
                            max_retries=max_retries,
         | 
| 854 | 
            -
                            retry_delay=2.0,
         | 
| 855 | 
            -
                            timeout=300
         | 
| 887 | 
            +
                            max_retries=max_retries, retry_delay=2.0, timeout=300
         | 
| 856 888 | 
             
                        )
         | 
| 857 | 
            -
             | 
| 889 | 
            +
             | 
| 858 890 | 
             
                        print(f"\nInstalling {len(compatible)} compatible packages...")
         | 
| 859 891 | 
             
                        successful, failed, errors = installer.install_packages(compatible)
         | 
| 860 | 
            -
             | 
| 892 | 
            +
             | 
| 861 893 | 
             
                        print("\n" + "=" * 70)
         | 
| 862 894 | 
             
                        print("INSTALLATION RESULTS:")
         | 
| 863 895 | 
             
                        print("=" * 70)
         | 
| 864 | 
            -
             | 
| 896 | 
            +
             | 
| 865 897 | 
             
                        if successful:
         | 
| 866 898 | 
             
                            print(f"✅ Successfully installed: {len(successful)} packages")
         | 
| 867 | 
            -
             | 
| 899 | 
            +
             | 
| 868 900 | 
             
                        if failed:
         | 
| 869 901 | 
             
                            print(f"❌ Failed to install: {len(failed)} packages")
         | 
| 870 902 | 
             
                            for pkg in failed:
         | 
| 871 903 | 
             
                                print(f"   - {pkg}: {errors.get(pkg, 'Unknown error')}")
         | 
| 872 | 
            -
             | 
| 904 | 
            +
             | 
| 873 905 | 
             
                        # Re-check
         | 
| 874 906 | 
             
                        print("\nVerifying installation...")
         | 
| 875 907 | 
             
                        loader.checked_packages.clear()
         | 
| 876 908 | 
             
                        final_results = loader.analyze_dependencies()
         | 
| 877 | 
            -
             | 
| 878 | 
            -
                        final_missing = final_results[ | 
| 909 | 
            +
             | 
| 910 | 
            +
                        final_missing = final_results["summary"]["missing_python"]
         | 
| 879 911 | 
             
                        if not final_missing:
         | 
| 880 912 | 
             
                            print("✅ All Python dependencies are now satisfied!")
         | 
| 881 913 | 
             
                        else:
         | 
| 882 914 | 
             
                            print(f"⚠️  Still missing {len(final_missing)} packages")
         | 
| 883 915 | 
             
                            print("\nTry running again or install manually:")
         | 
| 884 916 | 
             
                            print(f"  pip install {' '.join(final_missing[:3])}")
         | 
| 885 | 
            -
             | 
| 917 | 
            +
             | 
| 886 918 | 
             
                print("\n" + "=" * 70)
         | 
| 887 919 | 
             
                print("DONE")
         | 
| 888 | 
            -
                print("=" * 70)
         | 
| 920 | 
            +
                print("=" * 70)
         |