claude-mpm 5.4.48__py3-none-any.whl → 5.6.34__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 +109 -1925
- 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 +216 -0
- claude_mpm/cli/commands/configure.py +620 -21
- claude_mpm/cli/commands/configure_agent_display.py +3 -1
- 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 +15 -8
- claude_mpm/cli/commands/profile.py +9 -10
- 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 +116 -0
- claude_mpm/cli/parsers/profile_parser.py +0 -1
- 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 +544 -511
- claude_mpm/cli/startup_display.py +74 -6
- claude_mpm/cli/startup_logging.py +2 -2
- 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 +146 -0
- claude_mpm/commander/chat/commands.py +96 -0
- claude_mpm/commander/chat/repl.py +310 -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 +332 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +146 -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 +450 -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 +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 +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 +361 -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 +1 -0
- claude_mpm/core/claude_runner.py +154 -2
- 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 +51 -3
- claude_mpm/core/interactive_session.py +12 -11
- 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/optimized_startup.py +3 -1
- claude_mpm/core/output_style_manager.py +66 -18
- claude_mpm/core/shared/config_loader.py +3 -1
- claude_mpm/core/socketio_pool.py +47 -15
- 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/1WZnGYqX.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
- 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/C3rbW_a-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → DR8nis88.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.RgBboRvH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
- 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 +11 -11
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/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__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +527 -136
- claude_mpm/hooks/claude_hooks/hook_handler.py +170 -104
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +206 -36
- 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/__pycache__/__init__.cpython-311.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__/container.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -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 +310 -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 +215 -2
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- claude_mpm/scripts/start_activity_logging.py +0 -0
- 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/agent_discovery_service.py +3 -1
- claude_mpm/services/agents/deployment/agent_format_converter.py +8 -6
- claude_mpm/services/agents/deployment/agent_template_builder.py +14 -4
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +4 -4
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +4 -1
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/git_source_manager.py +6 -2
- 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/sources/git_source_sync_service.py +10 -5
- 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/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/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +8 -3
- claude_mpm/services/monitor/server.py +106 -16
- claude_mpm/services/pm_skills_deployer.py +267 -94
- claude_mpm/services/profile_manager.py +10 -4
- claude_mpm/services/skills/git_skill_source_manager.py +192 -29
- claude_mpm/services/skills/selective_skill_deployer.py +211 -46
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +188 -67
- 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/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/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-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -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-pr-workflow/SKILL.md +124 -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/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-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +112 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +29 -23
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/utils/agent_dependency_loader.py +103 -4
- claude_mpm/utils/robust_installer.py +45 -24
- claude_mpm-5.6.34.dist-info/METADATA +393 -0
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/RECORD +453 -151
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- claude_mpm-5.4.48.dist-info/METADATA +0 -999
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.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/
|
|
@@ -36,7 +39,7 @@ References:
|
|
|
36
39
|
import hashlib
|
|
37
40
|
import shutil
|
|
38
41
|
from dataclasses import dataclass
|
|
39
|
-
from datetime import datetime
|
|
42
|
+
from datetime import datetime, timezone
|
|
40
43
|
from pathlib import Path
|
|
41
44
|
from typing import Any, Callable, Dict, List, Optional
|
|
42
45
|
|
|
@@ -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,15 +139,19 @@ 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
|
|
145
|
+
skill_count: Total number of deployed skills
|
|
101
146
|
"""
|
|
102
147
|
|
|
103
148
|
verified: bool
|
|
104
149
|
warnings: List[str]
|
|
105
150
|
missing_skills: List[str]
|
|
151
|
+
corrupted_skills: List[str]
|
|
106
152
|
outdated_skills: List[str]
|
|
107
153
|
message: str
|
|
154
|
+
skill_count: int = 0
|
|
108
155
|
|
|
109
156
|
|
|
110
157
|
@dataclass
|
|
@@ -128,8 +175,9 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
128
175
|
"""Deploy and manage PM skills from bundled sources to projects.
|
|
129
176
|
|
|
130
177
|
This service provides:
|
|
131
|
-
- Discovery of bundled PM skills (
|
|
132
|
-
- 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)
|
|
133
181
|
- Version tracking via pm_skills_registry.yaml
|
|
134
182
|
- Checksum validation for integrity
|
|
135
183
|
- Non-blocking verification (warnings only)
|
|
@@ -138,7 +186,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
138
186
|
Example:
|
|
139
187
|
>>> deployer = PMSkillsDeployerService()
|
|
140
188
|
>>> result = deployer.deploy_pm_skills(Path("/project/root"))
|
|
141
|
-
>>> print(f"Deployed {len(result.deployed)} skills")
|
|
189
|
+
>>> print(f"Deployed {len(result.deployed)} skills to .claude/skills/")
|
|
142
190
|
>>>
|
|
143
191
|
>>> verify_result = deployer.verify_pm_skills(Path("/project/root"))
|
|
144
192
|
>>> if not verify_result.verified:
|
|
@@ -171,7 +219,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
171
219
|
self.logger.debug(f"Using dev templates path: {alt_path}")
|
|
172
220
|
else:
|
|
173
221
|
self.logger.warning(
|
|
174
|
-
|
|
222
|
+
"PM skills templates path not found (non-critical, uses defaults)"
|
|
175
223
|
)
|
|
176
224
|
|
|
177
225
|
def _find_project_root(self) -> Path:
|
|
@@ -244,9 +292,9 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
244
292
|
project_dir: Project root directory
|
|
245
293
|
|
|
246
294
|
Returns:
|
|
247
|
-
Path to .claude
|
|
295
|
+
Path to .claude/skills/
|
|
248
296
|
"""
|
|
249
|
-
return project_dir / ".claude
|
|
297
|
+
return project_dir / ".claude" / "skills"
|
|
250
298
|
|
|
251
299
|
def _load_registry(self, project_dir: Path) -> Dict[str, Any]:
|
|
252
300
|
"""Load PM skills registry with security checks.
|
|
@@ -320,14 +368,12 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
320
368
|
def _discover_bundled_pm_skills(self) -> List[Dict[str, Any]]:
|
|
321
369
|
"""Discover all PM skills in bundled templates directory.
|
|
322
370
|
|
|
323
|
-
PM skills
|
|
324
|
-
1. Directory structure: pm-skill-name/SKILL.md (new format)
|
|
325
|
-
2. Flat files: skill-name.md (legacy format for .claude-mpm/templates/)
|
|
371
|
+
PM skills follow mpm-skill-name/SKILL.md structure.
|
|
326
372
|
|
|
327
373
|
Returns:
|
|
328
374
|
List of skill dictionaries containing:
|
|
329
|
-
- name: Skill name (directory
|
|
330
|
-
- 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)
|
|
331
377
|
- type: File type (always 'md')
|
|
332
378
|
"""
|
|
333
379
|
skills = []
|
|
@@ -338,11 +384,17 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
338
384
|
)
|
|
339
385
|
return skills
|
|
340
386
|
|
|
341
|
-
# Scan for skill directories containing SKILL.md
|
|
387
|
+
# Scan for skill directories containing SKILL.md
|
|
342
388
|
for skill_dir in self.bundled_pm_skills_path.iterdir():
|
|
343
389
|
if not skill_dir.is_dir() or skill_dir.name.startswith("."):
|
|
344
390
|
continue
|
|
345
391
|
|
|
392
|
+
# Only process mpm* skills (framework management)
|
|
393
|
+
# Note: Includes both 'mpm' (core skill) and 'mpm-*' (other PM skills)
|
|
394
|
+
if not skill_dir.name.startswith("mpm"):
|
|
395
|
+
self.logger.debug(f"Skipping non-mpm skill: {skill_dir.name}")
|
|
396
|
+
continue
|
|
397
|
+
|
|
346
398
|
skill_file = skill_dir / "SKILL.md"
|
|
347
399
|
if skill_file.exists():
|
|
348
400
|
skills.append(
|
|
@@ -353,46 +405,91 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
353
405
|
}
|
|
354
406
|
)
|
|
355
407
|
|
|
356
|
-
# Fallback: Scan for .md files directly (legacy format)
|
|
357
|
-
for skill_file in self.bundled_pm_skills_path.glob("*.md"):
|
|
358
|
-
if skill_file.name.startswith("."):
|
|
359
|
-
continue
|
|
360
|
-
|
|
361
|
-
skills.append(
|
|
362
|
-
{
|
|
363
|
-
"name": skill_file.stem,
|
|
364
|
-
"path": skill_file,
|
|
365
|
-
"type": "md",
|
|
366
|
-
}
|
|
367
|
-
)
|
|
368
|
-
|
|
369
408
|
self.logger.info(f"Discovered {len(skills)} bundled PM skills")
|
|
370
409
|
return skills
|
|
371
410
|
|
|
411
|
+
def _get_skills_for_tier(self, tier: str) -> List[str]:
|
|
412
|
+
"""Get list of skills to deploy based on tier.
|
|
413
|
+
|
|
414
|
+
Args:
|
|
415
|
+
tier: Deployment tier - "minimal", "standard", or "full"
|
|
416
|
+
|
|
417
|
+
Returns:
|
|
418
|
+
List of skill names to deploy
|
|
419
|
+
|
|
420
|
+
Raises:
|
|
421
|
+
ValueError: If tier is invalid
|
|
422
|
+
"""
|
|
423
|
+
if tier == "minimal":
|
|
424
|
+
return REQUIRED_PM_SKILLS
|
|
425
|
+
if tier == "standard":
|
|
426
|
+
return REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS
|
|
427
|
+
if tier == "full":
|
|
428
|
+
return REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS + OPTIONAL_PM_SKILLS
|
|
429
|
+
raise ValueError(
|
|
430
|
+
f"Invalid tier '{tier}'. Must be 'minimal', 'standard', or 'full'"
|
|
431
|
+
)
|
|
432
|
+
|
|
372
433
|
def deploy_pm_skills(
|
|
373
434
|
self,
|
|
374
435
|
project_dir: Path,
|
|
375
436
|
force: bool = False,
|
|
437
|
+
tier: str = "standard",
|
|
376
438
|
progress_callback: Optional[Callable[[str, int, int], None]] = None,
|
|
377
439
|
) -> DeploymentResult:
|
|
378
|
-
"""Deploy bundled PM skills to project directory.
|
|
440
|
+
"""Deploy bundled PM skills to project directory with tier-based selection.
|
|
379
441
|
|
|
380
|
-
Copies PM skills from bundled templates to .claude
|
|
442
|
+
Copies PM skills from bundled templates to .claude/skills/{name}/SKILL.md
|
|
381
443
|
and updates registry with version and checksum information.
|
|
382
444
|
|
|
445
|
+
Deployment Tiers:
|
|
446
|
+
- "minimal": Only REQUIRED_PM_SKILLS (Tier 1 - core functionality)
|
|
447
|
+
- "standard": REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS (Tier 1+2 - common workflows)
|
|
448
|
+
- "full": All skills (Tier 1+2+3 - advanced features)
|
|
449
|
+
|
|
450
|
+
Conflict Resolution:
|
|
451
|
+
- mpm-* skills from src WIN (overwrite existing)
|
|
452
|
+
- Non-mpm-* skills in .claude/skills/ are untouched
|
|
453
|
+
|
|
383
454
|
Args:
|
|
384
455
|
project_dir: Project root directory
|
|
385
456
|
force: If True, redeploy even if skill already exists
|
|
457
|
+
tier: Deployment tier - "minimal", "standard" (default), or "full"
|
|
386
458
|
progress_callback: Optional callback(skill_name, current, total) for progress
|
|
387
459
|
|
|
388
460
|
Returns:
|
|
389
461
|
DeploymentResult with deployment status and details
|
|
390
462
|
|
|
391
463
|
Example:
|
|
392
|
-
>>>
|
|
393
|
-
>>>
|
|
464
|
+
>>> # Standard deployment (Tier 1 + Tier 2)
|
|
465
|
+
>>> result = deployer.deploy_pm_skills(Path("/project"))
|
|
466
|
+
>>> print(f"Deployed: {len(result.deployed)} to .claude/skills/")
|
|
467
|
+
>>>
|
|
468
|
+
>>> # Minimal deployment (Tier 1 only)
|
|
469
|
+
>>> result = deployer.deploy_pm_skills(Path("/project"), tier="minimal")
|
|
470
|
+
>>>
|
|
471
|
+
>>> # Full deployment (all tiers)
|
|
472
|
+
>>> result = deployer.deploy_pm_skills(Path("/project"), tier="full")
|
|
394
473
|
"""
|
|
395
|
-
|
|
474
|
+
# Get tier-based skill filter
|
|
475
|
+
try:
|
|
476
|
+
tier_skills = self._get_skills_for_tier(tier)
|
|
477
|
+
except ValueError as e:
|
|
478
|
+
return DeploymentResult(
|
|
479
|
+
success=False,
|
|
480
|
+
deployed=[],
|
|
481
|
+
skipped=[],
|
|
482
|
+
errors=[{"skill": "all", "error": str(e)}],
|
|
483
|
+
message=str(e),
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
# Discover all bundled skills, then filter by tier
|
|
487
|
+
all_skills = self._discover_bundled_pm_skills()
|
|
488
|
+
skills = [s for s in all_skills if s["name"] in tier_skills]
|
|
489
|
+
|
|
490
|
+
self.logger.info(
|
|
491
|
+
f"Deploying {len(skills)}/{len(all_skills)} skills for tier '{tier}'"
|
|
492
|
+
)
|
|
396
493
|
deployed = []
|
|
397
494
|
skipped = []
|
|
398
495
|
errors = []
|
|
@@ -430,12 +527,10 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
430
527
|
deployed_skills = registry.get("skills", [])
|
|
431
528
|
|
|
432
529
|
# Create lookup for existing deployments
|
|
433
|
-
existing_deployments = {
|
|
434
|
-
skill["name"]: skill for skill in deployed_skills
|
|
435
|
-
}
|
|
530
|
+
existing_deployments = {skill["name"]: skill for skill in deployed_skills}
|
|
436
531
|
|
|
437
532
|
new_deployed_skills = []
|
|
438
|
-
timestamp = datetime.
|
|
533
|
+
timestamp = datetime.now(tz=timezone.utc).isoformat()
|
|
439
534
|
total_skills = len(skills)
|
|
440
535
|
|
|
441
536
|
for idx, skill in enumerate(skills):
|
|
@@ -447,8 +542,12 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
447
542
|
if progress_callback:
|
|
448
543
|
progress_callback(skill_name, idx + 1, total_skills)
|
|
449
544
|
|
|
450
|
-
#
|
|
451
|
-
|
|
545
|
+
# Create skill directory: .claude/skills/{skill_name}/
|
|
546
|
+
skill_dir = deployment_dir / skill_name
|
|
547
|
+
skill_dir.mkdir(parents=True, exist_ok=True)
|
|
548
|
+
|
|
549
|
+
# Target path: .claude/skills/{skill_name}/SKILL.md
|
|
550
|
+
target_path = skill_dir / "SKILL.md"
|
|
452
551
|
|
|
453
552
|
# SECURITY: Validate target path
|
|
454
553
|
if not self._validate_safe_path(deployment_dir, target_path):
|
|
@@ -468,7 +567,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
468
567
|
)
|
|
469
568
|
continue
|
|
470
569
|
|
|
471
|
-
# Deploy skill
|
|
570
|
+
# Deploy skill (overwrites if exists - mpm-* skills WIN)
|
|
472
571
|
shutil.copy2(source_path, target_path)
|
|
473
572
|
|
|
474
573
|
# Add to deployed list
|
|
@@ -506,7 +605,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
506
605
|
|
|
507
606
|
success = len(errors) == 0
|
|
508
607
|
message = (
|
|
509
|
-
f"Deployed {len(deployed)} skills, skipped {len(skipped)}, "
|
|
608
|
+
f"Deployed {len(deployed)} skills (tier: {tier}), skipped {len(skipped)}, "
|
|
510
609
|
f"{len(errors)} errors"
|
|
511
610
|
)
|
|
512
611
|
|
|
@@ -520,75 +619,107 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
520
619
|
message=message,
|
|
521
620
|
)
|
|
522
621
|
|
|
523
|
-
def verify_pm_skills(
|
|
524
|
-
|
|
622
|
+
def verify_pm_skills(
|
|
623
|
+
self, project_dir: Path, auto_repair: bool = True
|
|
624
|
+
) -> VerificationResult:
|
|
625
|
+
"""Verify PM skills are properly deployed with enhanced validation.
|
|
525
626
|
|
|
526
|
-
Checks
|
|
527
|
-
|
|
627
|
+
Checks ALL required PM skills for:
|
|
628
|
+
- Existence in deployment directory
|
|
629
|
+
- File integrity (non-empty, valid checksums)
|
|
630
|
+
- Version currency (compared to bundled source)
|
|
631
|
+
|
|
632
|
+
Auto-repair logic:
|
|
633
|
+
- If auto_repair=True (default), automatically deploys missing/corrupted skills
|
|
634
|
+
- Reports what was fixed in the result
|
|
528
635
|
|
|
529
636
|
Args:
|
|
530
637
|
project_dir: Project root directory
|
|
638
|
+
auto_repair: If True, auto-deploy missing/corrupted skills (default: True)
|
|
531
639
|
|
|
532
640
|
Returns:
|
|
533
|
-
VerificationResult with verification status
|
|
641
|
+
VerificationResult with detailed verification status:
|
|
642
|
+
- verified: True if all required skills are deployed and valid
|
|
643
|
+
- missing_skills: List of required skills not deployed
|
|
644
|
+
- corrupted_skills: List of skills with checksum mismatches
|
|
645
|
+
- warnings: List of warning messages
|
|
646
|
+
- skill_count: Total number of deployed skills
|
|
534
647
|
|
|
535
648
|
Example:
|
|
536
649
|
>>> result = deployer.verify_pm_skills(Path("/project"))
|
|
537
650
|
>>> if not result.verified:
|
|
538
|
-
...
|
|
539
|
-
...
|
|
651
|
+
... print(f"Missing: {result.missing_skills}")
|
|
652
|
+
... print(f"Corrupted: {result.corrupted_skills}")
|
|
540
653
|
"""
|
|
541
654
|
warnings = []
|
|
542
655
|
missing_skills = []
|
|
656
|
+
corrupted_skills = []
|
|
543
657
|
outdated_skills = []
|
|
544
658
|
|
|
545
659
|
# Check if registry exists
|
|
546
660
|
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
|
-
)
|
|
557
|
-
|
|
558
|
-
# Check each registered skill exists
|
|
559
661
|
deployment_dir = self._get_deployment_dir(project_dir)
|
|
560
|
-
|
|
662
|
+
deployed_skills_data = registry.get("skills", []) if registry else []
|
|
561
663
|
|
|
562
|
-
for
|
|
563
|
-
|
|
564
|
-
skill_file = deployment_dir / f"{skill_name}.md"
|
|
664
|
+
# Build lookup for deployed skills
|
|
665
|
+
deployed_lookup = {skill["name"]: skill for skill in deployed_skills_data}
|
|
565
666
|
|
|
667
|
+
# Check ALL required PM skills
|
|
668
|
+
for required_skill in REQUIRED_PM_SKILLS:
|
|
669
|
+
# Check if skill is in registry
|
|
670
|
+
if required_skill not in deployed_lookup:
|
|
671
|
+
warnings.append(f"Required PM skill missing: {required_skill}")
|
|
672
|
+
missing_skills.append(required_skill)
|
|
673
|
+
continue
|
|
674
|
+
|
|
675
|
+
# Check if skill file exists
|
|
676
|
+
skill_file = deployment_dir / required_skill / "SKILL.md"
|
|
566
677
|
if not skill_file.exists():
|
|
567
|
-
warnings.append(
|
|
568
|
-
|
|
678
|
+
warnings.append(
|
|
679
|
+
f"Required PM skill file missing: {required_skill}/SKILL.md"
|
|
680
|
+
)
|
|
681
|
+
missing_skills.append(required_skill)
|
|
682
|
+
continue
|
|
683
|
+
|
|
684
|
+
# Check if skill file is empty/corrupted
|
|
685
|
+
try:
|
|
686
|
+
file_size = skill_file.stat().st_size
|
|
687
|
+
if file_size == 0:
|
|
688
|
+
warnings.append(
|
|
689
|
+
f"Required PM skill file is empty: {required_skill}/SKILL.md"
|
|
690
|
+
)
|
|
691
|
+
corrupted_skills.append(required_skill)
|
|
692
|
+
continue
|
|
693
|
+
except OSError as e:
|
|
694
|
+
warnings.append(
|
|
695
|
+
f"Cannot read required PM skill file: {required_skill}/SKILL.md - {e}"
|
|
696
|
+
)
|
|
697
|
+
corrupted_skills.append(required_skill)
|
|
569
698
|
continue
|
|
570
699
|
|
|
571
700
|
# Verify checksum
|
|
701
|
+
deployed_skill = deployed_lookup[required_skill]
|
|
572
702
|
current_checksum = self._compute_checksum(skill_file)
|
|
573
|
-
expected_checksum =
|
|
703
|
+
expected_checksum = deployed_skill.get("checksum", "")
|
|
574
704
|
|
|
575
705
|
if current_checksum != expected_checksum:
|
|
576
706
|
warnings.append(
|
|
577
|
-
f"
|
|
707
|
+
f"Required PM skill checksum mismatch: {required_skill} (file may be corrupted)"
|
|
578
708
|
)
|
|
579
|
-
|
|
709
|
+
corrupted_skills.append(required_skill)
|
|
580
710
|
|
|
581
|
-
# Check for available updates
|
|
711
|
+
# Check for available updates (bundled skills newer than deployed)
|
|
582
712
|
bundled_skills = {s["name"]: s for s in self._discover_bundled_pm_skills()}
|
|
583
713
|
for skill_name, bundled_skill in bundled_skills.items():
|
|
714
|
+
# Skip non-required skills
|
|
715
|
+
if skill_name not in REQUIRED_PM_SKILLS:
|
|
716
|
+
continue
|
|
717
|
+
|
|
584
718
|
# Find corresponding deployed skill
|
|
585
|
-
deployed_skill =
|
|
586
|
-
(s for s in deployed_skills if s["name"] == skill_name), None
|
|
587
|
-
)
|
|
719
|
+
deployed_skill = deployed_lookup.get(skill_name)
|
|
588
720
|
|
|
589
721
|
if not deployed_skill:
|
|
590
|
-
|
|
591
|
-
missing_skills.append(skill_name)
|
|
722
|
+
# Already tracked as missing
|
|
592
723
|
continue
|
|
593
724
|
|
|
594
725
|
# Check if checksums differ
|
|
@@ -596,22 +727,66 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
596
727
|
deployed_checksum = deployed_skill.get("checksum", "")
|
|
597
728
|
|
|
598
729
|
if bundled_checksum != deployed_checksum:
|
|
599
|
-
|
|
600
|
-
|
|
730
|
+
# Don't add to outdated_skills if already in corrupted_skills
|
|
731
|
+
if skill_name not in corrupted_skills:
|
|
732
|
+
warnings.append(f"PM skill update available: {skill_name}")
|
|
733
|
+
outdated_skills.append(skill_name)
|
|
734
|
+
|
|
735
|
+
# Auto-repair if enabled and issues found
|
|
736
|
+
repaired_skills = []
|
|
737
|
+
if auto_repair and (missing_skills or corrupted_skills):
|
|
738
|
+
self.logger.info(
|
|
739
|
+
f"Auto-repairing PM skills: {len(missing_skills)} missing, "
|
|
740
|
+
f"{len(corrupted_skills)} corrupted"
|
|
741
|
+
)
|
|
742
|
+
|
|
743
|
+
# Deploy missing and corrupted skills
|
|
744
|
+
repair_result = self.deploy_pm_skills(project_dir, force=True)
|
|
601
745
|
|
|
602
|
-
|
|
746
|
+
if repair_result.success:
|
|
747
|
+
repaired_skills = repair_result.deployed
|
|
748
|
+
self.logger.info(f"Auto-repaired {len(repaired_skills)} PM skills")
|
|
603
749
|
|
|
750
|
+
# Remove repaired skills from missing/corrupted lists
|
|
751
|
+
missing_skills = [s for s in missing_skills if s not in repaired_skills]
|
|
752
|
+
corrupted_skills = [
|
|
753
|
+
s for s in corrupted_skills if s not in repaired_skills
|
|
754
|
+
]
|
|
755
|
+
|
|
756
|
+
# Update warnings
|
|
757
|
+
if repaired_skills:
|
|
758
|
+
warnings.append(
|
|
759
|
+
f"Auto-repaired {len(repaired_skills)} PM skills: {', '.join(repaired_skills)}"
|
|
760
|
+
)
|
|
761
|
+
else:
|
|
762
|
+
warnings.append(
|
|
763
|
+
f"Auto-repair failed: {len(repair_result.errors)} errors"
|
|
764
|
+
)
|
|
765
|
+
self.logger.error(
|
|
766
|
+
f"Auto-repair failed with errors: {repair_result.errors}"
|
|
767
|
+
)
|
|
768
|
+
|
|
769
|
+
# Determine verification status
|
|
770
|
+
verified = len(missing_skills) == 0 and len(corrupted_skills) == 0
|
|
771
|
+
|
|
772
|
+
# Build message
|
|
604
773
|
if verified:
|
|
605
|
-
|
|
774
|
+
if repaired_skills:
|
|
775
|
+
message = f"All PM skills verified (auto-repaired {len(repaired_skills)} skills)"
|
|
776
|
+
else:
|
|
777
|
+
message = "All PM skills verified and up-to-date"
|
|
606
778
|
else:
|
|
607
|
-
|
|
779
|
+
issue_count = len(missing_skills) + len(corrupted_skills)
|
|
780
|
+
message = f"{issue_count} PM skill issues found"
|
|
608
781
|
|
|
609
782
|
return VerificationResult(
|
|
610
783
|
verified=verified,
|
|
611
784
|
warnings=warnings,
|
|
612
785
|
missing_skills=missing_skills,
|
|
786
|
+
corrupted_skills=corrupted_skills,
|
|
613
787
|
outdated_skills=outdated_skills,
|
|
614
788
|
message=message,
|
|
789
|
+
skill_count=len(deployed_skills_data),
|
|
615
790
|
)
|
|
616
791
|
|
|
617
792
|
def get_deployed_skills(self, project_dir: Path) -> List[PMSkillInfo]:
|
|
@@ -634,10 +809,10 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
634
809
|
skills = []
|
|
635
810
|
for skill_data in registry.get("skills", []):
|
|
636
811
|
skill_name = skill_data["name"]
|
|
637
|
-
deployed_path = deployment_dir /
|
|
812
|
+
deployed_path = deployment_dir / skill_name / "SKILL.md"
|
|
638
813
|
|
|
639
814
|
# Find source path (may not exist if bundled skills changed)
|
|
640
|
-
source_path = self.bundled_pm_skills_path /
|
|
815
|
+
source_path = self.bundled_pm_skills_path / skill_name / "SKILL.md"
|
|
641
816
|
|
|
642
817
|
skills.append(
|
|
643
818
|
PMSkillInfo(
|
|
@@ -669,9 +844,7 @@ class PMSkillsDeployerService(LoggerMixin):
|
|
|
669
844
|
... print(f"{update.skill_name}: {update.current_version} -> {update.new_version}")
|
|
670
845
|
"""
|
|
671
846
|
registry = self._load_registry(project_dir)
|
|
672
|
-
deployed_skills = {
|
|
673
|
-
skill["name"]: skill for skill in registry.get("skills", [])
|
|
674
|
-
}
|
|
847
|
+
deployed_skills = {skill["name"]: skill for skill in registry.get("skills", [])}
|
|
675
848
|
|
|
676
849
|
bundled_skills = self._discover_bundled_pm_skills()
|
|
677
850
|
|
|
@@ -49,7 +49,7 @@ Usage:
|
|
|
49
49
|
|
|
50
50
|
import fnmatch
|
|
51
51
|
from pathlib import Path
|
|
52
|
-
from typing import
|
|
52
|
+
from typing import Any, Dict, Optional, Set
|
|
53
53
|
|
|
54
54
|
import yaml
|
|
55
55
|
|
|
@@ -69,7 +69,9 @@ class ProfileManager:
|
|
|
69
69
|
- Get lists of enabled/disabled entities
|
|
70
70
|
"""
|
|
71
71
|
|
|
72
|
-
def __init__(
|
|
72
|
+
def __init__(
|
|
73
|
+
self, project_dir: Optional[Path] = None, profiles_dir: Optional[Path] = None
|
|
74
|
+
):
|
|
73
75
|
"""
|
|
74
76
|
Initialize ProfileManager.
|
|
75
77
|
|
|
@@ -212,7 +214,9 @@ class ProfileManager:
|
|
|
212
214
|
# Check if skill is explicitly disabled by pattern
|
|
213
215
|
for pattern in self._disabled_skill_patterns:
|
|
214
216
|
if fnmatch.fnmatch(skill_name, pattern):
|
|
215
|
-
logger.debug(
|
|
217
|
+
logger.debug(
|
|
218
|
+
f"Skill '{skill_name}' matched disabled pattern '{pattern}'"
|
|
219
|
+
)
|
|
216
220
|
return False
|
|
217
221
|
|
|
218
222
|
# If enabled list exists, check for match
|
|
@@ -227,7 +231,9 @@ class ProfileManager:
|
|
|
227
231
|
if skill_name.endswith(f"-{short_name}"):
|
|
228
232
|
return True
|
|
229
233
|
# Also check if short name is contained as a segment
|
|
230
|
-
if f"-{short_name}-" in skill_name or skill_name.startswith(
|
|
234
|
+
if f"-{short_name}-" in skill_name or skill_name.startswith(
|
|
235
|
+
f"{short_name}-"
|
|
236
|
+
):
|
|
231
237
|
return True
|
|
232
238
|
|
|
233
239
|
return False
|