claude-mpm 5.4.71__py3-none-any.whl → 5.6.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +8 -5
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +101 -703
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- 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/skills.py +166 -14
- claude_mpm/cli/executor.py +119 -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 +71 -1
- claude_mpm/cli/parsers/commander_parser.py +83 -0
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/startup.py +183 -348
- 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 +112 -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 +215 -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/constants.py +1 -0
- claude_mpm/core/claude_runner.py +2 -2
- claude_mpm/core/config.py +5 -0
- 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 +27 -9
- 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/auto_pause_handler.py +486 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +254 -11
- 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 +75 -8
- claude_mpm/hooks/claude_hooks/memory_integration.py +22 -11
- claude_mpm/hooks/claude_hooks/response_tracking.py +3 -1
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +20 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +14 -77
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +30 -6
- claude_mpm/hooks/session_resume_hook.py +85 -1
- claude_mpm/init.py +1 -1
- claude_mpm/scripts/claude-hook-handler.sh +39 -12
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- 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/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 +56 -3
- claude_mpm/services/skills/selective_skill_deployer.py +114 -26
- claude_mpm/services/skills/skill_discovery_service.py +57 -3
- 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/{pm-teaching-mode → mpm-teaching-mode}/SKILL.md +2 -2
- 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.3.dist-info/METADATA +391 -0
- {claude_mpm-5.4.71.dist-info → claude_mpm-5.6.3.dist-info}/RECORD +261 -179
- 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/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.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__/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__/installer.cpython-311.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__/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__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-312.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__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-312.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__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
- claude_mpm-5.4.71.dist-info/METADATA +0 -1005
- /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.71.dist-info → claude_mpm-5.6.3.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.71.dist-info → claude_mpm-5.6.3.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.71.dist-info → claude_mpm-5.6.3.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.71.dist-info → claude_mpm-5.6.3.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.71.dist-info → claude_mpm-5.6.3.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
|
|
|
@@ -312,64 +331,56 @@ def deploy_output_style_on_startup():
|
|
|
312
331
|
directory (~/.claude/output-styles/) which is the official Claude Code location
|
|
313
332
|
for custom output styles.
|
|
314
333
|
|
|
315
|
-
Deploys
|
|
334
|
+
Deploys all styles:
|
|
316
335
|
- claude-mpm.md (professional mode)
|
|
317
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/output-styles/
|
|
330
|
-
user_home = Path.home()
|
|
331
|
-
output_styles_dir = user_home / ".claude" / "output-styles"
|
|
332
|
-
professional_target = output_styles_dir / "claude-mpm.md"
|
|
333
|
-
teacher_target = output_styles_dir / "claude-mpm-teacher.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
|
|
@@ -489,7 +500,6 @@ def sync_remote_agents_on_startup(force_sync: bool = False):
|
|
|
489
500
|
from pathlib import Path
|
|
490
501
|
|
|
491
502
|
from ..core.shared.config_loader import ConfigLoader
|
|
492
|
-
from ..services.agents.deployment.agent_deployment import AgentDeploymentService
|
|
493
503
|
from ..services.agents.startup_sync import sync_agents_on_startup
|
|
494
504
|
from ..services.profile_manager import ProfileManager
|
|
495
505
|
from ..utils.progress import ProgressBar
|
|
@@ -537,305 +547,89 @@ def sync_remote_agents_on_startup(force_sync: bool = False):
|
|
|
537
547
|
logger.warning(f"Agent sync completed with {len(errors)} errors")
|
|
538
548
|
|
|
539
549
|
# Phase 2: Deploy agents from cache to ~/.claude/agents/
|
|
540
|
-
#
|
|
550
|
+
# Use reconciliation service to respect configuration.yaml settings
|
|
541
551
|
try:
|
|
542
|
-
# Initialize deployment service with profile-filtered configuration
|
|
543
|
-
from ..core.config import Config
|
|
544
|
-
|
|
545
|
-
deploy_config = None
|
|
546
|
-
if active_profile and profile_manager.active_profile:
|
|
547
|
-
# Create config with excluded agents based on profile
|
|
548
|
-
# Get all agents that should be excluded (not in enabled list)
|
|
549
|
-
from pathlib import Path
|
|
550
|
-
|
|
551
|
-
cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
|
|
552
|
-
if cache_dir.exists():
|
|
553
|
-
# Find all agent files
|
|
554
|
-
# Supports both flat cache and {owner}/{repo}/agents/ structure
|
|
555
|
-
all_agent_files = [
|
|
556
|
-
f
|
|
557
|
-
for f in cache_dir.rglob("*.md")
|
|
558
|
-
if "/agents/" in str(f)
|
|
559
|
-
and f.stem.lower() != "base-agent"
|
|
560
|
-
and f.name.lower()
|
|
561
|
-
not in {"readme.md", "changelog.md", "contributing.md"}
|
|
562
|
-
]
|
|
563
|
-
|
|
564
|
-
# Build exclusion list for agents not in profile
|
|
565
|
-
excluded_agents = []
|
|
566
|
-
for agent_file in all_agent_files:
|
|
567
|
-
agent_name = agent_file.stem
|
|
568
|
-
if not profile_manager.is_agent_enabled(agent_name):
|
|
569
|
-
excluded_agents.append(agent_name)
|
|
570
|
-
|
|
571
|
-
if excluded_agents:
|
|
572
|
-
# Get singleton config and update with profile settings
|
|
573
|
-
# BUGFIX: Config is a singleton that ignores dict parameter if already initialized.
|
|
574
|
-
# Creating Config({...}) doesn't store excluded_agents - use set() instead.
|
|
575
|
-
deploy_config = Config()
|
|
576
|
-
deploy_config.set(
|
|
577
|
-
"agent_deployment.excluded_agents", excluded_agents
|
|
578
|
-
)
|
|
579
|
-
deploy_config.set(
|
|
580
|
-
"agent_deployment.filter_non_mpm_agents", False
|
|
581
|
-
)
|
|
582
|
-
deploy_config.set("agent_deployment.case_sensitive", False)
|
|
583
|
-
deploy_config.set(
|
|
584
|
-
"agent_deployment.exclude_dependencies", False
|
|
585
|
-
)
|
|
586
|
-
logger.info(
|
|
587
|
-
f"Profile '{active_profile}': Excluding {len(excluded_agents)} agents from deployment"
|
|
588
|
-
)
|
|
589
|
-
|
|
590
|
-
deployment_service = AgentDeploymentService(config=deploy_config)
|
|
591
|
-
|
|
592
|
-
# Count agents in cache to show accurate progress
|
|
593
552
|
from pathlib import Path
|
|
594
553
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
# BUGFIX (cache-count-inflation): Clean up stale cache files
|
|
600
|
-
# from old repositories before counting to prevent inflated counts.
|
|
601
|
-
# Issue: Old caches like bobmatnyc/claude-mpm-agents/agents/
|
|
602
|
-
# were counted alongside current agents, inflating count
|
|
603
|
-
# from 44 to 85.
|
|
604
|
-
#
|
|
605
|
-
# Solution: Remove files with nested /agents/ paths
|
|
606
|
-
# (e.g., cache/agents/user/repo/agents/...)
|
|
607
|
-
# Keep only current agents (e.g., cache/agents/engineer/...)
|
|
608
|
-
removed_count = 0
|
|
609
|
-
stale_dirs = set()
|
|
610
|
-
|
|
611
|
-
for md_file in cache_dir.rglob("*.md"):
|
|
612
|
-
# Stale cache files have multiple /agents/ in their path RELATIVE to cache_dir
|
|
613
|
-
# Current: cache/agents/bobmatnyc/claude-mpm-agents/agents/engineer/...
|
|
614
|
-
# (1 occurrence in relative path: /agents/)
|
|
615
|
-
# Old flat: cache/agents/engineer/...
|
|
616
|
-
# (0 occurrences in relative path - no repo structure)
|
|
617
|
-
# The issue: str(md_file).count("/agents/") counts BOTH cache/agents/ AND repo/agents/
|
|
618
|
-
# Fix: Count /agents/ in path RELATIVE to cache_dir (after cache/agents/)
|
|
619
|
-
relative_path = str(md_file.relative_to(cache_dir))
|
|
620
|
-
if relative_path.count("/agents/") > 1:
|
|
621
|
-
# Track parent directory for cleanup
|
|
622
|
-
# Extract subdirectory under cache/agents/
|
|
623
|
-
# (e.g., "bobmatnyc")
|
|
624
|
-
parts = md_file.parts
|
|
625
|
-
cache_agents_idx = parts.index("agents")
|
|
626
|
-
if cache_agents_idx + 1 < len(parts):
|
|
627
|
-
stale_subdir = parts[cache_agents_idx + 1]
|
|
628
|
-
# Only remove if it's not a known category directory
|
|
629
|
-
if stale_subdir not in [
|
|
630
|
-
"engineer",
|
|
631
|
-
"ops",
|
|
632
|
-
"qa",
|
|
633
|
-
"universal",
|
|
634
|
-
"documentation",
|
|
635
|
-
"claude-mpm",
|
|
636
|
-
"security",
|
|
637
|
-
]:
|
|
638
|
-
stale_dirs.add(cache_dir / stale_subdir)
|
|
639
|
-
|
|
640
|
-
md_file.unlink()
|
|
641
|
-
removed_count += 1
|
|
642
|
-
|
|
643
|
-
# Remove empty stale directories
|
|
644
|
-
for stale_dir in stale_dirs:
|
|
645
|
-
if stale_dir.exists() and stale_dir.is_dir():
|
|
646
|
-
try:
|
|
647
|
-
# Remove directory and all contents
|
|
648
|
-
import shutil
|
|
649
|
-
|
|
650
|
-
shutil.rmtree(stale_dir)
|
|
651
|
-
except Exception:
|
|
652
|
-
pass # Ignore cleanup errors
|
|
653
|
-
|
|
654
|
-
if removed_count > 0:
|
|
655
|
-
from loguru import logger
|
|
656
|
-
|
|
657
|
-
logger.info(
|
|
658
|
-
f"Cleaned up {removed_count} stale cache files "
|
|
659
|
-
f"from old repositories"
|
|
660
|
-
)
|
|
554
|
+
from ..core.unified_config import UnifiedConfig
|
|
555
|
+
from ..services.agents.deployment.startup_reconciliation import (
|
|
556
|
+
perform_startup_reconciliation,
|
|
557
|
+
)
|
|
661
558
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
# (
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
"
|
|
675
|
-
"response_format.md",
|
|
676
|
-
"ticket_completeness_examples.md",
|
|
677
|
-
"validation_templates.md",
|
|
678
|
-
"git_file_tracking.md",
|
|
679
|
-
}
|
|
680
|
-
# Documentation files to exclude (by filename)
|
|
681
|
-
doc_files = {
|
|
682
|
-
"readme.md",
|
|
683
|
-
"changelog.md",
|
|
684
|
-
"contributing.md",
|
|
685
|
-
"implementation-summary.md",
|
|
686
|
-
"reorganization-plan.md",
|
|
687
|
-
"auto-deploy-index.md",
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
# Find all markdown files (after cleanup)
|
|
691
|
-
all_md_files = list(cache_dir.rglob("*.md"))
|
|
692
|
-
|
|
693
|
-
# Filter to only agent files:
|
|
694
|
-
# 1. Must have "/agents/" in path (current structure supports
|
|
695
|
-
# both flat and {owner}/{repo}/agents/ patterns)
|
|
696
|
-
# 2. Must not be in PM templates or doc files
|
|
697
|
-
# 3. Exclude BASE-AGENT.md which is not a deployable agent
|
|
698
|
-
# 4. Exclude build artifacts (dist/, build/, .cache/)
|
|
699
|
-
# to prevent double-counting
|
|
700
|
-
agent_files = [
|
|
701
|
-
f
|
|
702
|
-
for f in all_md_files
|
|
703
|
-
if
|
|
704
|
-
(
|
|
705
|
-
# Must be in an agent directory
|
|
706
|
-
# Supports: cache/agents/{category}/... (flat)
|
|
707
|
-
# Supports: cache/agents/{owner}/{repo}/agents/{category}/... (GitHub sync)
|
|
708
|
-
"/agents/" in str(f)
|
|
709
|
-
# Exclude PM templates, doc files, and BASE-AGENT
|
|
710
|
-
and f.name.lower() not in pm_templates
|
|
711
|
-
and f.name.lower() not in doc_files
|
|
712
|
-
and f.name.lower() != "base-agent.md"
|
|
713
|
-
# Exclude build artifacts (prevents double-counting
|
|
714
|
-
# source + built files)
|
|
715
|
-
and not any(
|
|
716
|
-
part in str(f).split("/")
|
|
717
|
-
for part in ["dist", "build", ".cache"]
|
|
718
|
-
)
|
|
719
|
-
)
|
|
720
|
-
]
|
|
721
|
-
agent_count = len(agent_files)
|
|
722
|
-
|
|
723
|
-
if agent_count > 0:
|
|
724
|
-
# Deploy agents to project-level directory where Claude Code expects them
|
|
725
|
-
deploy_target = Path.cwd() / ".claude" / "agents"
|
|
726
|
-
deployment_result = deployment_service.deploy_agents(
|
|
727
|
-
target_dir=deploy_target,
|
|
728
|
-
force_rebuild=False, # Only deploy if versions differ
|
|
729
|
-
deployment_mode="update", # Version-aware updates
|
|
730
|
-
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"
|
|
731
572
|
)
|
|
732
573
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
# FALLBACK: If deployment result doesn't track skipped agents (async path),
|
|
740
|
-
# count existing agents in target directory as "already deployed"
|
|
741
|
-
# This ensures accurate reporting when agents are already up-to-date
|
|
742
|
-
if total_configured == 0 and deploy_target.exists():
|
|
743
|
-
existing_agents = list(deploy_target.glob("*.md"))
|
|
744
|
-
# Filter out non-agent files (e.g., README.md, INSTRUCTIONS.md)
|
|
745
|
-
agent_count_in_target = len(
|
|
746
|
-
[
|
|
747
|
-
f
|
|
748
|
-
for f in existing_agents
|
|
749
|
-
if not f.name.startswith(("README", "INSTRUCTIONS"))
|
|
750
|
-
]
|
|
751
|
-
)
|
|
752
|
-
if agent_count_in_target > 0:
|
|
753
|
-
# All agents already deployed - count them as skipped
|
|
754
|
-
skipped = agent_count_in_target
|
|
755
|
-
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
|
+
)
|
|
756
579
|
|
|
757
|
-
|
|
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
|
+
)
|
|
586
|
+
|
|
587
|
+
if total_operations > 0:
|
|
758
588
|
deploy_progress = ProgressBar(
|
|
759
|
-
total=
|
|
589
|
+
total=total_operations,
|
|
760
590
|
prefix="Deploying agents",
|
|
761
591
|
show_percentage=True,
|
|
762
592
|
show_counter=True,
|
|
763
593
|
)
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
)
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
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"
|
|
783
616
|
)
|
|
617
|
+
print("\n⚠️ Agent Deployment Errors:")
|
|
618
|
+
max_errors_to_show = 10
|
|
619
|
+
errors_to_display = agent_result.errors[:max_errors_to_show]
|
|
784
620
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
if deployed > 0 or updated > 0:
|
|
788
|
-
if removed > 0:
|
|
789
|
-
deploy_progress.finish(
|
|
790
|
-
f"Complete: {deployed} new, {updated} updated, {skipped} unchanged, "
|
|
791
|
-
f"{removed} removed ({total_configured} configured from {agent_count} files in cache)"
|
|
792
|
-
)
|
|
793
|
-
else:
|
|
794
|
-
deploy_progress.finish(
|
|
795
|
-
f"Complete: {deployed} new, {updated} updated, {skipped} unchanged "
|
|
796
|
-
f"({total_configured} configured from {agent_count} files in cache)"
|
|
797
|
-
)
|
|
798
|
-
elif removed > 0:
|
|
799
|
-
deploy_progress.finish(
|
|
800
|
-
f"Complete: {total_configured} agents deployed, "
|
|
801
|
-
f"{removed} removed ({agent_count} files in cache)"
|
|
802
|
-
)
|
|
803
|
-
else:
|
|
804
|
-
deploy_progress.finish(
|
|
805
|
-
f"Complete: {total_configured} agents deployed "
|
|
806
|
-
f"({agent_count} files in cache)"
|
|
807
|
-
)
|
|
808
|
-
|
|
809
|
-
# Display deployment errors to user (not just logs)
|
|
810
|
-
deploy_errors = deployment_result.get("errors", [])
|
|
811
|
-
if deploy_errors:
|
|
812
|
-
# Log for debugging
|
|
813
|
-
logger.warning(
|
|
814
|
-
f"Agent deployment completed with {len(deploy_errors)} errors: {deploy_errors}"
|
|
815
|
-
)
|
|
816
|
-
|
|
817
|
-
# Display errors to user with clear formatting
|
|
818
|
-
print("\n⚠️ Agent Deployment Errors:")
|
|
819
|
-
|
|
820
|
-
# Show first 10 errors to avoid overwhelming output
|
|
821
|
-
max_errors_to_show = 10
|
|
822
|
-
errors_to_display = deploy_errors[:max_errors_to_show]
|
|
823
|
-
|
|
824
|
-
for error in errors_to_display:
|
|
825
|
-
# Format error message for readability
|
|
826
|
-
# Errors typically come as strings like "agent.md: Error message"
|
|
827
|
-
print(f" - {error}")
|
|
621
|
+
for error in errors_to_display:
|
|
622
|
+
print(f" - {error}")
|
|
828
623
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
print(f" ... and {remaining} more error(s)")
|
|
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)")
|
|
833
627
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
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")
|
|
839
633
|
|
|
840
634
|
except Exception as e:
|
|
841
635
|
# Deployment failure shouldn't block startup
|
|
@@ -860,7 +654,7 @@ def sync_remote_agents_on_startup(force_sync: bool = False):
|
|
|
860
654
|
# Cleanup legacy cache even if sync failed
|
|
861
655
|
try:
|
|
862
656
|
cleanup_legacy_agent_cache()
|
|
863
|
-
except Exception:
|
|
657
|
+
except Exception: # nosec B110
|
|
864
658
|
pass # Ignore cleanup errors
|
|
865
659
|
|
|
866
660
|
|
|
@@ -1364,33 +1158,70 @@ def show_skill_summary():
|
|
|
1364
1158
|
|
|
1365
1159
|
|
|
1366
1160
|
def verify_and_show_pm_skills():
|
|
1367
|
-
"""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.
|
|
1368
1167
|
|
|
1369
|
-
|
|
1370
|
-
|
|
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
|
|
1371
1172
|
"""
|
|
1372
1173
|
try:
|
|
1373
1174
|
from pathlib import Path
|
|
1374
1175
|
|
|
1375
|
-
from ..services.pm_skills_deployer import
|
|
1176
|
+
from ..services.pm_skills_deployer import (
|
|
1177
|
+
REQUIRED_PM_SKILLS,
|
|
1178
|
+
PMSkillsDeployerService,
|
|
1179
|
+
)
|
|
1376
1180
|
|
|
1377
1181
|
deployer = PMSkillsDeployerService()
|
|
1378
1182
|
project_dir = Path.cwd()
|
|
1379
1183
|
|
|
1380
|
-
|
|
1184
|
+
# Verify with auto-repair enabled
|
|
1185
|
+
result = deployer.verify_pm_skills(project_dir, auto_repair=True)
|
|
1381
1186
|
|
|
1382
1187
|
if result.verified:
|
|
1383
|
-
# Show verified status
|
|
1384
|
-
|
|
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
|
+
)
|
|
1385
1193
|
else:
|
|
1386
|
-
#
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
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
|
+
)
|
|
1392
1215
|
else:
|
|
1393
|
-
|
|
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}")
|
|
1394
1225
|
|
|
1395
1226
|
except ImportError:
|
|
1396
1227
|
# PM skills deployer not available - skip silently
|
|
@@ -1425,7 +1256,7 @@ def auto_install_chrome_devtools_on_startup():
|
|
|
1425
1256
|
if not chrome_devtools_config.get("auto_install", True):
|
|
1426
1257
|
# Auto-install disabled, skip silently
|
|
1427
1258
|
return
|
|
1428
|
-
except Exception:
|
|
1259
|
+
except Exception: # nosec B110
|
|
1429
1260
|
# If config loading fails, assume auto-install is enabled (default)
|
|
1430
1261
|
pass
|
|
1431
1262
|
|
|
@@ -1467,7 +1298,9 @@ def run_background_services(force_sync: bool = False):
|
|
|
1467
1298
|
check_mcp_auto_configuration()
|
|
1468
1299
|
verify_mcp_gateway_startup()
|
|
1469
1300
|
check_for_updates_async()
|
|
1470
|
-
sync_remote_agents_on_startup(
|
|
1301
|
+
sync_remote_agents_on_startup(
|
|
1302
|
+
force_sync=force_sync
|
|
1303
|
+
) # Sync agents from remote sources
|
|
1471
1304
|
show_agent_summary() # Display agent counts after deployment
|
|
1472
1305
|
|
|
1473
1306
|
# Skills deployment order (precedence: remote > bundled)
|
|
@@ -1476,7 +1309,9 @@ def run_background_services(force_sync: bool = False):
|
|
|
1476
1309
|
# 3. Discover and link runtime skills (user-added skills)
|
|
1477
1310
|
# This ensures remote skills take precedence over bundled skills when names conflict
|
|
1478
1311
|
deploy_bundled_skills() # Base layer: package-bundled skills
|
|
1479
|
-
sync_remote_skills_on_startup(
|
|
1312
|
+
sync_remote_skills_on_startup(
|
|
1313
|
+
force_sync=force_sync
|
|
1314
|
+
) # Override layer: Git-based skills (takes precedence)
|
|
1480
1315
|
discover_and_link_runtime_skills() # Discovery: user-added skills
|
|
1481
1316
|
show_skill_summary() # Display skill counts after deployment
|
|
1482
1317
|
verify_and_show_pm_skills() # PM skills verification and status
|
|
@@ -1676,7 +1511,7 @@ def verify_mcp_gateway_startup():
|
|
|
1676
1511
|
loop.run_until_complete(
|
|
1677
1512
|
asyncio.gather(*pending, return_exceptions=True)
|
|
1678
1513
|
)
|
|
1679
|
-
except Exception:
|
|
1514
|
+
except Exception: # nosec B110
|
|
1680
1515
|
pass # Ignore cleanup errors
|
|
1681
1516
|
finally:
|
|
1682
1517
|
loop.close()
|
|
@@ -1770,7 +1605,7 @@ def check_for_updates_async():
|
|
|
1770
1605
|
|
|
1771
1606
|
logger = get_logger("upgrade_check")
|
|
1772
1607
|
logger.debug(f"Update check failed (non-critical): {e}")
|
|
1773
|
-
except Exception:
|
|
1608
|
+
except Exception: # nosec B110
|
|
1774
1609
|
pass # Avoid any errors in error handling
|
|
1775
1610
|
finally:
|
|
1776
1611
|
# Properly clean up event loop
|
|
@@ -1785,7 +1620,7 @@ def check_for_updates_async():
|
|
|
1785
1620
|
loop.run_until_complete(
|
|
1786
1621
|
asyncio.gather(*pending, return_exceptions=True)
|
|
1787
1622
|
)
|
|
1788
|
-
except Exception:
|
|
1623
|
+
except Exception: # nosec B110
|
|
1789
1624
|
pass # Ignore cleanup errors
|
|
1790
1625
|
finally:
|
|
1791
1626
|
loop.close()
|