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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +12 -0
  3. claude_mpm/agents/OUTPUT_STYLE.md +3 -48
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +632 -334
  5. claude_mpm/agents/WORKFLOW.md +75 -2
  6. claude_mpm/agents/__init__.py +6 -0
  7. claude_mpm/agents/agent_loader.py +1 -4
  8. claude_mpm/agents/base_agent.json +6 -3
  9. claude_mpm/agents/frontmatter_validator.py +1 -1
  10. claude_mpm/agents/templates/{circuit_breakers.md → circuit-breakers.md} +370 -3
  11. claude_mpm/agents/templates/context-management-examples.md +544 -0
  12. claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +89 -19
  13. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  14. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  15. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  16. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  17. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  18. claude_mpm/cli/__init__.py +38 -2
  19. claude_mpm/cli/commands/agent_source.py +774 -0
  20. claude_mpm/cli/commands/agent_state_manager.py +125 -20
  21. claude_mpm/cli/commands/agents.py +684 -13
  22. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  23. claude_mpm/cli/commands/agents_discover.py +338 -0
  24. claude_mpm/cli/commands/aggregate.py +1 -1
  25. claude_mpm/cli/commands/analyze.py +3 -3
  26. claude_mpm/cli/commands/auto_configure.py +2 -6
  27. claude_mpm/cli/commands/cleanup.py +1 -1
  28. claude_mpm/cli/commands/config.py +7 -4
  29. claude_mpm/cli/commands/configure.py +478 -44
  30. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  31. claude_mpm/cli/commands/configure_navigation.py +63 -46
  32. claude_mpm/cli/commands/debug.py +12 -12
  33. claude_mpm/cli/commands/doctor.py +10 -2
  34. claude_mpm/cli/commands/hook_errors.py +277 -0
  35. claude_mpm/cli/commands/local_deploy.py +1 -4
  36. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  37. claude_mpm/cli/commands/mpm_init/core.py +50 -2
  38. claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
  39. claude_mpm/cli/commands/mpm_init/prompts.py +6 -6
  40. claude_mpm/cli/commands/run.py +124 -128
  41. claude_mpm/cli/commands/skill_source.py +694 -0
  42. claude_mpm/cli/commands/skills.py +435 -1
  43. claude_mpm/cli/executor.py +78 -3
  44. claude_mpm/cli/interactive/agent_wizard.py +919 -41
  45. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  46. claude_mpm/cli/parsers/agents_parser.py +173 -4
  47. claude_mpm/cli/parsers/base_parser.py +49 -0
  48. claude_mpm/cli/parsers/config_parser.py +96 -43
  49. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  50. claude_mpm/cli/parsers/skills_parser.py +138 -0
  51. claude_mpm/cli/parsers/source_parser.py +138 -0
  52. claude_mpm/cli/startup.py +499 -84
  53. claude_mpm/cli/startup_display.py +480 -0
  54. claude_mpm/cli/utils.py +1 -1
  55. claude_mpm/cli_module/commands.py +1 -1
  56. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  57. claude_mpm/commands/mpm-agents-detect.md +9 -0
  58. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  59. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  60. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  61. claude_mpm/commands/mpm-doctor.md +9 -0
  62. claude_mpm/commands/mpm-help.md +11 -2
  63. claude_mpm/commands/mpm-init.md +27 -2
  64. claude_mpm/commands/mpm-monitor.md +9 -0
  65. claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
  66. claude_mpm/commands/mpm-status.md +9 -0
  67. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  68. claude_mpm/commands/mpm-ticket-view.md +552 -0
  69. claude_mpm/commands/mpm-version.md +9 -0
  70. claude_mpm/commands/mpm.md +10 -0
  71. claude_mpm/config/agent_presets.py +258 -0
  72. claude_mpm/config/agent_sources.py +325 -0
  73. claude_mpm/config/skill_sources.py +590 -0
  74. claude_mpm/constants.py +12 -0
  75. claude_mpm/core/api_validator.py +1 -1
  76. claude_mpm/core/claude_runner.py +17 -10
  77. claude_mpm/core/config.py +24 -0
  78. claude_mpm/core/constants.py +1 -1
  79. claude_mpm/core/framework/__init__.py +3 -16
  80. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  81. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  82. claude_mpm/core/hook_error_memory.py +381 -0
  83. claude_mpm/core/hook_manager.py +41 -2
  84. claude_mpm/core/interactive_session.py +112 -5
  85. claude_mpm/core/logger.py +3 -1
  86. claude_mpm/core/oneshot_session.py +94 -4
  87. claude_mpm/dashboard/static/css/activity.css +69 -69
  88. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  89. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  90. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  91. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  92. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  93. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  94. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  95. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  96. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  97. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  98. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  99. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  100. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  101. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  102. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  103. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  104. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  105. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  106. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  107. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  108. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  109. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  110. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  111. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  112. claude_mpm/dashboard/templates/code_simple.html +23 -23
  113. claude_mpm/dashboard/templates/index.html +18 -18
  114. claude_mpm/experimental/cli_enhancements.py +1 -5
  115. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  116. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  117. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  118. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  119. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  120. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  121. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  122. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  123. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  124. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  125. claude_mpm/models/git_repository.py +198 -0
  126. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  127. claude_mpm/scripts/start_activity_logging.py +3 -1
  128. claude_mpm/services/agents/agent_builder.py +45 -9
  129. claude_mpm/services/agents/agent_preset_service.py +238 -0
  130. claude_mpm/services/agents/agent_selection_service.py +484 -0
  131. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  132. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  133. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  134. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  135. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  136. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  137. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  138. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  139. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  140. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  141. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  142. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
  143. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  144. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  145. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
  146. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  147. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  148. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  149. claude_mpm/services/agents/git_source_manager.py +629 -0
  150. claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
  151. claude_mpm/services/agents/local_template_manager.py +50 -10
  152. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  153. claude_mpm/services/agents/sources/__init__.py +13 -0
  154. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  155. claude_mpm/services/agents/sources/git_source_sync_service.py +1055 -0
  156. claude_mpm/services/agents/startup_sync.py +239 -0
  157. claude_mpm/services/agents/toolchain_detector.py +474 -0
  158. claude_mpm/services/cli/session_pause_manager.py +1 -1
  159. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  160. claude_mpm/services/command_deployment_service.py +92 -1
  161. claude_mpm/services/core/interfaces/__init__.py +1 -3
  162. claude_mpm/services/core/interfaces/health.py +1 -4
  163. claude_mpm/services/core/models/__init__.py +2 -11
  164. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  165. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  166. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  167. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  168. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  169. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  170. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  171. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  172. claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
  173. claude_mpm/services/event_bus/direct_relay.py +3 -3
  174. claude_mpm/services/event_bus/event_bus.py +36 -3
  175. claude_mpm/services/events/consumers/logging.py +1 -2
  176. claude_mpm/services/git/__init__.py +21 -0
  177. claude_mpm/services/git/git_operations_service.py +494 -0
  178. claude_mpm/services/github/__init__.py +21 -0
  179. claude_mpm/services/github/github_cli_service.py +397 -0
  180. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  181. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  182. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  183. claude_mpm/services/instructions/__init__.py +9 -0
  184. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  185. claude_mpm/services/local_ops/__init__.py +3 -13
  186. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  187. claude_mpm/services/local_ops/health_manager.py +1 -4
  188. claude_mpm/services/local_ops/process_manager.py +1 -1
  189. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  190. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  191. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  192. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  193. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  194. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  195. claude_mpm/services/memory/optimizer.py +1 -1
  196. claude_mpm/services/model/model_router.py +8 -9
  197. claude_mpm/services/monitor/daemon.py +1 -1
  198. claude_mpm/services/monitor/server.py +2 -2
  199. claude_mpm/services/native_agent_converter.py +356 -0
  200. claude_mpm/services/port_manager.py +1 -1
  201. claude_mpm/services/pr/__init__.py +14 -0
  202. claude_mpm/services/pr/pr_template_service.py +329 -0
  203. claude_mpm/services/project/documentation_manager.py +2 -1
  204. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  205. claude_mpm/services/runner_configuration_service.py +1 -0
  206. claude_mpm/services/self_upgrade_service.py +165 -7
  207. claude_mpm/services/skills/__init__.py +18 -0
  208. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  209. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  210. claude_mpm/services/skills_config.py +547 -0
  211. claude_mpm/services/skills_deployer.py +955 -0
  212. claude_mpm/services/socketio/handlers/connection.py +1 -1
  213. claude_mpm/services/socketio/handlers/git.py +2 -2
  214. claude_mpm/services/socketio/server/core.py +1 -4
  215. claude_mpm/services/socketio/server/main.py +1 -3
  216. claude_mpm/services/system_instructions_service.py +1 -3
  217. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  218. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  219. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  220. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  221. claude_mpm/services/unified/unified_deployment.py +1 -5
  222. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  223. claude_mpm/services/visualization/__init__.py +1 -5
  224. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  225. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  226. claude_mpm/skills/bundled/performance-profiling.md +6 -0
  227. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
  228. claude_mpm/skills/skills_registry.py +0 -1
  229. claude_mpm/templates/questions/__init__.py +38 -0
  230. claude_mpm/templates/questions/base.py +193 -0
  231. claude_mpm/templates/questions/pr_strategy.py +311 -0
  232. claude_mpm/templates/questions/project_init.py +385 -0
  233. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  234. claude_mpm/tools/__main__.py +8 -8
  235. claude_mpm/tools/code_tree_analyzer/analysis.py +1 -1
  236. claude_mpm/utils/agent_dependency_loader.py +80 -13
  237. claude_mpm/utils/dependency_cache.py +3 -1
  238. claude_mpm/utils/gitignore.py +241 -0
  239. claude_mpm/utils/log_cleanup.py +3 -3
  240. claude_mpm/utils/progress.py +383 -0
  241. claude_mpm/utils/robust_installer.py +3 -5
  242. claude_mpm/utils/structured_questions.py +619 -0
  243. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/METADATA +429 -59
  244. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/RECORD +252 -425
  245. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  246. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  247. claude_mpm/agents/templates/agent-manager.json +0 -273
  248. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  249. claude_mpm/agents/templates/api_qa.json +0 -180
  250. claude_mpm/agents/templates/clerk-ops.json +0 -235
  251. claude_mpm/agents/templates/code_analyzer.json +0 -101
  252. claude_mpm/agents/templates/content-agent.json +0 -358
  253. claude_mpm/agents/templates/dart_engineer.json +0 -307
  254. claude_mpm/agents/templates/data_engineer.json +0 -225
  255. claude_mpm/agents/templates/documentation.json +0 -211
  256. claude_mpm/agents/templates/engineer.json +0 -210
  257. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  258. claude_mpm/agents/templates/golang_engineer.json +0 -270
  259. claude_mpm/agents/templates/imagemagick.json +0 -264
  260. claude_mpm/agents/templates/java_engineer.json +0 -346
  261. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  262. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  263. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  264. claude_mpm/agents/templates/memory_manager.json +0 -158
  265. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  266. claude_mpm/agents/templates/ops.json +0 -185
  267. claude_mpm/agents/templates/php-engineer.json +0 -287
  268. claude_mpm/agents/templates/product_owner.json +0 -338
  269. claude_mpm/agents/templates/project_organizer.json +0 -140
  270. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  271. claude_mpm/agents/templates/python_engineer.json +0 -387
  272. claude_mpm/agents/templates/qa.json +0 -242
  273. claude_mpm/agents/templates/react_engineer.json +0 -238
  274. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  275. claude_mpm/agents/templates/research.json +0 -188
  276. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  277. claude_mpm/agents/templates/rust_engineer.json +0 -275
  278. claude_mpm/agents/templates/security.json +0 -202
  279. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  280. claude_mpm/agents/templates/ticketing.json +0 -177
  281. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  282. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  283. claude_mpm/agents/templates/version_control.json +0 -157
  284. claude_mpm/agents/templates/web_qa.json +0 -399
  285. claude_mpm/agents/templates/web_ui.json +0 -189
  286. claude_mpm/commands/mpm-tickets.md +0 -102
  287. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  288. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  289. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  290. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  291. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  292. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  293. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  294. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  295. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  296. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  297. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  298. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  299. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  300. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  301. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  302. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  303. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  304. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  305. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  306. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  307. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  308. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  309. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  310. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  311. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  312. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  313. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  314. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  315. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  316. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  317. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  318. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  319. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  320. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  321. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  322. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  323. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  324. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  325. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  326. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  327. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  328. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  329. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  330. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  331. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  332. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  333. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  334. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  335. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  336. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  337. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  338. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  339. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  340. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  341. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  342. claude_mpm/dashboard/static/built/react/events.js +0 -30
  343. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  344. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  345. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  346. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  347. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  348. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  349. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  350. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  351. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  352. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  353. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  354. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  355. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  356. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  357. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  358. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  359. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  360. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  361. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  362. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  363. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  364. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  365. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  366. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  367. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  368. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  369. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  370. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  371. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  372. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  373. claude_mpm/dashboard/static/events.html +0 -607
  374. claude_mpm/dashboard/static/index.html +0 -635
  375. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  376. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  377. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  378. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  379. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  380. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  381. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  382. claude_mpm/dashboard/static/legacy/files.html +0 -747
  383. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  384. claude_mpm/dashboard/static/monitors.html +0 -431
  385. claude_mpm/dashboard/static/production/events.html +0 -659
  386. claude_mpm/dashboard/static/production/main.html +0 -698
  387. claude_mpm/dashboard/static/production/monitors.html +0 -483
  388. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  389. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  390. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  391. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  392. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  393. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
  394. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
  395. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
  396. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
  397. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
  398. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
  399. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
  400. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
  401. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
  402. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
  403. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
  404. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
  405. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
  406. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
  407. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
  408. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
  409. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
  410. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  411. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  412. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  413. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  414. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  415. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  416. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  417. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  418. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  419. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  420. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
  421. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
  422. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
  423. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
  424. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
  425. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
  426. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
  427. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  428. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  429. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  430. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  431. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
  432. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
  433. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  434. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  435. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  436. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  437. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
  438. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
  439. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
  440. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
  441. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
  442. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
  443. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
  444. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
  445. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
  446. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
  447. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
  448. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
  449. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
  450. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
  451. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
  452. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
  453. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
  454. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
  455. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
  456. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
  457. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
  458. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
  459. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
  460. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  461. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  462. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  463. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  464. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  465. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  466. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
  467. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
  468. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
  469. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
  470. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
  471. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
  472. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
  473. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
  474. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
  475. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
  476. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
  477. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  478. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  479. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  480. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  481. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/WHEEL +0 -0
  482. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/entry_points.txt +0 -0
  483. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/licenses/LICENSE +0 -0
  484. {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,576 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Environment variable validation script.
4
+
5
+ This script validates .env files for:
6
+ - Structure (valid key-value format, no duplicates, proper quoting)
7
+ - Completeness (compare with .env.example)
8
+ - Naming conventions (UPPERCASE_WITH_UNDERSCORES)
9
+ - Framework-specific rules (Next.js, Express, Flask, etc.)
10
+
11
+ Security: NEVER logs actual secret values.
12
+ """
13
+
14
+ import argparse
15
+ import json
16
+ import re
17
+ import sys
18
+ from pathlib import Path
19
+ from typing import Dict, List, Optional
20
+
21
+
22
+ class ValidationError:
23
+ """Represents a validation error."""
24
+
25
+ def __init__(
26
+ self, line: Optional[int], key: str, message: str, severity: str = "error"
27
+ ):
28
+ self.line = line
29
+ self.key = key
30
+ self.message = message
31
+ self.severity = severity # "error" or "warning"
32
+
33
+ def to_dict(self) -> Dict:
34
+ return {
35
+ "line": self.line,
36
+ "key": self.key,
37
+ "message": self.message,
38
+ "severity": self.severity,
39
+ }
40
+
41
+ def __str__(self) -> str:
42
+ prefix = "❌" if self.severity == "error" else "⚠️ "
43
+ line_info = f"Line {self.line}: " if self.line else ""
44
+ return f"{prefix} {line_info}{self.key}: {self.message}"
45
+
46
+
47
+ class EnvValidator:
48
+ """Validates environment variable files."""
49
+
50
+ # Valid variable name pattern: UPPERCASE_WITH_UNDERSCORES
51
+ VALID_NAME_PATTERN = re.compile(r"^[A-Z][A-Z0-9_]*$")
52
+
53
+ # Framework-specific prefixes
54
+ FRAMEWORK_PREFIXES = {
55
+ "nextjs": ["NEXT_PUBLIC_", "NEXT_"],
56
+ "vite": ["VITE_"],
57
+ "react": ["REACT_APP_"],
58
+ }
59
+
60
+ # Secret indicators (variables that should never be in NEXT_PUBLIC_, etc.)
61
+ SECRET_INDICATORS = ["secret", "key", "password", "token", "private", "api_key"]
62
+
63
+ def __init__(self, framework: Optional[str] = None, strict: bool = False):
64
+ self.framework = framework
65
+ self.strict = strict
66
+ self.errors: List[ValidationError] = []
67
+ self.warnings: List[ValidationError] = []
68
+
69
+ def parse_env_file(self, env_file: Path) -> Dict[str, str]:
70
+ """Parse .env file safely. Returns dict of key-value pairs."""
71
+ vars_dict = {}
72
+
73
+ with open(env_file) as f:
74
+ for line_num, line in enumerate(f, 1):
75
+ line = line.strip()
76
+
77
+ # Skip empty lines and comments
78
+ if not line or line.startswith("#"):
79
+ continue
80
+
81
+ # Check for valid format
82
+ if "=" not in line:
83
+ self.errors.append(
84
+ ValidationError(
85
+ line_num,
86
+ "",
87
+ f"Invalid format (missing =): {line[:50]}",
88
+ "error",
89
+ )
90
+ )
91
+ continue
92
+
93
+ # Split on first = only
94
+ key, value = line.split("=", 1)
95
+ key = key.strip()
96
+
97
+ # Remove quotes from value
98
+ value = value.strip()
99
+ if value and value[0] == value[-1] and value[0] in ('"', "'"):
100
+ value = value[1:-1]
101
+
102
+ vars_dict[key] = value
103
+
104
+ return vars_dict
105
+
106
+ def validate_structure(self, env_file: Path) -> List[ValidationError]:
107
+ """Validate basic file structure."""
108
+ errors = []
109
+
110
+ with open(env_file) as f:
111
+ for line_num, line in enumerate(f, 1):
112
+ line = line.strip()
113
+
114
+ # Skip empty lines and comments
115
+ if not line or line.startswith("#"):
116
+ continue
117
+
118
+ # Check for inline comments (warning)
119
+ if "#" in line and not line.startswith("#"):
120
+ key_value = line.split("#", 1)[0]
121
+ if "=" in key_value:
122
+ key, value = key_value.split("=", 1)
123
+ # Check if # is inside quotes
124
+ value = value.strip()
125
+ if not (value.startswith('"') or value.startswith("'")):
126
+ errors.append(
127
+ ValidationError(
128
+ line_num,
129
+ key.strip(),
130
+ "Possible inline comment (not all parsers support this)",
131
+ "warning",
132
+ )
133
+ )
134
+
135
+ # Check format
136
+ if "=" not in line:
137
+ errors.append(
138
+ ValidationError(
139
+ line_num,
140
+ "",
141
+ f"Invalid format (missing =): {line[:50]}",
142
+ "error",
143
+ )
144
+ )
145
+ continue
146
+
147
+ key, value = line.split("=", 1)
148
+ key = key.strip()
149
+
150
+ # Validate key name
151
+ if not self.VALID_NAME_PATTERN.match(key):
152
+ errors.append(
153
+ ValidationError(
154
+ line_num,
155
+ key,
156
+ "Invalid naming (use UPPERCASE_WITH_UNDERSCORES)",
157
+ "error",
158
+ )
159
+ )
160
+
161
+ # Check for spaces without quotes
162
+ value = value.strip()
163
+ if value and " " in value:
164
+ if not (value.startswith('"') or value.startswith("'")):
165
+ errors.append(
166
+ ValidationError(
167
+ line_num,
168
+ key,
169
+ "Value with spaces should be quoted",
170
+ "warning",
171
+ )
172
+ )
173
+
174
+ return errors
175
+
176
+ def check_duplicates(self, env_file: Path) -> Dict[str, List[int]]:
177
+ """Find duplicate keys and their line numbers."""
178
+ keys: Dict[str, List[int]] = {}
179
+
180
+ with open(env_file) as f:
181
+ for line_num, line in enumerate(f, 1):
182
+ line = line.strip()
183
+ if not line or line.startswith("#"):
184
+ continue
185
+
186
+ if "=" in line:
187
+ key = line.split("=", 1)[0].strip()
188
+ if key in keys:
189
+ keys[key].append(line_num)
190
+ else:
191
+ keys[key] = [line_num]
192
+
193
+ # Return only duplicates
194
+ duplicates = {k: v for k, v in keys.items() if len(v) > 1}
195
+
196
+ # Add errors for duplicates
197
+ for key, lines in duplicates.items():
198
+ self.errors.append(
199
+ ValidationError(
200
+ None,
201
+ key,
202
+ f"Duplicate key found on lines: {', '.join(map(str, lines))}",
203
+ "error",
204
+ )
205
+ )
206
+
207
+ return duplicates
208
+
209
+ def compare_env_files(self, env_file: Path, example_file: Path) -> Dict:
210
+ """Compare .env against .env.example."""
211
+ if not example_file.exists():
212
+ self.warnings.append(
213
+ ValidationError(
214
+ None, "", f".env.example not found: {example_file}", "warning"
215
+ )
216
+ )
217
+ return {"missing": set(), "extra": set(), "common": set()}
218
+
219
+ env_vars = set(self.parse_env_file(env_file).keys())
220
+ example_vars = set(self.parse_env_file(example_file).keys())
221
+
222
+ missing = example_vars - env_vars
223
+ extra = env_vars - example_vars
224
+ common = env_vars & example_vars
225
+
226
+ # Add errors for missing required variables
227
+ for var in missing:
228
+ self.errors.append(
229
+ ValidationError(
230
+ None,
231
+ var,
232
+ "Required variable missing (defined in .env.example)",
233
+ "error",
234
+ )
235
+ )
236
+
237
+ # Add warnings for undocumented variables
238
+ for var in extra:
239
+ self.warnings.append(
240
+ ValidationError(
241
+ None, var, "Variable not documented in .env.example", "warning"
242
+ )
243
+ )
244
+
245
+ return {"missing": missing, "extra": extra, "common": common}
246
+
247
+ def validate_framework_specific(self, env_file: Path) -> List[ValidationError]:
248
+ """Validate framework-specific rules."""
249
+ errors = []
250
+ vars_dict = self.parse_env_file(env_file)
251
+
252
+ if self.framework == "nextjs":
253
+ errors.extend(self._validate_nextjs(vars_dict))
254
+ elif self.framework == "vite":
255
+ errors.extend(self._validate_vite(vars_dict))
256
+ elif self.framework == "react":
257
+ errors.extend(self._validate_react(vars_dict))
258
+ elif self.framework == "nodejs":
259
+ errors.extend(self._validate_nodejs(vars_dict))
260
+ elif self.framework == "flask":
261
+ errors.extend(self._validate_flask(vars_dict))
262
+
263
+ return errors
264
+
265
+ def _validate_nextjs(self, vars_dict: Dict[str, str]) -> List[ValidationError]:
266
+ """Validate Next.js environment variables."""
267
+ errors = []
268
+
269
+ for key, value in vars_dict.items():
270
+ # Check for secrets in NEXT_PUBLIC_ vars
271
+ if key.startswith("NEXT_PUBLIC_"):
272
+ if any(
273
+ indicator in key.lower() for indicator in self.SECRET_INDICATORS
274
+ ):
275
+ errors.append(
276
+ ValidationError(
277
+ None,
278
+ key,
279
+ "SECURITY: Secret in NEXT_PUBLIC_ variable (exposed to browser)",
280
+ "error",
281
+ )
282
+ )
283
+
284
+ # Check for API URLs without NEXT_PUBLIC_ prefix
285
+ if "api" in key.lower() and "url" in key.lower():
286
+ if not key.startswith("NEXT_PUBLIC_") and not key.endswith("_SECRET"):
287
+ errors.append(
288
+ ValidationError(
289
+ None,
290
+ key,
291
+ "API URL without NEXT_PUBLIC_ prefix (not accessible client-side)",
292
+ "warning",
293
+ )
294
+ )
295
+
296
+ return errors
297
+
298
+ def _validate_vite(self, vars_dict: Dict[str, str]) -> List[ValidationError]:
299
+ """Validate Vite environment variables."""
300
+ errors = []
301
+
302
+ for key in vars_dict:
303
+ # Check for secrets in VITE_ vars
304
+ if key.startswith("VITE_"):
305
+ if any(
306
+ indicator in key.lower() for indicator in self.SECRET_INDICATORS
307
+ ):
308
+ errors.append(
309
+ ValidationError(
310
+ None,
311
+ key,
312
+ "SECURITY: Secret in VITE_ variable (exposed to browser)",
313
+ "error",
314
+ )
315
+ )
316
+
317
+ # Warn about non-VITE_ vars
318
+ elif key not in ["NODE_ENV", "PORT"]:
319
+ errors.append(
320
+ ValidationError(
321
+ None,
322
+ key,
323
+ "Variable not prefixed with VITE_ (not accessible in client code)",
324
+ "warning",
325
+ )
326
+ )
327
+
328
+ return errors
329
+
330
+ def _validate_react(self, vars_dict: Dict[str, str]) -> List[ValidationError]:
331
+ """Validate Create React App environment variables."""
332
+ errors = []
333
+
334
+ for key in vars_dict:
335
+ # Check for secrets in REACT_APP_ vars
336
+ if key.startswith("REACT_APP_"):
337
+ if any(
338
+ indicator in key.lower() for indicator in self.SECRET_INDICATORS
339
+ ):
340
+ errors.append(
341
+ ValidationError(
342
+ None,
343
+ key,
344
+ "SECURITY: Secret in REACT_APP_ variable (exposed to browser)",
345
+ "error",
346
+ )
347
+ )
348
+
349
+ return errors
350
+
351
+ def _validate_nodejs(self, vars_dict: Dict[str, str]) -> List[ValidationError]:
352
+ """Validate Node.js environment variables."""
353
+ errors = []
354
+
355
+ # Check NODE_ENV value
356
+ if "NODE_ENV" in vars_dict:
357
+ valid_values = ["development", "production", "test"]
358
+ if vars_dict["NODE_ENV"] not in valid_values:
359
+ # SECURITY: Never expose actual variable values in error messages
360
+ # to prevent accidental secret leakage in logs/CI output
361
+ errors.append(
362
+ ValidationError(
363
+ None,
364
+ "NODE_ENV",
365
+ f"Invalid value for NODE_ENV, expected one of {valid_values}",
366
+ "error",
367
+ )
368
+ )
369
+
370
+ # Check PORT is numeric
371
+ if "PORT" in vars_dict:
372
+ try:
373
+ port = int(vars_dict["PORT"])
374
+ if not (1 <= port <= 65535):
375
+ errors.append(
376
+ ValidationError(
377
+ None, "PORT", "PORT must be between 1 and 65535", "error"
378
+ )
379
+ )
380
+ except ValueError:
381
+ errors.append(
382
+ ValidationError(None, "PORT", "PORT must be numeric", "error")
383
+ )
384
+
385
+ return errors
386
+
387
+ def _validate_flask(self, vars_dict: Dict[str, str]) -> List[ValidationError]:
388
+ """Validate Flask environment variables."""
389
+ errors = []
390
+
391
+ # Check required vars
392
+ required = ["FLASK_APP", "SECRET_KEY"]
393
+ for var in required:
394
+ if var not in vars_dict:
395
+ errors.append(
396
+ ValidationError(
397
+ None, var, "Required Flask variable missing", "error"
398
+ )
399
+ )
400
+
401
+ # Check FLASK_APP ends with .py
402
+ if "FLASK_APP" in vars_dict:
403
+ if not vars_dict["FLASK_APP"].endswith(".py"):
404
+ errors.append(
405
+ ValidationError(
406
+ None,
407
+ "FLASK_APP",
408
+ "FLASK_APP should point to a .py file",
409
+ "warning",
410
+ )
411
+ )
412
+
413
+ # Check FLASK_ENV value
414
+ if "FLASK_ENV" in vars_dict:
415
+ valid_values = ["development", "production"]
416
+ if vars_dict["FLASK_ENV"] not in valid_values:
417
+ errors.append(
418
+ ValidationError(
419
+ None,
420
+ "FLASK_ENV",
421
+ f"Invalid value, expected one of {valid_values}",
422
+ "error",
423
+ )
424
+ )
425
+
426
+ return errors
427
+
428
+ def validate(self, env_file: Path, example_file: Optional[Path] = None) -> Dict:
429
+ """Run all validations. Returns summary dict."""
430
+ self.errors = []
431
+ self.warnings = []
432
+
433
+ # 1. Structure validation
434
+ structure_errors = self.validate_structure(env_file)
435
+ self.errors.extend([e for e in structure_errors if e.severity == "error"])
436
+ self.warnings.extend([e for e in structure_errors if e.severity == "warning"])
437
+
438
+ # 2. Check duplicates
439
+ self.check_duplicates(env_file)
440
+
441
+ # 3. Compare with .env.example
442
+ if example_file:
443
+ self.compare_env_files(env_file, example_file)
444
+
445
+ # 4. Framework-specific validation
446
+ if self.framework:
447
+ framework_errors = self.validate_framework_specific(env_file)
448
+ self.errors.extend([e for e in framework_errors if e.severity == "error"])
449
+ self.warnings.extend(
450
+ [e for e in framework_errors if e.severity == "warning"]
451
+ )
452
+
453
+ return {
454
+ "valid": len(self.errors) == 0,
455
+ "errors": self.errors,
456
+ "warnings": self.warnings,
457
+ "error_count": len(self.errors),
458
+ "warning_count": len(self.warnings),
459
+ }
460
+
461
+
462
+ def generate_example(env_file: Path, output_file: Path) -> None:
463
+ """Generate .env.example from .env file (with values removed)."""
464
+ with open(env_file) as f:
465
+ lines = f.readlines()
466
+
467
+ with open(output_file, "w") as f:
468
+ for line in lines:
469
+ line = line.strip()
470
+
471
+ # Keep comments and empty lines
472
+ if not line or line.startswith("#"):
473
+ f.write(line + "\n")
474
+ continue
475
+
476
+ # Replace values with placeholders
477
+ if "=" in line:
478
+ key, _ = line.split("=", 1)
479
+ f.write(f"{key}=your-{key.lower().replace('_', '-')}-here\n")
480
+
481
+ print(f"✅ Generated {output_file}")
482
+
483
+
484
+ def main():
485
+ parser = argparse.ArgumentParser(description="Validate environment variable files")
486
+ parser.add_argument("file", type=Path, help="Path to .env file to validate")
487
+ parser.add_argument(
488
+ "--compare-with",
489
+ type=Path,
490
+ help="Compare with .env.example file",
491
+ metavar="FILE",
492
+ )
493
+ parser.add_argument(
494
+ "--framework",
495
+ choices=["nextjs", "vite", "react", "nodejs", "flask", "generic"],
496
+ help="Framework-specific validation",
497
+ )
498
+ parser.add_argument(
499
+ "--strict", action="store_true", help="Treat warnings as errors"
500
+ )
501
+ parser.add_argument("--json", action="store_true", help="Output results as JSON")
502
+ parser.add_argument(
503
+ "--quiet", action="store_true", help="Only show errors, not warnings"
504
+ )
505
+ parser.add_argument(
506
+ "--generate-example",
507
+ type=Path,
508
+ help="Generate .env.example file",
509
+ metavar="OUTPUT",
510
+ )
511
+
512
+ args = parser.parse_args()
513
+
514
+ # Check input file exists
515
+ if not args.file.exists():
516
+ print(f"❌ Error: File not found: {args.file}")
517
+ sys.exit(2)
518
+
519
+ # Generate example if requested
520
+ if args.generate_example:
521
+ generate_example(args.file, args.generate_example)
522
+ return
523
+
524
+ # Run validation
525
+ validator = EnvValidator(framework=args.framework, strict=args.strict)
526
+ result = validator.validate(args.file, example_file=args.compare_with)
527
+
528
+ # Output results
529
+ if args.json:
530
+ output = {
531
+ "valid": result["valid"],
532
+ "file": str(args.file),
533
+ "errors": [e.to_dict() for e in result["errors"]],
534
+ "warnings": [w.to_dict() for w in result["warnings"]],
535
+ }
536
+ print(json.dumps(output, indent=2))
537
+ else:
538
+ print(f"\n🔍 Validating: {args.file}")
539
+ if args.framework:
540
+ print(f"📦 Framework: {args.framework}")
541
+ print()
542
+
543
+ # Show errors
544
+ if result["errors"]:
545
+ print("❌ Errors:")
546
+ for error in result["errors"]:
547
+ print(f" {error}")
548
+ print()
549
+
550
+ # Show warnings (unless quiet)
551
+ if result["warnings"] and not args.quiet:
552
+ print("⚠️ Warnings:")
553
+ for warning in result["warnings"]:
554
+ print(f" {warning}")
555
+ print()
556
+
557
+ # Summary
558
+ if result["valid"]:
559
+ print("✅ Validation passed!")
560
+ else:
561
+ print(f"❌ Validation failed: {result['error_count']} error(s)")
562
+
563
+ if not args.quiet:
564
+ print(
565
+ f"📊 Summary: {result['error_count']} errors, {result['warning_count']} warnings"
566
+ )
567
+
568
+ # Exit code
569
+ if result["errors"] or (args.strict and result["warnings"]):
570
+ sys.exit(1)
571
+ else:
572
+ sys.exit(0)
573
+
574
+
575
+ if __name__ == "__main__":
576
+ main()
@@ -433,6 +433,12 @@ def sort_items(items):
433
433
 
434
434
  ### Load Testing
435
435
 
436
+ > **Note:** Locust is an optional dependency. Install it separately if you need load testing capabilities:
437
+ > ```bash
438
+ > pip install "claude-mpm[agents-load-testing]"
439
+ > ```
440
+ > Or install locust directly: `pip install locust>=2.15.0`
441
+
436
442
  ```python
437
443
  # Using locust for load testing
438
444
  from locust import HttpUser, task, between
@@ -84,7 +84,7 @@ def main():
84
84
  try:
85
85
  # Start all servers
86
86
  for i, server in enumerate(servers):
87
- print(f"Starting server {i+1}/{len(servers)}: {server['cmd']}")
87
+ print(f"Starting server {i + 1}/{len(servers)}: {server['cmd']}")
88
88
 
89
89
  # Use shell=True to support commands with cd and &&
90
90
  process = subprocess.Popen(
@@ -121,7 +121,7 @@ def main():
121
121
  except subprocess.TimeoutExpired:
122
122
  process.kill()
123
123
  process.wait()
124
- print(f"Server {i+1} stopped")
124
+ print(f"Server {i + 1} stopped")
125
125
  print("All servers stopped")
126
126
 
127
127
 
@@ -342,7 +342,6 @@ class SkillsRegistry(LoggerMixin):
342
342
  query_lower in skill_name.lower()
343
343
  or query_lower in metadata.get("description", "").lower()
344
344
  ):
345
-
346
345
  results.append({"name": skill_name, **metadata})
347
346
 
348
347
  return results
@@ -0,0 +1,38 @@
1
+ """Structured question templates for common PM workflows.
2
+
3
+ This package provides reusable question templates that PM agents can use to gather
4
+ user input in a structured way. Templates are pre-configured QuestionSet objects
5
+ that can be customized based on context.
6
+
7
+ Available Templates:
8
+ - PR Strategy: Questions about PR workflow, draft preferences, auto-merge
9
+ - Project Initialization: Questions about project type, language, frameworks
10
+ - Ticket Management: Questions about ticket prioritization and scope
11
+
12
+ Example Usage:
13
+ >>> from claude_mpm.templates.questions.pr_strategy import PRWorkflowTemplate
14
+ >>> template = PRWorkflowTemplate(num_tickets=3)
15
+ >>> question_set = template.build()
16
+ >>> params = question_set.to_ask_user_question_params()
17
+ """
18
+
19
+ from claude_mpm.templates.questions.base import ConditionalTemplate, QuestionTemplate
20
+ from claude_mpm.templates.questions.pr_strategy import PRWorkflowTemplate
21
+ from claude_mpm.templates.questions.project_init import (
22
+ DevelopmentWorkflowTemplate,
23
+ ProjectTypeTemplate,
24
+ )
25
+ from claude_mpm.templates.questions.ticket_mgmt import (
26
+ TicketPrioritizationTemplate,
27
+ TicketScopeTemplate,
28
+ )
29
+
30
+ __all__ = [
31
+ "ConditionalTemplate",
32
+ "DevelopmentWorkflowTemplate",
33
+ "PRWorkflowTemplate",
34
+ "ProjectTypeTemplate",
35
+ "QuestionTemplate",
36
+ "TicketPrioritizationTemplate",
37
+ "TicketScopeTemplate",
38
+ ]