claude-mpm 4.20.3__py3-none-any.whl → 5.1.8__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.

Files changed (520) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +35 -6
  3. claude_mpm/agents/OUTPUT_STYLE.md +3 -48
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +1241 -667
  5. claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +1322 -0
  6. claude_mpm/agents/WORKFLOW.md +75 -2
  7. claude_mpm/agents/__init__.py +6 -0
  8. claude_mpm/agents/agent_loader.py +1 -4
  9. claude_mpm/agents/base_agent.json +6 -3
  10. claude_mpm/agents/base_agent_loader.py +10 -35
  11. claude_mpm/agents/frontmatter_validator.py +1 -1
  12. claude_mpm/agents/templates/circuit-breakers.md +1254 -0
  13. claude_mpm/agents/templates/context-management-examples.md +544 -0
  14. claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +89 -19
  15. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  16. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  17. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  18. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  19. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  20. claude_mpm/cli/__init__.py +37 -2
  21. claude_mpm/cli/commands/__init__.py +2 -0
  22. claude_mpm/cli/commands/agent_source.py +774 -0
  23. claude_mpm/cli/commands/agent_state_manager.py +188 -30
  24. claude_mpm/cli/commands/agents.py +959 -36
  25. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  26. claude_mpm/cli/commands/agents_discover.py +338 -0
  27. claude_mpm/cli/commands/aggregate.py +1 -1
  28. claude_mpm/cli/commands/analyze.py +3 -3
  29. claude_mpm/cli/commands/auto_configure.py +537 -239
  30. claude_mpm/cli/commands/cleanup.py +1 -1
  31. claude_mpm/cli/commands/config.py +7 -4
  32. claude_mpm/cli/commands/configure.py +924 -45
  33. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  34. claude_mpm/cli/commands/configure_navigation.py +63 -46
  35. claude_mpm/cli/commands/debug.py +12 -12
  36. claude_mpm/cli/commands/doctor.py +10 -2
  37. claude_mpm/cli/commands/hook_errors.py +277 -0
  38. claude_mpm/cli/commands/local_deploy.py +1 -4
  39. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  40. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  41. claude_mpm/cli/commands/mpm_init/core.py +573 -0
  42. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  43. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  44. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  45. claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
  46. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  47. claude_mpm/cli/commands/mpm_init_handler.py +67 -1
  48. claude_mpm/cli/commands/postmortem.py +401 -0
  49. claude_mpm/cli/commands/run.py +125 -167
  50. claude_mpm/cli/commands/skill_source.py +694 -0
  51. claude_mpm/cli/commands/skills.py +835 -44
  52. claude_mpm/cli/executor.py +78 -3
  53. claude_mpm/cli/interactive/agent_wizard.py +1032 -47
  54. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  55. claude_mpm/cli/parsers/agents_parser.py +256 -4
  56. claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
  57. claude_mpm/cli/parsers/base_parser.py +53 -0
  58. claude_mpm/cli/parsers/config_parser.py +96 -43
  59. claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
  60. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  61. claude_mpm/cli/parsers/skills_parser.py +145 -0
  62. claude_mpm/cli/parsers/source_parser.py +138 -0
  63. claude_mpm/cli/startup.py +564 -108
  64. claude_mpm/cli/startup_display.py +480 -0
  65. claude_mpm/cli/utils.py +1 -1
  66. claude_mpm/cli_module/commands.py +1 -1
  67. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  68. claude_mpm/commands/mpm-agents-detect.md +9 -0
  69. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  70. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  71. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  72. claude_mpm/commands/mpm-doctor.md +9 -0
  73. claude_mpm/commands/mpm-help.md +17 -2
  74. claude_mpm/commands/mpm-init.md +28 -3
  75. claude_mpm/commands/mpm-monitor.md +9 -0
  76. claude_mpm/commands/mpm-postmortem.md +123 -0
  77. claude_mpm/commands/mpm-session-resume.md +381 -0
  78. claude_mpm/commands/mpm-status.md +9 -0
  79. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  80. claude_mpm/commands/mpm-ticket-view.md +552 -0
  81. claude_mpm/commands/mpm-version.md +9 -0
  82. claude_mpm/commands/mpm.md +11 -0
  83. claude_mpm/config/agent_presets.py +488 -0
  84. claude_mpm/config/agent_sources.py +325 -0
  85. claude_mpm/config/skill_presets.py +392 -0
  86. claude_mpm/config/skill_sources.py +590 -0
  87. claude_mpm/constants.py +13 -0
  88. claude_mpm/core/api_validator.py +1 -1
  89. claude_mpm/core/claude_runner.py +19 -35
  90. claude_mpm/core/config.py +24 -0
  91. claude_mpm/core/constants.py +1 -1
  92. claude_mpm/core/framework/__init__.py +3 -16
  93. claude_mpm/core/framework/loaders/file_loader.py +54 -101
  94. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  95. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  96. claude_mpm/core/hook_error_memory.py +381 -0
  97. claude_mpm/core/hook_manager.py +41 -2
  98. claude_mpm/core/interactive_session.py +131 -10
  99. claude_mpm/core/interfaces.py +56 -1
  100. claude_mpm/core/logger.py +3 -1
  101. claude_mpm/core/oneshot_session.py +110 -8
  102. claude_mpm/core/protocols/__init__.py +23 -0
  103. claude_mpm/core/protocols/runner_protocol.py +103 -0
  104. claude_mpm/core/protocols/session_protocol.py +131 -0
  105. claude_mpm/core/shared/singleton_manager.py +11 -4
  106. claude_mpm/core/system_context.py +38 -0
  107. claude_mpm/core/unified_config.py +22 -0
  108. claude_mpm/dashboard/static/css/activity.css +69 -69
  109. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  110. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  111. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  112. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  113. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  114. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  115. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  116. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  117. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  118. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  119. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  120. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  121. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  122. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  123. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  124. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  125. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  126. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  127. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  128. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  129. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  130. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  131. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  132. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  133. claude_mpm/dashboard/templates/code_simple.html +23 -23
  134. claude_mpm/dashboard/templates/index.html +18 -18
  135. claude_mpm/experimental/cli_enhancements.py +1 -5
  136. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  137. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  138. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  139. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  140. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  141. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  142. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  143. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  144. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  145. claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
  146. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  147. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  148. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  149. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  150. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  151. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  152. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  153. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  154. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  155. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  156. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  157. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  158. claude_mpm/models/git_repository.py +198 -0
  159. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  160. claude_mpm/scripts/start_activity_logging.py +3 -1
  161. claude_mpm/services/agents/agent_builder.py +45 -9
  162. claude_mpm/services/agents/agent_preset_service.py +238 -0
  163. claude_mpm/services/agents/agent_selection_service.py +484 -0
  164. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  165. claude_mpm/services/agents/cache_git_manager.py +621 -0
  166. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  167. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  168. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  169. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  170. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  171. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  172. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  173. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  174. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  175. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  176. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
  177. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  178. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  179. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
  180. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  181. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  182. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  183. claude_mpm/services/agents/git_source_manager.py +629 -0
  184. claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
  185. claude_mpm/services/agents/local_template_manager.py +50 -10
  186. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  187. claude_mpm/services/agents/sources/__init__.py +13 -0
  188. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  189. claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
  190. claude_mpm/services/agents/startup_sync.py +239 -0
  191. claude_mpm/services/agents/toolchain_detector.py +474 -0
  192. claude_mpm/services/analysis/__init__.py +25 -0
  193. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  194. claude_mpm/services/analysis/postmortem_service.py +765 -0
  195. claude_mpm/services/cli/session_pause_manager.py +504 -0
  196. claude_mpm/services/cli/session_resume_helper.py +36 -16
  197. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  198. claude_mpm/services/command_deployment_service.py +200 -6
  199. claude_mpm/services/core/base.py +31 -11
  200. claude_mpm/services/core/interfaces/__init__.py +1 -3
  201. claude_mpm/services/core/interfaces/health.py +1 -4
  202. claude_mpm/services/core/interfaces.py +56 -1
  203. claude_mpm/services/core/models/__init__.py +2 -11
  204. claude_mpm/services/core/models/agent_config.py +3 -0
  205. claude_mpm/services/core/models/process.py +4 -0
  206. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  207. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  208. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  209. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  210. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  211. claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
  212. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  213. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  214. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  215. claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
  216. claude_mpm/services/diagnostics/models.py +21 -0
  217. claude_mpm/services/event_bus/direct_relay.py +3 -3
  218. claude_mpm/services/event_bus/event_bus.py +36 -3
  219. claude_mpm/services/event_bus/relay.py +23 -7
  220. claude_mpm/services/events/consumers/logging.py +1 -2
  221. claude_mpm/services/git/__init__.py +21 -0
  222. claude_mpm/services/git/git_operations_service.py +494 -0
  223. claude_mpm/services/github/__init__.py +21 -0
  224. claude_mpm/services/github/github_cli_service.py +397 -0
  225. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  226. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  227. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  228. claude_mpm/services/instructions/__init__.py +9 -0
  229. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  230. claude_mpm/services/local_ops/__init__.py +5 -13
  231. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  232. claude_mpm/services/local_ops/health_manager.py +1 -4
  233. claude_mpm/services/local_ops/process_manager.py +1 -1
  234. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  235. claude_mpm/services/mcp_config_manager.py +75 -145
  236. claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
  237. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  238. claude_mpm/services/mcp_gateway/core/process_pool.py +41 -26
  239. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  240. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  241. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  242. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +26 -21
  243. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  244. claude_mpm/services/mcp_service_verifier.py +6 -3
  245. claude_mpm/services/memory/failure_tracker.py +19 -4
  246. claude_mpm/services/memory/optimizer.py +1 -1
  247. claude_mpm/services/model/model_router.py +8 -9
  248. claude_mpm/services/monitor/daemon.py +29 -9
  249. claude_mpm/services/monitor/daemon_manager.py +96 -19
  250. claude_mpm/services/monitor/server.py +2 -2
  251. claude_mpm/services/native_agent_converter.py +356 -0
  252. claude_mpm/services/port_manager.py +1 -1
  253. claude_mpm/services/pr/__init__.py +14 -0
  254. claude_mpm/services/pr/pr_template_service.py +329 -0
  255. claude_mpm/services/project/documentation_manager.py +2 -1
  256. claude_mpm/services/project/project_organizer.py +4 -0
  257. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  258. claude_mpm/services/runner_configuration_service.py +17 -3
  259. claude_mpm/services/self_upgrade_service.py +165 -7
  260. claude_mpm/services/session_management_service.py +16 -4
  261. claude_mpm/services/skills/__init__.py +18 -0
  262. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  263. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  264. claude_mpm/services/skills_config.py +547 -0
  265. claude_mpm/services/skills_deployer.py +955 -0
  266. claude_mpm/services/socketio/handlers/connection.py +1 -1
  267. claude_mpm/services/socketio/handlers/git.py +2 -2
  268. claude_mpm/services/socketio/server/core.py +1 -4
  269. claude_mpm/services/socketio/server/main.py +1 -3
  270. claude_mpm/services/system_instructions_service.py +1 -3
  271. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  272. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  273. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  274. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  275. claude_mpm/services/unified/unified_deployment.py +1 -5
  276. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  277. claude_mpm/services/visualization/__init__.py +1 -5
  278. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  279. claude_mpm/skills/__init__.py +3 -3
  280. claude_mpm/skills/agent_skills_injector.py +42 -49
  281. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  282. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +17 -10
  283. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +92 -39
  284. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +13 -12
  285. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +5 -3
  286. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +19 -12
  287. claude_mpm/skills/bundled/performance-profiling.md +6 -0
  288. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +6 -6
  289. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +13 -9
  290. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +8 -8
  291. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +37 -15
  292. claude_mpm/skills/skills_registry.py +44 -48
  293. claude_mpm/skills/skills_service.py +117 -108
  294. claude_mpm/templates/questions/__init__.py +38 -0
  295. claude_mpm/templates/questions/base.py +193 -0
  296. claude_mpm/templates/questions/pr_strategy.py +311 -0
  297. claude_mpm/templates/questions/project_init.py +385 -0
  298. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  299. claude_mpm/tools/__main__.py +8 -8
  300. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  301. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  302. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  303. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  304. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  305. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  306. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  307. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  308. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  309. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  310. claude_mpm/utils/agent_dependency_loader.py +80 -13
  311. claude_mpm/utils/agent_filters.py +288 -0
  312. claude_mpm/utils/dependency_cache.py +3 -1
  313. claude_mpm/utils/gitignore.py +244 -0
  314. claude_mpm/utils/log_cleanup.py +3 -3
  315. claude_mpm/utils/migration.py +372 -0
  316. claude_mpm/utils/progress.py +387 -0
  317. claude_mpm/utils/robust_installer.py +3 -5
  318. claude_mpm/utils/structured_questions.py +619 -0
  319. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/METADATA +496 -65
  320. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/RECORD +328 -416
  321. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  322. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  323. claude_mpm/agents/templates/agent-manager.json +0 -273
  324. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  325. claude_mpm/agents/templates/api_qa.json +0 -180
  326. claude_mpm/agents/templates/circuit_breakers.md +0 -638
  327. claude_mpm/agents/templates/clerk-ops.json +0 -235
  328. claude_mpm/agents/templates/code_analyzer.json +0 -101
  329. claude_mpm/agents/templates/content-agent.json +0 -358
  330. claude_mpm/agents/templates/dart_engineer.json +0 -307
  331. claude_mpm/agents/templates/data_engineer.json +0 -225
  332. claude_mpm/agents/templates/documentation.json +0 -211
  333. claude_mpm/agents/templates/engineer.json +0 -210
  334. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  335. claude_mpm/agents/templates/golang_engineer.json +0 -270
  336. claude_mpm/agents/templates/imagemagick.json +0 -264
  337. claude_mpm/agents/templates/java_engineer.json +0 -346
  338. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  339. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  340. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  341. claude_mpm/agents/templates/memory_manager.json +0 -158
  342. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  343. claude_mpm/agents/templates/ops.json +0 -185
  344. claude_mpm/agents/templates/php-engineer.json +0 -281
  345. claude_mpm/agents/templates/product_owner.json +0 -338
  346. claude_mpm/agents/templates/project_organizer.json +0 -140
  347. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  348. claude_mpm/agents/templates/python_engineer.json +0 -387
  349. claude_mpm/agents/templates/qa.json +0 -242
  350. claude_mpm/agents/templates/react_engineer.json +0 -238
  351. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  352. claude_mpm/agents/templates/research.json +0 -188
  353. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  354. claude_mpm/agents/templates/rust_engineer.json +0 -275
  355. claude_mpm/agents/templates/security.json +0 -202
  356. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  357. claude_mpm/agents/templates/ticketing.json +0 -177
  358. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  359. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  360. claude_mpm/agents/templates/version_control.json +0 -157
  361. claude_mpm/agents/templates/web_qa.json +0 -399
  362. claude_mpm/agents/templates/web_ui.json +0 -189
  363. claude_mpm/cli/commands/mpm_init.py +0 -2093
  364. claude_mpm/commands/mpm-tickets.md +0 -102
  365. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  366. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  367. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  368. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  369. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  370. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  371. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  372. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  373. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  374. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  375. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  376. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  377. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  378. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  379. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  380. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  381. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  382. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  383. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  384. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  385. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  386. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  387. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  388. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  389. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  390. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  391. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  392. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  393. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  394. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  395. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  396. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  397. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  398. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  399. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  400. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  401. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  402. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  403. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  404. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  405. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  406. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  407. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  408. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  409. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  410. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  411. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  412. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  413. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  414. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  415. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  416. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  417. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  418. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  419. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  420. claude_mpm/dashboard/static/built/react/events.js +0 -30
  421. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  422. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  423. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  424. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  425. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  426. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  427. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  428. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  429. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  430. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  431. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  432. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  433. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  434. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  435. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  436. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  437. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  438. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  439. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  440. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  441. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  442. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  443. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  444. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  445. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  446. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  447. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  448. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  449. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  450. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  451. claude_mpm/dashboard/static/events.html +0 -607
  452. claude_mpm/dashboard/static/index.html +0 -635
  453. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  454. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  455. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  456. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  457. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  458. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  459. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  460. claude_mpm/dashboard/static/legacy/files.html +0 -747
  461. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  462. claude_mpm/dashboard/static/monitors.html +0 -431
  463. claude_mpm/dashboard/static/production/events.html +0 -659
  464. claude_mpm/dashboard/static/production/main.html +0 -698
  465. claude_mpm/dashboard/static/production/monitors.html +0 -483
  466. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  467. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  468. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  469. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  470. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  471. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -75
  472. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -184
  473. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -107
  474. claude_mpm/skills/bundled/collaboration/requesting-code-review/code-reviewer.md +0 -146
  475. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -118
  476. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -177
  477. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  478. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  479. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  480. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  481. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  482. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  483. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  484. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  485. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  486. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  487. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -175
  488. claude_mpm/skills/bundled/debugging/verification-before-completion/references/common-failures.md +0 -213
  489. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -314
  490. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -227
  491. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -74
  492. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -32
  493. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  494. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  495. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  496. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  497. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -328
  498. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  499. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  500. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  501. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  502. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -209
  503. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -123
  504. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  505. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  506. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  507. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  508. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  509. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  510. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -304
  511. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -96
  512. claude_mpm/tools/code_tree_analyzer.py +0 -1825
  513. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  514. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  515. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  516. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  517. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/WHEEL +0 -0
  518. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/entry_points.txt +0 -0
  519. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/licenses/LICENSE +0 -0
  520. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,568 @@
1
+ """Service for discovering and parsing skills from Git repositories.
2
+
3
+ Skills are stored as Markdown files with YAML frontmatter. This service handles:
4
+ - Discovery of skill files in repository cache
5
+ - Parsing of YAML frontmatter for metadata
6
+ - Extraction of skill content (body)
7
+ - Detection of bundled resources (scripts/, references/, assets/)
8
+
9
+ Design Decision: YAML Frontmatter Format
10
+
11
+ Rationale: YAML frontmatter is a well-established pattern for metadata in
12
+ Markdown files (used by Jekyll, Hugo, MkDocs). It provides clean separation
13
+ between metadata and content, with excellent library support.
14
+
15
+ Trade-offs:
16
+ - Standardization: Widely recognized format
17
+ - Parsing Complexity: Requires regex + YAML parsing
18
+ - Extensibility: Easy to add new metadata fields
19
+
20
+ Example Skill File:
21
+ ---
22
+ name: code-review
23
+ description: Comprehensive code review skill
24
+ skill_version: 1.0.0
25
+ tags: [review, quality, best-practices]
26
+ agent_types: [engineer, qa]
27
+ ---
28
+
29
+ # Code Review Skill
30
+
31
+ When reviewing code, check for:
32
+ - Code quality and style
33
+ - Security vulnerabilities
34
+ ...
35
+ """
36
+
37
+ import re
38
+ from dataclasses import dataclass
39
+ from pathlib import Path
40
+ from typing import Any, Dict, List, Optional, Tuple
41
+
42
+ import yaml
43
+
44
+ from claude_mpm.core.logging_config import get_logger
45
+
46
+ logger = get_logger(__name__)
47
+
48
+
49
+ @dataclass
50
+ class SkillMetadata:
51
+ """Metadata extracted from skill file.
52
+
53
+ Attributes:
54
+ name: Skill name (human-readable)
55
+ description: Brief description of skill purpose
56
+ skill_version: Version string (e.g., "1.0.0")
57
+ tags: List of tags for categorization
58
+ agent_types: Optional list of agent types this skill applies to
59
+ source_file: Path to skill file
60
+ resources: Optional list of bundled resource paths
61
+
62
+ Example:
63
+ >>> metadata = SkillMetadata(
64
+ ... name="code-review",
65
+ ... description="Comprehensive code review",
66
+ ... skill_version="1.0.0",
67
+ ... tags=["review", "quality"],
68
+ ... agent_types=["engineer"],
69
+ ... source_file=Path("skills/code-review.md"),
70
+ ... resources=[]
71
+ ... )
72
+ """
73
+
74
+ name: str
75
+ description: str
76
+ skill_version: str
77
+ tags: List[str]
78
+ agent_types: Optional[List[str]]
79
+ source_file: Path
80
+ resources: Optional[List[Path]]
81
+
82
+
83
+ class SkillDiscoveryService:
84
+ """Discovers and parses skills from Git repositories.
85
+
86
+ Skills Format:
87
+ - Markdown files with YAML frontmatter
88
+ - Frontmatter contains metadata (name, description, version, tags)
89
+ - Body contains skill instructions/prompt
90
+ - Optional bundled resources in scripts/, references/, assets/
91
+
92
+ Design Pattern: Service with Single Responsibility
93
+
94
+ This service focuses solely on discovery and parsing. Syncing, caching,
95
+ and priority resolution are handled by GitSkillSourceManager.
96
+
97
+ Example:
98
+ >>> service = SkillDiscoveryService(Path("~/.claude-mpm/cache/skills/system"))
99
+ >>> skills = service.discover_skills()
100
+ >>> for skill in skills:
101
+ ... print(f"{skill['name']}: {skill['description']}")
102
+ """
103
+
104
+ def __init__(self, skills_dir: Path):
105
+ """Initialize skill discovery service.
106
+
107
+ Args:
108
+ skills_dir: Directory containing skill files
109
+ """
110
+ self.skills_dir = skills_dir
111
+ self.logger = get_logger(__name__)
112
+
113
+ def discover_skills(self) -> List[Dict[str, Any]]:
114
+ """Discover all skills in directory.
115
+
116
+ Scans directory RECURSIVELY for SKILL.md files and parses each as a skill.
117
+ This supports nested Git repository structures while deploying to flat structure.
118
+
119
+ Nested Repository Structure:
120
+ collaboration/
121
+ dispatching-parallel-agents/SKILL.md
122
+ brainstorming/SKILL.md
123
+ debugging/
124
+ systematic-debugging/SKILL.md
125
+
126
+ Deployed Flat Structure:
127
+ collaboration-dispatching-parallel-agents/SKILL.md
128
+ collaboration-brainstorming/SKILL.md
129
+ debugging-systematic-debugging/SKILL.md
130
+
131
+ Skips files that can't be parsed or are missing required fields.
132
+
133
+ Returns:
134
+ List of skill dictionaries:
135
+ [
136
+ {
137
+ "skill_id": str, # Normalized skill ID
138
+ "name": str, # Human-readable name
139
+ "description": str, # Brief description
140
+ "skill_version": str, # Version string
141
+ "tags": List[str], # Tags for categorization
142
+ "agent_types": List[str], # Applicable agent types (optional)
143
+ "content": str, # Skill body content
144
+ "source_file": str, # Path to skill file
145
+ "resources": List[str], # Bundled resource paths (optional)
146
+ "deployment_name": str, # Flattened deployment directory name
147
+ "relative_path": str # Relative path from skills_dir to SKILL.md
148
+ }
149
+ ]
150
+
151
+ Example:
152
+ >>> service = SkillDiscoveryService(Path("cache/skills/system"))
153
+ >>> skills = service.discover_skills()
154
+ >>> print(f"Found {len(skills)} skills")
155
+ """
156
+ skills = []
157
+
158
+ if not self.skills_dir.exists():
159
+ self.logger.debug(f"Skills directory does not exist: {self.skills_dir}")
160
+ return skills
161
+
162
+ # Find all SKILL.md files recursively (Claude Code standard naming)
163
+ skill_md_files = list(self.skills_dir.rglob("SKILL.md"))
164
+
165
+ # Also find legacy *.md files in top-level directory for backward compatibility
166
+ legacy_md_files = [
167
+ f
168
+ for f in self.skills_dir.glob("*.md")
169
+ if f.name != "SKILL.md" and f.name.lower() != "readme.md"
170
+ ]
171
+
172
+ all_skill_files = skill_md_files + legacy_md_files
173
+
174
+ self.logger.debug(
175
+ f"Found {len(skill_md_files)} SKILL.md files recursively "
176
+ f"and {len(legacy_md_files)} legacy .md files in {self.skills_dir}"
177
+ )
178
+
179
+ # Track deployment names to detect collisions
180
+ deployment_names = {}
181
+
182
+ for skill_file in all_skill_files:
183
+ try:
184
+ # Calculate deployment name from path
185
+ deployment_name = self._calculate_deployment_name(skill_file)
186
+
187
+ # Detect name collisions
188
+ if deployment_name in deployment_names:
189
+ self.logger.warning(
190
+ f"Deployment name collision: '{deployment_name}' would be created by both:\n"
191
+ f" - {deployment_names[deployment_name]}\n"
192
+ f" - {skill_file}\n"
193
+ f"Skipping {skill_file} to avoid overwrite."
194
+ )
195
+ continue
196
+
197
+ skill_dict = self._parse_skill_file(skill_file)
198
+ if skill_dict:
199
+ # Add deployment metadata
200
+ skill_dict["deployment_name"] = deployment_name
201
+ skill_dict["relative_path"] = str(
202
+ skill_file.relative_to(self.skills_dir)
203
+ )
204
+
205
+ skills.append(skill_dict)
206
+ deployment_names[deployment_name] = skill_file
207
+ self.logger.debug(
208
+ f"Successfully parsed skill: {skill_file.name} -> {deployment_name}"
209
+ )
210
+ else:
211
+ self.logger.warning(
212
+ f"Failed to parse skill (missing required fields): {skill_file}"
213
+ )
214
+ except Exception as e:
215
+ self.logger.warning(f"Failed to parse skill {skill_file}: {e}")
216
+
217
+ self.logger.info(f"Discovered {len(skills)} skills from {self.skills_dir.name}")
218
+ return skills
219
+
220
+ def _parse_skill_file(self, skill_file: Path) -> Optional[Dict[str, Any]]:
221
+ """Parse a skill Markdown file with YAML frontmatter.
222
+
223
+ Expected Format:
224
+ ---
225
+ name: skill-name
226
+ description: Brief description
227
+ skill_version: 1.0.0
228
+ tags: [tag1, tag2]
229
+ agent_types: [engineer, qa] # Optional
230
+ ---
231
+
232
+ # Skill Content
233
+
234
+ Skill instructions and prompt here...
235
+
236
+ Args:
237
+ skill_file: Path to skill .md file
238
+
239
+ Returns:
240
+ Skill dictionary or None if parsing fails
241
+
242
+ Error Handling:
243
+ - Returns None if frontmatter is missing
244
+ - Returns None if required fields are missing (name, description)
245
+ - Uses defaults for optional fields (tags=[], agent_types=None)
246
+ - Logs warnings for parsing errors
247
+ """
248
+ try:
249
+ content = skill_file.read_text(encoding="utf-8")
250
+ except Exception as e:
251
+ self.logger.error(f"Failed to read file {skill_file}: {e}")
252
+ return None
253
+
254
+ # Extract YAML frontmatter and body
255
+ try:
256
+ frontmatter, body = self._extract_frontmatter(content)
257
+ except Exception as e:
258
+ self.logger.warning(f"No valid frontmatter in {skill_file.name}: {e}")
259
+ return None
260
+
261
+ # Validate required fields
262
+ if "name" not in frontmatter:
263
+ self.logger.warning(f"Missing 'name' field in {skill_file.name}")
264
+ return None
265
+
266
+ if "description" not in frontmatter:
267
+ self.logger.warning(f"Missing 'description' field in {skill_file.name}")
268
+ return None
269
+
270
+ # Extract metadata with defaults
271
+ name = frontmatter["name"]
272
+ description = frontmatter["description"]
273
+ skill_version = frontmatter.get("skill_version", "1.0.0")
274
+ tags = frontmatter.get("tags", [])
275
+ agent_types = frontmatter.get("agent_types", None)
276
+
277
+ # Ensure tags is a list
278
+ if isinstance(tags, str):
279
+ tags = [tags]
280
+ elif not isinstance(tags, list):
281
+ tags = []
282
+
283
+ # Ensure agent_types is a list (if present)
284
+ if agent_types is not None:
285
+ if isinstance(agent_types, str):
286
+ agent_types = [agent_types]
287
+ elif not isinstance(agent_types, list):
288
+ agent_types = None
289
+
290
+ # Generate skill_id from name (lowercase, replace spaces/underscores with hyphens)
291
+ skill_id = self._generate_skill_id(name)
292
+
293
+ # Find bundled resources
294
+ resources = self._find_bundled_resources(skill_file)
295
+
296
+ # Build skill dictionary
297
+ skill_dict = {
298
+ "skill_id": skill_id,
299
+ "name": name,
300
+ "description": description,
301
+ "skill_version": skill_version,
302
+ "tags": tags,
303
+ "content": body.strip(),
304
+ "source_file": str(skill_file),
305
+ }
306
+
307
+ # Add optional fields
308
+ if agent_types is not None:
309
+ skill_dict["agent_types"] = agent_types
310
+
311
+ if resources:
312
+ skill_dict["resources"] = [str(r) for r in resources]
313
+
314
+ return skill_dict
315
+
316
+ def _extract_frontmatter(self, content: str) -> Tuple[Dict[str, Any], str]:
317
+ """Extract YAML frontmatter and body from Markdown.
318
+
319
+ Frontmatter must be at the start of the file, delimited by "---".
320
+
321
+ Args:
322
+ content: Markdown file content
323
+
324
+ Returns:
325
+ Tuple of (frontmatter_dict, body_content)
326
+
327
+ Raises:
328
+ ValueError: If no valid frontmatter found
329
+
330
+ Frontmatter Format:
331
+ ---
332
+ key: value
333
+ list: [item1, item2]
334
+ ---
335
+
336
+ Body content here...
337
+
338
+ Example:
339
+ >>> content = "---\\nname: test\\n---\\nBody"
340
+ >>> frontmatter, body = service._extract_frontmatter(content)
341
+ >>> frontmatter["name"]
342
+ 'test'
343
+ >>> body
344
+ 'Body'
345
+ """
346
+ # Use regex to extract frontmatter between --- markers
347
+ # Pattern: Start of string, ---, content, ---, rest
348
+ pattern = r"^---\s*\n(.*?)\n---\s*\n(.*)$"
349
+ match = re.match(pattern, content, re.DOTALL)
350
+
351
+ if not match:
352
+ raise ValueError("No valid YAML frontmatter found")
353
+
354
+ frontmatter_text = match.group(1)
355
+ body = match.group(2)
356
+
357
+ # Parse YAML
358
+ try:
359
+ frontmatter = yaml.safe_load(frontmatter_text)
360
+ except yaml.YAMLError as e:
361
+ raise ValueError(f"Invalid YAML in frontmatter: {e}") from e
362
+
363
+ if not isinstance(frontmatter, dict):
364
+ raise ValueError("Frontmatter must be a YAML dictionary")
365
+
366
+ return frontmatter, body
367
+
368
+ def _calculate_deployment_name(self, skill_file: Path) -> str:
369
+ """Calculate flat deployment name from nested skill path.
370
+
371
+ Flattens nested Git repository structure into hyphen-separated name
372
+ suitable for Claude Code's flat skill directory structure.
373
+
374
+ Path Flattening Algorithm:
375
+ 1. Get relative path from skills_dir to skill file
376
+ 2. Extract all parent directory names (excluding the final skill directory)
377
+ 3. Join path components with hyphens
378
+ 4. Normalize to lowercase, remove special characters
379
+
380
+ Args:
381
+ skill_file: Path to SKILL.md or skill markdown file
382
+
383
+ Returns:
384
+ Flattened deployment directory name
385
+
386
+ Examples:
387
+ >>> # Nested repository structure
388
+ >>> skill_file = Path("cache/skills/system/collaboration/dispatching-parallel-agents/SKILL.md")
389
+ >>> name = service._calculate_deployment_name(skill_file)
390
+ >>> name
391
+ 'collaboration-dispatching-parallel-agents'
392
+
393
+ >>> # Single-level structure (legacy)
394
+ >>> skill_file = Path("cache/skills/system/code-review.md")
395
+ >>> name = service._calculate_deployment_name(skill_file)
396
+ >>> name
397
+ 'code-review'
398
+
399
+ >>> # Deep nesting
400
+ >>> skill_file = Path("cache/skills/system/aws/s3/bucket-ops/SKILL.md")
401
+ >>> name = service._calculate_deployment_name(skill_file)
402
+ >>> name
403
+ 'aws-s3-bucket-ops'
404
+ """
405
+ # Get relative path from skills_dir to skill file
406
+ try:
407
+ relative_path = skill_file.relative_to(self.skills_dir)
408
+ except ValueError:
409
+ # Fallback: skill_file is not under skills_dir
410
+ # Use just the filename
411
+ self.logger.warning(
412
+ f"Skill file {skill_file} is not under {self.skills_dir}, "
413
+ f"using filename as deployment name"
414
+ )
415
+ return skill_file.stem
416
+
417
+ # Get all path parts (directories + filename)
418
+ parts = list(relative_path.parts)
419
+
420
+ # Handle different structures:
421
+ # 1. SKILL.md case: collaboration/dispatching-parallel-agents/SKILL.md
422
+ # -> Take parent directories: ['collaboration', 'dispatching-parallel-agents']
423
+ # 2. Legacy .md case: code-review.md
424
+ # -> Take just filename stem: ['code-review']
425
+
426
+ if skill_file.name == "SKILL.md":
427
+ # SKILL.md case: use all parent directories as deployment name
428
+ # Remove the final 'SKILL.md' part
429
+ deployment_parts = parts[:-1]
430
+
431
+ if not deployment_parts:
432
+ # Edge case: SKILL.md at top level
433
+ # Use parent directory name or 'skill'
434
+ deployment_parts = ["skill"]
435
+ else:
436
+ # Legacy .md case: use filename stem
437
+ deployment_parts = [skill_file.stem]
438
+
439
+ # Join with hyphens and normalize
440
+ deployment_name = "-".join(deployment_parts)
441
+
442
+ # Normalize: lowercase, remove special chars, collapse hyphens
443
+ deployment_name = deployment_name.lower()
444
+ deployment_name = deployment_name.replace("_", "-")
445
+ deployment_name = re.sub(r"[^a-z0-9-]+", "", deployment_name)
446
+ deployment_name = re.sub(r"-+", "-", deployment_name)
447
+ return deployment_name.strip("-")
448
+
449
+ def _generate_skill_id(self, name: str) -> str:
450
+ """Generate skill ID from name.
451
+
452
+ Converts name to lowercase, replaces spaces/underscores with hyphens,
453
+ removes non-alphanumeric characters, and collapses multiple hyphens.
454
+
455
+ Args:
456
+ name: Human-readable skill name
457
+
458
+ Returns:
459
+ Normalized skill ID
460
+
461
+ Example:
462
+ >>> service._generate_skill_id("Code Review")
463
+ 'code-review'
464
+ >>> service._generate_skill_id("Python_Style-Check!")
465
+ 'python-style-check'
466
+ """
467
+ # 1. Convert to lowercase
468
+ skill_id = name.lower()
469
+
470
+ # 2. Replace spaces and underscores with hyphens
471
+ skill_id = skill_id.replace(" ", "-").replace("_", "-")
472
+
473
+ # 3. Remove any characters that aren't alphanumeric or hyphens
474
+ skill_id = re.sub(r"[^a-z0-9-]+", "", skill_id)
475
+
476
+ # 4. Collapse multiple consecutive hyphens into one
477
+ skill_id = re.sub(r"-+", "-", skill_id)
478
+
479
+ # 5. Remove leading/trailing hyphens
480
+ return skill_id.strip("-")
481
+
482
+ def _find_bundled_resources(self, skill_file: Path) -> List[Path]:
483
+ """Find bundled resources for a skill.
484
+
485
+ Resources are in parallel directories:
486
+ skills/
487
+ skill-name.md
488
+ scripts/
489
+ skill-name/
490
+ helper.sh
491
+ references/
492
+ skill-name/
493
+ docs.md
494
+ assets/
495
+ skill-name/
496
+ image.png
497
+
498
+ Args:
499
+ skill_file: Path to skill .md file
500
+
501
+ Returns:
502
+ List of resource file paths
503
+
504
+ Example:
505
+ >>> skill_file = Path("cache/skills/system/code-review.md")
506
+ >>> resources = service._find_bundled_resources(skill_file)
507
+ >>> print(resources)
508
+ [Path('cache/skills/system/scripts/code-review/helper.sh')]
509
+ """
510
+ resources = []
511
+
512
+ # Derive skill name from filename (without .md extension)
513
+ skill_name = skill_file.stem
514
+
515
+ # Get parent directory (where skills/ is located)
516
+ parent_dir = skill_file.parent
517
+
518
+ # Check for resource directories
519
+ resource_dirs = ["scripts", "references", "assets"]
520
+
521
+ for resource_dir_name in resource_dirs:
522
+ resource_dir = parent_dir / resource_dir_name / skill_name
523
+
524
+ if resource_dir.exists() and resource_dir.is_dir():
525
+ # Find all files in resource directory (recursively)
526
+ for resource_file in resource_dir.rglob("*"):
527
+ if resource_file.is_file():
528
+ resources.append(resource_file)
529
+
530
+ if resources:
531
+ self.logger.debug(
532
+ f"Found {len(resources)} bundled resources for {skill_name}"
533
+ )
534
+
535
+ return resources
536
+
537
+ def get_skill_metadata(self, skill_name: str) -> Optional[SkillMetadata]:
538
+ """Get metadata for a specific skill.
539
+
540
+ Args:
541
+ skill_name: Name of the skill to retrieve
542
+
543
+ Returns:
544
+ SkillMetadata if found, None otherwise
545
+
546
+ Example:
547
+ >>> service = SkillDiscoveryService(Path("cache/skills/system"))
548
+ >>> metadata = service.get_skill_metadata("code-review")
549
+ >>> if metadata:
550
+ ... print(f"{metadata.name}: {metadata.description}")
551
+ """
552
+ for md_file in self.skills_dir.glob("*.md"):
553
+ skill_dict = self._parse_skill_file(md_file)
554
+ if skill_dict and skill_dict["name"] == skill_name:
555
+ return SkillMetadata(
556
+ name=skill_dict["name"],
557
+ description=skill_dict["description"],
558
+ skill_version=skill_dict["skill_version"],
559
+ tags=skill_dict["tags"],
560
+ agent_types=skill_dict.get("agent_types"),
561
+ source_file=Path(skill_dict["source_file"]),
562
+ resources=[Path(r) for r in skill_dict.get("resources", [])],
563
+ )
564
+ return None
565
+
566
+ def __repr__(self) -> str:
567
+ """Return string representation."""
568
+ return f"SkillDiscoveryService(skills_dir='{self.skills_dir}')"