claude-mpm 4.21.3__py3-none-any.whl → 5.1.9__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (517) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +12 -0
  3. claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +3 -48
  4. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +1239 -674
  6. claude_mpm/agents/WORKFLOW.md +75 -2
  7. claude_mpm/agents/__init__.py +6 -0
  8. claude_mpm/agents/agent_loader.py +1 -4
  9. claude_mpm/agents/base_agent.json +6 -3
  10. claude_mpm/agents/base_agent_loader.py +10 -35
  11. claude_mpm/agents/frontmatter_validator.py +69 -1
  12. claude_mpm/agents/templates/circuit-breakers.md +1254 -0
  13. claude_mpm/agents/templates/context-management-examples.md +544 -0
  14. claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +89 -19
  15. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  16. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  17. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  18. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  19. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  20. claude_mpm/cli/__init__.py +37 -2
  21. claude_mpm/cli/commands/__init__.py +2 -0
  22. claude_mpm/cli/commands/agent_source.py +774 -0
  23. claude_mpm/cli/commands/agent_state_manager.py +188 -30
  24. claude_mpm/cli/commands/agents.py +1128 -36
  25. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  26. claude_mpm/cli/commands/agents_discover.py +338 -0
  27. claude_mpm/cli/commands/aggregate.py +1 -1
  28. claude_mpm/cli/commands/analyze.py +3 -3
  29. claude_mpm/cli/commands/auto_configure.py +537 -239
  30. claude_mpm/cli/commands/cleanup.py +1 -1
  31. claude_mpm/cli/commands/config.py +7 -4
  32. claude_mpm/cli/commands/configure.py +935 -45
  33. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  34. claude_mpm/cli/commands/configure_navigation.py +63 -46
  35. claude_mpm/cli/commands/debug.py +12 -12
  36. claude_mpm/cli/commands/doctor.py +10 -2
  37. claude_mpm/cli/commands/hook_errors.py +277 -0
  38. claude_mpm/cli/commands/local_deploy.py +1 -4
  39. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  40. claude_mpm/cli/commands/mpm_init/core.py +50 -2
  41. claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
  42. claude_mpm/cli/commands/mpm_init/prompts.py +6 -6
  43. claude_mpm/cli/commands/postmortem.py +401 -0
  44. claude_mpm/cli/commands/run.py +125 -167
  45. claude_mpm/cli/commands/skill_source.py +694 -0
  46. claude_mpm/cli/commands/skills.py +757 -20
  47. claude_mpm/cli/executor.py +78 -3
  48. claude_mpm/cli/interactive/agent_wizard.py +1032 -47
  49. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  50. claude_mpm/cli/parsers/agents_parser.py +310 -4
  51. claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
  52. claude_mpm/cli/parsers/base_parser.py +53 -0
  53. claude_mpm/cli/parsers/config_parser.py +96 -43
  54. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  55. claude_mpm/cli/parsers/skills_parser.py +145 -0
  56. claude_mpm/cli/parsers/source_parser.py +138 -0
  57. claude_mpm/cli/startup.py +564 -108
  58. claude_mpm/cli/startup_display.py +480 -0
  59. claude_mpm/cli/utils.py +1 -1
  60. claude_mpm/cli_module/commands.py +1 -1
  61. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  62. claude_mpm/commands/mpm-agents-detect.md +9 -0
  63. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  64. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  65. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  66. claude_mpm/commands/mpm-doctor.md +9 -0
  67. claude_mpm/commands/mpm-help.md +14 -2
  68. claude_mpm/commands/mpm-init.md +27 -2
  69. claude_mpm/commands/mpm-monitor.md +9 -0
  70. claude_mpm/commands/mpm-postmortem.md +123 -0
  71. claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
  72. claude_mpm/commands/mpm-status.md +9 -0
  73. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  74. claude_mpm/commands/mpm-ticket-view.md +552 -0
  75. claude_mpm/commands/mpm-version.md +9 -0
  76. claude_mpm/commands/mpm.md +10 -0
  77. claude_mpm/config/agent_presets.py +488 -0
  78. claude_mpm/config/agent_sources.py +325 -0
  79. claude_mpm/config/skill_presets.py +392 -0
  80. claude_mpm/config/skill_sources.py +590 -0
  81. claude_mpm/constants.py +13 -0
  82. claude_mpm/core/api_validator.py +1 -1
  83. claude_mpm/core/claude_runner.py +19 -35
  84. claude_mpm/core/config.py +24 -0
  85. claude_mpm/core/constants.py +1 -1
  86. claude_mpm/core/framework/__init__.py +3 -16
  87. claude_mpm/core/framework/loaders/file_loader.py +54 -101
  88. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  89. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  90. claude_mpm/core/hook_error_memory.py +381 -0
  91. claude_mpm/core/hook_manager.py +41 -2
  92. claude_mpm/core/interactive_session.py +131 -10
  93. claude_mpm/core/logger.py +3 -1
  94. claude_mpm/core/oneshot_session.py +110 -8
  95. claude_mpm/core/output_style_manager.py +173 -43
  96. claude_mpm/core/protocols/__init__.py +23 -0
  97. claude_mpm/core/protocols/runner_protocol.py +103 -0
  98. claude_mpm/core/protocols/session_protocol.py +131 -0
  99. claude_mpm/core/shared/singleton_manager.py +11 -4
  100. claude_mpm/core/system_context.py +38 -0
  101. claude_mpm/core/unified_agent_registry.py +129 -1
  102. claude_mpm/core/unified_config.py +22 -0
  103. claude_mpm/dashboard/static/css/activity.css +69 -69
  104. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  105. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  106. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  107. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  108. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  109. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  110. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  111. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  112. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  113. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  114. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  115. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  116. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  117. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  118. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  119. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  120. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  121. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  122. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  123. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  124. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  125. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  126. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  127. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  128. claude_mpm/dashboard/templates/code_simple.html +23 -23
  129. claude_mpm/dashboard/templates/index.html +18 -18
  130. claude_mpm/experimental/cli_enhancements.py +1 -5
  131. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  132. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  133. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  134. claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
  135. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  136. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  137. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  138. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  139. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  140. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  141. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  142. claude_mpm/models/agent_definition.py +7 -0
  143. claude_mpm/models/git_repository.py +198 -0
  144. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  145. claude_mpm/scripts/start_activity_logging.py +3 -1
  146. claude_mpm/services/agents/agent_builder.py +45 -9
  147. claude_mpm/services/agents/agent_preset_service.py +238 -0
  148. claude_mpm/services/agents/agent_selection_service.py +484 -0
  149. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  150. claude_mpm/services/agents/cache_git_manager.py +621 -0
  151. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  152. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  153. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  154. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  155. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  156. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  157. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  158. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  159. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  160. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  161. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +225 -18
  162. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  163. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  164. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +557 -0
  165. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  166. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  167. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  168. claude_mpm/services/agents/git_source_manager.py +629 -0
  169. claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
  170. claude_mpm/services/agents/local_template_manager.py +50 -10
  171. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  172. claude_mpm/services/agents/sources/__init__.py +13 -0
  173. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  174. claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
  175. claude_mpm/services/agents/startup_sync.py +239 -0
  176. claude_mpm/services/agents/toolchain_detector.py +474 -0
  177. claude_mpm/services/analysis/__init__.py +25 -0
  178. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  179. claude_mpm/services/analysis/postmortem_service.py +765 -0
  180. claude_mpm/services/cli/session_pause_manager.py +1 -1
  181. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  182. claude_mpm/services/command_deployment_service.py +200 -6
  183. claude_mpm/services/core/base.py +7 -2
  184. claude_mpm/services/core/interfaces/__init__.py +1 -3
  185. claude_mpm/services/core/interfaces/health.py +1 -4
  186. claude_mpm/services/core/models/__init__.py +2 -11
  187. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  188. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  189. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  190. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  191. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  192. claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
  193. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  194. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  195. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  196. claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
  197. claude_mpm/services/event_bus/direct_relay.py +3 -3
  198. claude_mpm/services/event_bus/event_bus.py +36 -3
  199. claude_mpm/services/events/consumers/logging.py +1 -2
  200. claude_mpm/services/git/__init__.py +21 -0
  201. claude_mpm/services/git/git_operations_service.py +494 -0
  202. claude_mpm/services/github/__init__.py +21 -0
  203. claude_mpm/services/github/github_cli_service.py +397 -0
  204. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  205. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  206. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  207. claude_mpm/services/instructions/__init__.py +9 -0
  208. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  209. claude_mpm/services/local_ops/__init__.py +3 -13
  210. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  211. claude_mpm/services/local_ops/health_manager.py +1 -4
  212. claude_mpm/services/local_ops/process_manager.py +1 -1
  213. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  214. claude_mpm/services/mcp_config_manager.py +75 -145
  215. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  216. claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
  217. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  218. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  219. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  220. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  221. claude_mpm/services/mcp_service_verifier.py +6 -3
  222. claude_mpm/services/memory/optimizer.py +1 -1
  223. claude_mpm/services/model/model_router.py +8 -9
  224. claude_mpm/services/monitor/daemon.py +29 -9
  225. claude_mpm/services/monitor/daemon_manager.py +96 -19
  226. claude_mpm/services/monitor/server.py +2 -2
  227. claude_mpm/services/native_agent_converter.py +356 -0
  228. claude_mpm/services/port_manager.py +1 -1
  229. claude_mpm/services/pr/__init__.py +14 -0
  230. claude_mpm/services/pr/pr_template_service.py +329 -0
  231. claude_mpm/services/project/documentation_manager.py +2 -1
  232. claude_mpm/services/project/project_organizer.py +4 -0
  233. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  234. claude_mpm/services/runner_configuration_service.py +17 -3
  235. claude_mpm/services/self_upgrade_service.py +165 -7
  236. claude_mpm/services/session_management_service.py +16 -4
  237. claude_mpm/services/skills/__init__.py +18 -0
  238. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  239. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  240. claude_mpm/services/skills_config.py +547 -0
  241. claude_mpm/services/skills_deployer.py +955 -0
  242. claude_mpm/services/socketio/handlers/connection.py +1 -1
  243. claude_mpm/services/socketio/handlers/git.py +2 -2
  244. claude_mpm/services/socketio/server/core.py +1 -4
  245. claude_mpm/services/socketio/server/main.py +1 -3
  246. claude_mpm/services/system_instructions_service.py +1 -3
  247. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  248. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  249. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  250. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  251. claude_mpm/services/unified/unified_deployment.py +1 -5
  252. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  253. claude_mpm/services/visualization/__init__.py +1 -5
  254. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  255. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  256. claude_mpm/skills/bundled/performance-profiling.md +6 -0
  257. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
  258. claude_mpm/skills/skills_registry.py +0 -1
  259. claude_mpm/templates/questions/__init__.py +38 -0
  260. claude_mpm/templates/questions/base.py +193 -0
  261. claude_mpm/templates/questions/pr_strategy.py +311 -0
  262. claude_mpm/templates/questions/project_init.py +385 -0
  263. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  264. claude_mpm/tools/__main__.py +8 -8
  265. claude_mpm/tools/code_tree_analyzer/analysis.py +1 -1
  266. claude_mpm/utils/agent_dependency_loader.py +80 -13
  267. claude_mpm/utils/agent_filters.py +288 -0
  268. claude_mpm/utils/dependency_cache.py +3 -1
  269. claude_mpm/utils/gitignore.py +244 -0
  270. claude_mpm/utils/log_cleanup.py +3 -3
  271. claude_mpm/utils/migration.py +372 -0
  272. claude_mpm/utils/progress.py +387 -0
  273. claude_mpm/utils/robust_installer.py +3 -5
  274. claude_mpm/utils/structured_questions.py +619 -0
  275. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/METADATA +496 -65
  276. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/RECORD +284 -443
  277. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  278. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  279. claude_mpm/agents/templates/agent-manager.json +0 -273
  280. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  281. claude_mpm/agents/templates/api_qa.json +0 -180
  282. claude_mpm/agents/templates/circuit_breakers.md +0 -638
  283. claude_mpm/agents/templates/clerk-ops.json +0 -235
  284. claude_mpm/agents/templates/code_analyzer.json +0 -101
  285. claude_mpm/agents/templates/content-agent.json +0 -358
  286. claude_mpm/agents/templates/dart_engineer.json +0 -307
  287. claude_mpm/agents/templates/data_engineer.json +0 -225
  288. claude_mpm/agents/templates/documentation.json +0 -211
  289. claude_mpm/agents/templates/engineer.json +0 -210
  290. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  291. claude_mpm/agents/templates/golang_engineer.json +0 -270
  292. claude_mpm/agents/templates/imagemagick.json +0 -264
  293. claude_mpm/agents/templates/java_engineer.json +0 -346
  294. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  295. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  296. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  297. claude_mpm/agents/templates/memory_manager.json +0 -158
  298. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  299. claude_mpm/agents/templates/ops.json +0 -185
  300. claude_mpm/agents/templates/php-engineer.json +0 -287
  301. claude_mpm/agents/templates/product_owner.json +0 -338
  302. claude_mpm/agents/templates/project_organizer.json +0 -140
  303. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  304. claude_mpm/agents/templates/python_engineer.json +0 -387
  305. claude_mpm/agents/templates/qa.json +0 -242
  306. claude_mpm/agents/templates/react_engineer.json +0 -238
  307. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  308. claude_mpm/agents/templates/research.json +0 -188
  309. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  310. claude_mpm/agents/templates/rust_engineer.json +0 -275
  311. claude_mpm/agents/templates/security.json +0 -202
  312. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  313. claude_mpm/agents/templates/ticketing.json +0 -177
  314. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  315. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  316. claude_mpm/agents/templates/version_control.json +0 -157
  317. claude_mpm/agents/templates/web_qa.json +0 -399
  318. claude_mpm/agents/templates/web_ui.json +0 -189
  319. claude_mpm/commands/mpm-tickets.md +0 -102
  320. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  321. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  322. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  323. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  324. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  325. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  326. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  327. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  328. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  329. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  330. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  331. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  332. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  333. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  334. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  335. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  336. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  337. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  338. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  339. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  340. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  341. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  342. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  343. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  344. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  345. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  346. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  347. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  348. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  349. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  350. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  351. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  352. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  353. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  354. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  355. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  356. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  357. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  358. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  359. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  360. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  361. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  362. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  363. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  364. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  365. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  366. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  367. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  368. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  369. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  370. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  371. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  372. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  373. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  374. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  375. claude_mpm/dashboard/static/built/react/events.js +0 -30
  376. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  377. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  378. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  379. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  380. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  381. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  382. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  383. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  384. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  385. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  386. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  387. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  388. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  389. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  390. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  391. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  392. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  393. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  394. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  395. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  396. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  397. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  398. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  399. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  400. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  401. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  402. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  403. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  404. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  405. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  406. claude_mpm/dashboard/static/events.html +0 -607
  407. claude_mpm/dashboard/static/index.html +0 -635
  408. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  409. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  410. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  411. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  412. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  413. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  414. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  415. claude_mpm/dashboard/static/legacy/files.html +0 -747
  416. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  417. claude_mpm/dashboard/static/monitors.html +0 -431
  418. claude_mpm/dashboard/static/production/events.html +0 -659
  419. claude_mpm/dashboard/static/production/main.html +0 -698
  420. claude_mpm/dashboard/static/production/monitors.html +0 -483
  421. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  422. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  423. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  424. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  425. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  426. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
  427. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
  428. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
  429. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
  430. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
  431. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
  432. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
  433. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
  434. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
  435. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
  436. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
  437. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
  438. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
  439. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
  440. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
  441. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
  442. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
  443. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  444. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  445. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  446. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  447. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  448. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  449. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  450. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  451. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  452. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  453. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
  454. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
  455. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
  456. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
  457. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
  458. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
  459. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
  460. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  461. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  462. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  463. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  464. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
  465. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
  466. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  467. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  468. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  469. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  470. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
  471. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
  472. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
  473. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
  474. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
  475. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
  476. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
  477. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
  478. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
  479. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
  480. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
  481. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
  482. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
  483. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
  484. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
  485. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
  486. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
  487. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
  488. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
  489. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
  490. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
  491. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
  492. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
  493. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  494. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  495. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  496. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  497. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  498. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  499. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
  500. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
  501. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
  502. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
  503. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
  504. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
  505. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
  506. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
  507. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
  508. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
  509. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
  510. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  511. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  512. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  513. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  514. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/WHEEL +0 -0
  515. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/entry_points.txt +0 -0
  516. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/licenses/LICENSE +0 -0
  517. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,557 @@
1
+ """Service for discovering and converting remote Markdown agents to JSON format.
2
+
3
+ This service handles the 4th tier of agent discovery: remote agents cached from GitHub.
4
+ Remote agents are stored as Markdown files with YAML frontmatter and need to be converted
5
+ to the JSON template format expected by the deployment system.
6
+
7
+ WHY: Remote agents from GitHub are cached as Markdown but the deployment system expects
8
+ JSON templates. This service bridges that gap and integrates remote agents into the
9
+ multi-tier discovery system.
10
+ """
11
+
12
+ import json
13
+ import re
14
+ from dataclasses import dataclass
15
+ from pathlib import Path
16
+ from typing import Any, Dict, List, Optional
17
+
18
+ from claude_mpm.core.logging_config import get_logger
19
+
20
+ logger = get_logger(__name__)
21
+
22
+
23
+ @dataclass
24
+ class RemoteAgentMetadata:
25
+ """Metadata extracted from remote agent Markdown file."""
26
+
27
+ name: str
28
+ description: str
29
+ model: str
30
+ routing_keywords: List[str]
31
+ routing_paths: List[str]
32
+ routing_priority: int
33
+ source_file: Path
34
+ version: str # SHA-256 hash from cache metadata
35
+ collection_id: Optional[str] = None # Format: owner/repo-name
36
+ source_path: Optional[str] = None # Relative path in repo
37
+ canonical_id: Optional[str] = None # Format: collection_id:agent_id
38
+
39
+
40
+ class RemoteAgentDiscoveryService:
41
+ """Discovers and converts remote Markdown agents to JSON format.
42
+
43
+ Remote agents are discovered from the cache directory (~/.claude-mpm/cache/remote-agents/)
44
+ where they are stored as Markdown files. This service:
45
+ 1. Discovers all *.md files in the remote agents cache
46
+ 2. Parses Markdown frontmatter and content to extract metadata
47
+ 3. Converts to JSON template format for deployment
48
+ 4. Retrieves version (SHA-256 hash) from cache metadata
49
+
50
+ Design Decision: Markdown Parsing Strategy
51
+ - Use regex for simple frontmatter extraction (fast, no dependencies)
52
+ - Parse key-value pairs from Configuration section
53
+ - Extract routing info from Routing section
54
+ - Fallback to sensible defaults when sections are missing
55
+
56
+ Trade-offs:
57
+ - Performance: Regex parsing is fast for our simple format
58
+ - Maintainability: Clear regex patterns are easy to understand
59
+ - Flexibility: Supports optional sections with defaults
60
+ """
61
+
62
+ def __init__(self, remote_agents_dir: Path):
63
+ """Initialize the remote agent discovery service.
64
+
65
+ Args:
66
+ remote_agents_dir: Directory containing cached remote agent Markdown files
67
+ """
68
+ self.remote_agents_dir = remote_agents_dir
69
+ self.logger = get_logger(__name__)
70
+
71
+ def _extract_collection_id_from_path(self, file_path: Path) -> Optional[str]:
72
+ """Extract collection_id from repository path structure.
73
+
74
+ Collection ID is derived from the repository path structure:
75
+ ~/.claude-mpm/cache/remote-agents/{owner}/{repo}/agents/...
76
+
77
+ Args:
78
+ file_path: Absolute path to agent Markdown file
79
+
80
+ Returns:
81
+ Collection ID in format "owner/repo-name" or None if not found
82
+
83
+ Example:
84
+ Input: ~/.claude-mpm/cache/remote-agents/bobmatnyc/claude-mpm-agents/agents/pm.md
85
+ Output: "bobmatnyc/claude-mpm-agents"
86
+ """
87
+ try:
88
+ # Find "remote-agents" in the path
89
+ path_parts = file_path.parts
90
+ remote_agents_idx = -1
91
+
92
+ for i, part in enumerate(path_parts):
93
+ if part == "remote-agents":
94
+ remote_agents_idx = i
95
+ break
96
+
97
+ if remote_agents_idx == -1 or remote_agents_idx + 2 >= len(path_parts):
98
+ self.logger.debug(
99
+ f"Could not extract collection_id from path: {file_path}"
100
+ )
101
+ return None
102
+
103
+ # Extract owner and repo (next two parts after "remote-agents")
104
+ owner = path_parts[remote_agents_idx + 1]
105
+ repo = path_parts[remote_agents_idx + 2]
106
+
107
+ collection_id = f"{owner}/{repo}"
108
+ self.logger.debug(f"Extracted collection_id: {collection_id}")
109
+ return collection_id
110
+
111
+ except Exception as e:
112
+ self.logger.warning(
113
+ f"Failed to extract collection_id from {file_path}: {e}"
114
+ )
115
+ return None
116
+
117
+ def _extract_source_path_from_file(self, file_path: Path) -> Optional[str]:
118
+ """Extract relative source path within repository.
119
+
120
+ Source path is relative to the repository root (not the agents subdirectory).
121
+
122
+ Args:
123
+ file_path: Absolute path to agent Markdown file
124
+
125
+ Returns:
126
+ Relative path from repo root, or None if not found
127
+
128
+ Example:
129
+ Input: ~/.claude-mpm/cache/remote-agents/bobmatnyc/claude-mpm-agents/agents/pm.md
130
+ Output: "agents/pm.md"
131
+ """
132
+ try:
133
+ # Find "remote-agents" in the path
134
+ path_parts = file_path.parts
135
+ remote_agents_idx = -1
136
+
137
+ for i, part in enumerate(path_parts):
138
+ if part == "remote-agents":
139
+ remote_agents_idx = i
140
+ break
141
+
142
+ if remote_agents_idx == -1 or remote_agents_idx + 3 >= len(path_parts):
143
+ return None
144
+
145
+ # Path after owner/repo is the source path
146
+ # remote-agents/{owner}/{repo}/{source_path}
147
+ repo_root_idx = remote_agents_idx + 3
148
+ source_parts = path_parts[repo_root_idx:]
149
+
150
+ return "/".join(source_parts)
151
+
152
+ except Exception as e:
153
+ self.logger.warning(f"Failed to extract source_path from {file_path}: {e}")
154
+ return None
155
+
156
+ def _generate_hierarchical_id(self, file_path: Path) -> str:
157
+ """Generate hierarchical agent ID from file path.
158
+
159
+ Converts file path relative to agents subdirectory into hierarchical ID.
160
+
161
+ Design Decision: Path-based IDs for hierarchy preservation
162
+
163
+ Rationale: Agent IDs must reflect directory hierarchy to enable:
164
+ - Category-based filtering (engineer/backend/python-engineer)
165
+ - Preset matching against AUTO-DEPLOY-INDEX.md
166
+ - Multi-level organization without name collisions
167
+
168
+ Bug #4 Fix: Calculate relative to /agents/ subdirectory, not repository root
169
+ This ensures agent IDs are based on their position within the agents directory.
170
+
171
+ Example:
172
+ Input: /cache/bobmatnyc/claude-mpm-agents/agents/engineer/backend/python-engineer.md
173
+ Root: /cache/bobmatnyc/claude-mpm-agents/agents
174
+ Output: engineer/backend/python-engineer
175
+
176
+ Args:
177
+ file_path: Absolute path to agent Markdown file
178
+
179
+ Returns:
180
+ Hierarchical agent ID with forward slashes
181
+ """
182
+ try:
183
+ # Calculate relative to /agents/ subdirectory (Bug #4 fix)
184
+ agents_dir = self.remote_agents_dir / "agents"
185
+ relative_path = file_path.relative_to(agents_dir)
186
+
187
+ # Remove .md extension and convert to forward slashes
188
+ return str(relative_path.with_suffix("")).replace("\\", "/")
189
+ except ValueError:
190
+ # File is not under agents subdirectory, fall back to filename
191
+ self.logger.warning(
192
+ f"File {file_path} not under agents directory, using filename"
193
+ )
194
+ return file_path.stem
195
+
196
+ def _detect_category_from_path(self, file_path: Path) -> str:
197
+ """Detect category from file path hierarchy.
198
+
199
+ Extracts category from directory structure. Category is the path
200
+ from agents subdirectory to the file, excluding the filename.
201
+
202
+ Bug #4 Fix: Calculate relative to /agents/ subdirectory, not repository root
203
+ This ensures categories are based on agent organization within /agents/.
204
+
205
+ Example:
206
+ Input: /cache/bobmatnyc/claude-mpm-agents/agents/engineer/backend/python-engineer.md
207
+ Root: /cache/bobmatnyc/claude-mpm-agents/agents
208
+ Output: engineer/backend
209
+
210
+ Args:
211
+ file_path: Absolute path to agent Markdown file
212
+
213
+ Returns:
214
+ Category path with forward slashes, or "universal" if in root
215
+ """
216
+ try:
217
+ # Calculate relative to /agents/ subdirectory (Bug #4 fix)
218
+ agents_dir = self.remote_agents_dir / "agents"
219
+ relative_path = file_path.relative_to(agents_dir)
220
+ parts = relative_path.parts[:-1] # Exclude filename
221
+ return "/".join(parts) if parts else "universal"
222
+ except ValueError:
223
+ return "universal"
224
+
225
+ def discover_remote_agents(self) -> List[Dict[str, Any]]:
226
+ """Discover all remote agents from cache directory.
227
+
228
+ Scans the remote agents directory for *.md files recursively and converts each
229
+ to JSON template format. Skips files that can't be parsed.
230
+
231
+ Bug #4 Fix: Only scan /agents/ subdirectory, not entire repository
232
+ This prevents README.md, CHANGELOG.md, etc. from being treated as agents.
233
+
234
+ Returns:
235
+ List of agent dictionaries in JSON template format
236
+
237
+ Example:
238
+ >>> service = RemoteAgentDiscoveryService(Path("~/.claude-mpm/cache/remote-agents"))
239
+ >>> agents = service.discover_remote_agents()
240
+ >>> len(agents)
241
+ 5
242
+ >>> agents[0]['name']
243
+ 'Security Scanner Agent'
244
+ """
245
+ agents = []
246
+
247
+ if not self.remote_agents_dir.exists():
248
+ self.logger.debug(
249
+ f"Remote agents directory does not exist: {self.remote_agents_dir}"
250
+ )
251
+ return agents
252
+
253
+ # Bug #4 Fix: Only scan /agents/ subdirectory, not entire repository
254
+ # This prevents non-agent files (README.md, CHANGELOG.md, etc.) from polluting results
255
+ agents_dir = self.remote_agents_dir / "agents"
256
+
257
+ if not agents_dir.exists():
258
+ self.logger.warning(
259
+ f"Agents subdirectory not found: {agents_dir}. "
260
+ f"Expected agents to be in /agents/ subdirectory."
261
+ )
262
+ return agents
263
+
264
+ # Find all Markdown files recursively in /agents/ subdirectory only
265
+ md_files = list(agents_dir.rglob("*.md"))
266
+ self.logger.debug(f"Found {len(md_files)} Markdown files in {agents_dir}")
267
+
268
+ for md_file in md_files:
269
+ try:
270
+ agent_dict = self._parse_markdown_agent(md_file)
271
+ if agent_dict:
272
+ agents.append(agent_dict)
273
+ self.logger.debug(
274
+ f"Successfully parsed remote agent: {md_file.name}"
275
+ )
276
+ else:
277
+ self.logger.warning(
278
+ f"Failed to parse remote agent (no name found): {md_file.name}"
279
+ )
280
+ except Exception as e:
281
+ self.logger.warning(f"Failed to parse remote agent {md_file.name}: {e}")
282
+
283
+ self.logger.info(
284
+ f"Discovered {len(agents)} remote agents from {self.remote_agents_dir.name}"
285
+ )
286
+ return agents
287
+
288
+ def _parse_markdown_agent(self, md_file: Path) -> Optional[Dict[str, Any]]:
289
+ """Parse Markdown agent file and convert to JSON template format.
290
+
291
+ Expected Markdown format:
292
+ ```markdown
293
+ # Agent Name
294
+
295
+ Description paragraph (first paragraph after heading)
296
+
297
+ ## Configuration
298
+ - Model: sonnet
299
+ - Priority: 100
300
+
301
+ ## Routing
302
+ - Keywords: keyword1, keyword2
303
+ - Paths: /path1/, /path2/
304
+ ```
305
+
306
+ Args:
307
+ md_file: Path to Markdown agent file
308
+
309
+ Returns:
310
+ Agent dictionary in JSON template format, or None if parsing fails
311
+
312
+ Error Handling:
313
+ - Returns None if agent name (first heading) is missing
314
+ - Uses defaults for missing sections (model=sonnet, priority=50)
315
+ - Empty routing keywords/paths if Routing section missing
316
+ """
317
+ try:
318
+ content = md_file.read_text(encoding="utf-8")
319
+ except Exception as e:
320
+ self.logger.error(f"Failed to read file {md_file}: {e}")
321
+ return None
322
+
323
+ # Extract agent name from first heading
324
+ name_match = re.search(r"^#\s+(.+?)$", content, re.MULTILINE)
325
+ if not name_match:
326
+ self.logger.debug(f"No agent name heading found in {md_file.name}")
327
+ return None
328
+ name = name_match.group(1).strip()
329
+
330
+ # Extract description (first paragraph after heading, before next heading)
331
+ desc_match = re.search(
332
+ r"^#.+?\n\n(.+?)(?:\n\n##|\Z)", content, re.DOTALL | re.MULTILINE
333
+ )
334
+ description = desc_match.group(1).strip() if desc_match else ""
335
+
336
+ # Extract model from Configuration section
337
+ model_match = re.search(r"Model:\s*(\w+)", content, re.IGNORECASE)
338
+ model = model_match.group(1) if model_match else "sonnet"
339
+
340
+ # Extract priority from Configuration section
341
+ priority_match = re.search(r"Priority:\s*(\d+)", content, re.IGNORECASE)
342
+ priority = int(priority_match.group(1)) if priority_match else 50
343
+
344
+ # Extract routing keywords
345
+ keywords_match = re.search(r"Keywords:\s*(.+?)(?:\n|$)", content, re.IGNORECASE)
346
+ keywords = []
347
+ if keywords_match:
348
+ keywords = [k.strip() for k in keywords_match.group(1).split(",")]
349
+
350
+ # Extract routing paths
351
+ paths_match = re.search(r"Paths:\s*(.+?)(?:\n|$)", content, re.IGNORECASE)
352
+ paths = []
353
+ if paths_match:
354
+ paths = [p.strip() for p in paths_match.group(1).split(",")]
355
+
356
+ # Get version (SHA-256 hash) from cache metadata
357
+ version = self._get_agent_version(md_file)
358
+
359
+ # Bug #3 fix: Generate hierarchical agent_id from file path
360
+ # This preserves directory structure for category filtering and preset matching
361
+ agent_id = self._generate_hierarchical_id(md_file)
362
+
363
+ # Bug #1 fix: Detect category from directory path
364
+ category = self._detect_category_from_path(md_file)
365
+
366
+ # NEW: Extract collection metadata from path
367
+ collection_id = self._extract_collection_id_from_path(md_file)
368
+ source_path = self._extract_source_path_from_file(md_file)
369
+
370
+ # NEW: Generate canonical_id (collection_id:agent_id)
371
+ if collection_id:
372
+ canonical_id = f"{collection_id}:{agent_id}"
373
+ else:
374
+ # Fallback for legacy agents without collection
375
+ canonical_id = f"legacy:{agent_id}"
376
+
377
+ # Convert to JSON template format and return
378
+ # IMPORTANT: Include 'path' field for compatibility with deployment validation (ticket 1M-480)
379
+ # Git-sourced agents must have 'path' field to match structure from AgentDiscoveryService
380
+ return {
381
+ "agent_id": agent_id,
382
+ "canonical_id": canonical_id, # NEW: Primary matching key
383
+ "collection_id": collection_id, # NEW: Collection identifier
384
+ "source_path": source_path, # NEW: Path within repository
385
+ "metadata": {
386
+ "name": name,
387
+ "description": description,
388
+ "version": version,
389
+ "author": "remote", # Mark as remote agent
390
+ "category": category, # Use detected category from path
391
+ "collection_id": collection_id, # NEW: Also in metadata
392
+ "source_path": source_path, # NEW: Also in metadata
393
+ "canonical_id": canonical_id, # NEW: Also in metadata
394
+ },
395
+ "model": model,
396
+ "source": "remote", # Mark as remote agent
397
+ "source_file": str(md_file),
398
+ "path": str(
399
+ md_file
400
+ ), # Add 'path' field for deployment compatibility (1M-480)
401
+ "file_path": str(md_file), # Keep for backward compatibility
402
+ "version": version, # Include at root level for version comparison
403
+ "category": category, # Add category at root level for filtering
404
+ "routing": {"keywords": keywords, "paths": paths, "priority": priority},
405
+ }
406
+
407
+ def _get_agent_version(self, md_file: Path) -> str:
408
+ """Get version (SHA-256 hash) from cache metadata.
409
+
410
+ Looks for corresponding .meta.json file in cache directory that contains
411
+ the SHA-256 hash of the agent content.
412
+
413
+ Args:
414
+ md_file: Path to Markdown agent file
415
+
416
+ Returns:
417
+ SHA-256 hash from metadata, or 'unknown' if not found
418
+
419
+ Example metadata file:
420
+ {
421
+ "content_hash": "abc123...",
422
+ "etag": "W/\"abc123\"",
423
+ "last_modified": "2025-11-30T10:00:00Z"
424
+ }
425
+ """
426
+ # Look for .meta.json file
427
+ meta_file = md_file.with_suffix(".md.meta.json")
428
+
429
+ if not meta_file.exists():
430
+ self.logger.debug(f"No metadata file found for {md_file.name}")
431
+ return "unknown"
432
+
433
+ try:
434
+ meta_data = json.loads(meta_file.read_text(encoding="utf-8"))
435
+ content_hash = meta_data.get("content_hash", "unknown")
436
+ self.logger.debug(
437
+ f"Retrieved version {content_hash[:8]}... for {md_file.name}"
438
+ )
439
+ return content_hash
440
+ except Exception as e:
441
+ self.logger.warning(f"Failed to read metadata for {md_file.name}: {e}")
442
+ return "unknown"
443
+
444
+ def get_remote_agent_metadata(
445
+ self, agent_name: str
446
+ ) -> Optional[RemoteAgentMetadata]:
447
+ """Get metadata for a specific remote agent.
448
+
449
+ Args:
450
+ agent_name: Name of the agent to retrieve
451
+
452
+ Returns:
453
+ RemoteAgentMetadata if found, None otherwise
454
+ """
455
+ # Bug #4 fix: Search in /agents/ subdirectory, not root directory
456
+ agents_dir = self.remote_agents_dir / "agents"
457
+ if not agents_dir.exists():
458
+ return None
459
+
460
+ for md_file in agents_dir.rglob("*.md"):
461
+ agent_dict = self._parse_markdown_agent(md_file)
462
+ if agent_dict and agent_dict["metadata"]["name"] == agent_name:
463
+ return RemoteAgentMetadata(
464
+ name=agent_dict["metadata"]["name"],
465
+ description=agent_dict["metadata"]["description"],
466
+ model=agent_dict["model"],
467
+ routing_keywords=agent_dict["routing"]["keywords"],
468
+ routing_paths=agent_dict["routing"]["paths"],
469
+ routing_priority=agent_dict["routing"]["priority"],
470
+ source_file=Path(agent_dict["source_file"]),
471
+ version=agent_dict["version"],
472
+ collection_id=agent_dict.get("collection_id"),
473
+ source_path=agent_dict.get("source_path"),
474
+ canonical_id=agent_dict.get("canonical_id"),
475
+ )
476
+ return None
477
+
478
+ def get_agents_by_collection(self, collection_id: str) -> List[Dict[str, Any]]:
479
+ """Get all agents belonging to a specific collection.
480
+
481
+ Args:
482
+ collection_id: Collection identifier in format "owner/repo-name"
483
+
484
+ Returns:
485
+ List of agent dictionaries from the specified collection
486
+
487
+ Example:
488
+ >>> service = RemoteAgentDiscoveryService(Path("~/.claude-mpm/cache/remote-agents"))
489
+ >>> agents = service.get_agents_by_collection("bobmatnyc/claude-mpm-agents")
490
+ >>> len(agents)
491
+ 45
492
+ """
493
+ all_agents = self.discover_remote_agents()
494
+
495
+ # Filter by collection_id
496
+ collection_agents = [
497
+ agent for agent in all_agents if agent.get("collection_id") == collection_id
498
+ ]
499
+
500
+ self.logger.info(
501
+ f"Found {len(collection_agents)} agents in collection '{collection_id}'"
502
+ )
503
+
504
+ return collection_agents
505
+
506
+ def list_collections(self) -> List[Dict[str, Any]]:
507
+ """List all available collections with agent counts.
508
+
509
+ Returns:
510
+ List of collection info dictionaries with:
511
+ - collection_id: Collection identifier
512
+ - agent_count: Number of agents in collection
513
+ - agents: List of agent IDs in collection
514
+
515
+ Example:
516
+ >>> service = RemoteAgentDiscoveryService(Path("~/.claude-mpm/cache/remote-agents"))
517
+ >>> collections = service.list_collections()
518
+ >>> collections
519
+ [
520
+ {
521
+ "collection_id": "bobmatnyc/claude-mpm-agents",
522
+ "agent_count": 45,
523
+ "agents": ["pm", "engineer", "qa", ...]
524
+ }
525
+ ]
526
+ """
527
+ all_agents = self.discover_remote_agents()
528
+
529
+ # Group by collection_id
530
+ collections_map: Dict[str, List[str]] = {}
531
+
532
+ for agent in all_agents:
533
+ collection_id = agent.get("collection_id")
534
+ if not collection_id:
535
+ # Skip agents without collection (legacy)
536
+ continue
537
+
538
+ if collection_id not in collections_map:
539
+ collections_map[collection_id] = []
540
+
541
+ agent_id = agent.get("agent_id", agent.get("metadata", {}).get("name"))
542
+ if agent_id:
543
+ collections_map[collection_id].append(agent_id)
544
+
545
+ # Convert to list format
546
+ collections = [
547
+ {
548
+ "collection_id": coll_id,
549
+ "agent_count": len(agent_ids),
550
+ "agents": sorted(agent_ids),
551
+ }
552
+ for coll_id, agent_ids in collections_map.items()
553
+ ]
554
+
555
+ self.logger.info(f"Found {len(collections)} collections")
556
+
557
+ return collections
@@ -200,8 +200,8 @@ class SingleAgentDeployer:
200
200
  - Enables selective agent management in projects
201
201
  """
202
202
  try:
203
- # Find the template file
204
- template_file = templates_dir / f"{agent_name}.json"
203
+ # Find the template file (templates migrated to .md in v4.26.0+)
204
+ template_file = templates_dir / f"{agent_name}.md"
205
205
  if not template_file.exists():
206
206
  self.logger.error(f"Agent template not found: {agent_name}")
207
207
  return False