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
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
"""PM Skills Deployer Service - Deploy bundled PM skills to projects.
|
|
2
2
|
|
|
3
|
-
WHY: PM agents require specific
|
|
3
|
+
WHY: PM agents require specific framework management skills for proper operation.
|
|
4
4
|
This service manages deployment of bundled PM skills from the claude-mpm
|
|
5
|
-
package to
|
|
5
|
+
package to the Claude Code skills directory with version tracking.
|
|
6
6
|
|
|
7
7
|
DESIGN DECISIONS:
|
|
8
|
-
- Deploys from src/claude_mpm/skills/bundled/pm/ to .claude
|
|
8
|
+
- Deploys from src/claude_mpm/skills/bundled/pm/ to .claude/skills/
|
|
9
|
+
- Skills named mpm-* (framework management skills)
|
|
10
|
+
- Direct deployment (no intermediate .claude-mpm/skills/pm/ step)
|
|
9
11
|
- Uses package-relative paths (works for both installed and dev mode)
|
|
10
|
-
- Supports
|
|
11
|
-
|
|
12
|
-
2. Flat files: skill-name.md (legacy format in .claude-mpm/templates/)
|
|
13
|
-
- Per-project deployment (NOT global like Claude Code skills)
|
|
12
|
+
- Supports directory structure: mpm-skill-name/SKILL.md
|
|
13
|
+
- Per-project deployment to .claude/skills/ (Claude Code location)
|
|
14
14
|
- Version tracking via .claude-mpm/pm_skills_registry.yaml
|
|
15
15
|
- Checksum validation for integrity verification
|
|
16
|
+
- Conflict resolution: mpm-* skills from src WIN (overwrite existing)
|
|
17
|
+
- Non-mpm-* skills in .claude/skills/ are untouched (user/git managed)
|
|
16
18
|
- Non-blocking verification (returns warnings, doesn't halt execution)
|
|
17
19
|
- Force flag to redeploy even if versions match
|
|
18
20
|
|
|
19
21
|
ARCHITECTURE:
|
|
20
22
|
1. Discovery: Find bundled PM skills in package (skills/bundled/pm/)
|
|
21
|
-
2. Deployment: Copy SKILL.md files to .claude
|
|
22
|
-
3.
|
|
23
|
-
4.
|
|
24
|
-
5.
|
|
23
|
+
2. Deployment: Copy SKILL.md files to .claude/skills/{name}/SKILL.md
|
|
24
|
+
3. Conflict Check: Overwrite mpm-* skills, preserve non-mpm-* skills
|
|
25
|
+
4. Registry: Track deployed versions and checksums
|
|
26
|
+
5. Verification: Check deployment status (non-blocking)
|
|
27
|
+
6. Updates: Compare bundled vs deployed versions
|
|
25
28
|
|
|
26
29
|
PATH RESOLUTION:
|
|
27
30
|
- Installed package: Uses __file__ to find skills/bundled/pm/
|
|
@@ -47,6 +50,46 @@ from claude_mpm.core.mixins import LoggerMixin
|
|
|
47
50
|
# Security constants
|
|
48
51
|
MAX_YAML_SIZE = 10 * 1024 * 1024 # 10MB limit to prevent YAML bombs
|
|
49
52
|
|
|
53
|
+
# Tier 1: Required PM skills that MUST be deployed for PM agent to function properly
|
|
54
|
+
# These are core framework management skills for basic PM operation
|
|
55
|
+
REQUIRED_PM_SKILLS = [
|
|
56
|
+
# Core command-based skills (new consolidated CLI)
|
|
57
|
+
"mpm",
|
|
58
|
+
"mpm-init",
|
|
59
|
+
"mpm-status",
|
|
60
|
+
"mpm-help",
|
|
61
|
+
"mpm-doctor",
|
|
62
|
+
# Legacy framework management skills
|
|
63
|
+
"mpm-git-file-tracking",
|
|
64
|
+
"mpm-pr-workflow",
|
|
65
|
+
"mpm-ticketing-integration",
|
|
66
|
+
"mpm-delegation-patterns",
|
|
67
|
+
"mpm-verification-protocols",
|
|
68
|
+
"mpm-bug-reporting",
|
|
69
|
+
"mpm-teaching-mode",
|
|
70
|
+
"mpm-agent-update-workflow",
|
|
71
|
+
"mpm-circuit-breaker-enforcement",
|
|
72
|
+
"mpm-tool-usage-guide",
|
|
73
|
+
"mpm-session-management",
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
# Tier 2: Recommended skills (deployed with standard install)
|
|
77
|
+
# These provide enhanced functionality for common workflows
|
|
78
|
+
RECOMMENDED_PM_SKILLS = [
|
|
79
|
+
"mpm-config",
|
|
80
|
+
"mpm-ticket-view",
|
|
81
|
+
"mpm-session-resume",
|
|
82
|
+
"mpm-postmortem",
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
# Tier 3: Optional skills (deployed with full install)
|
|
86
|
+
# These provide additional features for advanced use cases
|
|
87
|
+
OPTIONAL_PM_SKILLS = [
|
|
88
|
+
"mpm-monitor",
|
|
89
|
+
"mpm-version",
|
|
90
|
+
"mpm-organize",
|
|
91
|
+
]
|
|
92
|
+
|
|
50
93
|
|
|
51
94
|
@dataclass
|
|
52
95
|
class PMSkillInfo:
|
|
@@ -96,6 +139,7 @@ class VerificationResult:
|
|
|
96
139
|
verified: Whether all skills are properly deployed
|
|
97
140
|
warnings: List of warning messages
|
|
98
141
|
missing_skills: List of missing skill names
|
|
142
|
+
corrupted_skills: List of corrupted skill names (checksum mismatch)
|
|
99
143
|
outdated_skills: List of outdated skill names
|
|
100
144
|
message: Summary message
|
|
101
145
|
skill_count: Total number of deployed skills
|
|
@@ -104,6 +148,7 @@ class VerificationResult:
|
|
|
104
148
|
verified: bool
|
|
105
149
|
warnings: List[str]
|
|
106
150
|
missing_skills: List[str]
|
|
151
|
+
corrupted_skills: List[str]
|
|
107
152
|
outdated_skills: List[str]
|
|
108
153
|
message: str
|
|
109
154
|
skill_count: int = 0
|
|
@@ -130,8 +175,9 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
130
175
|
"""Deploy and manage PM skills from bundled sources to projects.
|
|
131
176
|
|
|
132
177
|
This service provides:
|
|
133
|
-
- Discovery of bundled PM skills (
|
|
134
|
-
- Deployment to .claude
|
|
178
|
+
- Discovery of bundled PM skills (mpm-* framework management skills)
|
|
179
|
+
- Deployment to .claude/skills/ (Claude Code location)
|
|
180
|
+
- Conflict resolution (mpm-* skills from src WIN)
|
|
135
181
|
- Version tracking via pm_skills_registry.yaml
|
|
136
182
|
- Checksum validation for integrity
|
|
137
183
|
- Non-blocking verification (warnings only)
|
|
@@ -140,7 +186,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
140
186
|
Example:
|
|
141
187
|
>>> deployer = PMSkillsDeployerService()
|
|
142
188
|
>>> result = deployer.deploy_pm_skills(Path("/project/root"))
|
|
143
|
-
>>> print(f"Deployed {len(result.deployed)} skills")
|
|
189
|
+
>>> print(f"Deployed {len(result.deployed)} skills to .claude/skills/")
|
|
144
190
|
>>>
|
|
145
191
|
>>> verify_result = deployer.verify_pm_skills(Path("/project/root"))
|
|
146
192
|
>>> if not verify_result.verified:
|
|
@@ -246,9 +292,9 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
246
292
|
project_dir: Project root directory
|
|
247
293
|
|
|
248
294
|
Returns:
|
|
249
|
-
Path to .claude
|
|
295
|
+
Path to .claude/skills/
|
|
250
296
|
"""
|
|
251
|
-
return project_dir / ".claude
|
|
297
|
+
return project_dir / ".claude" / "skills"
|
|
252
298
|
|
|
253
299
|
def _load_registry(self, project_dir: Path) -> Dict[str, Any]:
|
|
254
300
|
"""Load PM skills registry with security checks.
|
|
@@ -322,14 +368,12 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
322
368
|
def _discover_bundled_pm_skills(self) -> List[Dict[str, Any]]:
|
|
323
369
|
"""Discover all PM skills in bundled templates directory.
|
|
324
370
|
|
|
325
|
-
PM skills
|
|
326
|
-
1. Directory structure: pm-skill-name/SKILL.md (new format)
|
|
327
|
-
2. Flat files: skill-name.md (legacy format for .claude-mpm/templates/)
|
|
371
|
+
PM skills follow mpm-skill-name/SKILL.md structure.
|
|
328
372
|
|
|
329
373
|
Returns:
|
|
330
374
|
List of skill dictionaries containing:
|
|
331
|
-
- name: Skill name (directory
|
|
332
|
-
- path: Full path to skill file (SKILL.md
|
|
375
|
+
- name: Skill name (directory name, e.g., mpm-git-file-tracking)
|
|
376
|
+
- path: Full path to skill file (SKILL.md)
|
|
333
377
|
- type: File type (always 'md')
|
|
334
378
|
"""
|
|
335
379
|
skills = []
|
|
@@ -340,11 +384,16 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
340
384
|
)
|
|
341
385
|
return skills
|
|
342
386
|
|
|
343
|
-
# Scan for skill directories containing SKILL.md
|
|
387
|
+
# Scan for skill directories containing SKILL.md
|
|
344
388
|
for skill_dir in self.bundled_pm_skills_path.iterdir():
|
|
345
389
|
if not skill_dir.is_dir() or skill_dir.name.startswith("."):
|
|
346
390
|
continue
|
|
347
391
|
|
|
392
|
+
# Only process mpm-* skills (framework management)
|
|
393
|
+
if not skill_dir.name.startswith("mpm-"):
|
|
394
|
+
self.logger.debug(f"Skipping non-mpm skill: {skill_dir.name}")
|
|
395
|
+
continue
|
|
396
|
+
|
|
348
397
|
skill_file = skill_dir / "SKILL.md"
|
|
349
398
|
if skill_file.exists():
|
|
350
399
|
skills.append(
|
|
@@ -355,46 +404,91 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
355
404
|
}
|
|
356
405
|
)
|
|
357
406
|
|
|
358
|
-
# Fallback: Scan for .md files directly (legacy format)
|
|
359
|
-
for skill_file in self.bundled_pm_skills_path.glob("*.md"):
|
|
360
|
-
if skill_file.name.startswith("."):
|
|
361
|
-
continue
|
|
362
|
-
|
|
363
|
-
skills.append(
|
|
364
|
-
{
|
|
365
|
-
"name": skill_file.stem,
|
|
366
|
-
"path": skill_file,
|
|
367
|
-
"type": "md",
|
|
368
|
-
}
|
|
369
|
-
)
|
|
370
|
-
|
|
371
407
|
self.logger.info(f"Discovered {len(skills)} bundled PM skills")
|
|
372
408
|
return skills
|
|
373
409
|
|
|
410
|
+
def _get_skills_for_tier(self, tier: str) -> List[str]:
|
|
411
|
+
"""Get list of skills to deploy based on tier.
|
|
412
|
+
|
|
413
|
+
Args:
|
|
414
|
+
tier: Deployment tier - "minimal", "standard", or "full"
|
|
415
|
+
|
|
416
|
+
Returns:
|
|
417
|
+
List of skill names to deploy
|
|
418
|
+
|
|
419
|
+
Raises:
|
|
420
|
+
ValueError: If tier is invalid
|
|
421
|
+
"""
|
|
422
|
+
if tier == "minimal":
|
|
423
|
+
return REQUIRED_PM_SKILLS
|
|
424
|
+
if tier == "standard":
|
|
425
|
+
return REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS
|
|
426
|
+
if tier == "full":
|
|
427
|
+
return REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS + OPTIONAL_PM_SKILLS
|
|
428
|
+
raise ValueError(
|
|
429
|
+
f"Invalid tier '{tier}'. Must be 'minimal', 'standard', or 'full'"
|
|
430
|
+
)
|
|
431
|
+
|
|
374
432
|
def deploy_pm_skills(
|
|
375
433
|
self,
|
|
376
434
|
project_dir: Path,
|
|
377
435
|
force: bool = False,
|
|
436
|
+
tier: str = "standard",
|
|
378
437
|
progress_callback: Optional[Callable[[str, int, int], None]] = None,
|
|
379
438
|
) -> DeploymentResult:
|
|
380
|
-
"""Deploy bundled PM skills to project directory.
|
|
439
|
+
"""Deploy bundled PM skills to project directory with tier-based selection.
|
|
381
440
|
|
|
382
|
-
Copies PM skills from bundled templates to .claude
|
|
441
|
+
Copies PM skills from bundled templates to .claude/skills/{name}/SKILL.md
|
|
383
442
|
and updates registry with version and checksum information.
|
|
384
443
|
|
|
444
|
+
Deployment Tiers:
|
|
445
|
+
- "minimal": Only REQUIRED_PM_SKILLS (Tier 1 - core functionality)
|
|
446
|
+
- "standard": REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS (Tier 1+2 - common workflows)
|
|
447
|
+
- "full": All skills (Tier 1+2+3 - advanced features)
|
|
448
|
+
|
|
449
|
+
Conflict Resolution:
|
|
450
|
+
- mpm-* skills from src WIN (overwrite existing)
|
|
451
|
+
- Non-mpm-* skills in .claude/skills/ are untouched
|
|
452
|
+
|
|
385
453
|
Args:
|
|
386
454
|
project_dir: Project root directory
|
|
387
455
|
force: If True, redeploy even if skill already exists
|
|
456
|
+
tier: Deployment tier - "minimal", "standard" (default), or "full"
|
|
388
457
|
progress_callback: Optional callback(skill_name, current, total) for progress
|
|
389
458
|
|
|
390
459
|
Returns:
|
|
391
460
|
DeploymentResult with deployment status and details
|
|
392
461
|
|
|
393
462
|
Example:
|
|
394
|
-
>>>
|
|
395
|
-
>>>
|
|
463
|
+
>>> # Standard deployment (Tier 1 + Tier 2)
|
|
464
|
+
>>> result = deployer.deploy_pm_skills(Path("/project"))
|
|
465
|
+
>>> print(f"Deployed: {len(result.deployed)} to .claude/skills/")
|
|
466
|
+
>>>
|
|
467
|
+
>>> # Minimal deployment (Tier 1 only)
|
|
468
|
+
>>> result = deployer.deploy_pm_skills(Path("/project"), tier="minimal")
|
|
469
|
+
>>>
|
|
470
|
+
>>> # Full deployment (all tiers)
|
|
471
|
+
>>> result = deployer.deploy_pm_skills(Path("/project"), tier="full")
|
|
396
472
|
"""
|
|
397
|
-
|
|
473
|
+
# Get tier-based skill filter
|
|
474
|
+
try:
|
|
475
|
+
tier_skills = self._get_skills_for_tier(tier)
|
|
476
|
+
except ValueError as e:
|
|
477
|
+
return DeploymentResult(
|
|
478
|
+
success=False,
|
|
479
|
+
deployed=[],
|
|
480
|
+
skipped=[],
|
|
481
|
+
errors=[{"skill": "all", "error": str(e)}],
|
|
482
|
+
message=str(e),
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
# Discover all bundled skills, then filter by tier
|
|
486
|
+
all_skills = self._discover_bundled_pm_skills()
|
|
487
|
+
skills = [s for s in all_skills if s["name"] in tier_skills]
|
|
488
|
+
|
|
489
|
+
self.logger.info(
|
|
490
|
+
f"Deploying {len(skills)}/{len(all_skills)} skills for tier '{tier}'"
|
|
491
|
+
)
|
|
398
492
|
deployed = []
|
|
399
493
|
skipped = []
|
|
400
494
|
errors = []
|
|
@@ -447,8 +541,12 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
447
541
|
if progress_callback:
|
|
448
542
|
progress_callback(skill_name, idx + 1, total_skills)
|
|
449
543
|
|
|
450
|
-
#
|
|
451
|
-
|
|
544
|
+
# Create skill directory: .claude/skills/{skill_name}/
|
|
545
|
+
skill_dir = deployment_dir / skill_name
|
|
546
|
+
skill_dir.mkdir(parents=True, exist_ok=True)
|
|
547
|
+
|
|
548
|
+
# Target path: .claude/skills/{skill_name}/SKILL.md
|
|
549
|
+
target_path = skill_dir / "SKILL.md"
|
|
452
550
|
|
|
453
551
|
# SECURITY: Validate target path
|
|
454
552
|
if not self._validate_safe_path(deployment_dir, target_path):
|
|
@@ -468,7 +566,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
468
566
|
)
|
|
469
567
|
continue
|
|
470
568
|
|
|
471
|
-
# Deploy skill
|
|
569
|
+
# Deploy skill (overwrites if exists - mpm-* skills WIN)
|
|
472
570
|
shutil.copy2(source_path, target_path)
|
|
473
571
|
|
|
474
572
|
# Add to deployed list
|
|
@@ -506,7 +604,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
506
604
|
|
|
507
605
|
success = len(errors) == 0
|
|
508
606
|
message = (
|
|
509
|
-
f"Deployed {len(deployed)} skills, skipped {len(skipped)}, "
|
|
607
|
+
f"Deployed {len(deployed)} skills (tier: {tier}), skipped {len(skipped)}, "
|
|
510
608
|
f"{len(errors)} errors"
|
|
511
609
|
)
|
|
512
610
|
|
|
@@ -520,76 +618,107 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
520
618
|
message=message,
|
|
521
619
|
)
|
|
522
620
|
|
|
523
|
-
def verify_pm_skills(
|
|
524
|
-
|
|
621
|
+
def verify_pm_skills(
|
|
622
|
+
self, project_dir: Path, auto_repair: bool = True
|
|
623
|
+
) -> VerificationResult:
|
|
624
|
+
"""Verify PM skills are properly deployed with enhanced validation.
|
|
525
625
|
|
|
526
|
-
Checks
|
|
527
|
-
|
|
626
|
+
Checks ALL required PM skills for:
|
|
627
|
+
- Existence in deployment directory
|
|
628
|
+
- File integrity (non-empty, valid checksums)
|
|
629
|
+
- Version currency (compared to bundled source)
|
|
630
|
+
|
|
631
|
+
Auto-repair logic:
|
|
632
|
+
- If auto_repair=True (default), automatically deploys missing/corrupted skills
|
|
633
|
+
- Reports what was fixed in the result
|
|
528
634
|
|
|
529
635
|
Args:
|
|
530
636
|
project_dir: Project root directory
|
|
637
|
+
auto_repair: If True, auto-deploy missing/corrupted skills (default: True)
|
|
531
638
|
|
|
532
639
|
Returns:
|
|
533
|
-
VerificationResult with verification status
|
|
640
|
+
VerificationResult with detailed verification status:
|
|
641
|
+
- verified: True if all required skills are deployed and valid
|
|
642
|
+
- missing_skills: List of required skills not deployed
|
|
643
|
+
- corrupted_skills: List of skills with checksum mismatches
|
|
644
|
+
- warnings: List of warning messages
|
|
645
|
+
- skill_count: Total number of deployed skills
|
|
534
646
|
|
|
535
647
|
Example:
|
|
536
648
|
>>> result = deployer.verify_pm_skills(Path("/project"))
|
|
537
649
|
>>> if not result.verified:
|
|
538
|
-
...
|
|
539
|
-
...
|
|
650
|
+
... print(f"Missing: {result.missing_skills}")
|
|
651
|
+
... print(f"Corrupted: {result.corrupted_skills}")
|
|
540
652
|
"""
|
|
541
653
|
warnings = []
|
|
542
654
|
missing_skills = []
|
|
655
|
+
corrupted_skills = []
|
|
543
656
|
outdated_skills = []
|
|
544
657
|
|
|
545
658
|
# Check if registry exists
|
|
546
659
|
registry = self._load_registry(project_dir)
|
|
547
|
-
if not registry:
|
|
548
|
-
warnings.append("PM skills registry not found or invalid")
|
|
549
|
-
missing_skills.append("all")
|
|
550
|
-
return VerificationResult(
|
|
551
|
-
verified=False,
|
|
552
|
-
warnings=warnings,
|
|
553
|
-
missing_skills=missing_skills,
|
|
554
|
-
outdated_skills=outdated_skills,
|
|
555
|
-
message="PM skills not deployed. Run 'claude-mpm init' to deploy.",
|
|
556
|
-
skill_count=0,
|
|
557
|
-
)
|
|
558
|
-
|
|
559
|
-
# Check each registered skill exists
|
|
560
660
|
deployment_dir = self._get_deployment_dir(project_dir)
|
|
561
|
-
|
|
661
|
+
deployed_skills_data = registry.get("skills", []) if registry else []
|
|
562
662
|
|
|
563
|
-
for
|
|
564
|
-
|
|
565
|
-
skill_file = deployment_dir / f"{skill_name}.md"
|
|
663
|
+
# Build lookup for deployed skills
|
|
664
|
+
deployed_lookup = {skill["name"]: skill for skill in deployed_skills_data}
|
|
566
665
|
|
|
666
|
+
# Check ALL required PM skills
|
|
667
|
+
for required_skill in REQUIRED_PM_SKILLS:
|
|
668
|
+
# Check if skill is in registry
|
|
669
|
+
if required_skill not in deployed_lookup:
|
|
670
|
+
warnings.append(f"Required PM skill missing: {required_skill}")
|
|
671
|
+
missing_skills.append(required_skill)
|
|
672
|
+
continue
|
|
673
|
+
|
|
674
|
+
# Check if skill file exists
|
|
675
|
+
skill_file = deployment_dir / required_skill / "SKILL.md"
|
|
567
676
|
if not skill_file.exists():
|
|
568
|
-
warnings.append(
|
|
569
|
-
|
|
677
|
+
warnings.append(
|
|
678
|
+
f"Required PM skill file missing: {required_skill}/SKILL.md"
|
|
679
|
+
)
|
|
680
|
+
missing_skills.append(required_skill)
|
|
681
|
+
continue
|
|
682
|
+
|
|
683
|
+
# Check if skill file is empty/corrupted
|
|
684
|
+
try:
|
|
685
|
+
file_size = skill_file.stat().st_size
|
|
686
|
+
if file_size == 0:
|
|
687
|
+
warnings.append(
|
|
688
|
+
f"Required PM skill file is empty: {required_skill}/SKILL.md"
|
|
689
|
+
)
|
|
690
|
+
corrupted_skills.append(required_skill)
|
|
691
|
+
continue
|
|
692
|
+
except OSError as e:
|
|
693
|
+
warnings.append(
|
|
694
|
+
f"Cannot read required PM skill file: {required_skill}/SKILL.md - {e}"
|
|
695
|
+
)
|
|
696
|
+
corrupted_skills.append(required_skill)
|
|
570
697
|
continue
|
|
571
698
|
|
|
572
699
|
# Verify checksum
|
|
700
|
+
deployed_skill = deployed_lookup[required_skill]
|
|
573
701
|
current_checksum = self._compute_checksum(skill_file)
|
|
574
|
-
expected_checksum =
|
|
702
|
+
expected_checksum = deployed_skill.get("checksum", "")
|
|
575
703
|
|
|
576
704
|
if current_checksum != expected_checksum:
|
|
577
705
|
warnings.append(
|
|
578
|
-
f"
|
|
706
|
+
f"Required PM skill checksum mismatch: {required_skill} (file may be corrupted)"
|
|
579
707
|
)
|
|
580
|
-
|
|
708
|
+
corrupted_skills.append(required_skill)
|
|
581
709
|
|
|
582
|
-
# Check for available updates
|
|
710
|
+
# Check for available updates (bundled skills newer than deployed)
|
|
583
711
|
bundled_skills = {s["name"]: s for s in self._discover_bundled_pm_skills()}
|
|
584
712
|
for skill_name, bundled_skill in bundled_skills.items():
|
|
713
|
+
# Skip non-required skills
|
|
714
|
+
if skill_name not in REQUIRED_PM_SKILLS:
|
|
715
|
+
continue
|
|
716
|
+
|
|
585
717
|
# Find corresponding deployed skill
|
|
586
|
-
deployed_skill =
|
|
587
|
-
(s for s in deployed_skills if s["name"] == skill_name), None
|
|
588
|
-
)
|
|
718
|
+
deployed_skill = deployed_lookup.get(skill_name)
|
|
589
719
|
|
|
590
720
|
if not deployed_skill:
|
|
591
|
-
|
|
592
|
-
missing_skills.append(skill_name)
|
|
721
|
+
# Already tracked as missing
|
|
593
722
|
continue
|
|
594
723
|
|
|
595
724
|
# Check if checksums differ
|
|
@@ -597,23 +726,66 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
597
726
|
deployed_checksum = deployed_skill.get("checksum", "")
|
|
598
727
|
|
|
599
728
|
if bundled_checksum != deployed_checksum:
|
|
600
|
-
|
|
601
|
-
|
|
729
|
+
# Don't add to outdated_skills if already in corrupted_skills
|
|
730
|
+
if skill_name not in corrupted_skills:
|
|
731
|
+
warnings.append(f"PM skill update available: {skill_name}")
|
|
732
|
+
outdated_skills.append(skill_name)
|
|
733
|
+
|
|
734
|
+
# Auto-repair if enabled and issues found
|
|
735
|
+
repaired_skills = []
|
|
736
|
+
if auto_repair and (missing_skills or corrupted_skills):
|
|
737
|
+
self.logger.info(
|
|
738
|
+
f"Auto-repairing PM skills: {len(missing_skills)} missing, "
|
|
739
|
+
f"{len(corrupted_skills)} corrupted"
|
|
740
|
+
)
|
|
741
|
+
|
|
742
|
+
# Deploy missing and corrupted skills
|
|
743
|
+
repair_result = self.deploy_pm_skills(project_dir, force=True)
|
|
744
|
+
|
|
745
|
+
if repair_result.success:
|
|
746
|
+
repaired_skills = repair_result.deployed
|
|
747
|
+
self.logger.info(f"Auto-repaired {len(repaired_skills)} PM skills")
|
|
748
|
+
|
|
749
|
+
# Remove repaired skills from missing/corrupted lists
|
|
750
|
+
missing_skills = [s for s in missing_skills if s not in repaired_skills]
|
|
751
|
+
corrupted_skills = [
|
|
752
|
+
s for s in corrupted_skills if s not in repaired_skills
|
|
753
|
+
]
|
|
754
|
+
|
|
755
|
+
# Update warnings
|
|
756
|
+
if repaired_skills:
|
|
757
|
+
warnings.append(
|
|
758
|
+
f"Auto-repaired {len(repaired_skills)} PM skills: {', '.join(repaired_skills)}"
|
|
759
|
+
)
|
|
760
|
+
else:
|
|
761
|
+
warnings.append(
|
|
762
|
+
f"Auto-repair failed: {len(repair_result.errors)} errors"
|
|
763
|
+
)
|
|
764
|
+
self.logger.error(
|
|
765
|
+
f"Auto-repair failed with errors: {repair_result.errors}"
|
|
766
|
+
)
|
|
602
767
|
|
|
603
|
-
|
|
768
|
+
# Determine verification status
|
|
769
|
+
verified = len(missing_skills) == 0 and len(corrupted_skills) == 0
|
|
604
770
|
|
|
771
|
+
# Build message
|
|
605
772
|
if verified:
|
|
606
|
-
|
|
773
|
+
if repaired_skills:
|
|
774
|
+
message = f"All PM skills verified (auto-repaired {len(repaired_skills)} skills)"
|
|
775
|
+
else:
|
|
776
|
+
message = "All PM skills verified and up-to-date"
|
|
607
777
|
else:
|
|
608
|
-
|
|
778
|
+
issue_count = len(missing_skills) + len(corrupted_skills)
|
|
779
|
+
message = f"{issue_count} PM skill issues found"
|
|
609
780
|
|
|
610
781
|
return VerificationResult(
|
|
611
782
|
verified=verified,
|
|
612
783
|
warnings=warnings,
|
|
613
784
|
missing_skills=missing_skills,
|
|
785
|
+
corrupted_skills=corrupted_skills,
|
|
614
786
|
outdated_skills=outdated_skills,
|
|
615
787
|
message=message,
|
|
616
|
-
skill_count=len(
|
|
788
|
+
skill_count=len(deployed_skills_data),
|
|
617
789
|
)
|
|
618
790
|
|
|
619
791
|
def get_deployed_skills(self, project_dir: Path) -> List[PMSkillInfo]:
|
|
@@ -636,10 +808,10 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
636
808
|
skills = []
|
|
637
809
|
for skill_data in registry.get("skills", []):
|
|
638
810
|
skill_name = skill_data["name"]
|
|
639
|
-
deployed_path = deployment_dir /
|
|
811
|
+
deployed_path = deployment_dir / skill_name / "SKILL.md"
|
|
640
812
|
|
|
641
813
|
# Find source path (may not exist if bundled skills changed)
|
|
642
|
-
source_path = self.bundled_pm_skills_path /
|
|
814
|
+
source_path = self.bundled_pm_skills_path / skill_name / "SKILL.md"
|
|
643
815
|
|
|
644
816
|
skills.append(
|
|
645
817
|
PMSkillInfo(
|