claude-mpm 4.24.0__py3-none-any.whl → 5.0.9__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 (502) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +12 -0
  3. claude_mpm/agents/OUTPUT_STYLE.md +3 -48
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +721 -911
  5. claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +1322 -0
  6. claude_mpm/agents/WORKFLOW.md +4 -4
  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 → circuit-breakers.md} +370 -3
  13. claude_mpm/agents/templates/context-management-examples.md +544 -0
  14. claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +48 -0
  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 +38 -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 +2 -6
  30. claude_mpm/cli/commands/config.py +7 -4
  31. claude_mpm/cli/commands/configure.py +769 -45
  32. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  33. claude_mpm/cli/commands/configure_navigation.py +63 -46
  34. claude_mpm/cli/commands/debug.py +12 -12
  35. claude_mpm/cli/commands/doctor.py +10 -2
  36. claude_mpm/cli/commands/hook_errors.py +277 -0
  37. claude_mpm/cli/commands/local_deploy.py +1 -4
  38. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  39. claude_mpm/cli/commands/mpm_init/core.py +49 -1
  40. claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
  41. claude_mpm/cli/commands/mpm_init/prompts.py +6 -6
  42. claude_mpm/cli/commands/postmortem.py +401 -0
  43. claude_mpm/cli/commands/run.py +123 -165
  44. claude_mpm/cli/commands/skill_source.py +694 -0
  45. claude_mpm/cli/commands/skills.py +757 -20
  46. claude_mpm/cli/executor.py +78 -3
  47. claude_mpm/cli/interactive/agent_wizard.py +955 -45
  48. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  49. claude_mpm/cli/parsers/agents_parser.py +256 -4
  50. claude_mpm/cli/parsers/base_parser.py +53 -0
  51. claude_mpm/cli/parsers/config_parser.py +96 -43
  52. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  53. claude_mpm/cli/parsers/skills_parser.py +145 -0
  54. claude_mpm/cli/parsers/source_parser.py +138 -0
  55. claude_mpm/cli/startup.py +538 -106
  56. claude_mpm/cli/startup_display.py +480 -0
  57. claude_mpm/cli/utils.py +1 -1
  58. claude_mpm/cli_module/commands.py +1 -1
  59. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  60. claude_mpm/commands/mpm-agents-detect.md +9 -0
  61. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  62. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  63. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  64. claude_mpm/commands/mpm-doctor.md +9 -0
  65. claude_mpm/commands/mpm-help.md +14 -2
  66. claude_mpm/commands/mpm-init.md +27 -2
  67. claude_mpm/commands/mpm-monitor.md +9 -0
  68. claude_mpm/commands/mpm-postmortem.md +123 -0
  69. claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
  70. claude_mpm/commands/mpm-status.md +9 -0
  71. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  72. claude_mpm/commands/mpm-ticket-view.md +552 -0
  73. claude_mpm/commands/mpm-version.md +9 -0
  74. claude_mpm/commands/mpm.md +10 -0
  75. claude_mpm/config/agent_presets.py +488 -0
  76. claude_mpm/config/agent_sources.py +325 -0
  77. claude_mpm/config/skill_presets.py +392 -0
  78. claude_mpm/config/skill_sources.py +590 -0
  79. claude_mpm/constants.py +13 -0
  80. claude_mpm/core/claude_runner.py +5 -34
  81. claude_mpm/core/config.py +16 -0
  82. claude_mpm/core/constants.py +1 -1
  83. claude_mpm/core/framework/__init__.py +3 -16
  84. claude_mpm/core/framework/loaders/file_loader.py +54 -101
  85. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  86. claude_mpm/core/hook_error_memory.py +381 -0
  87. claude_mpm/core/hook_manager.py +41 -2
  88. claude_mpm/core/interactive_session.py +91 -10
  89. claude_mpm/core/logger.py +3 -1
  90. claude_mpm/core/oneshot_session.py +71 -8
  91. claude_mpm/core/protocols/__init__.py +23 -0
  92. claude_mpm/core/protocols/runner_protocol.py +103 -0
  93. claude_mpm/core/protocols/session_protocol.py +131 -0
  94. claude_mpm/core/shared/singleton_manager.py +11 -4
  95. claude_mpm/core/system_context.py +38 -0
  96. claude_mpm/dashboard/static/css/activity.css +69 -69
  97. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  98. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  99. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  100. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  101. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  102. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  103. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  104. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  105. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  106. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  107. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  108. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  109. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  110. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  111. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  112. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  113. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  114. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  115. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  116. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  117. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  118. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  119. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  120. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  121. claude_mpm/dashboard/templates/code_simple.html +23 -23
  122. claude_mpm/dashboard/templates/index.html +18 -18
  123. claude_mpm/experimental/cli_enhancements.py +1 -5
  124. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  125. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  126. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  127. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  128. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  129. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  130. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  131. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  132. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  133. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  134. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  135. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  136. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  137. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  138. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  139. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  140. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  141. claude_mpm/models/git_repository.py +198 -0
  142. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  143. claude_mpm/scripts/start_activity_logging.py +3 -1
  144. claude_mpm/services/agents/agent_builder.py +45 -9
  145. claude_mpm/services/agents/agent_preset_service.py +238 -0
  146. claude_mpm/services/agents/agent_selection_service.py +484 -0
  147. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  148. claude_mpm/services/agents/cache_git_manager.py +621 -0
  149. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  150. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  151. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  152. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  153. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  154. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  155. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  156. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  157. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  158. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  159. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
  160. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  161. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  162. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
  163. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  164. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  165. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  166. claude_mpm/services/agents/git_source_manager.py +629 -0
  167. claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
  168. claude_mpm/services/agents/local_template_manager.py +50 -10
  169. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  170. claude_mpm/services/agents/sources/__init__.py +13 -0
  171. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  172. claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
  173. claude_mpm/services/agents/startup_sync.py +239 -0
  174. claude_mpm/services/agents/toolchain_detector.py +474 -0
  175. claude_mpm/services/analysis/__init__.py +25 -0
  176. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  177. claude_mpm/services/analysis/postmortem_service.py +765 -0
  178. claude_mpm/services/cli/session_pause_manager.py +1 -1
  179. claude_mpm/services/command_deployment_service.py +200 -6
  180. claude_mpm/services/core/base.py +7 -2
  181. claude_mpm/services/core/interfaces/__init__.py +1 -3
  182. claude_mpm/services/core/interfaces/health.py +1 -4
  183. claude_mpm/services/core/models/__init__.py +2 -11
  184. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  185. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  186. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  187. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  188. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  189. claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
  190. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  191. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  192. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  193. claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
  194. claude_mpm/services/event_bus/direct_relay.py +3 -3
  195. claude_mpm/services/events/consumers/logging.py +1 -2
  196. claude_mpm/services/git/__init__.py +21 -0
  197. claude_mpm/services/git/git_operations_service.py +494 -0
  198. claude_mpm/services/github/__init__.py +21 -0
  199. claude_mpm/services/github/github_cli_service.py +397 -0
  200. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  201. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  202. claude_mpm/services/instructions/__init__.py +9 -0
  203. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  204. claude_mpm/services/local_ops/__init__.py +3 -13
  205. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  206. claude_mpm/services/local_ops/health_manager.py +1 -4
  207. claude_mpm/services/local_ops/resource_monitor.py +1 -1
  208. claude_mpm/services/mcp_config_manager.py +75 -145
  209. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  210. claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
  211. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  212. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  213. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  214. claude_mpm/services/mcp_service_verifier.py +6 -3
  215. claude_mpm/services/model/model_router.py +1 -2
  216. claude_mpm/services/monitor/daemon.py +29 -9
  217. claude_mpm/services/monitor/daemon_manager.py +96 -19
  218. claude_mpm/services/monitor/server.py +2 -2
  219. claude_mpm/services/port_manager.py +1 -1
  220. claude_mpm/services/pr/__init__.py +14 -0
  221. claude_mpm/services/pr/pr_template_service.py +329 -0
  222. claude_mpm/services/project/documentation_manager.py +2 -1
  223. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  224. claude_mpm/services/runner_configuration_service.py +16 -3
  225. claude_mpm/services/session_management_service.py +16 -4
  226. claude_mpm/services/skills/__init__.py +18 -0
  227. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  228. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  229. claude_mpm/services/skills_config.py +547 -0
  230. claude_mpm/services/skills_deployer.py +955 -0
  231. claude_mpm/services/socketio/handlers/connection.py +1 -1
  232. claude_mpm/services/socketio/handlers/git.py +1 -1
  233. claude_mpm/services/socketio/server/core.py +1 -4
  234. claude_mpm/services/socketio/server/main.py +1 -3
  235. claude_mpm/services/system_instructions_service.py +1 -3
  236. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  237. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  238. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  239. claude_mpm/services/unified/unified_deployment.py +1 -5
  240. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  241. claude_mpm/services/visualization/__init__.py +1 -5
  242. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  243. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
  244. claude_mpm/skills/skills_registry.py +0 -1
  245. claude_mpm/templates/questions/__init__.py +38 -0
  246. claude_mpm/templates/questions/base.py +193 -0
  247. claude_mpm/templates/questions/pr_strategy.py +311 -0
  248. claude_mpm/templates/questions/project_init.py +385 -0
  249. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  250. claude_mpm/tools/__main__.py +8 -8
  251. claude_mpm/utils/agent_dependency_loader.py +77 -10
  252. claude_mpm/utils/agent_filters.py +288 -0
  253. claude_mpm/utils/dependency_cache.py +3 -1
  254. claude_mpm/utils/gitignore.py +241 -0
  255. claude_mpm/utils/migration.py +372 -0
  256. claude_mpm/utils/progress.py +387 -0
  257. claude_mpm/utils/robust_installer.py +2 -4
  258. claude_mpm/utils/structured_questions.py +619 -0
  259. {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/METADATA +396 -43
  260. {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/RECORD +268 -422
  261. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  262. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  263. claude_mpm/agents/templates/agent-manager.json +0 -273
  264. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  265. claude_mpm/agents/templates/api_qa.json +0 -183
  266. claude_mpm/agents/templates/clerk-ops.json +0 -235
  267. claude_mpm/agents/templates/code_analyzer.json +0 -101
  268. claude_mpm/agents/templates/content-agent.json +0 -358
  269. claude_mpm/agents/templates/dart_engineer.json +0 -307
  270. claude_mpm/agents/templates/data_engineer.json +0 -225
  271. claude_mpm/agents/templates/documentation.json +0 -238
  272. claude_mpm/agents/templates/engineer.json +0 -210
  273. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  274. claude_mpm/agents/templates/golang_engineer.json +0 -270
  275. claude_mpm/agents/templates/imagemagick.json +0 -264
  276. claude_mpm/agents/templates/java_engineer.json +0 -346
  277. claude_mpm/agents/templates/javascript_engineer_agent.json +0 -380
  278. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  279. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  280. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  281. claude_mpm/agents/templates/memory_manager.json +0 -158
  282. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  283. claude_mpm/agents/templates/ops.json +0 -185
  284. claude_mpm/agents/templates/php-engineer.json +0 -287
  285. claude_mpm/agents/templates/product_owner.json +0 -338
  286. claude_mpm/agents/templates/project_organizer.json +0 -144
  287. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  288. claude_mpm/agents/templates/python_engineer.json +0 -387
  289. claude_mpm/agents/templates/qa.json +0 -243
  290. claude_mpm/agents/templates/react_engineer.json +0 -239
  291. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  292. claude_mpm/agents/templates/research.json +0 -188
  293. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  294. claude_mpm/agents/templates/rust_engineer.json +0 -275
  295. claude_mpm/agents/templates/security.json +0 -202
  296. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  297. claude_mpm/agents/templates/tauri_engineer.json +0 -274
  298. claude_mpm/agents/templates/ticketing.json +0 -178
  299. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  300. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  301. claude_mpm/agents/templates/version_control.json +0 -159
  302. claude_mpm/agents/templates/web_qa.json +0 -400
  303. claude_mpm/agents/templates/web_ui.json +0 -189
  304. claude_mpm/commands/mpm-tickets.md +0 -151
  305. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  306. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  307. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  308. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  309. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  310. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  311. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  312. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  313. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  314. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  315. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  316. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  317. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  318. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  319. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  320. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  321. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  322. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  323. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  324. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  325. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  326. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  327. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  328. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  329. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  330. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  331. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  332. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  333. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  334. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  335. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  336. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  337. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  338. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  339. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  340. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  341. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  342. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  343. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  344. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  345. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  346. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  347. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  348. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  349. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  350. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  351. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  352. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  353. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  354. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  355. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  356. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  357. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  358. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  359. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  360. claude_mpm/dashboard/static/built/react/events.js +0 -30
  361. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  362. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  363. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  364. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  365. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  366. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  367. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  368. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  369. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  370. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  371. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  372. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  373. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  374. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  375. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  376. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  377. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  378. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  379. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  380. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  381. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  382. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  383. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  384. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  385. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  386. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  387. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  388. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  389. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  390. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  391. claude_mpm/dashboard/static/events.html +0 -607
  392. claude_mpm/dashboard/static/index.html +0 -635
  393. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  394. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  395. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  396. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  397. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  398. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  399. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  400. claude_mpm/dashboard/static/legacy/files.html +0 -747
  401. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  402. claude_mpm/dashboard/static/monitors.html +0 -431
  403. claude_mpm/dashboard/static/production/events.html +0 -659
  404. claude_mpm/dashboard/static/production/main.html +0 -698
  405. claude_mpm/dashboard/static/production/monitors.html +0 -483
  406. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  407. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  408. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  409. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  410. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  411. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
  412. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
  413. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
  414. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
  415. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
  416. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
  417. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
  418. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
  419. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
  420. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
  421. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
  422. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
  423. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
  424. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
  425. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
  426. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
  427. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
  428. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  429. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  430. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  431. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  432. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  433. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  434. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  435. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  436. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  437. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  438. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
  439. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
  440. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
  441. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
  442. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
  443. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
  444. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
  445. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  446. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  447. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  448. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  449. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
  450. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
  451. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  452. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  453. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  454. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  455. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
  456. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
  457. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
  458. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
  459. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
  460. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
  461. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
  462. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
  463. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
  464. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
  465. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
  466. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
  467. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
  468. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
  469. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
  470. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
  471. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
  472. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
  473. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
  474. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
  475. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
  476. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
  477. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
  478. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  479. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  480. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  481. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  482. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  483. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  484. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
  485. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
  486. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
  487. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
  488. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
  489. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
  490. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
  491. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
  492. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
  493. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
  494. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
  495. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  496. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  497. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  498. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  499. {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/WHEEL +0 -0
  500. {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/entry_points.txt +0 -0
  501. {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/licenses/LICENSE +0 -0
  502. {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.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}')"