claude-mpm 5.0.9__py3-none-any.whl → 5.6.23__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/__init__.py +4 -0
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +115 -0
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +186 -0
- claude_mpm/agents/MEMORY.md +1 -1
- claude_mpm/agents/PM_INSTRUCTIONS.md +479 -616
- claude_mpm/agents/WORKFLOW.md +6 -253
- claude_mpm/agents/agent_loader.py +13 -44
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/frontmatter_validator.py +70 -2
- claude_mpm/agents/templates/circuit-breakers.md +457 -62
- claude_mpm/cli/__init__.py +5 -2
- claude_mpm/cli/__main__.py +4 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/agent_state_manager.py +18 -27
- claude_mpm/cli/commands/agents.py +177 -41
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/auto_configure.py +723 -236
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/config.py +88 -2
- claude_mpm/cli/commands/configure.py +1874 -170
- claude_mpm/cli/commands/configure_agent_display.py +27 -6
- 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 +232 -46
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
- claude_mpm/cli/commands/postmortem.py +1 -1
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +379 -204
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/executor.py +141 -19
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +115 -60
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/agents_parser.py +54 -9
- claude_mpm/cli/parsers/auto_configure_parser.py +13 -138
- claude_mpm/cli/parsers/base_parser.py +88 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/config_parser.py +153 -83
- claude_mpm/cli/parsers/profile_parser.py +147 -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 +1 -1
- claude_mpm/cli/startup.py +1017 -266
- 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 +36 -0
- claude_mpm/commands/mpm-doctor.md +16 -21
- claude_mpm/commands/mpm-help.md +12 -286
- claude_mpm/commands/mpm-init.md +88 -506
- claude_mpm/commands/mpm-monitor.md +22 -401
- claude_mpm/commands/mpm-organize.md +128 -0
- claude_mpm/commands/mpm-postmortem.md +13 -107
- claude_mpm/commands/mpm-session-resume.md +20 -363
- claude_mpm/commands/mpm-status.md +13 -69
- claude_mpm/commands/mpm-ticket-view.md +60 -495
- claude_mpm/commands/mpm-version.md +13 -107
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/config/agent_sources.py +27 -0
- 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 +37 -26
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/framework/formatters/content_formatter.py +3 -13
- claude_mpm/core/framework/loaders/agent_loader.py +8 -5
- claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
- claude_mpm/core/framework_loader.py +4 -2
- claude_mpm/core/hook_manager.py +51 -3
- claude_mpm/core/interactive_session.py +12 -11
- claude_mpm/core/logger.py +39 -9
- claude_mpm/core/logging_utils.py +35 -11
- claude_mpm/core/network_config.py +148 -0
- claude_mpm/core/oneshot_session.py +7 -6
- claude_mpm/core/optimized_startup.py +61 -0
- claude_mpm/core/output_style_manager.py +219 -44
- claude_mpm/core/shared/config_loader.py +3 -1
- claude_mpm/core/socketio_pool.py +16 -8
- claude_mpm/core/unified_agent_registry.py +134 -16
- claude_mpm/core/unified_config.py +76 -8
- claude_mpm/core/unified_paths.py +95 -90
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- 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/BSNlmTZj.js +1 -0
- 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/DR8nis88.js +2 -0
- 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/NqQ1dWOy.js +1 -0
- 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.RgBboRvH.js +1 -0
- 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 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- 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__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/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/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +479 -128
- claude_mpm/hooks/claude_hooks/hook_handler.py +254 -83
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +149 -18
- claude_mpm/hooks/claude_hooks/memory_integration.py +67 -19
- claude_mpm/hooks/claude_hooks/response_tracking.py +44 -62
- 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__/duplicate_detector.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 +69 -30
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +36 -103
- claude_mpm/hooks/claude_hooks/services/state_manager.py +23 -36
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +73 -75
- claude_mpm/hooks/kuzu_memory_hook.py +5 -5
- claude_mpm/hooks/memory_integration_hook.py +46 -1
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_template.py +10 -2
- claude_mpm/init.py +276 -19
- claude_mpm/models/agent_definition.py +7 -0
- claude_mpm/models/git_repository.py +3 -3
- claude_mpm/scripts/claude-hook-handler.sh +87 -20
- claude_mpm/scripts/launch_monitor.py +93 -13
- claude_mpm/scripts/start_activity_logging.py +0 -0
- claude_mpm/services/agents/agent_builder.py +3 -3
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/cache_git_manager.py +7 -7
- claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
- claude_mpm/services/agents/deployment/agent_discovery_service.py +6 -5
- claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
- claude_mpm/services/agents/deployment/agent_template_builder.py +42 -20
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
- claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +348 -29
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +570 -68
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/git_source_manager.py +57 -4
- claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/recommender.py +5 -3
- claude_mpm/services/agents/single_tier_deployment_service.py +6 -6
- claude_mpm/services/agents/sources/git_source_sync_service.py +129 -11
- claude_mpm/services/agents/startup_sync.py +27 -4
- claude_mpm/services/agents/toolchain_detector.py +10 -6
- claude_mpm/services/analysis/__init__.py +11 -1
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- 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 +81 -10
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +31 -1
- 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_bus/config.py +3 -1
- claude_mpm/services/event_log.py +325 -0
- claude_mpm/services/git/git_operations_service.py +101 -16
- 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.py +9 -2
- claude_mpm/services/monitor/daemon_manager.py +54 -7
- claude_mpm/services/monitor/management/lifecycle.py +15 -3
- claude_mpm/services/monitor/server.py +796 -30
- claude_mpm/services/pm_skills_deployer.py +884 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/project/project_organizer.py +4 -0
- claude_mpm/services/self_upgrade_service.py +120 -12
- claude_mpm/services/skills/__init__.py +3 -0
- claude_mpm/services/skills/git_skill_source_manager.py +303 -12
- claude_mpm/services/skills/selective_skill_deployer.py +869 -0
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_deployer.py +294 -55
- claude_mpm/services/socketio/dashboard_server.py +1 -0
- claude_mpm/services/socketio/event_normalizer.py +51 -6
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/core.py +386 -108
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/services/version_control/git_operations.py +103 -0
- 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 +98 -3
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/utils/agent_dependency_loader.py +115 -4
- claude_mpm/utils/agent_filters.py +17 -44
- claude_mpm/utils/gitignore.py +3 -0
- claude_mpm/utils/migration.py +4 -4
- claude_mpm/utils/robust_installer.py +86 -21
- claude_mpm-5.6.23.dist-info/METADATA +393 -0
- {claude_mpm-5.0.9.dist-info → claude_mpm-5.6.23.dist-info}/RECORD +508 -261
- claude_mpm-5.6.23.dist-info/entry_points.txt +5 -0
- claude_mpm-5.6.23.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.6.23.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
- claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
- claude_mpm/agents/BASE_OPS.md +0 -219
- claude_mpm/agents/BASE_PM.md +0 -480
- claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
- claude_mpm/agents/BASE_QA.md +0 -167
- claude_mpm/agents/BASE_RESEARCH.md +0 -53
- claude_mpm/agents/OUTPUT_STYLE.md +0 -290
- claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +0 -1322
- claude_mpm/agents/base_agent_loader.py +0 -601
- claude_mpm/cli/commands/agents_detect.py +0 -380
- claude_mpm/cli/commands/agents_recommend.py +0 -309
- claude_mpm/cli/ticket_cli.py +0 -35
- claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
- claude_mpm/commands/mpm-agents-detect.md +0 -177
- claude_mpm/commands/mpm-agents-list.md +0 -131
- claude_mpm/commands/mpm-agents-recommend.md +0 -223
- claude_mpm/commands/mpm-config-view.md +0 -150
- claude_mpm/commands/mpm-ticket-organize.md +0 -304
- claude_mpm/dashboard/analysis_runner.py +0 -455
- claude_mpm/dashboard/index.html +0 -13
- claude_mpm/dashboard/open_dashboard.py +0 -66
- claude_mpm/dashboard/static/css/activity.css +0 -1958
- claude_mpm/dashboard/static/css/connection-status.css +0 -370
- claude_mpm/dashboard/static/css/dashboard.css +0 -4701
- claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
- claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
- claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
- claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
- claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
- claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
- claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
- claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
- claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
- claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
- claude_mpm/dashboard/static/js/connection-manager.js +0 -536
- claude_mpm/dashboard/static/js/dashboard.js +0 -1914
- claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/js/socket-client.js +0 -1474
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/socket.io.min.js +0 -7
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
- claude_mpm/dashboard/templates/code_simple.html +0 -153
- claude_mpm/dashboard/templates/index.html +0 -606
- claude_mpm/dashboard/test_dashboard.html +0 -372
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
- claude_mpm/scripts/mcp_server.py +0 -75
- claude_mpm/scripts/mcp_wrapper.py +0 -39
- claude_mpm/services/mcp_gateway/__init__.py +0 -159
- claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
- claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
- claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
- claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
- claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
- claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
- claude_mpm/services/mcp_gateway/core/base.py +0 -312
- claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
- claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
- claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
- claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
- claude_mpm/services/mcp_gateway/main.py +0 -589
- claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
- claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
- claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
- claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
- claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
- claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
- claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
- claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
- claude_mpm-5.0.9.dist-info/METADATA +0 -1028
- claude_mpm-5.0.9.dist-info/entry_points.txt +0 -10
- claude_mpm-5.0.9.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-5.0.9.dist-info → claude_mpm-5.6.23.dist-info}/WHEEL +0 -0
- {claude_mpm-5.0.9.dist-info → claude_mpm-5.6.23.dist-info}/top_level.txt +0 -0
|
@@ -28,7 +28,7 @@ References:
|
|
|
28
28
|
import json
|
|
29
29
|
import platform
|
|
30
30
|
import shutil
|
|
31
|
-
import subprocess
|
|
31
|
+
import subprocess # nosec B404 - subprocess needed for safe git operations
|
|
32
32
|
from pathlib import Path
|
|
33
33
|
from typing import Any, Dict, List, Optional
|
|
34
34
|
|
|
@@ -82,6 +82,8 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
82
82
|
toolchain: Optional[List[str]] = None,
|
|
83
83
|
categories: Optional[List[str]] = None,
|
|
84
84
|
force: bool = False,
|
|
85
|
+
selective: bool = True,
|
|
86
|
+
project_root: Optional[Path] = None,
|
|
85
87
|
) -> Dict:
|
|
86
88
|
"""Deploy skills from GitHub repository.
|
|
87
89
|
|
|
@@ -89,14 +91,17 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
89
91
|
1. Downloads skills from GitHub collection
|
|
90
92
|
2. Parses manifest for metadata
|
|
91
93
|
3. Filters by toolchain and categories
|
|
92
|
-
4.
|
|
93
|
-
5.
|
|
94
|
+
4. (If selective=True) Filters to only agent-referenced skills
|
|
95
|
+
5. Deploys to ~/.claude/skills/
|
|
96
|
+
6. Warns about Claude Code restart
|
|
94
97
|
|
|
95
98
|
Args:
|
|
96
99
|
collection: Collection name to deploy from (default: uses default collection)
|
|
97
100
|
toolchain: Filter by toolchain (e.g., ['python', 'javascript'])
|
|
98
101
|
categories: Filter by categories (e.g., ['testing', 'debugging'])
|
|
99
102
|
force: Overwrite existing skills
|
|
103
|
+
selective: If True, only deploy skills referenced by agents (default)
|
|
104
|
+
project_root: Project root directory (for finding agents, auto-detected if None)
|
|
100
105
|
|
|
101
106
|
Returns:
|
|
102
107
|
Dict containing:
|
|
@@ -107,10 +112,14 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
107
112
|
- restart_required: True if Claude Code needs restart
|
|
108
113
|
- restart_instructions: Message about restarting
|
|
109
114
|
- collection: Collection name used for deployment
|
|
115
|
+
- selective_mode: True if selective deployment was used
|
|
116
|
+
- total_available: Total skills available before filtering
|
|
110
117
|
|
|
111
118
|
Example:
|
|
112
119
|
>>> result = deployer.deploy_skills(collection="obra-superpowers")
|
|
113
120
|
>>> result = deployer.deploy_skills(toolchain=['python']) # Uses default
|
|
121
|
+
>>> # Deploy all skills (not just agent-referenced)
|
|
122
|
+
>>> result = deployer.deploy_skills(selective=False)
|
|
114
123
|
>>> if result['restart_required']:
|
|
115
124
|
>>> print(result['restart_instructions'])
|
|
116
125
|
"""
|
|
@@ -152,7 +161,7 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
152
161
|
|
|
153
162
|
self.logger.info(f"Found {len(skills)} skills in repository")
|
|
154
163
|
|
|
155
|
-
# Step 3: Filter skills
|
|
164
|
+
# Step 3: Filter skills by toolchain and categories
|
|
156
165
|
filtered_skills = self._filter_skills(skills, toolchain, categories)
|
|
157
166
|
|
|
158
167
|
self.logger.info(
|
|
@@ -160,11 +169,124 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
160
169
|
f" (toolchain={toolchain}, categories={categories})"
|
|
161
170
|
)
|
|
162
171
|
|
|
172
|
+
# Step 3.5: Apply selective filtering (only agent-referenced skills)
|
|
173
|
+
total_available = len(filtered_skills)
|
|
174
|
+
if selective:
|
|
175
|
+
# Auto-detect project root if not provided
|
|
176
|
+
if project_root is None:
|
|
177
|
+
# Try to find project root by looking for .claude-mpm directory
|
|
178
|
+
# Start from current directory and walk up
|
|
179
|
+
current = Path.cwd()
|
|
180
|
+
while current != current.parent:
|
|
181
|
+
if (current / ".claude-mpm").exists():
|
|
182
|
+
project_root = current
|
|
183
|
+
break
|
|
184
|
+
current = current.parent
|
|
185
|
+
|
|
186
|
+
# Read skills from configuration.yaml instead of agent frontmatter
|
|
187
|
+
if project_root:
|
|
188
|
+
config_path = Path(project_root) / ".claude-mpm" / "configuration.yaml"
|
|
189
|
+
else:
|
|
190
|
+
# Fallback to current directory's configuration
|
|
191
|
+
config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
|
|
192
|
+
|
|
193
|
+
from claude_mpm.services.skills.selective_skill_deployer import (
|
|
194
|
+
get_required_skills_from_agents,
|
|
195
|
+
get_skills_to_deploy,
|
|
196
|
+
save_agent_skills_to_config,
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
# Check if agent_referenced is empty and needs to be populated
|
|
200
|
+
required_skill_names, source = get_skills_to_deploy(config_path)
|
|
201
|
+
|
|
202
|
+
if not required_skill_names and project_root:
|
|
203
|
+
# agent_referenced is empty, scan deployed agents to populate it
|
|
204
|
+
agents_dir = Path(project_root) / ".claude" / "agents"
|
|
205
|
+
if agents_dir.exists():
|
|
206
|
+
self.logger.info(
|
|
207
|
+
"agent_referenced is empty in configuration.yaml, scanning deployed agents..."
|
|
208
|
+
)
|
|
209
|
+
agent_skills = get_required_skills_from_agents(agents_dir)
|
|
210
|
+
if agent_skills:
|
|
211
|
+
save_agent_skills_to_config(list(agent_skills), config_path)
|
|
212
|
+
self.logger.info(
|
|
213
|
+
f"Populated agent_referenced with {len(agent_skills)} skills from deployed agents"
|
|
214
|
+
)
|
|
215
|
+
# Re-read configuration after update
|
|
216
|
+
required_skill_names, source = get_skills_to_deploy(config_path)
|
|
217
|
+
else:
|
|
218
|
+
self.logger.warning(
|
|
219
|
+
"No skills found in deployed agents - configuration.yaml remains empty"
|
|
220
|
+
)
|
|
221
|
+
else:
|
|
222
|
+
self.logger.warning(
|
|
223
|
+
f"Agents directory not found at {agents_dir} - cannot scan for skills"
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
if required_skill_names:
|
|
227
|
+
# Convert required_skill_names to a set for O(1) lookup
|
|
228
|
+
required_set = set(required_skill_names)
|
|
229
|
+
|
|
230
|
+
# Filter to only required skills
|
|
231
|
+
# Match on: 'name', 'skill_id', or normalized 'source_path'
|
|
232
|
+
# source_path example: "universal/web/api-design-patterns/SKILL.md"
|
|
233
|
+
# normalized: "universal-web-api-design-patterns"
|
|
234
|
+
def skill_matches_requirement(skill):
|
|
235
|
+
# Check basic name and skill_id
|
|
236
|
+
if skill.get("name") in required_set:
|
|
237
|
+
return True
|
|
238
|
+
if skill.get("skill_id") in required_set:
|
|
239
|
+
return True
|
|
240
|
+
|
|
241
|
+
# Check normalized source_path
|
|
242
|
+
source_path = skill.get("source_path", "")
|
|
243
|
+
if source_path:
|
|
244
|
+
# Remove /SKILL.md suffix and replace / with -
|
|
245
|
+
normalized = source_path.replace("/SKILL.md", "").replace(
|
|
246
|
+
"/", "-"
|
|
247
|
+
)
|
|
248
|
+
if normalized in required_set:
|
|
249
|
+
return True
|
|
250
|
+
|
|
251
|
+
return False
|
|
252
|
+
|
|
253
|
+
filtered_skills = [
|
|
254
|
+
s for s in filtered_skills if skill_matches_requirement(s)
|
|
255
|
+
]
|
|
256
|
+
|
|
257
|
+
self.logger.info(
|
|
258
|
+
f"Selective deployment: {len(filtered_skills)}/{total_available} skills "
|
|
259
|
+
f"(source: {source})"
|
|
260
|
+
)
|
|
261
|
+
else:
|
|
262
|
+
self.logger.warning(
|
|
263
|
+
f"No skills found in configuration at {config_path}. "
|
|
264
|
+
f"Deploying all {total_available} skills."
|
|
265
|
+
)
|
|
266
|
+
else:
|
|
267
|
+
self.logger.info(
|
|
268
|
+
f"Selective mode disabled: deploying all {total_available} skills"
|
|
269
|
+
)
|
|
270
|
+
|
|
163
271
|
# Step 4: Deploy skills
|
|
164
272
|
deployed = []
|
|
165
273
|
skipped = []
|
|
166
274
|
errors = []
|
|
167
275
|
|
|
276
|
+
# Extract normalized skill names for cleanup (needed regardless of deployment outcome)
|
|
277
|
+
# Must match the names used during deployment (normalized from source_path)
|
|
278
|
+
filtered_skills_names = []
|
|
279
|
+
for skill in filtered_skills:
|
|
280
|
+
if isinstance(skill, dict) and "name" in skill:
|
|
281
|
+
source_path = skill.get("source_path", "")
|
|
282
|
+
if source_path:
|
|
283
|
+
# Normalize: "universal/web/api-design-patterns/SKILL.md" -> "universal-web-api-design-patterns"
|
|
284
|
+
normalized = source_path.replace("/SKILL.md", "").replace("/", "-")
|
|
285
|
+
filtered_skills_names.append(normalized)
|
|
286
|
+
else:
|
|
287
|
+
# Fallback to skill name
|
|
288
|
+
filtered_skills_names.append(skill["name"])
|
|
289
|
+
|
|
168
290
|
for skill in filtered_skills:
|
|
169
291
|
try:
|
|
170
292
|
# Validate skill is a dictionary
|
|
@@ -173,11 +295,29 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
173
295
|
errors.append(f"Invalid skill format: {skill}")
|
|
174
296
|
continue
|
|
175
297
|
|
|
176
|
-
result = self._deploy_skill(
|
|
298
|
+
result = self._deploy_skill(
|
|
299
|
+
skill, skills_data["temp_dir"], collection_name, force=force
|
|
300
|
+
)
|
|
177
301
|
if result["deployed"]:
|
|
178
|
-
|
|
302
|
+
# Use normalized name for reporting
|
|
303
|
+
source_path = skill.get("source_path", "")
|
|
304
|
+
if source_path:
|
|
305
|
+
normalized = source_path.replace("/SKILL.md", "").replace(
|
|
306
|
+
"/", "-"
|
|
307
|
+
)
|
|
308
|
+
deployed.append(normalized)
|
|
309
|
+
else:
|
|
310
|
+
deployed.append(skill["name"])
|
|
179
311
|
elif result["skipped"]:
|
|
180
|
-
|
|
312
|
+
# Use normalized name for reporting
|
|
313
|
+
source_path = skill.get("source_path", "")
|
|
314
|
+
if source_path:
|
|
315
|
+
normalized = source_path.replace("/SKILL.md", "").replace(
|
|
316
|
+
"/", "-"
|
|
317
|
+
)
|
|
318
|
+
skipped.append(normalized)
|
|
319
|
+
else:
|
|
320
|
+
skipped.append(skill["name"])
|
|
181
321
|
if result["error"]:
|
|
182
322
|
errors.append(result["error"])
|
|
183
323
|
except Exception as e:
|
|
@@ -189,10 +329,34 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
189
329
|
self.logger.error(f"Failed to deploy {skill_name}: {e}")
|
|
190
330
|
errors.append(f"{skill_name}: {e}")
|
|
191
331
|
|
|
192
|
-
# Step 5: Cleanup
|
|
332
|
+
# Step 5: Cleanup orphaned skills (always run in selective mode)
|
|
333
|
+
cleanup_result = {"removed_count": 0, "removed_skills": []}
|
|
334
|
+
if selective:
|
|
335
|
+
# Get the set of skills that should remain deployed
|
|
336
|
+
# This is the union of what we just deployed and what was already there
|
|
337
|
+
try:
|
|
338
|
+
from claude_mpm.services.skills.selective_skill_deployer import (
|
|
339
|
+
cleanup_orphan_skills,
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Cleanup orphaned skills not referenced by agents
|
|
343
|
+
# This runs even if nothing new was deployed to remove stale skills
|
|
344
|
+
cleanup_result = cleanup_orphan_skills(
|
|
345
|
+
self.CLAUDE_SKILLS_DIR, set(filtered_skills_names)
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
if cleanup_result["removed_count"] > 0:
|
|
349
|
+
self.logger.info(
|
|
350
|
+
f"Removed {cleanup_result['removed_count']} orphaned skills: "
|
|
351
|
+
f"{', '.join(cleanup_result['removed_skills'])}"
|
|
352
|
+
)
|
|
353
|
+
except Exception as e:
|
|
354
|
+
self.logger.warning(f"Failed to cleanup orphaned skills: {e}")
|
|
355
|
+
|
|
356
|
+
# Step 6: Cleanup temp directory
|
|
193
357
|
self._cleanup(skills_data["temp_dir"])
|
|
194
358
|
|
|
195
|
-
# Step
|
|
359
|
+
# Step 7: Check if Claude Code restart needed
|
|
196
360
|
restart_required = len(deployed) > 0
|
|
197
361
|
restart_instructions = ""
|
|
198
362
|
|
|
@@ -216,7 +380,8 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
216
380
|
|
|
217
381
|
self.logger.info(
|
|
218
382
|
f"Deployment complete: {len(deployed)} deployed, "
|
|
219
|
-
f"{len(skipped)} skipped, {len(errors)} errors"
|
|
383
|
+
f"{len(skipped)} skipped, {len(errors)} errors, "
|
|
384
|
+
f"{cleanup_result['removed_count']} orphaned skills removed"
|
|
220
385
|
)
|
|
221
386
|
|
|
222
387
|
return {
|
|
@@ -228,6 +393,9 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
228
393
|
"restart_required": restart_required,
|
|
229
394
|
"restart_instructions": restart_instructions,
|
|
230
395
|
"collection": collection_name,
|
|
396
|
+
"selective_mode": selective,
|
|
397
|
+
"total_available": total_available,
|
|
398
|
+
"cleanup": cleanup_result,
|
|
231
399
|
}
|
|
232
400
|
|
|
233
401
|
def list_available_skills(self, collection: Optional[str] = None) -> Dict:
|
|
@@ -412,6 +580,13 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
412
580
|
removed.append(skill_name)
|
|
413
581
|
self.logger.info(f"Removed skill: {skill_name}")
|
|
414
582
|
|
|
583
|
+
# Untrack skill from deployment index
|
|
584
|
+
from claude_mpm.services.skills.selective_skill_deployer import (
|
|
585
|
+
untrack_skill,
|
|
586
|
+
)
|
|
587
|
+
|
|
588
|
+
untrack_skill(self.CLAUDE_SKILLS_DIR, skill_name)
|
|
589
|
+
|
|
415
590
|
except Exception as e:
|
|
416
591
|
self.logger.error(f"Failed to remove {skill_name}: {e}")
|
|
417
592
|
errors.append(f"{skill_name}: {e}")
|
|
@@ -478,7 +653,7 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
478
653
|
f"Updating existing collection '{collection_name}' at {target_dir}"
|
|
479
654
|
)
|
|
480
655
|
try:
|
|
481
|
-
result = subprocess.run(
|
|
656
|
+
result = subprocess.run( # nosec B603 B607 - Safe: hardcoded git command
|
|
482
657
|
["git", "pull"],
|
|
483
658
|
cwd=target_dir,
|
|
484
659
|
capture_output=True,
|
|
@@ -509,7 +684,7 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
509
684
|
f"Installing new collection '{collection_name}' to {target_dir}"
|
|
510
685
|
)
|
|
511
686
|
try:
|
|
512
|
-
result = subprocess.run(
|
|
687
|
+
result = subprocess.run( # nosec B603 B607 - Safe: hardcoded git command
|
|
513
688
|
["git", "clone", repo_url, str(target_dir)],
|
|
514
689
|
capture_output=True,
|
|
515
690
|
text=True,
|
|
@@ -598,6 +773,32 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
598
773
|
if isinstance(skills_data, dict):
|
|
599
774
|
flat_skills = []
|
|
600
775
|
|
|
776
|
+
# Define valid top-level categories
|
|
777
|
+
VALID_CATEGORIES = {"universal", "toolchains"}
|
|
778
|
+
|
|
779
|
+
# Check for unknown categories and warn user
|
|
780
|
+
unknown_categories = set(skills_data.keys()) - VALID_CATEGORIES
|
|
781
|
+
if unknown_categories:
|
|
782
|
+
# Count skills in unknown categories
|
|
783
|
+
skipped_count = 0
|
|
784
|
+
for cat in unknown_categories:
|
|
785
|
+
cat_data = skills_data.get(cat, [])
|
|
786
|
+
if isinstance(cat_data, list):
|
|
787
|
+
skipped_count += len(cat_data)
|
|
788
|
+
elif isinstance(cat_data, dict):
|
|
789
|
+
# If it's a dict like toolchains, count nested skills
|
|
790
|
+
for skills_list in cat_data.values():
|
|
791
|
+
if isinstance(skills_list, list):
|
|
792
|
+
skipped_count += len(skills_list)
|
|
793
|
+
|
|
794
|
+
self.logger.warning(
|
|
795
|
+
f"Unknown categories in manifest will be skipped: "
|
|
796
|
+
f"{', '.join(sorted(unknown_categories))} ({skipped_count} skills)"
|
|
797
|
+
)
|
|
798
|
+
self.logger.info(
|
|
799
|
+
f"Valid top-level categories: {', '.join(sorted(VALID_CATEGORIES))}"
|
|
800
|
+
)
|
|
801
|
+
|
|
601
802
|
# Add universal skills
|
|
602
803
|
universal_skills = skills_data.get("universal", [])
|
|
603
804
|
if isinstance(universal_skills, list):
|
|
@@ -677,72 +878,101 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
677
878
|
return filtered
|
|
678
879
|
|
|
679
880
|
def _deploy_skill(
|
|
680
|
-
self,
|
|
881
|
+
self,
|
|
882
|
+
skill: Dict,
|
|
883
|
+
collection_dir: Path,
|
|
884
|
+
collection_name: str,
|
|
885
|
+
force: bool = False,
|
|
681
886
|
) -> Dict:
|
|
682
|
-
"""Deploy a single skill to ~/.claude/skills
|
|
887
|
+
"""Deploy a single skill to ~/.claude/skills/ and track deployment.
|
|
683
888
|
|
|
684
889
|
NOTE: With multi-collection support, skills are now stored in collection
|
|
685
890
|
subdirectories. This method creates symlinks or copies to maintain the
|
|
686
891
|
flat structure that Claude Code expects in ~/.claude/skills/.
|
|
687
892
|
|
|
893
|
+
Additionally tracks deployed skills in .mpm-deployed-skills.json index
|
|
894
|
+
for orphan cleanup functionality.
|
|
895
|
+
|
|
688
896
|
Args:
|
|
689
897
|
skill: Skill metadata dict
|
|
690
898
|
collection_dir: Collection directory containing skills
|
|
899
|
+
collection_name: Name of collection (for tracking)
|
|
691
900
|
force: Overwrite if already exists
|
|
692
901
|
|
|
693
902
|
Returns:
|
|
694
903
|
Dict with deployed, skipped, error flags
|
|
695
904
|
"""
|
|
696
905
|
skill_name = skill["name"]
|
|
697
|
-
|
|
906
|
+
|
|
907
|
+
# Use normalized source_path for both target directory and deployment tracking
|
|
908
|
+
# This ensures consistency with configuration.yaml skill names
|
|
909
|
+
source_path = skill.get("source_path", "")
|
|
910
|
+
if source_path:
|
|
911
|
+
# Normalize: "universal/web/api-design-patterns/SKILL.md" -> "universal-web-api-design-patterns"
|
|
912
|
+
normalized_name = source_path.replace("/SKILL.md", "").replace("/", "-")
|
|
913
|
+
target_dir = self.CLAUDE_SKILLS_DIR / normalized_name
|
|
914
|
+
else:
|
|
915
|
+
# Fallback to skill name if no source_path
|
|
916
|
+
target_dir = self.CLAUDE_SKILLS_DIR / skill_name
|
|
698
917
|
|
|
699
918
|
# Check if already deployed
|
|
700
919
|
if target_dir.exists() and not force:
|
|
701
920
|
self.logger.debug(f"Skipped {skill_name} (already deployed)")
|
|
702
921
|
return {"deployed": False, "skipped": True, "error": None}
|
|
703
922
|
|
|
704
|
-
# Find skill source
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
923
|
+
# Find skill source using source_path from manifest
|
|
924
|
+
source_dir = None
|
|
925
|
+
|
|
926
|
+
if source_path:
|
|
927
|
+
# Direct lookup using source_path (most reliable)
|
|
928
|
+
# Example: "universal/web/api-design-patterns/SKILL.md" -> "universal/web/api-design-patterns"
|
|
929
|
+
skill_dir_path = source_path.replace("/SKILL.md", "")
|
|
930
|
+
potential_source = collection_dir / skill_dir_path
|
|
931
|
+
if potential_source.exists():
|
|
932
|
+
source_dir = potential_source
|
|
933
|
+
else:
|
|
934
|
+
self.logger.debug(
|
|
935
|
+
f"Source path {skill_dir_path} not found, trying fallback search"
|
|
936
|
+
)
|
|
937
|
+
|
|
938
|
+
# Fallback: search using old logic (for backward compatibility)
|
|
939
|
+
if not source_dir:
|
|
940
|
+
skills_base = collection_dir / "skills"
|
|
941
|
+
category = skill.get("category", "")
|
|
708
942
|
|
|
709
|
-
|
|
710
|
-
|
|
943
|
+
# Try multiple possible locations
|
|
944
|
+
search_paths = []
|
|
711
945
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
# Search in all possible locations
|
|
731
|
-
for path in search_paths:
|
|
732
|
-
if path.exists():
|
|
733
|
-
source_dir = path
|
|
734
|
-
break
|
|
735
|
-
|
|
736
|
-
# Fallback: search recursively for skill in skills directory
|
|
737
|
-
if not source_dir and skills_base.exists():
|
|
738
|
-
for cat_dir in skills_base.iterdir():
|
|
739
|
-
if not cat_dir.is_dir():
|
|
740
|
-
continue
|
|
741
|
-
potential = cat_dir / skill_name
|
|
742
|
-
if potential.exists():
|
|
743
|
-
source_dir = potential
|
|
946
|
+
# Try category-based path
|
|
947
|
+
if category and skills_base.exists():
|
|
948
|
+
search_paths.append(skills_base / category / skill_name)
|
|
949
|
+
|
|
950
|
+
# Try universal/toolchains structure
|
|
951
|
+
if (collection_dir / "universal").exists():
|
|
952
|
+
search_paths.append(collection_dir / "universal" / skill_name)
|
|
953
|
+
|
|
954
|
+
if (collection_dir / "toolchains").exists():
|
|
955
|
+
toolchain_dir = collection_dir / "toolchains"
|
|
956
|
+
for tc in toolchain_dir.iterdir():
|
|
957
|
+
if tc.is_dir():
|
|
958
|
+
search_paths.append(tc / skill_name)
|
|
959
|
+
|
|
960
|
+
# Search in all possible locations
|
|
961
|
+
for path in search_paths:
|
|
962
|
+
if path.exists():
|
|
963
|
+
source_dir = path
|
|
744
964
|
break
|
|
745
965
|
|
|
966
|
+
# Final fallback: search recursively for skill in skills directory
|
|
967
|
+
if not source_dir and skills_base.exists():
|
|
968
|
+
for cat_dir in skills_base.iterdir():
|
|
969
|
+
if not cat_dir.is_dir():
|
|
970
|
+
continue
|
|
971
|
+
potential = cat_dir / skill_name
|
|
972
|
+
if potential.exists():
|
|
973
|
+
source_dir = potential
|
|
974
|
+
break
|
|
975
|
+
|
|
746
976
|
if not source_dir or not source_dir.exists():
|
|
747
977
|
return {
|
|
748
978
|
"deployed": False,
|
|
@@ -777,6 +1007,15 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
777
1007
|
# NOTE: We use copy instead of symlink to maintain Claude Code compatibility
|
|
778
1008
|
shutil.copytree(source_dir, target_dir)
|
|
779
1009
|
|
|
1010
|
+
# Track deployment in index using normalized name
|
|
1011
|
+
from claude_mpm.services.skills.selective_skill_deployer import (
|
|
1012
|
+
track_deployed_skill,
|
|
1013
|
+
)
|
|
1014
|
+
|
|
1015
|
+
# Use normalized name for tracking (matches configuration.yaml format)
|
|
1016
|
+
track_name = normalized_name if source_path else skill_name
|
|
1017
|
+
track_deployed_skill(self.CLAUDE_SKILLS_DIR, track_name, collection_name)
|
|
1018
|
+
|
|
780
1019
|
self.logger.debug(
|
|
781
1020
|
f"Deployed {skill_name} from {source_dir} to {target_dir}"
|
|
782
1021
|
)
|
|
@@ -809,12 +1048,12 @@ class SkillsDeployerService(LoggerMixin):
|
|
|
809
1048
|
"""
|
|
810
1049
|
try:
|
|
811
1050
|
if platform.system() == "Windows":
|
|
812
|
-
result = subprocess.run(
|
|
1051
|
+
result = subprocess.run( # nosec B603 B607 - Safe: hardcoded tasklist command
|
|
813
1052
|
["tasklist"], check=False, capture_output=True, text=True, timeout=5
|
|
814
1053
|
)
|
|
815
1054
|
return "claude" in result.stdout.lower()
|
|
816
1055
|
# macOS and Linux
|
|
817
|
-
result = subprocess.run(
|
|
1056
|
+
result = subprocess.run( # nosec B603 B607 - Safe: hardcoded ps command
|
|
818
1057
|
["ps", "aux"], check=False, capture_output=True, text=True, timeout=5
|
|
819
1058
|
)
|
|
820
1059
|
# Look for "Claude Code" or "claude-code" process
|
|
@@ -152,6 +152,7 @@ class DashboardServer(SocketIOServiceInterface):
|
|
|
152
152
|
|
|
153
153
|
# Register handlers for all events we want to relay from monitor to dashboard
|
|
154
154
|
relay_events = [
|
|
155
|
+
"claude_event", # Tool events from Claude Code hooks
|
|
155
156
|
"session_started",
|
|
156
157
|
"session_ended",
|
|
157
158
|
"claude_status",
|
|
@@ -6,7 +6,7 @@ This normalizer ensures all events follow a consistent schema before broadcastin
|
|
|
6
6
|
providing backward compatibility while establishing a standard format.
|
|
7
7
|
|
|
8
8
|
DESIGN DECISION: Transform all events to a consistent schema:
|
|
9
|
-
- event: Socket.IO event name (always "
|
|
9
|
+
- event: Socket.IO event name (always "mpm_event")
|
|
10
10
|
- type: Main category (hook, system, session, file, connection)
|
|
11
11
|
- subtype: Specific event type (pre_tool, heartbeat, started, etc.)
|
|
12
12
|
- timestamp: ISO format timestamp
|
|
@@ -72,16 +72,21 @@ class NormalizedEvent:
|
|
|
72
72
|
structure explicit and self-documenting.
|
|
73
73
|
"""
|
|
74
74
|
|
|
75
|
-
event: str = "
|
|
75
|
+
event: str = "mpm_event" # Socket.IO event name
|
|
76
76
|
source: str = "" # WHERE the event comes from
|
|
77
77
|
type: str = "" # WHAT category of event
|
|
78
78
|
subtype: str = "" # Specific event type
|
|
79
79
|
timestamp: str = "" # ISO format timestamp
|
|
80
80
|
data: Dict[str, Any] = field(default_factory=dict) # Event payload
|
|
81
|
+
correlation_id: Optional[str] = (
|
|
82
|
+
None # For correlating related events (e.g., pre_tool/post_tool)
|
|
83
|
+
)
|
|
84
|
+
session_id: Optional[str] = None # Session identifier for stream grouping
|
|
85
|
+
cwd: Optional[str] = None # Working directory for project identification
|
|
81
86
|
|
|
82
87
|
def to_dict(self) -> Dict[str, Any]:
|
|
83
88
|
"""Convert to dictionary for emission."""
|
|
84
|
-
|
|
89
|
+
result = {
|
|
85
90
|
"event": self.event,
|
|
86
91
|
"source": self.source,
|
|
87
92
|
"type": self.type,
|
|
@@ -89,6 +94,16 @@ class NormalizedEvent:
|
|
|
89
94
|
"timestamp": self.timestamp,
|
|
90
95
|
"data": self.data,
|
|
91
96
|
}
|
|
97
|
+
# Include correlation_id if present
|
|
98
|
+
if self.correlation_id:
|
|
99
|
+
result["correlation_id"] = self.correlation_id
|
|
100
|
+
# Include session_id if present
|
|
101
|
+
if self.session_id:
|
|
102
|
+
result["session_id"] = self.session_id
|
|
103
|
+
# Include cwd if present
|
|
104
|
+
if self.cwd:
|
|
105
|
+
result["cwd"] = self.cwd
|
|
106
|
+
return result
|
|
92
107
|
|
|
93
108
|
|
|
94
109
|
class EventNormalizer:
|
|
@@ -106,6 +121,7 @@ class EventNormalizer:
|
|
|
106
121
|
"pre_response": (EventType.HOOK, "pre_response"),
|
|
107
122
|
"post_response": (EventType.HOOK, "post_response"),
|
|
108
123
|
"hook_event": (EventType.HOOK, "generic"),
|
|
124
|
+
"hook_execution": (EventType.HOOK, "execution"), # Hook execution metadata
|
|
109
125
|
"UserPrompt": (EventType.HOOK, "user_prompt"), # Legacy format
|
|
110
126
|
# Test events (legacy format)
|
|
111
127
|
"TestStart": (EventType.TEST, "start"),
|
|
@@ -218,14 +234,32 @@ class EventNormalizer:
|
|
|
218
234
|
# Get or generate timestamp
|
|
219
235
|
timestamp = self._extract_timestamp(event_data)
|
|
220
236
|
|
|
237
|
+
# Extract correlation_id, session_id, and cwd if present
|
|
238
|
+
correlation_id = None
|
|
239
|
+
session_id = None
|
|
240
|
+
cwd = None
|
|
241
|
+
if isinstance(event_data, dict):
|
|
242
|
+
correlation_id = event_data.get("correlation_id")
|
|
243
|
+
# Try both naming conventions for session_id
|
|
244
|
+
session_id = event_data.get("session_id") or event_data.get("sessionId")
|
|
245
|
+
# Try multiple field names for working directory
|
|
246
|
+
cwd = (
|
|
247
|
+
event_data.get("cwd")
|
|
248
|
+
or event_data.get("working_directory")
|
|
249
|
+
or event_data.get("workingDirectory")
|
|
250
|
+
)
|
|
251
|
+
|
|
221
252
|
# Create normalized event
|
|
222
253
|
normalized = NormalizedEvent(
|
|
223
|
-
event="
|
|
254
|
+
event="mpm_event",
|
|
224
255
|
source=event_source,
|
|
225
256
|
type=event_type,
|
|
226
257
|
subtype=subtype,
|
|
227
258
|
timestamp=timestamp,
|
|
228
259
|
data=data,
|
|
260
|
+
correlation_id=correlation_id,
|
|
261
|
+
session_id=session_id,
|
|
262
|
+
cwd=cwd,
|
|
229
263
|
)
|
|
230
264
|
|
|
231
265
|
self.stats["normalized"] += 1
|
|
@@ -239,7 +273,7 @@ class EventNormalizer:
|
|
|
239
273
|
|
|
240
274
|
# Return a generic event on error
|
|
241
275
|
return NormalizedEvent(
|
|
242
|
-
event="
|
|
276
|
+
event="mpm_event",
|
|
243
277
|
source="system",
|
|
244
278
|
type="unknown",
|
|
245
279
|
subtype="error",
|
|
@@ -272,8 +306,16 @@ class EventNormalizer:
|
|
|
272
306
|
# If source is not a valid EventSource value, keep it as-is
|
|
273
307
|
pass
|
|
274
308
|
|
|
309
|
+
# Extract session_id and cwd, trying multiple naming conventions
|
|
310
|
+
session_id = event_data.get("session_id") or event_data.get("sessionId")
|
|
311
|
+
cwd = (
|
|
312
|
+
event_data.get("cwd")
|
|
313
|
+
or event_data.get("working_directory")
|
|
314
|
+
or event_data.get("workingDirectory")
|
|
315
|
+
)
|
|
316
|
+
|
|
275
317
|
return NormalizedEvent(
|
|
276
|
-
event="
|
|
318
|
+
event="mpm_event", # Always use standard event name
|
|
277
319
|
source=source,
|
|
278
320
|
type=event_data.get("type", "unknown"),
|
|
279
321
|
subtype=event_data.get("subtype", "generic"),
|
|
@@ -281,6 +323,9 @@ class EventNormalizer:
|
|
|
281
323
|
"timestamp", datetime.now(timezone.utc).isoformat()
|
|
282
324
|
),
|
|
283
325
|
data=event_data.get("data", {}),
|
|
326
|
+
correlation_id=event_data.get("correlation_id"),
|
|
327
|
+
session_id=session_id,
|
|
328
|
+
cwd=cwd,
|
|
284
329
|
)
|
|
285
330
|
|
|
286
331
|
def _extract_event_info(self, event_data: Any) -> Tuple[str, str, Dict[str, Any]]:
|