claude-mpm 5.4.85__py3-none-any.whl → 5.6.76__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_FOUNDERS_OUTPUT_STYLE.md → CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md} +14 -6
- claude_mpm/agents/PM_INSTRUCTIONS.md +109 -706
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/auth/__init__.py +35 -0
- claude_mpm/auth/callback_server.py +328 -0
- claude_mpm/auth/models.py +104 -0
- claude_mpm/auth/oauth_manager.py +266 -0
- claude_mpm/auth/providers/__init__.py +12 -0
- claude_mpm/auth/providers/base.py +165 -0
- claude_mpm/auth/providers/google.py +261 -0
- claude_mpm/auth/token_storage.py +252 -0
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/mcp.py +29 -17
- claude_mpm/cli/commands/mcp_command_router.py +39 -0
- claude_mpm/cli/commands/mcp_service_commands.py +304 -0
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +2 -2
- claude_mpm/cli/commands/oauth.py +481 -0
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +5 -3
- claude_mpm/cli/executor.py +128 -16
- claude_mpm/cli/helpers.py +1 -1
- claude_mpm/cli/parsers/base_parser.py +84 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/mcp_parser.py +79 -0
- claude_mpm/cli/parsers/oauth_parser.py +165 -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 +345 -40
- claude_mpm/cli/startup_display.py +76 -7
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/startup_migrations.py +236 -0
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +78 -0
- claude_mpm/commander/adapters/__init__.py +60 -0
- claude_mpm/commander/adapters/auggie.py +260 -0
- claude_mpm/commander/adapters/base.py +288 -0
- claude_mpm/commander/adapters/claude_code.py +392 -0
- claude_mpm/commander/adapters/codex.py +237 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/adapters/example_usage.py +310 -0
- claude_mpm/commander/adapters/mpm.py +389 -0
- claude_mpm/commander/adapters/registry.py +204 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +121 -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 +226 -0
- claude_mpm/commander/api/routes/work.py +296 -0
- claude_mpm/commander/api/schemas.py +186 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +149 -0
- claude_mpm/commander/chat/commands.py +124 -0
- claude_mpm/commander/chat/repl.py +1957 -0
- claude_mpm/commander/config.py +51 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/core/__init__.py +10 -0
- claude_mpm/commander/core/block_manager.py +325 -0
- claude_mpm/commander/core/response_manager.py +323 -0
- claude_mpm/commander/daemon.py +603 -0
- claude_mpm/commander/env_loader.py +59 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +392 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +233 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +57 -0
- claude_mpm/commander/git/__init__.py +5 -0
- claude_mpm/commander/git/worktree_manager.py +212 -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 +868 -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/memory/__init__.py +45 -0
- claude_mpm/commander/memory/compression.py +347 -0
- claude_mpm/commander/memory/embeddings.py +230 -0
- claude_mpm/commander/memory/entities.py +310 -0
- claude_mpm/commander/memory/example_usage.py +290 -0
- claude_mpm/commander/memory/integration.py +325 -0
- claude_mpm/commander/memory/search.py +381 -0
- claude_mpm/commander/memory/store.py +657 -0
- claude_mpm/commander/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +127 -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 +403 -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 +410 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +346 -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 +362 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +207 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +241 -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 +5 -0
- claude_mpm/core/claude_runner.py +152 -0
- claude_mpm/core/config.py +35 -22
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/hook_manager.py +53 -4
- claude_mpm/core/interactive_session.py +5 -4
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +39 -13
- claude_mpm/core/network_config.py +148 -0
- claude_mpm/core/oneshot_session.py +7 -6
- claude_mpm/core/output_style_manager.py +52 -12
- claude_mpm/core/socketio_pool.py +47 -15
- claude_mpm/core/unified_config.py +10 -6
- claude_mpm/core/unified_paths.py +68 -80
- 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 +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +466 -136
- claude_mpm/hooks/claude_hooks/hook_handler.py +204 -104
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +291 -59
- claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
- claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
- claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
- claude_mpm/hooks/claude_hooks/services/container.py +326 -0
- claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
- claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
- claude_mpm/init.py +22 -15
- claude_mpm/mcp/__init__.py +9 -0
- claude_mpm/mcp/google_workspace_server.py +610 -0
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- 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/remote_agent_discovery_service.py +3 -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/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/command_deployment_service.py +44 -26
- 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/hook_installer_service.py +77 -8
- 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/mcp_config_manager.py +99 -19
- claude_mpm/services/mcp_service_registry.py +294 -0
- claude_mpm/services/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +8 -2
- claude_mpm/services/monitor/server.py +111 -16
- claude_mpm/services/pm_skills_deployer.py +261 -87
- claude_mpm/services/skills/git_skill_source_manager.py +130 -10
- claude_mpm/services/skills/selective_skill_deployer.py +142 -16
- 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/__init__.py +2 -1
- 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-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-pause/SKILL.md +170 -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/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +4 -4
- claude_mpm-5.6.76.dist-info/METADATA +416 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/RECORD +312 -175
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/WHEEL +1 -1
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/entry_points.txt +2 -0
- 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.85.dist-info/METADATA +0 -1023
- /claude_mpm/skills/bundled/pm/{pm-bug-reporting/pm-bug-reporting.md → mpm-bug-reporting/SKILL.md} +0 -0
- /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.85.dist-info → claude_mpm-5.6.76.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.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,47 @@ 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
|
+
"mpm-session-pause",
|
|
75
|
+
"mpm-session-resume",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
# Tier 2: Recommended skills (deployed with standard install)
|
|
79
|
+
# These provide enhanced functionality for common workflows
|
|
80
|
+
RECOMMENDED_PM_SKILLS = [
|
|
81
|
+
"mpm-config",
|
|
82
|
+
"mpm-ticket-view",
|
|
83
|
+
"mpm-postmortem",
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
# Tier 3: Optional skills (deployed with full install)
|
|
87
|
+
# These provide additional features for advanced use cases
|
|
88
|
+
OPTIONAL_PM_SKILLS = [
|
|
89
|
+
"mpm-monitor",
|
|
90
|
+
"mpm-version",
|
|
91
|
+
"mpm-organize",
|
|
92
|
+
]
|
|
93
|
+
|
|
50
94
|
|
|
51
95
|
@dataclass
|
|
52
96
|
class PMSkillInfo:
|
|
@@ -96,6 +140,7 @@ class VerificationResult:
|
|
|
96
140
|
verified: Whether all skills are properly deployed
|
|
97
141
|
warnings: List of warning messages
|
|
98
142
|
missing_skills: List of missing skill names
|
|
143
|
+
corrupted_skills: List of corrupted skill names (checksum mismatch)
|
|
99
144
|
outdated_skills: List of outdated skill names
|
|
100
145
|
message: Summary message
|
|
101
146
|
skill_count: Total number of deployed skills
|
|
@@ -104,6 +149,7 @@ class VerificationResult:
|
|
|
104
149
|
verified: bool
|
|
105
150
|
warnings: List[str]
|
|
106
151
|
missing_skills: List[str]
|
|
152
|
+
corrupted_skills: List[str]
|
|
107
153
|
outdated_skills: List[str]
|
|
108
154
|
message: str
|
|
109
155
|
skill_count: int = 0
|
|
@@ -130,8 +176,9 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
130
176
|
"""Deploy and manage PM skills from bundled sources to projects.
|
|
131
177
|
|
|
132
178
|
This service provides:
|
|
133
|
-
- Discovery of bundled PM skills (
|
|
134
|
-
- Deployment to .claude
|
|
179
|
+
- Discovery of bundled PM skills (mpm-* framework management skills)
|
|
180
|
+
- Deployment to .claude/skills/ (Claude Code location)
|
|
181
|
+
- Conflict resolution (mpm-* skills from src WIN)
|
|
135
182
|
- Version tracking via pm_skills_registry.yaml
|
|
136
183
|
- Checksum validation for integrity
|
|
137
184
|
- Non-blocking verification (warnings only)
|
|
@@ -140,7 +187,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
140
187
|
Example:
|
|
141
188
|
>>> deployer = PMSkillsDeployerService()
|
|
142
189
|
>>> result = deployer.deploy_pm_skills(Path("/project/root"))
|
|
143
|
-
>>> print(f"Deployed {len(result.deployed)} skills")
|
|
190
|
+
>>> print(f"Deployed {len(result.deployed)} skills to .claude/skills/")
|
|
144
191
|
>>>
|
|
145
192
|
>>> verify_result = deployer.verify_pm_skills(Path("/project/root"))
|
|
146
193
|
>>> if not verify_result.verified:
|
|
@@ -246,9 +293,9 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
246
293
|
project_dir: Project root directory
|
|
247
294
|
|
|
248
295
|
Returns:
|
|
249
|
-
Path to .claude
|
|
296
|
+
Path to .claude/skills/
|
|
250
297
|
"""
|
|
251
|
-
return project_dir / ".claude
|
|
298
|
+
return project_dir / ".claude" / "skills"
|
|
252
299
|
|
|
253
300
|
def _load_registry(self, project_dir: Path) -> Dict[str, Any]:
|
|
254
301
|
"""Load PM skills registry with security checks.
|
|
@@ -322,14 +369,12 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
322
369
|
def _discover_bundled_pm_skills(self) -> List[Dict[str, Any]]:
|
|
323
370
|
"""Discover all PM skills in bundled templates directory.
|
|
324
371
|
|
|
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/)
|
|
372
|
+
PM skills follow mpm-skill-name/SKILL.md structure.
|
|
328
373
|
|
|
329
374
|
Returns:
|
|
330
375
|
List of skill dictionaries containing:
|
|
331
|
-
- name: Skill name (directory
|
|
332
|
-
- path: Full path to skill file (SKILL.md
|
|
376
|
+
- name: Skill name (directory name, e.g., mpm-git-file-tracking)
|
|
377
|
+
- path: Full path to skill file (SKILL.md)
|
|
333
378
|
- type: File type (always 'md')
|
|
334
379
|
"""
|
|
335
380
|
skills = []
|
|
@@ -340,11 +385,17 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
340
385
|
)
|
|
341
386
|
return skills
|
|
342
387
|
|
|
343
|
-
# Scan for skill directories containing SKILL.md
|
|
388
|
+
# Scan for skill directories containing SKILL.md
|
|
344
389
|
for skill_dir in self.bundled_pm_skills_path.iterdir():
|
|
345
390
|
if not skill_dir.is_dir() or skill_dir.name.startswith("."):
|
|
346
391
|
continue
|
|
347
392
|
|
|
393
|
+
# Only process mpm* skills (framework management)
|
|
394
|
+
# Note: Includes both 'mpm' (core skill) and 'mpm-*' (other PM skills)
|
|
395
|
+
if not skill_dir.name.startswith("mpm"):
|
|
396
|
+
self.logger.debug(f"Skipping non-mpm skill: {skill_dir.name}")
|
|
397
|
+
continue
|
|
398
|
+
|
|
348
399
|
skill_file = skill_dir / "SKILL.md"
|
|
349
400
|
if skill_file.exists():
|
|
350
401
|
skills.append(
|
|
@@ -355,46 +406,91 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
355
406
|
}
|
|
356
407
|
)
|
|
357
408
|
|
|
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
409
|
self.logger.info(f"Discovered {len(skills)} bundled PM skills")
|
|
372
410
|
return skills
|
|
373
411
|
|
|
412
|
+
def _get_skills_for_tier(self, tier: str) -> List[str]:
|
|
413
|
+
"""Get list of skills to deploy based on tier.
|
|
414
|
+
|
|
415
|
+
Args:
|
|
416
|
+
tier: Deployment tier - "minimal", "standard", or "full"
|
|
417
|
+
|
|
418
|
+
Returns:
|
|
419
|
+
List of skill names to deploy
|
|
420
|
+
|
|
421
|
+
Raises:
|
|
422
|
+
ValueError: If tier is invalid
|
|
423
|
+
"""
|
|
424
|
+
if tier == "minimal":
|
|
425
|
+
return REQUIRED_PM_SKILLS
|
|
426
|
+
if tier == "standard":
|
|
427
|
+
return REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS
|
|
428
|
+
if tier == "full":
|
|
429
|
+
return REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS + OPTIONAL_PM_SKILLS
|
|
430
|
+
raise ValueError(
|
|
431
|
+
f"Invalid tier '{tier}'. Must be 'minimal', 'standard', or 'full'"
|
|
432
|
+
)
|
|
433
|
+
|
|
374
434
|
def deploy_pm_skills(
|
|
375
435
|
self,
|
|
376
436
|
project_dir: Path,
|
|
377
437
|
force: bool = False,
|
|
438
|
+
tier: str = "standard",
|
|
378
439
|
progress_callback: Optional[Callable[[str, int, int], None]] = None,
|
|
379
440
|
) -> DeploymentResult:
|
|
380
|
-
"""Deploy bundled PM skills to project directory.
|
|
441
|
+
"""Deploy bundled PM skills to project directory with tier-based selection.
|
|
381
442
|
|
|
382
|
-
Copies PM skills from bundled templates to .claude
|
|
443
|
+
Copies PM skills from bundled templates to .claude/skills/{name}/SKILL.md
|
|
383
444
|
and updates registry with version and checksum information.
|
|
384
445
|
|
|
446
|
+
Deployment Tiers:
|
|
447
|
+
- "minimal": Only REQUIRED_PM_SKILLS (Tier 1 - core functionality)
|
|
448
|
+
- "standard": REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS (Tier 1+2 - common workflows)
|
|
449
|
+
- "full": All skills (Tier 1+2+3 - advanced features)
|
|
450
|
+
|
|
451
|
+
Conflict Resolution:
|
|
452
|
+
- mpm-* skills from src WIN (overwrite existing)
|
|
453
|
+
- Non-mpm-* skills in .claude/skills/ are untouched
|
|
454
|
+
|
|
385
455
|
Args:
|
|
386
456
|
project_dir: Project root directory
|
|
387
457
|
force: If True, redeploy even if skill already exists
|
|
458
|
+
tier: Deployment tier - "minimal", "standard" (default), or "full"
|
|
388
459
|
progress_callback: Optional callback(skill_name, current, total) for progress
|
|
389
460
|
|
|
390
461
|
Returns:
|
|
391
462
|
DeploymentResult with deployment status and details
|
|
392
463
|
|
|
393
464
|
Example:
|
|
394
|
-
>>>
|
|
395
|
-
>>>
|
|
465
|
+
>>> # Standard deployment (Tier 1 + Tier 2)
|
|
466
|
+
>>> result = deployer.deploy_pm_skills(Path("/project"))
|
|
467
|
+
>>> print(f"Deployed: {len(result.deployed)} to .claude/skills/")
|
|
468
|
+
>>>
|
|
469
|
+
>>> # Minimal deployment (Tier 1 only)
|
|
470
|
+
>>> result = deployer.deploy_pm_skills(Path("/project"), tier="minimal")
|
|
471
|
+
>>>
|
|
472
|
+
>>> # Full deployment (all tiers)
|
|
473
|
+
>>> result = deployer.deploy_pm_skills(Path("/project"), tier="full")
|
|
396
474
|
"""
|
|
397
|
-
|
|
475
|
+
# Get tier-based skill filter
|
|
476
|
+
try:
|
|
477
|
+
tier_skills = self._get_skills_for_tier(tier)
|
|
478
|
+
except ValueError as e:
|
|
479
|
+
return DeploymentResult(
|
|
480
|
+
success=False,
|
|
481
|
+
deployed=[],
|
|
482
|
+
skipped=[],
|
|
483
|
+
errors=[{"skill": "all", "error": str(e)}],
|
|
484
|
+
message=str(e),
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
# Discover all bundled skills, then filter by tier
|
|
488
|
+
all_skills = self._discover_bundled_pm_skills()
|
|
489
|
+
skills = [s for s in all_skills if s["name"] in tier_skills]
|
|
490
|
+
|
|
491
|
+
self.logger.info(
|
|
492
|
+
f"Deploying {len(skills)}/{len(all_skills)} skills for tier '{tier}'"
|
|
493
|
+
)
|
|
398
494
|
deployed = []
|
|
399
495
|
skipped = []
|
|
400
496
|
errors = []
|
|
@@ -447,8 +543,12 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
447
543
|
if progress_callback:
|
|
448
544
|
progress_callback(skill_name, idx + 1, total_skills)
|
|
449
545
|
|
|
450
|
-
#
|
|
451
|
-
|
|
546
|
+
# Create skill directory: .claude/skills/{skill_name}/
|
|
547
|
+
skill_dir = deployment_dir / skill_name
|
|
548
|
+
skill_dir.mkdir(parents=True, exist_ok=True)
|
|
549
|
+
|
|
550
|
+
# Target path: .claude/skills/{skill_name}/SKILL.md
|
|
551
|
+
target_path = skill_dir / "SKILL.md"
|
|
452
552
|
|
|
453
553
|
# SECURITY: Validate target path
|
|
454
554
|
if not self._validate_safe_path(deployment_dir, target_path):
|
|
@@ -468,7 +568,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
468
568
|
)
|
|
469
569
|
continue
|
|
470
570
|
|
|
471
|
-
# Deploy skill
|
|
571
|
+
# Deploy skill (overwrites if exists - mpm-* skills WIN)
|
|
472
572
|
shutil.copy2(source_path, target_path)
|
|
473
573
|
|
|
474
574
|
# Add to deployed list
|
|
@@ -506,7 +606,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
506
606
|
|
|
507
607
|
success = len(errors) == 0
|
|
508
608
|
message = (
|
|
509
|
-
f"Deployed {len(deployed)} skills, skipped {len(skipped)}, "
|
|
609
|
+
f"Deployed {len(deployed)} skills (tier: {tier}), skipped {len(skipped)}, "
|
|
510
610
|
f"{len(errors)} errors"
|
|
511
611
|
)
|
|
512
612
|
|
|
@@ -520,76 +620,107 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
520
620
|
message=message,
|
|
521
621
|
)
|
|
522
622
|
|
|
523
|
-
def verify_pm_skills(
|
|
524
|
-
|
|
623
|
+
def verify_pm_skills(
|
|
624
|
+
self, project_dir: Path, auto_repair: bool = True
|
|
625
|
+
) -> VerificationResult:
|
|
626
|
+
"""Verify PM skills are properly deployed with enhanced validation.
|
|
525
627
|
|
|
526
|
-
Checks
|
|
527
|
-
|
|
628
|
+
Checks ALL required PM skills for:
|
|
629
|
+
- Existence in deployment directory
|
|
630
|
+
- File integrity (non-empty, valid checksums)
|
|
631
|
+
- Version currency (compared to bundled source)
|
|
632
|
+
|
|
633
|
+
Auto-repair logic:
|
|
634
|
+
- If auto_repair=True (default), automatically deploys missing/corrupted skills
|
|
635
|
+
- Reports what was fixed in the result
|
|
528
636
|
|
|
529
637
|
Args:
|
|
530
638
|
project_dir: Project root directory
|
|
639
|
+
auto_repair: If True, auto-deploy missing/corrupted skills (default: True)
|
|
531
640
|
|
|
532
641
|
Returns:
|
|
533
|
-
VerificationResult with verification status
|
|
642
|
+
VerificationResult with detailed verification status:
|
|
643
|
+
- verified: True if all required skills are deployed and valid
|
|
644
|
+
- missing_skills: List of required skills not deployed
|
|
645
|
+
- corrupted_skills: List of skills with checksum mismatches
|
|
646
|
+
- warnings: List of warning messages
|
|
647
|
+
- skill_count: Total number of deployed skills
|
|
534
648
|
|
|
535
649
|
Example:
|
|
536
650
|
>>> result = deployer.verify_pm_skills(Path("/project"))
|
|
537
651
|
>>> if not result.verified:
|
|
538
|
-
...
|
|
539
|
-
...
|
|
652
|
+
... print(f"Missing: {result.missing_skills}")
|
|
653
|
+
... print(f"Corrupted: {result.corrupted_skills}")
|
|
540
654
|
"""
|
|
541
655
|
warnings = []
|
|
542
656
|
missing_skills = []
|
|
657
|
+
corrupted_skills = []
|
|
543
658
|
outdated_skills = []
|
|
544
659
|
|
|
545
660
|
# Check if registry exists
|
|
546
661
|
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
662
|
deployment_dir = self._get_deployment_dir(project_dir)
|
|
561
|
-
|
|
663
|
+
deployed_skills_data = registry.get("skills", []) if registry else []
|
|
562
664
|
|
|
563
|
-
for
|
|
564
|
-
|
|
565
|
-
skill_file = deployment_dir / f"{skill_name}.md"
|
|
665
|
+
# Build lookup for deployed skills
|
|
666
|
+
deployed_lookup = {skill["name"]: skill for skill in deployed_skills_data}
|
|
566
667
|
|
|
668
|
+
# Check ALL required PM skills
|
|
669
|
+
for required_skill in REQUIRED_PM_SKILLS:
|
|
670
|
+
# Check if skill is in registry
|
|
671
|
+
if required_skill not in deployed_lookup:
|
|
672
|
+
warnings.append(f"Required PM skill missing: {required_skill}")
|
|
673
|
+
missing_skills.append(required_skill)
|
|
674
|
+
continue
|
|
675
|
+
|
|
676
|
+
# Check if skill file exists
|
|
677
|
+
skill_file = deployment_dir / required_skill / "SKILL.md"
|
|
567
678
|
if not skill_file.exists():
|
|
568
|
-
warnings.append(
|
|
569
|
-
|
|
679
|
+
warnings.append(
|
|
680
|
+
f"Required PM skill file missing: {required_skill}/SKILL.md"
|
|
681
|
+
)
|
|
682
|
+
missing_skills.append(required_skill)
|
|
683
|
+
continue
|
|
684
|
+
|
|
685
|
+
# Check if skill file is empty/corrupted
|
|
686
|
+
try:
|
|
687
|
+
file_size = skill_file.stat().st_size
|
|
688
|
+
if file_size == 0:
|
|
689
|
+
warnings.append(
|
|
690
|
+
f"Required PM skill file is empty: {required_skill}/SKILL.md"
|
|
691
|
+
)
|
|
692
|
+
corrupted_skills.append(required_skill)
|
|
693
|
+
continue
|
|
694
|
+
except OSError as e:
|
|
695
|
+
warnings.append(
|
|
696
|
+
f"Cannot read required PM skill file: {required_skill}/SKILL.md - {e}"
|
|
697
|
+
)
|
|
698
|
+
corrupted_skills.append(required_skill)
|
|
570
699
|
continue
|
|
571
700
|
|
|
572
701
|
# Verify checksum
|
|
702
|
+
deployed_skill = deployed_lookup[required_skill]
|
|
573
703
|
current_checksum = self._compute_checksum(skill_file)
|
|
574
|
-
expected_checksum =
|
|
704
|
+
expected_checksum = deployed_skill.get("checksum", "")
|
|
575
705
|
|
|
576
706
|
if current_checksum != expected_checksum:
|
|
577
707
|
warnings.append(
|
|
578
|
-
f"
|
|
708
|
+
f"Required PM skill checksum mismatch: {required_skill} (file may be corrupted)"
|
|
579
709
|
)
|
|
580
|
-
|
|
710
|
+
corrupted_skills.append(required_skill)
|
|
581
711
|
|
|
582
|
-
# Check for available updates
|
|
712
|
+
# Check for available updates (bundled skills newer than deployed)
|
|
583
713
|
bundled_skills = {s["name"]: s for s in self._discover_bundled_pm_skills()}
|
|
584
714
|
for skill_name, bundled_skill in bundled_skills.items():
|
|
715
|
+
# Skip non-required skills
|
|
716
|
+
if skill_name not in REQUIRED_PM_SKILLS:
|
|
717
|
+
continue
|
|
718
|
+
|
|
585
719
|
# Find corresponding deployed skill
|
|
586
|
-
deployed_skill =
|
|
587
|
-
(s for s in deployed_skills if s["name"] == skill_name), None
|
|
588
|
-
)
|
|
720
|
+
deployed_skill = deployed_lookup.get(skill_name)
|
|
589
721
|
|
|
590
722
|
if not deployed_skill:
|
|
591
|
-
|
|
592
|
-
missing_skills.append(skill_name)
|
|
723
|
+
# Already tracked as missing
|
|
593
724
|
continue
|
|
594
725
|
|
|
595
726
|
# Check if checksums differ
|
|
@@ -597,23 +728,66 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
597
728
|
deployed_checksum = deployed_skill.get("checksum", "")
|
|
598
729
|
|
|
599
730
|
if bundled_checksum != deployed_checksum:
|
|
600
|
-
|
|
601
|
-
|
|
731
|
+
# Don't add to outdated_skills if already in corrupted_skills
|
|
732
|
+
if skill_name not in corrupted_skills:
|
|
733
|
+
warnings.append(f"PM skill update available: {skill_name}")
|
|
734
|
+
outdated_skills.append(skill_name)
|
|
735
|
+
|
|
736
|
+
# Auto-repair if enabled and issues found
|
|
737
|
+
repaired_skills = []
|
|
738
|
+
if auto_repair and (missing_skills or corrupted_skills):
|
|
739
|
+
self.logger.info(
|
|
740
|
+
f"Auto-repairing PM skills: {len(missing_skills)} missing, "
|
|
741
|
+
f"{len(corrupted_skills)} corrupted"
|
|
742
|
+
)
|
|
743
|
+
|
|
744
|
+
# Deploy missing and corrupted skills
|
|
745
|
+
repair_result = self.deploy_pm_skills(project_dir, force=True)
|
|
746
|
+
|
|
747
|
+
if repair_result.success:
|
|
748
|
+
repaired_skills = repair_result.deployed
|
|
749
|
+
self.logger.info(f"Auto-repaired {len(repaired_skills)} PM skills")
|
|
750
|
+
|
|
751
|
+
# Remove repaired skills from missing/corrupted lists
|
|
752
|
+
missing_skills = [s for s in missing_skills if s not in repaired_skills]
|
|
753
|
+
corrupted_skills = [
|
|
754
|
+
s for s in corrupted_skills if s not in repaired_skills
|
|
755
|
+
]
|
|
756
|
+
|
|
757
|
+
# Update warnings
|
|
758
|
+
if repaired_skills:
|
|
759
|
+
warnings.append(
|
|
760
|
+
f"Auto-repaired {len(repaired_skills)} PM skills: {', '.join(repaired_skills)}"
|
|
761
|
+
)
|
|
762
|
+
else:
|
|
763
|
+
warnings.append(
|
|
764
|
+
f"Auto-repair failed: {len(repair_result.errors)} errors"
|
|
765
|
+
)
|
|
766
|
+
self.logger.error(
|
|
767
|
+
f"Auto-repair failed with errors: {repair_result.errors}"
|
|
768
|
+
)
|
|
602
769
|
|
|
603
|
-
|
|
770
|
+
# Determine verification status
|
|
771
|
+
verified = len(missing_skills) == 0 and len(corrupted_skills) == 0
|
|
604
772
|
|
|
773
|
+
# Build message
|
|
605
774
|
if verified:
|
|
606
|
-
|
|
775
|
+
if repaired_skills:
|
|
776
|
+
message = f"All PM skills verified (auto-repaired {len(repaired_skills)} skills)"
|
|
777
|
+
else:
|
|
778
|
+
message = "All PM skills verified and up-to-date"
|
|
607
779
|
else:
|
|
608
|
-
|
|
780
|
+
issue_count = len(missing_skills) + len(corrupted_skills)
|
|
781
|
+
message = f"{issue_count} PM skill issues found"
|
|
609
782
|
|
|
610
783
|
return VerificationResult(
|
|
611
784
|
verified=verified,
|
|
612
785
|
warnings=warnings,
|
|
613
786
|
missing_skills=missing_skills,
|
|
787
|
+
corrupted_skills=corrupted_skills,
|
|
614
788
|
outdated_skills=outdated_skills,
|
|
615
789
|
message=message,
|
|
616
|
-
skill_count=len(
|
|
790
|
+
skill_count=len(deployed_skills_data),
|
|
617
791
|
)
|
|
618
792
|
|
|
619
793
|
def get_deployed_skills(self, project_dir: Path) -> List[PMSkillInfo]:
|
|
@@ -636,10 +810,10 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
636
810
|
skills = []
|
|
637
811
|
for skill_data in registry.get("skills", []):
|
|
638
812
|
skill_name = skill_data["name"]
|
|
639
|
-
deployed_path = deployment_dir /
|
|
813
|
+
deployed_path = deployment_dir / skill_name / "SKILL.md"
|
|
640
814
|
|
|
641
815
|
# Find source path (may not exist if bundled skills changed)
|
|
642
|
-
source_path = self.bundled_pm_skills_path /
|
|
816
|
+
source_path = self.bundled_pm_skills_path / skill_name / "SKILL.md"
|
|
643
817
|
|
|
644
818
|
skills.append(
|
|
645
819
|
PMSkillInfo(
|