claude-mpm 3.4.10__py3-none-any.whl → 5.4.85__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/BUILD_NUMBER +1 -0
- claude_mpm/VERSION +1 -0
- claude_mpm/__init__.py +50 -12
- claude_mpm/__main__.py +7 -2
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md +405 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +112 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +186 -0
- claude_mpm/agents/MEMORY.md +72 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1429 -0
- claude_mpm/agents/WORKFLOW.md +111 -0
- claude_mpm/agents/__init__.py +92 -80
- claude_mpm/agents/agent-template.yaml +83 -0
- claude_mpm/agents/agent_loader.py +560 -745
- claude_mpm/agents/agent_loader_integration.py +53 -55
- claude_mpm/agents/agents_metadata.py +186 -27
- claude_mpm/agents/async_agent_loader.py +436 -0
- claude_mpm/agents/base_agent.json +8 -4
- claude_mpm/agents/frontmatter_validator.py +754 -0
- claude_mpm/agents/system_agent_config.py +222 -155
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/__init__.py +17 -13
- claude_mpm/agents/templates/circuit-breakers.md +1391 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/git-file-tracking.md +584 -0
- claude_mpm/agents/templates/pm-examples.md +474 -0
- claude_mpm/agents/templates/pm-red-flags.md +310 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/response-format.md +583 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/agents/templates/validation-templates.md +312 -0
- claude_mpm/cli/__init__.py +94 -128
- claude_mpm/cli/__main__.py +33 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/__init__.py +36 -12
- claude_mpm/cli/commands/agent_manager.py +1403 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +335 -0
- claude_mpm/cli/commands/agents.py +2501 -168
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/aggregate.py +540 -0
- claude_mpm/cli/commands/analyze.py +553 -0
- claude_mpm/cli/commands/analyze_code.py +528 -0
- claude_mpm/cli/commands/auto_configure.py +1053 -0
- claude_mpm/cli/commands/cleanup.py +588 -0
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
- claude_mpm/cli/commands/config.py +586 -0
- claude_mpm/cli/commands/configure.py +3253 -0
- claude_mpm/cli/commands/configure_agent_display.py +282 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +184 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/dashboard.py +286 -0
- claude_mpm/cli/commands/debug.py +1386 -0
- claude_mpm/cli/commands/doctor.py +243 -0
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/info.py +195 -74
- claude_mpm/cli/commands/local_deploy.py +534 -0
- claude_mpm/cli/commands/mcp.py +205 -0
- claude_mpm/cli/commands/mcp_command_router.py +161 -0
- claude_mpm/cli/commands/mcp_config.py +154 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_external_commands.py +249 -0
- claude_mpm/cli/commands/mcp_install_commands.py +346 -0
- claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
- claude_mpm/cli/commands/mcp_server_commands.py +155 -0
- claude_mpm/cli/commands/mcp_setup_external.py +868 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +585 -846
- claude_mpm/cli/commands/monitor.py +228 -310
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +759 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +195 -0
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +910 -488
- claude_mpm/cli/commands/search.py +458 -0
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +1398 -0
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/commands/tickets.py +536 -53
- claude_mpm/cli/commands/uninstall.py +176 -0
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/commands/verify.py +119 -0
- claude_mpm/cli/executor.py +298 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +31 -0
- claude_mpm/cli/interactive/agent_wizard.py +1927 -0
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parser.py +87 -563
- claude_mpm/cli/parsers/__init__.py +35 -0
- claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +575 -0
- claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
- claude_mpm/cli/parsers/analyze_parser.py +135 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
- claude_mpm/cli/parsers/base_parser.py +649 -0
- claude_mpm/cli/parsers/config_parser.py +208 -0
- claude_mpm/cli/parsers/configure_parser.py +138 -0
- claude_mpm/cli/parsers/dashboard_parser.py +113 -0
- claude_mpm/cli/parsers/debug_parser.py +319 -0
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mcp_parser.py +195 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +142 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -0
- claude_mpm/cli/parsers/run_parser.py +157 -0
- claude_mpm/cli/parsers/search_parser.py +245 -0
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +277 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/shared/__init__.py +40 -0
- claude_mpm/cli/shared/argument_patterns.py +205 -0
- claude_mpm/cli/shared/base_command.py +242 -0
- claude_mpm/cli/shared/error_handling.py +242 -0
- claude_mpm/cli/shared/output_formatters.py +241 -0
- claude_mpm/cli/startup.py +1578 -0
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/startup_logging.py +839 -0
- claude_mpm/cli/utils.py +136 -47
- 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 +42 -64
- claude_mpm/commands/__init__.py +14 -0
- claude_mpm/commands/mpm-config.md +28 -0
- claude_mpm/commands/mpm-doctor.md +20 -0
- claude_mpm/commands/mpm-help.md +20 -0
- claude_mpm/commands/mpm-init.md +120 -0
- claude_mpm/commands/mpm-monitor.md +31 -0
- claude_mpm/commands/mpm-organize.md +120 -0
- claude_mpm/commands/mpm-postmortem.md +21 -0
- claude_mpm/commands/mpm-session-resume.md +30 -0
- claude_mpm/commands/mpm-status.md +20 -0
- claude_mpm/commands/mpm-ticket-view.md +109 -0
- claude_mpm/commands/mpm-version.md +20 -0
- claude_mpm/commands/mpm.md +31 -0
- claude_mpm/config/__init__.py +42 -2
- claude_mpm/config/agent_config.py +402 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +352 -0
- claude_mpm/config/experimental_features.py +217 -0
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/config/paths.py +258 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/config/socketio_config.py +125 -83
- claude_mpm/constants.py +133 -22
- claude_mpm/core/__init__.py +62 -36
- claude_mpm/core/agent_name_normalizer.py +71 -73
- claude_mpm/core/agent_registry.py +385 -492
- claude_mpm/core/agent_session_manager.py +81 -70
- claude_mpm/core/api_validator.py +330 -0
- claude_mpm/core/base_service.py +159 -122
- claude_mpm/core/cache.py +560 -0
- claude_mpm/core/claude_runner.py +696 -916
- claude_mpm/core/config.py +613 -122
- claude_mpm/core/config_aliases.py +74 -73
- claude_mpm/core/config_constants.py +314 -0
- claude_mpm/core/constants.py +361 -0
- claude_mpm/core/container.py +646 -104
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/error_handler.py +623 -0
- claude_mpm/core/exceptions.py +536 -0
- claude_mpm/core/factories.py +105 -109
- claude_mpm/core/file_utils.py +764 -0
- claude_mpm/core/framework/__init__.py +25 -0
- claude_mpm/core/framework/formatters/__init__.py +11 -0
- claude_mpm/core/framework/formatters/capability_generator.py +367 -0
- claude_mpm/core/framework/formatters/content_formatter.py +278 -0
- claude_mpm/core/framework/formatters/context_generator.py +185 -0
- claude_mpm/core/framework/loaders/__init__.py +13 -0
- claude_mpm/core/framework/loaders/agent_loader.py +213 -0
- claude_mpm/core/framework/loaders/file_loader.py +176 -0
- claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
- claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
- claude_mpm/core/framework/processors/__init__.py +11 -0
- claude_mpm/core/framework/processors/memory_processor.py +230 -0
- claude_mpm/core/framework/processors/metadata_processor.py +146 -0
- claude_mpm/core/framework/processors/template_processor.py +244 -0
- claude_mpm/core/framework_loader.py +485 -414
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +246 -86
- claude_mpm/core/hook_performance_config.py +147 -0
- claude_mpm/core/injectable_service.py +72 -63
- claude_mpm/core/instruction_reinforcement_hook.py +267 -0
- claude_mpm/core/interactive_session.py +670 -0
- claude_mpm/core/interfaces.py +570 -164
- claude_mpm/core/lazy.py +467 -0
- claude_mpm/core/log_manager.py +707 -0
- claude_mpm/core/logger.py +295 -134
- claude_mpm/core/logging_config.py +474 -0
- claude_mpm/core/logging_utils.py +520 -0
- claude_mpm/core/minimal_framework_loader.py +24 -22
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +594 -0
- claude_mpm/core/optimized_agent_loader.py +479 -0
- claude_mpm/core/optimized_startup.py +554 -0
- claude_mpm/core/output_style_manager.py +491 -0
- claude_mpm/core/pm_hook_interceptor.py +197 -82
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/service_registry.py +153 -116
- claude_mpm/core/session_manager.py +179 -64
- claude_mpm/core/shared/__init__.py +17 -0
- claude_mpm/core/shared/config_loader.py +326 -0
- claude_mpm/core/shared/path_resolver.py +281 -0
- claude_mpm/core/shared/singleton_manager.py +221 -0
- claude_mpm/core/socketio_pool.py +400 -137
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/tool_access_control.py +64 -57
- claude_mpm/core/types.py +307 -0
- claude_mpm/core/typing_utils.py +553 -0
- claude_mpm/core/unified_agent_registry.py +969 -0
- claude_mpm/core/unified_config.py +612 -0
- claude_mpm/core/unified_paths.py +958 -0
- claude_mpm/dashboard/__init__.py +12 -0
- claude_mpm/dashboard/api/simple_directory.py +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/__init__.py +10 -0
- claude_mpm/experimental/cli_enhancements.py +104 -89
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +76 -66
- claude_mpm/hooks/__init__.py +37 -1
- claude_mpm/hooks/base_hook.py +37 -32
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
- claude_mpm/hooks/claude_hooks/installer.py +806 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
- claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
- claude_mpm/hooks/failure_learning/__init__.py +54 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
- claude_mpm/hooks/instruction_reinforcement.py +301 -0
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +386 -0
- claude_mpm/hooks/kuzu_response_hook.py +179 -0
- claude_mpm/hooks/memory_integration_hook.py +201 -107
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/hooks/tool_call_interceptor.py +92 -76
- claude_mpm/hooks/validation_hooks.py +62 -54
- claude_mpm/init.py +518 -83
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +40 -23
- claude_mpm/models/agent_session.py +538 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/schemas/__init__.py +12 -0
- claude_mpm/scripts/__init__.py +15 -0
- claude_mpm/scripts/claude-hook-handler.sh +227 -0
- claude_mpm/scripts/launch_monitor.py +165 -0
- claude_mpm/scripts/mpm_doctor.py +322 -0
- claude_mpm/scripts/socketio_daemon.py +189 -200
- claude_mpm/scripts/start_activity_logging.py +91 -0
- claude_mpm/services/__init__.py +208 -39
- claude_mpm/services/agent_capabilities_service.py +266 -0
- claude_mpm/services/agents/__init__.py +89 -0
- claude_mpm/services/agents/agent_builder.py +514 -0
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/__init__.py +21 -0
- claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
- claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
- claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
- claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +1377 -0
- claude_mpm/services/agents/deployment/agent_validator.py +376 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
- claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
- claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -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 +70 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +226 -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/local_template_deployment.py +362 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -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 +162 -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 +240 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -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/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +21 -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 +319 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
- claude_mpm/services/agents/git_source_manager.py +682 -0
- claude_mpm/services/agents/loading/__init__.py +11 -0
- claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
- claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
- claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
- claude_mpm/services/agents/local_template_manager.py +784 -0
- claude_mpm/services/agents/management/__init__.py +9 -0
- claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
- claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
- claude_mpm/services/agents/memory/__init__.py +22 -0
- claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
- claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
- claude_mpm/services/agents/memory/content_manager.py +470 -0
- claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
- claude_mpm/services/agents/memory/memory_file_service.py +129 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
- claude_mpm/services/agents/memory/template_generator.py +83 -0
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +617 -0
- claude_mpm/services/agents/registry/__init__.py +30 -0
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
- claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1205 -0
- claude_mpm/services/agents/startup_sync.py +262 -0
- claude_mpm/services/agents/toolchain_detector.py +478 -0
- claude_mpm/services/analysis/__init__.py +35 -0
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/async_session_logger.py +665 -0
- claude_mpm/services/claude_session_logger.py +321 -0
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +408 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +590 -0
- claude_mpm/services/cli/memory_crud_service.py +622 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +604 -0
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +372 -0
- claude_mpm/services/cli/startup_checker.py +362 -0
- claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
- claude_mpm/services/command_deployment_service.py +446 -0
- claude_mpm/services/command_handler_service.py +221 -0
- claude_mpm/services/communication/__init__.py +22 -0
- claude_mpm/services/core/__init__.py +108 -0
- claude_mpm/services/core/base.py +269 -0
- claude_mpm/services/core/cache_manager.py +309 -0
- claude_mpm/services/core/interfaces/__init__.py +273 -0
- claude_mpm/services/core/interfaces/agent.py +514 -0
- claude_mpm/services/core/interfaces/communication.py +316 -0
- claude_mpm/services/core/interfaces/health.py +169 -0
- claude_mpm/services/core/interfaces/infrastructure.py +357 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/service.py +405 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/interfaces.py +81 -0
- claude_mpm/services/core/memory_manager.py +682 -0
- claude_mpm/services/core/models/__init__.py +70 -0
- claude_mpm/services/core/models/agent_config.py +384 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +239 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +517 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/__init__.py +18 -0
- claude_mpm/services/diagnostics/checks/__init__.py +38 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/base_check.py +60 -0
- claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
- claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
- claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
- claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
- claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
- claude_mpm/services/diagnostics/models.py +138 -0
- claude_mpm/services/event_aggregator.py +582 -0
- claude_mpm/services/event_bus/__init__.py +18 -0
- claude_mpm/services/event_bus/config.py +186 -0
- claude_mpm/services/event_bus/direct_relay.py +312 -0
- claude_mpm/services/event_bus/event_bus.py +396 -0
- claude_mpm/services/event_bus/relay.py +326 -0
- claude_mpm/services/events/__init__.py +44 -0
- claude_mpm/services/events/consumers/__init__.py +18 -0
- claude_mpm/services/events/consumers/dead_letter.py +306 -0
- claude_mpm/services/events/consumers/logging.py +184 -0
- claude_mpm/services/events/consumers/metrics.py +241 -0
- claude_mpm/services/events/consumers/socketio.py +377 -0
- claude_mpm/services/events/core.py +480 -0
- claude_mpm/services/events/interfaces.py +214 -0
- claude_mpm/services/events/producers/__init__.py +14 -0
- claude_mpm/services/events/producers/hook.py +269 -0
- claude_mpm/services/events/producers/system.py +329 -0
- claude_mpm/services/exceptions.py +433 -353
- claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
- claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
- 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 +5 -4
- 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 +26 -30
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +579 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/hook_installer_service.py +506 -0
- claude_mpm/services/hook_service.py +159 -111
- claude_mpm/services/infrastructure/__init__.py +52 -0
- claude_mpm/services/infrastructure/context_preservation.py +569 -0
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +209 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
- claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
- claude_mpm/services/infrastructure/monitoring/base.py +122 -0
- claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
- claude_mpm/services/infrastructure/monitoring/network.py +219 -0
- claude_mpm/services/infrastructure/monitoring/process.py +343 -0
- claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
- claude_mpm/services/infrastructure/monitoring/service.py +368 -0
- claude_mpm/services/infrastructure/monitoring.py +71 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +155 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +427 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +1542 -0
- claude_mpm/services/mcp_service_verifier.py +732 -0
- claude_mpm/services/memory/__init__.py +19 -0
- claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
- claude_mpm/services/memory/cache/__init__.py +14 -0
- claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
- claude_mpm/services/memory/cache/simple_cache.py +331 -0
- claude_mpm/services/memory/failure_tracker.py +578 -0
- claude_mpm/services/memory/indexed_memory.py +648 -0
- claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
- claude_mpm/services/memory/router.py +951 -0
- claude_mpm/services/memory_hook_service.py +470 -0
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +452 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/__init__.py +20 -0
- claude_mpm/services/monitor/daemon.py +698 -0
- claude_mpm/services/monitor/daemon_manager.py +1076 -0
- claude_mpm/services/monitor/event_emitter.py +350 -0
- claude_mpm/services/monitor/handlers/__init__.py +21 -0
- claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
- claude_mpm/services/monitor/handlers/dashboard.py +299 -0
- claude_mpm/services/monitor/handlers/file.py +264 -0
- claude_mpm/services/monitor/handlers/hooks.py +512 -0
- claude_mpm/services/monitor/management/__init__.py +18 -0
- claude_mpm/services/monitor/management/health.py +124 -0
- claude_mpm/services/monitor/management/lifecycle.py +730 -0
- claude_mpm/services/monitor/server.py +1493 -0
- claude_mpm/services/monitor_build_service.py +349 -0
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/orphan_detection.py +786 -0
- claude_mpm/services/pm_skills_deployer.py +711 -0
- claude_mpm/services/port_manager.py +597 -0
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/project/__init__.py +44 -0
- claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
- claude_mpm/services/project/analyzer_v2.py +566 -0
- claude_mpm/services/project/architecture_analyzer.py +461 -0
- claude_mpm/services/project/archive_manager.py +1045 -0
- claude_mpm/services/project/dependency_analyzer.py +462 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/documentation_manager.py +554 -0
- claude_mpm/services/project/enhanced_analyzer.py +572 -0
- claude_mpm/services/project/language_analyzer.py +265 -0
- claude_mpm/services/project/metrics_collector.py +407 -0
- claude_mpm/services/project/project_organizer.py +1009 -0
- claude_mpm/services/project/registry.py +636 -0
- claude_mpm/services/project/toolchain_analyzer.py +583 -0
- claude_mpm/services/project_port_allocator.py +596 -0
- claude_mpm/services/recovery_manager.py +293 -240
- claude_mpm/services/response_tracker.py +267 -0
- claude_mpm/services/runner_configuration_service.py +605 -0
- claude_mpm/services/self_upgrade_service.py +608 -0
- claude_mpm/services/session_management_service.py +314 -0
- claude_mpm/services/session_manager.py +380 -0
- claude_mpm/services/shared/__init__.py +21 -0
- claude_mpm/services/shared/async_service_base.py +216 -0
- claude_mpm/services/shared/config_service_base.py +301 -0
- claude_mpm/services/shared/lifecycle_service_base.py +308 -0
- claude_mpm/services/shared/manager_base.py +315 -0
- claude_mpm/services/shared/service_factory.py +309 -0
- claude_mpm/services/skills/__init__.py +21 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1340 -0
- claude_mpm/services/skills/selective_skill_deployer.py +743 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +1168 -0
- claude_mpm/services/socketio/__init__.py +25 -0
- claude_mpm/services/socketio/client_proxy.py +229 -0
- claude_mpm/services/socketio/dashboard_server.py +362 -0
- claude_mpm/services/socketio/event_normalizer.py +798 -0
- claude_mpm/services/socketio/handlers/__init__.py +30 -0
- claude_mpm/services/socketio/handlers/base.py +136 -0
- claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
- claude_mpm/services/socketio/handlers/connection.py +643 -0
- claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
- claude_mpm/services/socketio/handlers/file.py +263 -0
- claude_mpm/services/socketio/handlers/git.py +962 -0
- claude_mpm/services/socketio/handlers/hook.py +211 -0
- claude_mpm/services/socketio/handlers/memory.py +26 -0
- claude_mpm/services/socketio/handlers/project.py +24 -0
- claude_mpm/services/socketio/handlers/registry.py +214 -0
- claude_mpm/services/socketio/migration_utils.py +343 -0
- claude_mpm/services/socketio/monitor_client.py +364 -0
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +569 -0
- claude_mpm/services/socketio/server/connection_manager.py +579 -0
- claude_mpm/services/socketio/server/core.py +1079 -0
- claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
- claude_mpm/services/socketio/server/main.py +501 -0
- claude_mpm/services/socketio_client_manager.py +173 -143
- claude_mpm/services/socketio_server.py +38 -1657
- claude_mpm/services/subprocess_launcher_service.py +322 -0
- claude_mpm/services/system_instructions_service.py +270 -0
- claude_mpm/services/ticket_manager.py +25 -209
- claude_mpm/services/ticket_services/__init__.py +26 -0
- claude_mpm/services/ticket_services/crud_service.py +328 -0
- claude_mpm/services/ticket_services/formatter_service.py +290 -0
- claude_mpm/services/ticket_services/search_service.py +324 -0
- claude_mpm/services/ticket_services/validation_service.py +303 -0
- claude_mpm/services/ticket_services/workflow_service.py +244 -0
- claude_mpm/services/unified/__init__.py +65 -0
- claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
- claude_mpm/services/unified/config_strategies/__init__.py +175 -0
- claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
- claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
- claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
- claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
- claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
- claude_mpm/services/unified/deployment_strategies/base.py +553 -0
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
- claude_mpm/services/unified/deployment_strategies/local.py +607 -0
- claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
- claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
- claude_mpm/services/unified/interfaces.py +475 -0
- claude_mpm/services/unified/migration.py +509 -0
- claude_mpm/services/unified/strategies.py +534 -0
- claude_mpm/services/unified/unified_analyzer.py +542 -0
- claude_mpm/services/unified/unified_config.py +691 -0
- claude_mpm/services/unified/unified_deployment.py +466 -0
- claude_mpm/services/utility_service.py +280 -0
- claude_mpm/services/version_control/__init__.py +34 -37
- claude_mpm/services/version_control/branch_strategy.py +26 -17
- claude_mpm/services/version_control/conflict_resolution.py +52 -36
- claude_mpm/services/version_control/git_operations.py +183 -49
- claude_mpm/services/version_control/semantic_versioning.py +172 -61
- claude_mpm/services/version_control/version_parser.py +546 -0
- claude_mpm/services/version_service.py +379 -0
- claude_mpm/services/visualization/__init__.py +15 -0
- claude_mpm/services/visualization/mermaid_generator.py +937 -0
- claude_mpm/skills/__init__.py +42 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +573 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/pm-bug-reporting/pm-bug-reporting.md +248 -0
- claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/pm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +439 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +405 -0
- claude_mpm/skills/skills_registry.py +347 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/storage/__init__.py +9 -0
- claude_mpm/storage/state_storage.py +546 -0
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/tools/__init__.py +10 -0
- claude_mpm/tools/__main__.py +208 -0
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/tools/code_tree_builder.py +631 -0
- claude_mpm/tools/code_tree_events.py +420 -0
- claude_mpm/tools/socketio_debug.py +671 -0
- claude_mpm/utils/__init__.py +8 -8
- claude_mpm/utils/agent_dependency_loader.py +1189 -0
- claude_mpm/utils/agent_filters.py +261 -0
- claude_mpm/utils/common.py +544 -0
- claude_mpm/utils/config_manager.py +168 -126
- claude_mpm/utils/console.py +11 -0
- claude_mpm/utils/database_connector.py +298 -0
- claude_mpm/utils/dependency_cache.py +373 -0
- claude_mpm/utils/dependency_manager.py +60 -59
- claude_mpm/utils/dependency_strategies.py +381 -0
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/environment_context.py +313 -0
- claude_mpm/utils/error_handler.py +78 -66
- claude_mpm/utils/file_utils.py +305 -0
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/gitignore.py +244 -0
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/log_cleanup.py +627 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/path_operations.py +110 -104
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +844 -0
- claude_mpm/utils/session_logging.py +121 -0
- claude_mpm/utils/structured_questions.py +619 -0
- claude_mpm/utils/subprocess_utils.py +343 -0
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +214 -108
- claude_mpm/validation/frontmatter_validator.py +252 -0
- claude_mpm-5.4.85.dist-info/METADATA +1023 -0
- claude_mpm-5.4.85.dist-info/RECORD +980 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/entry_points.txt +1 -3
- claude_mpm-5.4.85.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.85.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
- claude_mpm/agents/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/base_agent_loader.py +0 -529
- claude_mpm/agents/schema/agent_schema.json +0 -314
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/data_engineer.json +0 -110
- claude_mpm/agents/templates/documentation.json +0 -109
- claude_mpm/agents/templates/engineer.json +0 -113
- claude_mpm/agents/templates/ops.json +0 -109
- claude_mpm/agents/templates/pm.json +0 -25
- claude_mpm/agents/templates/qa.json +0 -111
- claude_mpm/agents/templates/research.json +0 -65
- claude_mpm/agents/templates/security.json +0 -113
- claude_mpm/agents/templates/test_integration.json +0 -112
- claude_mpm/agents/templates/version_control.json +0 -107
- claude_mpm/cli/commands/ui.py +0 -57
- claude_mpm/core/simple_runner.py +0 -1046
- claude_mpm/dashboard/open_dashboard.py +0 -34
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/builtin/__init__.py +0 -1
- claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
- claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
- claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
- claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
- claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
- claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
- claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
- claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
- claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
- claude_mpm/orchestration/__init__.py +0 -6
- claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
- claude_mpm/orchestration/archive/factory.py +0 -215
- claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
- claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
- claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
- claude_mpm/orchestration/archive/orchestrator.py +0 -501
- claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
- claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
- claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
- claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
- claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
- claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
- claude_mpm/schemas/workflow_validator.py +0 -411
- claude_mpm/services/agent_deployment.py +0 -1534
- claude_mpm/services/agent_lifecycle_manager.py +0 -1169
- claude_mpm/services/agent_memory_manager.py +0 -1415
- claude_mpm/services/agent_registry.py +0 -676
- claude_mpm/services/deployed_agent_discovery.py +0 -226
- claude_mpm/services/framework_agent_loader.py +0 -337
- claude_mpm/services/framework_claude_md_generator.py +0 -621
- claude_mpm/services/health_monitor.py +0 -892
- claude_mpm/services/memory_router.py +0 -538
- claude_mpm/services/parent_directory_manager/__init__.py +0 -577
- claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
- claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
- claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
- claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
- claude_mpm/services/parent_directory_manager/operations.py +0 -186
- claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
- claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
- claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
- claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
- claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
- 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 -508
- claude_mpm/ui/__init__.py +0 -1
- claude_mpm/ui/rich_terminal_ui.py +0 -295
- claude_mpm/ui/terminal_ui.py +0 -328
- claude_mpm/utils/paths.py +0 -289
- claude_mpm-3.4.10.dist-info/METADATA +0 -183
- claude_mpm-3.4.10.dist-info/RECORD +0 -201
- claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1578 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI Startup Functions
|
|
3
|
+
=====================
|
|
4
|
+
|
|
5
|
+
This module contains initialization functions that run on CLI startup,
|
|
6
|
+
including project registry, MCP configuration, and update checks.
|
|
7
|
+
|
|
8
|
+
Part of cli/__init__.py refactoring to reduce file size and improve modularity.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def sync_hooks_on_startup(quiet: bool = False) -> bool:
|
|
17
|
+
"""Ensure hooks are up-to-date on startup.
|
|
18
|
+
|
|
19
|
+
WHY: Users can have stale hook configurations in settings.json that cause errors.
|
|
20
|
+
Reinstalling hooks ensures the hook format matches the current code.
|
|
21
|
+
|
|
22
|
+
DESIGN DECISION: Shows brief status message on success for user awareness.
|
|
23
|
+
Failures are logged but don't prevent startup to ensure claude-mpm remains functional.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
quiet: If True, suppress all output (used internally)
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
bool: True if hooks were synced successfully, False otherwise
|
|
30
|
+
"""
|
|
31
|
+
try:
|
|
32
|
+
from ..hooks.claude_hooks.installer import HookInstaller
|
|
33
|
+
|
|
34
|
+
installer = HookInstaller()
|
|
35
|
+
|
|
36
|
+
# Show brief status (hooks sync is fast)
|
|
37
|
+
if not quiet:
|
|
38
|
+
print("Syncing Claude Code hooks...", end=" ", flush=True)
|
|
39
|
+
|
|
40
|
+
# Reinstall hooks (force=True ensures update)
|
|
41
|
+
success = installer.install_hooks(force=True)
|
|
42
|
+
|
|
43
|
+
if not quiet:
|
|
44
|
+
if success:
|
|
45
|
+
print("✓")
|
|
46
|
+
else:
|
|
47
|
+
print("(skipped)")
|
|
48
|
+
|
|
49
|
+
return success
|
|
50
|
+
|
|
51
|
+
except Exception as e:
|
|
52
|
+
if not quiet:
|
|
53
|
+
print("(error)")
|
|
54
|
+
# Log but don't fail startup
|
|
55
|
+
from ..core.logger import get_logger
|
|
56
|
+
|
|
57
|
+
logger = get_logger("startup")
|
|
58
|
+
logger.warning(f"Hook sync failed (non-fatal): {e}")
|
|
59
|
+
return False
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def cleanup_legacy_agent_cache() -> None:
|
|
63
|
+
"""Remove legacy hierarchical agent cache directories.
|
|
64
|
+
|
|
65
|
+
WHY: Old agent cache used category-based directory structure directly in cache.
|
|
66
|
+
New structure uses remote source paths. This cleanup prevents confusion from
|
|
67
|
+
stale cache directories.
|
|
68
|
+
|
|
69
|
+
Old structure (removed):
|
|
70
|
+
~/.claude-mpm/cache/agents/engineer/
|
|
71
|
+
~/.claude-mpm/cache/agents/ops/
|
|
72
|
+
~/.claude-mpm/cache/agents/qa/
|
|
73
|
+
...
|
|
74
|
+
|
|
75
|
+
New structure (kept):
|
|
76
|
+
~/.claude-mpm/cache/agents/bobmatnyc/claude-mpm-agents/agents/...
|
|
77
|
+
|
|
78
|
+
DESIGN DECISION: Runs early in startup before agent deployment to ensure
|
|
79
|
+
clean cache state. Removes only known legacy directories to avoid deleting
|
|
80
|
+
user data.
|
|
81
|
+
"""
|
|
82
|
+
import shutil
|
|
83
|
+
from pathlib import Path
|
|
84
|
+
|
|
85
|
+
from ..core.logger import get_logger
|
|
86
|
+
|
|
87
|
+
logger = get_logger("startup")
|
|
88
|
+
|
|
89
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
|
|
90
|
+
if not cache_dir.exists():
|
|
91
|
+
return
|
|
92
|
+
|
|
93
|
+
# Known legacy category directories (from old hierarchical structure)
|
|
94
|
+
legacy_dirs = [
|
|
95
|
+
"claude-mpm",
|
|
96
|
+
"documentation",
|
|
97
|
+
"engineer",
|
|
98
|
+
"ops",
|
|
99
|
+
"qa",
|
|
100
|
+
"security",
|
|
101
|
+
"universal",
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
removed = []
|
|
105
|
+
|
|
106
|
+
# Remove legacy category directories
|
|
107
|
+
for dir_name in legacy_dirs:
|
|
108
|
+
legacy_path = cache_dir / dir_name
|
|
109
|
+
if legacy_path.exists() and legacy_path.is_dir():
|
|
110
|
+
try:
|
|
111
|
+
shutil.rmtree(legacy_path)
|
|
112
|
+
removed.append(dir_name)
|
|
113
|
+
except Exception as e:
|
|
114
|
+
logger.debug(f"Failed to remove legacy directory {dir_name}: {e}")
|
|
115
|
+
|
|
116
|
+
# Also remove stray BASE-AGENT.md in cache root
|
|
117
|
+
base_agent = cache_dir / "BASE-AGENT.md"
|
|
118
|
+
if base_agent.exists():
|
|
119
|
+
try:
|
|
120
|
+
base_agent.unlink()
|
|
121
|
+
removed.append("BASE-AGENT.md")
|
|
122
|
+
except Exception as e:
|
|
123
|
+
logger.debug(f"Failed to remove BASE-AGENT.md: {e}")
|
|
124
|
+
|
|
125
|
+
if removed:
|
|
126
|
+
logger.info(f"Cleaned up legacy agent cache: {', '.join(removed)}")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def check_legacy_cache() -> None:
|
|
130
|
+
"""Deprecated: Legacy cache checking is no longer needed.
|
|
131
|
+
|
|
132
|
+
This function is kept for backward compatibility but does nothing.
|
|
133
|
+
All agent cache operations now use the standardized cache/agents/ directory.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def setup_early_environment(argv):
|
|
138
|
+
"""
|
|
139
|
+
Set up early environment variables and logging suppression.
|
|
140
|
+
|
|
141
|
+
WHY: Some commands need special environment handling before any logging
|
|
142
|
+
or service initialization occurs.
|
|
143
|
+
|
|
144
|
+
CRITICAL: Suppress ALL logging by default until setup_mcp_server_logging()
|
|
145
|
+
configures the user's preference. This prevents early loggers (like
|
|
146
|
+
ProjectInitializer and service.* loggers) from logging at INFO level before
|
|
147
|
+
we know the user's logging preference.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
argv: Command line arguments
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Processed argv list
|
|
154
|
+
"""
|
|
155
|
+
import logging
|
|
156
|
+
|
|
157
|
+
# Disable telemetry and set cleanup flags early
|
|
158
|
+
os.environ.setdefault("DISABLE_TELEMETRY", "1")
|
|
159
|
+
os.environ.setdefault("CLAUDE_MPM_SKIP_CLEANUP", "0")
|
|
160
|
+
|
|
161
|
+
# CRITICAL: Suppress ALL logging by default
|
|
162
|
+
# This catches all loggers (claude_mpm.*, service.*, framework_loader, etc.)
|
|
163
|
+
# This will be overridden by setup_mcp_server_logging() based on user preference
|
|
164
|
+
logging.getLogger().setLevel(logging.CRITICAL + 1) # Root logger catches everything
|
|
165
|
+
|
|
166
|
+
# Process argv
|
|
167
|
+
if argv is None:
|
|
168
|
+
argv = sys.argv[1:]
|
|
169
|
+
|
|
170
|
+
# EARLY CHECK: Additional suppression for configure command
|
|
171
|
+
if "configure" in argv or (len(argv) > 0 and argv[0] == "configure"):
|
|
172
|
+
os.environ["CLAUDE_MPM_SKIP_CLEANUP"] = "1"
|
|
173
|
+
|
|
174
|
+
return argv
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def should_skip_background_services(args, processed_argv):
|
|
178
|
+
"""
|
|
179
|
+
Determine if background services should be skipped for this command.
|
|
180
|
+
|
|
181
|
+
WHY: Some commands (help, version, configure, doctor) don't need
|
|
182
|
+
background services and should start faster.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
args: Parsed arguments
|
|
186
|
+
processed_argv: Processed command line arguments
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
bool: True if background services should be skipped
|
|
190
|
+
"""
|
|
191
|
+
skip_commands = ["--version", "-v", "--help", "-h"]
|
|
192
|
+
return any(cmd in (processed_argv or sys.argv[1:]) for cmd in skip_commands) or (
|
|
193
|
+
hasattr(args, "command")
|
|
194
|
+
and args.command in ["info", "doctor", "config", "mcp", "configure"]
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def setup_configure_command_environment(args):
|
|
199
|
+
"""
|
|
200
|
+
Set up special environment for configure command.
|
|
201
|
+
|
|
202
|
+
WHY: Configure command needs clean state without background services
|
|
203
|
+
and with suppressed logging.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
args: Parsed arguments
|
|
207
|
+
"""
|
|
208
|
+
if hasattr(args, "command") and args.command == "configure":
|
|
209
|
+
os.environ["CLAUDE_MPM_SKIP_CLEANUP"] = "1"
|
|
210
|
+
import logging
|
|
211
|
+
|
|
212
|
+
logging.getLogger("claude_mpm").setLevel(logging.WARNING)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def deploy_bundled_skills():
|
|
216
|
+
"""
|
|
217
|
+
Deploy bundled Claude Code skills on startup.
|
|
218
|
+
|
|
219
|
+
WHY: Automatically deploy skills from the bundled/ directory to .claude/skills/
|
|
220
|
+
to ensure skills are available for agents without manual intervention.
|
|
221
|
+
|
|
222
|
+
DESIGN DECISION: Deployment happens with minimal feedback (checkmark on success).
|
|
223
|
+
Failures are logged but don't block startup to ensure claude-mpm remains
|
|
224
|
+
functional even if skills deployment fails. Respects auto_deploy config setting.
|
|
225
|
+
"""
|
|
226
|
+
try:
|
|
227
|
+
# Check if auto-deploy is disabled in config
|
|
228
|
+
from ..config.config_loader import ConfigLoader
|
|
229
|
+
|
|
230
|
+
config_loader = ConfigLoader()
|
|
231
|
+
try:
|
|
232
|
+
config = config_loader.load_config()
|
|
233
|
+
skills_config = config.get("skills", {})
|
|
234
|
+
if not skills_config.get("auto_deploy", True):
|
|
235
|
+
# Auto-deploy disabled, skip silently
|
|
236
|
+
return
|
|
237
|
+
except Exception: # nosec B110
|
|
238
|
+
# If config loading fails, assume auto-deploy is enabled (default)
|
|
239
|
+
pass
|
|
240
|
+
|
|
241
|
+
# Import and run skills deployment
|
|
242
|
+
from ..skills.skills_service import SkillsService
|
|
243
|
+
|
|
244
|
+
skills_service = SkillsService()
|
|
245
|
+
deployment_result = skills_service.deploy_bundled_skills()
|
|
246
|
+
|
|
247
|
+
# Log results
|
|
248
|
+
from ..core.logger import get_logger
|
|
249
|
+
|
|
250
|
+
logger = get_logger("cli")
|
|
251
|
+
|
|
252
|
+
if deployment_result.get("deployed"):
|
|
253
|
+
# Show simple feedback for deployed skills
|
|
254
|
+
deployed_count = len(deployment_result["deployed"])
|
|
255
|
+
print(f"✓ Bundled skills ready ({deployed_count} deployed)", flush=True)
|
|
256
|
+
logger.info(f"Skills: Deployed {deployed_count} skill(s)")
|
|
257
|
+
elif not deployment_result.get("errors"):
|
|
258
|
+
# No deployment needed, skills already present
|
|
259
|
+
print("✓ Bundled skills ready", flush=True)
|
|
260
|
+
|
|
261
|
+
if deployment_result.get("errors"):
|
|
262
|
+
logger.warning(
|
|
263
|
+
f"Skills: {len(deployment_result['errors'])} skill(s) failed to deploy"
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
except Exception as e:
|
|
267
|
+
# Import logger here to avoid circular imports
|
|
268
|
+
from ..core.logger import get_logger
|
|
269
|
+
|
|
270
|
+
logger = get_logger("cli")
|
|
271
|
+
logger.debug(f"Failed to deploy bundled skills: {e}")
|
|
272
|
+
# Continue execution - skills deployment failure shouldn't block startup
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def discover_and_link_runtime_skills():
|
|
276
|
+
"""
|
|
277
|
+
Discover and link runtime skills from user/project directories.
|
|
278
|
+
|
|
279
|
+
WHY: Automatically discover and link skills added to .claude/skills/
|
|
280
|
+
without requiring manual configuration.
|
|
281
|
+
|
|
282
|
+
DESIGN DECISION: Provides simple feedback on completion.
|
|
283
|
+
Failures are logged but don't block startup to ensure
|
|
284
|
+
claude-mpm remains functional even if skills discovery fails.
|
|
285
|
+
"""
|
|
286
|
+
try:
|
|
287
|
+
from ..cli.interactive.skills_wizard import (
|
|
288
|
+
discover_and_link_runtime_skills as discover_skills,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
discover_skills()
|
|
292
|
+
# Show simple success feedback
|
|
293
|
+
print("✓ Runtime skills linked", flush=True)
|
|
294
|
+
except Exception as e:
|
|
295
|
+
# Import logger here to avoid circular imports
|
|
296
|
+
from ..core.logger import get_logger
|
|
297
|
+
|
|
298
|
+
logger = get_logger("cli")
|
|
299
|
+
logger.debug(f"Failed to discover runtime skills: {e}")
|
|
300
|
+
# Continue execution - skills discovery failure shouldn't block startup
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def deploy_output_style_on_startup():
|
|
304
|
+
"""
|
|
305
|
+
Deploy claude-mpm output styles to PROJECT-LEVEL directory on CLI startup.
|
|
306
|
+
|
|
307
|
+
WHY: Automatically deploy output styles to ensure consistent, professional
|
|
308
|
+
communication without emojis and exclamation points. Styles are project-specific
|
|
309
|
+
to allow different projects to have different communication styles.
|
|
310
|
+
|
|
311
|
+
DESIGN DECISION: This is non-blocking and idempotent. Deploys to user-level
|
|
312
|
+
directory (~/.claude/output-styles/) which is the official Claude Code location
|
|
313
|
+
for custom output styles.
|
|
314
|
+
|
|
315
|
+
Deploys all styles:
|
|
316
|
+
- claude-mpm.md (professional mode)
|
|
317
|
+
- claude-mpm-teacher.md (teaching mode)
|
|
318
|
+
- claude-mpm-founders.md (founders mode)
|
|
319
|
+
"""
|
|
320
|
+
try:
|
|
321
|
+
from ..core.output_style_manager import OutputStyleManager
|
|
322
|
+
|
|
323
|
+
# Initialize the output style manager
|
|
324
|
+
manager = OutputStyleManager()
|
|
325
|
+
|
|
326
|
+
# Check if Claude Code version supports output styles (>= 1.0.83)
|
|
327
|
+
if not manager.supports_output_styles():
|
|
328
|
+
# Skip deployment for older versions
|
|
329
|
+
# The manager will fall back to injecting content directly
|
|
330
|
+
return
|
|
331
|
+
|
|
332
|
+
# Check if all styles are already deployed and up-to-date
|
|
333
|
+
all_up_to_date = True
|
|
334
|
+
for style_config in manager.styles.values():
|
|
335
|
+
source_path = style_config["source"]
|
|
336
|
+
target_path = style_config["target"]
|
|
337
|
+
|
|
338
|
+
if not (
|
|
339
|
+
target_path.exists()
|
|
340
|
+
and source_path.exists()
|
|
341
|
+
and target_path.stat().st_size == source_path.stat().st_size
|
|
342
|
+
):
|
|
343
|
+
all_up_to_date = False
|
|
344
|
+
break
|
|
345
|
+
|
|
346
|
+
if all_up_to_date:
|
|
347
|
+
# Show feedback that output styles are ready
|
|
348
|
+
print("✓ Output styles ready", flush=True)
|
|
349
|
+
return
|
|
350
|
+
|
|
351
|
+
# Deploy all styles using the manager
|
|
352
|
+
results = manager.deploy_all_styles(activate_default=True)
|
|
353
|
+
|
|
354
|
+
# Count successful deployments
|
|
355
|
+
deployed_count = sum(1 for success in results.values() if success)
|
|
356
|
+
|
|
357
|
+
if deployed_count > 0:
|
|
358
|
+
print(f"✓ Output styles deployed ({deployed_count} styles)", flush=True)
|
|
359
|
+
else:
|
|
360
|
+
# Deployment failed - log but don't fail startup
|
|
361
|
+
from ..core.logger import get_logger
|
|
362
|
+
|
|
363
|
+
logger = get_logger("cli")
|
|
364
|
+
logger.debug("Failed to deploy any output styles")
|
|
365
|
+
|
|
366
|
+
except Exception as e:
|
|
367
|
+
# Non-critical - log but don't fail startup
|
|
368
|
+
from ..core.logger import get_logger
|
|
369
|
+
|
|
370
|
+
logger = get_logger("cli")
|
|
371
|
+
logger.debug(f"Failed to deploy output styles: {e}")
|
|
372
|
+
# Continue execution - output style deployment shouldn't block startup
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _cleanup_orphaned_agents(deploy_target: Path, deployed_agents: list[str]) -> int:
|
|
376
|
+
"""Remove agents that are managed by claude-mpm but no longer deployed.
|
|
377
|
+
|
|
378
|
+
WHY: When agent configurations change, old agents should be removed to avoid
|
|
379
|
+
confusion and stale agent references. Only removes claude-mpm managed agents,
|
|
380
|
+
leaving user-created agents untouched.
|
|
381
|
+
|
|
382
|
+
SAFETY: Only removes files with claude-mpm ownership markers in frontmatter.
|
|
383
|
+
Files without frontmatter or without ownership indicators are preserved.
|
|
384
|
+
|
|
385
|
+
Args:
|
|
386
|
+
deploy_target: Path to .claude/agents/ directory
|
|
387
|
+
deployed_agents: List of agent filenames that should remain
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
Number of agents removed
|
|
391
|
+
"""
|
|
392
|
+
import re
|
|
393
|
+
|
|
394
|
+
import yaml
|
|
395
|
+
|
|
396
|
+
from ..core.logger import get_logger
|
|
397
|
+
|
|
398
|
+
logger = get_logger("cli")
|
|
399
|
+
removed_count = 0
|
|
400
|
+
deployed_set = set(deployed_agents)
|
|
401
|
+
|
|
402
|
+
if not deploy_target.exists():
|
|
403
|
+
return 0
|
|
404
|
+
|
|
405
|
+
# Scan all .md files in agents directory
|
|
406
|
+
for agent_file in deploy_target.glob("*.md"):
|
|
407
|
+
# Skip hidden files
|
|
408
|
+
if agent_file.name.startswith("."):
|
|
409
|
+
continue
|
|
410
|
+
|
|
411
|
+
# Skip if this agent should remain deployed
|
|
412
|
+
if agent_file.name in deployed_set:
|
|
413
|
+
continue
|
|
414
|
+
|
|
415
|
+
# Check if this is a claude-mpm managed agent
|
|
416
|
+
try:
|
|
417
|
+
content = agent_file.read_text(encoding="utf-8")
|
|
418
|
+
|
|
419
|
+
# Parse YAML frontmatter
|
|
420
|
+
if content.startswith("---"):
|
|
421
|
+
match = re.match(r"^---\n(.*?)\n---", content, re.DOTALL)
|
|
422
|
+
if match:
|
|
423
|
+
frontmatter = yaml.safe_load(match.group(1))
|
|
424
|
+
|
|
425
|
+
# Check ownership indicators
|
|
426
|
+
is_ours = False
|
|
427
|
+
if frontmatter:
|
|
428
|
+
author = frontmatter.get("author", "")
|
|
429
|
+
source = frontmatter.get("source", "")
|
|
430
|
+
agent_id = frontmatter.get("agent_id", "")
|
|
431
|
+
|
|
432
|
+
# It's ours if it has any of these markers
|
|
433
|
+
if (
|
|
434
|
+
"Claude MPM" in str(author)
|
|
435
|
+
or source == "remote"
|
|
436
|
+
or agent_id
|
|
437
|
+
):
|
|
438
|
+
is_ours = True
|
|
439
|
+
|
|
440
|
+
if is_ours:
|
|
441
|
+
# Safe to remove - it's our agent but not deployed
|
|
442
|
+
agent_file.unlink()
|
|
443
|
+
removed_count += 1
|
|
444
|
+
logger.info(f"Removed orphaned agent: {agent_file.name}")
|
|
445
|
+
|
|
446
|
+
except Exception as e:
|
|
447
|
+
logger.debug(f"Could not check agent {agent_file.name}: {e}")
|
|
448
|
+
# Don't remove if we can't verify ownership
|
|
449
|
+
|
|
450
|
+
return removed_count
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def sync_remote_agents_on_startup(force_sync: bool = False):
|
|
454
|
+
"""
|
|
455
|
+
Synchronize agent templates from remote sources on startup.
|
|
456
|
+
|
|
457
|
+
WHY: Ensures agents are up-to-date from remote Git sources (GitHub)
|
|
458
|
+
without manual intervention. Uses ETag-based caching for efficient
|
|
459
|
+
updates (95%+ bandwidth reduction).
|
|
460
|
+
|
|
461
|
+
DESIGN DECISION: Non-blocking synchronization that doesn't prevent
|
|
462
|
+
startup if network is unavailable. Failures are logged but don't
|
|
463
|
+
block startup to ensure claude-mpm remains functional.
|
|
464
|
+
|
|
465
|
+
Workflow:
|
|
466
|
+
1. Sync all enabled Git sources (download/cache files) - Phase 1 progress bar
|
|
467
|
+
2. Deploy agents to ~/.claude/agents/ - Phase 2 progress bar
|
|
468
|
+
3. Cleanup orphaned agents (ours but no longer deployed) - Phase 3
|
|
469
|
+
4. Cleanup legacy agent cache directories (after sync/deployment) - Phase 4
|
|
470
|
+
5. Log deployment results
|
|
471
|
+
|
|
472
|
+
Args:
|
|
473
|
+
force_sync: Force download even if cache is fresh (bypasses ETag).
|
|
474
|
+
"""
|
|
475
|
+
# DEPRECATED: Legacy warning - no-op function, kept for compatibility
|
|
476
|
+
check_legacy_cache()
|
|
477
|
+
|
|
478
|
+
try:
|
|
479
|
+
# Load active profile if configured
|
|
480
|
+
# Get project root (where .claude-mpm exists)
|
|
481
|
+
from pathlib import Path
|
|
482
|
+
|
|
483
|
+
from ..core.shared.config_loader import ConfigLoader
|
|
484
|
+
from ..services.agents.startup_sync import sync_agents_on_startup
|
|
485
|
+
from ..services.profile_manager import ProfileManager
|
|
486
|
+
from ..utils.progress import ProgressBar
|
|
487
|
+
|
|
488
|
+
project_root = Path.cwd()
|
|
489
|
+
|
|
490
|
+
profile_manager = ProfileManager(project_dir=project_root)
|
|
491
|
+
config_loader = ConfigLoader()
|
|
492
|
+
main_config = config_loader.load_main_config()
|
|
493
|
+
active_profile = main_config.get("active_profile")
|
|
494
|
+
|
|
495
|
+
if active_profile:
|
|
496
|
+
success = profile_manager.load_profile(active_profile)
|
|
497
|
+
if success:
|
|
498
|
+
summary = profile_manager.get_filtering_summary()
|
|
499
|
+
from ..core.logger import get_logger
|
|
500
|
+
|
|
501
|
+
logger = get_logger("cli")
|
|
502
|
+
logger.info(
|
|
503
|
+
f"Profile '{active_profile}' active: "
|
|
504
|
+
f"{summary['enabled_agents_count']} agents enabled"
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
# Phase 1: Sync files from Git sources
|
|
508
|
+
result = sync_agents_on_startup(force_refresh=force_sync)
|
|
509
|
+
|
|
510
|
+
# Only proceed with deployment if sync was enabled and ran
|
|
511
|
+
if result.get("enabled") and result.get("sources_synced", 0) > 0:
|
|
512
|
+
from ..core.logger import get_logger
|
|
513
|
+
|
|
514
|
+
logger = get_logger("cli")
|
|
515
|
+
|
|
516
|
+
downloaded = result.get("total_downloaded", 0)
|
|
517
|
+
cached = result.get("cache_hits", 0)
|
|
518
|
+
duration = result.get("duration_ms", 0)
|
|
519
|
+
|
|
520
|
+
if downloaded > 0 or cached > 0:
|
|
521
|
+
logger.debug(
|
|
522
|
+
f"Agent sync: {downloaded} updated, {cached} cached ({duration}ms)"
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
# Log errors if any
|
|
526
|
+
errors = result.get("errors", [])
|
|
527
|
+
if errors:
|
|
528
|
+
logger.warning(f"Agent sync completed with {len(errors)} errors")
|
|
529
|
+
|
|
530
|
+
# Phase 2: Deploy agents from cache to ~/.claude/agents/
|
|
531
|
+
# Use reconciliation service to respect configuration.yaml settings
|
|
532
|
+
try:
|
|
533
|
+
from pathlib import Path
|
|
534
|
+
|
|
535
|
+
from ..core.unified_config import UnifiedConfig
|
|
536
|
+
from ..services.agents.deployment.startup_reconciliation import (
|
|
537
|
+
perform_startup_reconciliation,
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
# Load configuration
|
|
541
|
+
unified_config = UnifiedConfig()
|
|
542
|
+
|
|
543
|
+
# Override with profile settings if active
|
|
544
|
+
if active_profile and profile_manager.active_profile:
|
|
545
|
+
# Get enabled agents from profile (returns Set[str])
|
|
546
|
+
profile_enabled_agents = (
|
|
547
|
+
profile_manager.active_profile.get_enabled_agents()
|
|
548
|
+
)
|
|
549
|
+
# Update config with profile's enabled list (convert Set to List)
|
|
550
|
+
unified_config.agents.enabled = list(profile_enabled_agents)
|
|
551
|
+
logger.info(
|
|
552
|
+
f"Profile '{active_profile}': Using {len(profile_enabled_agents)} enabled agents"
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
# Perform reconciliation to deploy configured agents
|
|
556
|
+
project_path = Path.cwd()
|
|
557
|
+
agent_result, _skill_result = perform_startup_reconciliation(
|
|
558
|
+
project_path=project_path, config=unified_config, silent=False
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
# Display results with progress bar
|
|
562
|
+
total_operations = (
|
|
563
|
+
len(agent_result.deployed)
|
|
564
|
+
+ len(agent_result.removed)
|
|
565
|
+
+ len(agent_result.unchanged)
|
|
566
|
+
)
|
|
567
|
+
|
|
568
|
+
if total_operations > 0:
|
|
569
|
+
deploy_progress = ProgressBar(
|
|
570
|
+
total=total_operations,
|
|
571
|
+
prefix="Deploying agents",
|
|
572
|
+
show_percentage=True,
|
|
573
|
+
show_counter=True,
|
|
574
|
+
)
|
|
575
|
+
deploy_progress.update(total_operations)
|
|
576
|
+
|
|
577
|
+
# Build summary message
|
|
578
|
+
deployed = len(agent_result.deployed)
|
|
579
|
+
removed = len(agent_result.removed)
|
|
580
|
+
unchanged = len(agent_result.unchanged)
|
|
581
|
+
|
|
582
|
+
summary_parts = []
|
|
583
|
+
if deployed > 0:
|
|
584
|
+
summary_parts.append(f"{deployed} new")
|
|
585
|
+
if removed > 0:
|
|
586
|
+
summary_parts.append(f"{removed} removed")
|
|
587
|
+
if unchanged > 0:
|
|
588
|
+
summary_parts.append(f"{unchanged} unchanged")
|
|
589
|
+
|
|
590
|
+
summary = f"Complete: {', '.join(summary_parts)}"
|
|
591
|
+
deploy_progress.finish(summary)
|
|
592
|
+
|
|
593
|
+
# Display errors if any
|
|
594
|
+
if agent_result.errors:
|
|
595
|
+
logger.warning(
|
|
596
|
+
f"Agent deployment completed with {len(agent_result.errors)} errors"
|
|
597
|
+
)
|
|
598
|
+
print("\n⚠️ Agent Deployment Errors:")
|
|
599
|
+
max_errors_to_show = 10
|
|
600
|
+
errors_to_display = agent_result.errors[:max_errors_to_show]
|
|
601
|
+
|
|
602
|
+
for error in errors_to_display:
|
|
603
|
+
print(f" - {error}")
|
|
604
|
+
|
|
605
|
+
if len(agent_result.errors) > max_errors_to_show:
|
|
606
|
+
remaining = len(agent_result.errors) - max_errors_to_show
|
|
607
|
+
print(f" ... and {remaining} more error(s)")
|
|
608
|
+
|
|
609
|
+
print(
|
|
610
|
+
f"\n❌ Failed to deploy {len(agent_result.errors)} agent(s). "
|
|
611
|
+
"Please check the error messages above."
|
|
612
|
+
)
|
|
613
|
+
print(" Run with --verbose for detailed error information.\n")
|
|
614
|
+
|
|
615
|
+
except Exception as e:
|
|
616
|
+
# Deployment failure shouldn't block startup
|
|
617
|
+
from ..core.logger import get_logger
|
|
618
|
+
|
|
619
|
+
logger = get_logger("cli")
|
|
620
|
+
logger.warning(f"Failed to deploy agents from cache: {e}")
|
|
621
|
+
|
|
622
|
+
# Phase 4: Cleanup legacy agent cache directories (after sync/deployment)
|
|
623
|
+
# CRITICAL: This must run AFTER sync completes because sync may recreate
|
|
624
|
+
# legacy directories. Running cleanup here ensures they're removed.
|
|
625
|
+
cleanup_legacy_agent_cache()
|
|
626
|
+
|
|
627
|
+
except Exception as e:
|
|
628
|
+
# Non-critical - log but don't fail startup
|
|
629
|
+
from ..core.logger import get_logger
|
|
630
|
+
|
|
631
|
+
logger = get_logger("cli")
|
|
632
|
+
logger.debug(f"Failed to sync remote agents: {e}")
|
|
633
|
+
# Continue execution - agent sync failure shouldn't block startup
|
|
634
|
+
|
|
635
|
+
# Cleanup legacy cache even if sync failed
|
|
636
|
+
try:
|
|
637
|
+
cleanup_legacy_agent_cache()
|
|
638
|
+
except Exception: # nosec B110
|
|
639
|
+
pass # Ignore cleanup errors
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
def sync_remote_skills_on_startup(force_sync: bool = False):
|
|
643
|
+
"""
|
|
644
|
+
Synchronize skill templates from remote sources on startup.
|
|
645
|
+
|
|
646
|
+
WHY: Ensures skills are up-to-date from remote Git sources (GitHub)
|
|
647
|
+
without manual intervention. Provides consistency with agent syncing.
|
|
648
|
+
|
|
649
|
+
DESIGN DECISION: Non-blocking synchronization that doesn't prevent
|
|
650
|
+
startup if network is unavailable. Failures are logged but don't
|
|
651
|
+
block startup to ensure claude-mpm remains functional.
|
|
652
|
+
|
|
653
|
+
Workflow:
|
|
654
|
+
1. Sync all enabled Git sources (download/cache files) - Phase 1 progress bar
|
|
655
|
+
2. Scan deployed agents for skill requirements → save to configuration.yaml
|
|
656
|
+
3. Resolve which skills to deploy (user_defined vs agent_referenced)
|
|
657
|
+
4. Apply profile filtering if active
|
|
658
|
+
5. Deploy resolved skills to ~/.claude/skills/ - Phase 2 progress bar
|
|
659
|
+
6. Log deployment results with source indication
|
|
660
|
+
|
|
661
|
+
Args:
|
|
662
|
+
force_sync: Force download even if cache is fresh (bypasses ETag).
|
|
663
|
+
"""
|
|
664
|
+
try:
|
|
665
|
+
from pathlib import Path
|
|
666
|
+
|
|
667
|
+
from ..config.skill_sources import SkillSourceConfiguration
|
|
668
|
+
from ..core.shared.config_loader import ConfigLoader
|
|
669
|
+
from ..services.profile_manager import ProfileManager
|
|
670
|
+
from ..services.skills.git_skill_source_manager import GitSkillSourceManager
|
|
671
|
+
from ..services.skills.selective_skill_deployer import (
|
|
672
|
+
get_required_skills_from_agents,
|
|
673
|
+
get_skills_to_deploy,
|
|
674
|
+
save_agent_skills_to_config,
|
|
675
|
+
)
|
|
676
|
+
from ..utils.progress import ProgressBar
|
|
677
|
+
|
|
678
|
+
# Load active profile if configured
|
|
679
|
+
# Get project root (where .claude-mpm exists)
|
|
680
|
+
project_root = Path.cwd()
|
|
681
|
+
|
|
682
|
+
profile_manager = ProfileManager(project_dir=project_root)
|
|
683
|
+
config_loader = ConfigLoader()
|
|
684
|
+
main_config = config_loader.load_main_config()
|
|
685
|
+
active_profile = main_config.get("active_profile")
|
|
686
|
+
|
|
687
|
+
if active_profile:
|
|
688
|
+
success = profile_manager.load_profile(active_profile)
|
|
689
|
+
if success:
|
|
690
|
+
from ..core.logger import get_logger
|
|
691
|
+
|
|
692
|
+
logger = get_logger("cli")
|
|
693
|
+
summary = profile_manager.get_filtering_summary()
|
|
694
|
+
logger.info(
|
|
695
|
+
f"Profile '{active_profile}' active: "
|
|
696
|
+
f"{summary['enabled_skills_count']} skills enabled, "
|
|
697
|
+
f"{summary['disabled_patterns_count']} patterns disabled"
|
|
698
|
+
)
|
|
699
|
+
|
|
700
|
+
config = SkillSourceConfiguration()
|
|
701
|
+
manager = GitSkillSourceManager(config)
|
|
702
|
+
|
|
703
|
+
# Get enabled sources
|
|
704
|
+
enabled_sources = config.get_enabled_sources()
|
|
705
|
+
if not enabled_sources:
|
|
706
|
+
return # No sources enabled, nothing to sync
|
|
707
|
+
|
|
708
|
+
# Phase 1: Sync files from Git sources
|
|
709
|
+
# We need to discover file count first to show accurate progress
|
|
710
|
+
# This requires pre-scanning repositories via GitHub API
|
|
711
|
+
from ..core.logger import get_logger
|
|
712
|
+
|
|
713
|
+
logger = get_logger("cli")
|
|
714
|
+
|
|
715
|
+
# Discover total file count across all sources
|
|
716
|
+
total_file_count = 0
|
|
717
|
+
total_skill_dirs = 0 # Count actual skill directories (folders with SKILL.md)
|
|
718
|
+
|
|
719
|
+
for source in enabled_sources:
|
|
720
|
+
try:
|
|
721
|
+
# Parse GitHub URL
|
|
722
|
+
url_parts = (
|
|
723
|
+
source.url.rstrip("/").replace(".git", "").split("github.com/")
|
|
724
|
+
)
|
|
725
|
+
if len(url_parts) == 2:
|
|
726
|
+
repo_path = url_parts[1].strip("/")
|
|
727
|
+
owner_repo = "/".join(repo_path.split("/")[:2])
|
|
728
|
+
|
|
729
|
+
# Use Tree API to discover all files
|
|
730
|
+
all_files = manager._discover_repository_files_via_tree_api(
|
|
731
|
+
owner_repo, source.branch
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
# Count relevant files (markdown, JSON)
|
|
735
|
+
relevant_files = [
|
|
736
|
+
f
|
|
737
|
+
for f in all_files
|
|
738
|
+
if f.endswith(".md") or f.endswith(".json") or f == ".gitignore"
|
|
739
|
+
]
|
|
740
|
+
total_file_count += len(relevant_files)
|
|
741
|
+
|
|
742
|
+
# Count skill directories (unique directories containing SKILL.md)
|
|
743
|
+
skill_dirs = set()
|
|
744
|
+
for f in all_files:
|
|
745
|
+
if f.endswith("/SKILL.md"):
|
|
746
|
+
# Extract directory path
|
|
747
|
+
skill_dir = "/".join(f.split("/")[:-1])
|
|
748
|
+
skill_dirs.add(skill_dir)
|
|
749
|
+
total_skill_dirs += len(skill_dirs)
|
|
750
|
+
|
|
751
|
+
except Exception as e:
|
|
752
|
+
logger.debug(f"Failed to discover files for {source.id}: {e}")
|
|
753
|
+
# Use estimate if discovery fails
|
|
754
|
+
total_file_count += 150
|
|
755
|
+
total_skill_dirs += 50 # Estimate ~50 skills
|
|
756
|
+
|
|
757
|
+
# Create progress bar for sync phase with actual file count
|
|
758
|
+
# Note: We sync files (md, json, etc.), but will deploy skill directories
|
|
759
|
+
sync_progress = ProgressBar(
|
|
760
|
+
total=total_file_count if total_file_count > 0 else 1,
|
|
761
|
+
prefix="Syncing skill files",
|
|
762
|
+
show_percentage=True,
|
|
763
|
+
show_counter=True,
|
|
764
|
+
)
|
|
765
|
+
|
|
766
|
+
# Sync all sources with progress callback
|
|
767
|
+
results = manager.sync_all_sources(
|
|
768
|
+
force=force_sync, progress_callback=sync_progress.update
|
|
769
|
+
)
|
|
770
|
+
|
|
771
|
+
# Finish sync progress bar with clear breakdown
|
|
772
|
+
downloaded = results["total_files_updated"]
|
|
773
|
+
cached = results["total_files_cached"]
|
|
774
|
+
total_files = downloaded + cached
|
|
775
|
+
|
|
776
|
+
if cached > 0:
|
|
777
|
+
sync_progress.finish(
|
|
778
|
+
f"Complete: {downloaded} downloaded, {cached} cached ({total_files} files, {total_skill_dirs} skills)"
|
|
779
|
+
)
|
|
780
|
+
else:
|
|
781
|
+
# All new downloads (first sync)
|
|
782
|
+
sync_progress.finish(
|
|
783
|
+
f"Complete: {downloaded} files downloaded ({total_skill_dirs} skills)"
|
|
784
|
+
)
|
|
785
|
+
|
|
786
|
+
# Phase 2: Scan agents and save to configuration.yaml
|
|
787
|
+
# This step populates configuration.yaml with agent-referenced skills
|
|
788
|
+
# CRITICAL: Always scan agents to populate agent_referenced, even when using cached skills.
|
|
789
|
+
# Without this, skill_filter=None causes ALL skills to deploy and NO cleanup to run.
|
|
790
|
+
agents_dir = Path.cwd() / ".claude" / "agents"
|
|
791
|
+
|
|
792
|
+
# Scan agents for skill requirements (ALWAYS run to ensure cleanup works)
|
|
793
|
+
agent_skills = get_required_skills_from_agents(agents_dir)
|
|
794
|
+
logger.info(
|
|
795
|
+
f"Agent scan found {len(agent_skills)} unique skills across deployed agents"
|
|
796
|
+
)
|
|
797
|
+
|
|
798
|
+
# Save to project-level configuration.yaml
|
|
799
|
+
project_config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
|
|
800
|
+
save_agent_skills_to_config(list(agent_skills), project_config_path)
|
|
801
|
+
logger.debug(
|
|
802
|
+
f"Saved {len(agent_skills)} agent-referenced skills to {project_config_path}"
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
# Phase 3: Resolve which skills to deploy (user_defined or agent_referenced)
|
|
806
|
+
skills_to_deploy, skill_source = get_skills_to_deploy(project_config_path)
|
|
807
|
+
|
|
808
|
+
# CRITICAL DEBUG: Log deployment resolution to diagnose cleanup issues
|
|
809
|
+
if skills_to_deploy:
|
|
810
|
+
logger.info(
|
|
811
|
+
f"Resolved {len(skills_to_deploy)} skills from {skill_source} (cleanup will run)"
|
|
812
|
+
)
|
|
813
|
+
else:
|
|
814
|
+
logger.warning(
|
|
815
|
+
f"No skills resolved from {skill_source} - will deploy ALL skills WITHOUT cleanup! "
|
|
816
|
+
f"This may indicate agent_referenced is empty in configuration.yaml."
|
|
817
|
+
)
|
|
818
|
+
|
|
819
|
+
# Phase 4: Apply profile filtering if active
|
|
820
|
+
if active_profile and profile_manager.active_profile:
|
|
821
|
+
# Filter skills based on profile
|
|
822
|
+
if skills_to_deploy:
|
|
823
|
+
# Filter the resolved skill list
|
|
824
|
+
original_count = len(skills_to_deploy)
|
|
825
|
+
filtered_skills = [
|
|
826
|
+
skill
|
|
827
|
+
for skill in skills_to_deploy
|
|
828
|
+
if profile_manager.is_skill_enabled(skill)
|
|
829
|
+
]
|
|
830
|
+
filtered_count = original_count - len(filtered_skills)
|
|
831
|
+
|
|
832
|
+
# SAFEGUARD: Warn if all skills were filtered out (misconfiguration)
|
|
833
|
+
if not filtered_skills and original_count > 0:
|
|
834
|
+
logger.warning(
|
|
835
|
+
f"Profile '{active_profile}' filtered ALL {original_count} skills. "
|
|
836
|
+
f"This may indicate a naming mismatch in the profile."
|
|
837
|
+
)
|
|
838
|
+
elif filtered_count > 0:
|
|
839
|
+
logger.info(
|
|
840
|
+
f"Profile '{active_profile}' filtered {filtered_count} skills "
|
|
841
|
+
f"({len(filtered_skills)} remaining)"
|
|
842
|
+
)
|
|
843
|
+
|
|
844
|
+
skills_to_deploy = filtered_skills
|
|
845
|
+
skill_source = f"{skill_source} + profile filtered"
|
|
846
|
+
else:
|
|
847
|
+
# No explicit skill list - filter from all available
|
|
848
|
+
all_skills = manager.get_all_skills()
|
|
849
|
+
filtered_skills = [
|
|
850
|
+
skill["name"]
|
|
851
|
+
for skill in all_skills
|
|
852
|
+
if profile_manager.is_skill_enabled(skill["name"])
|
|
853
|
+
]
|
|
854
|
+
skills_to_deploy = filtered_skills
|
|
855
|
+
skill_source = "profile filtered"
|
|
856
|
+
logger.info(
|
|
857
|
+
f"Profile '{active_profile}': "
|
|
858
|
+
f"{len(filtered_skills)} skills enabled from {len(all_skills)} available"
|
|
859
|
+
)
|
|
860
|
+
|
|
861
|
+
# Get all skills to determine counts
|
|
862
|
+
all_skills = manager.get_all_skills()
|
|
863
|
+
total_skill_count = len(all_skills)
|
|
864
|
+
|
|
865
|
+
# Determine skill count based on resolution
|
|
866
|
+
skill_count = len(skills_to_deploy) if skills_to_deploy else total_skill_count
|
|
867
|
+
|
|
868
|
+
if skill_count > 0:
|
|
869
|
+
# Deploy skills with resolved filter
|
|
870
|
+
# Deploy ONLY to project directory (not user-level)
|
|
871
|
+
# DESIGN DECISION: Project-level deployment keeps skills isolated per project,
|
|
872
|
+
# avoiding pollution of user's global ~/.claude/skills/ directory.
|
|
873
|
+
|
|
874
|
+
# Deploy to project-local directory with cleanup
|
|
875
|
+
deployment_result = manager.deploy_skills(
|
|
876
|
+
target_dir=Path.cwd() / ".claude" / "skills",
|
|
877
|
+
force=force_sync,
|
|
878
|
+
# CRITICAL FIX: Empty list should mean "deploy no skills", not "deploy all"
|
|
879
|
+
# When skills_to_deploy is [], we want skill_filter=set() NOT skill_filter=None
|
|
880
|
+
# None means "no filtering" (deploy all), empty set means "filter to nothing"
|
|
881
|
+
skill_filter=set(skills_to_deploy)
|
|
882
|
+
if skills_to_deploy is not None
|
|
883
|
+
else None,
|
|
884
|
+
)
|
|
885
|
+
|
|
886
|
+
# REMOVED: User-level deployment (lines 1068-1074)
|
|
887
|
+
# Reason: Skills should be project-specific, not user-global.
|
|
888
|
+
# Claude Code can read from project-level .claude/skills/ directory.
|
|
889
|
+
|
|
890
|
+
# Get actual counts from deployment result (use project-local for display)
|
|
891
|
+
deployed = deployment_result.get("deployed_count", 0)
|
|
892
|
+
skipped = deployment_result.get("skipped_count", 0)
|
|
893
|
+
filtered = deployment_result.get("filtered_count", 0)
|
|
894
|
+
removed = deployment_result.get("removed_count", 0)
|
|
895
|
+
total_available = deployed + skipped
|
|
896
|
+
|
|
897
|
+
# Only show progress bar if there are skills to deploy
|
|
898
|
+
if total_available > 0:
|
|
899
|
+
deploy_progress = ProgressBar(
|
|
900
|
+
total=total_available,
|
|
901
|
+
prefix="Deploying skill directories",
|
|
902
|
+
show_percentage=True,
|
|
903
|
+
show_counter=True,
|
|
904
|
+
)
|
|
905
|
+
# Update progress bar to completion
|
|
906
|
+
deploy_progress.update(total_available)
|
|
907
|
+
else:
|
|
908
|
+
# No skills to deploy - create dummy progress for message only
|
|
909
|
+
deploy_progress = ProgressBar(
|
|
910
|
+
total=1,
|
|
911
|
+
prefix="Deploying skill directories",
|
|
912
|
+
show_percentage=False,
|
|
913
|
+
show_counter=False,
|
|
914
|
+
)
|
|
915
|
+
deploy_progress.update(1)
|
|
916
|
+
|
|
917
|
+
# Show total available skills (deployed + already existing)
|
|
918
|
+
# Include source indication (user_defined vs agent_referenced)
|
|
919
|
+
# Note: total_skill_count is from cache, total_available is what's deployed/needed
|
|
920
|
+
source_label = (
|
|
921
|
+
"user override" if skill_source == "user_defined" else "from agents"
|
|
922
|
+
)
|
|
923
|
+
|
|
924
|
+
# Build finish message with cleanup info
|
|
925
|
+
if deployed > 0 or removed > 0:
|
|
926
|
+
parts = []
|
|
927
|
+
if deployed > 0:
|
|
928
|
+
parts.append(f"{deployed} new")
|
|
929
|
+
if skipped > 0:
|
|
930
|
+
parts.append(f"{skipped} unchanged")
|
|
931
|
+
if removed > 0:
|
|
932
|
+
parts.append(f"{removed} removed")
|
|
933
|
+
|
|
934
|
+
status = ", ".join(parts)
|
|
935
|
+
|
|
936
|
+
if filtered > 0:
|
|
937
|
+
deploy_progress.finish(
|
|
938
|
+
f"Complete: {status} ({total_available} {source_label}, {filtered} files in cache)"
|
|
939
|
+
)
|
|
940
|
+
else:
|
|
941
|
+
deploy_progress.finish(
|
|
942
|
+
f"Complete: {status} ({total_available} skills {source_label} from {total_skill_count} files in cache)"
|
|
943
|
+
)
|
|
944
|
+
elif filtered > 0:
|
|
945
|
+
# Skills filtered means agents require fewer skills than available
|
|
946
|
+
deploy_progress.finish(
|
|
947
|
+
f"No skills needed ({source_label}, {total_skill_count} files in cache)"
|
|
948
|
+
)
|
|
949
|
+
else:
|
|
950
|
+
# No changes - all skills already deployed
|
|
951
|
+
msg = f"Complete: {total_available} skills {source_label}"
|
|
952
|
+
if removed > 0:
|
|
953
|
+
msg += f", {removed} removed"
|
|
954
|
+
msg += f" ({total_skill_count} files in cache)"
|
|
955
|
+
deploy_progress.finish(msg)
|
|
956
|
+
|
|
957
|
+
# Log deployment errors if any
|
|
958
|
+
from ..core.logger import get_logger
|
|
959
|
+
|
|
960
|
+
logger = get_logger("cli")
|
|
961
|
+
|
|
962
|
+
errors = deployment_result.get("errors", [])
|
|
963
|
+
if errors:
|
|
964
|
+
logger.warning(
|
|
965
|
+
f"Skill deployment completed with {len(errors)} errors: {errors}"
|
|
966
|
+
)
|
|
967
|
+
|
|
968
|
+
# Log sync errors if any
|
|
969
|
+
if results["failed_count"] > 0:
|
|
970
|
+
logger.warning(
|
|
971
|
+
f"Skill sync completed with {results['failed_count']} failures"
|
|
972
|
+
)
|
|
973
|
+
|
|
974
|
+
except Exception as e:
|
|
975
|
+
# Non-critical - log but don't fail startup
|
|
976
|
+
from ..core.logger import get_logger
|
|
977
|
+
|
|
978
|
+
logger = get_logger("cli")
|
|
979
|
+
logger.debug(f"Failed to sync remote skills: {e}")
|
|
980
|
+
# Continue execution - skill sync failure shouldn't block startup
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
def show_agent_summary():
|
|
984
|
+
"""
|
|
985
|
+
Display agent availability summary on startup.
|
|
986
|
+
|
|
987
|
+
WHY: Users should see at a glance how many agents are available and installed
|
|
988
|
+
without having to run /mpm-agents list.
|
|
989
|
+
|
|
990
|
+
DESIGN DECISION: Fast, non-blocking check that counts agents from the deployment
|
|
991
|
+
directory. Shows simple "X installed / Y available" format. Failures are silent
|
|
992
|
+
to avoid blocking startup.
|
|
993
|
+
"""
|
|
994
|
+
try:
|
|
995
|
+
from pathlib import Path
|
|
996
|
+
|
|
997
|
+
# Count deployed agents (installed)
|
|
998
|
+
deploy_target = Path.cwd() / ".claude" / "agents"
|
|
999
|
+
installed_count = 0
|
|
1000
|
+
if deploy_target.exists():
|
|
1001
|
+
# Count .md files, excluding README and other docs
|
|
1002
|
+
agent_files = [
|
|
1003
|
+
f
|
|
1004
|
+
for f in deploy_target.glob("*.md")
|
|
1005
|
+
if not f.name.startswith(("README", "INSTRUCTIONS", "."))
|
|
1006
|
+
]
|
|
1007
|
+
installed_count = len(agent_files)
|
|
1008
|
+
|
|
1009
|
+
# Count available agents in cache (from remote sources)
|
|
1010
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
|
|
1011
|
+
available_count = 0
|
|
1012
|
+
if cache_dir.exists():
|
|
1013
|
+
# Use same filtering logic as agent deployment (lines 486-533 in startup.py)
|
|
1014
|
+
pm_templates = {
|
|
1015
|
+
"base-agent.md",
|
|
1016
|
+
"circuit_breakers.md",
|
|
1017
|
+
"pm_examples.md",
|
|
1018
|
+
"pm_red_flags.md",
|
|
1019
|
+
"research_gate_examples.md",
|
|
1020
|
+
"response_format.md",
|
|
1021
|
+
"ticket_completeness_examples.md",
|
|
1022
|
+
"validation_templates.md",
|
|
1023
|
+
"git_file_tracking.md",
|
|
1024
|
+
}
|
|
1025
|
+
doc_files = {
|
|
1026
|
+
"readme.md",
|
|
1027
|
+
"changelog.md",
|
|
1028
|
+
"contributing.md",
|
|
1029
|
+
"implementation-summary.md",
|
|
1030
|
+
"reorganization-plan.md",
|
|
1031
|
+
"auto-deploy-index.md",
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
# Find all markdown files in agents/ directories
|
|
1035
|
+
all_md_files = list(cache_dir.rglob("*.md"))
|
|
1036
|
+
agent_files = [
|
|
1037
|
+
f
|
|
1038
|
+
for f in all_md_files
|
|
1039
|
+
if (
|
|
1040
|
+
"/agents/" in str(f)
|
|
1041
|
+
and f.name.lower() not in pm_templates
|
|
1042
|
+
and f.name.lower() not in doc_files
|
|
1043
|
+
and f.name.lower() != "base-agent.md"
|
|
1044
|
+
and not any(
|
|
1045
|
+
part in str(f).split("/")
|
|
1046
|
+
for part in ["dist", "build", ".cache"]
|
|
1047
|
+
)
|
|
1048
|
+
)
|
|
1049
|
+
]
|
|
1050
|
+
available_count = len(agent_files)
|
|
1051
|
+
|
|
1052
|
+
# Display summary if we have agents
|
|
1053
|
+
if installed_count > 0 or available_count > 0:
|
|
1054
|
+
print(
|
|
1055
|
+
f"✓ Agents: {installed_count} deployed / {max(0, available_count - installed_count)} cached",
|
|
1056
|
+
flush=True,
|
|
1057
|
+
)
|
|
1058
|
+
|
|
1059
|
+
except Exception as e:
|
|
1060
|
+
# Silent failure - agent summary is informational only
|
|
1061
|
+
from ..core.logger import get_logger
|
|
1062
|
+
|
|
1063
|
+
logger = get_logger("cli")
|
|
1064
|
+
logger.debug(f"Failed to generate agent summary: {e}")
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
def show_skill_summary():
|
|
1068
|
+
"""
|
|
1069
|
+
Display skill availability summary on startup.
|
|
1070
|
+
|
|
1071
|
+
WHY: Users should see at a glance how many skills are deployed and available
|
|
1072
|
+
from cache, similar to the agent summary showing "X deployed / Y cached".
|
|
1073
|
+
|
|
1074
|
+
DESIGN DECISION: Fast, non-blocking check that counts skills from:
|
|
1075
|
+
- Deployed skills: PROJECT-level .claude/skills/ directory
|
|
1076
|
+
- Cached skills: ~/.claude-mpm/cache/skills/ directory (from remote sources)
|
|
1077
|
+
|
|
1078
|
+
Shows format: "✓ Skills: X deployed / Y cached"
|
|
1079
|
+
Failures are silent to avoid blocking startup.
|
|
1080
|
+
"""
|
|
1081
|
+
try:
|
|
1082
|
+
from pathlib import Path
|
|
1083
|
+
|
|
1084
|
+
# Count deployed skills (PROJECT-level, not user-level)
|
|
1085
|
+
project_skills_dir = Path.cwd() / ".claude" / "skills"
|
|
1086
|
+
deployed_count = 0
|
|
1087
|
+
if project_skills_dir.exists():
|
|
1088
|
+
# Count directories with SKILL.md (excludes collection repos)
|
|
1089
|
+
# Exclude collection directories (obra-superpowers, etc.)
|
|
1090
|
+
skill_dirs = [
|
|
1091
|
+
d
|
|
1092
|
+
for d in project_skills_dir.iterdir()
|
|
1093
|
+
if d.is_dir()
|
|
1094
|
+
and (d / "SKILL.md").exists()
|
|
1095
|
+
and not (d / ".git").exists() # Exclude collection repos
|
|
1096
|
+
]
|
|
1097
|
+
deployed_count = len(skill_dirs)
|
|
1098
|
+
|
|
1099
|
+
# Count cached skills (from remote sources, not deployed yet)
|
|
1100
|
+
# This matches the agent summary pattern: deployed vs cached
|
|
1101
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "skills"
|
|
1102
|
+
cached_count = 0
|
|
1103
|
+
if cache_dir.exists():
|
|
1104
|
+
# Scan all repository directories in cache
|
|
1105
|
+
# Cache structure: ~/.claude-mpm/cache/skills/{owner}/{repo}/...
|
|
1106
|
+
for repo_dir in cache_dir.rglob("*"):
|
|
1107
|
+
if not repo_dir.is_dir():
|
|
1108
|
+
continue
|
|
1109
|
+
|
|
1110
|
+
# Count skill directories (those with SKILL.md)
|
|
1111
|
+
# Skills can be nested in: skills/category/skill-name/SKILL.md
|
|
1112
|
+
# or in flat structure: skill-name/SKILL.md
|
|
1113
|
+
for root, dirs, files in os.walk(repo_dir):
|
|
1114
|
+
if "SKILL.md" in files:
|
|
1115
|
+
# Exclude build artifacts and hidden directories
|
|
1116
|
+
root_path = Path(root)
|
|
1117
|
+
if not any(
|
|
1118
|
+
part.startswith(".")
|
|
1119
|
+
or part in ["dist", "build", "__pycache__"]
|
|
1120
|
+
for part in root_path.parts
|
|
1121
|
+
):
|
|
1122
|
+
cached_count += 1
|
|
1123
|
+
|
|
1124
|
+
# Display summary using agent summary format: "X deployed / Y cached"
|
|
1125
|
+
# Only show non-deployed cached skills (subtract deployed from cached)
|
|
1126
|
+
non_deployed_cached = max(0, cached_count - deployed_count)
|
|
1127
|
+
if deployed_count > 0 or non_deployed_cached > 0:
|
|
1128
|
+
print(
|
|
1129
|
+
f"✓ Skills: {deployed_count} deployed / {non_deployed_cached} cached",
|
|
1130
|
+
flush=True,
|
|
1131
|
+
)
|
|
1132
|
+
|
|
1133
|
+
except Exception as e:
|
|
1134
|
+
# Silent failure - skill summary is informational only
|
|
1135
|
+
from ..core.logger import get_logger
|
|
1136
|
+
|
|
1137
|
+
logger = get_logger("cli")
|
|
1138
|
+
logger.debug(f"Failed to generate skill summary: {e}")
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
def verify_and_show_pm_skills():
|
|
1142
|
+
"""Verify PM skills and display status.
|
|
1143
|
+
|
|
1144
|
+
WHY: PM skills are essential for PM agent operation.
|
|
1145
|
+
Shows deployment status and auto-deploys if missing.
|
|
1146
|
+
"""
|
|
1147
|
+
try:
|
|
1148
|
+
from pathlib import Path
|
|
1149
|
+
|
|
1150
|
+
from ..services.pm_skills_deployer import PMSkillsDeployerService
|
|
1151
|
+
|
|
1152
|
+
deployer = PMSkillsDeployerService()
|
|
1153
|
+
project_dir = Path.cwd()
|
|
1154
|
+
|
|
1155
|
+
result = deployer.verify_pm_skills(project_dir)
|
|
1156
|
+
|
|
1157
|
+
if result.verified:
|
|
1158
|
+
# Show verified status
|
|
1159
|
+
print(f"✓ PM skills: {result.skill_count} verified", flush=True)
|
|
1160
|
+
else:
|
|
1161
|
+
# Auto-deploy if missing
|
|
1162
|
+
print("Deploying PM skills...", end="", flush=True)
|
|
1163
|
+
deploy_result = deployer.deploy_pm_skills(project_dir)
|
|
1164
|
+
if deploy_result.success:
|
|
1165
|
+
total = len(deploy_result.deployed) + len(deploy_result.skipped)
|
|
1166
|
+
print(f"\r✓ PM skills: {total} deployed" + " " * 20, flush=True)
|
|
1167
|
+
else:
|
|
1168
|
+
print("\r⚠ PM skills: deployment failed" + " " * 20, flush=True)
|
|
1169
|
+
|
|
1170
|
+
except ImportError:
|
|
1171
|
+
# PM skills deployer not available - skip silently
|
|
1172
|
+
pass
|
|
1173
|
+
except Exception as e:
|
|
1174
|
+
from ..core.logger import get_logger
|
|
1175
|
+
|
|
1176
|
+
logger = get_logger("cli")
|
|
1177
|
+
logger.debug(f"PM skills verification failed: {e}")
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
def auto_install_chrome_devtools_on_startup():
|
|
1181
|
+
"""
|
|
1182
|
+
Automatically install chrome-devtools-mcp on startup if enabled.
|
|
1183
|
+
|
|
1184
|
+
WHY: Browser automation capabilities should be available out-of-the-box without
|
|
1185
|
+
manual MCP server configuration. chrome-devtools-mcp provides powerful browser
|
|
1186
|
+
interaction tools for Claude Code.
|
|
1187
|
+
|
|
1188
|
+
DESIGN DECISION: Non-blocking installation that doesn't prevent startup if it fails.
|
|
1189
|
+
Respects user configuration setting (enabled by default). Only installs if not
|
|
1190
|
+
already configured in Claude.
|
|
1191
|
+
"""
|
|
1192
|
+
try:
|
|
1193
|
+
# Check if auto-install is disabled in config
|
|
1194
|
+
from ..config.config_loader import ConfigLoader
|
|
1195
|
+
|
|
1196
|
+
config_loader = ConfigLoader()
|
|
1197
|
+
try:
|
|
1198
|
+
config = config_loader.load_main_config()
|
|
1199
|
+
chrome_devtools_config = config.get("chrome_devtools", {})
|
|
1200
|
+
if not chrome_devtools_config.get("auto_install", True):
|
|
1201
|
+
# Auto-install disabled, skip silently
|
|
1202
|
+
return
|
|
1203
|
+
except Exception: # nosec B110
|
|
1204
|
+
# If config loading fails, assume auto-install is enabled (default)
|
|
1205
|
+
pass
|
|
1206
|
+
|
|
1207
|
+
# Import and run chrome-devtools installation
|
|
1208
|
+
from ..cli.chrome_devtools_installer import auto_install_chrome_devtools
|
|
1209
|
+
|
|
1210
|
+
auto_install_chrome_devtools(quiet=False)
|
|
1211
|
+
|
|
1212
|
+
except Exception as e:
|
|
1213
|
+
# Import logger here to avoid circular imports
|
|
1214
|
+
from ..core.logger import get_logger
|
|
1215
|
+
|
|
1216
|
+
logger = get_logger("cli")
|
|
1217
|
+
logger.debug(f"Failed to auto-install chrome-devtools-mcp: {e}")
|
|
1218
|
+
# Continue execution - chrome-devtools installation failure shouldn't block startup
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
def run_background_services(force_sync: bool = False):
|
|
1222
|
+
"""
|
|
1223
|
+
Initialize all background services on startup.
|
|
1224
|
+
|
|
1225
|
+
WHY: Centralizes all startup service initialization for cleaner main().
|
|
1226
|
+
|
|
1227
|
+
NOTE: System instructions (PM_INSTRUCTIONS.md, WORKFLOW.md, MEMORY.md) and
|
|
1228
|
+
templates do NOT deploy automatically on startup. They only deploy when user
|
|
1229
|
+
explicitly requests them via agent-manager commands. This prevents unwanted
|
|
1230
|
+
file creation in project .claude/ directories.
|
|
1231
|
+
See: SystemInstructionsDeployer and agent_deployment.py line 504-509
|
|
1232
|
+
|
|
1233
|
+
Args:
|
|
1234
|
+
force_sync: Force download even if cache is fresh (bypasses ETag).
|
|
1235
|
+
"""
|
|
1236
|
+
# Sync hooks early to ensure up-to-date configuration
|
|
1237
|
+
# RATIONALE: Hooks should be synced before other services to fix stale configs
|
|
1238
|
+
# This is fast (<100ms) and non-blocking, so it doesn't delay startup
|
|
1239
|
+
sync_hooks_on_startup() # Shows "Syncing Claude Code hooks... ✓"
|
|
1240
|
+
|
|
1241
|
+
initialize_project_registry()
|
|
1242
|
+
check_mcp_auto_configuration()
|
|
1243
|
+
verify_mcp_gateway_startup()
|
|
1244
|
+
check_for_updates_async()
|
|
1245
|
+
sync_remote_agents_on_startup(
|
|
1246
|
+
force_sync=force_sync
|
|
1247
|
+
) # Sync agents from remote sources
|
|
1248
|
+
show_agent_summary() # Display agent counts after deployment
|
|
1249
|
+
|
|
1250
|
+
# Skills deployment order (precedence: remote > bundled)
|
|
1251
|
+
# 1. Deploy bundled skills first (base layer from package)
|
|
1252
|
+
# 2. Sync and deploy remote skills (Git sources, can override bundled)
|
|
1253
|
+
# 3. Discover and link runtime skills (user-added skills)
|
|
1254
|
+
# This ensures remote skills take precedence over bundled skills when names conflict
|
|
1255
|
+
deploy_bundled_skills() # Base layer: package-bundled skills
|
|
1256
|
+
sync_remote_skills_on_startup(
|
|
1257
|
+
force_sync=force_sync
|
|
1258
|
+
) # Override layer: Git-based skills (takes precedence)
|
|
1259
|
+
discover_and_link_runtime_skills() # Discovery: user-added skills
|
|
1260
|
+
show_skill_summary() # Display skill counts after deployment
|
|
1261
|
+
verify_and_show_pm_skills() # PM skills verification and status
|
|
1262
|
+
|
|
1263
|
+
deploy_output_style_on_startup()
|
|
1264
|
+
|
|
1265
|
+
# Auto-install chrome-devtools-mcp for browser automation
|
|
1266
|
+
auto_install_chrome_devtools_on_startup()
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
def setup_mcp_server_logging(args):
|
|
1270
|
+
"""
|
|
1271
|
+
Configure minimal logging for MCP server mode.
|
|
1272
|
+
|
|
1273
|
+
WHY: MCP server needs minimal stderr-only logging to avoid interfering
|
|
1274
|
+
with stdout protocol communication.
|
|
1275
|
+
|
|
1276
|
+
Args:
|
|
1277
|
+
args: Parsed arguments
|
|
1278
|
+
|
|
1279
|
+
Returns:
|
|
1280
|
+
Configured logger
|
|
1281
|
+
"""
|
|
1282
|
+
import logging
|
|
1283
|
+
|
|
1284
|
+
from ..cli.utils import setup_logging
|
|
1285
|
+
from ..constants import CLICommands
|
|
1286
|
+
|
|
1287
|
+
if (
|
|
1288
|
+
args.command == CLICommands.MCP.value
|
|
1289
|
+
and getattr(args, "mcp_command", None) == "start"
|
|
1290
|
+
):
|
|
1291
|
+
if not getattr(args, "test", False) and not getattr(
|
|
1292
|
+
args, "instructions", False
|
|
1293
|
+
):
|
|
1294
|
+
# Production MCP mode - minimal logging
|
|
1295
|
+
logging.basicConfig(
|
|
1296
|
+
level=logging.ERROR,
|
|
1297
|
+
format="%(message)s",
|
|
1298
|
+
stream=sys.stderr,
|
|
1299
|
+
force=True,
|
|
1300
|
+
)
|
|
1301
|
+
return logging.getLogger("claude_mpm")
|
|
1302
|
+
# Test or instructions mode - normal logging
|
|
1303
|
+
return setup_logging(args)
|
|
1304
|
+
# Normal logging for all other commands
|
|
1305
|
+
return setup_logging(args)
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
def initialize_project_registry():
|
|
1309
|
+
"""
|
|
1310
|
+
Initialize or update the project registry for the current session.
|
|
1311
|
+
|
|
1312
|
+
WHY: The project registry tracks all claude-mpm projects and their metadata
|
|
1313
|
+
across sessions. This function ensures the current project is properly
|
|
1314
|
+
registered and updates session information.
|
|
1315
|
+
|
|
1316
|
+
DESIGN DECISION: Registry failures are logged but don't prevent startup
|
|
1317
|
+
to ensure claude-mpm remains functional even if registry operations fail.
|
|
1318
|
+
"""
|
|
1319
|
+
try:
|
|
1320
|
+
from ..services.project.registry import ProjectRegistry
|
|
1321
|
+
|
|
1322
|
+
registry = ProjectRegistry()
|
|
1323
|
+
registry.get_or_create_project_entry()
|
|
1324
|
+
except Exception as e:
|
|
1325
|
+
# Import logger here to avoid circular imports
|
|
1326
|
+
from ..core.logger import get_logger
|
|
1327
|
+
|
|
1328
|
+
logger = get_logger("cli")
|
|
1329
|
+
logger.debug(f"Failed to initialize project registry: {e}")
|
|
1330
|
+
# Continue execution - registry failure shouldn't block startup
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
def check_mcp_auto_configuration():
|
|
1334
|
+
"""
|
|
1335
|
+
Check and potentially auto-configure MCP for pipx installations.
|
|
1336
|
+
|
|
1337
|
+
WHY: Users installing via pipx should have MCP work out-of-the-box with
|
|
1338
|
+
minimal friction. This function offers one-time auto-configuration with
|
|
1339
|
+
user consent.
|
|
1340
|
+
|
|
1341
|
+
DESIGN DECISION: This is blocking but quick - it only runs once and has
|
|
1342
|
+
a 10-second timeout. Shows progress feedback during checks to avoid
|
|
1343
|
+
appearing frozen.
|
|
1344
|
+
|
|
1345
|
+
OPTIMIZATION: Skip ALL MCP checks for doctor and configure commands to avoid
|
|
1346
|
+
duplicate checks (doctor performs its own comprehensive check, configure
|
|
1347
|
+
allows users to select services).
|
|
1348
|
+
"""
|
|
1349
|
+
# Skip MCP service checks for the doctor and configure commands
|
|
1350
|
+
# The doctor command performs its own comprehensive MCP service check
|
|
1351
|
+
# The configure command allows users to configure which services to enable
|
|
1352
|
+
# Running both would cause duplicate checks and log messages (9 seconds apart)
|
|
1353
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("doctor", "configure"):
|
|
1354
|
+
return
|
|
1355
|
+
|
|
1356
|
+
try:
|
|
1357
|
+
from ..services.mcp_gateway.auto_configure import check_and_configure_mcp
|
|
1358
|
+
|
|
1359
|
+
# Show progress feedback - this operation can take 10+ seconds
|
|
1360
|
+
print("Checking MCP configuration...", end="", flush=True)
|
|
1361
|
+
|
|
1362
|
+
# This function handles all the logic:
|
|
1363
|
+
# - Checks if already configured
|
|
1364
|
+
# - Checks if pipx installation
|
|
1365
|
+
# - Checks if already asked before
|
|
1366
|
+
# - Prompts user if needed
|
|
1367
|
+
# - Configures if user agrees
|
|
1368
|
+
check_and_configure_mcp()
|
|
1369
|
+
|
|
1370
|
+
# Clear the "Checking..." message by overwriting with spaces
|
|
1371
|
+
print("\r" + " " * 30 + "\r", end="", flush=True)
|
|
1372
|
+
|
|
1373
|
+
except Exception as e:
|
|
1374
|
+
# Clear progress message on error
|
|
1375
|
+
print("\r" + " " * 30 + "\r", end="", flush=True)
|
|
1376
|
+
|
|
1377
|
+
# Non-critical - log but don't fail
|
|
1378
|
+
from ..core.logger import get_logger
|
|
1379
|
+
|
|
1380
|
+
logger = get_logger("cli")
|
|
1381
|
+
logger.debug(f"MCP auto-configuration check failed: {e}")
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
def verify_mcp_gateway_startup():
|
|
1385
|
+
"""
|
|
1386
|
+
Verify MCP Gateway configuration on startup and pre-warm MCP services.
|
|
1387
|
+
|
|
1388
|
+
WHY: The MCP gateway should be automatically configured and verified on startup
|
|
1389
|
+
to provide a seamless experience with diagnostic tools, file summarizer, and
|
|
1390
|
+
ticket service. Pre-warming MCP services eliminates the 11.9s delay on first use.
|
|
1391
|
+
|
|
1392
|
+
DESIGN DECISION: This is non-blocking - failures are logged but don't prevent
|
|
1393
|
+
startup to ensure claude-mpm remains functional even if MCP gateway has issues.
|
|
1394
|
+
"""
|
|
1395
|
+
# DISABLED: MCP service verification removed - Claude Code handles MCP natively
|
|
1396
|
+
# The previous check warned about missing MCP services, but users should configure
|
|
1397
|
+
# MCP servers through Claude Code's native MCP management, not through claude-mpm.
|
|
1398
|
+
# See: https://docs.anthropic.com/en/docs/claude-code/mcp
|
|
1399
|
+
|
|
1400
|
+
try:
|
|
1401
|
+
import asyncio
|
|
1402
|
+
|
|
1403
|
+
from ..core.logger import get_logger
|
|
1404
|
+
from ..services.mcp_gateway.core.startup_verification import (
|
|
1405
|
+
is_mcp_gateway_configured,
|
|
1406
|
+
verify_mcp_gateway_on_startup,
|
|
1407
|
+
)
|
|
1408
|
+
|
|
1409
|
+
logger = get_logger("mcp_prewarm")
|
|
1410
|
+
|
|
1411
|
+
# Quick check first - if already configured, skip detailed verification
|
|
1412
|
+
gateway_configured = is_mcp_gateway_configured()
|
|
1413
|
+
|
|
1414
|
+
# DISABLED: Pre-warming MCP servers can interfere with Claude Code's MCP management
|
|
1415
|
+
# This was causing issues with MCP server initialization and stderr handling
|
|
1416
|
+
# Pre-warming functionality has been removed. Gateway verification only runs
|
|
1417
|
+
# if MCP gateway is not already configured.
|
|
1418
|
+
|
|
1419
|
+
# Run gateway verification in background if not configured
|
|
1420
|
+
if not gateway_configured:
|
|
1421
|
+
|
|
1422
|
+
def run_verification():
|
|
1423
|
+
"""Background thread to verify MCP gateway configuration."""
|
|
1424
|
+
loop = None
|
|
1425
|
+
try:
|
|
1426
|
+
loop = asyncio.new_event_loop()
|
|
1427
|
+
asyncio.set_event_loop(loop)
|
|
1428
|
+
results = loop.run_until_complete(verify_mcp_gateway_on_startup())
|
|
1429
|
+
|
|
1430
|
+
# Log results but don't block
|
|
1431
|
+
from ..core.logger import get_logger
|
|
1432
|
+
|
|
1433
|
+
logger = get_logger("cli")
|
|
1434
|
+
|
|
1435
|
+
if results.get("gateway_configured"):
|
|
1436
|
+
logger.debug("MCP Gateway verification completed successfully")
|
|
1437
|
+
else:
|
|
1438
|
+
logger.debug("MCP Gateway verification completed with warnings")
|
|
1439
|
+
|
|
1440
|
+
except Exception as e:
|
|
1441
|
+
from ..core.logger import get_logger
|
|
1442
|
+
|
|
1443
|
+
logger = get_logger("cli")
|
|
1444
|
+
logger.debug(f"MCP Gateway verification failed: {e}")
|
|
1445
|
+
finally:
|
|
1446
|
+
# Properly clean up event loop to prevent kqueue warnings
|
|
1447
|
+
if loop is not None:
|
|
1448
|
+
try:
|
|
1449
|
+
# Cancel all running tasks
|
|
1450
|
+
pending = asyncio.all_tasks(loop)
|
|
1451
|
+
for task in pending:
|
|
1452
|
+
task.cancel()
|
|
1453
|
+
# Wait for tasks to complete cancellation
|
|
1454
|
+
if pending:
|
|
1455
|
+
loop.run_until_complete(
|
|
1456
|
+
asyncio.gather(*pending, return_exceptions=True)
|
|
1457
|
+
)
|
|
1458
|
+
except Exception: # nosec B110
|
|
1459
|
+
pass # Ignore cleanup errors
|
|
1460
|
+
finally:
|
|
1461
|
+
loop.close()
|
|
1462
|
+
# Clear the event loop reference to help with cleanup
|
|
1463
|
+
asyncio.set_event_loop(None)
|
|
1464
|
+
|
|
1465
|
+
# Run in background thread to avoid blocking startup
|
|
1466
|
+
import threading
|
|
1467
|
+
|
|
1468
|
+
verification_thread = threading.Thread(target=run_verification, daemon=True)
|
|
1469
|
+
verification_thread.start()
|
|
1470
|
+
|
|
1471
|
+
except Exception as e:
|
|
1472
|
+
# Import logger here to avoid circular imports
|
|
1473
|
+
from ..core.logger import get_logger
|
|
1474
|
+
|
|
1475
|
+
logger = get_logger("cli")
|
|
1476
|
+
logger.debug(f"Failed to start MCP Gateway verification: {e}")
|
|
1477
|
+
# Continue execution - MCP gateway issues shouldn't block startup
|
|
1478
|
+
|
|
1479
|
+
|
|
1480
|
+
def check_for_updates_async():
|
|
1481
|
+
"""
|
|
1482
|
+
Check for updates in background thread (non-blocking).
|
|
1483
|
+
|
|
1484
|
+
WHY: Users should be notified of new versions and have an easy way to upgrade
|
|
1485
|
+
without manually checking PyPI/npm. This runs asynchronously on startup to avoid
|
|
1486
|
+
blocking the CLI.
|
|
1487
|
+
|
|
1488
|
+
DESIGN DECISION: This is non-blocking and non-critical - failures are logged
|
|
1489
|
+
but don't prevent startup. Only runs for pip/pipx/npm installations, skips
|
|
1490
|
+
editable/development installations. Respects user configuration settings.
|
|
1491
|
+
"""
|
|
1492
|
+
|
|
1493
|
+
def run_update_check():
|
|
1494
|
+
"""Inner function to run in background thread."""
|
|
1495
|
+
loop = None
|
|
1496
|
+
try:
|
|
1497
|
+
import asyncio
|
|
1498
|
+
|
|
1499
|
+
from ..core.config import Config
|
|
1500
|
+
from ..core.logger import get_logger
|
|
1501
|
+
from ..services.self_upgrade_service import SelfUpgradeService
|
|
1502
|
+
|
|
1503
|
+
logger = get_logger("upgrade_check")
|
|
1504
|
+
|
|
1505
|
+
# Load configuration
|
|
1506
|
+
config = Config()
|
|
1507
|
+
updates_config = config.get("updates", {})
|
|
1508
|
+
|
|
1509
|
+
# Check if update checking is enabled
|
|
1510
|
+
if not updates_config.get("check_enabled", True):
|
|
1511
|
+
logger.debug("Update checking disabled in configuration")
|
|
1512
|
+
return
|
|
1513
|
+
|
|
1514
|
+
# Check frequency setting
|
|
1515
|
+
frequency = updates_config.get("check_frequency", "daily")
|
|
1516
|
+
if frequency == "never":
|
|
1517
|
+
logger.debug("Update checking frequency set to 'never'")
|
|
1518
|
+
return
|
|
1519
|
+
|
|
1520
|
+
# Create new event loop for this thread
|
|
1521
|
+
loop = asyncio.new_event_loop()
|
|
1522
|
+
asyncio.set_event_loop(loop)
|
|
1523
|
+
|
|
1524
|
+
# Create upgrade service and check for updates
|
|
1525
|
+
upgrade_service = SelfUpgradeService()
|
|
1526
|
+
|
|
1527
|
+
# Skip for editable installs (development mode)
|
|
1528
|
+
from ..services.self_upgrade_service import InstallationMethod
|
|
1529
|
+
|
|
1530
|
+
if upgrade_service.installation_method == InstallationMethod.EDITABLE:
|
|
1531
|
+
logger.debug("Skipping version check for editable installation")
|
|
1532
|
+
return
|
|
1533
|
+
|
|
1534
|
+
# Get configuration values
|
|
1535
|
+
check_claude_code = updates_config.get("check_claude_code", True)
|
|
1536
|
+
auto_upgrade = updates_config.get("auto_upgrade", False)
|
|
1537
|
+
|
|
1538
|
+
# Check and prompt for upgrade if available (non-blocking)
|
|
1539
|
+
loop.run_until_complete(
|
|
1540
|
+
upgrade_service.check_and_prompt_on_startup(
|
|
1541
|
+
auto_upgrade=auto_upgrade, check_claude_code=check_claude_code
|
|
1542
|
+
)
|
|
1543
|
+
)
|
|
1544
|
+
|
|
1545
|
+
except Exception as e:
|
|
1546
|
+
# Non-critical - log but don't fail startup
|
|
1547
|
+
try:
|
|
1548
|
+
from ..core.logger import get_logger
|
|
1549
|
+
|
|
1550
|
+
logger = get_logger("upgrade_check")
|
|
1551
|
+
logger.debug(f"Update check failed (non-critical): {e}")
|
|
1552
|
+
except Exception: # nosec B110
|
|
1553
|
+
pass # Avoid any errors in error handling
|
|
1554
|
+
finally:
|
|
1555
|
+
# Properly clean up event loop
|
|
1556
|
+
if loop is not None:
|
|
1557
|
+
try:
|
|
1558
|
+
# Cancel all running tasks
|
|
1559
|
+
pending = asyncio.all_tasks(loop)
|
|
1560
|
+
for task in pending:
|
|
1561
|
+
task.cancel()
|
|
1562
|
+
# Wait for tasks to complete cancellation
|
|
1563
|
+
if pending:
|
|
1564
|
+
loop.run_until_complete(
|
|
1565
|
+
asyncio.gather(*pending, return_exceptions=True)
|
|
1566
|
+
)
|
|
1567
|
+
except Exception: # nosec B110
|
|
1568
|
+
pass # Ignore cleanup errors
|
|
1569
|
+
finally:
|
|
1570
|
+
loop.close()
|
|
1571
|
+
# Clear the event loop reference to help with cleanup
|
|
1572
|
+
asyncio.set_event_loop(None)
|
|
1573
|
+
|
|
1574
|
+
# Run update check in background thread to avoid blocking startup
|
|
1575
|
+
import threading
|
|
1576
|
+
|
|
1577
|
+
update_check_thread = threading.Thread(target=run_update_check, daemon=True)
|
|
1578
|
+
update_check_thread.start()
|