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
@@ -2,190 +2,2523 @@
2
2
  Agents command implementation for claude-mpm.
3
3
 
4
4
  WHY: This module manages Claude Code native agents, including listing, deploying,
5
- and cleaning agent deployments.
5
+ and cleaning agent deployments. Refactored to use shared utilities for consistency.
6
+
7
+ DESIGN DECISIONS:
8
+ - Use AgentCommand base class for consistent CLI patterns
9
+ - Leverage shared utilities for argument parsing and output formatting
10
+ - Maintain backward compatibility with existing functionality
11
+ - Support multiple output formats (json, yaml, table, text)
6
12
  """
7
13
 
14
+ import json
8
15
  from pathlib import Path
9
16
 
10
- from ...core.logger import get_logger
11
17
  from ...constants import AgentCommands
18
+ from ...core.enums import OutputFormat
19
+ from ...services.cli.agent_cleanup_service import AgentCleanupService
20
+ from ...services.cli.agent_dependency_service import AgentDependencyService
21
+ from ...services.cli.agent_listing_service import AgentListingService
22
+ from ...services.cli.agent_output_formatter import AgentOutputFormatter
23
+ from ...services.cli.agent_validation_service import AgentValidationService
24
+ from ..shared import AgentCommand, CommandResult
12
25
  from ..utils import get_agent_versions_display
26
+ from .agents_cleanup import handle_agents_cleanup
13
27
 
14
28
 
15
- def manage_agents(args):
16
- """
17
- Manage Claude Code native agents.
18
-
19
- WHY: Claude Code agents need to be deployed and managed. This command provides
20
- a unified interface for all agent-related operations.
21
-
22
- DESIGN DECISION: When no subcommand is provided, we show the current agent
23
- versions as a quick status check. This matches the behavior users see at startup.
24
-
25
- Args:
26
- args: Parsed command line arguments with agents_command attribute
27
- """
28
- logger = get_logger("cli")
29
-
30
- try:
31
- from ...services.agent_deployment import AgentDeploymentService
32
- deployment_service = AgentDeploymentService()
33
-
34
- if not args.agents_command:
35
- # No subcommand - show agent versions
36
- # WHY: This provides a quick way for users to check deployed agent versions
37
- # without needing to specify additional subcommands
29
+ def _is_structured_output(args) -> bool:
30
+ """Check if args specify structured output format (JSON/YAML)."""
31
+ if hasattr(args, "format"):
32
+ fmt = str(args.format).lower()
33
+ return fmt in (OutputFormat.JSON, OutputFormat.YAML)
34
+ return False
35
+
36
+
37
+ class AgentsCommand(AgentCommand):
38
+ """Agent management command using shared utilities."""
39
+
40
+ def __init__(self):
41
+ super().__init__("agents")
42
+ self._deployment_service = None
43
+ self._listing_service = None
44
+ self._validation_service = None
45
+ self._dependency_service = None
46
+ self._cleanup_service = None
47
+ self._formatter = AgentOutputFormatter()
48
+
49
+ @property
50
+ def deployment_service(self):
51
+ """Get deployment service instance (lazy loaded)."""
52
+ if self._deployment_service is None:
53
+ try:
54
+ from ...services import AgentDeploymentService
55
+ from ...services.agents.deployment.deployment_wrapper import (
56
+ DeploymentServiceWrapper,
57
+ )
58
+
59
+ base_service = AgentDeploymentService()
60
+ self._deployment_service = DeploymentServiceWrapper(base_service)
61
+ except ImportError as e:
62
+ raise ImportError("Agent deployment service not available") from e
63
+ return self._deployment_service
64
+
65
+ @property
66
+ def listing_service(self):
67
+ """Get listing service instance (lazy loaded)."""
68
+ if self._listing_service is None:
69
+ self._listing_service = AgentListingService(
70
+ deployment_service=self.deployment_service
71
+ )
72
+ return self._listing_service
73
+
74
+ @property
75
+ def validation_service(self):
76
+ """Get validation service instance (lazy loaded)."""
77
+ if self._validation_service is None:
78
+ self._validation_service = AgentValidationService()
79
+ return self._validation_service
80
+
81
+ @property
82
+ def dependency_service(self):
83
+ """Get dependency service instance (lazy loaded)."""
84
+ if self._dependency_service is None:
85
+ self._dependency_service = AgentDependencyService()
86
+ return self._dependency_service
87
+
88
+ @property
89
+ def cleanup_service(self):
90
+ """Get cleanup service instance (lazy loaded)."""
91
+ if self._cleanup_service is None:
92
+ self._cleanup_service = AgentCleanupService(
93
+ deployment_service=self.deployment_service
94
+ )
95
+ return self._cleanup_service
96
+
97
+ def _get_output_format(self, args) -> str:
98
+ """
99
+ Get output format from args with enum default.
100
+
101
+ Args:
102
+ args: Command arguments
103
+
104
+ Returns:
105
+ Output format string (compatible with both enum and string usage)
106
+ """
107
+ return getattr(args, "format", OutputFormat.TEXT)
108
+
109
+ def _is_structured_format(self, format_str: str) -> bool:
110
+ """
111
+ Check if format is structured (JSON/YAML).
112
+
113
+ Args:
114
+ format_str: Format string to check
115
+
116
+ Returns:
117
+ True if format is JSON or YAML
118
+ """
119
+ fmt = str(format_str).lower()
120
+ return fmt in (OutputFormat.JSON, OutputFormat.YAML)
121
+
122
+ def validate_args(self, args) -> str:
123
+ """Validate command arguments."""
124
+ # Most agent commands are optional, so basic validation
125
+ return None
126
+
127
+ def run(self, args) -> CommandResult:
128
+ """Execute the agent command."""
129
+ try:
130
+ # Handle default case (no subcommand)
131
+ if not hasattr(args, "agents_command") or not args.agents_command:
132
+ return self._show_agent_versions(args)
133
+
134
+ # Route to appropriate subcommand
135
+ command_map = {
136
+ AgentCommands.LIST.value: self._list_agents,
137
+ AgentCommands.DEPLOY.value: lambda a: self._deploy_agents(
138
+ a, force=False
139
+ ),
140
+ AgentCommands.FORCE_DEPLOY.value: lambda a: self._deploy_agents(
141
+ a, force=True
142
+ ),
143
+ AgentCommands.CLEAN.value: self._clean_agents,
144
+ AgentCommands.VIEW.value: self._view_agent,
145
+ AgentCommands.FIX.value: self._fix_agents,
146
+ "deps-check": self._check_agent_dependencies,
147
+ "deps-install": self._install_agent_dependencies,
148
+ "deps-list": self._list_agent_dependencies,
149
+ "deps-fix": self._fix_agent_dependencies,
150
+ "cleanup": lambda a: self._handle_cleanup_command(a),
151
+ "cleanup-orphaned": self._cleanup_orphaned_agents,
152
+ # Local agent management commands
153
+ "create": self._create_local_agent,
154
+ "edit": self._edit_local_agent,
155
+ "delete": self._delete_local_agent,
156
+ "manage": self._manage_local_agents,
157
+ "configure": self._configure_deployment,
158
+ # Migration command (DEPRECATION support)
159
+ "migrate-to-project": self._migrate_to_project,
160
+ # Agent selection modes (Phase 3: 1M-382)
161
+ "deploy-minimal": self._deploy_minimal_configuration,
162
+ "deploy-auto": self._deploy_auto_configure,
163
+ # Agent source management (Phase 2: 1M-442)
164
+ "available": self._list_available_from_sources,
165
+ # Agent discovery with rich filtering (Phase 1: Discovery & Browsing)
166
+ "discover": self._discover_agents,
167
+ # NEW: Collection-based agent management
168
+ "list-collections": self._list_collections,
169
+ "deploy-collection": self._deploy_collection,
170
+ "list-by-collection": self._list_by_collection,
171
+ # Cache git management commands
172
+ "cache-status": self._cache_status,
173
+ "cache-pull": self._cache_pull,
174
+ "cache-push": self._cache_push,
175
+ "cache-sync": self._cache_sync,
176
+ "cache-commit": self._cache_commit,
177
+ }
178
+
179
+ if args.agents_command in command_map:
180
+ return command_map[args.agents_command](args)
181
+ return CommandResult.error_result(
182
+ f"Unknown agent command: {args.agents_command}"
183
+ )
184
+
185
+ except ImportError:
186
+ self.logger.error("Agent deployment service not available")
187
+ return CommandResult.error_result("Agent deployment service not available")
188
+ except Exception as e:
189
+ self.logger.error(f"Error managing agents: {e}", exc_info=True)
190
+ return CommandResult.error_result(f"Error managing agents: {e}")
191
+
192
+ def _show_agent_versions(self, args) -> CommandResult:
193
+ """Show current agent versions as default action."""
194
+ try:
38
195
  agent_versions = get_agent_versions_display()
196
+
197
+ output_format = self._get_output_format(args)
198
+ if self._is_structured_format(output_format):
199
+ # Parse the agent versions display into structured data
200
+ if agent_versions:
201
+ data = {"agent_versions": agent_versions, "has_agents": True}
202
+ formatted = (
203
+ self._formatter.format_as_json(data)
204
+ if str(output_format).lower() == OutputFormat.JSON
205
+ else self._formatter.format_as_yaml(data)
206
+ )
207
+ print(formatted)
208
+ return CommandResult.success_result(
209
+ "Agent versions retrieved", data=data
210
+ )
211
+ data = {
212
+ "agent_versions": None,
213
+ "has_agents": False,
214
+ "suggestion": "To deploy agents, run: claude-mpm --mpm:agents deploy",
215
+ }
216
+ formatted = (
217
+ self._formatter.format_as_json(data)
218
+ if str(output_format).lower() == OutputFormat.JSON
219
+ else self._formatter.format_as_yaml(data)
220
+ )
221
+ print(formatted)
222
+ return CommandResult.success_result(
223
+ "No deployed agents found", data=data
224
+ )
225
+ # Text output
39
226
  if agent_versions:
40
227
  print(agent_versions)
41
- else:
42
- print("No deployed agents found")
43
- print("\nTo deploy agents, run: claude-mpm --mpm:agents deploy")
44
- return
45
-
46
- if args.agents_command == AgentCommands.LIST.value:
47
- _list_agents(args, deployment_service)
48
-
49
- elif args.agents_command == AgentCommands.DEPLOY.value:
50
- _deploy_agents(args, deployment_service, force=False)
51
-
52
- elif args.agents_command == AgentCommands.FORCE_DEPLOY.value:
53
- _deploy_agents(args, deployment_service, force=True)
54
-
55
- elif args.agents_command == AgentCommands.CLEAN.value:
56
- _clean_agents(args, deployment_service)
57
-
58
- except ImportError:
59
- logger.error("Agent deployment service not available")
60
- print("Error: Agent deployment service not available")
61
- except Exception as e:
62
- logger.error(f"Error managing agents: {e}")
63
- print(f"Error: {e}")
64
-
65
-
66
- def _list_agents(args, deployment_service):
67
- """
68
- List available or deployed agents.
69
-
70
- WHY: Users need to see what agents are available in the system and what's
71
- currently deployed. This helps them understand the agent ecosystem.
72
-
73
- Args:
74
- args: Command arguments with 'system' and 'deployed' flags
75
- deployment_service: Agent deployment service instance
76
- """
77
- if args.system:
78
- # List available agent templates
79
- print("Available Agent Templates:")
80
- print("-" * 80)
81
- agents = deployment_service.list_available_agents()
82
- if not agents:
83
- print("No agent templates found")
84
- else:
85
- for agent in agents:
86
- print(f"šŸ“„ {agent['file']}")
87
- if 'name' in agent:
88
- print(f" Name: {agent['name']}")
89
- if 'description' in agent:
90
- print(f" Description: {agent['description']}")
91
- if 'version' in agent:
92
- print(f" Version: {agent['version']}")
93
- print()
94
-
95
- elif args.deployed:
96
- # List deployed agents
97
- print("Deployed Agents:")
98
- print("-" * 80)
99
- verification = deployment_service.verify_deployment()
100
- if not verification["agents_found"]:
228
+ return CommandResult.success_result("Agent versions displayed")
101
229
  print("No deployed agents found")
230
+ print("\nTo deploy agents, run: claude-mpm --mpm:agents deploy")
231
+ return CommandResult.success_result("No deployed agents found")
232
+
233
+ except Exception as e:
234
+ self.logger.error(f"Error getting agent versions: {e}", exc_info=True)
235
+ return CommandResult.error_result(f"Error getting agent versions: {e}")
236
+
237
+ def _list_agents(self, args) -> CommandResult:
238
+ """List available or deployed agents."""
239
+ try:
240
+ output_format = self._get_output_format(args)
241
+
242
+ if hasattr(args, "by_tier") and args.by_tier:
243
+ return self._list_agents_by_tier(args)
244
+ if getattr(args, "system", False):
245
+ return self._list_system_agents(args)
246
+ if getattr(args, "deployed", False):
247
+ return self._list_deployed_agents(args)
248
+ # Default: show usage
249
+ usage_msg = "Use --system to list system agents, --deployed to list deployed agents, or --by-tier to group by precedence"
250
+
251
+ if self._is_structured_format(output_format):
252
+ return CommandResult.error_result(
253
+ "No list option specified",
254
+ data={
255
+ "usage": usage_msg,
256
+ "available_options": ["--system", "--deployed", "--by-tier"],
257
+ },
258
+ )
259
+ print(usage_msg)
260
+ return CommandResult.error_result("No list option specified")
261
+
262
+ except Exception as e:
263
+ self.logger.error(f"Error listing agents: {e}", exc_info=True)
264
+ return CommandResult.error_result(f"Error listing agents: {e}")
265
+
266
+ def _list_system_agents(self, args) -> CommandResult:
267
+ """List available agent templates."""
268
+ try:
269
+ verbose = getattr(args, "verbose", False)
270
+ agents = self.listing_service.list_system_agents(verbose=verbose)
271
+
272
+ output_format = self._get_output_format(args)
273
+ quiet = getattr(args, "quiet", False)
274
+
275
+ # Convert AgentInfo objects to dicts for formatter
276
+ agents_data = [
277
+ {
278
+ "name": agent.name,
279
+ "type": agent.type,
280
+ "path": agent.path,
281
+ "file": Path(agent.path).name if agent.path else "Unknown",
282
+ "description": agent.description,
283
+ "specializations": agent.specializations,
284
+ "version": agent.version,
285
+ }
286
+ for agent in agents
287
+ ]
288
+
289
+ formatted = self._formatter.format_agent_list(
290
+ agents_data, output_format=output_format, verbose=verbose, quiet=quiet
291
+ )
292
+ print(formatted)
293
+
294
+ return CommandResult.success_result(
295
+ f"Listed {len(agents)} agent templates",
296
+ data={"agents": agents_data, "count": len(agents)},
297
+ )
298
+
299
+ except Exception as e:
300
+ self.logger.error(f"Error listing system agents: {e}", exc_info=True)
301
+ return CommandResult.error_result(f"Error listing system agents: {e}")
302
+
303
+ def _list_deployed_agents(self, args) -> CommandResult:
304
+ """List deployed agents."""
305
+ try:
306
+ verbose = getattr(args, "verbose", False)
307
+ agents, warnings = self.listing_service.list_deployed_agents(
308
+ verbose=verbose
309
+ )
310
+
311
+ output_format = self._get_output_format(args)
312
+ quiet = getattr(args, "quiet", False)
313
+
314
+ # Convert AgentInfo objects to dicts for formatter
315
+ agents_data = [
316
+ {
317
+ "name": agent.name,
318
+ "type": agent.type,
319
+ "tier": agent.tier,
320
+ "path": agent.path,
321
+ "file": Path(agent.path).name if agent.path else "Unknown",
322
+ "description": agent.description,
323
+ "specializations": agent.specializations,
324
+ "version": agent.version,
325
+ }
326
+ for agent in agents
327
+ ]
328
+
329
+ # Format the agent list
330
+ formatted = self._formatter.format_agent_list(
331
+ agents_data, output_format=output_format, verbose=verbose, quiet=quiet
332
+ )
333
+ print(formatted)
334
+
335
+ # Add warnings for text output
336
+ if str(output_format).lower() == OutputFormat.TEXT and warnings:
337
+ print("\nWarnings:")
338
+ for warning in warnings:
339
+ print(f" āš ļø {warning}")
340
+
341
+ return CommandResult.success_result(
342
+ f"Listed {len(agents)} deployed agents",
343
+ data={
344
+ "agents": agents_data,
345
+ "warnings": warnings,
346
+ "count": len(agents),
347
+ },
348
+ )
349
+
350
+ except Exception as e:
351
+ self.logger.error(f"Error listing deployed agents: {e}", exc_info=True)
352
+ return CommandResult.error_result(f"Error listing deployed agents: {e}")
353
+
354
+ def _list_agents_by_tier(self, args) -> CommandResult:
355
+ """List agents grouped by tier/precedence."""
356
+ try:
357
+ tier_info = self.listing_service.list_agents_by_tier()
358
+ output_format = self._get_output_format(args)
359
+
360
+ # Convert to format expected by formatter
361
+ agents_by_tier = {
362
+ "project": [
363
+ {
364
+ "name": agent.name,
365
+ "type": agent.type,
366
+ "path": agent.path,
367
+ "active": agent.active,
368
+ "overridden_by": agent.overridden_by,
369
+ }
370
+ for agent in tier_info.project
371
+ ],
372
+ "user": [
373
+ {
374
+ "name": agent.name,
375
+ "type": agent.type,
376
+ "path": agent.path,
377
+ "active": agent.active,
378
+ "overridden_by": agent.overridden_by,
379
+ }
380
+ for agent in tier_info.user
381
+ ],
382
+ "system": [
383
+ {
384
+ "name": agent.name,
385
+ "type": agent.type,
386
+ "path": agent.path,
387
+ "active": agent.active,
388
+ "overridden_by": agent.overridden_by,
389
+ }
390
+ for agent in tier_info.system
391
+ ],
392
+ "summary": {
393
+ "total_count": tier_info.total_count,
394
+ "active_count": tier_info.active_count,
395
+ "project_count": len(tier_info.project),
396
+ "user_count": len(tier_info.user),
397
+ "system_count": len(tier_info.system),
398
+ },
399
+ }
400
+
401
+ formatted = self._formatter.format_agents_by_tier(
402
+ agents_by_tier, output_format=output_format
403
+ )
404
+ print(formatted)
405
+
406
+ return CommandResult.success_result(
407
+ "Agents listed by tier", data=agents_by_tier
408
+ )
409
+
410
+ except Exception as e:
411
+ self.logger.error(f"Error listing agents by tier: {e}", exc_info=True)
412
+ return CommandResult.error_result(f"Error listing agents by tier: {e}")
413
+
414
+ def _list_available_from_sources(self, args) -> CommandResult:
415
+ """List available agents from all configured git sources.
416
+
417
+ This command shows agents discovered from configured agent sources
418
+ (Git repositories) after syncing their cache. Implements Phase 2 of 1M-442.
419
+
420
+ Args:
421
+ args: Command arguments with optional source filter and format
422
+
423
+ Returns:
424
+ CommandResult with agent list or error
425
+ """
426
+ try:
427
+ from ...config.agent_sources import AgentSourceConfiguration
428
+ from ...services.agents.git_source_manager import GitSourceManager
429
+
430
+ # Load agent sources configuration
431
+ config = AgentSourceConfiguration.load()
432
+ enabled_repos = [r for r in config.repositories if r.enabled]
433
+
434
+ if not enabled_repos:
435
+ message = (
436
+ "No agent sources configured.\n\n"
437
+ "Configure sources with:\n"
438
+ " claude-mpm agent-source add <url>\n\n"
439
+ "Example:\n"
440
+ " claude-mpm agent-source add https://github.com/owner/repo/agents"
441
+ )
442
+ print(message)
443
+ return CommandResult.error_result("No agent sources configured")
444
+
445
+ # Initialize git source manager
446
+ manager = GitSourceManager()
447
+
448
+ # Sync all configured sources (with timeout)
449
+ self.logger.info(f"Syncing {len(enabled_repos)} agent sources...")
450
+ sync_results = {}
451
+
452
+ for repo in enabled_repos:
453
+ try:
454
+ result = manager.sync_repository(repo, force=False)
455
+ sync_results[repo.identifier] = result
456
+ except Exception as e:
457
+ self.logger.warning(f"Failed to sync {repo.identifier}: {e}")
458
+ sync_results[repo.identifier] = {"synced": False, "error": str(e)}
459
+
460
+ # Get source filter from args
461
+ source_filter = getattr(args, "source", None)
462
+
463
+ # List all cached agents
464
+ all_agents = manager.list_cached_agents(repo_identifier=source_filter)
465
+
466
+ if not all_agents:
467
+ message = "No agents found in configured sources."
468
+ if sync_results:
469
+ failed_count = sum(
470
+ 1 for r in sync_results.values() if not r.get("synced")
471
+ )
472
+ if failed_count > 0:
473
+ message += f"\n\n{failed_count} source(s) failed to sync. Check logs for details."
474
+ print(message)
475
+ return CommandResult.success_result(message, data={"agents": []})
476
+
477
+ # Format output
478
+ output_format = getattr(args, "format", "table")
479
+
480
+ if output_format == "json":
481
+ import json
482
+
483
+ print(json.dumps(all_agents, indent=2))
484
+ elif output_format == "simple":
485
+ for agent in all_agents:
486
+ name = agent.get("metadata", {}).get(
487
+ "name", agent.get("agent_id", "unknown")
488
+ )
489
+ repo = agent.get("repository", "unknown")
490
+ print(f"{name} (from {repo})")
491
+ else: # table format
492
+ print(f"\n{'Agent Name':<30} {'Repository':<40} {'Version':<15}")
493
+ print("=" * 85)
494
+ for agent in all_agents:
495
+ name = agent.get("metadata", {}).get(
496
+ "name", agent.get("agent_id", "unknown")
497
+ )
498
+ repo = agent.get("repository", "unknown")
499
+ version = agent.get("version", "unknown")[:12]
500
+ print(f"{name:<30} {repo:<40} {version:<15}")
501
+ print(
502
+ f"\nTotal: {len(all_agents)} agents from {len(sync_results)} sources"
503
+ )
504
+
505
+ return CommandResult.success_result(
506
+ f"Listed {len(all_agents)} agents from sources",
507
+ data={"agents": all_agents, "sync_results": sync_results},
508
+ )
509
+
510
+ except Exception as e:
511
+ self.logger.error(f"Error listing available agents: {e}", exc_info=True)
512
+ return CommandResult.error_result(f"Error listing available agents: {e}")
513
+
514
+ def _discover_agents(self, args) -> CommandResult:
515
+ """Discover agents with rich filtering capabilities.
516
+
517
+ This command extends the 'available' command by adding semantic filtering
518
+ based on AUTO-DEPLOY-INDEX.md categories. Users can filter by category,
519
+ language, framework, platform, and specialization.
520
+
521
+ Design Decision: Delegate to agents_discover.py module
522
+
523
+ Rationale: Keep CLI command logic separate from routing logic for better
524
+ testability and maintainability. The discover_command function handles
525
+ all the complex filtering and formatting logic.
526
+
527
+ Args:
528
+ args: Command arguments with filter options:
529
+ - source: Source repository filter
530
+ - category: Category filter (e.g., 'engineer/backend')
531
+ - language: Language filter (e.g., 'python')
532
+ - framework: Framework filter (e.g., 'react')
533
+ - platform: Platform filter (e.g., 'vercel')
534
+ - specialization: Specialization filter (e.g., 'data')
535
+ - format: Output format (table, json, simple)
536
+ - verbose: Show descriptions and metadata
537
+
538
+ Returns:
539
+ CommandResult with filtered agent list or error
540
+
541
+ Example:
542
+ >>> # Called via: claude-mpm agents discover --category engineer/backend
543
+ >>> _discover_agents(args)
544
+ CommandResult(success=True, message="Discovered 8 agents")
545
+ """
546
+ try:
547
+ from .agents_discover import discover_command
548
+
549
+ # Call discover_command and convert exit code to CommandResult
550
+ exit_code = discover_command(args)
551
+
552
+ if exit_code == 0:
553
+ return CommandResult.success_result("Agent discovery complete")
554
+ return CommandResult.error_result("Agent discovery failed")
555
+
556
+ except Exception as e:
557
+ self.logger.error(f"Error discovering agents: {e}", exc_info=True)
558
+ return CommandResult.error_result(f"Error discovering agents: {e}")
559
+
560
+ def _deploy_agents(self, args, force=False) -> CommandResult:
561
+ """Deploy agents using two-phase sync: cache → deploy.
562
+
563
+ Phase 3 Integration (1M-486): Uses Git sync service for deployment.
564
+ - Phase 1: Sync agents to ~/.claude-mpm/cache/agents/ (if needed)
565
+ - Phase 2: Deploy from cache to project .claude-mpm/agents/
566
+
567
+ This replaces the old single-tier deployment with a multi-project
568
+ architecture where one cache serves multiple project deployments.
569
+ """
570
+ try:
571
+ # Handle preset deployment (uses different path)
572
+ if hasattr(args, "preset") and args.preset:
573
+ return self._deploy_preset(args)
574
+
575
+ from ...services.agents.sources.git_source_sync_service import (
576
+ GitSourceSyncService,
577
+ )
578
+
579
+ # Initialize git sync service
580
+ git_sync = GitSourceSyncService()
581
+ project_dir = Path.cwd()
582
+
583
+ self.logger.info("Phase 1: Syncing agents to cache...")
584
+
585
+ # Sync to cache (downloads from GitHub if needed)
586
+ sync_result = git_sync.sync_repository(force=force)
587
+
588
+ if not sync_result.get("synced"):
589
+ error_msg = sync_result.get("error", "Unknown sync error")
590
+ self.logger.error(f"Sync failed: {error_msg}")
591
+ return CommandResult.error_result(f"Sync failed: {error_msg}")
592
+
593
+ self.logger.info(
594
+ f"Phase 1 complete: {sync_result.get('agent_count', 0)} agents in cache"
595
+ )
596
+ self.logger.info(f"Phase 2: Deploying agents to {project_dir}...")
597
+
598
+ # Deploy from cache to project directory
599
+ deploy_result = git_sync.deploy_agents_to_project(
600
+ project_dir=project_dir,
601
+ agent_list=None, # Deploy all cached agents
602
+ force=force,
603
+ )
604
+
605
+ # Format combined results for output
606
+ combined_result = {
607
+ "deployed_count": len(deploy_result.get("deployed", []))
608
+ + len(deploy_result.get("updated", [])),
609
+ "deployed": deploy_result.get("deployed", []),
610
+ "updated": deploy_result.get("updated", []),
611
+ "skipped": deploy_result.get("skipped", []),
612
+ "errors": deploy_result.get("failed", []),
613
+ "target_dir": deploy_result.get("deployment_dir", ""),
614
+ "sync_info": {
615
+ "cached_agents": sync_result.get("agent_count", 0),
616
+ "cache_dir": sync_result.get("cache_dir", ""),
617
+ },
618
+ }
619
+
620
+ output_format = self._get_output_format(args)
621
+ verbose = getattr(args, "verbose", False)
622
+
623
+ formatted = self._formatter.format_deployment_result(
624
+ combined_result, output_format=output_format, verbose=verbose
625
+ )
626
+ print(formatted)
627
+
628
+ success_count = len(deploy_result["deployed"]) + len(
629
+ deploy_result["updated"]
630
+ )
631
+ return CommandResult.success_result(
632
+ f"Deployed {success_count} agents from cache",
633
+ data={
634
+ "sync_result": sync_result,
635
+ "deploy_result": deploy_result,
636
+ "total_deployed": success_count,
637
+ },
638
+ )
639
+
640
+ except Exception as e:
641
+ self.logger.error(f"Error deploying agents: {e}", exc_info=True)
642
+ return CommandResult.error_result(f"Error deploying agents: {e}")
643
+
644
+ def _deploy_preset(self, args) -> CommandResult:
645
+ """Deploy agents by preset name.
646
+
647
+ This method implements Phase 2 of the agents/skills CLI redesign,
648
+ enabling preset-based deployment like:
649
+ claude-mpm agents deploy --preset python-dev
650
+
651
+ Args:
652
+ args: Command arguments with preset name and optional flags
653
+
654
+ Returns:
655
+ CommandResult with deployment status
656
+ """
657
+ try:
658
+ from pathlib import Path
659
+
660
+ from ...config.agent_sources import AgentSourceConfiguration
661
+ from ...services.agents.agent_preset_service import AgentPresetService
662
+ from ...services.agents.git_source_manager import GitSourceManager
663
+ from ...services.agents.single_tier_deployment_service import (
664
+ SingleTierDeploymentService,
665
+ )
666
+
667
+ preset_name = args.preset
668
+ dry_run = getattr(args, "dry_run", False)
669
+
670
+ # Initialize services
671
+ config = AgentSourceConfiguration.load()
672
+ deployment_dir = Path.home() / ".claude" / "agents"
673
+ git_source_manager = GitSourceManager()
674
+ preset_service = AgentPresetService(git_source_manager)
675
+ deployment_service = SingleTierDeploymentService(config, deployment_dir)
676
+
677
+ # Validate preset
678
+ if not preset_service.validate_preset(preset_name):
679
+ available = preset_service.list_presets()
680
+ print(f"āŒ Unknown preset: {preset_name}")
681
+ print("\nšŸ“š Available presets:")
682
+ for preset in available:
683
+ print(
684
+ f" • {preset['name']}: {preset['description']} ({preset['agent_count']} agents)"
685
+ )
686
+ print(f" Use cases: {', '.join(preset['use_cases'])}")
687
+ return CommandResult.error_result(f"Unknown preset: {preset_name}")
688
+
689
+ # Resolve preset to agent list
690
+ print(f"\nšŸ” Resolving preset: {preset_name}")
691
+ resolution = preset_service.resolve_agents(
692
+ preset_name, validate_availability=True
693
+ )
694
+
695
+ # Show preset info
696
+ preset_info = resolution["preset_info"]
697
+ print(f"\nšŸŽÆ Preset: {preset_info['description']}")
698
+ print(f" Agents: {preset_info['agent_count']}")
699
+ print(f" Use cases: {', '.join(preset_info['use_cases'])}")
700
+
701
+ # Show warnings for missing agents
702
+ if resolution["missing_agents"]:
703
+ print("\nāš ļø Missing agents (not found in configured sources):")
704
+ for agent_id in resolution["missing_agents"]:
705
+ print(f" • {agent_id}")
706
+ print("\nšŸ’” These agents are not available in your configured sources.")
707
+ print(" Deployment will continue with available agents.")
708
+
709
+ # Show conflicts
710
+ if resolution["conflicts"]:
711
+ print("\nāš ļø Priority conflicts detected:")
712
+ for conflict in resolution["conflicts"]:
713
+ sources = ", ".join(conflict["sources"])
714
+ print(f" • {conflict['agent_id']} (found in: {sources})")
715
+ print(" Using highest priority source for each")
716
+
717
+ # Dry run mode
718
+ if dry_run:
719
+ print("\nšŸ” DRY RUN: Preview agent deployment\n")
720
+ print("Agents to deploy:")
721
+ for agent in resolution["agents"]:
722
+ source = agent.get("source", "unknown")
723
+ print(f" āœ“ {agent['agent_id']} (from {source})")
724
+ print(
725
+ "\nšŸ’” This is a dry run. Run without --dry-run to actually deploy."
726
+ )
727
+ return CommandResult.success_result(
728
+ "Dry run complete",
729
+ data={
730
+ "preset": preset_name,
731
+ "agents": resolution["agents"],
732
+ "missing": resolution["missing_agents"],
733
+ },
734
+ )
735
+
736
+ # Deploy agents
737
+ print(f"\nšŸ“¦ Deploying {len(resolution['agents'])} agents...")
738
+ deployed_count = 0
739
+ failed_count = 0
740
+ skipped_count = len(resolution["missing_agents"])
741
+ deployed_agents = []
742
+ failed_agents = []
743
+
744
+ for agent in resolution["agents"]:
745
+ agent_id = agent["agent_id"]
746
+ try:
747
+ # Deploy using single-tier deployment service
748
+ result = deployment_service.deploy_agent(
749
+ agent_id, source_repo=agent.get("source"), dry_run=False
750
+ )
751
+
752
+ if result.get("deployed"):
753
+ deployed_count += 1
754
+ deployed_agents.append(agent_id)
755
+ print(f" āœ“ {agent_id}")
756
+ else:
757
+ failed_count += 1
758
+ failed_agents.append(
759
+ {
760
+ "agent_id": agent_id,
761
+ "error": result.get("error", "Unknown"),
762
+ }
763
+ )
764
+ print(f" āœ— {agent_id}: {result.get('error', 'Failed')}")
765
+
766
+ except Exception as e:
767
+ failed_count += 1
768
+ failed_agents.append({"agent_id": agent_id, "error": str(e)})
769
+ print(f" āœ— {agent_id}: {e}")
770
+
771
+ # Summary
772
+ print(f"\n{'=' * 60}")
773
+ print("šŸ“Š Deployment Summary")
774
+ print(f"{'=' * 60}")
775
+ print(f" āœ… Deployed: {deployed_count}")
776
+ print(f" āŒ Failed: {failed_count}")
777
+ print(f" ā­ļø Skipped: {skipped_count} (missing from sources)")
778
+ print(f"{'=' * 60}\n")
779
+
780
+ if failed_agents:
781
+ print("āŒ Failed agents:")
782
+ for failure in failed_agents:
783
+ print(f" • {failure['agent_id']}: {failure['error']}")
784
+ print()
785
+
786
+ if deployed_count > 0:
787
+ print(f"āœ… Successfully deployed {deployed_count} agents!")
788
+ return CommandResult.success_result(
789
+ f"Deployed {deployed_count} agents from preset '{preset_name}'",
790
+ data={
791
+ "preset": preset_name,
792
+ "deployed": deployed_agents,
793
+ "failed": failed_agents,
794
+ "skipped": resolution["missing_agents"],
795
+ },
796
+ )
797
+ return CommandResult.error_result(
798
+ f"No agents deployed from preset '{preset_name}'",
799
+ data={
800
+ "preset": preset_name,
801
+ "failed": failed_agents,
802
+ "skipped": resolution["missing_agents"],
803
+ },
804
+ )
805
+
806
+ except Exception as e:
807
+ self.logger.error(f"Error deploying preset: {e}", exc_info=True)
808
+ print(f"\nāŒ Error deploying preset: {e}")
809
+ return CommandResult.error_result(f"Error deploying preset: {e}")
810
+
811
+ def _clean_agents(self, args) -> CommandResult:
812
+ """Clean deployed agents."""
813
+ try:
814
+ result = self.cleanup_service.clean_deployed_agents()
815
+
816
+ output_format = self._get_output_format(args)
817
+ dry_run = False # Regular clean is not a dry run
818
+
819
+ formatted = self._formatter.format_cleanup_result(
820
+ result, output_format=output_format, dry_run=dry_run
821
+ )
822
+ print(formatted)
823
+
824
+ cleaned_count = result.get("cleaned_count", 0)
825
+ return CommandResult.success_result(
826
+ f"Cleaned {cleaned_count} agents", data=result
827
+ )
828
+
829
+ except Exception as e:
830
+ self.logger.error(f"Error cleaning agents: {e}", exc_info=True)
831
+ return CommandResult.error_result(f"Error cleaning agents: {e}")
832
+
833
+ def _view_agent(self, args) -> CommandResult:
834
+ """View details of a specific agent."""
835
+ try:
836
+ agent_name = getattr(args, "agent_name", None)
837
+ if not agent_name:
838
+ return CommandResult.error_result(
839
+ "Agent name is required for view command"
840
+ )
841
+
842
+ # Get agent details from listing service
843
+ agent_details = self.listing_service.get_agent_details(agent_name)
844
+
845
+ if not agent_details:
846
+ # Try to find the agent to provide helpful error message
847
+ agent = self.listing_service.find_agent(agent_name)
848
+ if not agent:
849
+ return CommandResult.error_result(f"Agent '{agent_name}' not found")
850
+ return CommandResult.error_result(
851
+ f"Could not retrieve details for agent '{agent_name}'"
852
+ )
853
+
854
+ output_format = self._get_output_format(args)
855
+ verbose = getattr(args, "verbose", False)
856
+
857
+ formatted = self._formatter.format_agent_details(
858
+ agent_details, output_format=output_format, verbose=verbose
859
+ )
860
+ print(formatted)
861
+
862
+ return CommandResult.success_result(
863
+ f"Displayed details for {agent_name}", data=agent_details
864
+ )
865
+
866
+ except Exception as e:
867
+ self.logger.error(f"Error viewing agent: {e}", exc_info=True)
868
+ return CommandResult.error_result(f"Error viewing agent: {e}")
869
+
870
+ def _fix_agents(self, args) -> CommandResult:
871
+ """Fix agent frontmatter issues using validation service."""
872
+ try:
873
+ dry_run = getattr(args, "dry_run", False)
874
+ agent_name = getattr(args, "agent_name", None)
875
+ fix_all = getattr(args, "all", False)
876
+ output_format = self._get_output_format(args)
877
+
878
+ # Route to appropriate handler based on input
879
+ if fix_all:
880
+ return self._fix_all_agents(dry_run, output_format)
881
+ if agent_name:
882
+ return self._fix_single_agent(agent_name, dry_run, output_format)
883
+ return self._handle_no_agent_specified(output_format)
884
+
885
+ except Exception as e:
886
+ self.logger.error(f"Error fixing agents: {e}", exc_info=True)
887
+ return CommandResult.error_result(f"Error fixing agents: {e}")
888
+
889
+ def _fix_all_agents(self, dry_run: bool, output_format: str) -> CommandResult:
890
+ """Fix all agents' frontmatter issues."""
891
+ result = self.validation_service.fix_all_agents(dry_run=dry_run)
892
+
893
+ if self._is_structured_format(output_format):
894
+ self._print_structured_output(result, output_format)
102
895
  else:
103
- for agent in verification["agents_found"]:
104
- print(f"šŸ“„ {agent['file']}")
105
- if 'name' in agent:
106
- print(f" Name: {agent['name']}")
107
- print(f" Path: {agent['path']}")
896
+ self._print_all_agents_text_output(result, dry_run)
897
+
898
+ msg = f"{'Would fix' if dry_run else 'Fixed'} {result.get('total_corrections_available' if dry_run else 'total_corrections_made', 0)} issues"
899
+ return CommandResult.success_result(msg, data=result)
900
+
901
+ def _fix_single_agent(
902
+ self, agent_name: str, dry_run: bool, output_format: str
903
+ ) -> CommandResult:
904
+ """Fix a single agent's frontmatter issues."""
905
+ result = self.validation_service.fix_agent_frontmatter(
906
+ agent_name, dry_run=dry_run
907
+ )
908
+
909
+ if not result.get("success"):
910
+ return CommandResult.error_result(
911
+ result.get("error", "Failed to fix agent")
912
+ )
913
+
914
+ if self._is_structured_format(output_format):
915
+ self._print_structured_output(result, output_format)
916
+ else:
917
+ self._print_single_agent_text_output(agent_name, result, dry_run)
918
+
919
+ msg = f"{'Would fix' if dry_run else 'Fixed'} agent '{agent_name}'"
920
+ return CommandResult.success_result(msg, data=result)
921
+
922
+ def _handle_no_agent_specified(self, output_format: str) -> CommandResult:
923
+ """Handle case where no agent is specified."""
924
+ usage_msg = "Please specify an agent name or use --all to fix all agents\nUsage: claude-mpm agents fix [agent_name] [--dry-run] [--all]"
925
+ if self._is_structured_format(output_format):
926
+ return CommandResult.error_result(
927
+ "No agent specified", data={"usage": usage_msg}
928
+ )
929
+ print(f"āŒ {usage_msg}")
930
+ return CommandResult.error_result("No agent specified")
931
+
932
+ def _print_structured_output(self, result: dict, output_format: str) -> None:
933
+ """Print result in JSON or YAML format."""
934
+ formatted = (
935
+ self._formatter.format_as_json(result)
936
+ if str(output_format).lower() == OutputFormat.JSON
937
+ else self._formatter.format_as_yaml(result)
938
+ )
939
+ print(formatted)
940
+
941
+ def _print_all_agents_text_output(self, result: dict, dry_run: bool) -> None:
942
+ """Print text output for all agents fix operation."""
943
+ mode = "DRY RUN" if dry_run else "FIX"
944
+ print(
945
+ f"\nšŸ”§ {mode}: Checking {result.get('total_agents', 0)} agent(s) for frontmatter issues...\n"
946
+ )
947
+
948
+ if result.get("results"):
949
+ for agent_result in result["results"]:
950
+ self._print_agent_result(agent_result, dry_run)
951
+
952
+ self._print_all_agents_summary(result, dry_run)
953
+
954
+ def _print_agent_result(self, agent_result: dict, dry_run: bool) -> None:
955
+ """Print result for a single agent."""
956
+ print(f"šŸ“„ {agent_result['agent']}:")
957
+ if agent_result.get("skipped"):
958
+ print(f" āš ļø Skipped: {agent_result.get('reason', 'Unknown reason')}")
959
+ elif agent_result.get("was_valid"):
960
+ print(" āœ“ No issues found")
961
+ else:
962
+ self._print_agent_issues(agent_result, dry_run)
963
+ print()
964
+
965
+ def _print_agent_issues(self, agent_result: dict, dry_run: bool) -> None:
966
+ """Print issues found for an agent."""
967
+ if agent_result.get("errors_found", 0) > 0:
968
+ print(f" āŒ Errors found: {agent_result['errors_found']}")
969
+ if agent_result.get("warnings_found", 0) > 0:
970
+ print(f" āš ļø Warnings found: {agent_result['warnings_found']}")
971
+
972
+ if dry_run:
973
+ if agent_result.get("corrections_available", 0) > 0:
974
+ print(f" šŸ”§ Would fix: {agent_result['corrections_available']} issues")
975
+ elif agent_result.get("corrections_made", 0) > 0:
976
+ print(f" āœ“ Fixed: {agent_result['corrections_made']} issues")
977
+
978
+ def _print_all_agents_summary(self, result: dict, dry_run: bool) -> None:
979
+ """Print summary for all agents fix operation."""
980
+ print("=" * 80)
981
+ print("SUMMARY:")
982
+ print(f" Agents checked: {result.get('agents_checked', 0)}")
983
+ print(f" Total issues found: {result.get('total_issues_found', 0)}")
984
+
985
+ if dry_run:
986
+ print(
987
+ f" Issues that would be fixed: {result.get('total_corrections_available', 0)}"
988
+ )
989
+ print("\nšŸ’” Run without --dry-run to apply fixes")
990
+ else:
991
+ print(f" Issues fixed: {result.get('total_corrections_made', 0)}")
992
+ if result.get("total_corrections_made", 0) > 0:
993
+ print("\nāœ“ Frontmatter issues have been fixed!")
994
+ print("=" * 80 + "\n")
995
+
996
+ def _print_single_agent_text_output(
997
+ self, agent_name: str, result: dict, dry_run: bool
998
+ ) -> None:
999
+ """Print text output for single agent fix operation."""
1000
+ mode = "DRY RUN" if dry_run else "FIX"
1001
+ print(f"\nšŸ”§ {mode}: Checking agent '{agent_name}' for frontmatter issues...\n")
1002
+
1003
+ print(f"šŸ“„ {agent_name}:")
1004
+ if result.get("was_valid"):
1005
+ print(" āœ“ No issues found")
1006
+ else:
1007
+ self._print_single_agent_issues(result, dry_run)
1008
+ print()
1009
+
1010
+ self._print_single_agent_footer(result, dry_run)
1011
+
1012
+ def _print_single_agent_issues(self, result: dict, dry_run: bool) -> None:
1013
+ """Print issues for a single agent."""
1014
+ if result.get("errors_found"):
1015
+ print(" āŒ Errors:")
1016
+ for error in result["errors_found"]:
1017
+ print(f" - {error}")
1018
+
1019
+ if result.get("warnings_found"):
1020
+ print(" āš ļø Warnings:")
1021
+ for warning in result["warnings_found"]:
1022
+ print(f" - {warning}")
1023
+
1024
+ if dry_run:
1025
+ if result.get("corrections_available"):
1026
+ print(" šŸ”§ Would fix:")
1027
+ for correction in result["corrections_available"]:
1028
+ print(f" - {correction}")
1029
+ elif result.get("corrections_made"):
1030
+ print(" āœ“ Fixed:")
1031
+ for correction in result["corrections_made"]:
1032
+ print(f" - {correction}")
1033
+
1034
+ def _print_single_agent_footer(self, result: dict, dry_run: bool) -> None:
1035
+ """Print footer message for single agent fix."""
1036
+ if dry_run and result.get("corrections_available"):
1037
+ print("šŸ’” Run without --dry-run to apply fixes\n")
1038
+ elif not dry_run and result.get("corrections_made"):
1039
+ print("āœ“ Frontmatter issues have been fixed!\n")
1040
+
1041
+ def _check_agent_dependencies(self, args) -> CommandResult:
1042
+ """Check agent dependencies."""
1043
+ try:
1044
+ agent_name = getattr(args, "agent", None)
1045
+ result = self.dependency_service.check_dependencies(agent_name=agent_name)
1046
+
1047
+ if not result["success"]:
1048
+ if "available_agents" in result:
1049
+ print(f"āŒ Agent '{agent_name}' is not deployed")
1050
+ print(
1051
+ f" Available agents: {', '.join(result['available_agents'])}"
1052
+ )
1053
+ return CommandResult.error_result(
1054
+ result.get("error", "Dependency check failed")
1055
+ )
1056
+
1057
+ # Print the formatted report
1058
+ print(result["report"])
1059
+
1060
+ return CommandResult.success_result(
1061
+ "Dependency check completed", data=result
1062
+ )
1063
+
1064
+ except Exception as e:
1065
+ self.logger.error(f"Error checking dependencies: {e}", exc_info=True)
1066
+ return CommandResult.error_result(f"Error checking dependencies: {e}")
1067
+
1068
+ def _install_agent_dependencies(self, args) -> CommandResult:
1069
+ """Install agent dependencies."""
1070
+ try:
1071
+ agent_name = getattr(args, "agent", None)
1072
+ dry_run = getattr(args, "dry_run", False)
1073
+ result = self.dependency_service.install_dependencies(
1074
+ agent_name=agent_name, dry_run=dry_run
1075
+ )
1076
+
1077
+ if not result["success"]:
1078
+ if "available_agents" in result:
1079
+ print(f"āŒ Agent '{agent_name}' is not deployed")
1080
+ print(
1081
+ f" Available agents: {', '.join(result['available_agents'])}"
1082
+ )
1083
+ return CommandResult.error_result(
1084
+ result.get("error", "Installation failed")
1085
+ )
1086
+
1087
+ if result.get("missing_count") == 0:
1088
+ print("āœ… All Python dependencies are already installed")
1089
+ elif dry_run:
1090
+ print(
1091
+ f"Found {len(result['missing_dependencies'])} missing dependencies:"
1092
+ )
1093
+ for dep in result["missing_dependencies"]:
1094
+ print(f" - {dep}")
1095
+ print("\n--dry-run specified, not installing anything")
1096
+ print(f"Would install: {result['install_command']}")
1097
+ else:
1098
+ print(
1099
+ f"āœ… Successfully installed {len(result.get('installed', []))} dependencies"
1100
+ )
1101
+ if result.get("still_missing"):
1102
+ print(
1103
+ f"āš ļø {len(result['still_missing'])} dependencies still missing after installation"
1104
+ )
1105
+ elif result.get("fully_resolved"):
1106
+ print("āœ… All dependencies verified after installation")
1107
+
1108
+ return CommandResult.success_result(
1109
+ "Dependency installation completed", data=result
1110
+ )
1111
+
1112
+ except Exception as e:
1113
+ self.logger.error(f"Error installing dependencies: {e}", exc_info=True)
1114
+ return CommandResult.error_result(f"Error installing dependencies: {e}")
1115
+
1116
+ def _list_agent_dependencies(self, args) -> CommandResult:
1117
+ """List agent dependencies."""
1118
+ try:
1119
+ output_format = self._get_output_format(args)
1120
+ result = self.dependency_service.list_dependencies(
1121
+ format_type=output_format
1122
+ )
1123
+
1124
+ if not result["success"]:
1125
+ return CommandResult.error_result(result.get("error", "Listing failed"))
1126
+
1127
+ # Format output based on requested format
1128
+ if output_format == "pip":
1129
+ for dep in result["dependencies"]:
1130
+ print(dep)
1131
+ elif str(output_format).lower() == OutputFormat.JSON:
1132
+ print(json.dumps(result["data"], indent=2))
1133
+ else: # text format
1134
+ print("=" * 60)
1135
+ print("DEPENDENCIES FROM DEPLOYED AGENTS")
1136
+ print("=" * 60)
108
1137
  print()
109
-
110
- if verification["warnings"]:
111
- print("\nWarnings:")
112
- for warning in verification["warnings"]:
113
- print(f" āš ļø {warning}")
114
-
115
- else:
116
- # Default: show usage
117
- print("Use --system to list system agents or --deployed to list deployed agents")
118
-
119
-
120
- def _deploy_agents(args, deployment_service, force=False):
121
- """
122
- Deploy system agents.
123
-
124
- WHY: Agents need to be deployed to the working directory for Claude Code to use them.
125
- This function handles both regular and forced deployment.
126
-
127
- Args:
128
- args: Command arguments with optional 'target' path
129
- deployment_service: Agent deployment service instance
130
- force: Whether to force rebuild all agents
131
- """
132
- if force:
133
- print("Force deploying all system agents...")
134
- else:
135
- print("Deploying system agents...")
136
-
137
- results = deployment_service.deploy_agents(args.target, force_rebuild=force)
138
-
139
- if results["deployed"]:
140
- print(f"\nāœ“ Successfully deployed {len(results['deployed'])} agents to {results['target_dir']}")
141
- for agent in results["deployed"]:
142
- print(f" - {agent['name']}")
143
-
144
- if force and results.get("updated", []):
145
- print(f"\nāœ“ Updated {len(results['updated'])} agents")
146
- for agent in results["updated"]:
147
- print(f" - {agent['name']}")
148
-
149
- if force and results.get("skipped", []):
150
- print(f"\nāœ“ Skipped {len(results['skipped'])} up-to-date agents")
151
-
152
- if results["errors"]:
153
- print("\nāŒ Errors during deployment:")
154
- for error in results["errors"]:
155
- print(f" - {error}")
156
-
157
- if force:
158
- # Set environment for force deploy
159
- env_vars = deployment_service.set_claude_environment(
160
- args.target.parent if args.target else None
1138
+
1139
+ if result["python_dependencies"]:
1140
+ print(
1141
+ f"Python Dependencies ({len(result['python_dependencies'])}):"
1142
+ )
1143
+ print("-" * 30)
1144
+ for dep in result["python_dependencies"]:
1145
+ print(f" {dep}")
1146
+ print()
1147
+
1148
+ if result["system_dependencies"]:
1149
+ print(
1150
+ f"System Dependencies ({len(result['system_dependencies'])}):"
1151
+ )
1152
+ print("-" * 30)
1153
+ for dep in result["system_dependencies"]:
1154
+ print(f" {dep}")
1155
+ print()
1156
+
1157
+ print("Per-Agent Dependencies:")
1158
+ print("-" * 30)
1159
+ for agent_id in sorted(result["per_agent"].keys()):
1160
+ deps = result["per_agent"][agent_id]
1161
+ python_count = len(deps.get("python", []))
1162
+ system_count = len(deps.get("system", []))
1163
+ if python_count or system_count:
1164
+ print(
1165
+ f" {agent_id}: {python_count} Python, {system_count} System"
1166
+ )
1167
+
1168
+ return CommandResult.success_result(
1169
+ "Dependency listing completed", data=result
1170
+ )
1171
+
1172
+ except Exception as e:
1173
+ self.logger.error(f"Error listing dependencies: {e}", exc_info=True)
1174
+ return CommandResult.error_result(f"Error listing dependencies: {e}")
1175
+
1176
+ def _fix_agent_dependencies(self, args) -> CommandResult:
1177
+ """Fix agent dependency issues."""
1178
+ try:
1179
+ max_retries = getattr(args, "max_retries", 3)
1180
+ agent_name = getattr(args, "agent", None)
1181
+
1182
+ print("=" * 70)
1183
+ print("FIXING AGENT DEPENDENCIES WITH RETRY LOGIC")
1184
+ print("=" * 70)
1185
+ print()
1186
+
1187
+ result = self.dependency_service.fix_dependencies(
1188
+ max_retries=max_retries, agent_name=agent_name
1189
+ )
1190
+
1191
+ if not result["success"]:
1192
+ if "error" in result and "not deployed" in result["error"]:
1193
+ print(f"āŒ {result['error']}")
1194
+ return CommandResult.error_result(result.get("error", "Fix failed"))
1195
+
1196
+ if result.get("message") == "No deployed agents found":
1197
+ print("No deployed agents found")
1198
+ return CommandResult.success_result("No agents to fix")
1199
+
1200
+ if result.get("message") == "All dependencies are already satisfied":
1201
+ print("\nāœ… All dependencies are already satisfied!")
1202
+ return CommandResult.success_result("All dependencies satisfied")
1203
+
1204
+ # Show what's missing
1205
+ if result.get("missing_python"):
1206
+ print(f"\nāŒ Missing Python packages: {len(result['missing_python'])}")
1207
+ for pkg in result["missing_python"][:10]:
1208
+ print(f" - {pkg}")
1209
+ if len(result["missing_python"]) > 10:
1210
+ print(f" ... and {len(result['missing_python']) - 10} more")
1211
+
1212
+ if result.get("missing_system"):
1213
+ print(f"\nāŒ Missing system commands: {len(result['missing_system'])}")
1214
+ for cmd in result["missing_system"]:
1215
+ print(f" - {cmd}")
1216
+ print("\nāš ļø System dependencies must be installed manually:")
1217
+ print(f" macOS: brew install {' '.join(result['missing_system'])}")
1218
+ print(f" Ubuntu: apt-get install {' '.join(result['missing_system'])}")
1219
+
1220
+ # Show incompatible packages
1221
+ if result.get("incompatible"):
1222
+ print(
1223
+ f"\nāš ļø Skipping {len(result['incompatible'])} incompatible packages:"
1224
+ )
1225
+ for pkg in result["incompatible"][:5]:
1226
+ print(f" - {pkg}")
1227
+ if len(result["incompatible"]) > 5:
1228
+ print(f" ... and {len(result['incompatible']) - 5} more")
1229
+
1230
+ # Show installation results
1231
+ if result.get("fixed_python") or result.get("failed_python"):
1232
+ print("\n" + "=" * 70)
1233
+ print("INSTALLATION RESULTS:")
1234
+ print("=" * 70)
1235
+
1236
+ if result.get("fixed_python"):
1237
+ print(
1238
+ f"āœ… Successfully installed: {len(result['fixed_python'])} packages"
1239
+ )
1240
+
1241
+ if result.get("failed_python"):
1242
+ print(
1243
+ f"āŒ Failed to install: {len(result['failed_python'])} packages"
1244
+ )
1245
+ errors = result.get("errors", {})
1246
+ for pkg in result["failed_python"]:
1247
+ print(f" - {pkg}: {errors.get(pkg, 'Unknown error')}")
1248
+
1249
+ # Final verification
1250
+ if result.get("still_missing") is not None:
1251
+ if not result["still_missing"]:
1252
+ print("\nāœ… All Python dependencies are now satisfied!")
1253
+ else:
1254
+ print(
1255
+ f"\nāš ļø Still missing {len(result['still_missing'])} packages"
1256
+ )
1257
+ print("\nTry running again or install manually:")
1258
+ missing_sample = result["still_missing"][:3]
1259
+ print(f" pip install {' '.join(missing_sample)}")
1260
+
1261
+ print("\n" + "=" * 70)
1262
+ print("DONE")
1263
+ print("=" * 70)
1264
+
1265
+ return CommandResult.success_result("Dependency fix completed", data=result)
1266
+
1267
+ except Exception as e:
1268
+ self.logger.error(f"Error fixing dependencies: {e}", exc_info=True)
1269
+ return CommandResult.error_result(f"Error fixing dependencies: {e}")
1270
+
1271
+ def _handle_cleanup_command(self, args) -> CommandResult:
1272
+ """Handle cleanup command with proper result wrapping."""
1273
+ exit_code = handle_agents_cleanup(args)
1274
+ return CommandResult(
1275
+ success=exit_code == 0,
1276
+ message=(
1277
+ "Agent cleanup complete" if exit_code == 0 else "Agent cleanup failed"
1278
+ ),
161
1279
  )
162
- print(f"\nāœ“ Set Claude environment variables:")
163
- for key, value in env_vars.items():
164
- print(f" - {key}={value}")
165
1280
 
1281
+ def _cleanup_orphaned_agents(self, args) -> CommandResult:
1282
+ """Clean up orphaned agents that don't have templates."""
1283
+ try:
1284
+ # Determine agents directory
1285
+ agents_dir = None
1286
+ if hasattr(args, "agents_dir") and args.agents_dir:
1287
+ agents_dir = args.agents_dir
1288
+
1289
+ # Determine if we're doing a dry run
1290
+ dry_run = getattr(args, "dry_run", True)
1291
+ if hasattr(args, "force") and args.force:
1292
+ dry_run = False
1293
+
1294
+ # Perform cleanup using the cleanup service
1295
+ results = self.cleanup_service.clean_orphaned_agents(
1296
+ agents_dir=agents_dir, dry_run=dry_run
1297
+ )
1298
+
1299
+ output_format = self._get_output_format(args)
1300
+
1301
+ formatted = self._formatter.format_cleanup_result(
1302
+ results, output_format=output_format, dry_run=dry_run
1303
+ )
1304
+ print(formatted)
1305
+
1306
+ # Determine success/error based on results
1307
+ if results.get("errors") and not dry_run:
1308
+ return CommandResult.error_result(
1309
+ f"Cleanup completed with {len(results['errors'])} errors",
1310
+ data=results,
1311
+ )
1312
+
1313
+ return CommandResult.success_result(
1314
+ f"Cleanup {'preview' if dry_run else 'completed'}", data=results
1315
+ )
1316
+
1317
+ except Exception as e:
1318
+ self.logger.error(f"Error during cleanup: {e}", exc_info=True)
1319
+ return CommandResult.error_result(f"Error during cleanup: {e}")
1320
+
1321
+ def _create_local_agent(self, args) -> CommandResult:
1322
+ """Create a new local agent template."""
1323
+ try:
1324
+ if getattr(args, "interactive", False):
1325
+ # Launch interactive wizard
1326
+ from ..interactive.agent_wizard import run_interactive_agent_wizard
1327
+
1328
+ exit_code = run_interactive_agent_wizard()
1329
+ if exit_code == 0:
1330
+ return CommandResult.success_result("Agent created successfully")
1331
+ return CommandResult.error_result("Agent creation cancelled or failed")
1332
+
1333
+ # Non-interactive creation
1334
+ from ...services.agents.local_template_manager import (
1335
+ LocalAgentTemplateManager,
1336
+ )
1337
+
1338
+ agent_id = getattr(args, "agent_id", None)
1339
+ if not agent_id:
1340
+ return CommandResult.error_result(
1341
+ "--agent-id is required for non-interactive creation"
1342
+ )
1343
+
1344
+ manager = LocalAgentTemplateManager()
1345
+ name = getattr(args, "name", agent_id.replace("-", " ").title())
1346
+ model = getattr(args, "model", "sonnet")
1347
+ inherit_from = getattr(args, "inherit_from", None)
1348
+
1349
+ # Create basic template
1350
+ template = manager.create_local_template(
1351
+ agent_id=agent_id,
1352
+ name=name,
1353
+ description=f"Local agent: {name}",
1354
+ instructions="# Agent Instructions\n\nCustomize this agent's behavior here.",
1355
+ model=model,
1356
+ parent_agent=inherit_from,
1357
+ tier="project",
1358
+ )
1359
+
1360
+ if template:
1361
+ return CommandResult.success_result(
1362
+ f"Created local agent '{agent_id}' in .claude-mpm/agents/",
1363
+ data={
1364
+ "agent_id": agent_id,
1365
+ "path": f".claude-mpm/agents/{agent_id}.json",
1366
+ },
1367
+ )
1368
+ return CommandResult.error_result("Failed to create agent template")
1369
+
1370
+ except Exception as e:
1371
+ self.logger.error(f"Error creating local agent: {e}", exc_info=True)
1372
+ return CommandResult.error_result(f"Error creating local agent: {e}")
1373
+
1374
+ def _edit_local_agent(self, args) -> CommandResult:
1375
+ """Edit a local agent template."""
1376
+ try:
1377
+ agent_id = getattr(args, "agent_id", None)
1378
+ if not agent_id:
1379
+ return CommandResult.error_result("agent_id is required")
166
1380
 
167
- def _clean_agents(args, deployment_service):
1381
+ import os
1382
+ import subprocess # nosec B404
1383
+
1384
+ from ...services.agents.local_template_manager import (
1385
+ LocalAgentTemplateManager,
1386
+ )
1387
+
1388
+ manager = LocalAgentTemplateManager()
1389
+ template = manager.get_local_template(agent_id)
1390
+
1391
+ if not template:
1392
+ return CommandResult.error_result(f"Local agent '{agent_id}' not found")
1393
+
1394
+ # Get template file path
1395
+ template_file = None
1396
+ if template.tier == "project":
1397
+ template_file = manager.project_agents_dir / f"{agent_id}.json"
1398
+ else:
1399
+ template_file = manager.user_agents_dir / f"{agent_id}.json"
1400
+
1401
+ if not template_file or not template_file.exists():
1402
+ return CommandResult.error_result(
1403
+ f"Template file not found for '{agent_id}'"
1404
+ )
1405
+
1406
+ if getattr(args, "interactive", False):
1407
+ # Launch interactive editor
1408
+ from ..interactive.agent_wizard import AgentWizard
1409
+
1410
+ wizard = AgentWizard()
1411
+ success, message = wizard._edit_agent_config(template)
1412
+ if success:
1413
+ return CommandResult.success_result(message)
1414
+ return CommandResult.error_result(message)
1415
+
1416
+ # Use system editor
1417
+ editor = getattr(args, "editor", None) or os.environ.get("EDITOR", "nano")
1418
+ subprocess.run([editor, str(template_file)], check=True) # nosec B603
1419
+ return CommandResult.success_result(
1420
+ f"Agent '{agent_id}' edited successfully"
1421
+ )
1422
+
1423
+ except subprocess.CalledProcessError:
1424
+ return CommandResult.error_result("Editor exited with error")
1425
+ except Exception as e:
1426
+ self.logger.error(f"Error editing local agent: {e}", exc_info=True)
1427
+ return CommandResult.error_result(f"Error editing local agent: {e}")
1428
+
1429
+ def _delete_local_agent(self, args) -> CommandResult:
1430
+ """Delete local agent templates."""
1431
+ try:
1432
+ agent_ids = getattr(args, "agent_ids", [])
1433
+ if not agent_ids:
1434
+ return CommandResult.error_result("No agent IDs specified")
1435
+
1436
+ from ...services.agents.local_template_manager import (
1437
+ LocalAgentTemplateManager,
1438
+ )
1439
+
1440
+ manager = LocalAgentTemplateManager()
1441
+ force = getattr(args, "force", False)
1442
+ keep_deployment = getattr(args, "keep_deployment", False)
1443
+ backup = getattr(args, "backup", False)
1444
+
1445
+ # Confirmation if not forced
1446
+ if not force:
1447
+ print(f"\nāš ļø This will delete {len(agent_ids)} agent(s):")
1448
+ for agent_id in agent_ids:
1449
+ print(f" - {agent_id}")
1450
+ confirm = input("\nAre you sure? [y/N]: ").strip().lower()
1451
+ if confirm not in ["y", "yes"]:
1452
+ return CommandResult.error_result("Deletion cancelled")
1453
+
1454
+ # Delete agents
1455
+ if len(agent_ids) == 1:
1456
+ result = manager.delete_local_template(
1457
+ agent_id=agent_ids[0],
1458
+ tier="all",
1459
+ delete_deployment=not keep_deployment,
1460
+ backup_first=backup,
1461
+ )
1462
+ if result["success"]:
1463
+ message = f"Successfully deleted agent '{agent_ids[0]}'"
1464
+ if result["backup_location"]:
1465
+ message += f"\nBackup saved to: {result['backup_location']}"
1466
+ return CommandResult.success_result(message, data=result)
1467
+ return CommandResult.error_result(
1468
+ f"Failed to delete agent: {', '.join(result['errors'])}"
1469
+ )
1470
+ results = manager.delete_multiple_templates(
1471
+ agent_ids=agent_ids,
1472
+ tier="all",
1473
+ delete_deployment=not keep_deployment,
1474
+ backup_first=backup,
1475
+ )
1476
+
1477
+ message = ""
1478
+ if results["successful"]:
1479
+ message = (
1480
+ f"Successfully deleted {len(results['successful'])} agent(s):\n"
1481
+ )
1482
+ for agent_id in results["successful"]:
1483
+ message += f" - {agent_id}\n"
1484
+
1485
+ if results["failed"]:
1486
+ if message:
1487
+ message += "\n"
1488
+ message += f"Failed to delete {len(results['failed'])} agent(s):\n"
1489
+ for agent_id in results["failed"]:
1490
+ errors = results["details"][agent_id]["errors"]
1491
+ message += f" - {agent_id}: {', '.join(errors)}\n"
1492
+
1493
+ if results["successful"]:
1494
+ return CommandResult.success_result(message.strip(), data=results)
1495
+ return CommandResult.error_result(message.strip(), data=results)
1496
+
1497
+ except Exception as e:
1498
+ self.logger.error(f"Error deleting local agents: {e}", exc_info=True)
1499
+ return CommandResult.error_result(f"Error deleting local agents: {e}")
1500
+
1501
+ def _manage_local_agents(self, args) -> CommandResult:
1502
+ """Redirect to main configuration interface (DEPRECATED)."""
1503
+ try:
1504
+ from rich.console import Console
1505
+ from rich.prompt import Confirm
1506
+
1507
+ console = Console()
1508
+
1509
+ console.print(
1510
+ "\n[bold cyan]╭─────────────────────────────────────────╮[/bold cyan]"
1511
+ )
1512
+ console.print(
1513
+ "[bold cyan]│ Agent Management Has Moved! │[/bold cyan]"
1514
+ )
1515
+ console.print(
1516
+ "[bold cyan]╰─────────────────────────────────────────╯[/bold cyan]\n"
1517
+ )
1518
+
1519
+ console.print("For a better experience with integrated configuration:")
1520
+ console.print(" • Agent management")
1521
+ console.print(" • Skills management")
1522
+ console.print(" • Startup settings\n")
1523
+
1524
+ console.print("Please use: [bold green]claude-mpm config[/bold green]\n")
1525
+
1526
+ if Confirm.ask("Launch configuration interface now?", default=True):
1527
+ # Import and run config command directly
1528
+ from claude_mpm.cli.commands.configure import ConfigureCommand
1529
+
1530
+ config_cmd = ConfigureCommand()
1531
+ return config_cmd.execute(args)
1532
+ console.print(
1533
+ "\n[dim]Run 'claude-mpm config' anytime to access agent management[/dim]"
1534
+ )
1535
+ return CommandResult.success_result("Redirected to config interface")
1536
+
1537
+ except Exception as e:
1538
+ self.logger.error(f"Error redirecting to config: {e}", exc_info=True)
1539
+ return CommandResult.error_result(f"Error redirecting to config: {e}")
1540
+
1541
+ def _configure_deployment(self, args) -> CommandResult:
1542
+ """Configure agent deployment settings."""
1543
+ try:
1544
+ from pathlib import Path
1545
+
1546
+ import yaml
1547
+
1548
+ from claude_mpm.core.config import Config
1549
+
1550
+ config = Config()
1551
+ config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
1552
+
1553
+ # Handle show command
1554
+ if getattr(args, "show", False):
1555
+ from ...services.agents.deployment.deployment_config_loader import (
1556
+ DeploymentConfigLoader,
1557
+ )
1558
+
1559
+ loader = DeploymentConfigLoader(self.logger)
1560
+ settings = loader.get_deployment_settings(config)
1561
+
1562
+ print("\nšŸ“‹ Agent Deployment Configuration")
1563
+ print("=" * 50)
1564
+ print(f"Configuration file: {config_path}")
1565
+ print("\nšŸ”§ Deployment Settings:")
1566
+ print(f" Deploy system agents: {settings['deploy_system_agents']}")
1567
+ print(f" Deploy local agents: {settings['deploy_local_agents']}")
1568
+ print(f" Deploy user agents: {settings['deploy_user_agents']}")
1569
+ print(
1570
+ f" Prefer local over system: {settings['prefer_local_over_system']}"
1571
+ )
1572
+ print(f" Version comparison: {settings['version_comparison']}")
1573
+
1574
+ if settings["enabled_agents"]:
1575
+ print(
1576
+ f"\nāœ… Enabled agents: {', '.join(settings['enabled_agents'])}"
1577
+ )
1578
+ else:
1579
+ print("\nāœ… Enabled agents: All (no restrictions)")
1580
+
1581
+ if settings["disabled_agents"]:
1582
+ print(
1583
+ f"āŒ Disabled agents: {', '.join(settings['disabled_agents'])}"
1584
+ )
1585
+ else:
1586
+ print("āŒ Disabled agents: None")
1587
+
1588
+ print("\n" + "=" * 50)
1589
+ return CommandResult.success_result(
1590
+ "Displayed deployment configuration"
1591
+ )
1592
+
1593
+ # Handle interactive mode
1594
+ if getattr(args, "interactive", False):
1595
+ return self._configure_deployment_interactive(config_path)
1596
+
1597
+ # Load current configuration
1598
+ if not config_path.exists():
1599
+ config_path.parent.mkdir(parents=True, exist_ok=True)
1600
+ config_data = {}
1601
+ else:
1602
+ with config_path.open() as f:
1603
+ config_data = yaml.safe_load(f) or {}
1604
+
1605
+ # Ensure agent_deployment section exists
1606
+ if "agent_deployment" not in config_data:
1607
+ config_data["agent_deployment"] = {}
1608
+
1609
+ modified = False
1610
+
1611
+ # Handle enable/disable operations
1612
+ if getattr(args, "enable_all", False):
1613
+ config_data["agent_deployment"]["enabled_agents"] = []
1614
+ config_data["agent_deployment"]["disabled_agents"] = []
1615
+ print("āœ… Enabled all agents for deployment")
1616
+ modified = True
1617
+
1618
+ if getattr(args, "enable_system", False):
1619
+ config_data["agent_deployment"]["deploy_system_agents"] = True
1620
+ print("āœ… Enabled system agents for deployment")
1621
+ modified = True
1622
+
1623
+ if getattr(args, "disable_system", False):
1624
+ config_data["agent_deployment"]["deploy_system_agents"] = False
1625
+ print("āŒ Disabled system agents from deployment")
1626
+ modified = True
1627
+
1628
+ if getattr(args, "enable_local", False):
1629
+ config_data["agent_deployment"]["deploy_local_agents"] = True
1630
+ print("āœ… Enabled local agents for deployment")
1631
+ modified = True
1632
+
1633
+ if getattr(args, "disable_local", False):
1634
+ config_data["agent_deployment"]["deploy_local_agents"] = False
1635
+ print("āŒ Disabled local agents from deployment")
1636
+ modified = True
1637
+
1638
+ if getattr(args, "enable", None):
1639
+ enabled = config_data["agent_deployment"].get("enabled_agents", [])
1640
+ disabled = config_data["agent_deployment"].get("disabled_agents", [])
1641
+
1642
+ for agent_id in args.enable:
1643
+ if agent_id not in enabled:
1644
+ enabled.append(agent_id)
1645
+ if agent_id in disabled:
1646
+ disabled.remove(agent_id)
1647
+
1648
+ config_data["agent_deployment"]["enabled_agents"] = enabled
1649
+ config_data["agent_deployment"]["disabled_agents"] = disabled
1650
+ print(f"āœ… Enabled agents: {', '.join(args.enable)}")
1651
+ modified = True
1652
+
1653
+ if getattr(args, "disable", None):
1654
+ disabled = config_data["agent_deployment"].get("disabled_agents", [])
1655
+
1656
+ for agent_id in args.disable:
1657
+ if agent_id not in disabled:
1658
+ disabled.append(agent_id)
1659
+
1660
+ config_data["agent_deployment"]["disabled_agents"] = disabled
1661
+ print(f"āŒ Disabled agents: {', '.join(args.disable)}")
1662
+ modified = True
1663
+
1664
+ # Save configuration if modified
1665
+ if modified:
1666
+ with config_path.open("w") as f:
1667
+ yaml.dump(config_data, f, default_flow_style=False, sort_keys=False)
1668
+ print(f"\nšŸ’¾ Configuration saved to {config_path}")
1669
+ return CommandResult.success_result("Deployment configuration updated")
1670
+
1671
+ # If no modifications were made and not showing, display help
1672
+ if not getattr(args, "show", False):
1673
+ print("No configuration changes specified. Use --help for options.")
1674
+ return CommandResult.success_result("No changes made")
1675
+
1676
+ except Exception as e:
1677
+ self.logger.error(f"Error configuring deployment: {e}", exc_info=True)
1678
+ return CommandResult.error_result(f"Error configuring deployment: {e}")
1679
+
1680
+ def _configure_deployment_interactive(self, config_path: Path) -> CommandResult:
1681
+ """Interactive mode for configuring agent deployment."""
1682
+ try:
1683
+ import yaml
1684
+
1685
+ from ...utils.ui_helpers import (
1686
+ prompt_choice,
1687
+ prompt_multiselect,
1688
+ prompt_yes_no,
1689
+ )
1690
+
1691
+ # Load current configuration
1692
+ if config_path.exists():
1693
+ with config_path.open() as f:
1694
+ config_data = yaml.safe_load(f) or {}
1695
+ else:
1696
+ config_data = {}
1697
+
1698
+ if "agent_deployment" not in config_data:
1699
+ config_data["agent_deployment"] = {}
1700
+
1701
+ settings = config_data["agent_deployment"]
1702
+
1703
+ print("\nšŸŽ® Interactive Agent Deployment Configuration")
1704
+ print("=" * 50)
1705
+
1706
+ # Configure source types
1707
+ settings["deploy_system_agents"] = prompt_yes_no(
1708
+ "Deploy system agents?",
1709
+ default=settings.get("deploy_system_agents", True),
1710
+ )
1711
+
1712
+ settings["deploy_local_agents"] = prompt_yes_no(
1713
+ "Deploy local project agents?",
1714
+ default=settings.get("deploy_local_agents", True),
1715
+ )
1716
+
1717
+ settings["deploy_user_agents"] = prompt_yes_no(
1718
+ "Deploy user-level agents?",
1719
+ default=settings.get("deploy_user_agents", True),
1720
+ )
1721
+
1722
+ # Configure version behavior
1723
+ settings["prefer_local_over_system"] = prompt_yes_no(
1724
+ "Should local agents override system agents with same ID?",
1725
+ default=settings.get("prefer_local_over_system", True),
1726
+ )
1727
+
1728
+ settings["version_comparison"] = prompt_yes_no(
1729
+ "Compare versions across sources and deploy highest?",
1730
+ default=settings.get("version_comparison", True),
1731
+ )
1732
+
1733
+ # Configure specific agents
1734
+ choice = prompt_choice(
1735
+ "How would you like to configure specific agents?",
1736
+ [
1737
+ "No restrictions (all agents enabled)",
1738
+ "Specify disabled agents",
1739
+ "Specify enabled agents only",
1740
+ ],
1741
+ )
1742
+
1743
+ if choice == "No restrictions (all agents enabled)":
1744
+ settings["enabled_agents"] = []
1745
+ settings["disabled_agents"] = []
1746
+ elif choice == "Specify disabled agents":
1747
+ # Get list of available agents
1748
+ from ...services.agents.listing_service import AgentListingService
1749
+
1750
+ listing_service = AgentListingService()
1751
+ agents, _ = listing_service.list_all_agents()
1752
+ agent_ids = sorted({agent.name for agent in agents})
1753
+
1754
+ if agent_ids:
1755
+ disabled = prompt_multiselect(
1756
+ "Select agents to disable:",
1757
+ agent_ids,
1758
+ default=settings.get("disabled_agents", []),
1759
+ )
1760
+ settings["disabled_agents"] = disabled
1761
+ settings["enabled_agents"] = []
1762
+ else:
1763
+ print("No agents found to configure")
1764
+ else: # Specify enabled agents only
1765
+ from ...services.agents.listing_service import AgentListingService
1766
+
1767
+ listing_service = AgentListingService()
1768
+ agents, _ = listing_service.list_all_agents()
1769
+ agent_ids = sorted({agent.name for agent in agents})
1770
+
1771
+ if agent_ids:
1772
+ enabled = prompt_multiselect(
1773
+ "Select agents to enable (others will be disabled):",
1774
+ agent_ids,
1775
+ default=settings.get("enabled_agents", []),
1776
+ )
1777
+ settings["enabled_agents"] = enabled
1778
+ settings["disabled_agents"] = []
1779
+ else:
1780
+ print("No agents found to configure")
1781
+
1782
+ # Save configuration
1783
+ config_data["agent_deployment"] = settings
1784
+
1785
+ # Ensure parent directory exists
1786
+ config_path.parent.mkdir(parents=True, exist_ok=True)
1787
+
1788
+ with config_path.open("w") as f:
1789
+ yaml.dump(config_data, f, default_flow_style=False, sort_keys=False)
1790
+
1791
+ print(f"\nāœ… Configuration saved to {config_path}")
1792
+
1793
+ # Show summary
1794
+ print("\nšŸ“‹ New Configuration Summary:")
1795
+ print(
1796
+ f" System agents: {'Enabled' if settings.get('deploy_system_agents', True) else 'Disabled'}"
1797
+ )
1798
+ print(
1799
+ f" Local agents: {'Enabled' if settings.get('deploy_local_agents', True) else 'Disabled'}"
1800
+ )
1801
+ print(
1802
+ f" User agents: {'Enabled' if settings.get('deploy_user_agents', True) else 'Disabled'}"
1803
+ )
1804
+
1805
+ if settings.get("enabled_agents"):
1806
+ print(f" Enabled specific: {', '.join(settings['enabled_agents'])}")
1807
+ elif settings.get("disabled_agents"):
1808
+ print(f" Disabled specific: {', '.join(settings['disabled_agents'])}")
1809
+ else:
1810
+ print(" All agents enabled")
1811
+
1812
+ return CommandResult.success_result("Interactive configuration completed")
1813
+
1814
+ except KeyboardInterrupt:
1815
+ print("\n\nConfiguration cancelled.")
1816
+ return CommandResult.error_result("Configuration cancelled by user")
1817
+ except Exception as e:
1818
+ self.logger.error(f"Error in interactive configuration: {e}", exc_info=True)
1819
+ return CommandResult.error_result(
1820
+ f"Error in interactive configuration: {e}"
1821
+ )
1822
+
1823
+ def _migrate_to_project(self, args) -> CommandResult:
1824
+ """Migrate user-level agents to project-level.
1825
+
1826
+ DEPRECATION: User-level agents (~/.claude-mpm/agents/) are deprecated and
1827
+ will be removed in v5.0.0. This command migrates them to project-level
1828
+ (.claude-mpm/agents/) where they belong.
1829
+
1830
+ Args:
1831
+ args: Command arguments with dry_run and force flags
1832
+
1833
+ Returns:
1834
+ CommandResult with migration status
1835
+ """
1836
+ import shutil
1837
+
1838
+ try:
1839
+ user_agents_dir = Path.home() / ".claude-mpm" / "agents"
1840
+ project_agents_dir = Path.cwd() / ".claude-mpm" / "agents"
1841
+
1842
+ dry_run = getattr(args, "dry_run", False)
1843
+ force = getattr(args, "force", False)
1844
+
1845
+ # Check if user agents directory exists
1846
+ if not user_agents_dir.exists():
1847
+ print("āœ… No user-level agents found. Nothing to migrate.")
1848
+ return CommandResult.success_result("No user-level agents to migrate")
1849
+
1850
+ # Find all user agent files
1851
+ user_agent_files = list(user_agents_dir.glob("*.json")) + list(
1852
+ user_agents_dir.glob("*.md")
1853
+ )
1854
+
1855
+ if not user_agent_files:
1856
+ print("āœ… No user-level agents found. Nothing to migrate.")
1857
+ return CommandResult.success_result("No user-level agents to migrate")
1858
+
1859
+ # Display what we found
1860
+ print(f"\nšŸ“¦ Found {len(user_agent_files)} user-level agent(s) to migrate:")
1861
+ for agent_file in user_agent_files:
1862
+ print(f" - {agent_file.name}")
1863
+
1864
+ if dry_run:
1865
+ print("\nšŸ” DRY RUN: Would migrate to:")
1866
+ print(f" → {project_agents_dir}")
1867
+ print("\nRun without --dry-run to perform the migration.")
1868
+ return CommandResult.success_result(
1869
+ "Dry run completed",
1870
+ data={
1871
+ "user_agents_found": len(user_agent_files),
1872
+ "target_directory": str(project_agents_dir),
1873
+ },
1874
+ )
1875
+
1876
+ # Create project agents directory
1877
+ project_agents_dir.mkdir(parents=True, exist_ok=True)
1878
+
1879
+ # Migrate agents
1880
+ migrated = 0
1881
+ skipped = 0
1882
+ errors = []
1883
+
1884
+ for agent_file in user_agent_files:
1885
+ target_file = project_agents_dir / agent_file.name
1886
+
1887
+ # Check for conflicts
1888
+ if target_file.exists() and not force:
1889
+ print(f"āš ļø Skipping {agent_file.name} (already exists in project)")
1890
+ print(" Use --force to overwrite existing agents")
1891
+ skipped += 1
1892
+ continue
1893
+
1894
+ try:
1895
+ # Copy agent to project directory
1896
+ shutil.copy2(agent_file, target_file)
1897
+ migrated += 1
1898
+ print(f"āœ… Migrated {agent_file.name}")
1899
+ except Exception as e:
1900
+ error_msg = f"Failed to migrate {agent_file.name}: {e}"
1901
+ errors.append(error_msg)
1902
+ print(f"āŒ {error_msg}")
1903
+
1904
+ # Summary
1905
+ print("\nšŸ“Š Migration Summary:")
1906
+ print(f" āœ… Migrated: {migrated}/{len(user_agent_files)}")
1907
+ if skipped > 0:
1908
+ print(f" ā­ļø Skipped: {skipped} (already exist)")
1909
+ if errors:
1910
+ print(f" āŒ Errors: {len(errors)}")
1911
+
1912
+ if migrated > 0:
1913
+ print(f"\nāœ… Successfully migrated {migrated} agent(s) to:")
1914
+ print(f" {project_agents_dir}")
1915
+ print(
1916
+ "\nāš ļø IMPORTANT: Verify agents work correctly, then remove user-level agents:"
1917
+ )
1918
+ print(f" rm -rf {user_agents_dir}")
1919
+ print("\nšŸ’” Why this change?")
1920
+ print(" - Project isolation: Each project has its own agents")
1921
+ print(" - Version control: Agents can be versioned with your code")
1922
+ print(" - Team consistency: Everyone uses the same agents")
1923
+
1924
+ return CommandResult.success_result(
1925
+ f"Migrated {migrated} agents",
1926
+ data={
1927
+ "migrated": migrated,
1928
+ "skipped": skipped,
1929
+ "errors": errors,
1930
+ "total": len(user_agent_files),
1931
+ },
1932
+ )
1933
+
1934
+ except Exception as e:
1935
+ self.logger.error(f"Error migrating agents: {e}", exc_info=True)
1936
+ return CommandResult.error_result(f"Error migrating agents: {e}")
1937
+
1938
+ def _deploy_minimal_configuration(self, args) -> CommandResult:
1939
+ """Deploy minimal configuration (6 core agents).
1940
+
1941
+ Part of Phase 3 (1M-382): Agent Selection Modes.
1942
+ Deploy exactly 6 agents for basic Claude MPM workflow:
1943
+ engineer, documentation, qa, research, ops, ticketing.
1944
+ """
1945
+ try:
1946
+ from ...config.agent_sources import AgentSourceConfiguration
1947
+ from ...services.agents.agent_selection_service import AgentSelectionService
1948
+ from ...services.agents.single_tier_deployment_service import (
1949
+ SingleTierDeploymentService,
1950
+ )
1951
+
1952
+ # Initialize services
1953
+ config = AgentSourceConfiguration.load()
1954
+ deployment_dir = Path.home() / ".claude" / "agents"
1955
+ deployment_service = SingleTierDeploymentService(config, deployment_dir)
1956
+ selection_service = AgentSelectionService(deployment_service)
1957
+
1958
+ # Get dry_run flag
1959
+ dry_run = getattr(args, "dry_run", False)
1960
+
1961
+ # Deploy minimal configuration
1962
+ print("šŸŽÆ Deploying minimal configuration (6 core agents)...")
1963
+ if dry_run:
1964
+ print("šŸ” DRY RUN MODE - No agents will be deployed\n")
1965
+
1966
+ result = selection_service.deploy_minimal_configuration(dry_run=dry_run)
1967
+
1968
+ # Format output
1969
+ output_format = self._get_output_format(args)
1970
+ if self._is_structured_format(output_format):
1971
+ formatted = (
1972
+ self._formatter.format_as_json(result)
1973
+ if str(output_format).lower() == OutputFormat.JSON
1974
+ else self._formatter.format_as_yaml(result)
1975
+ )
1976
+ print(formatted)
1977
+ return CommandResult.success_result(
1978
+ f"Minimal configuration {result['status']}", data=result
1979
+ )
1980
+
1981
+ # Text output
1982
+ print(f"\n{'=' * 60}")
1983
+ print(f"Status: {result['status'].upper()}")
1984
+ print(f"Mode: {result['mode']}")
1985
+ print(f"{'=' * 60}")
1986
+ print(
1987
+ f"\nšŸ“Š Summary: {result['deployed_count']} deployed, "
1988
+ f"{result['failed_count']} failed, {result['missing_count']} missing"
1989
+ )
1990
+
1991
+ if result["deployed_agents"]:
1992
+ print(f"\nāœ… Deployed agents ({len(result['deployed_agents'])}):")
1993
+ for agent in result["deployed_agents"]:
1994
+ print(f" • {agent}")
1995
+
1996
+ if result["failed_agents"]:
1997
+ print(f"\nāŒ Failed agents ({len(result['failed_agents'])}):")
1998
+ for agent in result["failed_agents"]:
1999
+ print(f" • {agent}")
2000
+
2001
+ if result["missing_agents"]:
2002
+ print(f"\nāš ļø Missing agents ({len(result['missing_agents'])}):")
2003
+ for agent in result["missing_agents"]:
2004
+ print(f" • {agent}")
2005
+ print("\nThese agents are not available in configured sources.")
2006
+
2007
+ if dry_run:
2008
+ print(
2009
+ "\nšŸ’” This was a dry run. Run without --dry-run to deploy agents."
2010
+ )
2011
+
2012
+ return CommandResult.success_result(
2013
+ f"Minimal configuration {result['status']}", data=result
2014
+ )
2015
+
2016
+ except Exception as e:
2017
+ self.logger.error(
2018
+ f"Error deploying minimal configuration: {e}", exc_info=True
2019
+ )
2020
+ return CommandResult.error_result(
2021
+ f"Error deploying minimal configuration: {e}"
2022
+ )
2023
+
2024
+ def _deploy_auto_configure(self, args) -> CommandResult:
2025
+ """Auto-detect toolchain and deploy matching agents.
2026
+
2027
+ Part of Phase 3 (1M-382): Agent Selection Modes.
2028
+ Detect project toolchain (languages, frameworks, build tools) and
2029
+ deploy matching specialized agents.
2030
+ """
2031
+ try:
2032
+ from ...config.agent_sources import AgentSourceConfiguration
2033
+ from ...services.agents.agent_selection_service import AgentSelectionService
2034
+ from ...services.agents.single_tier_deployment_service import (
2035
+ SingleTierDeploymentService,
2036
+ )
2037
+
2038
+ # Initialize services
2039
+ config = AgentSourceConfiguration.load()
2040
+ deployment_dir = Path.home() / ".claude" / "agents"
2041
+ deployment_service = SingleTierDeploymentService(config, deployment_dir)
2042
+ selection_service = AgentSelectionService(deployment_service)
2043
+
2044
+ # Get arguments
2045
+ project_path = getattr(args, "path", Path.cwd())
2046
+ dry_run = getattr(args, "dry_run", False)
2047
+
2048
+ # Deploy auto-configure
2049
+ print(f"šŸ” Auto-detecting toolchain in {project_path}...")
2050
+ if dry_run:
2051
+ print("šŸ” DRY RUN MODE - No agents will be deployed\n")
2052
+
2053
+ result = selection_service.deploy_auto_configure(
2054
+ project_path=project_path, dry_run=dry_run
2055
+ )
2056
+
2057
+ # Format output
2058
+ output_format = self._get_output_format(args)
2059
+ if self._is_structured_format(output_format):
2060
+ formatted = (
2061
+ self._formatter.format_as_json(result)
2062
+ if str(output_format).lower() == OutputFormat.JSON
2063
+ else self._formatter.format_as_yaml(result)
2064
+ )
2065
+ print(formatted)
2066
+ return CommandResult.success_result(
2067
+ f"Auto-configure {result['status']}", data=result
2068
+ )
2069
+
2070
+ # Text output
2071
+ print(f"\n{'=' * 60}")
2072
+ print(f"Status: {result['status'].upper()}")
2073
+ print(f"Mode: {result['mode']}")
2074
+ print(f"{'=' * 60}")
2075
+
2076
+ # Show detected toolchain
2077
+ toolchain = result.get("toolchain", {})
2078
+ print("\nšŸ”§ Detected Toolchain:")
2079
+ if toolchain.get("languages"):
2080
+ print(f" Languages: {', '.join(toolchain['languages'])}")
2081
+ if toolchain.get("frameworks"):
2082
+ print(f" Frameworks: {', '.join(toolchain['frameworks'])}")
2083
+ if toolchain.get("build_tools"):
2084
+ print(f" Build Tools: {', '.join(toolchain['build_tools'])}")
2085
+
2086
+ if not any(toolchain.values()):
2087
+ print(" (No toolchain detected)")
2088
+
2089
+ # Show recommended agents
2090
+ recommended = result.get("recommended_agents", [])
2091
+ if recommended:
2092
+ print(f"\nšŸŽÆ Recommended agents ({len(recommended)}):")
2093
+ for agent in recommended:
2094
+ print(f" • {agent}")
2095
+
2096
+ # Show deployment summary
2097
+ print(
2098
+ f"\nšŸ“Š Summary: {result['deployed_count']} deployed, "
2099
+ f"{result['failed_count']} failed, {result['missing_count']} missing"
2100
+ )
2101
+
2102
+ if result.get("deployed_agents"):
2103
+ print(f"\nāœ… Deployed agents ({len(result['deployed_agents'])}):")
2104
+ for agent in result["deployed_agents"]:
2105
+ print(f" • {agent}")
2106
+
2107
+ if result.get("failed_agents"):
2108
+ print(f"\nāŒ Failed agents ({len(result['failed_agents'])}):")
2109
+ for agent in result["failed_agents"]:
2110
+ print(f" • {agent}")
2111
+
2112
+ if result.get("missing_agents"):
2113
+ print(f"\nāš ļø Missing agents ({len(result['missing_agents'])}):")
2114
+ for agent in result["missing_agents"]:
2115
+ print(f" • {agent}")
2116
+ print("\nThese agents are not available in configured sources.")
2117
+
2118
+ if dry_run:
2119
+ print(
2120
+ "\nšŸ’” This was a dry run. Run without --dry-run to deploy agents."
2121
+ )
2122
+
2123
+ return CommandResult.success_result(
2124
+ f"Auto-configure {result['status']}", data=result
2125
+ )
2126
+
2127
+ except Exception as e:
2128
+ self.logger.error(f"Error in auto-configure: {e}", exc_info=True)
2129
+ return CommandResult.error_result(f"Error in auto-configure: {e}")
2130
+
2131
+ def _list_collections(self, args) -> CommandResult:
2132
+ """List all available agent collections.
2133
+
2134
+ NEW: Shows all collections with agent counts and metadata.
2135
+ Enables discovery of available agent collections before deployment.
2136
+ """
2137
+ try:
2138
+ from pathlib import Path
2139
+
2140
+ from ...services.agents.deployment.remote_agent_discovery_service import (
2141
+ RemoteAgentDiscoveryService,
2142
+ )
2143
+
2144
+ # Get remote agents cache directory
2145
+ cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
2146
+
2147
+ if not cache_dir.exists():
2148
+ return CommandResult.error_result(
2149
+ "No remote agent collections found. Run 'claude-mpm agents deploy' first."
2150
+ )
2151
+
2152
+ # Use RemoteAgentDiscoveryService to list collections
2153
+ remote_service = RemoteAgentDiscoveryService(cache_dir)
2154
+ collections = remote_service.list_collections()
2155
+
2156
+ if not collections:
2157
+ return CommandResult.success_result(
2158
+ "No agent collections found in cache.", data={"collections": []}
2159
+ )
2160
+
2161
+ # Format output
2162
+ output_lines = ["Available Agent Collections:\n"]
2163
+ for collection in collections:
2164
+ output_lines.append(
2165
+ f" • {collection['collection_id']} ({collection['agent_count']} agents)"
2166
+ )
2167
+
2168
+ return CommandResult.success_result(
2169
+ "\n".join(output_lines), data={"collections": collections}
2170
+ )
2171
+
2172
+ except Exception as e:
2173
+ self.logger.error(f"Error listing collections: {e}", exc_info=True)
2174
+ return CommandResult.error_result(f"Error listing collections: {e}")
2175
+
2176
+ def _deploy_collection(self, args) -> CommandResult:
2177
+ """Deploy all agents from a specific collection.
2178
+
2179
+ NEW: Enables bulk deployment of all agents from a named collection.
2180
+ Useful for deploying entire agent sets at once.
2181
+ """
2182
+ try:
2183
+ from pathlib import Path
2184
+
2185
+ from ...services.agents.deployment.multi_source_deployment_service import (
2186
+ MultiSourceAgentDeploymentService,
2187
+ )
2188
+
2189
+ collection_id = args.collection_id
2190
+
2191
+ # Get agents from collection
2192
+ service = MultiSourceAgentDeploymentService()
2193
+ cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
2194
+ agents = service.get_agents_by_collection(collection_id, cache_dir)
2195
+
2196
+ if not agents:
2197
+ return CommandResult.error_result(
2198
+ f"No agents found in collection '{collection_id}'"
2199
+ )
2200
+
2201
+ # Dry run mode
2202
+ if getattr(args, "dry_run", False):
2203
+ agent_names = [
2204
+ agent.get("metadata", {}).get("name", "Unknown") for agent in agents
2205
+ ]
2206
+ output = f"Would deploy {len(agents)} agents from collection '{collection_id}':\n"
2207
+ for name in agent_names:
2208
+ output += f" • {name}\n"
2209
+ return CommandResult.success_result(
2210
+ output,
2211
+ data={"collection_id": collection_id, "agent_count": len(agents)},
2212
+ )
2213
+
2214
+ # Deploy agents
2215
+ # TODO: Implement actual deployment logic using deployment service
2216
+ # For now, show what would be deployed
2217
+ return CommandResult.success_result(
2218
+ f"Deployment of collection '{collection_id}' would deploy {len(agents)} agents.\n"
2219
+ f"(Full deployment implementation pending)",
2220
+ data={
2221
+ "collection_id": collection_id,
2222
+ "agent_count": len(agents),
2223
+ "status": "pending_implementation",
2224
+ },
2225
+ )
2226
+
2227
+ except Exception as e:
2228
+ self.logger.error(f"Error deploying collection: {e}", exc_info=True)
2229
+ return CommandResult.error_result(f"Error deploying collection: {e}")
2230
+
2231
+ def _list_by_collection(self, args) -> CommandResult:
2232
+ """List agents from a specific collection.
2233
+
2234
+ NEW: Shows detailed information about agents in a collection.
2235
+ Supports multiple output formats (table, json, yaml).
2236
+ """
2237
+ try:
2238
+ import json as json_lib
2239
+ from pathlib import Path
2240
+
2241
+ from ...services.agents.deployment.multi_source_deployment_service import (
2242
+ MultiSourceAgentDeploymentService,
2243
+ )
2244
+
2245
+ collection_id = args.collection_id
2246
+ output_format = getattr(args, "format", "table")
2247
+
2248
+ # Get agents from collection
2249
+ service = MultiSourceAgentDeploymentService()
2250
+ cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
2251
+ agents = service.get_agents_by_collection(collection_id, cache_dir)
2252
+
2253
+ if not agents:
2254
+ return CommandResult.error_result(
2255
+ f"No agents found in collection '{collection_id}'"
2256
+ )
2257
+
2258
+ # Format output based on requested format
2259
+ if output_format == "json":
2260
+ return CommandResult.success_result(
2261
+ json_lib.dumps(agents, indent=2),
2262
+ data={"collection_id": collection_id, "agents": agents},
2263
+ )
2264
+ if output_format == "yaml":
2265
+ try:
2266
+ import yaml
2267
+
2268
+ return CommandResult.success_result(
2269
+ yaml.dump(agents, default_flow_style=False),
2270
+ data={"collection_id": collection_id, "agents": agents},
2271
+ )
2272
+ except ImportError:
2273
+ return CommandResult.error_result(
2274
+ "YAML support not available (install PyYAML)"
2275
+ )
2276
+
2277
+ # Table format (default)
2278
+ output_lines = [f"Agents in collection '{collection_id}':\n"]
2279
+ for agent in agents:
2280
+ metadata = agent.get("metadata", {})
2281
+ name = metadata.get("name", "Unknown")
2282
+ description = metadata.get("description", "No description")
2283
+ version = agent.get("version", "unknown")
2284
+ output_lines.append(f" • {name} (v{version})")
2285
+ output_lines.append(f" {description}\n")
2286
+
2287
+ return CommandResult.success_result(
2288
+ "\n".join(output_lines),
2289
+ data={"collection_id": collection_id, "agent_count": len(agents)},
2290
+ )
2291
+
2292
+ except Exception as e:
2293
+ self.logger.error(f"Error listing collection agents: {e}", exc_info=True)
2294
+ return CommandResult.error_result(f"Error listing collection agents: {e}")
2295
+
2296
+ def _cache_status(self, args) -> CommandResult:
2297
+ """Show git status of agent cache.
2298
+
2299
+ Displays current branch, uncommitted changes, unpushed commits, and
2300
+ remote URL for the agent cache repository.
2301
+ """
2302
+ try:
2303
+ from ...services.agents.cache_git_manager import CacheGitManager
2304
+
2305
+ cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
2306
+ manager = CacheGitManager(cache_dir)
2307
+
2308
+ if not manager.is_git_repo():
2309
+ print("āŒ Cache is not a git repository")
2310
+ print(f"\nCache location: {cache_dir}")
2311
+ print(
2312
+ "\nšŸ’” This is expected if you haven't cloned the agents repository."
2313
+ )
2314
+ print(" The cache will be managed via HTTP sync instead.")
2315
+ return CommandResult.error_result("Cache is not a git repository")
2316
+
2317
+ status = manager.get_status()
2318
+ output_format = self._get_output_format(args)
2319
+
2320
+ if self._is_structured_format(output_format):
2321
+ formatted = (
2322
+ self._formatter.format_as_json(status)
2323
+ if str(output_format).lower() == OutputFormat.JSON
2324
+ else self._formatter.format_as_yaml(status)
2325
+ )
2326
+ print(formatted)
2327
+ return CommandResult.success_result(
2328
+ "Cache status retrieved", data=status
2329
+ )
2330
+
2331
+ # Text output
2332
+ print(f"\nšŸ“ Cache: {manager.repo_path}")
2333
+ print(f"🌿 Branch: {status.get('branch', 'unknown')}")
2334
+
2335
+ if status.get("remote_url"):
2336
+ print(f"šŸ”— Remote: {status['remote_url']}")
2337
+
2338
+ # Show sync status
2339
+ ahead = status.get("ahead", 0)
2340
+ behind = status.get("behind", 0)
2341
+
2342
+ if ahead > 0:
2343
+ print(f"šŸ“¤ Ahead of remote: {ahead} commit(s)")
2344
+ if behind > 0:
2345
+ print(f"šŸ“„ Behind remote: {behind} commit(s)")
2346
+
2347
+ if ahead == 0 and behind == 0:
2348
+ print("āœ… In sync with remote")
2349
+
2350
+ # Show uncommitted changes
2351
+ uncommitted = status.get("uncommitted", [])
2352
+ if uncommitted:
2353
+ print(f"\nāš ļø Uncommitted changes: {len(uncommitted)}")
2354
+ for file in uncommitted[:10]: # Show max 10 files
2355
+ print(f" - {file}")
2356
+ if len(uncommitted) > 10:
2357
+ print(f" ... and {len(uncommitted) - 10} more")
2358
+ else:
2359
+ print("\nāœ… No uncommitted changes")
2360
+
2361
+ # Overall status
2362
+ if status.get("is_clean"):
2363
+ print("\n✨ Cache is clean and up-to-date")
2364
+ else:
2365
+ print("\nšŸ’” Run 'claude-mpm agents cache-sync' to sync with remote")
2366
+
2367
+ return CommandResult.success_result("Cache status displayed", data=status)
2368
+
2369
+ except Exception as e:
2370
+ self.logger.error(f"Error getting cache status: {e}", exc_info=True)
2371
+ return CommandResult.error_result(f"Error getting cache status: {e}")
2372
+
2373
+ def _cache_pull(self, args) -> CommandResult:
2374
+ """Pull latest agents from remote repository."""
2375
+ try:
2376
+ from ...services.agents.cache_git_manager import CacheGitManager
2377
+
2378
+ cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
2379
+ manager = CacheGitManager(cache_dir)
2380
+
2381
+ if not manager.is_git_repo():
2382
+ print("āŒ Cache is not a git repository")
2383
+ return CommandResult.error_result("Cache is not a git repository")
2384
+
2385
+ branch = getattr(args, "branch", "main")
2386
+ print(f"šŸ”„ Pulling latest changes from {branch}...")
2387
+
2388
+ success, msg = manager.pull_latest(branch)
2389
+
2390
+ if success:
2391
+ print(f"āœ… {msg}")
2392
+ return CommandResult.success_result(msg)
2393
+ print(f"āŒ {msg}")
2394
+ return CommandResult.error_result(msg)
2395
+
2396
+ except Exception as e:
2397
+ self.logger.error(f"Error pulling cache: {e}", exc_info=True)
2398
+ return CommandResult.error_result(f"Error pulling cache: {e}")
2399
+
2400
+ def _cache_commit(self, args) -> CommandResult:
2401
+ """Commit changes to cache repository."""
2402
+ try:
2403
+ from ...services.agents.cache_git_manager import CacheGitManager
2404
+
2405
+ cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
2406
+ manager = CacheGitManager(cache_dir)
2407
+
2408
+ if not manager.is_git_repo():
2409
+ print("āŒ Cache is not a git repository")
2410
+ return CommandResult.error_result("Cache is not a git repository")
2411
+
2412
+ # Get commit message from args
2413
+ message = getattr(args, "message", None)
2414
+ if not message:
2415
+ # Default message
2416
+ message = "feat: update agents from local development"
2417
+
2418
+ print("šŸ’¾ Committing changes...")
2419
+ success, msg = manager.commit_changes(message)
2420
+
2421
+ if success:
2422
+ print(f"āœ… {msg}")
2423
+ print(f"\nšŸ’” Commit message: {message}")
2424
+ return CommandResult.success_result(msg)
2425
+ print(f"āŒ {msg}")
2426
+ return CommandResult.error_result(msg)
2427
+
2428
+ except Exception as e:
2429
+ self.logger.error(f"Error committing cache changes: {e}", exc_info=True)
2430
+ return CommandResult.error_result(f"Error committing cache changes: {e}")
2431
+
2432
+ def _cache_push(self, args) -> CommandResult:
2433
+ """Push local agent changes to remote."""
2434
+ try:
2435
+ from ...services.agents.cache_git_manager import CacheGitManager
2436
+
2437
+ cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
2438
+ manager = CacheGitManager(cache_dir)
2439
+
2440
+ if not manager.is_git_repo():
2441
+ print("āŒ Cache is not a git repository")
2442
+ return CommandResult.error_result("Cache is not a git repository")
2443
+
2444
+ # Check for uncommitted changes
2445
+ if manager.has_uncommitted_changes():
2446
+ print("āš ļø You have uncommitted changes.")
2447
+ print("\nšŸ’” Commit changes first with:")
2448
+ print(" claude-mpm agents cache-commit --message 'your message'")
2449
+
2450
+ # Ask if user wants to commit first
2451
+ auto_commit = getattr(args, "auto_commit", False)
2452
+ if auto_commit:
2453
+ print("\nšŸ“ Auto-committing changes...")
2454
+ success, msg = manager.commit_changes("feat: update agents")
2455
+ if not success:
2456
+ print(f"āŒ Commit failed: {msg}")
2457
+ return CommandResult.error_result(f"Commit failed: {msg}")
2458
+ print(f"āœ… {msg}")
2459
+ else:
2460
+ return CommandResult.error_result(
2461
+ "Uncommitted changes detected. Commit first or use --auto-commit"
2462
+ )
2463
+
2464
+ # Push changes
2465
+ branch = getattr(args, "branch", "main")
2466
+ print(f"šŸ“¤ Pushing changes to {branch}...")
2467
+
2468
+ success, msg = manager.push_changes(branch)
2469
+
2470
+ if success:
2471
+ print(f"āœ… {msg}")
2472
+ return CommandResult.success_result(msg)
2473
+ print(f"āŒ {msg}")
2474
+ return CommandResult.error_result(msg)
2475
+
2476
+ except Exception as e:
2477
+ self.logger.error(f"Error pushing cache: {e}", exc_info=True)
2478
+ return CommandResult.error_result(f"Error pushing cache: {e}")
2479
+
2480
+ def _cache_sync(self, args) -> CommandResult:
2481
+ """Full cache sync: pull, commit (if needed), push."""
2482
+ try:
2483
+ from ...services.agents.cache_git_manager import CacheGitManager
2484
+
2485
+ cache_dir = Path.home() / ".claude-mpm" / "cache" / "agents"
2486
+ manager = CacheGitManager(cache_dir)
2487
+
2488
+ if not manager.is_git_repo():
2489
+ print("āŒ Cache is not a git repository")
2490
+ return CommandResult.error_result("Cache is not a git repository")
2491
+
2492
+ print("šŸ”„ Syncing cache with remote...\n")
2493
+
2494
+ success, msg = manager.sync_with_remote()
2495
+
2496
+ # Print detailed sync message
2497
+ print(msg)
2498
+
2499
+ if success:
2500
+ print("\n✨ Cache sync complete!")
2501
+ return CommandResult.success_result("Cache synced successfully")
2502
+
2503
+ print("\nāŒ Cache sync failed. See details above.")
2504
+ return CommandResult.error_result("Cache sync failed")
2505
+
2506
+ except Exception as e:
2507
+ self.logger.error(f"Error syncing cache: {e}", exc_info=True)
2508
+ return CommandResult.error_result(f"Error syncing cache: {e}")
2509
+
2510
+
2511
+ def manage_agents(args):
168
2512
  """
169
- Clean deployed system agents.
170
-
171
- WHY: Users may want to remove deployed agents to start fresh or clean up
172
- their working directory.
173
-
174
- Args:
175
- args: Command arguments with optional 'target' path
176
- deployment_service: Agent deployment service instance
2513
+ Main entry point for agent management commands.
2514
+
2515
+ This function maintains backward compatibility while using the new AgentCommand pattern.
177
2516
  """
178
- print("Cleaning deployed system agents...")
179
- results = deployment_service.clean_deployment(args.target)
180
-
181
- if results["removed"]:
182
- print(f"\nāœ“ Removed {len(results['removed'])} agents")
183
- for path in results["removed"]:
184
- print(f" - {Path(path).name}")
185
- else:
186
- print("No system agents found to remove")
187
-
188
- if results["errors"]:
189
- print("\nāŒ Errors during cleanup:")
190
- for error in results["errors"]:
191
- print(f" - {error}")
2517
+ command = AgentsCommand()
2518
+ result = command.execute(args)
2519
+
2520
+ # Print result if structured output format is requested
2521
+ if _is_structured_output(args):
2522
+ command.print_result(result, args)
2523
+
2524
+ return result.exit_code