claude-mpm 5.4.65__py3-none-any.whl → 5.6.10__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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +107 -1928
- claude_mpm/agents/PM_INSTRUCTIONS.md +119 -689
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agents.py +2 -4
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +46 -0
- claude_mpm/cli/commands/configure.py +620 -21
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +2 -2
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +171 -17
- claude_mpm/cli/executor.py +120 -16
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +30 -50
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/base_parser.py +76 -1
- claude_mpm/cli/parsers/commander_parser.py +83 -0
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +5 -0
- claude_mpm/cli/startup.py +203 -359
- claude_mpm/cli/startup_display.py +72 -5
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +72 -0
- claude_mpm/commander/adapters/__init__.py +31 -0
- claude_mpm/commander/adapters/base.py +191 -0
- claude_mpm/commander/adapters/claude_code.py +361 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +105 -0
- claude_mpm/commander/api/errors.py +133 -0
- claude_mpm/commander/api/routes/__init__.py +8 -0
- claude_mpm/commander/api/routes/events.py +184 -0
- claude_mpm/commander/api/routes/inbox.py +171 -0
- claude_mpm/commander/api/routes/messages.py +148 -0
- claude_mpm/commander/api/routes/projects.py +271 -0
- claude_mpm/commander/api/routes/sessions.py +228 -0
- claude_mpm/commander/api/routes/work.py +260 -0
- claude_mpm/commander/api/schemas.py +182 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +107 -0
- claude_mpm/commander/chat/commands.py +96 -0
- claude_mpm/commander/chat/repl.py +310 -0
- claude_mpm/commander/config.py +49 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/daemon.py +398 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +332 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +143 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +62 -0
- claude_mpm/commander/inbox/__init__.py +16 -0
- claude_mpm/commander/inbox/dedup.py +128 -0
- claude_mpm/commander/inbox/inbox.py +224 -0
- claude_mpm/commander/inbox/models.py +70 -0
- claude_mpm/commander/instance_manager.py +337 -0
- claude_mpm/commander/llm/__init__.py +6 -0
- claude_mpm/commander/llm/openrouter_client.py +167 -0
- claude_mpm/commander/llm/summarizer.py +70 -0
- claude_mpm/commander/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +121 -0
- claude_mpm/commander/models/project.py +162 -0
- claude_mpm/commander/models/work.py +214 -0
- claude_mpm/commander/parsing/__init__.py +20 -0
- claude_mpm/commander/parsing/extractor.py +132 -0
- claude_mpm/commander/parsing/output_parser.py +270 -0
- claude_mpm/commander/parsing/patterns.py +100 -0
- claude_mpm/commander/persistence/__init__.py +11 -0
- claude_mpm/commander/persistence/event_store.py +274 -0
- claude_mpm/commander/persistence/state_store.py +309 -0
- claude_mpm/commander/persistence/work_store.py +164 -0
- claude_mpm/commander/polling/__init__.py +13 -0
- claude_mpm/commander/polling/event_detector.py +104 -0
- claude_mpm/commander/polling/output_buffer.py +49 -0
- claude_mpm/commander/polling/output_poller.py +153 -0
- claude_mpm/commander/project_session.py +268 -0
- claude_mpm/commander/proxy/__init__.py +12 -0
- claude_mpm/commander/proxy/formatter.py +89 -0
- claude_mpm/commander/proxy/output_handler.py +191 -0
- claude_mpm/commander/proxy/relay.py +155 -0
- claude_mpm/commander/registry.py +404 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +316 -0
- claude_mpm/commander/session/__init__.py +6 -0
- claude_mpm/commander/session/context.py +81 -0
- claude_mpm/commander/session/manager.py +59 -0
- claude_mpm/commander/tmux_orchestrator.py +361 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +189 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +219 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +8 -0
- claude_mpm/commands/mpm-doctor.md +8 -0
- claude_mpm/commands/mpm-help.md +8 -0
- claude_mpm/commands/mpm-init.md +8 -0
- claude_mpm/commands/mpm-monitor.md +8 -0
- claude_mpm/commands/mpm-organize.md +8 -0
- claude_mpm/commands/mpm-postmortem.md +8 -0
- claude_mpm/commands/mpm-session-resume.md +9 -1
- claude_mpm/commands/mpm-status.md +8 -0
- claude_mpm/commands/mpm-ticket-view.md +8 -0
- claude_mpm/commands/mpm-version.md +8 -0
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/config/skill_sources.py +16 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +2 -2
- claude_mpm/core/config.py +32 -19
- claude_mpm/core/hook_manager.py +51 -3
- claude_mpm/core/interactive_session.py +7 -7
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +35 -11
- claude_mpm/core/output_style_manager.py +31 -13
- claude_mpm/core/unified_config.py +54 -8
- claude_mpm/core/unified_paths.py +95 -90
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cs_tUR18.js → 1WZnGYqX.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CDuw-vjf.js → 67pF3qNn.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bTOqqlTd.js → 6RxdMKe4.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DwBR2MJi.js → 8cZrfX0h.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{ZGh7QtNv.js → 9a6T2nm-.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D9lljYKQ.js → B443AUzu.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{RJiighC3.js → B8AwtY2H.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uuIeMWc-.js → BF15LAsF.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D3k0OPJN.js → BRcwIQNr.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CyWMqx4W.js → BV6nKitt.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CiIAseT4.js → BViJ8lZt.js} +5 -5
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CBBdVcY8.js → BcQ-Q0FE.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BovzEFCE.js → Bpyvgze_.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{eNVUfhuA.js → C3rbW_a-.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{GYwsonyD.js → C8WYN38h.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BIF9m_hv.js → C9I8FlXH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B0uc0UOD.js → CIQcWgO2.js} +3 -3
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Be7GpZd6.js → CIctN7YN.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Bh0LDWpI.js → CKrS_JZW.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DUrLdbGD.js → CR6P9C4A.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7xVLGWV.js → CRRR9MD_.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dhb8PKl3.js → CSXtMOf0.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BPYeabCQ.js → CT-sbxSk.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{sQeU3Y1z.js → CWm6DJsp.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CnA0NrzZ.js → CpqQ1Kzn.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4B-KCzX.js → D2nGpDRe.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DGkLK5U1.js → D9iCMida.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BofRWZRR.js → D9ykgMoY.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DmxopI1J.js → DL2Ldur1.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C30mlcqg.js → DPfltzjH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Vzk33B_K.js → DR8nis88.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DI7hHRFL.js → DUliQN2b.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4JcI4KD.js → DXlhR01x.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bT1r9zLR.js → D_lyTybS.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DZX00Y4g.js → DngoTTgh.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzZX-COe.js → DqkmHtDC.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7RN905-.js → DsDh8EYs.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DLVjFsZ3.js → DypDmXgd.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{iEWssX7S.js → IPYC-LnN.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DaimHw_p.js → JpevfAFt.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DY1XQ8fi.js → R8CEIRAd.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dle-35c7.js → Zxy7qc-l.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C_Usid8X.js → qtd3IeO4.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzeYkLYB.js → ulBFON_C.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cfqx1Qun.js → wQVh1CoA.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/{app.D6-I5TpK.js → app.Dr7t0z2J.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.m1gL8KXf.js → 0.RgBboRvH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{1.CgNOuw-d.js → 1.DG-KkbDf.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
- claude_mpm/dashboard/static/svelte-build/index.html +9 -9
- claude_mpm/experimental/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
- claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +283 -87
- claude_mpm/hooks/claude_hooks/hook_handler.py +106 -89
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +116 -8
- claude_mpm/hooks/claude_hooks/memory_integration.py +51 -31
- claude_mpm/hooks/claude_hooks/response_tracking.py +42 -59
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +39 -24
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +36 -103
- claude_mpm/hooks/claude_hooks/services/state_manager.py +23 -36
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +73 -75
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_template.py +10 -2
- claude_mpm/init.py +1 -1
- claude_mpm/scripts/claude-hook-handler.sh +43 -16
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/cache_git_manager.py +1 -1
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +3 -0
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
- claude_mpm/services/agents/startup_sync.py +5 -2
- claude_mpm/services/cli/__init__.py +3 -0
- claude_mpm/services/cli/incremental_pause_manager.py +561 -0
- claude_mpm/services/cli/session_resume_helper.py +10 -2
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
- claude_mpm/services/diagnostics/models.py +14 -1
- claude_mpm/services/event_log.py +325 -0
- claude_mpm/services/infrastructure/__init__.py +4 -0
- claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
- claude_mpm/services/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +8 -2
- claude_mpm/services/monitor/server.py +106 -16
- claude_mpm/services/pm_skills_deployer.py +259 -87
- claude_mpm/services/skills/git_skill_source_manager.py +135 -11
- claude_mpm/services/skills/selective_skill_deployer.py +142 -26
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +31 -5
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
- claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
- claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
- claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
- claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
- claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
- claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
- claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
- claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
- claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
- claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/skill_manager.py +4 -4
- claude_mpm/utils/agent_dependency_loader.py +4 -2
- claude_mpm/utils/robust_installer.py +10 -6
- claude_mpm-5.6.10.dist-info/METADATA +391 -0
- {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/RECORD +303 -181
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +0 -24
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +0 -323
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +0 -1
- claude_mpm-5.4.65.dist-info/METADATA +0 -999
- /claude_mpm/skills/bundled/pm/{pm-delegation-patterns → mpm-delegation-patterns}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-git-file-tracking → mpm-git-file-tracking}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-pr-workflow → mpm-pr-workflow}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-ticketing-integration → mpm-ticketing-integration}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-verification-protocols → mpm-verification-protocols}/SKILL.md +0 -0
- {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/top_level.txt +0 -0
claude_mpm/cli/startup.py
CHANGED
|
@@ -161,7 +161,25 @@ def setup_early_environment(argv):
|
|
|
161
161
|
# CRITICAL: Suppress ALL logging by default
|
|
162
162
|
# This catches all loggers (claude_mpm.*, service.*, framework_loader, etc.)
|
|
163
163
|
# This will be overridden by setup_mcp_server_logging() based on user preference
|
|
164
|
-
logging.getLogger()
|
|
164
|
+
root_logger = logging.getLogger()
|
|
165
|
+
root_logger.setLevel(logging.CRITICAL + 1) # Root logger catches everything
|
|
166
|
+
root_logger.handlers = [] # Remove any handlers
|
|
167
|
+
|
|
168
|
+
# Also suppress common module loggers explicitly to prevent handler leakage
|
|
169
|
+
for logger_name in [
|
|
170
|
+
"claude_mpm",
|
|
171
|
+
"path_resolver",
|
|
172
|
+
"file_loader",
|
|
173
|
+
"framework_loader",
|
|
174
|
+
"service",
|
|
175
|
+
"instruction_loader",
|
|
176
|
+
"agent_loader",
|
|
177
|
+
"startup",
|
|
178
|
+
]:
|
|
179
|
+
module_logger = logging.getLogger(logger_name)
|
|
180
|
+
module_logger.setLevel(logging.CRITICAL + 1)
|
|
181
|
+
module_logger.handlers = []
|
|
182
|
+
module_logger.propagate = False
|
|
165
183
|
|
|
166
184
|
# Process argv
|
|
167
185
|
if argv is None:
|
|
@@ -191,7 +209,8 @@ def should_skip_background_services(args, processed_argv):
|
|
|
191
209
|
skip_commands = ["--version", "-v", "--help", "-h"]
|
|
192
210
|
return any(cmd in (processed_argv or sys.argv[1:]) for cmd in skip_commands) or (
|
|
193
211
|
hasattr(args, "command")
|
|
194
|
-
and args.command
|
|
212
|
+
and args.command
|
|
213
|
+
in ["info", "doctor", "config", "mcp", "configure", "hook-errors", "autotodos"]
|
|
195
214
|
)
|
|
196
215
|
|
|
197
216
|
|
|
@@ -234,7 +253,7 @@ def deploy_bundled_skills():
|
|
|
234
253
|
if not skills_config.get("auto_deploy", True):
|
|
235
254
|
# Auto-deploy disabled, skip silently
|
|
236
255
|
return
|
|
237
|
-
except Exception:
|
|
256
|
+
except Exception: # nosec B110
|
|
238
257
|
# If config loading fails, assume auto-deploy is enabled (default)
|
|
239
258
|
pass
|
|
240
259
|
|
|
@@ -308,68 +327,60 @@ def deploy_output_style_on_startup():
|
|
|
308
327
|
communication without emojis and exclamation points. Styles are project-specific
|
|
309
328
|
to allow different projects to have different communication styles.
|
|
310
329
|
|
|
311
|
-
DESIGN DECISION: This is non-blocking and idempotent. Deploys to
|
|
312
|
-
directory (
|
|
313
|
-
|
|
330
|
+
DESIGN DECISION: This is non-blocking and idempotent. Deploys to user-level
|
|
331
|
+
directory (~/.claude/output-styles/) which is the official Claude Code location
|
|
332
|
+
for custom output styles.
|
|
314
333
|
|
|
315
|
-
Deploys
|
|
316
|
-
- claude-mpm
|
|
317
|
-
- claude-mpm-
|
|
334
|
+
Deploys all styles:
|
|
335
|
+
- claude-mpm.md (professional mode)
|
|
336
|
+
- claude-mpm-teacher.md (teaching mode)
|
|
337
|
+
- claude-mpm-research.md (research mode - for codebase analysis)
|
|
318
338
|
"""
|
|
319
339
|
try:
|
|
320
|
-
import
|
|
321
|
-
from pathlib import Path
|
|
340
|
+
from ..core.output_style_manager import OutputStyleManager
|
|
322
341
|
|
|
323
|
-
#
|
|
324
|
-
|
|
325
|
-
professional_source = package_dir / "CLAUDE_MPM_OUTPUT_STYLE.md"
|
|
326
|
-
teacher_source = package_dir / "CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md"
|
|
327
|
-
|
|
328
|
-
# Target directory (USER-LEVEL for global availability)
|
|
329
|
-
# Claude Code reads output styles from ~/.claude/settings/output-styles/
|
|
330
|
-
user_home = Path.home()
|
|
331
|
-
output_styles_dir = user_home / ".claude" / "settings" / "output-styles"
|
|
332
|
-
professional_target = output_styles_dir / "claude-mpm-style.md"
|
|
333
|
-
teacher_target = output_styles_dir / "claude-mpm-teach.md"
|
|
334
|
-
|
|
335
|
-
# Create directory if it doesn't exist
|
|
336
|
-
output_styles_dir.mkdir(parents=True, exist_ok=True)
|
|
337
|
-
|
|
338
|
-
# Check if already deployed AND up-to-date (compare sizes to detect changes)
|
|
339
|
-
professional_up_to_date = (
|
|
340
|
-
professional_target.exists()
|
|
341
|
-
and professional_source.exists()
|
|
342
|
-
and professional_target.stat().st_size == professional_source.stat().st_size
|
|
343
|
-
)
|
|
344
|
-
teacher_up_to_date = (
|
|
345
|
-
teacher_target.exists()
|
|
346
|
-
and teacher_source.exists()
|
|
347
|
-
and teacher_target.stat().st_size == teacher_source.stat().st_size
|
|
348
|
-
)
|
|
342
|
+
# Initialize the output style manager
|
|
343
|
+
manager = OutputStyleManager()
|
|
349
344
|
|
|
350
|
-
if
|
|
345
|
+
# Check if Claude Code version supports output styles (>= 1.0.83)
|
|
346
|
+
if not manager.supports_output_styles():
|
|
347
|
+
# Skip deployment for older versions
|
|
348
|
+
# The manager will fall back to injecting content directly
|
|
349
|
+
return
|
|
350
|
+
|
|
351
|
+
# Check if all styles are already deployed and up-to-date
|
|
352
|
+
all_up_to_date = True
|
|
353
|
+
for style_config in manager.styles.values():
|
|
354
|
+
source_path = style_config["source"]
|
|
355
|
+
target_path = style_config["target"]
|
|
356
|
+
|
|
357
|
+
if not (
|
|
358
|
+
target_path.exists()
|
|
359
|
+
and source_path.exists()
|
|
360
|
+
and target_path.stat().st_size == source_path.stat().st_size
|
|
361
|
+
):
|
|
362
|
+
all_up_to_date = False
|
|
363
|
+
break
|
|
364
|
+
|
|
365
|
+
if all_up_to_date:
|
|
351
366
|
# Show feedback that output styles are ready
|
|
352
367
|
print("✓ Output styles ready", flush=True)
|
|
353
368
|
return
|
|
354
369
|
|
|
355
|
-
# Deploy
|
|
356
|
-
|
|
357
|
-
if professional_source.exists():
|
|
358
|
-
shutil.copy2(professional_source, professional_target)
|
|
359
|
-
deployed_count += 1
|
|
370
|
+
# Deploy all styles using the manager
|
|
371
|
+
results = manager.deploy_all_styles(activate_default=True)
|
|
360
372
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
deployed_count += 1
|
|
373
|
+
# Count successful deployments
|
|
374
|
+
deployed_count = sum(1 for success in results.values() if success)
|
|
364
375
|
|
|
365
376
|
if deployed_count > 0:
|
|
366
377
|
print(f"✓ Output styles deployed ({deployed_count} styles)", flush=True)
|
|
367
378
|
else:
|
|
368
|
-
#
|
|
379
|
+
# Deployment failed - log but don't fail startup
|
|
369
380
|
from ..core.logger import get_logger
|
|
370
381
|
|
|
371
382
|
logger = get_logger("cli")
|
|
372
|
-
logger.debug("
|
|
383
|
+
logger.debug("Failed to deploy any output styles")
|
|
373
384
|
|
|
374
385
|
except Exception as e:
|
|
375
386
|
# Non-critical - log but don't fail startup
|
|
@@ -458,7 +469,7 @@ def _cleanup_orphaned_agents(deploy_target: Path, deployed_agents: list[str]) ->
|
|
|
458
469
|
return removed_count
|
|
459
470
|
|
|
460
471
|
|
|
461
|
-
def sync_remote_agents_on_startup():
|
|
472
|
+
def sync_remote_agents_on_startup(force_sync: bool = False):
|
|
462
473
|
"""
|
|
463
474
|
Synchronize agent templates from remote sources on startup.
|
|
464
475
|
|
|
@@ -476,6 +487,9 @@ def sync_remote_agents_on_startup():
|
|
|
476
487
|
3. Cleanup orphaned agents (ours but no longer deployed) - Phase 3
|
|
477
488
|
4. Cleanup legacy agent cache directories (after sync/deployment) - Phase 4
|
|
478
489
|
5. Log deployment results
|
|
490
|
+
|
|
491
|
+
Args:
|
|
492
|
+
force_sync: Force download even if cache is fresh (bypasses ETag).
|
|
479
493
|
"""
|
|
480
494
|
# DEPRECATED: Legacy warning - no-op function, kept for compatibility
|
|
481
495
|
check_legacy_cache()
|
|
@@ -486,7 +500,6 @@ def sync_remote_agents_on_startup():
|
|
|
486
500
|
from pathlib import Path
|
|
487
501
|
|
|
488
502
|
from ..core.shared.config_loader import ConfigLoader
|
|
489
|
-
from ..services.agents.deployment.agent_deployment import AgentDeploymentService
|
|
490
503
|
from ..services.agents.startup_sync import sync_agents_on_startup
|
|
491
504
|
from ..services.profile_manager import ProfileManager
|
|
492
505
|
from ..utils.progress import ProgressBar
|
|
@@ -511,7 +524,7 @@ def sync_remote_agents_on_startup():
|
|
|
511
524
|
)
|
|
512
525
|
|
|
513
526
|
# Phase 1: Sync files from Git sources
|
|
514
|
-
result = sync_agents_on_startup()
|
|
527
|
+
result = sync_agents_on_startup(force_refresh=force_sync)
|
|
515
528
|
|
|
516
529
|
# Only proceed with deployment if sync was enabled and ran
|
|
517
530
|
if result.get("enabled") and result.get("sources_synced", 0) > 0:
|
|
@@ -534,305 +547,89 @@ def sync_remote_agents_on_startup():
|
|
|
534
547
|
logger.warning(f"Agent sync completed with {len(errors)} errors")
|
|
535
548
|
|
|
536
549
|
# Phase 2: Deploy agents from cache to ~/.claude/agents/
|
|
537
|
-
#
|
|
550
|
+
# Use reconciliation service to respect configuration.yaml settings
|
|
538
551
|
try:
|
|
539
|
-
# Initialize deployment service with profile-filtered configuration
|
|
540
|
-
from ..core.config import Config
|
|
541
|
-
|
|
542
|
-
deploy_config = None
|
|
543
|
-
if active_profile and profile_manager.active_profile:
|
|
544
|
-
# Create config with excluded agents based on profile
|
|
545
|
-
# Get all agents that should be excluded (not in enabled list)
|
|
546
|
-
from pathlib import Path
|
|
547
|
-
|
|
548
|
-
cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
|
|
549
|
-
if cache_dir.exists():
|
|
550
|
-
# Find all agent files
|
|
551
|
-
# Supports both flat cache and {owner}/{repo}/agents/ structure
|
|
552
|
-
all_agent_files = [
|
|
553
|
-
f
|
|
554
|
-
for f in cache_dir.rglob("*.md")
|
|
555
|
-
if "/agents/" in str(f)
|
|
556
|
-
and f.stem.lower() != "base-agent"
|
|
557
|
-
and f.name.lower()
|
|
558
|
-
not in {"readme.md", "changelog.md", "contributing.md"}
|
|
559
|
-
]
|
|
560
|
-
|
|
561
|
-
# Build exclusion list for agents not in profile
|
|
562
|
-
excluded_agents = []
|
|
563
|
-
for agent_file in all_agent_files:
|
|
564
|
-
agent_name = agent_file.stem
|
|
565
|
-
if not profile_manager.is_agent_enabled(agent_name):
|
|
566
|
-
excluded_agents.append(agent_name)
|
|
567
|
-
|
|
568
|
-
if excluded_agents:
|
|
569
|
-
# Get singleton config and update with profile settings
|
|
570
|
-
# BUGFIX: Config is a singleton that ignores dict parameter if already initialized.
|
|
571
|
-
# Creating Config({...}) doesn't store excluded_agents - use set() instead.
|
|
572
|
-
deploy_config = Config()
|
|
573
|
-
deploy_config.set(
|
|
574
|
-
"agent_deployment.excluded_agents", excluded_agents
|
|
575
|
-
)
|
|
576
|
-
deploy_config.set(
|
|
577
|
-
"agent_deployment.filter_non_mpm_agents", False
|
|
578
|
-
)
|
|
579
|
-
deploy_config.set("agent_deployment.case_sensitive", False)
|
|
580
|
-
deploy_config.set(
|
|
581
|
-
"agent_deployment.exclude_dependencies", False
|
|
582
|
-
)
|
|
583
|
-
logger.info(
|
|
584
|
-
f"Profile '{active_profile}': Excluding {len(excluded_agents)} agents from deployment"
|
|
585
|
-
)
|
|
586
|
-
|
|
587
|
-
deployment_service = AgentDeploymentService(config=deploy_config)
|
|
588
|
-
|
|
589
|
-
# Count agents in cache to show accurate progress
|
|
590
552
|
from pathlib import Path
|
|
591
553
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
# BUGFIX (cache-count-inflation): Clean up stale cache files
|
|
597
|
-
# from old repositories before counting to prevent inflated counts.
|
|
598
|
-
# Issue: Old caches like bobmatnyc/claude-mpm-agents/agents/
|
|
599
|
-
# were counted alongside current agents, inflating count
|
|
600
|
-
# from 44 to 85.
|
|
601
|
-
#
|
|
602
|
-
# Solution: Remove files with nested /agents/ paths
|
|
603
|
-
# (e.g., cache/agents/user/repo/agents/...)
|
|
604
|
-
# Keep only current agents (e.g., cache/agents/engineer/...)
|
|
605
|
-
removed_count = 0
|
|
606
|
-
stale_dirs = set()
|
|
607
|
-
|
|
608
|
-
for md_file in cache_dir.rglob("*.md"):
|
|
609
|
-
# Stale cache files have multiple /agents/ in their path RELATIVE to cache_dir
|
|
610
|
-
# Current: cache/agents/bobmatnyc/claude-mpm-agents/agents/engineer/...
|
|
611
|
-
# (1 occurrence in relative path: /agents/)
|
|
612
|
-
# Old flat: cache/agents/engineer/...
|
|
613
|
-
# (0 occurrences in relative path - no repo structure)
|
|
614
|
-
# The issue: str(md_file).count("/agents/") counts BOTH cache/agents/ AND repo/agents/
|
|
615
|
-
# Fix: Count /agents/ in path RELATIVE to cache_dir (after cache/agents/)
|
|
616
|
-
relative_path = str(md_file.relative_to(cache_dir))
|
|
617
|
-
if relative_path.count("/agents/") > 1:
|
|
618
|
-
# Track parent directory for cleanup
|
|
619
|
-
# Extract subdirectory under cache/agents/
|
|
620
|
-
# (e.g., "bobmatnyc")
|
|
621
|
-
parts = md_file.parts
|
|
622
|
-
cache_agents_idx = parts.index("agents")
|
|
623
|
-
if cache_agents_idx + 1 < len(parts):
|
|
624
|
-
stale_subdir = parts[cache_agents_idx + 1]
|
|
625
|
-
# Only remove if it's not a known category directory
|
|
626
|
-
if stale_subdir not in [
|
|
627
|
-
"engineer",
|
|
628
|
-
"ops",
|
|
629
|
-
"qa",
|
|
630
|
-
"universal",
|
|
631
|
-
"documentation",
|
|
632
|
-
"claude-mpm",
|
|
633
|
-
"security",
|
|
634
|
-
]:
|
|
635
|
-
stale_dirs.add(cache_dir / stale_subdir)
|
|
636
|
-
|
|
637
|
-
md_file.unlink()
|
|
638
|
-
removed_count += 1
|
|
639
|
-
|
|
640
|
-
# Remove empty stale directories
|
|
641
|
-
for stale_dir in stale_dirs:
|
|
642
|
-
if stale_dir.exists() and stale_dir.is_dir():
|
|
643
|
-
try:
|
|
644
|
-
# Remove directory and all contents
|
|
645
|
-
import shutil
|
|
646
|
-
|
|
647
|
-
shutil.rmtree(stale_dir)
|
|
648
|
-
except Exception:
|
|
649
|
-
pass # Ignore cleanup errors
|
|
650
|
-
|
|
651
|
-
if removed_count > 0:
|
|
652
|
-
from loguru import logger
|
|
653
|
-
|
|
654
|
-
logger.info(
|
|
655
|
-
f"Cleaned up {removed_count} stale cache files "
|
|
656
|
-
f"from old repositories"
|
|
657
|
-
)
|
|
554
|
+
from ..core.unified_config import UnifiedConfig
|
|
555
|
+
from ..services.agents.deployment.startup_reconciliation import (
|
|
556
|
+
perform_startup_reconciliation,
|
|
557
|
+
)
|
|
658
558
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
# (
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
"
|
|
672
|
-
"response_format.md",
|
|
673
|
-
"ticket_completeness_examples.md",
|
|
674
|
-
"validation_templates.md",
|
|
675
|
-
"git_file_tracking.md",
|
|
676
|
-
}
|
|
677
|
-
# Documentation files to exclude (by filename)
|
|
678
|
-
doc_files = {
|
|
679
|
-
"readme.md",
|
|
680
|
-
"changelog.md",
|
|
681
|
-
"contributing.md",
|
|
682
|
-
"implementation-summary.md",
|
|
683
|
-
"reorganization-plan.md",
|
|
684
|
-
"auto-deploy-index.md",
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
# Find all markdown files (after cleanup)
|
|
688
|
-
all_md_files = list(cache_dir.rglob("*.md"))
|
|
689
|
-
|
|
690
|
-
# Filter to only agent files:
|
|
691
|
-
# 1. Must have "/agents/" in path (current structure supports
|
|
692
|
-
# both flat and {owner}/{repo}/agents/ patterns)
|
|
693
|
-
# 2. Must not be in PM templates or doc files
|
|
694
|
-
# 3. Exclude BASE-AGENT.md which is not a deployable agent
|
|
695
|
-
# 4. Exclude build artifacts (dist/, build/, .cache/)
|
|
696
|
-
# to prevent double-counting
|
|
697
|
-
agent_files = [
|
|
698
|
-
f
|
|
699
|
-
for f in all_md_files
|
|
700
|
-
if
|
|
701
|
-
(
|
|
702
|
-
# Must be in an agent directory
|
|
703
|
-
# Supports: cache/agents/{category}/... (flat)
|
|
704
|
-
# Supports: cache/agents/{owner}/{repo}/agents/{category}/... (GitHub sync)
|
|
705
|
-
"/agents/" in str(f)
|
|
706
|
-
# Exclude PM templates, doc files, and BASE-AGENT
|
|
707
|
-
and f.name.lower() not in pm_templates
|
|
708
|
-
and f.name.lower() not in doc_files
|
|
709
|
-
and f.name.lower() != "base-agent.md"
|
|
710
|
-
# Exclude build artifacts (prevents double-counting
|
|
711
|
-
# source + built files)
|
|
712
|
-
and not any(
|
|
713
|
-
part in str(f).split("/")
|
|
714
|
-
for part in ["dist", "build", ".cache"]
|
|
715
|
-
)
|
|
716
|
-
)
|
|
717
|
-
]
|
|
718
|
-
agent_count = len(agent_files)
|
|
719
|
-
|
|
720
|
-
if agent_count > 0:
|
|
721
|
-
# Deploy agents to project-level directory where Claude Code expects them
|
|
722
|
-
deploy_target = Path.cwd() / ".claude" / "agents"
|
|
723
|
-
deployment_result = deployment_service.deploy_agents(
|
|
724
|
-
target_dir=deploy_target,
|
|
725
|
-
force_rebuild=False, # Only deploy if versions differ
|
|
726
|
-
deployment_mode="update", # Version-aware updates
|
|
727
|
-
config=deploy_config, # Pass config to respect profile filtering
|
|
559
|
+
# Load configuration
|
|
560
|
+
unified_config = UnifiedConfig()
|
|
561
|
+
|
|
562
|
+
# Override with profile settings if active
|
|
563
|
+
if active_profile and profile_manager.active_profile:
|
|
564
|
+
# Get enabled agents from profile (returns Set[str])
|
|
565
|
+
profile_enabled_agents = (
|
|
566
|
+
profile_manager.active_profile.get_enabled_agents()
|
|
567
|
+
)
|
|
568
|
+
# Update config with profile's enabled list (convert Set to List)
|
|
569
|
+
unified_config.agents.enabled = list(profile_enabled_agents)
|
|
570
|
+
logger.info(
|
|
571
|
+
f"Profile '{active_profile}': Using {len(profile_enabled_agents)} enabled agents"
|
|
728
572
|
)
|
|
729
573
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
agent_count_in_target = len(
|
|
743
|
-
[
|
|
744
|
-
f
|
|
745
|
-
for f in existing_agents
|
|
746
|
-
if not f.name.startswith(("README", "INSTRUCTIONS"))
|
|
747
|
-
]
|
|
748
|
-
)
|
|
749
|
-
if agent_count_in_target > 0:
|
|
750
|
-
# All agents already deployed - count them as skipped
|
|
751
|
-
skipped = agent_count_in_target
|
|
752
|
-
total_configured = agent_count_in_target
|
|
574
|
+
# Perform reconciliation to deploy configured agents
|
|
575
|
+
project_path = Path.cwd()
|
|
576
|
+
agent_result, _skill_result = perform_startup_reconciliation(
|
|
577
|
+
project_path=project_path, config=unified_config, silent=False
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
# Display results with progress bar
|
|
581
|
+
total_operations = (
|
|
582
|
+
len(agent_result.deployed)
|
|
583
|
+
+ len(agent_result.removed)
|
|
584
|
+
+ len(agent_result.unchanged)
|
|
585
|
+
)
|
|
753
586
|
|
|
754
|
-
|
|
587
|
+
if total_operations > 0:
|
|
755
588
|
deploy_progress = ProgressBar(
|
|
756
|
-
total=
|
|
589
|
+
total=total_operations,
|
|
757
590
|
prefix="Deploying agents",
|
|
758
591
|
show_percentage=True,
|
|
759
592
|
show_counter=True,
|
|
760
593
|
)
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
)
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
594
|
+
deploy_progress.update(total_operations)
|
|
595
|
+
|
|
596
|
+
# Build summary message
|
|
597
|
+
deployed = len(agent_result.deployed)
|
|
598
|
+
removed = len(agent_result.removed)
|
|
599
|
+
unchanged = len(agent_result.unchanged)
|
|
600
|
+
|
|
601
|
+
summary_parts = []
|
|
602
|
+
if deployed > 0:
|
|
603
|
+
summary_parts.append(f"{deployed} new")
|
|
604
|
+
if removed > 0:
|
|
605
|
+
summary_parts.append(f"{removed} removed")
|
|
606
|
+
if unchanged > 0:
|
|
607
|
+
summary_parts.append(f"{unchanged} unchanged")
|
|
608
|
+
|
|
609
|
+
summary = f"Complete: {', '.join(summary_parts)}"
|
|
610
|
+
deploy_progress.finish(summary)
|
|
611
|
+
|
|
612
|
+
# Display errors if any
|
|
613
|
+
if agent_result.errors:
|
|
614
|
+
logger.warning(
|
|
615
|
+
f"Agent deployment completed with {len(agent_result.errors)} errors"
|
|
780
616
|
)
|
|
617
|
+
print("\n⚠️ Agent Deployment Errors:")
|
|
618
|
+
max_errors_to_show = 10
|
|
619
|
+
errors_to_display = agent_result.errors[:max_errors_to_show]
|
|
781
620
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
if deployed > 0 or updated > 0:
|
|
785
|
-
if removed > 0:
|
|
786
|
-
deploy_progress.finish(
|
|
787
|
-
f"Complete: {deployed} new, {updated} updated, {skipped} unchanged, "
|
|
788
|
-
f"{removed} removed ({total_configured} configured from {agent_count} files in cache)"
|
|
789
|
-
)
|
|
790
|
-
else:
|
|
791
|
-
deploy_progress.finish(
|
|
792
|
-
f"Complete: {deployed} new, {updated} updated, {skipped} unchanged "
|
|
793
|
-
f"({total_configured} configured from {agent_count} files in cache)"
|
|
794
|
-
)
|
|
795
|
-
elif removed > 0:
|
|
796
|
-
deploy_progress.finish(
|
|
797
|
-
f"Complete: {total_configured} agents deployed, "
|
|
798
|
-
f"{removed} removed ({agent_count} files in cache)"
|
|
799
|
-
)
|
|
800
|
-
else:
|
|
801
|
-
deploy_progress.finish(
|
|
802
|
-
f"Complete: {total_configured} agents deployed "
|
|
803
|
-
f"({agent_count} files in cache)"
|
|
804
|
-
)
|
|
805
|
-
|
|
806
|
-
# Display deployment errors to user (not just logs)
|
|
807
|
-
deploy_errors = deployment_result.get("errors", [])
|
|
808
|
-
if deploy_errors:
|
|
809
|
-
# Log for debugging
|
|
810
|
-
logger.warning(
|
|
811
|
-
f"Agent deployment completed with {len(deploy_errors)} errors: {deploy_errors}"
|
|
812
|
-
)
|
|
621
|
+
for error in errors_to_display:
|
|
622
|
+
print(f" - {error}")
|
|
813
623
|
|
|
814
|
-
|
|
815
|
-
|
|
624
|
+
if len(agent_result.errors) > max_errors_to_show:
|
|
625
|
+
remaining = len(agent_result.errors) - max_errors_to_show
|
|
626
|
+
print(f" ... and {remaining} more error(s)")
|
|
816
627
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
# Format error message for readability
|
|
823
|
-
# Errors typically come as strings like "agent.md: Error message"
|
|
824
|
-
print(f" - {error}")
|
|
825
|
-
|
|
826
|
-
# If more errors exist, show count
|
|
827
|
-
if len(deploy_errors) > max_errors_to_show:
|
|
828
|
-
remaining = len(deploy_errors) - max_errors_to_show
|
|
829
|
-
print(f" ... and {remaining} more error(s)")
|
|
830
|
-
|
|
831
|
-
# Show summary message
|
|
832
|
-
print(
|
|
833
|
-
f"\n❌ Failed to deploy {len(deploy_errors)} agent(s). Please check the error messages above."
|
|
834
|
-
)
|
|
835
|
-
print(" Run with --verbose for detailed error information.\n")
|
|
628
|
+
print(
|
|
629
|
+
f"\n❌ Failed to deploy {len(agent_result.errors)} agent(s). "
|
|
630
|
+
"Please check the error messages above."
|
|
631
|
+
)
|
|
632
|
+
print(" Run with --verbose for detailed error information.\n")
|
|
836
633
|
|
|
837
634
|
except Exception as e:
|
|
838
635
|
# Deployment failure shouldn't block startup
|
|
@@ -857,11 +654,11 @@ def sync_remote_agents_on_startup():
|
|
|
857
654
|
# Cleanup legacy cache even if sync failed
|
|
858
655
|
try:
|
|
859
656
|
cleanup_legacy_agent_cache()
|
|
860
|
-
except Exception:
|
|
657
|
+
except Exception: # nosec B110
|
|
861
658
|
pass # Ignore cleanup errors
|
|
862
659
|
|
|
863
660
|
|
|
864
|
-
def sync_remote_skills_on_startup():
|
|
661
|
+
def sync_remote_skills_on_startup(force_sync: bool = False):
|
|
865
662
|
"""
|
|
866
663
|
Synchronize skill templates from remote sources on startup.
|
|
867
664
|
|
|
@@ -879,6 +676,9 @@ def sync_remote_skills_on_startup():
|
|
|
879
676
|
4. Apply profile filtering if active
|
|
880
677
|
5. Deploy resolved skills to ~/.claude/skills/ - Phase 2 progress bar
|
|
881
678
|
6. Log deployment results with source indication
|
|
679
|
+
|
|
680
|
+
Args:
|
|
681
|
+
force_sync: Force download even if cache is fresh (bypasses ETag).
|
|
882
682
|
"""
|
|
883
683
|
try:
|
|
884
684
|
from pathlib import Path
|
|
@@ -984,7 +784,7 @@ def sync_remote_skills_on_startup():
|
|
|
984
784
|
|
|
985
785
|
# Sync all sources with progress callback
|
|
986
786
|
results = manager.sync_all_sources(
|
|
987
|
-
force=
|
|
787
|
+
force=force_sync, progress_callback=sync_progress.update
|
|
988
788
|
)
|
|
989
789
|
|
|
990
790
|
# Finish sync progress bar with clear breakdown
|
|
@@ -1093,7 +893,7 @@ def sync_remote_skills_on_startup():
|
|
|
1093
893
|
# Deploy to project-local directory with cleanup
|
|
1094
894
|
deployment_result = manager.deploy_skills(
|
|
1095
895
|
target_dir=Path.cwd() / ".claude" / "skills",
|
|
1096
|
-
force=
|
|
896
|
+
force=force_sync,
|
|
1097
897
|
# CRITICAL FIX: Empty list should mean "deploy no skills", not "deploy all"
|
|
1098
898
|
# When skills_to_deploy is [], we want skill_filter=set() NOT skill_filter=None
|
|
1099
899
|
# None means "no filtering" (deploy all), empty set means "filter to nothing"
|
|
@@ -1358,33 +1158,70 @@ def show_skill_summary():
|
|
|
1358
1158
|
|
|
1359
1159
|
|
|
1360
1160
|
def verify_and_show_pm_skills():
|
|
1361
|
-
"""Verify PM skills and display status.
|
|
1161
|
+
"""Verify PM skills and display status with enhanced validation.
|
|
1162
|
+
|
|
1163
|
+
WHY: PM skills are CRITICAL for PM agent operation. PM must KNOW if
|
|
1164
|
+
framework knowledge is unavailable at startup. Enhanced validation
|
|
1165
|
+
checks all required skills exist, are not corrupted, and auto-repairs
|
|
1166
|
+
if needed.
|
|
1362
1167
|
|
|
1363
|
-
|
|
1364
|
-
|
|
1168
|
+
Shows deployment status:
|
|
1169
|
+
- "✓ PM skills: 8/8 verified" if all required skills are valid
|
|
1170
|
+
- "⚠ PM skills: 2 missing, auto-repairing..." if issues detected
|
|
1171
|
+
- Non-blocking but visible warning if auto-repair fails
|
|
1365
1172
|
"""
|
|
1366
1173
|
try:
|
|
1367
1174
|
from pathlib import Path
|
|
1368
1175
|
|
|
1369
|
-
from ..services.pm_skills_deployer import
|
|
1176
|
+
from ..services.pm_skills_deployer import (
|
|
1177
|
+
REQUIRED_PM_SKILLS,
|
|
1178
|
+
PMSkillsDeployerService,
|
|
1179
|
+
)
|
|
1370
1180
|
|
|
1371
1181
|
deployer = PMSkillsDeployerService()
|
|
1372
1182
|
project_dir = Path.cwd()
|
|
1373
1183
|
|
|
1374
|
-
|
|
1184
|
+
# Verify with auto-repair enabled
|
|
1185
|
+
result = deployer.verify_pm_skills(project_dir, auto_repair=True)
|
|
1375
1186
|
|
|
1376
1187
|
if result.verified:
|
|
1377
|
-
# Show verified status
|
|
1378
|
-
|
|
1188
|
+
# Show verified status with count
|
|
1189
|
+
total_required = len(REQUIRED_PM_SKILLS)
|
|
1190
|
+
print(
|
|
1191
|
+
f"✓ PM skills: {total_required}/{total_required} verified", flush=True
|
|
1192
|
+
)
|
|
1379
1193
|
else:
|
|
1380
|
-
#
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1194
|
+
# Show warning with details
|
|
1195
|
+
missing_count = len(result.missing_skills)
|
|
1196
|
+
corrupted_count = len(result.corrupted_skills)
|
|
1197
|
+
|
|
1198
|
+
# Build status message
|
|
1199
|
+
issues = []
|
|
1200
|
+
if missing_count > 0:
|
|
1201
|
+
issues.append(f"{missing_count} missing")
|
|
1202
|
+
if corrupted_count > 0:
|
|
1203
|
+
issues.append(f"{corrupted_count} corrupted")
|
|
1204
|
+
|
|
1205
|
+
status = ", ".join(issues)
|
|
1206
|
+
|
|
1207
|
+
# Check if auto-repair was attempted
|
|
1208
|
+
if "Auto-repaired" in result.message:
|
|
1209
|
+
# Auto-repair succeeded
|
|
1210
|
+
total_required = len(REQUIRED_PM_SKILLS)
|
|
1211
|
+
print(
|
|
1212
|
+
f"✓ PM skills: {total_required}/{total_required} verified (auto-repaired)",
|
|
1213
|
+
flush=True,
|
|
1214
|
+
)
|
|
1386
1215
|
else:
|
|
1387
|
-
|
|
1216
|
+
# Auto-repair failed or not attempted
|
|
1217
|
+
print(f"⚠ PM skills: {status}", flush=True)
|
|
1218
|
+
|
|
1219
|
+
# Log warnings for debugging
|
|
1220
|
+
from ..core.logger import get_logger
|
|
1221
|
+
|
|
1222
|
+
logger = get_logger("cli")
|
|
1223
|
+
for warning in result.warnings:
|
|
1224
|
+
logger.warning(f"PM skills: {warning}")
|
|
1388
1225
|
|
|
1389
1226
|
except ImportError:
|
|
1390
1227
|
# PM skills deployer not available - skip silently
|
|
@@ -1419,7 +1256,7 @@ def auto_install_chrome_devtools_on_startup():
|
|
|
1419
1256
|
if not chrome_devtools_config.get("auto_install", True):
|
|
1420
1257
|
# Auto-install disabled, skip silently
|
|
1421
1258
|
return
|
|
1422
|
-
except Exception:
|
|
1259
|
+
except Exception: # nosec B110
|
|
1423
1260
|
# If config loading fails, assume auto-install is enabled (default)
|
|
1424
1261
|
pass
|
|
1425
1262
|
|
|
@@ -1437,7 +1274,7 @@ def auto_install_chrome_devtools_on_startup():
|
|
|
1437
1274
|
# Continue execution - chrome-devtools installation failure shouldn't block startup
|
|
1438
1275
|
|
|
1439
1276
|
|
|
1440
|
-
def run_background_services():
|
|
1277
|
+
def run_background_services(force_sync: bool = False):
|
|
1441
1278
|
"""
|
|
1442
1279
|
Initialize all background services on startup.
|
|
1443
1280
|
|
|
@@ -1448,6 +1285,9 @@ def run_background_services():
|
|
|
1448
1285
|
explicitly requests them via agent-manager commands. This prevents unwanted
|
|
1449
1286
|
file creation in project .claude/ directories.
|
|
1450
1287
|
See: SystemInstructionsDeployer and agent_deployment.py line 504-509
|
|
1288
|
+
|
|
1289
|
+
Args:
|
|
1290
|
+
force_sync: Force download even if cache is fresh (bypasses ETag).
|
|
1451
1291
|
"""
|
|
1452
1292
|
# Sync hooks early to ensure up-to-date configuration
|
|
1453
1293
|
# RATIONALE: Hooks should be synced before other services to fix stale configs
|
|
@@ -1458,7 +1298,9 @@ def run_background_services():
|
|
|
1458
1298
|
check_mcp_auto_configuration()
|
|
1459
1299
|
verify_mcp_gateway_startup()
|
|
1460
1300
|
check_for_updates_async()
|
|
1461
|
-
sync_remote_agents_on_startup(
|
|
1301
|
+
sync_remote_agents_on_startup(
|
|
1302
|
+
force_sync=force_sync
|
|
1303
|
+
) # Sync agents from remote sources
|
|
1462
1304
|
show_agent_summary() # Display agent counts after deployment
|
|
1463
1305
|
|
|
1464
1306
|
# Skills deployment order (precedence: remote > bundled)
|
|
@@ -1467,7 +1309,9 @@ def run_background_services():
|
|
|
1467
1309
|
# 3. Discover and link runtime skills (user-added skills)
|
|
1468
1310
|
# This ensures remote skills take precedence over bundled skills when names conflict
|
|
1469
1311
|
deploy_bundled_skills() # Base layer: package-bundled skills
|
|
1470
|
-
sync_remote_skills_on_startup(
|
|
1312
|
+
sync_remote_skills_on_startup(
|
|
1313
|
+
force_sync=force_sync
|
|
1314
|
+
) # Override layer: Git-based skills (takes precedence)
|
|
1471
1315
|
discover_and_link_runtime_skills() # Discovery: user-added skills
|
|
1472
1316
|
show_skill_summary() # Display skill counts after deployment
|
|
1473
1317
|
verify_and_show_pm_skills() # PM skills verification and status
|
|
@@ -1667,7 +1511,7 @@ def verify_mcp_gateway_startup():
|
|
|
1667
1511
|
loop.run_until_complete(
|
|
1668
1512
|
asyncio.gather(*pending, return_exceptions=True)
|
|
1669
1513
|
)
|
|
1670
|
-
except Exception:
|
|
1514
|
+
except Exception: # nosec B110
|
|
1671
1515
|
pass # Ignore cleanup errors
|
|
1672
1516
|
finally:
|
|
1673
1517
|
loop.close()
|
|
@@ -1761,7 +1605,7 @@ def check_for_updates_async():
|
|
|
1761
1605
|
|
|
1762
1606
|
logger = get_logger("upgrade_check")
|
|
1763
1607
|
logger.debug(f"Update check failed (non-critical): {e}")
|
|
1764
|
-
except Exception:
|
|
1608
|
+
except Exception: # nosec B110
|
|
1765
1609
|
pass # Avoid any errors in error handling
|
|
1766
1610
|
finally:
|
|
1767
1611
|
# Properly clean up event loop
|
|
@@ -1776,7 +1620,7 @@ def check_for_updates_async():
|
|
|
1776
1620
|
loop.run_until_complete(
|
|
1777
1621
|
asyncio.gather(*pending, return_exceptions=True)
|
|
1778
1622
|
)
|
|
1779
|
-
except Exception:
|
|
1623
|
+
except Exception: # nosec B110
|
|
1780
1624
|
pass # Ignore cleanup errors
|
|
1781
1625
|
finally:
|
|
1782
1626
|
loop.close()
|