claude-mpm 4.24.0__py3-none-any.whl → 5.4.41__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/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +3 -48
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
- claude_mpm/agents/MEMORY.md +1 -1
- claude_mpm/agents/PM_INSTRUCTIONS.md +735 -925
- claude_mpm/agents/WORKFLOW.md +5 -254
- claude_mpm/agents/__init__.py +6 -0
- claude_mpm/agents/agent_loader.py +14 -48
- claude_mpm/agents/base_agent.json +7 -4
- claude_mpm/agents/frontmatter_validator.py +71 -3
- claude_mpm/agents/templates/circuit-breakers.md +1391 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +48 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/cli/__init__.py +37 -2
- claude_mpm/cli/__main__.py +4 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +180 -31
- claude_mpm/cli/commands/agents.py +1116 -55
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +1 -1
- claude_mpm/cli/commands/analyze.py +3 -3
- claude_mpm/cli/commands/auto_configure.py +725 -242
- claude_mpm/cli/commands/config.py +95 -6
- claude_mpm/cli/commands/configure.py +1875 -46
- claude_mpm/cli/commands/configure_agent_display.py +29 -10
- claude_mpm/cli/commands/configure_navigation.py +63 -46
- claude_mpm/cli/commands/debug.py +12 -12
- claude_mpm/cli/commands/doctor.py +10 -2
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/local_deploy.py +1 -4
- claude_mpm/cli/commands/mcp_install_commands.py +1 -1
- claude_mpm/cli/commands/mpm_init/core.py +229 -2
- claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +286 -6
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/profile.py +277 -0
- claude_mpm/cli/commands/run.py +123 -165
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +782 -20
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/executor.py +96 -3
- claude_mpm/cli/interactive/agent_wizard.py +1030 -45
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +307 -10
- claude_mpm/cli/parsers/auto_configure_parser.py +13 -138
- claude_mpm/cli/parsers/base_parser.py +65 -0
- claude_mpm/cli/parsers/config_parser.py +162 -39
- claude_mpm/cli/parsers/profile_parser.py +148 -0
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +146 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/startup.py +1280 -118
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/cli_module/commands.py +1 -1
- claude_mpm/commands/mpm-config.md +21 -134
- claude_mpm/commands/mpm-doctor.md +16 -20
- claude_mpm/commands/mpm-help.md +13 -283
- claude_mpm/commands/mpm-init.md +88 -489
- claude_mpm/commands/mpm-monitor.md +23 -401
- claude_mpm/commands/mpm-organize.md +72 -247
- claude_mpm/commands/mpm-postmortem.md +21 -0
- claude_mpm/commands/mpm-session-resume.md +30 -0
- claude_mpm/commands/mpm-status.md +13 -68
- claude_mpm/commands/mpm-ticket-view.md +109 -0
- claude_mpm/commands/mpm-version.md +13 -106
- claude_mpm/commands/mpm.md +10 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +352 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/constants.py +13 -0
- claude_mpm/core/claude_runner.py +5 -34
- claude_mpm/core/config.py +15 -1
- claude_mpm/core/constants.py +1 -1
- claude_mpm/core/framework/__init__.py +3 -16
- 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/file_loader.py +54 -101
- claude_mpm/core/framework/loaders/instruction_loader.py +66 -5
- claude_mpm/core/framework_loader.py +4 -2
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +41 -2
- claude_mpm/core/interactive_session.py +91 -10
- claude_mpm/core/logger.py +16 -1
- claude_mpm/core/oneshot_session.py +71 -8
- claude_mpm/core/optimized_startup.py +59 -0
- claude_mpm/core/output_style_manager.py +173 -43
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/shared/config_loader.py +1 -1
- claude_mpm/core/shared/singleton_manager.py +11 -4
- claude_mpm/core/socketio_pool.py +3 -3
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/unified_agent_registry.py +134 -16
- claude_mpm/core/unified_config.py +22 -0
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DjhvlsAc.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/N4qtv3Hx.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uj46x2Wr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.CAGBuiOw.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +10 -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/experimental/cli_enhancements.py +1 -5
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.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__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/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/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +214 -79
- claude_mpm/hooks/claude_hooks/hook_handler.py +155 -1
- claude_mpm/hooks/claude_hooks/installer.py +33 -10
- claude_mpm/hooks/claude_hooks/memory_integration.py +28 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.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 +30 -6
- claude_mpm/hooks/failure_learning/__init__.py +2 -8
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
- claude_mpm/hooks/kuzu_response_hook.py +1 -5
- claude_mpm/hooks/memory_integration_hook.py +46 -1
- claude_mpm/init.py +63 -19
- claude_mpm/models/agent_definition.py +7 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/scripts/claude-hook-handler.sh +60 -20
- claude_mpm/scripts/launch_monitor.py +93 -13
- claude_mpm/scripts/start_activity_logging.py +3 -1
- claude_mpm/services/agents/agent_builder.py +48 -12
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- 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 +484 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +148 -2
- claude_mpm/services/agents/deployment/agent_discovery_service.py +104 -73
- claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
- claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
- claude_mpm/services/agents/deployment/agent_template_builder.py +238 -15
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
- claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +422 -31
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +841 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
- claude_mpm/services/agents/git_source_manager.py +663 -0
- claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
- claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
- claude_mpm/services/agents/local_template_manager.py +50 -10
- claude_mpm/services/agents/recommender.py +5 -3
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1094 -0
- claude_mpm/services/agents/startup_sync.py +259 -0
- claude_mpm/services/agents/toolchain_detector.py +478 -0
- claude_mpm/services/analysis/__init__.py +35 -0
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/cli/session_pause_manager.py +1 -1
- claude_mpm/services/command_deployment_service.py +271 -6
- claude_mpm/services/core/base.py +7 -2
- claude_mpm/services/core/interfaces/__init__.py +1 -3
- claude_mpm/services/core/interfaces/health.py +1 -4
- claude_mpm/services/core/models/__init__.py +2 -11
- claude_mpm/services/diagnostics/checks/__init__.py +4 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +2 -4
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
- claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
- claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
- claude_mpm/services/event_bus/config.py +3 -1
- claude_mpm/services/event_bus/direct_relay.py +3 -3
- claude_mpm/services/events/consumers/logging.py +1 -2
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +579 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
- claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +3 -13
- claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
- claude_mpm/services/local_ops/health_manager.py +1 -4
- claude_mpm/services/local_ops/resource_monitor.py +1 -1
- claude_mpm/services/mcp_config_manager.py +75 -145
- claude_mpm/services/mcp_service_verifier.py +6 -3
- claude_mpm/services/model/model_router.py +1 -2
- claude_mpm/services/monitor/daemon.py +38 -11
- claude_mpm/services/monitor/daemon_manager.py +134 -21
- claude_mpm/services/monitor/management/lifecycle.py +8 -1
- claude_mpm/services/monitor/server.py +700 -24
- claude_mpm/services/pm_skills_deployer.py +676 -0
- claude_mpm/services/port_manager.py +1 -1
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/profile_manager.py +331 -0
- claude_mpm/services/project/documentation_manager.py +2 -1
- claude_mpm/services/project/project_organizer.py +4 -0
- claude_mpm/services/project/toolchain_analyzer.py +3 -1
- claude_mpm/services/runner_configuration_service.py +16 -3
- claude_mpm/services/self_upgrade_service.py +120 -12
- claude_mpm/services/session_management_service.py +16 -4
- claude_mpm/services/skills/__init__.py +21 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1297 -0
- claude_mpm/services/skills/selective_skill_deployer.py +704 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +1072 -0
- claude_mpm/services/socketio/dashboard_server.py +1 -0
- claude_mpm/services/socketio/event_normalizer.py +51 -6
- claude_mpm/services/socketio/handlers/connection.py +1 -1
- claude_mpm/services/socketio/handlers/git.py +1 -1
- claude_mpm/services/socketio/server/core.py +387 -112
- claude_mpm/services/socketio/server/main.py +1 -3
- claude_mpm/services/system_instructions_service.py +1 -3
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
- claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
- claude_mpm/services/unified/unified_deployment.py +1 -5
- claude_mpm/services/version_control/conflict_resolution.py +6 -4
- claude_mpm/services/version_control/git_operations.py +103 -0
- claude_mpm/services/visualization/__init__.py +1 -5
- claude_mpm/services/visualization/mermaid_generator.py +2 -3
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
- claude_mpm/skills/skill_manager.py +92 -3
- claude_mpm/skills/skills_registry.py +0 -1
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/tools/__main__.py +8 -8
- claude_mpm/utils/agent_dependency_loader.py +91 -12
- claude_mpm/utils/agent_filters.py +261 -0
- claude_mpm/utils/dependency_cache.py +3 -1
- claude_mpm/utils/gitignore.py +244 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +49 -7
- claude_mpm/utils/structured_questions.py +619 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.4.41.dist-info}/METADATA +445 -122
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.4.41.dist-info}/RECORD +298 -503
- claude_mpm-5.4.41.dist-info/entry_points.txt +5 -0
- claude_mpm-5.4.41.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.41.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 -468
- 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/base_agent_loader.py +0 -626
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
- claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
- claude_mpm/agents/templates/agent-manager.json +0 -273
- claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
- claude_mpm/agents/templates/api_qa.json +0 -183
- claude_mpm/agents/templates/circuit_breakers.md +0 -638
- claude_mpm/agents/templates/clerk-ops.json +0 -235
- claude_mpm/agents/templates/code_analyzer.json +0 -101
- claude_mpm/agents/templates/content-agent.json +0 -358
- claude_mpm/agents/templates/dart_engineer.json +0 -307
- claude_mpm/agents/templates/data_engineer.json +0 -225
- claude_mpm/agents/templates/documentation.json +0 -238
- claude_mpm/agents/templates/engineer.json +0 -210
- claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
- claude_mpm/agents/templates/golang_engineer.json +0 -270
- claude_mpm/agents/templates/imagemagick.json +0 -264
- claude_mpm/agents/templates/java_engineer.json +0 -346
- claude_mpm/agents/templates/javascript_engineer_agent.json +0 -380
- claude_mpm/agents/templates/local_ops_agent.json +0 -1840
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
- claude_mpm/agents/templates/memory_manager.json +0 -158
- claude_mpm/agents/templates/nextjs_engineer.json +0 -285
- claude_mpm/agents/templates/ops.json +0 -185
- claude_mpm/agents/templates/php-engineer.json +0 -287
- claude_mpm/agents/templates/product_owner.json +0 -338
- claude_mpm/agents/templates/project_organizer.json +0 -144
- claude_mpm/agents/templates/prompt-engineer.json +0 -737
- claude_mpm/agents/templates/python_engineer.json +0 -387
- claude_mpm/agents/templates/qa.json +0 -243
- claude_mpm/agents/templates/react_engineer.json +0 -239
- claude_mpm/agents/templates/refactoring_engineer.json +0 -276
- claude_mpm/agents/templates/research.json +0 -188
- claude_mpm/agents/templates/ruby-engineer.json +0 -280
- claude_mpm/agents/templates/rust_engineer.json +0 -275
- claude_mpm/agents/templates/security.json +0 -202
- claude_mpm/agents/templates/svelte-engineer.json +0 -225
- claude_mpm/agents/templates/tauri_engineer.json +0 -274
- claude_mpm/agents/templates/ticketing.json +0 -178
- claude_mpm/agents/templates/typescript_engineer.json +0 -285
- claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
- claude_mpm/agents/templates/version_control.json +0 -159
- claude_mpm/agents/templates/web_qa.json +0 -400
- claude_mpm/agents/templates/web_ui.json +0 -189
- 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-detect.md +0 -168
- claude_mpm/commands/mpm-agents-recommend.md +0 -214
- claude_mpm/commands/mpm-agents.md +0 -122
- claude_mpm/commands/mpm-auto-configure.md +0 -269
- claude_mpm/commands/mpm-resume.md +0 -372
- claude_mpm/commands/mpm-tickets.md +0 -151
- claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
- 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/react/components/DataInspector/DataInspector.module.css +0 -188
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
- claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
- claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
- claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
- claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
- claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
- claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
- claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
- claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/built/connection-manager.js +0 -536
- claude_mpm/dashboard/static/built/dashboard.js +0 -2
- claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/built/react/events.js +0 -30
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
- claude_mpm/dashboard/static/built/shared/logger.js +0 -385
- claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/built/socket-client.js +0 -2
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
- 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/dist/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/dist/dashboard.js +0 -2
- claude_mpm/dashboard/static/dist/react/events.js +0 -30
- claude_mpm/dashboard/static/dist/socket-client.js +0 -2
- claude_mpm/dashboard/static/events.html +0 -607
- claude_mpm/dashboard/static/index.html +0 -635
- 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 -1896
- claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/js/shared/logger.js +0 -385
- claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/js/socket-client.js +0 -1457
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/legacy/activity.html +0 -736
- claude_mpm/dashboard/static/legacy/agents.html +0 -786
- claude_mpm/dashboard/static/legacy/files.html +0 -747
- claude_mpm/dashboard/static/legacy/tools.html +0 -831
- claude_mpm/dashboard/static/monitors.html +0 -431
- claude_mpm/dashboard/static/production/events.html +0 -659
- claude_mpm/dashboard/static/production/main.html +0 -698
- claude_mpm/dashboard/static/production/monitors.html +0 -483
- 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/static/test-archive/dashboard.html +0 -635
- claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
- claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
- claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
- 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/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 -971
- 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 -419
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -714
- 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 -551
- 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/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
- claude_mpm-4.24.0.dist-info/entry_points.txt +0 -10
- claude_mpm-4.24.0.dist-info/licenses/LICENSE +0 -21
- /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
- /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
- /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
- /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.4.41.dist-info}/WHEEL +0 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.4.41.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
"""PM Skills Deployer Service - Deploy bundled PM skills to projects.
|
|
2
|
+
|
|
3
|
+
WHY: PM agents require specific templates and skills for proper operation.
|
|
4
|
+
This service manages deployment of bundled PM skills from the claude-mpm
|
|
5
|
+
package to individual project .claude-mpm directories with version tracking.
|
|
6
|
+
|
|
7
|
+
DESIGN DECISIONS:
|
|
8
|
+
- Deploys from src/claude_mpm/skills/bundled/pm/ to .claude-mpm/skills/pm/
|
|
9
|
+
- Per-project deployment (NOT global like Claude Code skills)
|
|
10
|
+
- Version tracking via .claude-mpm/pm_skills_registry.yaml
|
|
11
|
+
- Checksum validation for integrity verification
|
|
12
|
+
- Non-blocking verification (returns warnings, doesn't halt execution)
|
|
13
|
+
- Force flag to redeploy even if versions match
|
|
14
|
+
|
|
15
|
+
ARCHITECTURE:
|
|
16
|
+
1. Discovery: Find bundled PM skills in package
|
|
17
|
+
2. Deployment: Copy to project .claude-mpm/skills/pm/
|
|
18
|
+
3. Registry: Track deployed versions and checksums
|
|
19
|
+
4. Verification: Check deployment status (non-blocking)
|
|
20
|
+
5. Updates: Compare bundled vs deployed versions
|
|
21
|
+
|
|
22
|
+
References:
|
|
23
|
+
- Parent Service: src/claude_mpm/services/skills_deployer.py
|
|
24
|
+
- Skills Service: src/claude_mpm/skills/skills_service.py
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
import hashlib
|
|
28
|
+
import shutil
|
|
29
|
+
from dataclasses import dataclass
|
|
30
|
+
from datetime import datetime
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
33
|
+
|
|
34
|
+
import yaml
|
|
35
|
+
|
|
36
|
+
from claude_mpm.core.mixins import LoggerMixin
|
|
37
|
+
|
|
38
|
+
# Security constants
|
|
39
|
+
MAX_YAML_SIZE = 10 * 1024 * 1024 # 10MB limit to prevent YAML bombs
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class PMSkillInfo:
|
|
44
|
+
"""Information about a deployed PM skill.
|
|
45
|
+
|
|
46
|
+
Attributes:
|
|
47
|
+
name: Skill name (directory/file name)
|
|
48
|
+
version: Skill version from metadata
|
|
49
|
+
deployed_at: ISO timestamp of deployment
|
|
50
|
+
checksum: SHA256 checksum of skill content
|
|
51
|
+
source_path: Original bundled skill path
|
|
52
|
+
deployed_path: Deployed skill path
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
name: str
|
|
56
|
+
version: str
|
|
57
|
+
deployed_at: str
|
|
58
|
+
checksum: str
|
|
59
|
+
source_path: Path
|
|
60
|
+
deployed_path: Path
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class DeploymentResult:
|
|
65
|
+
"""Result of skill deployment operation.
|
|
66
|
+
|
|
67
|
+
Attributes:
|
|
68
|
+
success: Whether deployment succeeded
|
|
69
|
+
deployed: List of successfully deployed skill names
|
|
70
|
+
skipped: List of skipped skill names (already deployed)
|
|
71
|
+
errors: List of dicts with 'skill' and 'error' keys
|
|
72
|
+
message: Summary message
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
success: bool
|
|
76
|
+
deployed: List[str]
|
|
77
|
+
skipped: List[str]
|
|
78
|
+
errors: List[Dict[str, str]]
|
|
79
|
+
message: str
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass
|
|
83
|
+
class VerificationResult:
|
|
84
|
+
"""Result of skill verification operation.
|
|
85
|
+
|
|
86
|
+
Attributes:
|
|
87
|
+
verified: Whether all skills are properly deployed
|
|
88
|
+
warnings: List of warning messages
|
|
89
|
+
missing_skills: List of missing skill names
|
|
90
|
+
outdated_skills: List of outdated skill names
|
|
91
|
+
message: Summary message
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
verified: bool
|
|
95
|
+
warnings: List[str]
|
|
96
|
+
missing_skills: List[str]
|
|
97
|
+
outdated_skills: List[str]
|
|
98
|
+
message: str
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@dataclass
|
|
102
|
+
class UpdateInfo:
|
|
103
|
+
"""Information about available skill update.
|
|
104
|
+
|
|
105
|
+
Attributes:
|
|
106
|
+
skill_name: Name of skill with update available
|
|
107
|
+
current_version: Currently deployed version
|
|
108
|
+
new_version: Available bundled version
|
|
109
|
+
checksum_changed: Whether content changed (even if version same)
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
skill_name: str
|
|
113
|
+
current_version: str
|
|
114
|
+
new_version: str
|
|
115
|
+
checksum_changed: bool
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class PMSkillsDeployerService(LoggerMixin):
|
|
119
|
+
"""Deploy and manage PM skills from bundled sources to projects.
|
|
120
|
+
|
|
121
|
+
This service provides:
|
|
122
|
+
- Discovery of bundled PM skills (templates)
|
|
123
|
+
- Deployment to .claude-mpm/skills/pm/
|
|
124
|
+
- Version tracking via pm_skills_registry.yaml
|
|
125
|
+
- Checksum validation for integrity
|
|
126
|
+
- Non-blocking verification (warnings only)
|
|
127
|
+
- Update detection and deployment
|
|
128
|
+
|
|
129
|
+
Example:
|
|
130
|
+
>>> deployer = PMSkillsDeployerService()
|
|
131
|
+
>>> result = deployer.deploy_pm_skills(Path("/project/root"))
|
|
132
|
+
>>> print(f"Deployed {len(result.deployed)} skills")
|
|
133
|
+
>>>
|
|
134
|
+
>>> verify_result = deployer.verify_pm_skills(Path("/project/root"))
|
|
135
|
+
>>> if not verify_result.verified:
|
|
136
|
+
... print(f"Warnings: {verify_result.warnings}")
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
REGISTRY_VERSION = "1.0.0"
|
|
140
|
+
REGISTRY_FILENAME = "pm_skills_registry.yaml"
|
|
141
|
+
|
|
142
|
+
def __init__(self) -> None:
|
|
143
|
+
"""Initialize PM Skills Deployer Service.
|
|
144
|
+
|
|
145
|
+
Sets up paths for:
|
|
146
|
+
- bundled_pm_skills_path: Source bundled PM skills (.claude-mpm/templates/)
|
|
147
|
+
- Deployment paths are project-specific (passed to methods)
|
|
148
|
+
"""
|
|
149
|
+
super().__init__()
|
|
150
|
+
|
|
151
|
+
# Bundled PM skills are in .claude-mpm/templates/ at project root
|
|
152
|
+
# Find project root by traversing up from this file
|
|
153
|
+
self.project_root = self._find_project_root()
|
|
154
|
+
self.bundled_pm_skills_path = (
|
|
155
|
+
self.project_root / ".claude-mpm" / "templates"
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
if not self.bundled_pm_skills_path.exists():
|
|
159
|
+
self.logger.warning(
|
|
160
|
+
f"Bundled PM skills path not found: {self.bundled_pm_skills_path}"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
def _find_project_root(self) -> Path:
|
|
164
|
+
"""Find project root by traversing up from current file.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Path to project root (directory containing .git or pyproject.toml)
|
|
168
|
+
"""
|
|
169
|
+
current = Path(__file__).resolve()
|
|
170
|
+
|
|
171
|
+
# Traverse up to find project root markers
|
|
172
|
+
for parent in [current] + list(current.parents):
|
|
173
|
+
if (parent / ".git").exists() or (parent / "pyproject.toml").exists():
|
|
174
|
+
return parent
|
|
175
|
+
|
|
176
|
+
# Fallback to current working directory
|
|
177
|
+
return Path.cwd()
|
|
178
|
+
|
|
179
|
+
def _validate_safe_path(self, base: Path, target: Path) -> bool:
|
|
180
|
+
"""Ensure target path is within base directory to prevent path traversal.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
base: Base directory that should contain the target
|
|
184
|
+
target: Target path to validate
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
True if path is safe, False otherwise
|
|
188
|
+
"""
|
|
189
|
+
try:
|
|
190
|
+
target.resolve().relative_to(base.resolve())
|
|
191
|
+
return True
|
|
192
|
+
except ValueError:
|
|
193
|
+
return False
|
|
194
|
+
|
|
195
|
+
def _compute_checksum(self, file_path: Path) -> str:
|
|
196
|
+
"""Compute SHA256 checksum of file content.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
file_path: Path to file to checksum
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
Hex string of SHA256 checksum
|
|
203
|
+
"""
|
|
204
|
+
sha256 = hashlib.sha256()
|
|
205
|
+
try:
|
|
206
|
+
with open(file_path, "rb") as f:
|
|
207
|
+
# Read in 64KB chunks to handle large files
|
|
208
|
+
for chunk in iter(lambda: f.read(65536), b""):
|
|
209
|
+
sha256.update(chunk)
|
|
210
|
+
return sha256.hexdigest()
|
|
211
|
+
except OSError as e:
|
|
212
|
+
self.logger.error(f"Failed to compute checksum for {file_path}: {e}")
|
|
213
|
+
return ""
|
|
214
|
+
|
|
215
|
+
def _get_registry_path(self, project_dir: Path) -> Path:
|
|
216
|
+
"""Get path to PM skills registry file.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
project_dir: Project root directory
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Path to pm_skills_registry.yaml
|
|
223
|
+
"""
|
|
224
|
+
return project_dir / ".claude-mpm" / self.REGISTRY_FILENAME
|
|
225
|
+
|
|
226
|
+
def _get_deployment_dir(self, project_dir: Path) -> Path:
|
|
227
|
+
"""Get deployment directory for PM skills.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
project_dir: Project root directory
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
Path to .claude-mpm/skills/pm/
|
|
234
|
+
"""
|
|
235
|
+
return project_dir / ".claude-mpm" / "skills" / "pm"
|
|
236
|
+
|
|
237
|
+
def _load_registry(self, project_dir: Path) -> Dict[str, Any]:
|
|
238
|
+
"""Load PM skills registry with security checks.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
project_dir: Project root directory
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
Dict containing registry data, or empty dict if not found/invalid
|
|
245
|
+
"""
|
|
246
|
+
registry_path = self._get_registry_path(project_dir)
|
|
247
|
+
|
|
248
|
+
if not registry_path.exists():
|
|
249
|
+
self.logger.debug(f"PM skills registry not found: {registry_path}")
|
|
250
|
+
return {}
|
|
251
|
+
|
|
252
|
+
# Check file size to prevent YAML bomb
|
|
253
|
+
try:
|
|
254
|
+
file_size = registry_path.stat().st_size
|
|
255
|
+
if file_size > MAX_YAML_SIZE:
|
|
256
|
+
self.logger.error(
|
|
257
|
+
f"Registry file too large: {file_size} bytes (max {MAX_YAML_SIZE})"
|
|
258
|
+
)
|
|
259
|
+
return {}
|
|
260
|
+
except OSError as e:
|
|
261
|
+
self.logger.error(f"Failed to stat registry file: {e}")
|
|
262
|
+
return {}
|
|
263
|
+
|
|
264
|
+
try:
|
|
265
|
+
with open(registry_path, encoding="utf-8") as f:
|
|
266
|
+
registry = yaml.safe_load(f)
|
|
267
|
+
if not registry:
|
|
268
|
+
self.logger.warning(f"Empty registry file: {registry_path}")
|
|
269
|
+
return {}
|
|
270
|
+
self.logger.debug(f"Loaded PM skills registry from {registry_path}")
|
|
271
|
+
return registry
|
|
272
|
+
except yaml.YAMLError as e:
|
|
273
|
+
self.logger.error(f"Invalid YAML in registry: {e}")
|
|
274
|
+
return {}
|
|
275
|
+
except OSError as e:
|
|
276
|
+
self.logger.error(f"Failed to read registry file: {e}")
|
|
277
|
+
return {}
|
|
278
|
+
|
|
279
|
+
def _save_registry(self, project_dir: Path, registry: Dict[str, Any]) -> bool:
|
|
280
|
+
"""Save PM skills registry to file.
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
project_dir: Project root directory
|
|
284
|
+
registry: Registry data to save
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
True if save succeeded, False otherwise
|
|
288
|
+
"""
|
|
289
|
+
registry_path = self._get_registry_path(project_dir)
|
|
290
|
+
|
|
291
|
+
try:
|
|
292
|
+
# Ensure parent directory exists
|
|
293
|
+
registry_path.parent.mkdir(parents=True, exist_ok=True)
|
|
294
|
+
|
|
295
|
+
with open(registry_path, "w", encoding="utf-8") as f:
|
|
296
|
+
yaml.safe_dump(
|
|
297
|
+
registry, f, default_flow_style=False, allow_unicode=True
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
self.logger.debug(f"Saved PM skills registry to {registry_path}")
|
|
301
|
+
return True
|
|
302
|
+
except (OSError, yaml.YAMLError) as e:
|
|
303
|
+
self.logger.error(f"Failed to save registry: {e}")
|
|
304
|
+
return False
|
|
305
|
+
|
|
306
|
+
def _discover_bundled_pm_skills(self) -> List[Dict[str, Any]]:
|
|
307
|
+
"""Discover all PM skills in bundled templates directory.
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
List of skill dictionaries containing:
|
|
311
|
+
- name: Skill name (filename without extension)
|
|
312
|
+
- path: Full path to skill file
|
|
313
|
+
- type: File type (md, json, yaml, etc.)
|
|
314
|
+
"""
|
|
315
|
+
skills = []
|
|
316
|
+
|
|
317
|
+
if not self.bundled_pm_skills_path.exists():
|
|
318
|
+
self.logger.warning(
|
|
319
|
+
f"Bundled PM skills path not found: {self.bundled_pm_skills_path}"
|
|
320
|
+
)
|
|
321
|
+
return skills
|
|
322
|
+
|
|
323
|
+
# Scan for skill files (.md templates)
|
|
324
|
+
for skill_file in self.bundled_pm_skills_path.glob("*.md"):
|
|
325
|
+
if skill_file.name.startswith("."):
|
|
326
|
+
continue
|
|
327
|
+
|
|
328
|
+
skills.append(
|
|
329
|
+
{
|
|
330
|
+
"name": skill_file.stem,
|
|
331
|
+
"path": skill_file,
|
|
332
|
+
"type": skill_file.suffix[1:], # Remove leading dot
|
|
333
|
+
}
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
self.logger.info(f"Discovered {len(skills)} bundled PM skills")
|
|
337
|
+
return skills
|
|
338
|
+
|
|
339
|
+
def deploy_pm_skills(
|
|
340
|
+
self,
|
|
341
|
+
project_dir: Path,
|
|
342
|
+
force: bool = False,
|
|
343
|
+
progress_callback: Optional[Callable[[str, int, int], None]] = None,
|
|
344
|
+
) -> DeploymentResult:
|
|
345
|
+
"""Deploy bundled PM skills to project directory.
|
|
346
|
+
|
|
347
|
+
Copies PM skills from bundled templates to .claude-mpm/skills/pm/
|
|
348
|
+
and updates registry with version and checksum information.
|
|
349
|
+
|
|
350
|
+
Args:
|
|
351
|
+
project_dir: Project root directory
|
|
352
|
+
force: If True, redeploy even if skill already exists
|
|
353
|
+
progress_callback: Optional callback(skill_name, current, total) for progress
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
DeploymentResult with deployment status and details
|
|
357
|
+
|
|
358
|
+
Example:
|
|
359
|
+
>>> result = deployer.deploy_pm_skills(Path("/project"), force=True)
|
|
360
|
+
>>> print(f"Deployed: {len(result.deployed)}")
|
|
361
|
+
"""
|
|
362
|
+
skills = self._discover_bundled_pm_skills()
|
|
363
|
+
deployed = []
|
|
364
|
+
skipped = []
|
|
365
|
+
errors = []
|
|
366
|
+
|
|
367
|
+
if not skills:
|
|
368
|
+
return DeploymentResult(
|
|
369
|
+
success=True,
|
|
370
|
+
deployed=[],
|
|
371
|
+
skipped=[],
|
|
372
|
+
errors=[],
|
|
373
|
+
message="No PM skills found to deploy",
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
# Ensure deployment directory exists
|
|
377
|
+
deployment_dir = self._get_deployment_dir(project_dir)
|
|
378
|
+
deployment_dir.mkdir(parents=True, exist_ok=True)
|
|
379
|
+
|
|
380
|
+
# SECURITY: Validate deployment path
|
|
381
|
+
if not self._validate_safe_path(project_dir, deployment_dir):
|
|
382
|
+
return DeploymentResult(
|
|
383
|
+
success=False,
|
|
384
|
+
deployed=[],
|
|
385
|
+
skipped=[],
|
|
386
|
+
errors=[
|
|
387
|
+
{
|
|
388
|
+
"skill": "all",
|
|
389
|
+
"error": "Path traversal attempt detected in deployment directory",
|
|
390
|
+
}
|
|
391
|
+
],
|
|
392
|
+
message="Security check failed",
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
# Load existing registry
|
|
396
|
+
registry = self._load_registry(project_dir)
|
|
397
|
+
deployed_skills = registry.get("skills", [])
|
|
398
|
+
|
|
399
|
+
# Create lookup for existing deployments
|
|
400
|
+
existing_deployments = {
|
|
401
|
+
skill["name"]: skill for skill in deployed_skills
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
new_deployed_skills = []
|
|
405
|
+
timestamp = datetime.utcnow().isoformat() + "Z"
|
|
406
|
+
total_skills = len(skills)
|
|
407
|
+
|
|
408
|
+
for idx, skill in enumerate(skills):
|
|
409
|
+
try:
|
|
410
|
+
skill_name = skill["name"]
|
|
411
|
+
source_path = skill["path"]
|
|
412
|
+
|
|
413
|
+
# Report progress if callback provided
|
|
414
|
+
if progress_callback:
|
|
415
|
+
progress_callback(skill_name, idx + 1, total_skills)
|
|
416
|
+
target_path = deployment_dir / source_path.name
|
|
417
|
+
|
|
418
|
+
# SECURITY: Validate target path
|
|
419
|
+
if not self._validate_safe_path(deployment_dir, target_path):
|
|
420
|
+
raise ValueError(f"Path traversal attempt detected: {target_path}")
|
|
421
|
+
|
|
422
|
+
# Compute checksum of source
|
|
423
|
+
checksum = self._compute_checksum(source_path)
|
|
424
|
+
|
|
425
|
+
# Check if already deployed
|
|
426
|
+
if skill_name in existing_deployments and not force:
|
|
427
|
+
existing = existing_deployments[skill_name]
|
|
428
|
+
if existing.get("checksum") == checksum:
|
|
429
|
+
skipped.append(skill_name)
|
|
430
|
+
new_deployed_skills.append(existing) # Keep existing entry
|
|
431
|
+
self.logger.debug(
|
|
432
|
+
f"Skipped {skill_name} (already deployed with same checksum)"
|
|
433
|
+
)
|
|
434
|
+
continue
|
|
435
|
+
|
|
436
|
+
# Deploy skill
|
|
437
|
+
shutil.copy2(source_path, target_path)
|
|
438
|
+
|
|
439
|
+
# Add to deployed list
|
|
440
|
+
deployed.append(skill_name)
|
|
441
|
+
|
|
442
|
+
# Update registry entry
|
|
443
|
+
skill_entry = {
|
|
444
|
+
"name": skill_name,
|
|
445
|
+
"version": "1.0.0", # PM templates don't have versions yet
|
|
446
|
+
"deployed_at": timestamp,
|
|
447
|
+
"checksum": checksum,
|
|
448
|
+
}
|
|
449
|
+
new_deployed_skills.append(skill_entry)
|
|
450
|
+
|
|
451
|
+
self.logger.debug(f"Deployed PM skill: {skill_name}")
|
|
452
|
+
|
|
453
|
+
except (ValueError, OSError) as e:
|
|
454
|
+
self.logger.error(f"Failed to deploy {skill['name']}: {e}")
|
|
455
|
+
errors.append({"skill": skill["name"], "error": str(e)})
|
|
456
|
+
|
|
457
|
+
# Update registry
|
|
458
|
+
updated_registry = {
|
|
459
|
+
"version": self.REGISTRY_VERSION,
|
|
460
|
+
"deployed_at": timestamp,
|
|
461
|
+
"skills": new_deployed_skills,
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if not self._save_registry(project_dir, updated_registry):
|
|
465
|
+
errors.append(
|
|
466
|
+
{
|
|
467
|
+
"skill": "registry",
|
|
468
|
+
"error": "Failed to save registry after deployment",
|
|
469
|
+
}
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
success = len(errors) == 0
|
|
473
|
+
message = (
|
|
474
|
+
f"Deployed {len(deployed)} skills, skipped {len(skipped)}, "
|
|
475
|
+
f"{len(errors)} errors"
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
self.logger.info(message)
|
|
479
|
+
|
|
480
|
+
return DeploymentResult(
|
|
481
|
+
success=success,
|
|
482
|
+
deployed=deployed,
|
|
483
|
+
skipped=skipped,
|
|
484
|
+
errors=errors,
|
|
485
|
+
message=message,
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
def verify_pm_skills(self, project_dir: Path) -> VerificationResult:
|
|
489
|
+
"""Verify PM skills are properly deployed (non-blocking).
|
|
490
|
+
|
|
491
|
+
Checks deployment status and returns warnings without halting execution.
|
|
492
|
+
This allows graceful degradation if PM skills are missing.
|
|
493
|
+
|
|
494
|
+
Args:
|
|
495
|
+
project_dir: Project root directory
|
|
496
|
+
|
|
497
|
+
Returns:
|
|
498
|
+
VerificationResult with verification status and warnings
|
|
499
|
+
|
|
500
|
+
Example:
|
|
501
|
+
>>> result = deployer.verify_pm_skills(Path("/project"))
|
|
502
|
+
>>> if not result.verified:
|
|
503
|
+
... for warning in result.warnings:
|
|
504
|
+
... print(f"WARNING: {warning}")
|
|
505
|
+
"""
|
|
506
|
+
warnings = []
|
|
507
|
+
missing_skills = []
|
|
508
|
+
outdated_skills = []
|
|
509
|
+
|
|
510
|
+
# Check if registry exists
|
|
511
|
+
registry = self._load_registry(project_dir)
|
|
512
|
+
if not registry:
|
|
513
|
+
warnings.append("PM skills registry not found or invalid")
|
|
514
|
+
missing_skills.append("all")
|
|
515
|
+
return VerificationResult(
|
|
516
|
+
verified=False,
|
|
517
|
+
warnings=warnings,
|
|
518
|
+
missing_skills=missing_skills,
|
|
519
|
+
outdated_skills=outdated_skills,
|
|
520
|
+
message="PM skills not deployed. Run 'claude-mpm init' to deploy.",
|
|
521
|
+
)
|
|
522
|
+
|
|
523
|
+
# Check each registered skill exists
|
|
524
|
+
deployment_dir = self._get_deployment_dir(project_dir)
|
|
525
|
+
deployed_skills = registry.get("skills", [])
|
|
526
|
+
|
|
527
|
+
for skill in deployed_skills:
|
|
528
|
+
skill_name = skill["name"]
|
|
529
|
+
skill_file = deployment_dir / f"{skill_name}.md"
|
|
530
|
+
|
|
531
|
+
if not skill_file.exists():
|
|
532
|
+
warnings.append(f"Deployed skill file missing: {skill_name}")
|
|
533
|
+
missing_skills.append(skill_name)
|
|
534
|
+
continue
|
|
535
|
+
|
|
536
|
+
# Verify checksum
|
|
537
|
+
current_checksum = self._compute_checksum(skill_file)
|
|
538
|
+
expected_checksum = skill.get("checksum", "")
|
|
539
|
+
|
|
540
|
+
if current_checksum != expected_checksum:
|
|
541
|
+
warnings.append(
|
|
542
|
+
f"Skill checksum mismatch: {skill_name} (file may be corrupted)"
|
|
543
|
+
)
|
|
544
|
+
outdated_skills.append(skill_name)
|
|
545
|
+
|
|
546
|
+
# Check for available updates
|
|
547
|
+
bundled_skills = {s["name"]: s for s in self._discover_bundled_pm_skills()}
|
|
548
|
+
for skill_name, bundled_skill in bundled_skills.items():
|
|
549
|
+
# Find corresponding deployed skill
|
|
550
|
+
deployed_skill = next(
|
|
551
|
+
(s for s in deployed_skills if s["name"] == skill_name), None
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
if not deployed_skill:
|
|
555
|
+
warnings.append(f"New PM skill available: {skill_name}")
|
|
556
|
+
missing_skills.append(skill_name)
|
|
557
|
+
continue
|
|
558
|
+
|
|
559
|
+
# Check if checksums differ
|
|
560
|
+
bundled_checksum = self._compute_checksum(bundled_skill["path"])
|
|
561
|
+
deployed_checksum = deployed_skill.get("checksum", "")
|
|
562
|
+
|
|
563
|
+
if bundled_checksum != deployed_checksum:
|
|
564
|
+
warnings.append(f"PM skill update available: {skill_name}")
|
|
565
|
+
outdated_skills.append(skill_name)
|
|
566
|
+
|
|
567
|
+
verified = len(warnings) == 0
|
|
568
|
+
|
|
569
|
+
if verified:
|
|
570
|
+
message = "All PM skills verified and up-to-date"
|
|
571
|
+
else:
|
|
572
|
+
message = f"{len(warnings)} verification warnings found"
|
|
573
|
+
|
|
574
|
+
return VerificationResult(
|
|
575
|
+
verified=verified,
|
|
576
|
+
warnings=warnings,
|
|
577
|
+
missing_skills=missing_skills,
|
|
578
|
+
outdated_skills=outdated_skills,
|
|
579
|
+
message=message,
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
def get_deployed_skills(self, project_dir: Path) -> List[PMSkillInfo]:
|
|
583
|
+
"""Get list of deployed PM skills with metadata.
|
|
584
|
+
|
|
585
|
+
Args:
|
|
586
|
+
project_dir: Project root directory
|
|
587
|
+
|
|
588
|
+
Returns:
|
|
589
|
+
List of PMSkillInfo objects for deployed skills
|
|
590
|
+
|
|
591
|
+
Example:
|
|
592
|
+
>>> skills = deployer.get_deployed_skills(Path("/project"))
|
|
593
|
+
>>> for skill in skills:
|
|
594
|
+
... print(f"{skill.name} v{skill.version} ({skill.deployed_at})")
|
|
595
|
+
"""
|
|
596
|
+
registry = self._load_registry(project_dir)
|
|
597
|
+
deployment_dir = self._get_deployment_dir(project_dir)
|
|
598
|
+
|
|
599
|
+
skills = []
|
|
600
|
+
for skill_data in registry.get("skills", []):
|
|
601
|
+
skill_name = skill_data["name"]
|
|
602
|
+
deployed_path = deployment_dir / f"{skill_name}.md"
|
|
603
|
+
|
|
604
|
+
# Find source path (may not exist if bundled skills changed)
|
|
605
|
+
source_path = self.bundled_pm_skills_path / f"{skill_name}.md"
|
|
606
|
+
|
|
607
|
+
skills.append(
|
|
608
|
+
PMSkillInfo(
|
|
609
|
+
name=skill_name,
|
|
610
|
+
version=skill_data.get("version", "1.0.0"),
|
|
611
|
+
deployed_at=skill_data.get("deployed_at", "unknown"),
|
|
612
|
+
checksum=skill_data.get("checksum", ""),
|
|
613
|
+
source_path=source_path,
|
|
614
|
+
deployed_path=deployed_path,
|
|
615
|
+
)
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
return skills
|
|
619
|
+
|
|
620
|
+
def check_updates_available(self, project_dir: Path) -> List[UpdateInfo]:
|
|
621
|
+
"""Check for available PM skill updates.
|
|
622
|
+
|
|
623
|
+
Compares bundled skills against deployed skills to identify updates.
|
|
624
|
+
|
|
625
|
+
Args:
|
|
626
|
+
project_dir: Project root directory
|
|
627
|
+
|
|
628
|
+
Returns:
|
|
629
|
+
List of UpdateInfo objects for skills with updates available
|
|
630
|
+
|
|
631
|
+
Example:
|
|
632
|
+
>>> updates = deployer.check_updates_available(Path("/project"))
|
|
633
|
+
>>> for update in updates:
|
|
634
|
+
... print(f"{update.skill_name}: {update.current_version} -> {update.new_version}")
|
|
635
|
+
"""
|
|
636
|
+
registry = self._load_registry(project_dir)
|
|
637
|
+
deployed_skills = {
|
|
638
|
+
skill["name"]: skill for skill in registry.get("skills", [])
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
bundled_skills = self._discover_bundled_pm_skills()
|
|
642
|
+
|
|
643
|
+
updates = []
|
|
644
|
+
for bundled_skill in bundled_skills:
|
|
645
|
+
skill_name = bundled_skill["name"]
|
|
646
|
+
|
|
647
|
+
# Compute bundled checksum
|
|
648
|
+
bundled_checksum = self._compute_checksum(bundled_skill["path"])
|
|
649
|
+
|
|
650
|
+
if skill_name not in deployed_skills:
|
|
651
|
+
# New skill available
|
|
652
|
+
updates.append(
|
|
653
|
+
UpdateInfo(
|
|
654
|
+
skill_name=skill_name,
|
|
655
|
+
current_version="not deployed",
|
|
656
|
+
new_version="1.0.0",
|
|
657
|
+
checksum_changed=True,
|
|
658
|
+
)
|
|
659
|
+
)
|
|
660
|
+
continue
|
|
661
|
+
|
|
662
|
+
# Check if checksum differs
|
|
663
|
+
deployed_skill = deployed_skills[skill_name]
|
|
664
|
+
deployed_checksum = deployed_skill.get("checksum", "")
|
|
665
|
+
|
|
666
|
+
if bundled_checksum != deployed_checksum:
|
|
667
|
+
updates.append(
|
|
668
|
+
UpdateInfo(
|
|
669
|
+
skill_name=skill_name,
|
|
670
|
+
current_version=deployed_skill.get("version", "1.0.0"),
|
|
671
|
+
new_version="1.0.0",
|
|
672
|
+
checksum_changed=True,
|
|
673
|
+
)
|
|
674
|
+
)
|
|
675
|
+
|
|
676
|
+
return updates
|
|
@@ -431,7 +431,7 @@ class PortManager:
|
|
|
431
431
|
return port
|
|
432
432
|
|
|
433
433
|
self.logger.error(
|
|
434
|
-
f"No available ports in range {self.PORT_RANGE.start}-{self.PORT_RANGE.stop-1}"
|
|
434
|
+
f"No available ports in range {self.PORT_RANGE.start}-{self.PORT_RANGE.stop - 1}"
|
|
435
435
|
)
|
|
436
436
|
return None
|
|
437
437
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pull Request Services Package
|
|
3
|
+
==============================
|
|
4
|
+
|
|
5
|
+
Provides PR template generation and workflow automation.
|
|
6
|
+
Used by agent-improver and skills-manager agents.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .pr_template_service import PRTemplateService, PRType
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"PRTemplateService",
|
|
13
|
+
"PRType",
|
|
14
|
+
]
|