claude-mpm 4.21.3__py3-none-any.whl → 5.0.2__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 (484) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +12 -0
  3. claude_mpm/agents/OUTPUT_STYLE.md +3 -48
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +632 -334
  5. claude_mpm/agents/WORKFLOW.md +75 -2
  6. claude_mpm/agents/__init__.py +6 -0
  7. claude_mpm/agents/agent_loader.py +1 -4
  8. claude_mpm/agents/base_agent.json +6 -3
  9. claude_mpm/agents/frontmatter_validator.py +1 -1
  10. claude_mpm/agents/templates/{circuit_breakers.md → circuit-breakers.md} +370 -3
  11. claude_mpm/agents/templates/context-management-examples.md +544 -0
  12. claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +89 -19
  13. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  14. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  15. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  16. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  17. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  18. claude_mpm/cli/__init__.py +38 -2
  19. claude_mpm/cli/commands/agent_source.py +774 -0
  20. claude_mpm/cli/commands/agent_state_manager.py +125 -20
  21. claude_mpm/cli/commands/agents.py +684 -13
  22. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  23. claude_mpm/cli/commands/agents_discover.py +338 -0
  24. claude_mpm/cli/commands/aggregate.py +1 -1
  25. claude_mpm/cli/commands/analyze.py +3 -3
  26. claude_mpm/cli/commands/auto_configure.py +2 -6
  27. claude_mpm/cli/commands/cleanup.py +1 -1
  28. claude_mpm/cli/commands/config.py +7 -4
  29. claude_mpm/cli/commands/configure.py +478 -44
  30. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  31. claude_mpm/cli/commands/configure_navigation.py +63 -46
  32. claude_mpm/cli/commands/debug.py +12 -12
  33. claude_mpm/cli/commands/doctor.py +10 -2
  34. claude_mpm/cli/commands/hook_errors.py +277 -0
  35. claude_mpm/cli/commands/local_deploy.py +1 -4
  36. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  37. claude_mpm/cli/commands/mpm_init/core.py +50 -2
  38. claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
  39. claude_mpm/cli/commands/mpm_init/prompts.py +6 -6
  40. claude_mpm/cli/commands/run.py +124 -128
  41. claude_mpm/cli/commands/skill_source.py +694 -0
  42. claude_mpm/cli/commands/skills.py +435 -1
  43. claude_mpm/cli/executor.py +78 -3
  44. claude_mpm/cli/interactive/agent_wizard.py +919 -41
  45. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  46. claude_mpm/cli/parsers/agents_parser.py +173 -4
  47. claude_mpm/cli/parsers/base_parser.py +49 -0
  48. claude_mpm/cli/parsers/config_parser.py +96 -43
  49. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  50. claude_mpm/cli/parsers/skills_parser.py +138 -0
  51. claude_mpm/cli/parsers/source_parser.py +138 -0
  52. claude_mpm/cli/startup.py +499 -84
  53. claude_mpm/cli/startup_display.py +480 -0
  54. claude_mpm/cli/utils.py +1 -1
  55. claude_mpm/cli_module/commands.py +1 -1
  56. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  57. claude_mpm/commands/mpm-agents-detect.md +9 -0
  58. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  59. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  60. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  61. claude_mpm/commands/mpm-doctor.md +9 -0
  62. claude_mpm/commands/mpm-help.md +11 -2
  63. claude_mpm/commands/mpm-init.md +27 -2
  64. claude_mpm/commands/mpm-monitor.md +9 -0
  65. claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
  66. claude_mpm/commands/mpm-status.md +9 -0
  67. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  68. claude_mpm/commands/mpm-ticket-view.md +552 -0
  69. claude_mpm/commands/mpm-version.md +9 -0
  70. claude_mpm/commands/mpm.md +10 -0
  71. claude_mpm/config/agent_presets.py +258 -0
  72. claude_mpm/config/agent_sources.py +325 -0
  73. claude_mpm/config/skill_sources.py +590 -0
  74. claude_mpm/constants.py +12 -0
  75. claude_mpm/core/api_validator.py +1 -1
  76. claude_mpm/core/claude_runner.py +17 -10
  77. claude_mpm/core/config.py +24 -0
  78. claude_mpm/core/constants.py +1 -1
  79. claude_mpm/core/framework/__init__.py +3 -16
  80. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  81. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  82. claude_mpm/core/hook_error_memory.py +381 -0
  83. claude_mpm/core/hook_manager.py +41 -2
  84. claude_mpm/core/interactive_session.py +112 -5
  85. claude_mpm/core/logger.py +3 -1
  86. claude_mpm/core/oneshot_session.py +94 -4
  87. claude_mpm/dashboard/static/css/activity.css +69 -69
  88. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  89. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  90. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  91. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  92. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  93. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  94. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  95. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  96. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  97. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  98. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  99. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  100. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  101. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  102. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  103. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  104. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  105. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  106. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  107. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  108. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  109. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  110. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  111. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  112. claude_mpm/dashboard/templates/code_simple.html +23 -23
  113. claude_mpm/dashboard/templates/index.html +18 -18
  114. claude_mpm/experimental/cli_enhancements.py +1 -5
  115. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  116. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  117. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  118. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  119. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  120. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  121. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  122. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  123. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  124. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  125. claude_mpm/models/git_repository.py +198 -0
  126. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  127. claude_mpm/scripts/start_activity_logging.py +3 -1
  128. claude_mpm/services/agents/agent_builder.py +45 -9
  129. claude_mpm/services/agents/agent_preset_service.py +238 -0
  130. claude_mpm/services/agents/agent_selection_service.py +484 -0
  131. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  132. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  133. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  134. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  135. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  136. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  137. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  138. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  139. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  140. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  141. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  142. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
  143. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  144. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  145. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
  146. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  147. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  148. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  149. claude_mpm/services/agents/git_source_manager.py +629 -0
  150. claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
  151. claude_mpm/services/agents/local_template_manager.py +50 -10
  152. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  153. claude_mpm/services/agents/sources/__init__.py +13 -0
  154. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  155. claude_mpm/services/agents/sources/git_source_sync_service.py +1055 -0
  156. claude_mpm/services/agents/startup_sync.py +239 -0
  157. claude_mpm/services/agents/toolchain_detector.py +474 -0
  158. claude_mpm/services/cli/session_pause_manager.py +1 -1
  159. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  160. claude_mpm/services/command_deployment_service.py +92 -1
  161. claude_mpm/services/core/interfaces/__init__.py +1 -3
  162. claude_mpm/services/core/interfaces/health.py +1 -4
  163. claude_mpm/services/core/models/__init__.py +2 -11
  164. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  165. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  166. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  167. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  168. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  169. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  170. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  171. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  172. claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
  173. claude_mpm/services/event_bus/direct_relay.py +3 -3
  174. claude_mpm/services/event_bus/event_bus.py +36 -3
  175. claude_mpm/services/events/consumers/logging.py +1 -2
  176. claude_mpm/services/git/__init__.py +21 -0
  177. claude_mpm/services/git/git_operations_service.py +494 -0
  178. claude_mpm/services/github/__init__.py +21 -0
  179. claude_mpm/services/github/github_cli_service.py +397 -0
  180. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  181. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  182. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  183. claude_mpm/services/instructions/__init__.py +9 -0
  184. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  185. claude_mpm/services/local_ops/__init__.py +3 -13
  186. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  187. claude_mpm/services/local_ops/health_manager.py +1 -4
  188. claude_mpm/services/local_ops/process_manager.py +1 -1
  189. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  190. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  191. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  192. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  193. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  194. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  195. claude_mpm/services/memory/optimizer.py +1 -1
  196. claude_mpm/services/model/model_router.py +8 -9
  197. claude_mpm/services/monitor/daemon.py +1 -1
  198. claude_mpm/services/monitor/server.py +2 -2
  199. claude_mpm/services/native_agent_converter.py +356 -0
  200. claude_mpm/services/port_manager.py +1 -1
  201. claude_mpm/services/pr/__init__.py +14 -0
  202. claude_mpm/services/pr/pr_template_service.py +329 -0
  203. claude_mpm/services/project/documentation_manager.py +2 -1
  204. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  205. claude_mpm/services/runner_configuration_service.py +1 -0
  206. claude_mpm/services/self_upgrade_service.py +165 -7
  207. claude_mpm/services/skills/__init__.py +18 -0
  208. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  209. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  210. claude_mpm/services/skills_config.py +547 -0
  211. claude_mpm/services/skills_deployer.py +955 -0
  212. claude_mpm/services/socketio/handlers/connection.py +1 -1
  213. claude_mpm/services/socketio/handlers/git.py +2 -2
  214. claude_mpm/services/socketio/server/core.py +1 -4
  215. claude_mpm/services/socketio/server/main.py +1 -3
  216. claude_mpm/services/system_instructions_service.py +1 -3
  217. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  218. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  219. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  220. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  221. claude_mpm/services/unified/unified_deployment.py +1 -5
  222. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  223. claude_mpm/services/visualization/__init__.py +1 -5
  224. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  225. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  226. claude_mpm/skills/bundled/performance-profiling.md +6 -0
  227. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
  228. claude_mpm/skills/skills_registry.py +0 -1
  229. claude_mpm/templates/questions/__init__.py +38 -0
  230. claude_mpm/templates/questions/base.py +193 -0
  231. claude_mpm/templates/questions/pr_strategy.py +311 -0
  232. claude_mpm/templates/questions/project_init.py +385 -0
  233. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  234. claude_mpm/tools/__main__.py +8 -8
  235. claude_mpm/tools/code_tree_analyzer/analysis.py +1 -1
  236. claude_mpm/utils/agent_dependency_loader.py +80 -13
  237. claude_mpm/utils/dependency_cache.py +3 -1
  238. claude_mpm/utils/gitignore.py +241 -0
  239. claude_mpm/utils/log_cleanup.py +3 -3
  240. claude_mpm/utils/progress.py +383 -0
  241. claude_mpm/utils/robust_installer.py +3 -5
  242. claude_mpm/utils/structured_questions.py +619 -0
  243. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/METADATA +429 -59
  244. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/RECORD +252 -425
  245. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  246. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  247. claude_mpm/agents/templates/agent-manager.json +0 -273
  248. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  249. claude_mpm/agents/templates/api_qa.json +0 -180
  250. claude_mpm/agents/templates/clerk-ops.json +0 -235
  251. claude_mpm/agents/templates/code_analyzer.json +0 -101
  252. claude_mpm/agents/templates/content-agent.json +0 -358
  253. claude_mpm/agents/templates/dart_engineer.json +0 -307
  254. claude_mpm/agents/templates/data_engineer.json +0 -225
  255. claude_mpm/agents/templates/documentation.json +0 -211
  256. claude_mpm/agents/templates/engineer.json +0 -210
  257. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  258. claude_mpm/agents/templates/golang_engineer.json +0 -270
  259. claude_mpm/agents/templates/imagemagick.json +0 -264
  260. claude_mpm/agents/templates/java_engineer.json +0 -346
  261. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  262. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  263. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  264. claude_mpm/agents/templates/memory_manager.json +0 -158
  265. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  266. claude_mpm/agents/templates/ops.json +0 -185
  267. claude_mpm/agents/templates/php-engineer.json +0 -287
  268. claude_mpm/agents/templates/product_owner.json +0 -338
  269. claude_mpm/agents/templates/project_organizer.json +0 -140
  270. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  271. claude_mpm/agents/templates/python_engineer.json +0 -387
  272. claude_mpm/agents/templates/qa.json +0 -242
  273. claude_mpm/agents/templates/react_engineer.json +0 -238
  274. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  275. claude_mpm/agents/templates/research.json +0 -188
  276. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  277. claude_mpm/agents/templates/rust_engineer.json +0 -275
  278. claude_mpm/agents/templates/security.json +0 -202
  279. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  280. claude_mpm/agents/templates/ticketing.json +0 -177
  281. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  282. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  283. claude_mpm/agents/templates/version_control.json +0 -157
  284. claude_mpm/agents/templates/web_qa.json +0 -399
  285. claude_mpm/agents/templates/web_ui.json +0 -189
  286. claude_mpm/commands/mpm-tickets.md +0 -102
  287. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  288. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  289. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  290. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  291. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  292. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  293. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  294. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  295. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  296. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  297. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  298. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  299. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  300. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  301. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  302. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  303. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  304. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  305. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  306. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  307. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  308. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  309. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  310. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  311. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  312. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  313. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  314. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  315. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  316. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  317. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  318. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  319. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  320. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  321. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  322. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  323. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  324. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  325. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  326. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  327. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  328. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  329. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  330. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  331. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  332. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  333. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  334. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  335. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  336. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  337. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  338. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  339. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  340. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  341. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  342. claude_mpm/dashboard/static/built/react/events.js +0 -30
  343. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  344. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  345. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  346. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  347. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  348. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  349. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  350. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  351. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  352. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  353. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  354. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  355. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  356. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  357. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  358. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  359. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  360. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  361. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  362. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  363. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  364. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  365. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  366. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  367. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  368. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  369. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  370. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  371. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  372. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  373. claude_mpm/dashboard/static/events.html +0 -607
  374. claude_mpm/dashboard/static/index.html +0 -635
  375. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  376. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  377. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  378. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  379. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  380. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  381. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  382. claude_mpm/dashboard/static/legacy/files.html +0 -747
  383. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  384. claude_mpm/dashboard/static/monitors.html +0 -431
  385. claude_mpm/dashboard/static/production/events.html +0 -659
  386. claude_mpm/dashboard/static/production/main.html +0 -698
  387. claude_mpm/dashboard/static/production/monitors.html +0 -483
  388. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  389. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  390. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  391. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  392. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  393. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
  394. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
  395. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
  396. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
  397. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
  398. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
  399. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
  400. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
  401. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
  402. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
  403. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
  404. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
  405. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
  406. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
  407. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
  408. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
  409. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
  410. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  411. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  412. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  413. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  414. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  415. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  416. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  417. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  418. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  419. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  420. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
  421. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
  422. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
  423. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
  424. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
  425. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
  426. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
  427. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  428. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  429. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  430. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  431. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
  432. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
  433. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  434. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  435. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  436. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  437. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
  438. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
  439. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
  440. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
  441. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
  442. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
  443. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
  444. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
  445. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
  446. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
  447. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
  448. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
  449. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
  450. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
  451. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
  452. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
  453. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
  454. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
  455. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
  456. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
  457. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
  458. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
  459. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
  460. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  461. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  462. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  463. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  464. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  465. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  466. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
  467. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
  468. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
  469. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
  470. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
  471. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
  472. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
  473. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
  474. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
  475. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
  476. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
  477. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  478. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  479. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  480. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  481. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/WHEEL +0 -0
  482. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/entry_points.txt +0 -0
  483. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/licenses/LICENSE +0 -0
  484. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,696 @@
1
+ """Single-tier agent deployment service using Git sources.
2
+
3
+ This service replaces the multi-tier deployment system with a simpler,
4
+ Git-source-based approach. All agents come from Git repositories with
5
+ priority-based conflict resolution.
6
+
7
+ WHY: The multi-tier system (PROJECT > USER > SYSTEM) added complexity
8
+ without providing clear value. Single-tier with Git sources provides:
9
+ - Simpler mental model (Git repos with priorities)
10
+ - Better version control and collaboration
11
+ - Easier testing and debugging
12
+ - More flexible agent distribution
13
+
14
+ Design Decision: Composition over Inheritance
15
+
16
+ This service composes Phase 1 components (GitSourceManager,
17
+ RemoteAgentDiscoveryService) rather than inheriting. This provides
18
+ better separation of concerns and makes it easier to test each
19
+ component independently.
20
+
21
+ Trade-offs:
22
+ - Flexibility: Easy to swap implementations or mock for testing
23
+ - Complexity: Slightly more code than inheritance
24
+ - Maintainability: Clear boundaries between sync, discovery, and deployment
25
+ """
26
+
27
+ import logging
28
+ import shutil
29
+ from datetime import datetime, timezone
30
+ from pathlib import Path
31
+ from typing import Any, Dict, List, Optional
32
+
33
+ from src.claude_mpm.config.agent_sources import AgentSourceConfiguration
34
+ from src.claude_mpm.models.git_repository import GitRepository
35
+ from src.claude_mpm.services.agents.deployment.remote_agent_discovery_service import (
36
+ RemoteAgentDiscoveryService,
37
+ )
38
+ from src.claude_mpm.services.agents.git_source_manager import GitSourceManager
39
+
40
+ logger = logging.getLogger(__name__)
41
+
42
+
43
+ class SingleTierDeploymentService:
44
+ """Single-tier agent deployment service using Git sources.
45
+
46
+ This service manages agent deployment from Git repositories with
47
+ priority-based conflict resolution. It coordinates:
48
+ - Git repository syncing (via GitSourceManager)
49
+ - Agent discovery from cached repositories
50
+ - Priority-based agent resolution
51
+ - Deployment to .claude/agents/ directory
52
+
53
+ Architecture:
54
+ - Phase 1 GitSourceManager handles repository sync
55
+ - Phase 1 RemoteAgentDiscoveryService discovers agents
56
+ - This service orchestrates deployment workflow
57
+ - Priority system resolves conflicts (lower priority = higher precedence)
58
+
59
+ Example:
60
+ >>> config = AgentSourceConfiguration.load()
61
+ >>> service = SingleTierDeploymentService(
62
+ ... config=config,
63
+ ... deployment_dir=Path.home() / ".claude" / "agents"
64
+ ... )
65
+ >>> result = service.deploy_all_agents(force_sync=True)
66
+ >>> print(f"Deployed {result['deployed_agents']} agents")
67
+ """
68
+
69
+ def __init__(
70
+ self,
71
+ config: AgentSourceConfiguration,
72
+ deployment_dir: Path,
73
+ cache_root: Optional[Path] = None,
74
+ ):
75
+ """Initialize single-tier deployment service.
76
+
77
+ Args:
78
+ config: Agent source configuration with repositories
79
+ deployment_dir: Target deployment directory (.claude/agents/)
80
+ cache_root: Cache root for repositories
81
+ (defaults to ~/.claude-mpm/cache/remote-agents/)
82
+ """
83
+ self.config = config
84
+ self.deployment_dir = deployment_dir
85
+ self.deployment_dir.mkdir(parents=True, exist_ok=True)
86
+
87
+ if cache_root is None:
88
+ cache_root = Path.home() / ".claude-mpm" / "cache" / "remote-agents"
89
+
90
+ self.cache_root = cache_root
91
+ self.git_source_manager = GitSourceManager(cache_root)
92
+
93
+ logger.info(
94
+ f"SingleTierDeploymentService initialized: "
95
+ f"deployment={deployment_dir}, cache={cache_root}"
96
+ )
97
+
98
+ def deploy_all_agents(
99
+ self, force_sync: bool = False, dry_run: bool = False
100
+ ) -> Dict[str, Any]:
101
+ """Deploy all agents from configured Git sources.
102
+
103
+ Workflow:
104
+ 1. Get all enabled repositories from configuration
105
+ 2. Sync repositories (unless cached and not force_sync)
106
+ 3. Discover all agents from all repositories
107
+ 4. Resolve conflicts using priority system (lower = higher precedence)
108
+ 5. Deploy agents to .claude/agents/
109
+ 6. Return deployment report
110
+
111
+ Args:
112
+ force_sync: Force repository sync even if cache is fresh
113
+ dry_run: Show what would be deployed without actually deploying
114
+
115
+ Returns:
116
+ Deployment report dictionary:
117
+ {
118
+ "synced_repos": int, # Repositories successfully synced
119
+ "discovered_agents": int, # Total agents discovered
120
+ "deployed_agents": int, # Agents actually deployed
121
+ "skipped_agents": int, # Agents skipped (dry run or errors)
122
+ "conflicts_resolved": int, # Agent name conflicts resolved
123
+ "timestamp": str, # ISO timestamp
124
+ "agents": [ # Per-agent details
125
+ {
126
+ "name": "engineer",
127
+ "source": "bobmatnyc/claude-mpm-agents",
128
+ "priority": 100,
129
+ "deployed": true
130
+ }
131
+ ]
132
+ }
133
+
134
+ Error Handling:
135
+ - Individual repository sync failures don't stop overall deployment
136
+ - Failed deployments are logged and counted as skipped
137
+ - Returns partial success with error details
138
+ """
139
+ logger.info(
140
+ f"Starting deploy_all_agents (force_sync={force_sync}, dry_run={dry_run})"
141
+ )
142
+
143
+ # Step 1: Get enabled repositories
144
+ repos = self.config.get_enabled_repositories()
145
+ logger.info(f"Found {len(repos)} enabled repositories")
146
+
147
+ if not repos:
148
+ logger.warning("No enabled repositories found")
149
+ return {
150
+ "synced_repos": 0,
151
+ "discovered_agents": 0,
152
+ "deployed_agents": 0,
153
+ "skipped_agents": 0,
154
+ "conflicts_resolved": 0,
155
+ "timestamp": datetime.now(timezone.utc).isoformat(),
156
+ "agents": [],
157
+ }
158
+
159
+ # Step 2: Sync all repositories
160
+ sync_results = self.git_source_manager.sync_all_repositories(repos, force_sync)
161
+ synced_count = sum(1 for r in sync_results.values() if r.get("synced"))
162
+ logger.info(f"Synced {synced_count}/{len(repos)} repositories")
163
+
164
+ # Step 3: Discover all agents from all repositories
165
+ all_agents = []
166
+ for repo in repos:
167
+ try:
168
+ # Discover agents in this repository's cache
169
+ agents = self._discover_agents_in_repo(repo)
170
+ all_agents.extend(agents)
171
+ logger.debug(f"Discovered {len(agents)} agents from {repo.identifier}")
172
+ except Exception as e:
173
+ logger.error(f"Failed to discover agents in {repo.identifier}: {e}")
174
+
175
+ logger.info(f"Discovered {len(all_agents)} total agents")
176
+
177
+ # Step 4: Resolve conflicts (lower priority = higher precedence)
178
+ resolved_agents, conflicts_count = self._resolve_conflicts(all_agents)
179
+ logger.info(
180
+ f"Resolved {conflicts_count} conflicts, {len(resolved_agents)} unique agents"
181
+ )
182
+
183
+ # Step 5: Deploy agents
184
+ deployed_count = 0
185
+ skipped_count = 0
186
+ agent_details = []
187
+
188
+ for agent in resolved_agents:
189
+ agent_name = agent.get("metadata", {}).get("name", "unknown")
190
+ source_repo = agent.get("repository", "unknown")
191
+ priority = agent.get("priority", 100)
192
+
193
+ try:
194
+ if dry_run:
195
+ logger.info(
196
+ f"[DRY RUN] Would deploy {agent_name} from {source_repo}"
197
+ )
198
+ agent_details.append(
199
+ {
200
+ "name": agent_name,
201
+ "source": source_repo,
202
+ "priority": priority,
203
+ "deployed": False,
204
+ "dry_run": True,
205
+ }
206
+ )
207
+ skipped_count += 1
208
+ else:
209
+ # Deploy agent to .claude/agents/
210
+ success = self._deploy_agent_file(agent)
211
+ if success:
212
+ logger.info(f"Deployed {agent_name} from {source_repo}")
213
+ deployed_count += 1
214
+ agent_details.append(
215
+ {
216
+ "name": agent_name,
217
+ "source": source_repo,
218
+ "priority": priority,
219
+ "deployed": True,
220
+ }
221
+ )
222
+ else:
223
+ logger.warning(f"Failed to deploy {agent_name}")
224
+ skipped_count += 1
225
+ agent_details.append(
226
+ {
227
+ "name": agent_name,
228
+ "source": source_repo,
229
+ "priority": priority,
230
+ "deployed": False,
231
+ "error": "deployment_failed",
232
+ }
233
+ )
234
+ except Exception as e:
235
+ logger.error(f"Error deploying {agent_name}: {e}")
236
+ skipped_count += 1
237
+ agent_details.append(
238
+ {
239
+ "name": agent_name,
240
+ "source": source_repo,
241
+ "priority": priority,
242
+ "deployed": False,
243
+ "error": str(e),
244
+ }
245
+ )
246
+
247
+ # Step 6: Build and return report
248
+ report = {
249
+ "synced_repos": synced_count,
250
+ "discovered_agents": len(all_agents),
251
+ "deployed_agents": deployed_count,
252
+ "skipped_agents": skipped_count,
253
+ "conflicts_resolved": conflicts_count,
254
+ "timestamp": datetime.now(timezone.utc).isoformat(),
255
+ "agents": agent_details,
256
+ }
257
+
258
+ logger.info(
259
+ f"Deployment complete: {deployed_count} deployed, "
260
+ f"{skipped_count} skipped, {conflicts_count} conflicts resolved"
261
+ )
262
+
263
+ return report
264
+
265
+ def deploy_agent(
266
+ self, agent_name: str, source_repo: Optional[str] = None, dry_run: bool = False
267
+ ) -> Dict[str, Any]:
268
+ """Deploy a specific agent.
269
+
270
+ Args:
271
+ agent_name: Name of agent to deploy (e.g., "engineer", "research")
272
+ source_repo: Optional specific repository identifier
273
+ (e.g., "owner/repo/subdirectory")
274
+ dry_run: Show what would be deployed without actually deploying
275
+
276
+ Returns:
277
+ Deployment result:
278
+ {
279
+ "deployed": bool,
280
+ "agent_name": str,
281
+ "source": str,
282
+ "priority": int,
283
+ "path": str, # Deployment path (if successful)
284
+ "error": str # Error message (if failed)
285
+ }
286
+
287
+ Error Handling:
288
+ - Returns deployed=False with error message if agent not found
289
+ - Returns deployed=False with error message if deployment fails
290
+ """
291
+ logger.info(f"Deploying agent: {agent_name} (source={source_repo})")
292
+
293
+ # Discover agents (filtered by source_repo if specified)
294
+ if source_repo:
295
+ # Find specific repository
296
+ repos = [
297
+ r
298
+ for r in self.config.get_enabled_repositories()
299
+ if r.identifier == source_repo
300
+ ]
301
+ if not repos:
302
+ return {
303
+ "deployed": False,
304
+ "agent_name": agent_name,
305
+ "error": f"Source repository not found: {source_repo}",
306
+ }
307
+ else:
308
+ repos = self.config.get_enabled_repositories()
309
+
310
+ # Discover agents from repositories
311
+ all_agents = []
312
+ for repo in repos:
313
+ try:
314
+ agents = self._discover_agents_in_repo(repo)
315
+ all_agents.extend(agents)
316
+ except Exception as e:
317
+ logger.warning(f"Failed to discover agents in {repo.identifier}: {e}")
318
+
319
+ # Find matching agent
320
+ matching_agents = [
321
+ a
322
+ for a in all_agents
323
+ if a.get("metadata", {}).get("name", "").lower().replace(" ", "-")
324
+ == agent_name.lower()
325
+ or a.get("agent_id", "") == agent_name.lower()
326
+ ]
327
+
328
+ if not matching_agents:
329
+ return {
330
+ "deployed": False,
331
+ "agent_name": agent_name,
332
+ "error": f"Agent not found: {agent_name}",
333
+ }
334
+
335
+ # Resolve conflicts if multiple sources have same agent
336
+ if len(matching_agents) > 1:
337
+ # Sort by priority (lower = higher precedence)
338
+ matching_agents.sort(key=lambda a: a.get("priority", 100))
339
+ logger.info(
340
+ f"Multiple sources for {agent_name}, using highest priority "
341
+ f"(priority={matching_agents[0].get('priority')})"
342
+ )
343
+
344
+ # Deploy the highest priority agent
345
+ agent = matching_agents[0]
346
+ agent_name_display = agent.get("metadata", {}).get("name", agent_name)
347
+ source = agent.get("repository", "unknown")
348
+ priority = agent.get("priority", 100)
349
+
350
+ if dry_run:
351
+ logger.info(f"[DRY RUN] Would deploy {agent_name_display} from {source}")
352
+ return {
353
+ "deployed": False,
354
+ "agent_name": agent_name_display,
355
+ "source": source,
356
+ "priority": priority,
357
+ "dry_run": True,
358
+ }
359
+
360
+ # Deploy agent
361
+ try:
362
+ success = self._deploy_agent_file(agent)
363
+ if success:
364
+ deployed_path = (
365
+ self.deployment_dir
366
+ / f"{agent.get('agent_id', agent_name.lower())}.md"
367
+ )
368
+ logger.info(f"Deployed {agent_name_display} to {deployed_path}")
369
+ return {
370
+ "deployed": True,
371
+ "agent_name": agent_name_display,
372
+ "source": source,
373
+ "priority": priority,
374
+ "path": str(deployed_path),
375
+ }
376
+ return {
377
+ "deployed": False,
378
+ "agent_name": agent_name_display,
379
+ "source": source,
380
+ "priority": priority,
381
+ "error": "Deployment failed",
382
+ }
383
+ except Exception as e:
384
+ logger.error(f"Error deploying {agent_name_display}: {e}")
385
+ return {
386
+ "deployed": False,
387
+ "agent_name": agent_name_display,
388
+ "source": source,
389
+ "priority": priority,
390
+ "error": str(e),
391
+ }
392
+
393
+ def list_available_agents(
394
+ self, source_repo: Optional[str] = None
395
+ ) -> List[Dict[str, Any]]:
396
+ """List all agents available from configured sources.
397
+
398
+ Args:
399
+ source_repo: Optional repository filter (e.g., "owner/repo/subdirectory")
400
+
401
+ Returns:
402
+ List of agent metadata dictionaries:
403
+ [
404
+ {
405
+ "name": "Engineer",
406
+ "agent_id": "engineer",
407
+ "description": "Python specialist...",
408
+ "source": "bobmatnyc/claude-mpm-agents",
409
+ "priority": 100,
410
+ "version": "abc123...",
411
+ "model": "sonnet"
412
+ }
413
+ ]
414
+ """
415
+ logger.debug(f"Listing available agents (source={source_repo})")
416
+
417
+ # Get repositories
418
+ if source_repo:
419
+ repos = [
420
+ r
421
+ for r in self.config.get_enabled_repositories()
422
+ if r.identifier == source_repo
423
+ ]
424
+ else:
425
+ repos = self.config.get_enabled_repositories()
426
+
427
+ # Discover all agents
428
+ all_agents = []
429
+ for repo in repos:
430
+ try:
431
+ agents = self._discover_agents_in_repo(repo)
432
+ all_agents.extend(agents)
433
+ except Exception as e:
434
+ logger.warning(f"Failed to discover agents in {repo.identifier}: {e}")
435
+
436
+ # Format for return
437
+ formatted_agents = []
438
+ for agent in all_agents:
439
+ metadata = agent.get("metadata", {})
440
+ formatted_agents.append(
441
+ {
442
+ "name": metadata.get("name", "Unknown"),
443
+ "agent_id": agent.get("agent_id", "unknown"),
444
+ "description": metadata.get("description", ""),
445
+ "source": agent.get("repository", "unknown"),
446
+ "priority": agent.get("priority", 100),
447
+ "version": agent.get("version", "unknown"),
448
+ "model": agent.get("model", "sonnet"),
449
+ }
450
+ )
451
+
452
+ logger.debug(f"Found {len(formatted_agents)} available agents")
453
+ return formatted_agents
454
+
455
+ def get_deployed_agents(self) -> List[Dict[str, Any]]:
456
+ """List currently deployed agents.
457
+
458
+ Scans .claude/agents/ directory for deployed agent files.
459
+
460
+ Returns:
461
+ List of deployed agent metadata:
462
+ [
463
+ {
464
+ "name": "Engineer",
465
+ "agent_id": "engineer",
466
+ "path": "/Users/user/.claude/agents/engineer.md",
467
+ "size": 12345
468
+ }
469
+ ]
470
+ """
471
+ logger.debug(f"Listing deployed agents from {self.deployment_dir}")
472
+
473
+ if not self.deployment_dir.exists():
474
+ return []
475
+
476
+ deployed = []
477
+ for md_file in self.deployment_dir.glob("*.md"):
478
+ try:
479
+ # Extract agent_id from filename
480
+ agent_id = md_file.stem
481
+
482
+ # Read first line to get agent name
483
+ with open(md_file) as f:
484
+ first_line = f.readline().strip()
485
+ # Extract name from markdown heading
486
+ name = (
487
+ first_line.lstrip("#").strip()
488
+ if first_line.startswith("#")
489
+ else agent_id
490
+ )
491
+
492
+ deployed.append(
493
+ {
494
+ "name": name,
495
+ "agent_id": agent_id,
496
+ "path": str(md_file),
497
+ "size": md_file.stat().st_size,
498
+ }
499
+ )
500
+ except Exception as e:
501
+ logger.warning(f"Failed to read deployed agent {md_file.name}: {e}")
502
+
503
+ logger.debug(f"Found {len(deployed)} deployed agents")
504
+ return deployed
505
+
506
+ def remove_agent(self, agent_name: str) -> bool:
507
+ """Remove a deployed agent.
508
+
509
+ Args:
510
+ agent_name: Agent ID to remove (e.g., "engineer")
511
+
512
+ Returns:
513
+ True if agent was removed, False if not found
514
+ """
515
+ logger.info(f"Removing agent: {agent_name}")
516
+
517
+ # Find deployed agent file
518
+ agent_file = self.deployment_dir / f"{agent_name.lower()}.md"
519
+
520
+ if not agent_file.exists():
521
+ logger.warning(f"Agent not found: {agent_name}")
522
+ return False
523
+
524
+ try:
525
+ agent_file.unlink()
526
+ logger.info(f"Removed agent: {agent_name}")
527
+ return True
528
+ except Exception as e:
529
+ logger.error(f"Failed to remove agent {agent_name}: {e}")
530
+ return False
531
+
532
+ def sync_sources(
533
+ self, force: bool = False, repo_identifier: Optional[str] = None
534
+ ) -> Dict[str, Any]:
535
+ """Sync Git sources.
536
+
537
+ Wrapper for GitSourceManager.sync_all_repositories() with filtering.
538
+
539
+ Args:
540
+ force: Force sync even if cache is fresh (bypasses ETag)
541
+ repo_identifier: Optional repository identifier to sync
542
+ (e.g., "owner/repo/subdirectory")
543
+
544
+ Returns:
545
+ Sync results dictionary:
546
+ {
547
+ "owner/repo": {
548
+ "synced": bool,
549
+ "files_updated": int,
550
+ ...
551
+ }
552
+ }
553
+ """
554
+ logger.info(f"Syncing sources (force={force}, repo={repo_identifier})")
555
+
556
+ repos = self.config.get_enabled_repositories()
557
+
558
+ if repo_identifier:
559
+ repos = [r for r in repos if r.identifier == repo_identifier]
560
+ if not repos:
561
+ return {
562
+ repo_identifier: {
563
+ "synced": False,
564
+ "error": "Repository not found",
565
+ }
566
+ }
567
+
568
+ return self.git_source_manager.sync_all_repositories(repos, force)
569
+
570
+ def _discover_agents_in_repo(self, repo: GitRepository) -> List[Dict[str, Any]]:
571
+ """Discover agents in a specific repository's cache.
572
+
573
+ Args:
574
+ repo: Repository to discover agents from
575
+
576
+ Returns:
577
+ List of agent dictionaries with repository and priority metadata
578
+ """
579
+ try:
580
+ discovery_service = RemoteAgentDiscoveryService(repo.cache_path)
581
+ agents = discovery_service.discover_remote_agents()
582
+
583
+ # Add repository identifier and priority to each agent
584
+ for agent in agents:
585
+ agent["repository"] = repo.identifier
586
+ agent["priority"] = repo.priority
587
+
588
+ return agents
589
+
590
+ except Exception as e:
591
+ logger.error(f"Failed to discover agents in {repo.identifier}: {e}")
592
+ return []
593
+
594
+ def _resolve_conflicts(
595
+ self, agents: List[Dict[str, Any]]
596
+ ) -> tuple[List[Dict[str, Any]], int]:
597
+ """Resolve agent name conflicts using priority system.
598
+
599
+ When multiple repositories provide the same agent, choose the one
600
+ with the lowest priority number (highest precedence).
601
+
602
+ Args:
603
+ agents: List of all discovered agents from all repositories
604
+
605
+ Returns:
606
+ Tuple of (resolved_agents, conflict_count):
607
+ - resolved_agents: List with one agent per name (highest priority)
608
+ - conflict_count: Number of conflicts resolved
609
+
610
+ Algorithm:
611
+ 1. Group agents by name
612
+ 2. For each group, sort by priority (ascending)
613
+ 3. Take the first agent (lowest priority number = highest precedence)
614
+ 4. Count groups with multiple agents as conflicts
615
+ """
616
+ # Group agents by name
617
+ agents_by_name: Dict[str, List[Dict[str, Any]]] = {}
618
+
619
+ for agent in agents:
620
+ name = agent.get("metadata", {}).get("name", "").lower().replace(" ", "-")
621
+ if not name:
622
+ # Skip agents without valid names
623
+ continue
624
+
625
+ if name not in agents_by_name:
626
+ agents_by_name[name] = []
627
+
628
+ agents_by_name[name].append(agent)
629
+
630
+ # Resolve conflicts
631
+ resolved = []
632
+ conflict_count = 0
633
+
634
+ for name, agent_list in agents_by_name.items():
635
+ if len(agent_list) > 1:
636
+ # Conflict detected
637
+ conflict_count += 1
638
+
639
+ # Sort by priority (ascending - lower number = higher precedence)
640
+ agent_list.sort(key=lambda a: a.get("priority", 100))
641
+
642
+ logger.info(
643
+ f"Conflict for '{name}': {len(agent_list)} sources, "
644
+ f"using {agent_list[0].get('repository')} "
645
+ f"(priority {agent_list[0].get('priority')})"
646
+ )
647
+
648
+ # Use highest priority agent (first after sort)
649
+ resolved.append(agent_list[0])
650
+
651
+ return resolved, conflict_count
652
+
653
+ def _deploy_agent_file(self, agent: Dict[str, Any]) -> bool:
654
+ """Deploy a single agent file to deployment directory.
655
+
656
+ Copies the agent Markdown file from cache to .claude/agents/
657
+
658
+ Args:
659
+ agent: Agent dictionary with source_file path
660
+
661
+ Returns:
662
+ True if deployment succeeded, False otherwise
663
+
664
+ Error Handling:
665
+ - Returns False if source file doesn't exist
666
+ - Returns False if copy operation fails
667
+ - Logs all errors for debugging
668
+ """
669
+ try:
670
+ # Get source file path
671
+ source_file = Path(agent.get("source_file", ""))
672
+ if not source_file.exists():
673
+ logger.error(f"Source file does not exist: {source_file}")
674
+ return False
675
+
676
+ # Build target filename using agent_id
677
+ agent_id = agent.get("agent_id", "unknown")
678
+ target_file = self.deployment_dir / f"{agent_id}.md"
679
+
680
+ # Copy file
681
+ shutil.copy2(source_file, target_file)
682
+
683
+ logger.debug(f"Deployed {source_file.name} to {target_file}")
684
+ return True
685
+
686
+ except Exception as e:
687
+ logger.error(f"Failed to deploy agent file: {e}")
688
+ return False
689
+
690
+ def __repr__(self) -> str:
691
+ """Return string representation."""
692
+ return (
693
+ f"SingleTierDeploymentService("
694
+ f"deployment_dir='{self.deployment_dir}', "
695
+ f"repositories={len(self.config.get_enabled_repositories())})"
696
+ )