claude-mpm 5.0.9__py3-none-any.whl → 5.6.23__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (614) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +4 -0
  3. claude_mpm/agents/BASE_AGENT.md +164 -0
  4. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +115 -0
  5. claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
  6. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +186 -0
  7. claude_mpm/agents/MEMORY.md +1 -1
  8. claude_mpm/agents/PM_INSTRUCTIONS.md +479 -616
  9. claude_mpm/agents/WORKFLOW.md +6 -253
  10. claude_mpm/agents/agent_loader.py +13 -44
  11. claude_mpm/agents/base_agent.json +1 -1
  12. claude_mpm/agents/frontmatter_validator.py +70 -2
  13. claude_mpm/agents/templates/circuit-breakers.md +457 -62
  14. claude_mpm/cli/__init__.py +5 -2
  15. claude_mpm/cli/__main__.py +4 -0
  16. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  17. claude_mpm/cli/commands/agent_state_manager.py +18 -27
  18. claude_mpm/cli/commands/agents.py +177 -41
  19. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  20. claude_mpm/cli/commands/auto_configure.py +723 -236
  21. claude_mpm/cli/commands/autotodos.py +566 -0
  22. claude_mpm/cli/commands/commander.py +216 -0
  23. claude_mpm/cli/commands/config.py +88 -2
  24. claude_mpm/cli/commands/configure.py +1874 -170
  25. claude_mpm/cli/commands/configure_agent_display.py +27 -6
  26. claude_mpm/cli/commands/hook_errors.py +60 -60
  27. claude_mpm/cli/commands/monitor.py +2 -2
  28. claude_mpm/cli/commands/mpm_init/core.py +232 -46
  29. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  30. claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
  31. claude_mpm/cli/commands/postmortem.py +1 -1
  32. claude_mpm/cli/commands/profile.py +276 -0
  33. claude_mpm/cli/commands/run.py +35 -3
  34. claude_mpm/cli/commands/skill_source.py +51 -2
  35. claude_mpm/cli/commands/skills.py +379 -204
  36. claude_mpm/cli/commands/summarize.py +413 -0
  37. claude_mpm/cli/executor.py +141 -19
  38. claude_mpm/cli/interactive/__init__.py +10 -0
  39. claude_mpm/cli/interactive/agent_wizard.py +115 -60
  40. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  41. claude_mpm/cli/interactive/skill_selector.py +481 -0
  42. claude_mpm/cli/parsers/agents_parser.py +54 -9
  43. claude_mpm/cli/parsers/auto_configure_parser.py +13 -138
  44. claude_mpm/cli/parsers/base_parser.py +88 -1
  45. claude_mpm/cli/parsers/commander_parser.py +116 -0
  46. claude_mpm/cli/parsers/config_parser.py +153 -83
  47. claude_mpm/cli/parsers/profile_parser.py +147 -0
  48. claude_mpm/cli/parsers/run_parser.py +10 -0
  49. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  50. claude_mpm/cli/parsers/skills_parser.py +1 -1
  51. claude_mpm/cli/startup.py +1017 -266
  52. claude_mpm/cli/startup_display.py +74 -6
  53. claude_mpm/cli/startup_logging.py +2 -2
  54. claude_mpm/cli/utils.py +7 -3
  55. claude_mpm/commander/__init__.py +78 -0
  56. claude_mpm/commander/adapters/__init__.py +60 -0
  57. claude_mpm/commander/adapters/auggie.py +260 -0
  58. claude_mpm/commander/adapters/base.py +288 -0
  59. claude_mpm/commander/adapters/claude_code.py +392 -0
  60. claude_mpm/commander/adapters/codex.py +237 -0
  61. claude_mpm/commander/adapters/communication.py +366 -0
  62. claude_mpm/commander/adapters/example_usage.py +310 -0
  63. claude_mpm/commander/adapters/mpm.py +389 -0
  64. claude_mpm/commander/adapters/registry.py +204 -0
  65. claude_mpm/commander/api/__init__.py +16 -0
  66. claude_mpm/commander/api/app.py +121 -0
  67. claude_mpm/commander/api/errors.py +133 -0
  68. claude_mpm/commander/api/routes/__init__.py +8 -0
  69. claude_mpm/commander/api/routes/events.py +184 -0
  70. claude_mpm/commander/api/routes/inbox.py +171 -0
  71. claude_mpm/commander/api/routes/messages.py +148 -0
  72. claude_mpm/commander/api/routes/projects.py +271 -0
  73. claude_mpm/commander/api/routes/sessions.py +226 -0
  74. claude_mpm/commander/api/routes/work.py +296 -0
  75. claude_mpm/commander/api/schemas.py +186 -0
  76. claude_mpm/commander/chat/__init__.py +7 -0
  77. claude_mpm/commander/chat/cli.py +146 -0
  78. claude_mpm/commander/chat/commands.py +96 -0
  79. claude_mpm/commander/chat/repl.py +310 -0
  80. claude_mpm/commander/config.py +51 -0
  81. claude_mpm/commander/config_loader.py +115 -0
  82. claude_mpm/commander/core/__init__.py +10 -0
  83. claude_mpm/commander/core/block_manager.py +325 -0
  84. claude_mpm/commander/core/response_manager.py +323 -0
  85. claude_mpm/commander/daemon.py +603 -0
  86. claude_mpm/commander/env_loader.py +59 -0
  87. claude_mpm/commander/events/__init__.py +26 -0
  88. claude_mpm/commander/events/manager.py +332 -0
  89. claude_mpm/commander/frameworks/__init__.py +12 -0
  90. claude_mpm/commander/frameworks/base.py +146 -0
  91. claude_mpm/commander/frameworks/claude_code.py +58 -0
  92. claude_mpm/commander/frameworks/mpm.py +62 -0
  93. claude_mpm/commander/inbox/__init__.py +16 -0
  94. claude_mpm/commander/inbox/dedup.py +128 -0
  95. claude_mpm/commander/inbox/inbox.py +224 -0
  96. claude_mpm/commander/inbox/models.py +70 -0
  97. claude_mpm/commander/instance_manager.py +450 -0
  98. claude_mpm/commander/llm/__init__.py +6 -0
  99. claude_mpm/commander/llm/openrouter_client.py +167 -0
  100. claude_mpm/commander/llm/summarizer.py +70 -0
  101. claude_mpm/commander/memory/__init__.py +45 -0
  102. claude_mpm/commander/memory/compression.py +347 -0
  103. claude_mpm/commander/memory/embeddings.py +230 -0
  104. claude_mpm/commander/memory/entities.py +310 -0
  105. claude_mpm/commander/memory/example_usage.py +290 -0
  106. claude_mpm/commander/memory/integration.py +325 -0
  107. claude_mpm/commander/memory/search.py +381 -0
  108. claude_mpm/commander/memory/store.py +657 -0
  109. claude_mpm/commander/models/__init__.py +18 -0
  110. claude_mpm/commander/models/events.py +121 -0
  111. claude_mpm/commander/models/project.py +162 -0
  112. claude_mpm/commander/models/work.py +214 -0
  113. claude_mpm/commander/parsing/__init__.py +20 -0
  114. claude_mpm/commander/parsing/extractor.py +132 -0
  115. claude_mpm/commander/parsing/output_parser.py +270 -0
  116. claude_mpm/commander/parsing/patterns.py +100 -0
  117. claude_mpm/commander/persistence/__init__.py +11 -0
  118. claude_mpm/commander/persistence/event_store.py +274 -0
  119. claude_mpm/commander/persistence/state_store.py +309 -0
  120. claude_mpm/commander/persistence/work_store.py +164 -0
  121. claude_mpm/commander/polling/__init__.py +13 -0
  122. claude_mpm/commander/polling/event_detector.py +104 -0
  123. claude_mpm/commander/polling/output_buffer.py +49 -0
  124. claude_mpm/commander/polling/output_poller.py +153 -0
  125. claude_mpm/commander/project_session.py +268 -0
  126. claude_mpm/commander/proxy/__init__.py +12 -0
  127. claude_mpm/commander/proxy/formatter.py +89 -0
  128. claude_mpm/commander/proxy/output_handler.py +191 -0
  129. claude_mpm/commander/proxy/relay.py +155 -0
  130. claude_mpm/commander/registry.py +410 -0
  131. claude_mpm/commander/runtime/__init__.py +10 -0
  132. claude_mpm/commander/runtime/executor.py +191 -0
  133. claude_mpm/commander/runtime/monitor.py +346 -0
  134. claude_mpm/commander/session/__init__.py +6 -0
  135. claude_mpm/commander/session/context.py +81 -0
  136. claude_mpm/commander/session/manager.py +59 -0
  137. claude_mpm/commander/tmux_orchestrator.py +361 -0
  138. claude_mpm/commander/web/__init__.py +1 -0
  139. claude_mpm/commander/work/__init__.py +30 -0
  140. claude_mpm/commander/work/executor.py +207 -0
  141. claude_mpm/commander/work/queue.py +405 -0
  142. claude_mpm/commander/workflow/__init__.py +27 -0
  143. claude_mpm/commander/workflow/event_handler.py +241 -0
  144. claude_mpm/commander/workflow/notifier.py +146 -0
  145. claude_mpm/commands/mpm-config.md +36 -0
  146. claude_mpm/commands/mpm-doctor.md +16 -21
  147. claude_mpm/commands/mpm-help.md +12 -286
  148. claude_mpm/commands/mpm-init.md +88 -506
  149. claude_mpm/commands/mpm-monitor.md +22 -401
  150. claude_mpm/commands/mpm-organize.md +128 -0
  151. claude_mpm/commands/mpm-postmortem.md +13 -107
  152. claude_mpm/commands/mpm-session-resume.md +20 -363
  153. claude_mpm/commands/mpm-status.md +13 -69
  154. claude_mpm/commands/mpm-ticket-view.md +60 -495
  155. claude_mpm/commands/mpm-version.md +13 -107
  156. claude_mpm/commands/mpm.md +8 -0
  157. claude_mpm/config/agent_presets.py +8 -7
  158. claude_mpm/config/agent_sources.py +27 -0
  159. claude_mpm/config/skill_sources.py +16 -0
  160. claude_mpm/constants.py +1 -0
  161. claude_mpm/core/claude_runner.py +154 -2
  162. claude_mpm/core/config.py +37 -26
  163. claude_mpm/core/config_constants.py +74 -9
  164. claude_mpm/core/constants.py +56 -12
  165. claude_mpm/core/framework/formatters/content_formatter.py +3 -13
  166. claude_mpm/core/framework/loaders/agent_loader.py +8 -5
  167. claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
  168. claude_mpm/core/framework_loader.py +4 -2
  169. claude_mpm/core/hook_manager.py +51 -3
  170. claude_mpm/core/interactive_session.py +12 -11
  171. claude_mpm/core/logger.py +39 -9
  172. claude_mpm/core/logging_utils.py +35 -11
  173. claude_mpm/core/network_config.py +148 -0
  174. claude_mpm/core/oneshot_session.py +7 -6
  175. claude_mpm/core/optimized_startup.py +61 -0
  176. claude_mpm/core/output_style_manager.py +219 -44
  177. claude_mpm/core/shared/config_loader.py +3 -1
  178. claude_mpm/core/socketio_pool.py +16 -8
  179. claude_mpm/core/unified_agent_registry.py +134 -16
  180. claude_mpm/core/unified_config.py +76 -8
  181. claude_mpm/core/unified_paths.py +95 -90
  182. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  184. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  185. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
  186. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
  187. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
  188. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
  189. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
  190. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
  191. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
  192. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
  193. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  194. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
  195. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
  196. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
  197. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
  198. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
  199. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
  200. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  201. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  202. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
  203. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
  204. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
  205. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
  206. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
  207. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
  208. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
  209. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
  210. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  211. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
  212. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
  213. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
  214. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  215. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
  216. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  217. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
  218. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
  219. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
  220. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
  221. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
  222. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DR8nis88.js +2 -0
  223. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
  224. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  225. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
  226. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
  227. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
  228. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
  229. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
  230. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
  231. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  232. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
  233. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  234. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
  235. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
  236. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
  237. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
  238. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  239. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
  240. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
  241. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
  242. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
  243. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  244. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.RgBboRvH.js +1 -0
  245. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
  246. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  247. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  248. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  249. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  250. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  251. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  252. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  253. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  254. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  255. claude_mpm/experimental/cli_enhancements.py +2 -1
  256. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  257. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  258. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  259. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  260. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  261. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  262. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  263. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  264. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  265. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  266. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
  267. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  268. claude_mpm/hooks/claude_hooks/event_handlers.py +479 -128
  269. claude_mpm/hooks/claude_hooks/hook_handler.py +254 -83
  270. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  271. claude_mpm/hooks/claude_hooks/installer.py +149 -18
  272. claude_mpm/hooks/claude_hooks/memory_integration.py +67 -19
  273. claude_mpm/hooks/claude_hooks/response_tracking.py +44 -62
  274. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  275. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  276. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  277. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  278. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  279. claude_mpm/hooks/claude_hooks/services/connection_manager.py +69 -30
  280. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +36 -103
  281. claude_mpm/hooks/claude_hooks/services/state_manager.py +23 -36
  282. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +73 -75
  283. claude_mpm/hooks/kuzu_memory_hook.py +5 -5
  284. claude_mpm/hooks/memory_integration_hook.py +46 -1
  285. claude_mpm/hooks/session_resume_hook.py +89 -1
  286. claude_mpm/hooks/templates/pre_tool_use_template.py +10 -2
  287. claude_mpm/init.py +276 -19
  288. claude_mpm/models/agent_definition.py +7 -0
  289. claude_mpm/models/git_repository.py +3 -3
  290. claude_mpm/scripts/claude-hook-handler.sh +87 -20
  291. claude_mpm/scripts/launch_monitor.py +93 -13
  292. claude_mpm/scripts/start_activity_logging.py +0 -0
  293. claude_mpm/services/agents/agent_builder.py +3 -3
  294. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  295. claude_mpm/services/agents/agent_review_service.py +280 -0
  296. claude_mpm/services/agents/agent_selection_service.py +2 -2
  297. claude_mpm/services/agents/cache_git_manager.py +7 -7
  298. claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
  299. claude_mpm/services/agents/deployment/agent_discovery_service.py +6 -5
  300. claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
  301. claude_mpm/services/agents/deployment/agent_template_builder.py +42 -20
  302. claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
  303. claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
  304. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  305. claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
  306. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +348 -29
  307. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +570 -68
  308. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  309. claude_mpm/services/agents/git_source_manager.py +57 -4
  310. claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
  311. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  312. claude_mpm/services/agents/recommender.py +5 -3
  313. claude_mpm/services/agents/single_tier_deployment_service.py +6 -6
  314. claude_mpm/services/agents/sources/git_source_sync_service.py +129 -11
  315. claude_mpm/services/agents/startup_sync.py +27 -4
  316. claude_mpm/services/agents/toolchain_detector.py +10 -6
  317. claude_mpm/services/analysis/__init__.py +11 -1
  318. claude_mpm/services/analysis/clone_detector.py +1030 -0
  319. claude_mpm/services/cli/__init__.py +3 -0
  320. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  321. claude_mpm/services/cli/session_resume_helper.py +10 -2
  322. claude_mpm/services/command_deployment_service.py +81 -10
  323. claude_mpm/services/delegation_detector.py +175 -0
  324. claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
  325. claude_mpm/services/diagnostics/checks/agent_sources_check.py +31 -1
  326. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  327. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  328. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  329. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  330. claude_mpm/services/diagnostics/models.py +14 -1
  331. claude_mpm/services/event_bus/config.py +3 -1
  332. claude_mpm/services/event_log.py +325 -0
  333. claude_mpm/services/git/git_operations_service.py +101 -16
  334. claude_mpm/services/infrastructure/__init__.py +4 -0
  335. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  336. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  337. claude_mpm/services/monitor/daemon.py +9 -2
  338. claude_mpm/services/monitor/daemon_manager.py +54 -7
  339. claude_mpm/services/monitor/management/lifecycle.py +15 -3
  340. claude_mpm/services/monitor/server.py +796 -30
  341. claude_mpm/services/pm_skills_deployer.py +884 -0
  342. claude_mpm/services/profile_manager.py +337 -0
  343. claude_mpm/services/project/project_organizer.py +4 -0
  344. claude_mpm/services/self_upgrade_service.py +120 -12
  345. claude_mpm/services/skills/__init__.py +3 -0
  346. claude_mpm/services/skills/git_skill_source_manager.py +303 -12
  347. claude_mpm/services/skills/selective_skill_deployer.py +869 -0
  348. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  349. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  350. claude_mpm/services/skills_deployer.py +294 -55
  351. claude_mpm/services/socketio/dashboard_server.py +1 -0
  352. claude_mpm/services/socketio/event_normalizer.py +51 -6
  353. claude_mpm/services/socketio/handlers/hook.py +14 -7
  354. claude_mpm/services/socketio/server/core.py +386 -108
  355. claude_mpm/services/socketio/server/main.py +12 -4
  356. claude_mpm/services/version_control/git_operations.py +103 -0
  357. claude_mpm/skills/__init__.py +2 -1
  358. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  359. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  360. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  361. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  362. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  363. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  364. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  365. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  366. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  367. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  368. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  369. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  370. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  371. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  372. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  373. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  374. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  375. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  376. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  377. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  378. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  379. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  380. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  381. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  382. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  383. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  384. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  385. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  386. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  387. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  388. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  389. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  390. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  391. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  392. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  393. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  394. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  395. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  396. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  397. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  398. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  399. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  400. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  401. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  402. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  403. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  404. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  405. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  406. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  407. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  408. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  409. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  410. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  411. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  412. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  413. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  414. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  415. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  416. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  417. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  418. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  419. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  420. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  421. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  422. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  423. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  424. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  425. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  426. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  427. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  428. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  429. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  430. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  431. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  432. claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
  433. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  434. claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
  435. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  436. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  437. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  438. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  439. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  440. claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
  441. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  442. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  443. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  444. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  445. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  446. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  447. claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
  448. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  449. claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
  450. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  451. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  452. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  453. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  454. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  455. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  456. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  457. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  458. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  459. claude_mpm/skills/bundled/security-scanning.md +112 -0
  460. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  461. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  462. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  463. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  464. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  465. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  466. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  467. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  468. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  469. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  470. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  471. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  472. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  473. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  474. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  475. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  476. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  477. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  478. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  479. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  480. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  481. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  482. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  483. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  484. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  485. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  486. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  487. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  488. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  489. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  490. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  491. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  492. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  493. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  494. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  495. claude_mpm/skills/registry.py +295 -90
  496. claude_mpm/skills/skill_manager.py +98 -3
  497. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  498. claude_mpm/utils/agent_dependency_loader.py +115 -4
  499. claude_mpm/utils/agent_filters.py +17 -44
  500. claude_mpm/utils/gitignore.py +3 -0
  501. claude_mpm/utils/migration.py +4 -4
  502. claude_mpm/utils/robust_installer.py +86 -21
  503. claude_mpm-5.6.23.dist-info/METADATA +393 -0
  504. {claude_mpm-5.0.9.dist-info → claude_mpm-5.6.23.dist-info}/RECORD +508 -261
  505. claude_mpm-5.6.23.dist-info/entry_points.txt +5 -0
  506. claude_mpm-5.6.23.dist-info/licenses/LICENSE +94 -0
  507. claude_mpm-5.6.23.dist-info/licenses/LICENSE-FAQ.md +153 -0
  508. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
  509. claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
  510. claude_mpm/agents/BASE_OPS.md +0 -219
  511. claude_mpm/agents/BASE_PM.md +0 -480
  512. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
  513. claude_mpm/agents/BASE_QA.md +0 -167
  514. claude_mpm/agents/BASE_RESEARCH.md +0 -53
  515. claude_mpm/agents/OUTPUT_STYLE.md +0 -290
  516. claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +0 -1322
  517. claude_mpm/agents/base_agent_loader.py +0 -601
  518. claude_mpm/cli/commands/agents_detect.py +0 -380
  519. claude_mpm/cli/commands/agents_recommend.py +0 -309
  520. claude_mpm/cli/ticket_cli.py +0 -35
  521. claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
  522. claude_mpm/commands/mpm-agents-detect.md +0 -177
  523. claude_mpm/commands/mpm-agents-list.md +0 -131
  524. claude_mpm/commands/mpm-agents-recommend.md +0 -223
  525. claude_mpm/commands/mpm-config-view.md +0 -150
  526. claude_mpm/commands/mpm-ticket-organize.md +0 -304
  527. claude_mpm/dashboard/analysis_runner.py +0 -455
  528. claude_mpm/dashboard/index.html +0 -13
  529. claude_mpm/dashboard/open_dashboard.py +0 -66
  530. claude_mpm/dashboard/static/css/activity.css +0 -1958
  531. claude_mpm/dashboard/static/css/connection-status.css +0 -370
  532. claude_mpm/dashboard/static/css/dashboard.css +0 -4701
  533. claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
  534. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
  535. claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
  536. claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
  537. claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
  538. claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
  539. claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
  540. claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
  541. claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
  542. claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
  543. claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
  544. claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
  545. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
  546. claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
  547. claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
  548. claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
  549. claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
  550. claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
  551. claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
  552. claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
  553. claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
  554. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
  555. claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
  556. claude_mpm/dashboard/static/js/connection-manager.js +0 -536
  557. claude_mpm/dashboard/static/js/dashboard.js +0 -1914
  558. claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
  559. claude_mpm/dashboard/static/js/socket-client.js +0 -1474
  560. claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
  561. claude_mpm/dashboard/static/socket.io.min.js +0 -7
  562. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
  563. claude_mpm/dashboard/templates/code_simple.html +0 -153
  564. claude_mpm/dashboard/templates/index.html +0 -606
  565. claude_mpm/dashboard/test_dashboard.html +0 -372
  566. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  567. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  568. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  569. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  570. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  571. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  572. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  573. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  574. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  575. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  576. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  577. claude_mpm/scripts/mcp_server.py +0 -75
  578. claude_mpm/scripts/mcp_wrapper.py +0 -39
  579. claude_mpm/services/mcp_gateway/__init__.py +0 -159
  580. claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
  581. claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
  582. claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
  583. claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
  584. claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
  585. claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
  586. claude_mpm/services/mcp_gateway/core/base.py +0 -312
  587. claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
  588. claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
  589. claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
  590. claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
  591. claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
  592. claude_mpm/services/mcp_gateway/main.py +0 -589
  593. claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
  594. claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
  595. claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
  596. claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
  597. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
  598. claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
  599. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
  600. claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
  601. claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
  602. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
  603. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
  604. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
  605. claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
  606. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
  607. claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
  608. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
  609. claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
  610. claude_mpm-5.0.9.dist-info/METADATA +0 -1028
  611. claude_mpm-5.0.9.dist-info/entry_points.txt +0 -10
  612. claude_mpm-5.0.9.dist-info/licenses/LICENSE +0 -21
  613. {claude_mpm-5.0.9.dist-info → claude_mpm-5.6.23.dist-info}/WHEEL +0 -0
  614. {claude_mpm-5.0.9.dist-info → claude_mpm-5.6.23.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,869 @@
1
+ """Selective skill deployment based on agent requirements.
2
+
3
+ WHY: Agents now have a skills field in their frontmatter. We should only deploy
4
+ skills that agents actually reference, reducing deployed skills from ~78 to ~20
5
+ for a typical project.
6
+
7
+ DESIGN DECISIONS:
8
+ - Dual-source skill discovery:
9
+ 1. Explicit frontmatter declarations (skills: field)
10
+ 2. SkillToAgentMapper inference (pattern-based)
11
+ - Support both legacy flat list and new required/optional dict formats
12
+ - Parse YAML frontmatter from agent markdown files
13
+ - Combine explicit + inferred skills for comprehensive coverage
14
+ - Return set of unique skill names for filtering
15
+ - Track deployed skills in .mpm-deployed-skills.json index
16
+ - Remove orphaned skills (deployed by mpm but no longer referenced)
17
+
18
+ FORMATS SUPPORTED:
19
+ 1. Legacy: skills: [skill-a, skill-b, ...]
20
+ 2. New: skills: {required: [...], optional: [...]}
21
+
22
+ SKILL DISCOVERY FLOW:
23
+ 1. Scan deployed agents (.claude/agents/*.md)
24
+ 2. Extract frontmatter skills (explicit declarations)
25
+ 3. Query SkillToAgentMapper for pattern-based skills
26
+ 4. Combine both sources into unified set
27
+
28
+ DEPLOYMENT TRACKING:
29
+ 1. Track which skills were deployed by claude-mpm in index file
30
+ 2. Update index after each deployment operation
31
+ 3. Clean up orphaned skills no longer referenced by agents
32
+
33
+ References:
34
+ - Feature: Progressive skills discovery (#117)
35
+ - Service: SkillToAgentMapper (skill_to_agent_mapper.py)
36
+ """
37
+
38
+ import json
39
+ import re
40
+ from datetime import datetime, timezone
41
+ from pathlib import Path
42
+ from typing import Any, Dict, List, Set, Tuple
43
+
44
+ import yaml
45
+
46
+ from claude_mpm.core.logging_config import get_logger
47
+
48
+ logger = get_logger(__name__)
49
+
50
+ # Deployment tracking index file
51
+ DEPLOYED_INDEX_FILE = ".mpm-deployed-skills.json"
52
+
53
+ # Core PM skills that should always be deployed
54
+ # These are referenced in PM_INSTRUCTIONS.md with [SKILL: name] markers
55
+ # Without these skills, PM only sees placeholders, not actual content
56
+ PM_CORE_SKILLS = {
57
+ "mpm-delegation-patterns",
58
+ "mpm-verification-protocols",
59
+ "mpm-tool-usage-guide",
60
+ "mpm-git-file-tracking",
61
+ "mpm-pr-workflow",
62
+ "mpm-ticketing-integration",
63
+ "mpm-teaching-mode",
64
+ "mpm-bug-reporting",
65
+ "mpm-circuit-breaker-enforcement",
66
+ "mpm-session-management",
67
+ }
68
+
69
+ # Core skills that are universally useful across all projects
70
+ # These are deployed when skill mapping returns too many skills (>60)
71
+ # Target: ~25-30 core skills for balanced functionality
72
+ CORE_SKILLS = {
73
+ # Universal debugging and verification (4 skills)
74
+ "universal-debugging-systematic-debugging",
75
+ "universal-debugging-verification-before-completion",
76
+ "universal-verification-pre-merge",
77
+ "universal-verification-screenshot",
78
+ # Universal testing patterns (2 skills)
79
+ "universal-testing-test-driven-development",
80
+ "universal-testing-testing-anti-patterns",
81
+ # Universal architecture and design (1 skill)
82
+ "universal-architecture-software-patterns",
83
+ # Universal infrastructure (3 skills)
84
+ "universal-infrastructure-env-manager",
85
+ "universal-infrastructure-docker",
86
+ "universal-infrastructure-github-actions",
87
+ # Universal collaboration (1 skill)
88
+ "universal-collaboration-stacked-prs",
89
+ # Universal emergency/operations (1 skill)
90
+ "toolchains-universal-emergency-release",
91
+ "toolchains-universal-dependency-audit",
92
+ # Common language toolchains (6 skills)
93
+ "toolchains-typescript-core",
94
+ "toolchains-python-core",
95
+ "toolchains-javascript-tooling-biome",
96
+ "toolchains-python-tooling-mypy",
97
+ "toolchains-typescript-testing-vitest",
98
+ "toolchains-python-frameworks-flask",
99
+ # Common web frameworks (4 skills)
100
+ "toolchains-javascript-frameworks-nextjs",
101
+ "toolchains-nextjs-core",
102
+ "toolchains-typescript-frameworks-nodejs-backend",
103
+ "toolchains-javascript-frameworks-react-state-machine",
104
+ # Common testing tools (2 skills)
105
+ "toolchains-javascript-testing-playwright",
106
+ "toolchains-typescript-testing-jest",
107
+ # Common data/UI tools (3 skills)
108
+ "universal-data-xlsx",
109
+ "toolchains-ui-styling-tailwind",
110
+ "toolchains-ui-components-headlessui",
111
+ }
112
+
113
+
114
+ def parse_agent_frontmatter(agent_file: Path) -> Dict[str, Any]:
115
+ """Parse YAML frontmatter from agent markdown file.
116
+
117
+ Args:
118
+ agent_file: Path to agent markdown file
119
+
120
+ Returns:
121
+ Parsed frontmatter as dictionary, or empty dict if parsing fails
122
+
123
+ Example:
124
+ >>> frontmatter = parse_agent_frontmatter(Path("agent.md"))
125
+ >>> skills = frontmatter.get('skills', [])
126
+ """
127
+ try:
128
+ content = agent_file.read_text(encoding="utf-8")
129
+ except Exception as e:
130
+ logger.warning(f"Failed to read {agent_file}: {e}")
131
+ return {}
132
+
133
+ # Match YAML frontmatter between --- delimiters
134
+ match = re.match(r"^---\n(.*?)\n---", content, re.DOTALL)
135
+ if not match:
136
+ logger.debug(f"No frontmatter found in {agent_file}")
137
+ return {}
138
+
139
+ try:
140
+ frontmatter = yaml.safe_load(match.group(1))
141
+ return frontmatter or {}
142
+ except yaml.YAMLError as e:
143
+ logger.warning(f"Failed to parse frontmatter in {agent_file}: {e}")
144
+ return {}
145
+
146
+
147
+ def get_skills_from_agent(frontmatter: Dict[str, Any]) -> Set[str]:
148
+ """Extract skill names from agent frontmatter (handles both formats).
149
+
150
+ Supports both legacy and new formats:
151
+ - Legacy: skills: [skill-a, skill-b, ...]
152
+ - New: skills: {required: [...], optional: [...]}
153
+
154
+ Args:
155
+ frontmatter: Parsed agent frontmatter
156
+
157
+ Returns:
158
+ Set of unique skill names
159
+
160
+ Example:
161
+ >>> # Legacy format
162
+ >>> frontmatter = {'skills': ['skill-a', 'skill-b']}
163
+ >>> get_skills_from_agent(frontmatter)
164
+ {'skill-a', 'skill-b'}
165
+
166
+ >>> # New format
167
+ >>> frontmatter = {'skills': {'required': ['skill-a'], 'optional': ['skill-b']}}
168
+ >>> get_skills_from_agent(frontmatter)
169
+ {'skill-a', 'skill-b'}
170
+ """
171
+ skills_field = frontmatter.get("skills")
172
+
173
+ # Handle None or missing skills field
174
+ if skills_field is None:
175
+ return set()
176
+
177
+ # New format: {required: [...], optional: [...]}
178
+ if isinstance(skills_field, dict):
179
+ required = skills_field.get("required") or []
180
+ optional = skills_field.get("optional") or []
181
+
182
+ # Ensure both are lists
183
+ if not isinstance(required, list):
184
+ required = []
185
+ if not isinstance(optional, list):
186
+ optional = []
187
+
188
+ return set(required + optional)
189
+
190
+ # Legacy format: [skill1, skill2, ...]
191
+ if isinstance(skills_field, list):
192
+ return set(skills_field)
193
+
194
+ # Unsupported format
195
+ logger.warning(f"Unexpected skills field type: {type(skills_field)}")
196
+ return set()
197
+
198
+
199
+ def get_skills_from_mapping(agent_ids: List[str]) -> Set[str]:
200
+ """Get skills for agents using SkillToAgentMapper inference.
201
+
202
+ DEPRECATED: This function is deprecated as of Phase 3 refactor.
203
+ Skills are now declared exclusively in agent frontmatter.
204
+
205
+ The static skill_to_agent_mapping.yaml is no longer used for skill deployment.
206
+ Each agent must declare its skills in frontmatter or it gets zero skills.
207
+
208
+ This function remains for backward compatibility but is NO LONGER CALLED
209
+ by get_required_skills_from_agents().
210
+
211
+ Args:
212
+ agent_ids: List of DEPLOYED agent identifiers (e.g., ["python-engineer", "typescript-engineer"])
213
+ These should be extracted from ~/.claude/agents/*.md files only.
214
+
215
+ Returns:
216
+ Set of unique skill names inferred from mapping configuration for DEPLOYED agents only
217
+ NOTE: This is now an empty set as the function is deprecated.
218
+
219
+ Example:
220
+ >>> # DEPRECATED - use frontmatter instead
221
+ >>> deployed_agent_ids = ["python-engineer", "typescript-engineer", "qa"]
222
+ >>> skills = get_skills_from_mapping(deployed_agent_ids) # Returns empty set
223
+ """
224
+ # DEPRECATED: Return empty set
225
+ logger.warning(
226
+ "get_skills_from_mapping() is DEPRECATED and returns empty set. "
227
+ "Skills are now declared in agent frontmatter only. "
228
+ "Update your agents with 'skills:' field in frontmatter."
229
+ )
230
+ return set()
231
+
232
+
233
+ def extract_skills_from_content(agent_file: Path) -> Set[str]:
234
+ """Extract skill names from [SKILL: skill-name] markers in agent file content.
235
+
236
+ This function complements frontmatter skill extraction by finding inline
237
+ skill references in the agent's markdown content body.
238
+
239
+ Supports multiple formats:
240
+ - Bold marker: **[SKILL: skill-name]**
241
+ - Plain marker: [SKILL: skill-name]
242
+ - Backtick list: - `skill-name` - Description
243
+ - With spaces: [SKILL: skill-name ]
244
+
245
+ Args:
246
+ agent_file: Path to agent markdown file
247
+
248
+ Returns:
249
+ Set of skill names found in content body
250
+
251
+ Example:
252
+ >>> skills = extract_skills_from_content(Path("pm.md"))
253
+ >>> # Finds skills from markers like **[SKILL: mpm-delegation-patterns]**
254
+ >>> # Also finds from lists like - `mpm-teaching-mode` - Description
255
+ >>> print(f"Found {len(skills)} skills in content")
256
+ """
257
+ try:
258
+ content = agent_file.read_text(encoding="utf-8")
259
+ except Exception as e:
260
+ logger.warning(f"Failed to read {agent_file}: {e}")
261
+ return set()
262
+
263
+ skills = set()
264
+
265
+ # Pattern 1: [SKILL: skill-name] markers (with optional markdown bold)
266
+ # Handles: **[SKILL: skill-name]** or [SKILL: skill-name]
267
+ # Pattern breakdown:
268
+ # - \*{0,2}: Optional bold markdown (0-2 asterisks)
269
+ # - \[SKILL:\s*: Opening bracket with optional whitespace
270
+ # - ([a-zA-Z0-9_-]+): Skill name (capture group)
271
+ # - \s*\]: Closing bracket with optional whitespace
272
+ # - \*{0,2}: Optional closing bold markdown
273
+ pattern1 = r"\*{0,2}\[SKILL:\s*([a-zA-Z0-9_-]+)\s*\]\*{0,2}"
274
+ matches1 = re.findall(pattern1, content, re.IGNORECASE)
275
+ skills.update(matches1)
276
+
277
+ # Pattern 2: Backtick list items with mpm-* or toolchains-* skills
278
+ # Handles: - `mpm-skill-name` - Description
279
+ # Pattern breakdown:
280
+ # - ^-\s+: Start with dash and whitespace (list item)
281
+ # - `: Opening backtick
282
+ # - ((?:mpm-|toolchains-|universal-)[a-zA-Z0-9_-]+): Skill name starting with prefix
283
+ # - `: Closing backtick
284
+ # - \s+-: Followed by whitespace and dash (description separator)
285
+ pattern2 = r"^-\s+`((?:mpm-|toolchains-|universal-)[a-zA-Z0-9_-]+)`\s+-"
286
+ matches2 = re.findall(pattern2, content, re.MULTILINE | re.IGNORECASE)
287
+ skills.update(matches2)
288
+
289
+ if skills:
290
+ logger.debug(
291
+ f"Found {len(skills)} skills from content markers in {agent_file.name}"
292
+ )
293
+
294
+ return skills
295
+
296
+
297
+ def get_required_skills_from_agents(agents_dir: Path) -> Set[str]:
298
+ """Extract all skills referenced by deployed agents.
299
+
300
+ MAJOR CHANGE (Phase 3): Now uses TWO sources for skill discovery:
301
+ 1. Frontmatter-declared skills (skills: field)
302
+ 2. Content body markers ([SKILL: skill-name])
303
+
304
+ The static skill_to_agent_mapping.yaml is DEPRECATED. Each agent must
305
+ declare its skills via frontmatter OR inline markers.
306
+
307
+ This change:
308
+ - Eliminates dual-source complexity (frontmatter + mapping)
309
+ - Makes skill requirements explicit per agent
310
+ - Enables per-agent customization via frontmatter or inline markers
311
+ - Removes dependency on static YAML mapping
312
+ - Fixes PM skills being removed as orphaned (they use inline markers)
313
+
314
+ Special handling for PM_INSTRUCTIONS.md:
315
+ - Also scans .claude-mpm/PM_INSTRUCTIONS.md for skill markers
316
+ - PM instructions are not in agents_dir but contain [SKILL: ...] references
317
+
318
+ Args:
319
+ agents_dir: Path to deployed agents directory (e.g., .claude/agents/)
320
+
321
+ Returns:
322
+ Set of unique skill names referenced across all agents
323
+
324
+ Example:
325
+ >>> agents_dir = Path(".claude/agents")
326
+ >>> required_skills = get_required_skills_from_agents(agents_dir)
327
+ >>> print(f"Found {len(required_skills)} unique skills")
328
+ """
329
+ if not agents_dir.exists():
330
+ logger.warning(f"Agents directory not found: {agents_dir}")
331
+ return set()
332
+
333
+ # Scan all agent markdown files
334
+ agent_files = list(agents_dir.glob("*.md"))
335
+
336
+ # Special case: Add PM_INSTRUCTIONS.md if it exists
337
+ # PM instructions live in .claude-mpm/ not .claude/agents/
338
+ pm_instructions = agents_dir.parent.parent / ".claude-mpm" / "PM_INSTRUCTIONS.md"
339
+ if pm_instructions.exists():
340
+ agent_files.append(pm_instructions)
341
+ logger.debug("Added PM_INSTRUCTIONS.md for skill scanning")
342
+
343
+ logger.debug(f"Scanning {len(agent_files)} agent files (including PM instructions)")
344
+
345
+ # Use TWO sources: frontmatter AND content markers
346
+ frontmatter_skills = set()
347
+ content_skills = set()
348
+
349
+ for agent_file in agent_files:
350
+ agent_id = agent_file.stem
351
+
352
+ # Source 1: Extract from frontmatter
353
+ frontmatter = parse_agent_frontmatter(agent_file)
354
+ agent_fm_skills = get_skills_from_agent(frontmatter)
355
+
356
+ if agent_fm_skills:
357
+ frontmatter_skills.update(agent_fm_skills)
358
+ logger.debug(
359
+ f"Agent {agent_id}: {len(agent_fm_skills)} skills from frontmatter"
360
+ )
361
+
362
+ # Source 2: Extract from content body [SKILL: ...] markers
363
+ agent_content_skills = extract_skills_from_content(agent_file)
364
+
365
+ if agent_content_skills:
366
+ content_skills.update(agent_content_skills)
367
+ logger.debug(
368
+ f"Agent {agent_id}: {len(agent_content_skills)} skills from content markers"
369
+ )
370
+
371
+ if not agent_fm_skills and not agent_content_skills:
372
+ logger.debug(
373
+ f"Agent {agent_id}: No skills declared (checked frontmatter + content)"
374
+ )
375
+
376
+ # Combine both sources
377
+ all_skills = frontmatter_skills | content_skills
378
+
379
+ logger.info(
380
+ f"Found {len(all_skills)} unique skills "
381
+ f"({len(frontmatter_skills)} from frontmatter, "
382
+ f"{len(content_skills)} from content markers)"
383
+ )
384
+
385
+ # Normalize skill paths: convert slashes to dashes for compatibility with deployment
386
+ # Some skills may use slash format, normalize to dashes
387
+ normalized_skills = {skill.replace("/", "-") for skill in all_skills}
388
+
389
+ if normalized_skills != all_skills:
390
+ logger.debug(
391
+ f"Normalized {len(all_skills)} skills to {len(normalized_skills)} "
392
+ "(converted slashes to dashes)"
393
+ )
394
+
395
+ # Always include PM core skills to ensure PM_INSTRUCTIONS.md markers are resolved
396
+ # These skills are referenced in PM_INSTRUCTIONS.md and must be deployed
397
+ # for PM to see actual content instead of [SKILL: name] placeholders
398
+ before_pm_skills = len(normalized_skills)
399
+ normalized_skills = normalized_skills | PM_CORE_SKILLS
400
+ pm_skills_added = len(normalized_skills) - before_pm_skills
401
+
402
+ if pm_skills_added > 0:
403
+ logger.info(
404
+ f"Added {pm_skills_added} PM core skills to ensure PM_INSTRUCTIONS.md markers resolve"
405
+ )
406
+
407
+ return normalized_skills
408
+
409
+
410
+ # === Deployment Tracking Functions ===
411
+
412
+
413
+ def load_deployment_index(claude_skills_dir: Path) -> Dict[str, Any]:
414
+ """Load deployment tracking index from ~/.claude/skills/.
415
+
416
+ Args:
417
+ claude_skills_dir: Path to Claude skills directory (~/.claude/skills/)
418
+
419
+ Returns:
420
+ Dict containing:
421
+ - deployed_skills: Dict mapping skill name to deployment metadata
422
+ - user_requested_skills: List of skill names manually requested by user
423
+ - last_sync: ISO timestamp of last sync operation
424
+
425
+ Example:
426
+ >>> index = load_deployment_index(Path.home() / ".claude" / "skills")
427
+ >>> print(f"Tracked skills: {len(index['deployed_skills'])}")
428
+ """
429
+ index_path = claude_skills_dir / DEPLOYED_INDEX_FILE
430
+
431
+ if not index_path.exists():
432
+ logger.debug(f"No deployment index found at {index_path}, creating new")
433
+ return {"deployed_skills": {}, "user_requested_skills": [], "last_sync": None}
434
+
435
+ try:
436
+ with open(index_path, encoding="utf-8") as f:
437
+ index = json.load(f)
438
+
439
+ # Ensure required keys exist
440
+ if "deployed_skills" not in index:
441
+ index["deployed_skills"] = {}
442
+ if "user_requested_skills" not in index:
443
+ index["user_requested_skills"] = []
444
+ if "last_sync" not in index:
445
+ index["last_sync"] = None
446
+
447
+ logger.debug(
448
+ f"Loaded deployment index: {len(index['deployed_skills'])} tracked skills, "
449
+ f"{len(index['user_requested_skills'])} user-requested"
450
+ )
451
+ return index
452
+
453
+ except (json.JSONDecodeError, OSError) as e:
454
+ logger.warning(f"Failed to load deployment index: {e}, creating new")
455
+ return {"deployed_skills": {}, "user_requested_skills": [], "last_sync": None}
456
+
457
+
458
+ def save_deployment_index(claude_skills_dir: Path, index: Dict[str, Any]) -> None:
459
+ """Save deployment tracking index to ~/.claude/skills/.
460
+
461
+ Args:
462
+ claude_skills_dir: Path to Claude skills directory (~/.claude/skills/)
463
+ index: Index data to save
464
+
465
+ Example:
466
+ >>> index = {"deployed_skills": {...}, "last_sync": "2025-12-22T10:30:00Z"}
467
+ >>> save_deployment_index(Path.home() / ".claude" / "skills", index)
468
+ """
469
+ index_path = claude_skills_dir / DEPLOYED_INDEX_FILE
470
+
471
+ try:
472
+ # Ensure directory exists
473
+ claude_skills_dir.mkdir(parents=True, exist_ok=True)
474
+
475
+ with open(index_path, "w", encoding="utf-8") as f:
476
+ json.dump(index, f, indent=2, ensure_ascii=False)
477
+
478
+ logger.debug(f"Saved deployment index: {len(index['deployed_skills'])} skills")
479
+
480
+ except OSError as e:
481
+ logger.error(f"Failed to save deployment index: {e}")
482
+ raise
483
+
484
+
485
+ def track_deployed_skill(
486
+ claude_skills_dir: Path, skill_name: str, collection: str
487
+ ) -> None:
488
+ """Track a newly deployed skill in the deployment index.
489
+
490
+ Args:
491
+ claude_skills_dir: Path to Claude skills directory (~/.claude/skills/)
492
+ skill_name: Name of deployed skill
493
+ collection: Collection name skill was deployed from
494
+
495
+ Example:
496
+ >>> track_deployed_skill(
497
+ ... Path.home() / ".claude" / "skills",
498
+ ... "systematic-debugging",
499
+ ... "claude-mpm-skills"
500
+ ... )
501
+ """
502
+ index = load_deployment_index(claude_skills_dir)
503
+
504
+ # Add skill to deployed_skills
505
+ index["deployed_skills"][skill_name] = {
506
+ "collection": collection,
507
+ "deployed_at": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
508
+ }
509
+
510
+ # Update last_sync timestamp
511
+ index["last_sync"] = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
512
+
513
+ save_deployment_index(claude_skills_dir, index)
514
+ logger.debug(f"Tracked deployment: {skill_name} from {collection}")
515
+
516
+
517
+ def untrack_skill(claude_skills_dir: Path, skill_name: str) -> None:
518
+ """Remove skill from deployment tracking index.
519
+
520
+ Args:
521
+ claude_skills_dir: Path to Claude skills directory (~/.claude/skills/)
522
+ skill_name: Name of skill to untrack
523
+
524
+ Example:
525
+ >>> untrack_skill(
526
+ ... Path.home() / ".claude" / "skills",
527
+ ... "old-skill"
528
+ ... )
529
+ """
530
+ index = load_deployment_index(claude_skills_dir)
531
+
532
+ if skill_name in index["deployed_skills"]:
533
+ del index["deployed_skills"][skill_name]
534
+ index["last_sync"] = (
535
+ datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
536
+ )
537
+ save_deployment_index(claude_skills_dir, index)
538
+ logger.debug(f"Untracked skill: {skill_name}")
539
+
540
+
541
+ def cleanup_orphan_skills(
542
+ claude_skills_dir: Path, required_skills: Set[str]
543
+ ) -> Dict[str, Any]:
544
+ """Remove skills deployed by claude-mpm but no longer referenced by agents.
545
+
546
+ This function:
547
+ 1. Loads deployment tracking index
548
+ 2. Identifies orphaned skills (tracked but not in required_skills AND not user-requested)
549
+ 3. Removes orphaned skill directories from ~/.claude/skills/
550
+ 4. Updates deployment index
551
+
552
+ User-requested skills are NEVER cleaned up as orphans - they are treated as required.
553
+
554
+ Args:
555
+ claude_skills_dir: Path to Claude skills directory (~/.claude/skills/)
556
+ required_skills: Set of skill names currently required by agents
557
+
558
+ Returns:
559
+ Dict containing:
560
+ - removed_count: Number of skills removed
561
+ - removed_skills: List of removed skill names
562
+ - kept_count: Number of skills kept
563
+ - errors: List of error messages
564
+
565
+ Example:
566
+ >>> required = {"skill-a", "skill-b"}
567
+ >>> result = cleanup_orphan_skills(
568
+ ... Path.home() / ".claude" / "skills",
569
+ ... required
570
+ ... )
571
+ >>> print(f"Removed {result['removed_count']} orphaned skills")
572
+ """
573
+ import shutil
574
+
575
+ index = load_deployment_index(claude_skills_dir)
576
+ tracked_skills = set(index["deployed_skills"].keys())
577
+ user_requested = set(index.get("user_requested_skills", []))
578
+
579
+ # Find orphaned skills: tracked by mpm but not in required_skills AND not user-requested
580
+ # User-requested skills are treated as required and NEVER cleaned up
581
+ all_required = required_skills | user_requested
582
+ orphaned = tracked_skills - all_required
583
+
584
+ if not orphaned:
585
+ logger.info("No orphaned skills to remove")
586
+ return {
587
+ "removed_count": 0,
588
+ "removed_skills": [],
589
+ "kept_count": len(tracked_skills),
590
+ "errors": [],
591
+ }
592
+
593
+ logger.info(
594
+ f"Found {len(orphaned)} orphaned skills (tracked but not required by agents)"
595
+ )
596
+
597
+ removed = []
598
+ errors = []
599
+
600
+ for skill_name in orphaned:
601
+ skill_dir = claude_skills_dir / skill_name
602
+
603
+ # Remove skill directory if it exists
604
+ if skill_dir.exists():
605
+ try:
606
+ # Validate path is within claude_skills_dir (security)
607
+ skill_dir.resolve().relative_to(claude_skills_dir.resolve())
608
+
609
+ # Remove directory
610
+ if skill_dir.is_symlink():
611
+ logger.debug(f"Removing symlink: {skill_dir}")
612
+ skill_dir.unlink()
613
+ else:
614
+ shutil.rmtree(skill_dir)
615
+
616
+ removed.append(skill_name)
617
+ logger.info(f"Removed orphaned skill: {skill_name}")
618
+
619
+ except ValueError:
620
+ error_msg = f"Path traversal attempt detected: {skill_dir}"
621
+ logger.error(error_msg)
622
+ errors.append(error_msg)
623
+ continue
624
+ except Exception as e:
625
+ error_msg = f"Failed to remove {skill_name}: {e}"
626
+ logger.error(error_msg)
627
+ errors.append(error_msg)
628
+ continue
629
+
630
+ # Remove from tracking index
631
+ untrack_skill(claude_skills_dir, skill_name)
632
+
633
+ kept_count = len(tracked_skills) - len(removed)
634
+
635
+ logger.info(
636
+ f"Cleanup complete: removed {len(removed)} skills, kept {kept_count} skills"
637
+ )
638
+
639
+ return {
640
+ "removed_count": len(removed),
641
+ "removed_skills": removed,
642
+ "kept_count": kept_count,
643
+ "errors": errors,
644
+ }
645
+
646
+
647
+ # === Configuration Management Functions ===
648
+
649
+
650
+ def save_agent_skills_to_config(skills: List[str], config_path: Path) -> None:
651
+ """Save agent-scanned skills to configuration.yaml under skills.agent_referenced.
652
+
653
+ Args:
654
+ skills: List of skill names scanned from deployed agents
655
+ config_path: Path to configuration.yaml file
656
+
657
+ Example:
658
+ >>> skills = ["systematic-debugging", "typescript-core"]
659
+ >>> save_agent_skills_to_config(skills, Path(".claude-mpm/configuration.yaml"))
660
+ """
661
+ import yaml
662
+
663
+ try:
664
+ # Load existing configuration (or create empty dict)
665
+ if config_path.exists():
666
+ with open(config_path, encoding="utf-8") as f:
667
+ config = yaml.safe_load(f) or {}
668
+ else:
669
+ config = {}
670
+
671
+ # Ensure skills section exists
672
+ if "skills" not in config:
673
+ config["skills"] = {}
674
+
675
+ # Update agent_referenced skills (sorted for consistency)
676
+ config["skills"]["agent_referenced"] = sorted(skills)
677
+
678
+ # Ensure user_defined exists (but don't overwrite if set)
679
+ if "user_defined" not in config["skills"]:
680
+ config["skills"]["user_defined"] = []
681
+
682
+ # Save configuration
683
+ config_path.parent.mkdir(parents=True, exist_ok=True)
684
+ with open(config_path, "w", encoding="utf-8") as f:
685
+ yaml.dump(config, f, default_flow_style=False, sort_keys=False)
686
+
687
+ logger.info(
688
+ f"Saved {len(skills)} agent-referenced skills to configuration.yaml"
689
+ )
690
+
691
+ except Exception as e:
692
+ logger.error(f"Failed to save agent skills to config: {e}")
693
+ raise
694
+
695
+
696
+ def get_skills_to_deploy(config_path: Path) -> Tuple[List[str], str]:
697
+ """Resolve which skills to deploy based on configuration priority.
698
+
699
+ Returns (skills_list, source) where source is 'user_defined' or 'agent_referenced'.
700
+
701
+ Logic:
702
+ - If config.skills.user_defined is non-empty → return (user_defined, 'user_defined')
703
+ - Otherwise → return (agent_referenced, 'agent_referenced')
704
+
705
+ Args:
706
+ config_path: Path to configuration.yaml file
707
+
708
+ Returns:
709
+ Tuple of (skills list, source string)
710
+
711
+ Example:
712
+ >>> skills, source = get_skills_to_deploy(Path(".claude-mpm/configuration.yaml"))
713
+ >>> print(f"Deploy {len(skills)} skills from {source}")
714
+ """
715
+ import yaml
716
+
717
+ try:
718
+ # Load configuration
719
+ if not config_path.exists():
720
+ logger.warning(f"Configuration file not found: {config_path}")
721
+ return ([], "agent_referenced")
722
+
723
+ with open(config_path, encoding="utf-8") as f:
724
+ config = yaml.safe_load(f) or {}
725
+
726
+ skills_config = config.get("skills", {})
727
+ user_defined = skills_config.get("user_defined", [])
728
+ agent_referenced = skills_config.get("agent_referenced", [])
729
+
730
+ # Priority: user_defined if non-empty, otherwise agent_referenced
731
+ if user_defined:
732
+ logger.info(
733
+ f"Using {len(user_defined)} user-defined skills from configuration"
734
+ )
735
+ return (user_defined, "user_defined")
736
+ logger.info(
737
+ f"Using {len(agent_referenced)} agent-referenced skills from configuration"
738
+ )
739
+ return (agent_referenced, "agent_referenced")
740
+
741
+ except Exception as e:
742
+ logger.error(f"Failed to load skills from config: {e}")
743
+ return ([], "agent_referenced")
744
+
745
+
746
+ # === User-Requested Skills Management ===
747
+
748
+
749
+ def get_user_requested_skills(claude_skills_dir: Path) -> List[str]:
750
+ """Get list of user-requested skills.
751
+
752
+ Args:
753
+ claude_skills_dir: Path to Claude skills directory (~/.claude/skills/)
754
+
755
+ Returns:
756
+ List of skill names manually requested by user
757
+
758
+ Example:
759
+ >>> skills = get_user_requested_skills(Path.home() / ".claude" / "skills")
760
+ >>> print(f"User requested {len(skills)} skills")
761
+ """
762
+ index = load_deployment_index(claude_skills_dir)
763
+ return index.get("user_requested_skills", [])
764
+
765
+
766
+ def add_user_requested_skill(skill_name: str, claude_skills_dir: Path) -> bool:
767
+ """Add a skill to user_requested_skills list.
768
+
769
+ This function:
770
+ 1. Loads deployment index
771
+ 2. Adds skill name to user_requested_skills (if not already present)
772
+ 3. Saves updated index
773
+ 4. Returns success status
774
+
775
+ Note: This function does NOT deploy the skill, it only marks it as user-requested.
776
+ Use this in conjunction with skill deployment functions.
777
+
778
+ Args:
779
+ skill_name: Name of skill to mark as user-requested
780
+ claude_skills_dir: Path to Claude skills directory (~/.claude/skills/)
781
+
782
+ Returns:
783
+ True if skill was added, False if already present
784
+
785
+ Example:
786
+ >>> added = add_user_requested_skill(
787
+ ... "django-framework",
788
+ ... Path.home() / ".claude" / "skills"
789
+ ... )
790
+ >>> print(f"Skill added: {added}")
791
+ """
792
+ index = load_deployment_index(claude_skills_dir)
793
+ user_requested = index.get("user_requested_skills", [])
794
+
795
+ if skill_name in user_requested:
796
+ logger.debug(f"Skill {skill_name} already in user_requested_skills")
797
+ return False
798
+
799
+ user_requested.append(skill_name)
800
+ index["user_requested_skills"] = user_requested
801
+ index["last_sync"] = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
802
+
803
+ save_deployment_index(claude_skills_dir, index)
804
+ logger.info(f"Added {skill_name} to user_requested_skills")
805
+ return True
806
+
807
+
808
+ def remove_user_requested_skill(skill_name: str, claude_skills_dir: Path) -> bool:
809
+ """Remove a skill from user_requested_skills list.
810
+
811
+ This function:
812
+ 1. Loads deployment index
813
+ 2. Removes skill name from user_requested_skills
814
+ 3. Saves updated index
815
+ 4. Returns success status
816
+
817
+ Note: This function does NOT remove the deployed skill directory.
818
+ It only removes the skill from user_requested_skills, making it eligible
819
+ for cleanup during orphan removal.
820
+
821
+ Args:
822
+ skill_name: Name of skill to remove from user_requested_skills
823
+ claude_skills_dir: Path to Claude skills directory (~/.claude/skills/)
824
+
825
+ Returns:
826
+ True if skill was removed, False if not present
827
+
828
+ Example:
829
+ >>> removed = remove_user_requested_skill(
830
+ ... "django-framework",
831
+ ... Path.home() / ".claude" / "skills"
832
+ ... )
833
+ >>> print(f"Skill removed: {removed}")
834
+ """
835
+ index = load_deployment_index(claude_skills_dir)
836
+ user_requested = index.get("user_requested_skills", [])
837
+
838
+ if skill_name not in user_requested:
839
+ logger.debug(f"Skill {skill_name} not in user_requested_skills")
840
+ return False
841
+
842
+ user_requested.remove(skill_name)
843
+ index["user_requested_skills"] = user_requested
844
+ index["last_sync"] = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
845
+
846
+ save_deployment_index(claude_skills_dir, index)
847
+ logger.info(f"Removed {skill_name} from user_requested_skills")
848
+ return True
849
+
850
+
851
+ def is_user_requested_skill(skill_name: str, claude_skills_dir: Path) -> bool:
852
+ """Check if a skill is in the user_requested_skills list.
853
+
854
+ Args:
855
+ skill_name: Name of skill to check
856
+ claude_skills_dir: Path to Claude skills directory (~/.claude/skills/)
857
+
858
+ Returns:
859
+ True if skill is user-requested, False otherwise
860
+
861
+ Example:
862
+ >>> is_requested = is_user_requested_skill(
863
+ ... "django-framework",
864
+ ... Path.home() / ".claude" / "skills"
865
+ ... )
866
+ >>> print(f"User requested: {is_requested}")
867
+ """
868
+ user_requested = get_user_requested_skills(claude_skills_dir)
869
+ return skill_name in user_requested