claude-mpm 4.20.3__py3-none-any.whl → 5.1.8__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 (520) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +35 -6
  3. claude_mpm/agents/OUTPUT_STYLE.md +3 -48
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +1241 -667
  5. claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +1322 -0
  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 +1 -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 +959 -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 +924 -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/__init__.py +73 -0
  41. claude_mpm/cli/commands/mpm_init/core.py +573 -0
  42. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  43. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  44. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  45. claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
  46. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  47. claude_mpm/cli/commands/mpm_init_handler.py +67 -1
  48. claude_mpm/cli/commands/postmortem.py +401 -0
  49. claude_mpm/cli/commands/run.py +125 -167
  50. claude_mpm/cli/commands/skill_source.py +694 -0
  51. claude_mpm/cli/commands/skills.py +835 -44
  52. claude_mpm/cli/executor.py +78 -3
  53. claude_mpm/cli/interactive/agent_wizard.py +1032 -47
  54. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  55. claude_mpm/cli/parsers/agents_parser.py +256 -4
  56. claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
  57. claude_mpm/cli/parsers/base_parser.py +53 -0
  58. claude_mpm/cli/parsers/config_parser.py +96 -43
  59. claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
  60. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  61. claude_mpm/cli/parsers/skills_parser.py +145 -0
  62. claude_mpm/cli/parsers/source_parser.py +138 -0
  63. claude_mpm/cli/startup.py +564 -108
  64. claude_mpm/cli/startup_display.py +480 -0
  65. claude_mpm/cli/utils.py +1 -1
  66. claude_mpm/cli_module/commands.py +1 -1
  67. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  68. claude_mpm/commands/mpm-agents-detect.md +9 -0
  69. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  70. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  71. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  72. claude_mpm/commands/mpm-doctor.md +9 -0
  73. claude_mpm/commands/mpm-help.md +17 -2
  74. claude_mpm/commands/mpm-init.md +28 -3
  75. claude_mpm/commands/mpm-monitor.md +9 -0
  76. claude_mpm/commands/mpm-postmortem.md +123 -0
  77. claude_mpm/commands/mpm-session-resume.md +381 -0
  78. claude_mpm/commands/mpm-status.md +9 -0
  79. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  80. claude_mpm/commands/mpm-ticket-view.md +552 -0
  81. claude_mpm/commands/mpm-version.md +9 -0
  82. claude_mpm/commands/mpm.md +11 -0
  83. claude_mpm/config/agent_presets.py +488 -0
  84. claude_mpm/config/agent_sources.py +325 -0
  85. claude_mpm/config/skill_presets.py +392 -0
  86. claude_mpm/config/skill_sources.py +590 -0
  87. claude_mpm/constants.py +13 -0
  88. claude_mpm/core/api_validator.py +1 -1
  89. claude_mpm/core/claude_runner.py +19 -35
  90. claude_mpm/core/config.py +24 -0
  91. claude_mpm/core/constants.py +1 -1
  92. claude_mpm/core/framework/__init__.py +3 -16
  93. claude_mpm/core/framework/loaders/file_loader.py +54 -101
  94. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  95. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  96. claude_mpm/core/hook_error_memory.py +381 -0
  97. claude_mpm/core/hook_manager.py +41 -2
  98. claude_mpm/core/interactive_session.py +131 -10
  99. claude_mpm/core/interfaces.py +56 -1
  100. claude_mpm/core/logger.py +3 -1
  101. claude_mpm/core/oneshot_session.py +110 -8
  102. claude_mpm/core/protocols/__init__.py +23 -0
  103. claude_mpm/core/protocols/runner_protocol.py +103 -0
  104. claude_mpm/core/protocols/session_protocol.py +131 -0
  105. claude_mpm/core/shared/singleton_manager.py +11 -4
  106. claude_mpm/core/system_context.py +38 -0
  107. claude_mpm/core/unified_config.py +22 -0
  108. claude_mpm/dashboard/static/css/activity.css +69 -69
  109. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  110. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  111. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  112. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  113. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  114. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  115. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  116. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  117. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  118. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  119. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  120. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  121. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  122. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  123. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  124. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  125. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  126. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  127. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  128. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  129. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  130. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  131. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  132. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  133. claude_mpm/dashboard/templates/code_simple.html +23 -23
  134. claude_mpm/dashboard/templates/index.html +18 -18
  135. claude_mpm/experimental/cli_enhancements.py +1 -5
  136. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  137. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  138. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  139. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  140. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  141. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  142. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  143. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  144. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  145. claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
  146. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  147. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  148. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  149. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  150. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  151. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  152. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  153. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  154. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  155. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  156. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  157. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  158. claude_mpm/models/git_repository.py +198 -0
  159. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  160. claude_mpm/scripts/start_activity_logging.py +3 -1
  161. claude_mpm/services/agents/agent_builder.py +45 -9
  162. claude_mpm/services/agents/agent_preset_service.py +238 -0
  163. claude_mpm/services/agents/agent_selection_service.py +484 -0
  164. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  165. claude_mpm/services/agents/cache_git_manager.py +621 -0
  166. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  167. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  168. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  169. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  170. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  171. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  172. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  173. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  174. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  175. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  176. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
  177. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  178. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  179. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
  180. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  181. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  182. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  183. claude_mpm/services/agents/git_source_manager.py +629 -0
  184. claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
  185. claude_mpm/services/agents/local_template_manager.py +50 -10
  186. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  187. claude_mpm/services/agents/sources/__init__.py +13 -0
  188. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  189. claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
  190. claude_mpm/services/agents/startup_sync.py +239 -0
  191. claude_mpm/services/agents/toolchain_detector.py +474 -0
  192. claude_mpm/services/analysis/__init__.py +25 -0
  193. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  194. claude_mpm/services/analysis/postmortem_service.py +765 -0
  195. claude_mpm/services/cli/session_pause_manager.py +504 -0
  196. claude_mpm/services/cli/session_resume_helper.py +36 -16
  197. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  198. claude_mpm/services/command_deployment_service.py +200 -6
  199. claude_mpm/services/core/base.py +31 -11
  200. claude_mpm/services/core/interfaces/__init__.py +1 -3
  201. claude_mpm/services/core/interfaces/health.py +1 -4
  202. claude_mpm/services/core/interfaces.py +56 -1
  203. claude_mpm/services/core/models/__init__.py +2 -11
  204. claude_mpm/services/core/models/agent_config.py +3 -0
  205. claude_mpm/services/core/models/process.py +4 -0
  206. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  207. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  208. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  209. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  210. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  211. claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
  212. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  213. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  214. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  215. claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
  216. claude_mpm/services/diagnostics/models.py +21 -0
  217. claude_mpm/services/event_bus/direct_relay.py +3 -3
  218. claude_mpm/services/event_bus/event_bus.py +36 -3
  219. claude_mpm/services/event_bus/relay.py +23 -7
  220. claude_mpm/services/events/consumers/logging.py +1 -2
  221. claude_mpm/services/git/__init__.py +21 -0
  222. claude_mpm/services/git/git_operations_service.py +494 -0
  223. claude_mpm/services/github/__init__.py +21 -0
  224. claude_mpm/services/github/github_cli_service.py +397 -0
  225. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  226. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  227. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  228. claude_mpm/services/instructions/__init__.py +9 -0
  229. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  230. claude_mpm/services/local_ops/__init__.py +5 -13
  231. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  232. claude_mpm/services/local_ops/health_manager.py +1 -4
  233. claude_mpm/services/local_ops/process_manager.py +1 -1
  234. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  235. claude_mpm/services/mcp_config_manager.py +75 -145
  236. claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
  237. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  238. claude_mpm/services/mcp_gateway/core/process_pool.py +41 -26
  239. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  240. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  241. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  242. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +26 -21
  243. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  244. claude_mpm/services/mcp_service_verifier.py +6 -3
  245. claude_mpm/services/memory/failure_tracker.py +19 -4
  246. claude_mpm/services/memory/optimizer.py +1 -1
  247. claude_mpm/services/model/model_router.py +8 -9
  248. claude_mpm/services/monitor/daemon.py +29 -9
  249. claude_mpm/services/monitor/daemon_manager.py +96 -19
  250. claude_mpm/services/monitor/server.py +2 -2
  251. claude_mpm/services/native_agent_converter.py +356 -0
  252. claude_mpm/services/port_manager.py +1 -1
  253. claude_mpm/services/pr/__init__.py +14 -0
  254. claude_mpm/services/pr/pr_template_service.py +329 -0
  255. claude_mpm/services/project/documentation_manager.py +2 -1
  256. claude_mpm/services/project/project_organizer.py +4 -0
  257. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  258. claude_mpm/services/runner_configuration_service.py +17 -3
  259. claude_mpm/services/self_upgrade_service.py +165 -7
  260. claude_mpm/services/session_management_service.py +16 -4
  261. claude_mpm/services/skills/__init__.py +18 -0
  262. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  263. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  264. claude_mpm/services/skills_config.py +547 -0
  265. claude_mpm/services/skills_deployer.py +955 -0
  266. claude_mpm/services/socketio/handlers/connection.py +1 -1
  267. claude_mpm/services/socketio/handlers/git.py +2 -2
  268. claude_mpm/services/socketio/server/core.py +1 -4
  269. claude_mpm/services/socketio/server/main.py +1 -3
  270. claude_mpm/services/system_instructions_service.py +1 -3
  271. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  272. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  273. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  274. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  275. claude_mpm/services/unified/unified_deployment.py +1 -5
  276. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  277. claude_mpm/services/visualization/__init__.py +1 -5
  278. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  279. claude_mpm/skills/__init__.py +3 -3
  280. claude_mpm/skills/agent_skills_injector.py +42 -49
  281. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  282. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +17 -10
  283. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +92 -39
  284. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +13 -12
  285. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +5 -3
  286. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +19 -12
  287. claude_mpm/skills/bundled/performance-profiling.md +6 -0
  288. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +6 -6
  289. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +13 -9
  290. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +8 -8
  291. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +37 -15
  292. claude_mpm/skills/skills_registry.py +44 -48
  293. claude_mpm/skills/skills_service.py +117 -108
  294. claude_mpm/templates/questions/__init__.py +38 -0
  295. claude_mpm/templates/questions/base.py +193 -0
  296. claude_mpm/templates/questions/pr_strategy.py +311 -0
  297. claude_mpm/templates/questions/project_init.py +385 -0
  298. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  299. claude_mpm/tools/__main__.py +8 -8
  300. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  301. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  302. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  303. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  304. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  305. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  306. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  307. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  308. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  309. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  310. claude_mpm/utils/agent_dependency_loader.py +80 -13
  311. claude_mpm/utils/agent_filters.py +288 -0
  312. claude_mpm/utils/dependency_cache.py +3 -1
  313. claude_mpm/utils/gitignore.py +244 -0
  314. claude_mpm/utils/log_cleanup.py +3 -3
  315. claude_mpm/utils/migration.py +372 -0
  316. claude_mpm/utils/progress.py +387 -0
  317. claude_mpm/utils/robust_installer.py +3 -5
  318. claude_mpm/utils/structured_questions.py +619 -0
  319. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/METADATA +496 -65
  320. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/RECORD +328 -416
  321. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  322. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  323. claude_mpm/agents/templates/agent-manager.json +0 -273
  324. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  325. claude_mpm/agents/templates/api_qa.json +0 -180
  326. claude_mpm/agents/templates/circuit_breakers.md +0 -638
  327. claude_mpm/agents/templates/clerk-ops.json +0 -235
  328. claude_mpm/agents/templates/code_analyzer.json +0 -101
  329. claude_mpm/agents/templates/content-agent.json +0 -358
  330. claude_mpm/agents/templates/dart_engineer.json +0 -307
  331. claude_mpm/agents/templates/data_engineer.json +0 -225
  332. claude_mpm/agents/templates/documentation.json +0 -211
  333. claude_mpm/agents/templates/engineer.json +0 -210
  334. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  335. claude_mpm/agents/templates/golang_engineer.json +0 -270
  336. claude_mpm/agents/templates/imagemagick.json +0 -264
  337. claude_mpm/agents/templates/java_engineer.json +0 -346
  338. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  339. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  340. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  341. claude_mpm/agents/templates/memory_manager.json +0 -158
  342. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  343. claude_mpm/agents/templates/ops.json +0 -185
  344. claude_mpm/agents/templates/php-engineer.json +0 -281
  345. claude_mpm/agents/templates/product_owner.json +0 -338
  346. claude_mpm/agents/templates/project_organizer.json +0 -140
  347. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  348. claude_mpm/agents/templates/python_engineer.json +0 -387
  349. claude_mpm/agents/templates/qa.json +0 -242
  350. claude_mpm/agents/templates/react_engineer.json +0 -238
  351. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  352. claude_mpm/agents/templates/research.json +0 -188
  353. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  354. claude_mpm/agents/templates/rust_engineer.json +0 -275
  355. claude_mpm/agents/templates/security.json +0 -202
  356. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  357. claude_mpm/agents/templates/ticketing.json +0 -177
  358. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  359. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  360. claude_mpm/agents/templates/version_control.json +0 -157
  361. claude_mpm/agents/templates/web_qa.json +0 -399
  362. claude_mpm/agents/templates/web_ui.json +0 -189
  363. claude_mpm/cli/commands/mpm_init.py +0 -2093
  364. claude_mpm/commands/mpm-tickets.md +0 -102
  365. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  366. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  367. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  368. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  369. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  370. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  371. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  372. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  373. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  374. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  375. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  376. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  377. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  378. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  379. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  380. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  381. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  382. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  383. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  384. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  385. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  386. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  387. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  388. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  389. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  390. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  391. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  392. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  393. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  394. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  395. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  396. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  397. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  398. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  399. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  400. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  401. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  402. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  403. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  404. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  405. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  406. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  407. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  408. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  409. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  410. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  411. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  412. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  413. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  414. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  415. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  416. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  417. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  418. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  419. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  420. claude_mpm/dashboard/static/built/react/events.js +0 -30
  421. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  422. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  423. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  424. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  425. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  426. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  427. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  428. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  429. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  430. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  431. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  432. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  433. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  434. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  435. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  436. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  437. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  438. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  439. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  440. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  441. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  442. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  443. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  444. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  445. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  446. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  447. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  448. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  449. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  450. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  451. claude_mpm/dashboard/static/events.html +0 -607
  452. claude_mpm/dashboard/static/index.html +0 -635
  453. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  454. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  455. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  456. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  457. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  458. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  459. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  460. claude_mpm/dashboard/static/legacy/files.html +0 -747
  461. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  462. claude_mpm/dashboard/static/monitors.html +0 -431
  463. claude_mpm/dashboard/static/production/events.html +0 -659
  464. claude_mpm/dashboard/static/production/main.html +0 -698
  465. claude_mpm/dashboard/static/production/monitors.html +0 -483
  466. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  467. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  468. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  469. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  470. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  471. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -75
  472. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -184
  473. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -107
  474. claude_mpm/skills/bundled/collaboration/requesting-code-review/code-reviewer.md +0 -146
  475. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -118
  476. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -177
  477. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  478. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  479. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  480. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  481. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  482. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  483. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  484. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  485. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  486. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  487. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -175
  488. claude_mpm/skills/bundled/debugging/verification-before-completion/references/common-failures.md +0 -213
  489. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -314
  490. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -227
  491. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -74
  492. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -32
  493. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  494. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  495. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  496. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  497. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -328
  498. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  499. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  500. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  501. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  502. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -209
  503. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -123
  504. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  505. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  506. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  507. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  508. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  509. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  510. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -304
  511. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -96
  512. claude_mpm/tools/code_tree_analyzer.py +0 -1825
  513. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  514. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  515. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  516. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  517. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/WHEEL +0 -0
  518. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/entry_points.txt +0 -0
  519. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/licenses/LICENSE +0 -0
  520. {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,288 @@
1
+ """
2
+ Agent filtering utilities for claude-mpm.
3
+
4
+ WHY: This module provides centralized filtering logic to remove non-deployable
5
+ agents (BASE_AGENT) and already-deployed agents from user-facing displays.
6
+
7
+ DESIGN DECISIONS:
8
+ - BASE_AGENT is a build tool, not a deployable agent - filter everywhere
9
+ - Deployed agent detection supports both new (.claude-mpm/agents/) and
10
+ legacy (.claude/agents/)
11
+ - Case-insensitive BASE_AGENT detection for robustness
12
+ - Pure functions for easy testing and reuse
13
+
14
+ IMPLEMENTATION NOTES:
15
+ - Related to ticket 1M-502 Phase 1: UX improvements for agent filtering
16
+ - Addresses user confusion from seeing BASE_AGENT and deployed agents in lists
17
+ """
18
+
19
+ from pathlib import Path
20
+ from typing import Dict, List, Optional, Set
21
+
22
+
23
+ def is_base_agent(agent_id: str) -> bool:
24
+ """Check if agent is BASE_AGENT (build tool, not deployable).
25
+
26
+ BASE_AGENT is an internal build tool used to construct other agents.
27
+ It should never appear in user-facing agent lists or deployment menus.
28
+
29
+ Args:
30
+ agent_id: Agent identifier to check (may include path like "qa/BASE-AGENT")
31
+
32
+ Returns:
33
+ True if agent is BASE_AGENT (case-insensitive), False otherwise
34
+
35
+ Examples:
36
+ >>> is_base_agent("BASE_AGENT")
37
+ True
38
+ >>> is_base_agent("base-agent")
39
+ True
40
+ >>> is_base_agent("qa/BASE-AGENT")
41
+ True
42
+ >>> is_base_agent("ENGINEER")
43
+ False
44
+ """
45
+ if not agent_id:
46
+ return False
47
+
48
+ # Extract filename from path (handle cases like "qa/BASE-AGENT")
49
+ # 1M-502: Remote agents may have path prefixes like "qa/", "pm/", etc.
50
+ agent_name = agent_id.split("/")[-1]
51
+
52
+ normalized_id = agent_name.lower().replace("-", "").replace("_", "")
53
+ return normalized_id == "baseagent"
54
+
55
+
56
+ def filter_base_agents(agents: List[Dict]) -> List[Dict]:
57
+ """Remove BASE_AGENT from agent list.
58
+
59
+ Filters out any agent with agent_id matching BASE_AGENT (case-insensitive).
60
+ This prevents users from seeing or selecting the internal build tool.
61
+
62
+ Args:
63
+ agents: List of agent dictionaries, each containing at least 'agent_id' key
64
+
65
+ Returns:
66
+ Filtered list with BASE_AGENT removed
67
+
68
+ Examples:
69
+ >>> agents = [
70
+ ... {"agent_id": "ENGINEER", "name": "Engineer"},
71
+ ... {"agent_id": "BASE_AGENT", "name": "Base Agent"},
72
+ ... {"agent_id": "PM", "name": "PM"}
73
+ ... ]
74
+ >>> filtered = filter_base_agents(agents)
75
+ >>> len(filtered)
76
+ 2
77
+ >>> "BASE_AGENT" in [a["agent_id"] for a in filtered]
78
+ False
79
+ """
80
+ return [a for a in agents if not is_base_agent(a.get("agent_id", ""))]
81
+
82
+
83
+ def get_deployed_agent_ids(project_dir: Optional[Path] = None) -> Set[str]:
84
+ """Get set of currently deployed agent IDs.
85
+
86
+ Checks virtual deployment state (.mpm_deployment_state) first, then falls back
87
+ to physical .md files for backward compatibility. This ensures agents are detected
88
+ whether deployed virtually or as physical files.
89
+
90
+ Args:
91
+ project_dir: Project directory to check, defaults to current working directory
92
+
93
+ Returns:
94
+ Set of deployed agent IDs (leaf names like "python-engineer", "qa")
95
+
96
+ Examples:
97
+ >>> deployed = get_deployed_agent_ids()
98
+ >>> "python-engineer" in deployed # If agent exists in deployment state
99
+ True
100
+ >>> "ENGINEER" in deployed # If ENGINEER.md exists
101
+ True
102
+
103
+ Design Rationale:
104
+ - Primary detection: Virtual deployment state (.mpm_deployment_state)
105
+ - Fallback detection: Physical .md files (.claude-mpm/agents/, .claude/agents/)
106
+ - Returns leaf names for consistent comparison with agent_id formats
107
+ - Combines both detection methods for complete coverage
108
+ - Graceful error handling for malformed or missing state files
109
+
110
+ Related:
111
+ - Fixes checkbox interface showing all agents as "○ [Available]" instead of "● [Installed]"
112
+ - Matches detection logic from _is_agent_deployed() in agent_state_manager.py
113
+ - Related to ticket 1M-502: Virtual deployment state detection
114
+ """
115
+ deployed = set()
116
+
117
+ # Track if project_dir was explicitly provided
118
+ explicit_project_dir = project_dir is not None
119
+
120
+ if project_dir is None:
121
+ project_dir = Path.cwd()
122
+
123
+ # NEW: Check virtual deployment state (primary method)
124
+ # This is the current deployment model used by Claude Code
125
+ deployment_state_paths = [
126
+ project_dir / ".claude" / "agents" / ".mpm_deployment_state",
127
+ ]
128
+
129
+ # Only check user-level state if using default project directory
130
+ # This prevents test isolation issues when explicit project_dir is provided
131
+ if not explicit_project_dir:
132
+ deployment_state_paths.append(
133
+ Path.home() / ".claude" / "agents" / ".mpm_deployment_state"
134
+ )
135
+
136
+ for state_path in deployment_state_paths:
137
+ if state_path.exists():
138
+ try:
139
+ import json
140
+
141
+ with state_path.open() as f:
142
+ state = json.load(f)
143
+
144
+ # Extract agent IDs from deployment state
145
+ # Agent IDs are leaf names (e.g., "python-engineer", "qa")
146
+ agents = state.get("last_check_results", {}).get("agents", {})
147
+ deployed.update(agents.keys())
148
+
149
+ except (json.JSONDecodeError, KeyError) as e:
150
+ # Log error but continue - don't break if state file is malformed
151
+ import logging
152
+
153
+ logger = logging.getLogger(__name__)
154
+ logger.debug(f"Failed to read deployment state from {state_path}: {e}")
155
+ continue
156
+ except Exception as e:
157
+ # Catch unexpected errors - fail gracefully
158
+ import logging
159
+
160
+ logger = logging.getLogger(__name__)
161
+ logger.debug(f"Unexpected error reading deployment state: {e}")
162
+ continue
163
+
164
+ # EXISTING: Check physical .md files (fallback for backward compatibility)
165
+ # Check new architecture
166
+ new_agents_dir = project_dir / ".claude-mpm" / "agents"
167
+ if new_agents_dir.exists():
168
+ for file in new_agents_dir.glob("*.md"):
169
+ if file.stem not in {"BASE-AGENT", ".DS_Store"}:
170
+ deployed.add(file.stem)
171
+
172
+ # Check legacy architecture
173
+ legacy_agents_dir = project_dir / ".claude" / "agents"
174
+ if legacy_agents_dir.exists():
175
+ for file in legacy_agents_dir.glob("*.md"):
176
+ if file.stem not in {"BASE-AGENT", ".DS_Store"}:
177
+ deployed.add(file.stem)
178
+
179
+ # Check .claude/templates/ directory (where agents are actually deployed)
180
+ templates_dir = project_dir / ".claude" / "templates"
181
+ if templates_dir.exists():
182
+ for file in templates_dir.glob("*.md"):
183
+ if file.stem not in {
184
+ "BASE-AGENT",
185
+ ".DS_Store",
186
+ "README",
187
+ "circuit-breakers",
188
+ }:
189
+ # Skip template/example files
190
+ if not any(x in file.stem for x in ["example", "template", "pm-"]):
191
+ deployed.add(file.stem)
192
+
193
+ # Check user-level directory only if using default project directory
194
+ # This prevents test isolation issues when explicit project_dir is provided
195
+ if not explicit_project_dir:
196
+ user_agents_dir = Path.home() / ".claude" / "agents"
197
+ if user_agents_dir.exists():
198
+ for file in user_agents_dir.glob("*.md"):
199
+ if file.stem not in {"BASE-AGENT", ".DS_Store"}:
200
+ deployed.add(file.stem)
201
+
202
+ return deployed
203
+
204
+
205
+ def filter_deployed_agents(
206
+ agents: List[Dict], project_dir: Optional[Path] = None
207
+ ) -> List[Dict]:
208
+ """Remove already-deployed agents from list.
209
+
210
+ Filters agent list to show only agents that are not currently deployed.
211
+ This prevents users from attempting to re-deploy existing agents and
212
+ reduces confusion in deployment menus.
213
+
214
+ Args:
215
+ agents: List of agent dictionaries, each containing at least 'agent_id' key
216
+ project_dir: Project directory to check, defaults to current working directory
217
+
218
+ Returns:
219
+ Filtered list containing only non-deployed agents
220
+
221
+ Examples:
222
+ >>> agents = [
223
+ ... {"agent_id": "ENGINEER", "name": "Engineer"},
224
+ ... {"agent_id": "PM", "name": "PM"},
225
+ ... {"agent_id": "QA", "name": "QA"}
226
+ ... ]
227
+ >>> # Assuming ENGINEER is deployed
228
+ >>> filtered = filter_deployed_agents(agents)
229
+ >>> "ENGINEER" not in [a["agent_id"] for a in filtered]
230
+ True
231
+
232
+ Design Rationale:
233
+ - Checks filesystem for actual deployed files (source of truth)
234
+ - Supports both new and legacy agent directory structures
235
+ - Preserves agent order for consistent UX
236
+ """
237
+ deployed_ids = get_deployed_agent_ids(project_dir)
238
+ return [a for a in agents if a.get("agent_id") not in deployed_ids]
239
+
240
+
241
+ def apply_all_filters(
242
+ agents: List[Dict],
243
+ project_dir: Optional[Path] = None,
244
+ filter_base: bool = True,
245
+ filter_deployed: bool = False,
246
+ ) -> List[Dict]:
247
+ """Apply multiple filters to agent list in correct order.
248
+
249
+ Convenience function to apply common filtering combinations. Filters are
250
+ applied in this order:
251
+ 1. BASE_AGENT filtering (if enabled)
252
+ 2. Deployed agent filtering (if enabled)
253
+
254
+ Args:
255
+ agents: List of agent dictionaries to filter
256
+ project_dir: Project directory for deployment checks
257
+ filter_base: Remove BASE_AGENT from list (default: True)
258
+ filter_deployed: Remove deployed agents from list (default: False)
259
+
260
+ Returns:
261
+ Filtered agent list
262
+
263
+ Examples:
264
+ >>> agents = get_all_agents()
265
+ >>> # For display/info purposes - remove only BASE_AGENT
266
+ >>> filtered = apply_all_filters(
267
+ ... agents, filter_base=True, filter_deployed=False
268
+ ... )
269
+ >>> # For deployment menus - remove BASE_AGENT and deployed agents
270
+ >>> deployable = apply_all_filters(
271
+ ... agents, filter_base=True, filter_deployed=True
272
+ ... )
273
+
274
+ Usage Guidelines:
275
+ - Use filter_base=True (default) for all user-facing displays
276
+ - Use filter_deployed=True when showing deployment options
277
+ - Use filter_deployed=False when showing all available agents
278
+ (info/list commands)
279
+ """
280
+ result = agents
281
+
282
+ if filter_base:
283
+ result = filter_base_agents(result)
284
+
285
+ if filter_deployed:
286
+ result = filter_deployed_agents(result, project_dir)
287
+
288
+ return result
@@ -333,7 +333,9 @@ class SmartDependencyChecker:
333
333
  return True, "No valid cache, checking needed"
334
334
 
335
335
  def get_or_check_dependencies(
336
- self, loader, force_check: bool = False # AgentDependencyLoader instance
336
+ self,
337
+ loader,
338
+ force_check: bool = False, # AgentDependencyLoader instance
337
339
  ) -> Tuple[Dict, bool]:
338
340
  """
339
341
  Get dependency results from cache or perform check.
@@ -0,0 +1,244 @@
1
+ """GitIgnore management utilities.
2
+
3
+ This module provides functionality to safely manage .gitignore entries,
4
+ ensuring claude-mpm configuration directories are excluded from version control.
5
+
6
+ Design Decisions:
7
+ - In-memory set for duplicate detection (O(1) lookups)
8
+ - Preserves existing file formatting and comments
9
+ - Adds section headers for clarity
10
+ - Handles edge cases (missing newlines, empty files, etc.)
11
+
12
+ Trade-offs:
13
+ - Simplicity: File append vs. full parse/rewrite (chosen append for safety)
14
+ - Performance: Read entire file vs. streaming (file is small, simplicity wins)
15
+ - Safety: Non-destructive append only, never modifies existing entries
16
+ """
17
+
18
+ from pathlib import Path
19
+ from typing import List, Set, Tuple
20
+
21
+ from claude_mpm.core.logging_utils import get_logger
22
+
23
+ logger = get_logger(__name__)
24
+
25
+
26
+ class GitIgnoreManager:
27
+ """Manages .gitignore file updates safely and non-destructively.
28
+
29
+ Design Pattern: Builder pattern for fluent API
30
+ - Initialize with project directory
31
+ - Call ensure_entries() to add patterns
32
+ - Returns summary of changes made
33
+
34
+ Performance:
35
+ - Time Complexity: O(n) where n = existing .gitignore lines
36
+ - Space Complexity: O(n) for storing unique entries in set
37
+ - Expected Performance: <1ms for typical .gitignore files (<1000 lines)
38
+
39
+ Error Handling:
40
+ - FileNotFoundError: Creates new .gitignore if missing
41
+ - PermissionError: Propagated to caller for appropriate handling
42
+ - UnicodeDecodeError: Logged and treated as binary file (skip)
43
+ """
44
+
45
+ def __init__(self, project_dir: Path):
46
+ """Initialize with project directory.
47
+
48
+ Args:
49
+ project_dir: Path to project root (where .gitignore lives)
50
+ """
51
+ self.project_dir = Path(project_dir)
52
+ self.gitignore_path = self.project_dir / ".gitignore"
53
+
54
+ def ensure_entries(self, entries: List[str]) -> Tuple[List[str], List[str]]:
55
+ """Ensure specified entries exist in .gitignore.
56
+
57
+ Non-destructive operation that:
58
+ 1. Reads existing entries (if file exists)
59
+ 2. Identifies which entries are missing
60
+ 3. Appends only missing entries with section header
61
+ 4. Preserves all existing content and formatting
62
+
63
+ Args:
64
+ entries: List of gitignore patterns to add (e.g., [".claude-mpm/"])
65
+
66
+ Returns:
67
+ Tuple of (added_entries, existing_entries)
68
+ - added_entries: Patterns that were added to .gitignore
69
+ - existing_entries: Patterns that were already present
70
+
71
+ Example:
72
+ >>> manager = GitIgnoreManager(Path("."))
73
+ >>> added, existing = manager.ensure_entries([".claude-mpm/"])
74
+ >>> print(f"Added: {added}, Already present: {existing}")
75
+ Added: ['.claude-mpm/'], Already present: []
76
+ """
77
+ # Read existing entries
78
+ existing = self._read_existing_entries()
79
+
80
+ # Determine what needs to be added
81
+ to_add = [e for e in entries if e not in existing]
82
+ already_present = [e for e in entries if e in existing]
83
+
84
+ if to_add:
85
+ self._append_entries(to_add)
86
+ logger.info(f"Added {len(to_add)} entries to .gitignore: {to_add}")
87
+
88
+ if already_present:
89
+ logger.debug(f"Entries already in .gitignore: {already_present}")
90
+
91
+ return to_add, already_present
92
+
93
+ def _read_existing_entries(self) -> Set[str]:
94
+ """Read existing .gitignore entries.
95
+
96
+ Parses .gitignore file and extracts all non-comment, non-blank patterns.
97
+ Handles edge cases:
98
+ - File doesn't exist -> returns empty set
99
+ - File is binary -> logs warning, returns empty set
100
+ - File has no newline at end -> handled correctly
101
+
102
+ Returns:
103
+ Set of existing gitignore patterns (stripped, normalized)
104
+ """
105
+ if not self.gitignore_path.exists():
106
+ logger.debug(".gitignore does not exist, will create new file")
107
+ return set()
108
+
109
+ try:
110
+ with open(self.gitignore_path, encoding="utf-8") as f:
111
+ # Strip whitespace and comments, filter blanks
112
+ entries = {
113
+ line.strip()
114
+ for line in f
115
+ if line.strip() and not line.strip().startswith("#")
116
+ }
117
+
118
+ logger.debug(f"Found {len(entries)} existing entries in .gitignore")
119
+ return entries
120
+
121
+ except UnicodeDecodeError:
122
+ logger.warning(
123
+ f".gitignore appears to be binary, cannot parse: {self.gitignore_path}"
124
+ )
125
+ return set()
126
+ except Exception as e:
127
+ logger.error(f"Error reading .gitignore: {e}")
128
+ raise
129
+
130
+ def _append_entries(self, entries: List[str]) -> None:
131
+ """Append entries to .gitignore with proper formatting.
132
+
133
+ Handles formatting edge cases:
134
+ - Ensures blank line before new section (if file exists and isn't empty)
135
+ - Adds section header comment for clarity
136
+ - Ensures each entry on its own line
137
+ - Handles missing trailing newline in existing file
138
+
139
+ Args:
140
+ entries: List of patterns to append
141
+
142
+ Raises:
143
+ PermissionError: If cannot write to .gitignore
144
+ OSError: If disk is full or other I/O error
145
+ """
146
+ mode = "a" if self.gitignore_path.exists() else "w"
147
+
148
+ try:
149
+ with open(self.gitignore_path, mode, encoding="utf-8") as f:
150
+ # Add blank line before entries if file exists and isn't empty
151
+ if mode == "a" and self.gitignore_path.stat().st_size > 0:
152
+ # Check if last line has newline
153
+ with open(self.gitignore_path, "rb") as check:
154
+ check.seek(-1, 2) # Seek to last byte
155
+ last_byte = check.read(1)
156
+ if last_byte != b"\n":
157
+ f.write("\n")
158
+
159
+ f.write("\n# Claude MPM configuration\n")
160
+ else:
161
+ # New file or empty file - add header without extra blank line
162
+ f.write("# Claude MPM configuration\n")
163
+
164
+ for entry in entries:
165
+ f.write(f"{entry}\n")
166
+
167
+ logger.info(f"Updated .gitignore at {self.gitignore_path}")
168
+
169
+ except PermissionError:
170
+ logger.error(
171
+ f"Permission denied writing to .gitignore: {self.gitignore_path}"
172
+ )
173
+ raise
174
+ except OSError as e:
175
+ logger.error(f"I/O error writing to .gitignore: {e}")
176
+ raise
177
+
178
+
179
+ def ensure_claude_mpm_gitignore(project_dir: str = ".") -> dict:
180
+ """Ensure claude-mpm directories are in .gitignore.
181
+
182
+ Convenience function that wraps GitIgnoreManager to add standard
183
+ claude-mpm configuration directories to .gitignore.
184
+
185
+ Standard Entries Added:
186
+ - .claude-mpm/: Main configuration directory
187
+ - .claude/agents/: Agent runtime files
188
+
189
+ Args:
190
+ project_dir: Project directory path (default: current directory)
191
+
192
+ Returns:
193
+ Dictionary with operation results:
194
+ - added: List of patterns that were added
195
+ - existing: List of patterns that were already present
196
+ - gitignore_path: Path to the .gitignore file
197
+
198
+ Example:
199
+ >>> result = ensure_claude_mpm_gitignore()
200
+ >>> if result["added"]:
201
+ ... print(f"Added {len(result['added'])} entries to .gitignore")
202
+
203
+ Error Handling:
204
+ - PermissionError: Returns error dict with status="error"
205
+ - FileNotFoundError on parent dir: Returns error dict
206
+ - All other exceptions: Propagated to caller
207
+ """
208
+ try:
209
+ manager = GitIgnoreManager(Path(project_dir))
210
+
211
+ # Standard claude-mpm entries
212
+ entries_to_add = [
213
+ ".claude-mpm/",
214
+ ".claude/agents/",
215
+ ".mcp.json",
216
+ ".claude.json",
217
+ ".claude/",
218
+ ]
219
+
220
+ added, existing = manager.ensure_entries(entries_to_add)
221
+
222
+ return {
223
+ "status": "success",
224
+ "added": added,
225
+ "existing": existing,
226
+ "gitignore_path": str(manager.gitignore_path),
227
+ }
228
+
229
+ except PermissionError as e:
230
+ logger.error(f"Permission denied updating .gitignore: {e}")
231
+ return {
232
+ "status": "error",
233
+ "error": f"Permission denied: {e}",
234
+ "added": [],
235
+ "existing": [],
236
+ }
237
+ except FileNotFoundError as e:
238
+ logger.error(f"Project directory not found: {e}")
239
+ return {
240
+ "status": "error",
241
+ "error": f"Directory not found: {e}",
242
+ "added": [],
243
+ "existing": [],
244
+ }
@@ -496,15 +496,15 @@ class LogCleanupUtility:
496
496
  }
497
497
 
498
498
  # Cleanup operations
499
- sessions_removed, sessions_space = self.cleanup_old_sessions(
499
+ _sessions_removed, _sessions_space = self.cleanup_old_sessions(
500
500
  session_max_age_days, dry_run
501
501
  )
502
502
 
503
- archives_removed, archives_space = self.cleanup_archived_logs(
503
+ _archives_removed, _archives_space = self.cleanup_archived_logs(
504
504
  archive_max_age_days, dry_run
505
505
  )
506
506
 
507
- logs_removed, logs_space = self.cleanup_old_logs(log_max_age_days, dry_run)
507
+ _logs_removed, _logs_space = self.cleanup_old_logs(log_max_age_days, dry_run)
508
508
 
509
509
  # Optional compression
510
510
  if compress_age_days is not None: