claude-mpm 3.4.10__py3-none-any.whl → 5.4.85__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.
Files changed (1062) hide show
  1. claude_mpm/BUILD_NUMBER +1 -0
  2. claude_mpm/VERSION +1 -0
  3. claude_mpm/__init__.py +50 -12
  4. claude_mpm/__main__.py +7 -2
  5. claude_mpm/agents/BASE_AGENT.md +164 -0
  6. claude_mpm/agents/BASE_ENGINEER.md +658 -0
  7. claude_mpm/agents/CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md +405 -0
  8. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +112 -0
  9. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +186 -0
  10. claude_mpm/agents/MEMORY.md +72 -0
  11. claude_mpm/agents/PM_INSTRUCTIONS.md +1429 -0
  12. claude_mpm/agents/WORKFLOW.md +111 -0
  13. claude_mpm/agents/__init__.py +92 -80
  14. claude_mpm/agents/agent-template.yaml +83 -0
  15. claude_mpm/agents/agent_loader.py +560 -745
  16. claude_mpm/agents/agent_loader_integration.py +53 -55
  17. claude_mpm/agents/agents_metadata.py +186 -27
  18. claude_mpm/agents/async_agent_loader.py +436 -0
  19. claude_mpm/agents/base_agent.json +8 -4
  20. claude_mpm/agents/frontmatter_validator.py +754 -0
  21. claude_mpm/agents/system_agent_config.py +222 -155
  22. claude_mpm/agents/templates/README.md +465 -0
  23. claude_mpm/agents/templates/__init__.py +17 -13
  24. claude_mpm/agents/templates/circuit-breakers.md +1391 -0
  25. claude_mpm/agents/templates/context-management-examples.md +544 -0
  26. claude_mpm/agents/templates/git-file-tracking.md +584 -0
  27. claude_mpm/agents/templates/pm-examples.md +474 -0
  28. claude_mpm/agents/templates/pm-red-flags.md +310 -0
  29. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  30. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  31. claude_mpm/agents/templates/response-format.md +583 -0
  32. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  33. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  34. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  35. claude_mpm/agents/templates/validation-templates.md +312 -0
  36. claude_mpm/cli/__init__.py +94 -128
  37. claude_mpm/cli/__main__.py +33 -0
  38. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  39. claude_mpm/cli/commands/__init__.py +36 -12
  40. claude_mpm/cli/commands/agent_manager.py +1403 -0
  41. claude_mpm/cli/commands/agent_source.py +774 -0
  42. claude_mpm/cli/commands/agent_state_manager.py +335 -0
  43. claude_mpm/cli/commands/agents.py +2501 -168
  44. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  45. claude_mpm/cli/commands/agents_discover.py +338 -0
  46. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  47. claude_mpm/cli/commands/aggregate.py +540 -0
  48. claude_mpm/cli/commands/analyze.py +553 -0
  49. claude_mpm/cli/commands/analyze_code.py +528 -0
  50. claude_mpm/cli/commands/auto_configure.py +1053 -0
  51. claude_mpm/cli/commands/cleanup.py +588 -0
  52. claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
  53. claude_mpm/cli/commands/config.py +586 -0
  54. claude_mpm/cli/commands/configure.py +3253 -0
  55. claude_mpm/cli/commands/configure_agent_display.py +282 -0
  56. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  57. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  58. claude_mpm/cli/commands/configure_models.py +18 -0
  59. claude_mpm/cli/commands/configure_navigation.py +184 -0
  60. claude_mpm/cli/commands/configure_paths.py +104 -0
  61. claude_mpm/cli/commands/configure_persistence.py +254 -0
  62. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  63. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  64. claude_mpm/cli/commands/configure_validators.py +73 -0
  65. claude_mpm/cli/commands/dashboard.py +286 -0
  66. claude_mpm/cli/commands/debug.py +1386 -0
  67. claude_mpm/cli/commands/doctor.py +243 -0
  68. claude_mpm/cli/commands/hook_errors.py +277 -0
  69. claude_mpm/cli/commands/info.py +195 -74
  70. claude_mpm/cli/commands/local_deploy.py +534 -0
  71. claude_mpm/cli/commands/mcp.py +205 -0
  72. claude_mpm/cli/commands/mcp_command_router.py +161 -0
  73. claude_mpm/cli/commands/mcp_config.py +154 -0
  74. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  75. claude_mpm/cli/commands/mcp_external_commands.py +249 -0
  76. claude_mpm/cli/commands/mcp_install_commands.py +346 -0
  77. claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
  78. claude_mpm/cli/commands/mcp_server_commands.py +155 -0
  79. claude_mpm/cli/commands/mcp_setup_external.py +868 -0
  80. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  81. claude_mpm/cli/commands/memory.py +585 -846
  82. claude_mpm/cli/commands/monitor.py +228 -310
  83. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  84. claude_mpm/cli/commands/mpm_init/core.py +759 -0
  85. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  86. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  87. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  88. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  89. claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
  90. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  91. claude_mpm/cli/commands/mpm_init_handler.py +195 -0
  92. claude_mpm/cli/commands/postmortem.py +401 -0
  93. claude_mpm/cli/commands/profile.py +276 -0
  94. claude_mpm/cli/commands/run.py +910 -488
  95. claude_mpm/cli/commands/search.py +458 -0
  96. claude_mpm/cli/commands/skill_source.py +694 -0
  97. claude_mpm/cli/commands/skills.py +1398 -0
  98. claude_mpm/cli/commands/summarize.py +413 -0
  99. claude_mpm/cli/commands/tickets.py +536 -53
  100. claude_mpm/cli/commands/uninstall.py +176 -0
  101. claude_mpm/cli/commands/upgrade.py +152 -0
  102. claude_mpm/cli/commands/verify.py +119 -0
  103. claude_mpm/cli/executor.py +298 -0
  104. claude_mpm/cli/helpers.py +105 -0
  105. claude_mpm/cli/interactive/__init__.py +31 -0
  106. claude_mpm/cli/interactive/agent_wizard.py +1927 -0
  107. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  108. claude_mpm/cli/interactive/skill_selector.py +481 -0
  109. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  110. claude_mpm/cli/parser.py +87 -563
  111. claude_mpm/cli/parsers/__init__.py +35 -0
  112. claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
  113. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  114. claude_mpm/cli/parsers/agents_parser.py +575 -0
  115. claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
  116. claude_mpm/cli/parsers/analyze_parser.py +135 -0
  117. claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
  118. claude_mpm/cli/parsers/base_parser.py +649 -0
  119. claude_mpm/cli/parsers/config_parser.py +208 -0
  120. claude_mpm/cli/parsers/configure_parser.py +138 -0
  121. claude_mpm/cli/parsers/dashboard_parser.py +113 -0
  122. claude_mpm/cli/parsers/debug_parser.py +319 -0
  123. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  124. claude_mpm/cli/parsers/mcp_parser.py +195 -0
  125. claude_mpm/cli/parsers/memory_parser.py +138 -0
  126. claude_mpm/cli/parsers/monitor_parser.py +142 -0
  127. claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
  128. claude_mpm/cli/parsers/profile_parser.py +147 -0
  129. claude_mpm/cli/parsers/run_parser.py +157 -0
  130. claude_mpm/cli/parsers/search_parser.py +245 -0
  131. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  132. claude_mpm/cli/parsers/skills_parser.py +277 -0
  133. claude_mpm/cli/parsers/source_parser.py +138 -0
  134. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  135. claude_mpm/cli/shared/__init__.py +40 -0
  136. claude_mpm/cli/shared/argument_patterns.py +205 -0
  137. claude_mpm/cli/shared/base_command.py +242 -0
  138. claude_mpm/cli/shared/error_handling.py +242 -0
  139. claude_mpm/cli/shared/output_formatters.py +241 -0
  140. claude_mpm/cli/startup.py +1578 -0
  141. claude_mpm/cli/startup_display.py +480 -0
  142. claude_mpm/cli/startup_logging.py +839 -0
  143. claude_mpm/cli/utils.py +136 -47
  144. claude_mpm/cli_module/__init__.py +6 -6
  145. claude_mpm/cli_module/args.py +188 -140
  146. claude_mpm/cli_module/commands.py +79 -70
  147. claude_mpm/cli_module/migration_example.py +42 -64
  148. claude_mpm/commands/__init__.py +14 -0
  149. claude_mpm/commands/mpm-config.md +28 -0
  150. claude_mpm/commands/mpm-doctor.md +20 -0
  151. claude_mpm/commands/mpm-help.md +20 -0
  152. claude_mpm/commands/mpm-init.md +120 -0
  153. claude_mpm/commands/mpm-monitor.md +31 -0
  154. claude_mpm/commands/mpm-organize.md +120 -0
  155. claude_mpm/commands/mpm-postmortem.md +21 -0
  156. claude_mpm/commands/mpm-session-resume.md +30 -0
  157. claude_mpm/commands/mpm-status.md +20 -0
  158. claude_mpm/commands/mpm-ticket-view.md +109 -0
  159. claude_mpm/commands/mpm-version.md +20 -0
  160. claude_mpm/commands/mpm.md +31 -0
  161. claude_mpm/config/__init__.py +42 -2
  162. claude_mpm/config/agent_config.py +402 -0
  163. claude_mpm/config/agent_presets.py +488 -0
  164. claude_mpm/config/agent_sources.py +352 -0
  165. claude_mpm/config/experimental_features.py +217 -0
  166. claude_mpm/config/model_config.py +428 -0
  167. claude_mpm/config/paths.py +258 -0
  168. claude_mpm/config/skill_presets.py +392 -0
  169. claude_mpm/config/skill_sources.py +590 -0
  170. claude_mpm/config/socketio_config.py +125 -83
  171. claude_mpm/constants.py +133 -22
  172. claude_mpm/core/__init__.py +62 -36
  173. claude_mpm/core/agent_name_normalizer.py +71 -73
  174. claude_mpm/core/agent_registry.py +385 -492
  175. claude_mpm/core/agent_session_manager.py +81 -70
  176. claude_mpm/core/api_validator.py +330 -0
  177. claude_mpm/core/base_service.py +159 -122
  178. claude_mpm/core/cache.py +560 -0
  179. claude_mpm/core/claude_runner.py +696 -916
  180. claude_mpm/core/config.py +613 -122
  181. claude_mpm/core/config_aliases.py +74 -73
  182. claude_mpm/core/config_constants.py +314 -0
  183. claude_mpm/core/constants.py +361 -0
  184. claude_mpm/core/container.py +646 -104
  185. claude_mpm/core/enums.py +452 -0
  186. claude_mpm/core/error_handler.py +623 -0
  187. claude_mpm/core/exceptions.py +536 -0
  188. claude_mpm/core/factories.py +105 -109
  189. claude_mpm/core/file_utils.py +764 -0
  190. claude_mpm/core/framework/__init__.py +25 -0
  191. claude_mpm/core/framework/formatters/__init__.py +11 -0
  192. claude_mpm/core/framework/formatters/capability_generator.py +367 -0
  193. claude_mpm/core/framework/formatters/content_formatter.py +278 -0
  194. claude_mpm/core/framework/formatters/context_generator.py +185 -0
  195. claude_mpm/core/framework/loaders/__init__.py +13 -0
  196. claude_mpm/core/framework/loaders/agent_loader.py +213 -0
  197. claude_mpm/core/framework/loaders/file_loader.py +176 -0
  198. claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
  199. claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
  200. claude_mpm/core/framework/processors/__init__.py +11 -0
  201. claude_mpm/core/framework/processors/memory_processor.py +230 -0
  202. claude_mpm/core/framework/processors/metadata_processor.py +146 -0
  203. claude_mpm/core/framework/processors/template_processor.py +244 -0
  204. claude_mpm/core/framework_loader.py +485 -414
  205. claude_mpm/core/hook_error_memory.py +381 -0
  206. claude_mpm/core/hook_manager.py +246 -86
  207. claude_mpm/core/hook_performance_config.py +147 -0
  208. claude_mpm/core/injectable_service.py +72 -63
  209. claude_mpm/core/instruction_reinforcement_hook.py +267 -0
  210. claude_mpm/core/interactive_session.py +670 -0
  211. claude_mpm/core/interfaces.py +570 -164
  212. claude_mpm/core/lazy.py +467 -0
  213. claude_mpm/core/log_manager.py +707 -0
  214. claude_mpm/core/logger.py +295 -134
  215. claude_mpm/core/logging_config.py +474 -0
  216. claude_mpm/core/logging_utils.py +520 -0
  217. claude_mpm/core/minimal_framework_loader.py +24 -22
  218. claude_mpm/core/mixins.py +30 -29
  219. claude_mpm/core/oneshot_session.py +594 -0
  220. claude_mpm/core/optimized_agent_loader.py +479 -0
  221. claude_mpm/core/optimized_startup.py +554 -0
  222. claude_mpm/core/output_style_manager.py +491 -0
  223. claude_mpm/core/pm_hook_interceptor.py +197 -82
  224. claude_mpm/core/protocols/__init__.py +23 -0
  225. claude_mpm/core/protocols/runner_protocol.py +103 -0
  226. claude_mpm/core/protocols/session_protocol.py +131 -0
  227. claude_mpm/core/service_registry.py +153 -116
  228. claude_mpm/core/session_manager.py +179 -64
  229. claude_mpm/core/shared/__init__.py +17 -0
  230. claude_mpm/core/shared/config_loader.py +326 -0
  231. claude_mpm/core/shared/path_resolver.py +281 -0
  232. claude_mpm/core/shared/singleton_manager.py +221 -0
  233. claude_mpm/core/socketio_pool.py +400 -137
  234. claude_mpm/core/system_context.py +38 -0
  235. claude_mpm/core/tool_access_control.py +64 -57
  236. claude_mpm/core/types.py +307 -0
  237. claude_mpm/core/typing_utils.py +553 -0
  238. claude_mpm/core/unified_agent_registry.py +969 -0
  239. claude_mpm/core/unified_config.py +612 -0
  240. claude_mpm/core/unified_paths.py +958 -0
  241. claude_mpm/dashboard/__init__.py +12 -0
  242. claude_mpm/dashboard/api/simple_directory.py +261 -0
  243. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  244. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
  245. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
  246. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
  247. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
  248. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
  249. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
  250. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
  251. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
  252. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
  253. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
  254. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  255. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
  256. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
  257. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
  258. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
  259. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
  260. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
  261. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
  262. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
  263. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
  264. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
  265. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
  266. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
  267. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
  268. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  269. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
  270. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
  271. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  272. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
  273. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
  274. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
  275. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
  276. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
  277. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
  278. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
  279. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
  280. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
  281. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  282. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
  283. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
  284. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
  285. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
  286. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
  287. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
  288. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
  289. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
  290. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
  291. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
  292. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  293. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
  294. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
  295. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
  296. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
  297. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
  298. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
  299. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
  300. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
  301. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
  302. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
  303. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
  304. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
  305. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
  306. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
  307. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
  308. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  309. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  310. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  311. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  312. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  313. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  314. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  315. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  316. claude_mpm/experimental/__init__.py +10 -0
  317. claude_mpm/experimental/cli_enhancements.py +104 -89
  318. claude_mpm/generators/__init__.py +1 -1
  319. claude_mpm/generators/agent_profile_generator.py +76 -66
  320. claude_mpm/hooks/__init__.py +37 -1
  321. claude_mpm/hooks/base_hook.py +37 -32
  322. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  323. claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
  324. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  325. claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
  326. claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
  327. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
  328. claude_mpm/hooks/claude_hooks/installer.py +806 -0
  329. claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
  330. claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
  331. claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
  332. claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
  333. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
  334. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  335. claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
  336. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  337. claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
  338. claude_mpm/hooks/failure_learning/__init__.py +54 -0
  339. claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
  340. claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
  341. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
  342. claude_mpm/hooks/instruction_reinforcement.py +301 -0
  343. claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
  344. claude_mpm/hooks/kuzu_memory_hook.py +386 -0
  345. claude_mpm/hooks/kuzu_response_hook.py +179 -0
  346. claude_mpm/hooks/memory_integration_hook.py +201 -107
  347. claude_mpm/hooks/session_resume_hook.py +121 -0
  348. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  349. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  350. claude_mpm/hooks/tool_call_interceptor.py +92 -76
  351. claude_mpm/hooks/validation_hooks.py +62 -54
  352. claude_mpm/init.py +518 -83
  353. claude_mpm/models/__init__.py +9 -9
  354. claude_mpm/models/agent_definition.py +40 -23
  355. claude_mpm/models/agent_session.py +538 -0
  356. claude_mpm/models/git_repository.py +198 -0
  357. claude_mpm/models/resume_log.py +340 -0
  358. claude_mpm/schemas/__init__.py +12 -0
  359. claude_mpm/scripts/__init__.py +15 -0
  360. claude_mpm/scripts/claude-hook-handler.sh +227 -0
  361. claude_mpm/scripts/launch_monitor.py +165 -0
  362. claude_mpm/scripts/mpm_doctor.py +322 -0
  363. claude_mpm/scripts/socketio_daemon.py +189 -200
  364. claude_mpm/scripts/start_activity_logging.py +91 -0
  365. claude_mpm/services/__init__.py +208 -39
  366. claude_mpm/services/agent_capabilities_service.py +266 -0
  367. claude_mpm/services/agents/__init__.py +89 -0
  368. claude_mpm/services/agents/agent_builder.py +514 -0
  369. claude_mpm/services/agents/agent_preset_service.py +238 -0
  370. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  371. claude_mpm/services/agents/agent_review_service.py +280 -0
  372. claude_mpm/services/agents/agent_selection_service.py +484 -0
  373. claude_mpm/services/agents/auto_config_manager.py +796 -0
  374. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  375. claude_mpm/services/agents/cache_git_manager.py +621 -0
  376. claude_mpm/services/agents/deployment/__init__.py +21 -0
  377. claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
  378. claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
  379. claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
  380. claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
  381. claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
  382. claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
  383. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
  384. claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
  385. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
  386. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
  387. claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
  388. claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
  389. claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
  390. claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
  391. claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
  392. claude_mpm/services/agents/deployment/agent_template_builder.py +1377 -0
  393. claude_mpm/services/agents/deployment/agent_validator.py +376 -0
  394. claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
  395. claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
  396. claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
  397. claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
  398. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  399. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  400. claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
  401. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  402. claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
  403. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  404. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  405. claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
  406. claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -0
  407. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  408. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  409. claude_mpm/services/agents/deployment/facade/deployment_executor.py +70 -0
  410. claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
  411. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  412. claude_mpm/services/agents/deployment/interface_adapter.py +226 -0
  413. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  414. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  415. claude_mpm/services/agents/deployment/local_template_deployment.py +362 -0
  416. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -0
  417. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  418. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  419. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +162 -0
  420. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  421. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  422. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +240 -0
  423. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
  424. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
  425. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
  426. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
  427. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  428. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
  429. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  430. claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
  431. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
  432. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -0
  433. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  434. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  435. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  436. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  437. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  438. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  439. claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
  440. claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
  441. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  442. claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
  443. claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
  444. claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
  445. claude_mpm/services/agents/deployment/validation/__init__.py +21 -0
  446. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  447. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  448. claude_mpm/services/agents/deployment/validation/template_validator.py +319 -0
  449. claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
  450. claude_mpm/services/agents/git_source_manager.py +682 -0
  451. claude_mpm/services/agents/loading/__init__.py +11 -0
  452. claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
  453. claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
  454. claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
  455. claude_mpm/services/agents/local_template_manager.py +784 -0
  456. claude_mpm/services/agents/management/__init__.py +9 -0
  457. claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
  458. claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
  459. claude_mpm/services/agents/memory/__init__.py +22 -0
  460. claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
  461. claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
  462. claude_mpm/services/agents/memory/content_manager.py +470 -0
  463. claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
  464. claude_mpm/services/agents/memory/memory_file_service.py +129 -0
  465. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  466. claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
  467. claude_mpm/services/agents/memory/template_generator.py +83 -0
  468. claude_mpm/services/agents/observers.py +547 -0
  469. claude_mpm/services/agents/recommender.py +617 -0
  470. claude_mpm/services/agents/registry/__init__.py +30 -0
  471. claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
  472. claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
  473. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  474. claude_mpm/services/agents/sources/__init__.py +13 -0
  475. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  476. claude_mpm/services/agents/sources/git_source_sync_service.py +1205 -0
  477. claude_mpm/services/agents/startup_sync.py +262 -0
  478. claude_mpm/services/agents/toolchain_detector.py +478 -0
  479. claude_mpm/services/analysis/__init__.py +35 -0
  480. claude_mpm/services/analysis/clone_detector.py +1030 -0
  481. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  482. claude_mpm/services/analysis/postmortem_service.py +765 -0
  483. claude_mpm/services/async_session_logger.py +665 -0
  484. claude_mpm/services/claude_session_logger.py +321 -0
  485. claude_mpm/services/cli/__init__.py +18 -0
  486. claude_mpm/services/cli/agent_cleanup_service.py +408 -0
  487. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  488. claude_mpm/services/cli/agent_listing_service.py +463 -0
  489. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  490. claude_mpm/services/cli/agent_validation_service.py +590 -0
  491. claude_mpm/services/cli/memory_crud_service.py +622 -0
  492. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  493. claude_mpm/services/cli/resume_service.py +617 -0
  494. claude_mpm/services/cli/session_manager.py +604 -0
  495. claude_mpm/services/cli/session_pause_manager.py +504 -0
  496. claude_mpm/services/cli/session_resume_helper.py +372 -0
  497. claude_mpm/services/cli/startup_checker.py +362 -0
  498. claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
  499. claude_mpm/services/command_deployment_service.py +446 -0
  500. claude_mpm/services/command_handler_service.py +221 -0
  501. claude_mpm/services/communication/__init__.py +22 -0
  502. claude_mpm/services/core/__init__.py +108 -0
  503. claude_mpm/services/core/base.py +269 -0
  504. claude_mpm/services/core/cache_manager.py +309 -0
  505. claude_mpm/services/core/interfaces/__init__.py +273 -0
  506. claude_mpm/services/core/interfaces/agent.py +514 -0
  507. claude_mpm/services/core/interfaces/communication.py +316 -0
  508. claude_mpm/services/core/interfaces/health.py +169 -0
  509. claude_mpm/services/core/interfaces/infrastructure.py +357 -0
  510. claude_mpm/services/core/interfaces/model.py +281 -0
  511. claude_mpm/services/core/interfaces/process.py +372 -0
  512. claude_mpm/services/core/interfaces/project.py +121 -0
  513. claude_mpm/services/core/interfaces/restart.py +307 -0
  514. claude_mpm/services/core/interfaces/service.py +405 -0
  515. claude_mpm/services/core/interfaces/stability.py +260 -0
  516. claude_mpm/services/core/interfaces.py +81 -0
  517. claude_mpm/services/core/memory_manager.py +682 -0
  518. claude_mpm/services/core/models/__init__.py +70 -0
  519. claude_mpm/services/core/models/agent_config.py +384 -0
  520. claude_mpm/services/core/models/health.py +162 -0
  521. claude_mpm/services/core/models/process.py +239 -0
  522. claude_mpm/services/core/models/restart.py +302 -0
  523. claude_mpm/services/core/models/stability.py +264 -0
  524. claude_mpm/services/core/models/toolchain.py +306 -0
  525. claude_mpm/services/core/path_resolver.py +517 -0
  526. claude_mpm/services/core/service_container.py +520 -0
  527. claude_mpm/services/core/service_interfaces.py +436 -0
  528. claude_mpm/services/diagnostics/__init__.py +18 -0
  529. claude_mpm/services/diagnostics/checks/__init__.py +38 -0
  530. claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
  531. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  532. claude_mpm/services/diagnostics/checks/base_check.py +60 -0
  533. claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
  534. claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
  535. claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
  536. claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
  537. claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
  538. claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
  539. claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
  540. claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
  541. claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
  542. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  543. claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
  544. claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
  545. claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
  546. claude_mpm/services/diagnostics/models.py +138 -0
  547. claude_mpm/services/event_aggregator.py +582 -0
  548. claude_mpm/services/event_bus/__init__.py +18 -0
  549. claude_mpm/services/event_bus/config.py +186 -0
  550. claude_mpm/services/event_bus/direct_relay.py +312 -0
  551. claude_mpm/services/event_bus/event_bus.py +396 -0
  552. claude_mpm/services/event_bus/relay.py +326 -0
  553. claude_mpm/services/events/__init__.py +44 -0
  554. claude_mpm/services/events/consumers/__init__.py +18 -0
  555. claude_mpm/services/events/consumers/dead_letter.py +306 -0
  556. claude_mpm/services/events/consumers/logging.py +184 -0
  557. claude_mpm/services/events/consumers/metrics.py +241 -0
  558. claude_mpm/services/events/consumers/socketio.py +377 -0
  559. claude_mpm/services/events/core.py +480 -0
  560. claude_mpm/services/events/interfaces.py +214 -0
  561. claude_mpm/services/events/producers/__init__.py +14 -0
  562. claude_mpm/services/events/producers/hook.py +269 -0
  563. claude_mpm/services/events/producers/system.py +329 -0
  564. claude_mpm/services/exceptions.py +433 -353
  565. claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
  566. claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
  567. claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
  568. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
  569. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
  570. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
  571. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
  572. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
  573. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  574. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  575. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  576. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  577. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +5 -4
  578. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  579. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  580. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +26 -30
  581. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
  582. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  583. claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
  584. claude_mpm/services/git/__init__.py +21 -0
  585. claude_mpm/services/git/git_operations_service.py +579 -0
  586. claude_mpm/services/github/__init__.py +21 -0
  587. claude_mpm/services/github/github_cli_service.py +397 -0
  588. claude_mpm/services/hook_installer_service.py +506 -0
  589. claude_mpm/services/hook_service.py +159 -111
  590. claude_mpm/services/infrastructure/__init__.py +52 -0
  591. claude_mpm/services/infrastructure/context_preservation.py +569 -0
  592. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  593. claude_mpm/services/infrastructure/logging.py +209 -0
  594. claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
  595. claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
  596. claude_mpm/services/infrastructure/monitoring/base.py +122 -0
  597. claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
  598. claude_mpm/services/infrastructure/monitoring/network.py +219 -0
  599. claude_mpm/services/infrastructure/monitoring/process.py +343 -0
  600. claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
  601. claude_mpm/services/infrastructure/monitoring/service.py +368 -0
  602. claude_mpm/services/infrastructure/monitoring.py +71 -0
  603. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  604. claude_mpm/services/instructions/__init__.py +9 -0
  605. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  606. claude_mpm/services/local_ops/__init__.py +155 -0
  607. claude_mpm/services/local_ops/crash_detector.py +257 -0
  608. claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
  609. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  610. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  611. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  612. claude_mpm/services/local_ops/health_manager.py +427 -0
  613. claude_mpm/services/local_ops/log_monitor.py +396 -0
  614. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  615. claude_mpm/services/local_ops/process_manager.py +595 -0
  616. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  617. claude_mpm/services/local_ops/restart_manager.py +401 -0
  618. claude_mpm/services/local_ops/restart_policy.py +387 -0
  619. claude_mpm/services/local_ops/state_manager.py +372 -0
  620. claude_mpm/services/local_ops/unified_manager.py +600 -0
  621. claude_mpm/services/mcp_config_manager.py +1542 -0
  622. claude_mpm/services/mcp_service_verifier.py +732 -0
  623. claude_mpm/services/memory/__init__.py +19 -0
  624. claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
  625. claude_mpm/services/memory/cache/__init__.py +14 -0
  626. claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
  627. claude_mpm/services/memory/cache/simple_cache.py +331 -0
  628. claude_mpm/services/memory/failure_tracker.py +578 -0
  629. claude_mpm/services/memory/indexed_memory.py +648 -0
  630. claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
  631. claude_mpm/services/memory/router.py +951 -0
  632. claude_mpm/services/memory_hook_service.py +470 -0
  633. claude_mpm/services/model/__init__.py +147 -0
  634. claude_mpm/services/model/base_provider.py +365 -0
  635. claude_mpm/services/model/claude_provider.py +412 -0
  636. claude_mpm/services/model/model_router.py +452 -0
  637. claude_mpm/services/model/ollama_provider.py +415 -0
  638. claude_mpm/services/monitor/__init__.py +20 -0
  639. claude_mpm/services/monitor/daemon.py +698 -0
  640. claude_mpm/services/monitor/daemon_manager.py +1076 -0
  641. claude_mpm/services/monitor/event_emitter.py +350 -0
  642. claude_mpm/services/monitor/handlers/__init__.py +21 -0
  643. claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
  644. claude_mpm/services/monitor/handlers/dashboard.py +299 -0
  645. claude_mpm/services/monitor/handlers/file.py +264 -0
  646. claude_mpm/services/monitor/handlers/hooks.py +512 -0
  647. claude_mpm/services/monitor/management/__init__.py +18 -0
  648. claude_mpm/services/monitor/management/health.py +124 -0
  649. claude_mpm/services/monitor/management/lifecycle.py +730 -0
  650. claude_mpm/services/monitor/server.py +1493 -0
  651. claude_mpm/services/monitor_build_service.py +349 -0
  652. claude_mpm/services/native_agent_converter.py +356 -0
  653. claude_mpm/services/orphan_detection.py +786 -0
  654. claude_mpm/services/pm_skills_deployer.py +711 -0
  655. claude_mpm/services/port_manager.py +597 -0
  656. claude_mpm/services/pr/__init__.py +14 -0
  657. claude_mpm/services/pr/pr_template_service.py +329 -0
  658. claude_mpm/services/profile_manager.py +337 -0
  659. claude_mpm/services/project/__init__.py +44 -0
  660. claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
  661. claude_mpm/services/project/analyzer_v2.py +566 -0
  662. claude_mpm/services/project/architecture_analyzer.py +461 -0
  663. claude_mpm/services/project/archive_manager.py +1045 -0
  664. claude_mpm/services/project/dependency_analyzer.py +462 -0
  665. claude_mpm/services/project/detection_strategies.py +719 -0
  666. claude_mpm/services/project/documentation_manager.py +554 -0
  667. claude_mpm/services/project/enhanced_analyzer.py +572 -0
  668. claude_mpm/services/project/language_analyzer.py +265 -0
  669. claude_mpm/services/project/metrics_collector.py +407 -0
  670. claude_mpm/services/project/project_organizer.py +1009 -0
  671. claude_mpm/services/project/registry.py +636 -0
  672. claude_mpm/services/project/toolchain_analyzer.py +583 -0
  673. claude_mpm/services/project_port_allocator.py +596 -0
  674. claude_mpm/services/recovery_manager.py +293 -240
  675. claude_mpm/services/response_tracker.py +267 -0
  676. claude_mpm/services/runner_configuration_service.py +605 -0
  677. claude_mpm/services/self_upgrade_service.py +608 -0
  678. claude_mpm/services/session_management_service.py +314 -0
  679. claude_mpm/services/session_manager.py +380 -0
  680. claude_mpm/services/shared/__init__.py +21 -0
  681. claude_mpm/services/shared/async_service_base.py +216 -0
  682. claude_mpm/services/shared/config_service_base.py +301 -0
  683. claude_mpm/services/shared/lifecycle_service_base.py +308 -0
  684. claude_mpm/services/shared/manager_base.py +315 -0
  685. claude_mpm/services/shared/service_factory.py +309 -0
  686. claude_mpm/services/skills/__init__.py +21 -0
  687. claude_mpm/services/skills/git_skill_source_manager.py +1340 -0
  688. claude_mpm/services/skills/selective_skill_deployer.py +743 -0
  689. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  690. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  691. claude_mpm/services/skills_config.py +547 -0
  692. claude_mpm/services/skills_deployer.py +1168 -0
  693. claude_mpm/services/socketio/__init__.py +25 -0
  694. claude_mpm/services/socketio/client_proxy.py +229 -0
  695. claude_mpm/services/socketio/dashboard_server.py +362 -0
  696. claude_mpm/services/socketio/event_normalizer.py +798 -0
  697. claude_mpm/services/socketio/handlers/__init__.py +30 -0
  698. claude_mpm/services/socketio/handlers/base.py +136 -0
  699. claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
  700. claude_mpm/services/socketio/handlers/connection.py +643 -0
  701. claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
  702. claude_mpm/services/socketio/handlers/file.py +263 -0
  703. claude_mpm/services/socketio/handlers/git.py +962 -0
  704. claude_mpm/services/socketio/handlers/hook.py +211 -0
  705. claude_mpm/services/socketio/handlers/memory.py +26 -0
  706. claude_mpm/services/socketio/handlers/project.py +24 -0
  707. claude_mpm/services/socketio/handlers/registry.py +214 -0
  708. claude_mpm/services/socketio/migration_utils.py +343 -0
  709. claude_mpm/services/socketio/monitor_client.py +364 -0
  710. claude_mpm/services/socketio/server/__init__.py +18 -0
  711. claude_mpm/services/socketio/server/broadcaster.py +569 -0
  712. claude_mpm/services/socketio/server/connection_manager.py +579 -0
  713. claude_mpm/services/socketio/server/core.py +1079 -0
  714. claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
  715. claude_mpm/services/socketio/server/main.py +501 -0
  716. claude_mpm/services/socketio_client_manager.py +173 -143
  717. claude_mpm/services/socketio_server.py +38 -1657
  718. claude_mpm/services/subprocess_launcher_service.py +322 -0
  719. claude_mpm/services/system_instructions_service.py +270 -0
  720. claude_mpm/services/ticket_manager.py +25 -209
  721. claude_mpm/services/ticket_services/__init__.py +26 -0
  722. claude_mpm/services/ticket_services/crud_service.py +328 -0
  723. claude_mpm/services/ticket_services/formatter_service.py +290 -0
  724. claude_mpm/services/ticket_services/search_service.py +324 -0
  725. claude_mpm/services/ticket_services/validation_service.py +303 -0
  726. claude_mpm/services/ticket_services/workflow_service.py +244 -0
  727. claude_mpm/services/unified/__init__.py +65 -0
  728. claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
  729. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
  730. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
  731. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
  732. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
  733. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
  734. claude_mpm/services/unified/config_strategies/__init__.py +175 -0
  735. claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
  736. claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
  737. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
  738. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
  739. claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
  740. claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
  741. claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
  742. claude_mpm/services/unified/deployment_strategies/base.py +553 -0
  743. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
  744. claude_mpm/services/unified/deployment_strategies/local.py +607 -0
  745. claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
  746. claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
  747. claude_mpm/services/unified/interfaces.py +475 -0
  748. claude_mpm/services/unified/migration.py +509 -0
  749. claude_mpm/services/unified/strategies.py +534 -0
  750. claude_mpm/services/unified/unified_analyzer.py +542 -0
  751. claude_mpm/services/unified/unified_config.py +691 -0
  752. claude_mpm/services/unified/unified_deployment.py +466 -0
  753. claude_mpm/services/utility_service.py +280 -0
  754. claude_mpm/services/version_control/__init__.py +34 -37
  755. claude_mpm/services/version_control/branch_strategy.py +26 -17
  756. claude_mpm/services/version_control/conflict_resolution.py +52 -36
  757. claude_mpm/services/version_control/git_operations.py +183 -49
  758. claude_mpm/services/version_control/semantic_versioning.py +172 -61
  759. claude_mpm/services/version_control/version_parser.py +546 -0
  760. claude_mpm/services/version_service.py +379 -0
  761. claude_mpm/services/visualization/__init__.py +15 -0
  762. claude_mpm/services/visualization/mermaid_generator.py +937 -0
  763. claude_mpm/skills/__init__.py +42 -0
  764. claude_mpm/skills/agent_skills_injector.py +324 -0
  765. claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
  766. claude_mpm/skills/bundled/__init__.py +6 -0
  767. claude_mpm/skills/bundled/api-documentation.md +393 -0
  768. claude_mpm/skills/bundled/async-testing.md +571 -0
  769. claude_mpm/skills/bundled/code-review.md +143 -0
  770. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  771. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  772. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  773. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  774. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  775. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  776. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  777. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  778. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  779. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  780. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  781. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  782. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  783. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  784. claude_mpm/skills/bundled/database-migration.md +199 -0
  785. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  786. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  787. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  788. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  789. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  790. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  791. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  792. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  793. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  794. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  795. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  796. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  797. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  798. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  799. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  800. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  801. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  802. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  803. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  804. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  805. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  806. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  807. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  808. claude_mpm/skills/bundled/git-workflow.md +414 -0
  809. claude_mpm/skills/bundled/imagemagick.md +204 -0
  810. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  811. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  812. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  813. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  814. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  815. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  816. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  817. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  818. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  819. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  820. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  821. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  822. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  823. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  824. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  825. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  826. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  827. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  828. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  829. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  830. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  831. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  832. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  833. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  834. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
  835. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
  836. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  837. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  838. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  839. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  840. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  841. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  842. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
  843. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
  844. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
  845. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  846. claude_mpm/skills/bundled/pdf.md +141 -0
  847. claude_mpm/skills/bundled/performance-profiling.md +573 -0
  848. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  849. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  850. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  851. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  852. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  853. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  854. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  855. claude_mpm/skills/bundled/pm/pm-bug-reporting/pm-bug-reporting.md +248 -0
  856. claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
  857. claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
  858. claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
  859. claude_mpm/skills/bundled/pm/pm-teaching-mode/SKILL.md +657 -0
  860. claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
  861. claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
  862. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  863. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  864. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  865. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  866. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  867. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  868. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  869. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  870. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  871. claude_mpm/skills/bundled/security-scanning.md +439 -0
  872. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  873. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  874. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  875. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  876. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  877. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  878. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  879. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  880. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  881. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  882. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  883. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  884. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  885. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  886. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  887. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  888. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  889. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  890. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  891. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  892. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  893. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  894. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  895. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  896. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  897. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  898. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  899. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  900. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  901. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  902. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  903. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  904. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  905. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
  906. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
  907. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
  908. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  909. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  910. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
  911. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  912. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  913. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  914. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  915. claude_mpm/skills/bundled/xlsx.md +157 -0
  916. claude_mpm/skills/registry.py +286 -0
  917. claude_mpm/skills/skill_manager.py +405 -0
  918. claude_mpm/skills/skills_registry.py +347 -0
  919. claude_mpm/skills/skills_service.py +739 -0
  920. claude_mpm/storage/__init__.py +9 -0
  921. claude_mpm/storage/state_storage.py +546 -0
  922. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  923. claude_mpm/templates/questions/__init__.py +38 -0
  924. claude_mpm/templates/questions/base.py +193 -0
  925. claude_mpm/templates/questions/pr_strategy.py +311 -0
  926. claude_mpm/templates/questions/project_init.py +385 -0
  927. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  928. claude_mpm/ticket_wrapper.py +2 -2
  929. claude_mpm/tools/__init__.py +10 -0
  930. claude_mpm/tools/__main__.py +208 -0
  931. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  932. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  933. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  934. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  935. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  936. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  937. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  938. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  939. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  940. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  941. claude_mpm/tools/code_tree_builder.py +631 -0
  942. claude_mpm/tools/code_tree_events.py +420 -0
  943. claude_mpm/tools/socketio_debug.py +671 -0
  944. claude_mpm/utils/__init__.py +8 -8
  945. claude_mpm/utils/agent_dependency_loader.py +1189 -0
  946. claude_mpm/utils/agent_filters.py +261 -0
  947. claude_mpm/utils/common.py +544 -0
  948. claude_mpm/utils/config_manager.py +168 -126
  949. claude_mpm/utils/console.py +11 -0
  950. claude_mpm/utils/database_connector.py +298 -0
  951. claude_mpm/utils/dependency_cache.py +373 -0
  952. claude_mpm/utils/dependency_manager.py +60 -59
  953. claude_mpm/utils/dependency_strategies.py +381 -0
  954. claude_mpm/utils/display_helper.py +260 -0
  955. claude_mpm/utils/environment_context.py +313 -0
  956. claude_mpm/utils/error_handler.py +78 -66
  957. claude_mpm/utils/file_utils.py +305 -0
  958. claude_mpm/utils/framework_detection.py +12 -11
  959. claude_mpm/utils/git_analyzer.py +407 -0
  960. claude_mpm/utils/gitignore.py +244 -0
  961. claude_mpm/utils/import_migration_example.py +12 -60
  962. claude_mpm/utils/imports.py +48 -45
  963. claude_mpm/utils/log_cleanup.py +627 -0
  964. claude_mpm/utils/migration.py +372 -0
  965. claude_mpm/utils/path_operations.py +110 -104
  966. claude_mpm/utils/progress.py +387 -0
  967. claude_mpm/utils/robust_installer.py +844 -0
  968. claude_mpm/utils/session_logging.py +121 -0
  969. claude_mpm/utils/structured_questions.py +619 -0
  970. claude_mpm/utils/subprocess_utils.py +343 -0
  971. claude_mpm/validation/__init__.py +1 -1
  972. claude_mpm/validation/agent_validator.py +214 -108
  973. claude_mpm/validation/frontmatter_validator.py +252 -0
  974. claude_mpm-5.4.85.dist-info/METADATA +1023 -0
  975. claude_mpm-5.4.85.dist-info/RECORD +980 -0
  976. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/entry_points.txt +1 -3
  977. claude_mpm-5.4.85.dist-info/licenses/LICENSE +94 -0
  978. claude_mpm-5.4.85.dist-info/licenses/LICENSE-FAQ.md +153 -0
  979. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
  980. claude_mpm/agents/INSTRUCTIONS.md +0 -352
  981. claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
  982. claude_mpm/agents/base_agent_loader.py +0 -529
  983. claude_mpm/agents/schema/agent_schema.json +0 -314
  984. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
  985. claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
  986. claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
  987. claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
  988. claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
  989. claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
  990. claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
  991. claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
  992. claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
  993. claude_mpm/agents/templates/data_engineer.json +0 -110
  994. claude_mpm/agents/templates/documentation.json +0 -109
  995. claude_mpm/agents/templates/engineer.json +0 -113
  996. claude_mpm/agents/templates/ops.json +0 -109
  997. claude_mpm/agents/templates/pm.json +0 -25
  998. claude_mpm/agents/templates/qa.json +0 -111
  999. claude_mpm/agents/templates/research.json +0 -65
  1000. claude_mpm/agents/templates/security.json +0 -113
  1001. claude_mpm/agents/templates/test_integration.json +0 -112
  1002. claude_mpm/agents/templates/version_control.json +0 -107
  1003. claude_mpm/cli/commands/ui.py +0 -57
  1004. claude_mpm/core/simple_runner.py +0 -1046
  1005. claude_mpm/dashboard/open_dashboard.py +0 -34
  1006. claude_mpm/deployment_paths.py +0 -261
  1007. claude_mpm/hooks/builtin/__init__.py +0 -1
  1008. claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
  1009. claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
  1010. claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
  1011. claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
  1012. claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
  1013. claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
  1014. claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
  1015. claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
  1016. claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
  1017. claude_mpm/orchestration/__init__.py +0 -6
  1018. claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
  1019. claude_mpm/orchestration/archive/factory.py +0 -215
  1020. claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
  1021. claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
  1022. claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
  1023. claude_mpm/orchestration/archive/orchestrator.py +0 -501
  1024. claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
  1025. claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
  1026. claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
  1027. claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
  1028. claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
  1029. claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
  1030. claude_mpm/schemas/workflow_validator.py +0 -411
  1031. claude_mpm/services/agent_deployment.py +0 -1534
  1032. claude_mpm/services/agent_lifecycle_manager.py +0 -1169
  1033. claude_mpm/services/agent_memory_manager.py +0 -1415
  1034. claude_mpm/services/agent_registry.py +0 -676
  1035. claude_mpm/services/deployed_agent_discovery.py +0 -226
  1036. claude_mpm/services/framework_agent_loader.py +0 -337
  1037. claude_mpm/services/framework_claude_md_generator.py +0 -621
  1038. claude_mpm/services/health_monitor.py +0 -892
  1039. claude_mpm/services/memory_router.py +0 -538
  1040. claude_mpm/services/parent_directory_manager/__init__.py +0 -577
  1041. claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
  1042. claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
  1043. claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
  1044. claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
  1045. claude_mpm/services/parent_directory_manager/operations.py +0 -186
  1046. claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
  1047. claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
  1048. claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
  1049. claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
  1050. claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
  1051. claude_mpm/services/standalone_socketio_server.py +0 -1300
  1052. claude_mpm/services/ticket_manager_di.py +0 -318
  1053. claude_mpm/services/ticketing_service_original.py +0 -508
  1054. claude_mpm/ui/__init__.py +0 -1
  1055. claude_mpm/ui/rich_terminal_ui.py +0 -295
  1056. claude_mpm/ui/terminal_ui.py +0 -328
  1057. claude_mpm/utils/paths.py +0 -289
  1058. claude_mpm-3.4.10.dist-info/METADATA +0 -183
  1059. claude_mpm-3.4.10.dist-info/RECORD +0 -201
  1060. claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
  1061. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/WHEEL +0 -0
  1062. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1168 @@
1
+ """Skills Deployer Service - Deploy Claude Code skills from GitHub.
2
+
3
+ WHY: Claude Code loads skills at STARTUP ONLY from ~/.claude/skills/ directory.
4
+ This service manages downloading skills from external GitHub repositories and
5
+ deploying them to Claude Code's skills directory with automatic restart warnings.
6
+
7
+ DESIGN DECISIONS:
8
+ - Downloads from https://github.com/bobmatnyc/claude-mpm-skills by default
9
+ - Deploys to ~/.claude/skills/ (Claude Code's directory), NOT project directory
10
+ - Integrates with ToolchainAnalyzer for automatic language detection
11
+ - Handles Claude Code restart requirement (skills only load at startup)
12
+ - Provides filtering by toolchain and categories
13
+ - Graceful error handling with actionable messages
14
+
15
+ ARCHITECTURE:
16
+ 1. GitHub Download: Fetch ZIP archive from repository
17
+ 2. Manifest Parsing: Read skill metadata from manifest.json
18
+ 3. Filtering: Apply toolchain and category filters
19
+ 4. Deployment: Copy skills to ~/.claude/skills/
20
+ 5. Restart Detection: Warn if Claude Code is running
21
+ 6. Cleanup: Remove temporary files
22
+
23
+ References:
24
+ - Research: docs/research/skills-research.md
25
+ - GitHub Repo: https://github.com/bobmatnyc/claude-mpm-skills
26
+ """
27
+
28
+ import json
29
+ import platform
30
+ import shutil
31
+ import subprocess
32
+ from pathlib import Path
33
+ from typing import Any, Dict, List, Optional
34
+
35
+ from claude_mpm.core.mixins import LoggerMixin
36
+ from claude_mpm.services.skills_config import SkillsConfig
37
+
38
+
39
+ class SkillsDeployerService(LoggerMixin):
40
+ """Deploy Claude Code skills from external GitHub repositories.
41
+
42
+ This service:
43
+ - Downloads skills from GitHub repositories
44
+ - Deploys to ~/.claude/skills/ directory
45
+ - Filters by toolchain (python, javascript, rust, etc.)
46
+ - Filters by categories (testing, debugging, web, etc.)
47
+ - Detects Claude Code process and warns about restart requirement
48
+ - Provides deployment summaries and error handling
49
+
50
+ Example:
51
+ >>> deployer = SkillsDeployerService()
52
+ >>> result = deployer.deploy_skills(toolchain=['python'], categories=['testing'])
53
+ >>> print(f"Deployed {result['deployed_count']} skills")
54
+ >>> print(f"Restart Claude Code: {result['restart_required']}")
55
+ """
56
+
57
+ DEFAULT_REPO_URL = "https://github.com/bobmatnyc/claude-mpm-skills"
58
+ CLAUDE_SKILLS_DIR = Path.home() / ".claude" / "skills"
59
+
60
+ def __init__(
61
+ self,
62
+ repo_url: Optional[str] = None,
63
+ toolchain_analyzer: Optional[any] = None,
64
+ ):
65
+ """Initialize Skills Deployer Service.
66
+
67
+ Args:
68
+ repo_url: GitHub repository URL (default: bobmatnyc/claude-mpm-skills)
69
+ toolchain_analyzer: Optional ToolchainAnalyzer for auto-detection
70
+ """
71
+ super().__init__()
72
+ self.repo_url = repo_url or self.DEFAULT_REPO_URL
73
+ self.toolchain_analyzer = toolchain_analyzer
74
+ self.skills_config = SkillsConfig()
75
+
76
+ # Ensure Claude skills directory exists
77
+ self.CLAUDE_SKILLS_DIR.mkdir(parents=True, exist_ok=True)
78
+
79
+ def deploy_skills(
80
+ self,
81
+ collection: Optional[str] = None,
82
+ toolchain: Optional[List[str]] = None,
83
+ categories: Optional[List[str]] = None,
84
+ force: bool = False,
85
+ selective: bool = True,
86
+ project_root: Optional[Path] = None,
87
+ ) -> Dict:
88
+ """Deploy skills from GitHub repository.
89
+
90
+ This is the main entry point for skill deployment. It:
91
+ 1. Downloads skills from GitHub collection
92
+ 2. Parses manifest for metadata
93
+ 3. Filters by toolchain and categories
94
+ 4. (If selective=True) Filters to only agent-referenced skills
95
+ 5. Deploys to ~/.claude/skills/
96
+ 6. Warns about Claude Code restart
97
+
98
+ Args:
99
+ collection: Collection name to deploy from (default: uses default collection)
100
+ toolchain: Filter by toolchain (e.g., ['python', 'javascript'])
101
+ categories: Filter by categories (e.g., ['testing', 'debugging'])
102
+ force: Overwrite existing skills
103
+ selective: If True, only deploy skills referenced by agents (default)
104
+ project_root: Project root directory (for finding agents, auto-detected if None)
105
+
106
+ Returns:
107
+ Dict containing:
108
+ - deployed_count: Number of skills deployed
109
+ - skipped_count: Number of skills skipped
110
+ - errors: List of error messages
111
+ - deployed_skills: List of deployed skill names
112
+ - restart_required: True if Claude Code needs restart
113
+ - restart_instructions: Message about restarting
114
+ - collection: Collection name used for deployment
115
+ - selective_mode: True if selective deployment was used
116
+ - total_available: Total skills available before filtering
117
+
118
+ Example:
119
+ >>> result = deployer.deploy_skills(collection="obra-superpowers")
120
+ >>> result = deployer.deploy_skills(toolchain=['python']) # Uses default
121
+ >>> # Deploy all skills (not just agent-referenced)
122
+ >>> result = deployer.deploy_skills(selective=False)
123
+ >>> if result['restart_required']:
124
+ >>> print(result['restart_instructions'])
125
+ """
126
+ # Determine which collection to use
127
+ collection_name = collection or self.skills_config.get_default_collection()
128
+
129
+ self.logger.info(f"Deploying skills from collection '{collection_name}'")
130
+
131
+ # Step 1: Download skills from GitHub collection
132
+ try:
133
+ skills_data = self._download_from_github(collection_name)
134
+ except Exception as e:
135
+ self.logger.error(f"Failed to download skills: {e}")
136
+ return {
137
+ "deployed_count": 0,
138
+ "skipped_count": 0,
139
+ "errors": [f"Download failed: {e}"],
140
+ "deployed_skills": [],
141
+ "restart_required": False,
142
+ "restart_instructions": "",
143
+ "collection": collection_name,
144
+ }
145
+
146
+ # Step 2: Parse manifest and flatten skills
147
+ manifest = skills_data.get("manifest", {})
148
+ try:
149
+ skills = self._flatten_manifest_skills(manifest)
150
+ except ValueError as e:
151
+ self.logger.error(f"Invalid manifest structure: {e}")
152
+ return {
153
+ "deployed_count": 0,
154
+ "skipped_count": 0,
155
+ "errors": [f"Invalid manifest: {e}"],
156
+ "deployed_skills": [],
157
+ "restart_required": False,
158
+ "restart_instructions": "",
159
+ "collection": collection_name,
160
+ }
161
+
162
+ self.logger.info(f"Found {len(skills)} skills in repository")
163
+
164
+ # Step 3: Filter skills by toolchain and categories
165
+ filtered_skills = self._filter_skills(skills, toolchain, categories)
166
+
167
+ self.logger.info(
168
+ f"After filtering: {len(filtered_skills)} skills to deploy"
169
+ f" (toolchain={toolchain}, categories={categories})"
170
+ )
171
+
172
+ # Step 3.5: Apply selective filtering (only agent-referenced skills)
173
+ total_available = len(filtered_skills)
174
+ if selective:
175
+ # Auto-detect project root if not provided
176
+ if project_root is None:
177
+ # Try to find project root by looking for .claude-mpm directory
178
+ # Start from current directory and walk up
179
+ current = Path.cwd()
180
+ while current != current.parent:
181
+ if (current / ".claude-mpm").exists():
182
+ project_root = current
183
+ break
184
+ current = current.parent
185
+
186
+ # Read skills from configuration.yaml instead of agent frontmatter
187
+ if project_root:
188
+ config_path = Path(project_root) / ".claude-mpm" / "configuration.yaml"
189
+ else:
190
+ # Fallback to current directory's configuration
191
+ config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
192
+
193
+ from claude_mpm.services.skills.selective_skill_deployer import (
194
+ get_required_skills_from_agents,
195
+ get_skills_to_deploy,
196
+ save_agent_skills_to_config,
197
+ )
198
+
199
+ # Check if agent_referenced is empty and needs to be populated
200
+ required_skill_names, source = get_skills_to_deploy(config_path)
201
+
202
+ if not required_skill_names and project_root:
203
+ # agent_referenced is empty, scan deployed agents to populate it
204
+ agents_dir = Path(project_root) / ".claude" / "agents"
205
+ if agents_dir.exists():
206
+ self.logger.info(
207
+ "agent_referenced is empty in configuration.yaml, scanning deployed agents..."
208
+ )
209
+ agent_skills = get_required_skills_from_agents(agents_dir)
210
+ if agent_skills:
211
+ save_agent_skills_to_config(list(agent_skills), config_path)
212
+ self.logger.info(
213
+ f"Populated agent_referenced with {len(agent_skills)} skills from deployed agents"
214
+ )
215
+ # Re-read configuration after update
216
+ required_skill_names, source = get_skills_to_deploy(config_path)
217
+ else:
218
+ self.logger.warning(
219
+ "No skills found in deployed agents - configuration.yaml remains empty"
220
+ )
221
+ else:
222
+ self.logger.warning(
223
+ f"Agents directory not found at {agents_dir} - cannot scan for skills"
224
+ )
225
+
226
+ if required_skill_names:
227
+ # Convert required_skill_names to a set for O(1) lookup
228
+ required_set = set(required_skill_names)
229
+
230
+ # Filter to only required skills
231
+ # Match on: 'name', 'skill_id', or normalized 'source_path'
232
+ # source_path example: "universal/web/api-design-patterns/SKILL.md"
233
+ # normalized: "universal-web-api-design-patterns"
234
+ def skill_matches_requirement(skill):
235
+ # Check basic name and skill_id
236
+ if skill.get("name") in required_set:
237
+ return True
238
+ if skill.get("skill_id") in required_set:
239
+ return True
240
+
241
+ # Check normalized source_path
242
+ source_path = skill.get("source_path", "")
243
+ if source_path:
244
+ # Remove /SKILL.md suffix and replace / with -
245
+ normalized = source_path.replace("/SKILL.md", "").replace(
246
+ "/", "-"
247
+ )
248
+ if normalized in required_set:
249
+ return True
250
+
251
+ return False
252
+
253
+ filtered_skills = [
254
+ s for s in filtered_skills if skill_matches_requirement(s)
255
+ ]
256
+
257
+ self.logger.info(
258
+ f"Selective deployment: {len(filtered_skills)}/{total_available} skills "
259
+ f"(source: {source})"
260
+ )
261
+ else:
262
+ self.logger.warning(
263
+ f"No skills found in configuration at {config_path}. "
264
+ f"Deploying all {total_available} skills."
265
+ )
266
+ else:
267
+ self.logger.info(
268
+ f"Selective mode disabled: deploying all {total_available} skills"
269
+ )
270
+
271
+ # Step 4: Deploy skills
272
+ deployed = []
273
+ skipped = []
274
+ errors = []
275
+
276
+ # Extract normalized skill names for cleanup (needed regardless of deployment outcome)
277
+ # Must match the names used during deployment (normalized from source_path)
278
+ filtered_skills_names = []
279
+ for skill in filtered_skills:
280
+ if isinstance(skill, dict) and "name" in skill:
281
+ source_path = skill.get("source_path", "")
282
+ if source_path:
283
+ # Normalize: "universal/web/api-design-patterns/SKILL.md" -> "universal-web-api-design-patterns"
284
+ normalized = source_path.replace("/SKILL.md", "").replace("/", "-")
285
+ filtered_skills_names.append(normalized)
286
+ else:
287
+ # Fallback to skill name
288
+ filtered_skills_names.append(skill["name"])
289
+
290
+ for skill in filtered_skills:
291
+ try:
292
+ # Validate skill is a dictionary
293
+ if not isinstance(skill, dict):
294
+ self.logger.error(f"Invalid skill format: {skill}")
295
+ errors.append(f"Invalid skill format: {skill}")
296
+ continue
297
+
298
+ result = self._deploy_skill(
299
+ skill, skills_data["temp_dir"], collection_name, force=force
300
+ )
301
+ if result["deployed"]:
302
+ # Use normalized name for reporting
303
+ source_path = skill.get("source_path", "")
304
+ if source_path:
305
+ normalized = source_path.replace("/SKILL.md", "").replace(
306
+ "/", "-"
307
+ )
308
+ deployed.append(normalized)
309
+ else:
310
+ deployed.append(skill["name"])
311
+ elif result["skipped"]:
312
+ # Use normalized name for reporting
313
+ source_path = skill.get("source_path", "")
314
+ if source_path:
315
+ normalized = source_path.replace("/SKILL.md", "").replace(
316
+ "/", "-"
317
+ )
318
+ skipped.append(normalized)
319
+ else:
320
+ skipped.append(skill["name"])
321
+ if result["error"]:
322
+ errors.append(result["error"])
323
+ except Exception as e:
324
+ skill_name = (
325
+ skill.get("name", "unknown")
326
+ if isinstance(skill, dict)
327
+ else "unknown"
328
+ )
329
+ self.logger.error(f"Failed to deploy {skill_name}: {e}")
330
+ errors.append(f"{skill_name}: {e}")
331
+
332
+ # Step 5: Cleanup orphaned skills (always run in selective mode)
333
+ cleanup_result = {"removed_count": 0, "removed_skills": []}
334
+ if selective:
335
+ # Get the set of skills that should remain deployed
336
+ # This is the union of what we just deployed and what was already there
337
+ try:
338
+ from claude_mpm.services.skills.selective_skill_deployer import (
339
+ cleanup_orphan_skills,
340
+ )
341
+
342
+ # Cleanup orphaned skills not referenced by agents
343
+ # This runs even if nothing new was deployed to remove stale skills
344
+ cleanup_result = cleanup_orphan_skills(
345
+ self.CLAUDE_SKILLS_DIR, set(filtered_skills_names)
346
+ )
347
+
348
+ if cleanup_result["removed_count"] > 0:
349
+ self.logger.info(
350
+ f"Removed {cleanup_result['removed_count']} orphaned skills: "
351
+ f"{', '.join(cleanup_result['removed_skills'])}"
352
+ )
353
+ except Exception as e:
354
+ self.logger.warning(f"Failed to cleanup orphaned skills: {e}")
355
+
356
+ # Step 6: Cleanup temp directory
357
+ self._cleanup(skills_data["temp_dir"])
358
+
359
+ # Step 7: Check if Claude Code restart needed
360
+ restart_required = len(deployed) > 0
361
+ restart_instructions = ""
362
+
363
+ if restart_required:
364
+ claude_running = self._is_claude_code_running()
365
+ if claude_running:
366
+ restart_instructions = (
367
+ "⚠️ Claude Code is currently running.\n"
368
+ "Skills are only loaded at STARTUP.\n"
369
+ "Please restart Claude Code for new skills to be available.\n\n"
370
+ "How to restart Claude Code:\n"
371
+ "1. Close all Claude Code windows\n"
372
+ "2. Quit Claude Code completely (Cmd+Q on Mac, Alt+F4 on Windows)\n"
373
+ "3. Re-launch Claude Code\n"
374
+ )
375
+ else:
376
+ restart_instructions = (
377
+ "✓ Claude Code is not currently running.\n"
378
+ "Skills will be available when you launch Claude Code.\n"
379
+ )
380
+
381
+ self.logger.info(
382
+ f"Deployment complete: {len(deployed)} deployed, "
383
+ f"{len(skipped)} skipped, {len(errors)} errors, "
384
+ f"{cleanup_result['removed_count']} orphaned skills removed"
385
+ )
386
+
387
+ return {
388
+ "deployed_count": len(deployed),
389
+ "skipped_count": len(skipped),
390
+ "errors": errors,
391
+ "deployed_skills": deployed,
392
+ "skipped_skills": skipped,
393
+ "restart_required": restart_required,
394
+ "restart_instructions": restart_instructions,
395
+ "collection": collection_name,
396
+ "selective_mode": selective,
397
+ "total_available": total_available,
398
+ "cleanup": cleanup_result,
399
+ }
400
+
401
+ def list_available_skills(self, collection: Optional[str] = None) -> Dict:
402
+ """List all available skills from GitHub repository.
403
+
404
+ Downloads manifest and returns skill metadata grouped by category
405
+ and toolchain.
406
+
407
+ Args:
408
+ collection: Collection name to list from (default: uses default collection)
409
+
410
+ Returns:
411
+ Dict containing:
412
+ - total_skills: Total number of available skills
413
+ - by_category: Skills grouped by category
414
+ - by_toolchain: Skills grouped by toolchain
415
+ - skills: Full list of skill metadata
416
+ - collection: Collection name used
417
+
418
+ Example:
419
+ >>> result = deployer.list_available_skills(collection="obra-superpowers")
420
+ >>> result = deployer.list_available_skills() # Uses default
421
+ >>> print(f"Available: {result['total_skills']} skills")
422
+ >>> for category, skills in result['by_category'].items():
423
+ >>> print(f"{category}: {len(skills)} skills")
424
+ """
425
+ collection_name = collection or self.skills_config.get_default_collection()
426
+
427
+ try:
428
+ skills_data = self._download_from_github(collection_name)
429
+ manifest = skills_data.get("manifest", {})
430
+
431
+ # Flatten skills from manifest (supports both legacy and new structure)
432
+ try:
433
+ skills = self._flatten_manifest_skills(manifest)
434
+ except ValueError as e:
435
+ self.logger.error(f"Failed to parse manifest: {e}")
436
+ return {
437
+ "total_skills": 0,
438
+ "by_category": {},
439
+ "by_toolchain": {},
440
+ "skills": [],
441
+ "error": str(e),
442
+ }
443
+
444
+ # Group by category
445
+ by_category = {}
446
+ for skill in skills:
447
+ if not isinstance(skill, dict):
448
+ continue
449
+ category = skill.get("category", "uncategorized")
450
+ if category not in by_category:
451
+ by_category[category] = []
452
+ by_category[category].append(skill)
453
+
454
+ # Group by toolchain
455
+ by_toolchain = {}
456
+ for skill in skills:
457
+ if not isinstance(skill, dict):
458
+ continue
459
+ toolchains = skill.get("toolchain", [])
460
+ if isinstance(toolchains, str):
461
+ toolchains = [toolchains]
462
+ elif not isinstance(toolchains, list):
463
+ toolchains = []
464
+
465
+ for toolchain in toolchains:
466
+ if toolchain not in by_toolchain:
467
+ by_toolchain[toolchain] = []
468
+ by_toolchain[toolchain].append(skill)
469
+
470
+ # Cleanup
471
+ self._cleanup(skills_data["temp_dir"])
472
+
473
+ return {
474
+ "total_skills": len(skills),
475
+ "by_category": by_category,
476
+ "by_toolchain": by_toolchain,
477
+ "skills": skills,
478
+ "collection": collection_name,
479
+ }
480
+
481
+ except Exception as e:
482
+ self.logger.error(f"Failed to list available skills: {e}")
483
+ return {
484
+ "total_skills": 0,
485
+ "by_category": {},
486
+ "by_toolchain": {},
487
+ "skills": [],
488
+ "error": str(e),
489
+ "collection": collection_name,
490
+ }
491
+
492
+ def check_deployed_skills(self) -> Dict:
493
+ """Check which skills are currently deployed.
494
+
495
+ Scans ~/.claude/skills/ directory for deployed skills.
496
+
497
+ Returns:
498
+ Dict containing:
499
+ - deployed_count: Number of deployed skills
500
+ - skills: List of deployed skill names with paths
501
+ - claude_skills_dir: Path to Claude skills directory
502
+
503
+ Example:
504
+ >>> result = deployer.check_deployed_skills()
505
+ >>> print(f"Currently deployed: {result['deployed_count']} skills")
506
+ """
507
+ deployed_skills = []
508
+
509
+ if self.CLAUDE_SKILLS_DIR.exists():
510
+ for skill_dir in self.CLAUDE_SKILLS_DIR.iterdir():
511
+ if skill_dir.is_dir() and not skill_dir.name.startswith("."):
512
+ # Check for SKILL.md
513
+ skill_md = skill_dir / "SKILL.md"
514
+ if skill_md.exists():
515
+ deployed_skills.append(
516
+ {"name": skill_dir.name, "path": str(skill_dir)}
517
+ )
518
+
519
+ return {
520
+ "deployed_count": len(deployed_skills),
521
+ "skills": deployed_skills,
522
+ "claude_skills_dir": str(self.CLAUDE_SKILLS_DIR),
523
+ }
524
+
525
+ def remove_skills(self, skill_names: Optional[List[str]] = None) -> Dict:
526
+ """Remove deployed skills.
527
+
528
+ Args:
529
+ skill_names: List of skill names to remove, or None to remove all
530
+
531
+ Returns:
532
+ Dict containing:
533
+ - removed_count: Number of skills removed
534
+ - removed_skills: List of removed skill names
535
+ - errors: List of error messages
536
+
537
+ Example:
538
+ >>> # Remove specific skills
539
+ >>> result = deployer.remove_skills(['test-skill', 'debug-skill'])
540
+ >>> # Remove all skills
541
+ >>> result = deployer.remove_skills()
542
+ """
543
+ removed = []
544
+ errors = []
545
+
546
+ if not self.CLAUDE_SKILLS_DIR.exists():
547
+ return {
548
+ "removed_count": 0,
549
+ "removed_skills": [],
550
+ "errors": ["Claude skills directory does not exist"],
551
+ }
552
+
553
+ # Get all skills if no specific names provided
554
+ if skill_names is None:
555
+ skill_names = [
556
+ d.name
557
+ for d in self.CLAUDE_SKILLS_DIR.iterdir()
558
+ if d.is_dir() and not d.name.startswith(".")
559
+ ]
560
+
561
+ for skill_name in skill_names:
562
+ skill_dir = self.CLAUDE_SKILLS_DIR / skill_name
563
+
564
+ if not skill_dir.exists():
565
+ errors.append(f"Skill not found: {skill_name}")
566
+ continue
567
+
568
+ try:
569
+ # Security: Validate path is within CLAUDE_SKILLS_DIR
570
+ if not self._validate_safe_path(self.CLAUDE_SKILLS_DIR, skill_dir):
571
+ raise ValueError(f"Path traversal attempt detected: {skill_dir}")
572
+
573
+ # Remove skill directory
574
+ if skill_dir.is_symlink():
575
+ self.logger.warning(f"Removing symlink: {skill_dir}")
576
+ skill_dir.unlink()
577
+ else:
578
+ shutil.rmtree(skill_dir)
579
+
580
+ removed.append(skill_name)
581
+ self.logger.info(f"Removed skill: {skill_name}")
582
+
583
+ # Untrack skill from deployment index
584
+ from claude_mpm.services.skills.selective_skill_deployer import (
585
+ untrack_skill,
586
+ )
587
+
588
+ untrack_skill(self.CLAUDE_SKILLS_DIR, skill_name)
589
+
590
+ except Exception as e:
591
+ self.logger.error(f"Failed to remove {skill_name}: {e}")
592
+ errors.append(f"{skill_name}: {e}")
593
+
594
+ return {
595
+ "removed_count": len(removed),
596
+ "removed_skills": removed,
597
+ "errors": errors,
598
+ }
599
+
600
+ def _download_from_github(self, collection_name: str) -> Dict:
601
+ """Download skills repository from GitHub using git clone/pull.
602
+
603
+ Logic:
604
+ 1. Get collection config from SkillsConfig
605
+ 2. Determine target directory: ~/.claude/skills/{collection_name}/
606
+ 3. Check if directory exists:
607
+ - Exists + is git repo → git pull (update)
608
+ - Exists + not git repo → error (manual cleanup needed)
609
+ - Not exists → git clone (first install)
610
+ 4. Parse manifest.json from collection
611
+ 5. Update last_update timestamp in config
612
+ 6. Return skills data
613
+
614
+ Args:
615
+ collection_name: Name of collection to download
616
+
617
+ Returns:
618
+ Dict containing:
619
+ - temp_dir: Path to collection directory (not temp, but kept for compatibility)
620
+ - manifest: Parsed manifest.json
621
+ - repo_dir: Path to repository directory
622
+
623
+ Raises:
624
+ ValueError: If collection not found or disabled
625
+ Exception: If git operations fail
626
+ """
627
+ # Get collection configuration
628
+ collection_config = self.skills_config.get_collection(collection_name)
629
+ if not collection_config:
630
+ raise ValueError(
631
+ f"Collection '{collection_name}' not found. "
632
+ f"Use 'claude-mpm skills collection add' to add it."
633
+ )
634
+
635
+ if not collection_config.get("enabled", True):
636
+ raise ValueError(
637
+ f"Collection '{collection_name}' is disabled. "
638
+ f"Use 'claude-mpm skills collection enable {collection_name}' to enable it."
639
+ )
640
+
641
+ repo_url = collection_config["url"]
642
+ target_dir = self.CLAUDE_SKILLS_DIR / collection_name
643
+
644
+ self.logger.info(f"Processing collection '{collection_name}' from {repo_url}")
645
+
646
+ # Check if directory exists and handle accordingly
647
+ if target_dir.exists():
648
+ git_dir = target_dir / ".git"
649
+
650
+ if git_dir.exists():
651
+ # Update existing: git pull
652
+ self.logger.info(
653
+ f"Updating existing collection '{collection_name}' at {target_dir}"
654
+ )
655
+ try:
656
+ result = subprocess.run(
657
+ ["git", "pull"],
658
+ cwd=target_dir,
659
+ capture_output=True,
660
+ text=True,
661
+ check=True,
662
+ timeout=60,
663
+ )
664
+ self.logger.debug(f"Git pull output: {result.stdout}")
665
+
666
+ except subprocess.CalledProcessError as e:
667
+ raise Exception(
668
+ f"Failed to update collection '{collection_name}': {e.stderr}"
669
+ ) from e
670
+ except subprocess.TimeoutExpired as e:
671
+ raise Exception(
672
+ f"Git pull timed out for collection '{collection_name}'"
673
+ ) from e
674
+ else:
675
+ # Directory exists but not a git repo - error
676
+ raise ValueError(
677
+ f"Directory {target_dir} exists but is not a git repository. "
678
+ f"Please remove it manually and try again:\n"
679
+ f" rm -rf {target_dir}"
680
+ )
681
+ else:
682
+ # First install: git clone
683
+ self.logger.info(
684
+ f"Installing new collection '{collection_name}' to {target_dir}"
685
+ )
686
+ try:
687
+ result = subprocess.run(
688
+ ["git", "clone", repo_url, str(target_dir)],
689
+ capture_output=True,
690
+ text=True,
691
+ check=True,
692
+ timeout=120,
693
+ )
694
+ self.logger.debug(f"Git clone output: {result.stdout}")
695
+
696
+ except subprocess.CalledProcessError as e:
697
+ raise Exception(
698
+ f"Failed to clone collection '{collection_name}': {e.stderr}"
699
+ ) from e
700
+ except subprocess.TimeoutExpired as e:
701
+ raise Exception(
702
+ f"Git clone timed out for collection '{collection_name}'"
703
+ ) from e
704
+
705
+ # Update last_update timestamp
706
+ self.skills_config.update_collection_timestamp(collection_name)
707
+
708
+ # Parse manifest.json
709
+ manifest_path = target_dir / "manifest.json"
710
+ if not manifest_path.exists():
711
+ raise Exception(
712
+ f"manifest.json not found in collection '{collection_name}' at {target_dir}"
713
+ )
714
+
715
+ try:
716
+ with open(manifest_path, encoding="utf-8") as f:
717
+ manifest = json.load(f)
718
+ except json.JSONDecodeError as e:
719
+ raise Exception(
720
+ f"Invalid manifest.json in collection '{collection_name}': {e}"
721
+ ) from e
722
+
723
+ self.logger.info(
724
+ f"Successfully loaded collection '{collection_name}' from {target_dir}"
725
+ )
726
+
727
+ # Return data in same format as before for compatibility
728
+ # Note: temp_dir is now the persistent collection directory
729
+ return {"temp_dir": target_dir, "manifest": manifest, "repo_dir": target_dir}
730
+
731
+ def _flatten_manifest_skills(self, manifest: Dict) -> List[Dict]:
732
+ """Flatten skills from manifest, supporting both structures.
733
+
734
+ Supports both legacy flat list and new nested dict structures:
735
+ - Legacy: {"skills": [skill1, skill2, ...]}
736
+ - New: {"skills": {"universal": [...], "toolchains": {...}}}
737
+
738
+ Args:
739
+ manifest: The manifest dictionary
740
+
741
+ Returns:
742
+ List of flattened skill dictionaries
743
+
744
+ Raises:
745
+ ValueError: If manifest structure is invalid
746
+
747
+ Example:
748
+ >>> # Legacy flat structure
749
+ >>> manifest = {"skills": [{"name": "skill1"}, {"name": "skill2"}]}
750
+ >>> skills = deployer._flatten_manifest_skills(manifest)
751
+ >>> len(skills) # 2
752
+
753
+ >>> # New nested structure
754
+ >>> manifest = {
755
+ ... "skills": {
756
+ ... "universal": [{"name": "skill1"}],
757
+ ... "toolchains": {"python": [{"name": "skill2"}]}
758
+ ... }
759
+ ... }
760
+ >>> skills = deployer._flatten_manifest_skills(manifest)
761
+ >>> len(skills) # 2
762
+ """
763
+ skills_data = manifest.get("skills", {})
764
+
765
+ # Handle legacy flat list structure
766
+ if isinstance(skills_data, list):
767
+ self.logger.debug(
768
+ f"Using legacy flat manifest structure ({len(skills_data)} skills)"
769
+ )
770
+ return skills_data
771
+
772
+ # Handle new nested dict structure
773
+ if isinstance(skills_data, dict):
774
+ flat_skills = []
775
+
776
+ # Add universal skills
777
+ universal_skills = skills_data.get("universal", [])
778
+ if isinstance(universal_skills, list):
779
+ flat_skills.extend(universal_skills)
780
+ self.logger.debug(f"Added {len(universal_skills)} universal skills")
781
+
782
+ # Add toolchain-specific skills
783
+ toolchains = skills_data.get("toolchains", {})
784
+ if isinstance(toolchains, dict):
785
+ for toolchain_name, toolchain_skills in toolchains.items():
786
+ if isinstance(toolchain_skills, list):
787
+ flat_skills.extend(toolchain_skills)
788
+ self.logger.debug(
789
+ f"Added {len(toolchain_skills)} {toolchain_name} skills"
790
+ )
791
+
792
+ self.logger.info(
793
+ f"Flattened {len(flat_skills)} total skills from nested structure"
794
+ )
795
+ return flat_skills
796
+
797
+ # Invalid structure
798
+ raise ValueError(
799
+ f"Skills manifest must be a list or dict, got {type(skills_data).__name__}"
800
+ )
801
+
802
+ def _filter_skills(
803
+ self,
804
+ skills: List[Dict],
805
+ toolchain: Optional[List[str]] = None,
806
+ categories: Optional[List[str]] = None,
807
+ ) -> List[Dict]:
808
+ """Filter skills by toolchain and categories.
809
+
810
+ Args:
811
+ skills: List of skill metadata dicts
812
+ toolchain: List of toolchains to include (None = all)
813
+ categories: List of categories to include (None = all)
814
+
815
+ Returns:
816
+ Filtered list of skills
817
+ """
818
+ # Ensure skills is a list and contains dicts
819
+ if not isinstance(skills, list):
820
+ return []
821
+
822
+ # Filter out non-dict items
823
+ filtered = [s for s in skills if isinstance(s, dict)]
824
+
825
+ # Filter by toolchain
826
+ if toolchain:
827
+ toolchain_lower = [t.lower() for t in toolchain]
828
+ filtered = [
829
+ s
830
+ for s in filtered
831
+ if isinstance(s, dict)
832
+ and any(
833
+ t.lower() in toolchain_lower
834
+ for t in (
835
+ s.get("toolchain", [])
836
+ if isinstance(s.get("toolchain"), list)
837
+ else ([s.get("toolchain")] if s.get("toolchain") else [])
838
+ )
839
+ )
840
+ ]
841
+
842
+ # Filter by categories
843
+ if categories:
844
+ categories_lower = [c.lower() for c in categories]
845
+ filtered = [
846
+ s
847
+ for s in filtered
848
+ if isinstance(s, dict)
849
+ and s.get("category", "").lower() in categories_lower
850
+ ]
851
+
852
+ return filtered
853
+
854
+ def _deploy_skill(
855
+ self,
856
+ skill: Dict,
857
+ collection_dir: Path,
858
+ collection_name: str,
859
+ force: bool = False,
860
+ ) -> Dict:
861
+ """Deploy a single skill to ~/.claude/skills/ and track deployment.
862
+
863
+ NOTE: With multi-collection support, skills are now stored in collection
864
+ subdirectories. This method creates symlinks or copies to maintain the
865
+ flat structure that Claude Code expects in ~/.claude/skills/.
866
+
867
+ Additionally tracks deployed skills in .mpm-deployed-skills.json index
868
+ for orphan cleanup functionality.
869
+
870
+ Args:
871
+ skill: Skill metadata dict
872
+ collection_dir: Collection directory containing skills
873
+ collection_name: Name of collection (for tracking)
874
+ force: Overwrite if already exists
875
+
876
+ Returns:
877
+ Dict with deployed, skipped, error flags
878
+ """
879
+ skill_name = skill["name"]
880
+
881
+ # Use normalized source_path for both target directory and deployment tracking
882
+ # This ensures consistency with configuration.yaml skill names
883
+ source_path = skill.get("source_path", "")
884
+ if source_path:
885
+ # Normalize: "universal/web/api-design-patterns/SKILL.md" -> "universal-web-api-design-patterns"
886
+ normalized_name = source_path.replace("/SKILL.md", "").replace("/", "-")
887
+ target_dir = self.CLAUDE_SKILLS_DIR / normalized_name
888
+ else:
889
+ # Fallback to skill name if no source_path
890
+ target_dir = self.CLAUDE_SKILLS_DIR / skill_name
891
+
892
+ # Check if already deployed
893
+ if target_dir.exists() and not force:
894
+ self.logger.debug(f"Skipped {skill_name} (already deployed)")
895
+ return {"deployed": False, "skipped": True, "error": None}
896
+
897
+ # Find skill source using source_path from manifest
898
+ source_dir = None
899
+
900
+ if source_path:
901
+ # Direct lookup using source_path (most reliable)
902
+ # Example: "universal/web/api-design-patterns/SKILL.md" -> "universal/web/api-design-patterns"
903
+ skill_dir_path = source_path.replace("/SKILL.md", "")
904
+ potential_source = collection_dir / skill_dir_path
905
+ if potential_source.exists():
906
+ source_dir = potential_source
907
+ else:
908
+ self.logger.debug(
909
+ f"Source path {skill_dir_path} not found, trying fallback search"
910
+ )
911
+
912
+ # Fallback: search using old logic (for backward compatibility)
913
+ if not source_dir:
914
+ skills_base = collection_dir / "skills"
915
+ category = skill.get("category", "")
916
+
917
+ # Try multiple possible locations
918
+ search_paths = []
919
+
920
+ # Try category-based path
921
+ if category and skills_base.exists():
922
+ search_paths.append(skills_base / category / skill_name)
923
+
924
+ # Try universal/toolchains structure
925
+ if (collection_dir / "universal").exists():
926
+ search_paths.append(collection_dir / "universal" / skill_name)
927
+
928
+ if (collection_dir / "toolchains").exists():
929
+ toolchain_dir = collection_dir / "toolchains"
930
+ for tc in toolchain_dir.iterdir():
931
+ if tc.is_dir():
932
+ search_paths.append(tc / skill_name)
933
+
934
+ # Search in all possible locations
935
+ for path in search_paths:
936
+ if path.exists():
937
+ source_dir = path
938
+ break
939
+
940
+ # Final fallback: search recursively for skill in skills directory
941
+ if not source_dir and skills_base.exists():
942
+ for cat_dir in skills_base.iterdir():
943
+ if not cat_dir.is_dir():
944
+ continue
945
+ potential = cat_dir / skill_name
946
+ if potential.exists():
947
+ source_dir = potential
948
+ break
949
+
950
+ if not source_dir or not source_dir.exists():
951
+ return {
952
+ "deployed": False,
953
+ "skipped": False,
954
+ "error": f"Skill source not found: {skill_name} (searched in {collection_dir})",
955
+ }
956
+
957
+ # Security: Validate paths
958
+ if not self._validate_safe_path(collection_dir, source_dir):
959
+ return {
960
+ "deployed": False,
961
+ "skipped": False,
962
+ "error": f"Invalid source path: {source_dir}",
963
+ }
964
+
965
+ if not self._validate_safe_path(self.CLAUDE_SKILLS_DIR, target_dir):
966
+ return {
967
+ "deployed": False,
968
+ "skipped": False,
969
+ "error": f"Invalid target path: {target_dir}",
970
+ }
971
+
972
+ try:
973
+ # Remove existing if force
974
+ if target_dir.exists():
975
+ if target_dir.is_symlink():
976
+ target_dir.unlink()
977
+ else:
978
+ shutil.rmtree(target_dir)
979
+
980
+ # Copy skill to Claude skills directory
981
+ # NOTE: We use copy instead of symlink to maintain Claude Code compatibility
982
+ shutil.copytree(source_dir, target_dir)
983
+
984
+ # Track deployment in index using normalized name
985
+ from claude_mpm.services.skills.selective_skill_deployer import (
986
+ track_deployed_skill,
987
+ )
988
+
989
+ # Use normalized name for tracking (matches configuration.yaml format)
990
+ track_name = normalized_name if source_path else skill_name
991
+ track_deployed_skill(self.CLAUDE_SKILLS_DIR, track_name, collection_name)
992
+
993
+ self.logger.debug(
994
+ f"Deployed {skill_name} from {source_dir} to {target_dir}"
995
+ )
996
+ return {"deployed": True, "skipped": False, "error": None}
997
+
998
+ except Exception as e:
999
+ return {"deployed": False, "skipped": False, "error": str(e)}
1000
+
1001
+ def _validate_safe_path(self, base: Path, target: Path) -> bool:
1002
+ """Ensure target path is within base directory (security).
1003
+
1004
+ Args:
1005
+ base: Base directory
1006
+ target: Target path to validate
1007
+
1008
+ Returns:
1009
+ True if path is safe, False otherwise
1010
+ """
1011
+ try:
1012
+ target.resolve().relative_to(base.resolve())
1013
+ return True
1014
+ except ValueError:
1015
+ return False
1016
+
1017
+ def _is_claude_code_running(self) -> bool:
1018
+ """Check if Claude Code process is running.
1019
+
1020
+ Returns:
1021
+ True if Claude Code is running, False otherwise
1022
+ """
1023
+ try:
1024
+ if platform.system() == "Windows":
1025
+ result = subprocess.run(
1026
+ ["tasklist"], check=False, capture_output=True, text=True, timeout=5
1027
+ )
1028
+ return "claude" in result.stdout.lower()
1029
+ # macOS and Linux
1030
+ result = subprocess.run(
1031
+ ["ps", "aux"], check=False, capture_output=True, text=True, timeout=5
1032
+ )
1033
+ # Look for "Claude Code" or "claude-code" process
1034
+ return (
1035
+ "claude code" in result.stdout.lower()
1036
+ or "claude-code" in result.stdout.lower()
1037
+ )
1038
+
1039
+ except Exception as e:
1040
+ self.logger.debug(f"Failed to check Claude Code process: {e}")
1041
+ return False
1042
+
1043
+ def _cleanup(self, temp_dir: Path) -> None:
1044
+ """Cleanup temporary directory.
1045
+
1046
+ NOTE: With multi-collection support, temp_dir is now the persistent
1047
+ collection directory, so we DON'T delete it. This method is kept for
1048
+ backward compatibility but is now a no-op.
1049
+
1050
+ Args:
1051
+ temp_dir: Collection directory (not deleted)
1052
+ """
1053
+ # NO-OP: Collection directories are persistent, not temporary
1054
+ # Skills are deployed from collection directories to Claude skills dir
1055
+ self.logger.debug(f"Collection directory preserved at {temp_dir} (not deleted)")
1056
+
1057
+ # === Collection Management Methods ===
1058
+
1059
+ def list_collections(self) -> Dict[str, Any]:
1060
+ """List all configured skill collections.
1061
+
1062
+ Returns:
1063
+ Dict containing:
1064
+ - collections: Dict of collection configurations
1065
+ - default_collection: Name of default collection
1066
+ - enabled_count: Number of enabled collections
1067
+
1068
+ Example:
1069
+ >>> result = deployer.list_collections()
1070
+ >>> for name, config in result['collections'].items():
1071
+ >>> print(f"{name}: {config['url']} (priority: {config['priority']})")
1072
+ """
1073
+ collections = self.skills_config.get_collections()
1074
+ default = self.skills_config.get_default_collection()
1075
+ enabled = self.skills_config.get_enabled_collections()
1076
+
1077
+ return {
1078
+ "collections": collections,
1079
+ "default_collection": default,
1080
+ "enabled_count": len(enabled),
1081
+ "total_count": len(collections),
1082
+ }
1083
+
1084
+ def add_collection(self, name: str, url: str, priority: int = 99) -> Dict[str, Any]:
1085
+ """Add a new skill collection.
1086
+
1087
+ Args:
1088
+ name: Collection name (must be unique)
1089
+ url: GitHub repository URL
1090
+ priority: Collection priority (lower = higher priority, default: 99)
1091
+
1092
+ Returns:
1093
+ Dict with operation result
1094
+
1095
+ Example:
1096
+ >>> deployer.add_collection("obra-superpowers", "https://github.com/obra/superpowers")
1097
+ """
1098
+ return self.skills_config.add_collection(name, url, priority)
1099
+
1100
+ def remove_collection(self, name: str) -> Dict[str, Any]:
1101
+ """Remove a skill collection.
1102
+
1103
+ Args:
1104
+ name: Collection name to remove
1105
+
1106
+ Returns:
1107
+ Dict with operation result
1108
+
1109
+ Example:
1110
+ >>> deployer.remove_collection("obra-superpowers")
1111
+ """
1112
+ result = self.skills_config.remove_collection(name)
1113
+
1114
+ # Also remove the collection directory
1115
+ collection_dir = self.CLAUDE_SKILLS_DIR / name
1116
+ if collection_dir.exists():
1117
+ try:
1118
+ shutil.rmtree(collection_dir)
1119
+ self.logger.info(f"Removed collection directory: {collection_dir}")
1120
+ result["directory_removed"] = True
1121
+ except Exception as e:
1122
+ self.logger.warning(f"Failed to remove directory {collection_dir}: {e}")
1123
+ result["directory_removed"] = False
1124
+ result["directory_error"] = str(e)
1125
+
1126
+ return result
1127
+
1128
+ def enable_collection(self, name: str) -> Dict[str, Any]:
1129
+ """Enable a disabled collection.
1130
+
1131
+ Args:
1132
+ name: Collection name
1133
+
1134
+ Returns:
1135
+ Dict with operation result
1136
+
1137
+ Example:
1138
+ >>> deployer.enable_collection("obra-superpowers")
1139
+ """
1140
+ return self.skills_config.enable_collection(name)
1141
+
1142
+ def disable_collection(self, name: str) -> Dict[str, Any]:
1143
+ """Disable a collection without removing it.
1144
+
1145
+ Args:
1146
+ name: Collection name
1147
+
1148
+ Returns:
1149
+ Dict with operation result
1150
+
1151
+ Example:
1152
+ >>> deployer.disable_collection("obra-superpowers")
1153
+ """
1154
+ return self.skills_config.disable_collection(name)
1155
+
1156
+ def set_default_collection(self, name: str) -> Dict[str, Any]:
1157
+ """Set the default collection for deployments.
1158
+
1159
+ Args:
1160
+ name: Collection name to set as default
1161
+
1162
+ Returns:
1163
+ Dict with operation result
1164
+
1165
+ Example:
1166
+ >>> deployer.set_default_collection("obra-superpowers")
1167
+ """
1168
+ return self.skills_config.set_default_collection(name)