claude-mpm 4.20.3__py3-none-any.whl → 4.25.10__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 (454) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +23 -6
  3. claude_mpm/agents/OUTPUT_STYLE.md +3 -48
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +1783 -34
  5. claude_mpm/agents/WORKFLOW.md +75 -2
  6. claude_mpm/agents/base_agent.json +6 -3
  7. claude_mpm/agents/frontmatter_validator.py +1 -1
  8. claude_mpm/agents/templates/api_qa.json +5 -2
  9. claude_mpm/agents/templates/circuit_breakers.md +108 -2
  10. claude_mpm/agents/templates/documentation.json +33 -6
  11. claude_mpm/agents/templates/javascript_engineer_agent.json +380 -0
  12. claude_mpm/agents/templates/php-engineer.json +10 -4
  13. claude_mpm/agents/templates/pm_red_flags.md +89 -19
  14. claude_mpm/agents/templates/project_organizer.json +7 -3
  15. claude_mpm/agents/templates/qa.json +2 -1
  16. claude_mpm/agents/templates/react_engineer.json +1 -0
  17. claude_mpm/agents/templates/research.json +82 -12
  18. claude_mpm/agents/templates/security.json +4 -4
  19. claude_mpm/agents/templates/tauri_engineer.json +274 -0
  20. claude_mpm/agents/templates/ticketing.json +10 -6
  21. claude_mpm/agents/templates/version_control.json +4 -2
  22. claude_mpm/agents/templates/web_qa.json +2 -1
  23. claude_mpm/cli/README.md +253 -0
  24. claude_mpm/cli/__init__.py +11 -1
  25. claude_mpm/cli/commands/aggregate.py +1 -1
  26. claude_mpm/cli/commands/analyze.py +3 -3
  27. claude_mpm/cli/commands/cleanup.py +1 -1
  28. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  29. claude_mpm/cli/commands/debug.py +12 -12
  30. claude_mpm/cli/commands/hook_errors.py +277 -0
  31. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  32. claude_mpm/cli/commands/mcp_install_commands.py.backup +284 -0
  33. claude_mpm/cli/commands/mpm_init/README.md +365 -0
  34. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  35. claude_mpm/cli/commands/mpm_init/core.py +573 -0
  36. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  37. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  38. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  39. claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
  40. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  41. claude_mpm/cli/commands/mpm_init_handler.py +67 -1
  42. claude_mpm/cli/commands/run.py +124 -128
  43. claude_mpm/cli/commands/skills.py +522 -34
  44. claude_mpm/cli/executor.py +56 -0
  45. claude_mpm/cli/interactive/agent_wizard.py +5 -5
  46. claude_mpm/cli/parsers/base_parser.py +28 -0
  47. claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
  48. claude_mpm/cli/parsers/skills_parser.py +138 -0
  49. claude_mpm/cli/startup.py +111 -8
  50. claude_mpm/cli/startup_display.py +480 -0
  51. claude_mpm/cli/utils.py +1 -1
  52. claude_mpm/cli_module/commands.py +1 -1
  53. claude_mpm/cli_module/refactoring_guide.md +253 -0
  54. claude_mpm/commands/mpm-help.md +3 -0
  55. claude_mpm/commands/mpm-init.md +19 -3
  56. claude_mpm/commands/mpm-resume.md +372 -0
  57. claude_mpm/commands/mpm-tickets.md +56 -7
  58. claude_mpm/commands/mpm.md +1 -0
  59. claude_mpm/config/agent_capabilities.yaml +658 -0
  60. claude_mpm/config/async_logging_config.yaml +145 -0
  61. claude_mpm/constants.py +12 -0
  62. claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +34 -0
  63. claude_mpm/core/api_validator.py +1 -1
  64. claude_mpm/core/claude_runner.py +14 -1
  65. claude_mpm/core/config.py +8 -0
  66. claude_mpm/core/constants.py +1 -1
  67. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  68. claude_mpm/core/hook_error_memory.py +381 -0
  69. claude_mpm/core/hook_manager.py +41 -2
  70. claude_mpm/core/interactive_session.py +48 -3
  71. claude_mpm/core/interfaces.py +56 -1
  72. claude_mpm/core/logger.py +3 -1
  73. claude_mpm/core/oneshot_session.py +39 -0
  74. claude_mpm/d2/.gitignore +22 -0
  75. claude_mpm/d2/ARCHITECTURE_COMPARISON.md +273 -0
  76. claude_mpm/d2/FLASK_INTEGRATION.md +156 -0
  77. claude_mpm/d2/IMPLEMENTATION_SUMMARY.md +452 -0
  78. claude_mpm/d2/QUICKSTART.md +186 -0
  79. claude_mpm/d2/README.md +232 -0
  80. claude_mpm/d2/STORE_FIX_SUMMARY.md +167 -0
  81. claude_mpm/d2/SVELTE5_STORES_GUIDE.md +180 -0
  82. claude_mpm/d2/TESTING.md +288 -0
  83. claude_mpm/d2/index.html +118 -0
  84. claude_mpm/d2/package.json +19 -0
  85. claude_mpm/d2/src/App.svelte +110 -0
  86. claude_mpm/d2/src/components/Header.svelte +153 -0
  87. claude_mpm/d2/src/components/MainContent.svelte +74 -0
  88. claude_mpm/d2/src/components/Sidebar.svelte +85 -0
  89. claude_mpm/d2/src/components/tabs/EventsTab.svelte +326 -0
  90. claude_mpm/d2/src/lib/socketio.js +144 -0
  91. claude_mpm/d2/src/main.js +7 -0
  92. claude_mpm/d2/src/stores/events.js +114 -0
  93. claude_mpm/d2/src/stores/socket.js +108 -0
  94. claude_mpm/d2/src/stores/theme.js +65 -0
  95. claude_mpm/d2/svelte.config.js +12 -0
  96. claude_mpm/d2/vite.config.js +15 -0
  97. claude_mpm/dashboard/.claude-mpm/memories/README.md +36 -0
  98. claude_mpm/dashboard/BUILD_NUMBER +1 -0
  99. claude_mpm/dashboard/README.md +121 -0
  100. claude_mpm/dashboard/VERSION +1 -0
  101. claude_mpm/dashboard/react/components/DataInspector/DataInspector.tsx +273 -0
  102. claude_mpm/dashboard/react/components/ErrorBoundary.tsx +75 -0
  103. claude_mpm/dashboard/react/components/EventViewer/EventViewer.tsx +141 -0
  104. claude_mpm/dashboard/react/components/shared/ConnectionStatus.tsx +36 -0
  105. claude_mpm/dashboard/react/components/shared/FilterBar.tsx +89 -0
  106. claude_mpm/dashboard/react/contexts/DashboardContext.tsx +215 -0
  107. claude_mpm/dashboard/react/entries/events.tsx +165 -0
  108. claude_mpm/dashboard/react/hooks/useEvents.ts +191 -0
  109. claude_mpm/dashboard/react/hooks/useSocket.ts +225 -0
  110. claude_mpm/dashboard/static/built/REFACTORING_SUMMARY.md +170 -0
  111. claude_mpm/dashboard/static/built/components/activity-tree.js.map +1 -0
  112. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +101 -101
  113. claude_mpm/dashboard/static/built/components/agent-inference.js.map +1 -0
  114. claude_mpm/dashboard/static/built/components/build-tracker.js +59 -59
  115. claude_mpm/dashboard/static/built/components/code-simple.js +107 -107
  116. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +29 -29
  117. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +24 -24
  118. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +27 -27
  119. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +25 -25
  120. claude_mpm/dashboard/static/built/components/code-tree.js.map +1 -0
  121. claude_mpm/dashboard/static/built/components/code-viewer.js.map +1 -0
  122. claude_mpm/dashboard/static/built/components/connection-debug.js +101 -101
  123. claude_mpm/dashboard/static/built/components/diff-viewer.js +113 -113
  124. claude_mpm/dashboard/static/built/components/event-processor.js.map +1 -0
  125. claude_mpm/dashboard/static/built/components/event-viewer.js.map +1 -0
  126. claude_mpm/dashboard/static/built/components/export-manager.js.map +1 -0
  127. claude_mpm/dashboard/static/built/components/file-change-tracker.js +57 -57
  128. claude_mpm/dashboard/static/built/components/file-change-viewer.js +74 -74
  129. claude_mpm/dashboard/static/built/components/file-tool-tracker.js.map +1 -0
  130. claude_mpm/dashboard/static/built/components/file-viewer.js.map +1 -0
  131. claude_mpm/dashboard/static/built/components/hud-library-loader.js.map +1 -0
  132. claude_mpm/dashboard/static/built/components/hud-manager.js.map +1 -0
  133. claude_mpm/dashboard/static/built/components/hud-visualizer.js.map +1 -0
  134. claude_mpm/dashboard/static/built/components/module-viewer.js.map +1 -0
  135. claude_mpm/dashboard/static/built/components/session-manager.js.map +1 -0
  136. claude_mpm/dashboard/static/built/components/socket-manager.js.map +1 -0
  137. claude_mpm/dashboard/static/built/components/ui-state-manager.js.map +1 -0
  138. claude_mpm/dashboard/static/built/components/unified-data-viewer.js.map +1 -0
  139. claude_mpm/dashboard/static/built/components/working-directory.js.map +1 -0
  140. claude_mpm/dashboard/static/built/connection-manager.js +76 -76
  141. claude_mpm/dashboard/static/built/dashboard.js.map +1 -0
  142. claude_mpm/dashboard/static/built/extension-error-handler.js +22 -22
  143. claude_mpm/dashboard/static/built/react/events.js.map +1 -0
  144. claude_mpm/dashboard/static/built/shared/dom-helpers.js +9 -9
  145. claude_mpm/dashboard/static/built/shared/event-bus.js +5 -5
  146. claude_mpm/dashboard/static/built/shared/logger.js +16 -16
  147. claude_mpm/dashboard/static/built/shared/tooltip-service.js +6 -6
  148. claude_mpm/dashboard/static/built/socket-client.js.map +1 -0
  149. claude_mpm/dashboard/static/css/activity.css +69 -69
  150. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  151. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  152. claude_mpm/dashboard/static/index.html +22 -22
  153. claude_mpm/dashboard/static/js/REFACTORING_SUMMARY.md +170 -0
  154. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  155. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  156. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  157. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  158. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  159. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  160. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  161. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  162. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  163. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  164. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  165. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  166. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  167. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  168. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  169. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  170. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  171. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  172. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  173. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  174. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  175. claude_mpm/dashboard/static/js/shared/dom-helpers.js +9 -9
  176. claude_mpm/dashboard/static/js/shared/event-bus.js +5 -5
  177. claude_mpm/dashboard/static/js/shared/logger.js +16 -16
  178. claude_mpm/dashboard/static/js/shared/tooltip-service.js +6 -6
  179. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  180. claude_mpm/dashboard/static/navigation-test-results.md +118 -0
  181. claude_mpm/dashboard/static/production/main.html +21 -21
  182. claude_mpm/dashboard/static/test-archive/dashboard.html +22 -22
  183. claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +36 -0
  184. claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +39 -0
  185. claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +38 -0
  186. claude_mpm/dashboard/templates/code_simple.html +23 -23
  187. claude_mpm/dashboard/templates/index.html +18 -18
  188. claude_mpm/hooks/README.md +143 -0
  189. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  190. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  191. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  192. claude_mpm/hooks/templates/README.md +180 -0
  193. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  194. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  195. claude_mpm/hooks/templates/settings.json.example +147 -0
  196. claude_mpm/schemas/agent_schema.json +596 -0
  197. claude_mpm/schemas/frontmatter_schema.json +165 -0
  198. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  199. claude_mpm/scripts/start_activity_logging.py +3 -1
  200. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  201. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  202. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  203. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  204. claude_mpm/services/agents/loading/framework_agent_loader.py +8 -8
  205. claude_mpm/services/agents/local_template_manager.py +3 -1
  206. claude_mpm/services/cli/session_pause_manager.py +504 -0
  207. claude_mpm/services/cli/session_resume_helper.py +36 -16
  208. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  209. claude_mpm/services/core/base.py +26 -11
  210. claude_mpm/services/core/interfaces.py +56 -1
  211. claude_mpm/services/core/models/agent_config.py +3 -0
  212. claude_mpm/services/core/models/process.py +4 -0
  213. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  214. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  215. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  216. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  217. claude_mpm/services/diagnostics/doctor_reporter.py +6 -4
  218. claude_mpm/services/diagnostics/models.py +21 -0
  219. claude_mpm/services/event_bus/README.md +244 -0
  220. claude_mpm/services/event_bus/direct_relay.py +3 -3
  221. claude_mpm/services/event_bus/event_bus.py +36 -3
  222. claude_mpm/services/event_bus/relay.py +23 -7
  223. claude_mpm/services/events/README.md +303 -0
  224. claude_mpm/services/events/consumers/logging.py +1 -2
  225. claude_mpm/services/framework_claude_md_generator/README.md +119 -0
  226. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  227. claude_mpm/services/local_ops/__init__.py +2 -0
  228. claude_mpm/services/local_ops/process_manager.py +1 -1
  229. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  230. claude_mpm/services/mcp_gateway/README.md +185 -0
  231. claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
  232. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  233. claude_mpm/services/mcp_gateway/core/process_pool.py +19 -10
  234. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  235. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  236. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +26 -21
  237. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  238. claude_mpm/services/memory/failure_tracker.py +19 -4
  239. claude_mpm/services/memory/optimizer.py +1 -1
  240. claude_mpm/services/model/model_router.py +8 -9
  241. claude_mpm/services/monitor/daemon.py +1 -1
  242. claude_mpm/services/monitor/server.py +2 -2
  243. claude_mpm/services/native_agent_converter.py +356 -0
  244. claude_mpm/services/port_manager.py +1 -1
  245. claude_mpm/services/project/documentation_manager.py +2 -1
  246. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  247. claude_mpm/services/runner_configuration_service.py +1 -0
  248. claude_mpm/services/self_upgrade_service.py +165 -7
  249. claude_mpm/services/skills_config.py +547 -0
  250. claude_mpm/services/skills_deployer.py +955 -0
  251. claude_mpm/services/socketio/handlers/connection.py +1 -1
  252. claude_mpm/services/socketio/handlers/connection.py.backup +217 -0
  253. claude_mpm/services/socketio/handlers/git.py +2 -2
  254. claude_mpm/services/socketio/handlers/hook.py.backup +154 -0
  255. claude_mpm/services/static/.gitkeep +2 -0
  256. claude_mpm/services/system_instructions_service.py +1 -3
  257. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  258. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  259. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  260. claude_mpm/services/version_control/VERSION +1 -0
  261. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  262. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  263. claude_mpm/skills/__init__.py +3 -3
  264. claude_mpm/skills/agent_skills_injector.py +42 -49
  265. claude_mpm/skills/bundled/.gitkeep +2 -0
  266. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +4 -0
  267. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +108 -114
  268. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  269. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  270. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  271. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  272. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  273. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +46 -41
  274. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  275. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  276. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +36 -73
  277. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  278. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  279. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +100 -125
  280. claude_mpm/skills/bundled/debugging/root-cause-tracing/find-polluter.sh +63 -0
  281. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  282. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  283. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  284. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  285. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +28 -72
  286. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +11 -0
  287. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  288. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  289. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +272 -0
  290. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  291. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  292. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  293. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  294. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  295. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  296. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  297. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  298. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  299. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  300. claude_mpm/skills/bundled/main/artifacts-builder/LICENSE.txt +202 -0
  301. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +13 -1
  302. claude_mpm/skills/bundled/main/artifacts-builder/scripts/bundle-artifact.sh +54 -0
  303. claude_mpm/skills/bundled/main/artifacts-builder/scripts/init-artifact.sh +322 -0
  304. claude_mpm/skills/bundled/main/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  305. claude_mpm/skills/bundled/main/internal-comms/LICENSE.txt +202 -0
  306. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +11 -0
  307. claude_mpm/skills/bundled/main/mcp-builder/LICENSE.txt +202 -0
  308. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +109 -277
  309. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  310. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  311. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +17 -10
  312. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +92 -39
  313. claude_mpm/skills/bundled/main/mcp-builder/scripts/example_evaluation.xml +22 -0
  314. claude_mpm/skills/bundled/main/mcp-builder/scripts/requirements.txt +2 -0
  315. claude_mpm/skills/bundled/main/skill-creator/LICENSE.txt +202 -0
  316. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +135 -155
  317. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  318. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  319. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  320. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  321. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  322. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +13 -12
  323. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +5 -3
  324. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +19 -12
  325. claude_mpm/skills/bundled/performance-profiling.md +6 -0
  326. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  327. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  328. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  329. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  330. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  331. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  332. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  333. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  334. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  335. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  336. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  337. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  338. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  339. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  340. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  341. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  342. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  343. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  344. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  345. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  346. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  347. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  348. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  349. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  350. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  351. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  352. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +21 -25
  353. claude_mpm/skills/bundled/testing/condition-based-waiting/example.ts +158 -0
  354. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  355. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  356. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  357. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  358. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  359. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  360. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +86 -250
  361. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  362. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  363. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  364. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  365. claude_mpm/skills/bundled/testing/webapp-testing/LICENSE.txt +202 -0
  366. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +145 -57
  367. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  368. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +6 -6
  369. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +13 -9
  370. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +8 -8
  371. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  372. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  373. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +37 -15
  374. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  375. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  376. claude_mpm/skills/skills_registry.py +44 -48
  377. claude_mpm/skills/skills_service.py +117 -108
  378. claude_mpm/templates/questions/EXAMPLES.md +501 -0
  379. claude_mpm/templates/questions/__init__.py +43 -0
  380. claude_mpm/templates/questions/base.py +193 -0
  381. claude_mpm/templates/questions/pr_strategy.py +314 -0
  382. claude_mpm/templates/questions/project_init.py +388 -0
  383. claude_mpm/templates/questions/ticket_mgmt.py +397 -0
  384. claude_mpm/tools/README_SOCKETIO_DEBUG.md +224 -0
  385. claude_mpm/tools/__main__.py +8 -8
  386. claude_mpm/tools/code_tree_analyzer/README.md +64 -0
  387. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  388. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  389. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  390. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  391. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  392. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  393. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  394. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  395. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  396. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  397. claude_mpm/utils/agent_dependency_loader.py +3 -3
  398. claude_mpm/utils/dependency_cache.py +3 -1
  399. claude_mpm/utils/gitignore.py +241 -0
  400. claude_mpm/utils/log_cleanup.py +3 -3
  401. claude_mpm/utils/robust_installer.py +3 -5
  402. claude_mpm/utils/structured_questions.py +619 -0
  403. {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/METADATA +218 -31
  404. {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/RECORD +409 -246
  405. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  406. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  407. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  408. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  409. claude_mpm/cli/commands/mpm_init.py +0 -2093
  410. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  411. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  412. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  413. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  414. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  415. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  416. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  417. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  418. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  419. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  420. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  421. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  422. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  423. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  424. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  425. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  426. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  427. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  428. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  429. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  430. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  431. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  432. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  433. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  434. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  435. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  436. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  437. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  438. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  439. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  440. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  441. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  442. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  443. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  444. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  445. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  446. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  447. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  448. claude_mpm/skills/bundled/debugging/verification-before-completion/references/common-failures.md +0 -213
  449. claude_mpm/tools/code_tree_analyzer.py +0 -1825
  450. /claude_mpm/skills/bundled/collaboration/requesting-code-review/{code-reviewer.md → references/code-reviewer-template.md} +0 -0
  451. {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/WHEEL +0 -0
  452. {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/entry_points.txt +0 -0
  453. {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/licenses/LICENSE +0 -0
  454. {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,284 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Python Analyzer
4
+ ===============
5
+
6
+ Analyzes Python source code using AST.
7
+
8
+ WHY: Python's built-in AST module provides rich structural information
9
+ that we can leverage for detailed analysis.
10
+ """
11
+
12
+ import ast
13
+ from pathlib import Path
14
+ from typing import List, Optional
15
+
16
+ from ...core.logging_config import get_logger
17
+ from ..code_tree_events import CodeNodeEvent, CodeTreeEventEmitter
18
+ from .models import CodeNode
19
+
20
+
21
+ class PythonAnalyzer:
22
+ """Analyzes Python source code using AST."""
23
+
24
+ def __init__(self, emitter: Optional[CodeTreeEventEmitter] = None):
25
+ self.logger = get_logger(__name__)
26
+ self.emitter = emitter
27
+
28
+ def analyze_file(self, file_path: Path) -> List[CodeNode]:
29
+ """Analyze a Python file and extract code structure.
30
+
31
+ Args:
32
+ file_path: Path to Python file
33
+
34
+ Returns:
35
+ List of code nodes found in the file
36
+ """
37
+ nodes = []
38
+
39
+ try:
40
+ with Path(file_path).open(
41
+ encoding="utf-8",
42
+ ) as f:
43
+ source = f.read()
44
+
45
+ tree = ast.parse(source, filename=str(file_path))
46
+ nodes = self._extract_nodes(tree, file_path, source)
47
+
48
+ except SyntaxError as e:
49
+ self.logger.warning(f"Syntax error in {file_path}: {e}")
50
+ if self.emitter:
51
+ self.emitter.emit_error(str(file_path), f"Syntax error: {e}")
52
+ except Exception as e:
53
+ self.logger.error(f"Error analyzing {file_path}: {e}")
54
+ if self.emitter:
55
+ self.emitter.emit_error(str(file_path), str(e))
56
+
57
+ return nodes
58
+
59
+ def _extract_nodes(
60
+ self, tree: ast.AST, file_path: Path, source: str
61
+ ) -> List[CodeNode]:
62
+ """Extract code nodes from AST tree.
63
+
64
+ Args:
65
+ tree: AST tree
66
+ file_path: Source file path
67
+ source: Source code text
68
+
69
+ Returns:
70
+ List of extracted code nodes
71
+ """
72
+ nodes = []
73
+ source.splitlines()
74
+
75
+ class NodeVisitor(ast.NodeVisitor):
76
+ def __init__(self, parent_name: Optional[str] = None):
77
+ self.parent_name = parent_name
78
+ self.current_class = None
79
+
80
+ def visit_ClassDef(self, node):
81
+ # Extract class information
82
+ class_node = CodeNode(
83
+ file_path=str(file_path),
84
+ node_type="class",
85
+ name=node.name,
86
+ line_start=node.lineno,
87
+ line_end=node.end_lineno or node.lineno,
88
+ has_docstring=bool(ast.get_docstring(node)),
89
+ decorators=[self._decorator_name(d) for d in node.decorator_list],
90
+ parent=self.parent_name,
91
+ complexity=self._calculate_complexity(node),
92
+ signature=self._get_class_signature(node),
93
+ )
94
+
95
+ nodes.append(class_node)
96
+
97
+ # Emit event if emitter is available
98
+ if self.emitter:
99
+ self.emitter.emit_node(
100
+ CodeNodeEvent(
101
+ file_path=str(file_path),
102
+ node_type="class",
103
+ name=node.name,
104
+ line_start=node.lineno,
105
+ line_end=node.end_lineno or node.lineno,
106
+ complexity=class_node.complexity,
107
+ has_docstring=class_node.has_docstring,
108
+ decorators=class_node.decorators,
109
+ parent=self.parent_name,
110
+ children_count=len(node.body),
111
+ )
112
+ )
113
+
114
+ # Visit class members
115
+ old_class = self.current_class
116
+ self.current_class = node.name
117
+ for child in node.body:
118
+ if isinstance(child, (ast.FunctionDef, ast.AsyncFunctionDef)):
119
+ self.visit_FunctionDef(child, is_method=True)
120
+ self.current_class = old_class
121
+
122
+ def visit_FunctionDef(self, node, is_method=False):
123
+ # Determine node type
124
+ node_type = "method" if is_method else "function"
125
+ parent = self.current_class if is_method else self.parent_name
126
+
127
+ # Extract function information
128
+ func_node = CodeNode(
129
+ file_path=str(file_path),
130
+ node_type=node_type,
131
+ name=node.name,
132
+ line_start=node.lineno,
133
+ line_end=node.end_lineno or node.lineno,
134
+ has_docstring=bool(ast.get_docstring(node)),
135
+ decorators=[self._decorator_name(d) for d in node.decorator_list],
136
+ parent=parent,
137
+ complexity=self._calculate_complexity(node),
138
+ signature=self._get_function_signature(node),
139
+ )
140
+
141
+ nodes.append(func_node)
142
+
143
+ # Emit event if emitter is available
144
+ if self.emitter:
145
+ self.emitter.emit_node(
146
+ CodeNodeEvent(
147
+ file_path=str(file_path),
148
+ node_type=node_type,
149
+ name=node.name,
150
+ line_start=node.lineno,
151
+ line_end=node.end_lineno or node.lineno,
152
+ complexity=func_node.complexity,
153
+ has_docstring=func_node.has_docstring,
154
+ decorators=func_node.decorators,
155
+ parent=parent,
156
+ children_count=0,
157
+ )
158
+ )
159
+
160
+ def visit_Assign(self, node):
161
+ # Handle module-level variable assignments
162
+ if self.current_class is None: # Only module-level assignments
163
+ for target in node.targets:
164
+ if isinstance(target, ast.Name):
165
+ var_node = CodeNode(
166
+ file_path=str(file_path),
167
+ node_type="variable",
168
+ name=target.id,
169
+ line_start=node.lineno,
170
+ line_end=node.end_lineno or node.lineno,
171
+ parent=self.parent_name,
172
+ complexity=0,
173
+ signature=f"{target.id} = ...",
174
+ )
175
+ nodes.append(var_node)
176
+
177
+ # Emit event if emitter is available
178
+ if self.emitter:
179
+ self.emitter.emit_node(
180
+ CodeNodeEvent(
181
+ file_path=str(file_path),
182
+ node_type="variable",
183
+ name=target.id,
184
+ line_start=node.lineno,
185
+ line_end=node.end_lineno or node.lineno,
186
+ parent=self.parent_name,
187
+ )
188
+ )
189
+
190
+ def visit_AsyncFunctionDef(self, node):
191
+ self.visit_FunctionDef(node)
192
+
193
+ def _decorator_name(self, decorator):
194
+ """Extract decorator name from AST node."""
195
+ if isinstance(decorator, ast.Name):
196
+ return decorator.id
197
+ if isinstance(decorator, ast.Call):
198
+ if isinstance(decorator.func, ast.Name):
199
+ return decorator.func.id
200
+ if isinstance(decorator.func, ast.Attribute):
201
+ return decorator.func.attr
202
+ return "unknown"
203
+
204
+ def _calculate_complexity(self, node):
205
+ """Calculate cyclomatic complexity of a node."""
206
+ complexity = 1 # Base complexity
207
+
208
+ for child in ast.walk(node):
209
+ if isinstance(
210
+ child, (ast.If, ast.While, ast.For, ast.ExceptHandler)
211
+ ):
212
+ complexity += 1
213
+ elif isinstance(child, ast.BoolOp):
214
+ complexity += len(child.values) - 1
215
+
216
+ return complexity
217
+
218
+ def _get_function_signature(self, node):
219
+ """Extract function signature."""
220
+ args = []
221
+ for arg in node.args.args:
222
+ args.append(arg.arg)
223
+ return f"{node.name}({', '.join(args)})"
224
+
225
+ def _get_class_signature(self, node):
226
+ """Extract class signature."""
227
+ bases = []
228
+ for base in node.bases:
229
+ if isinstance(base, ast.Name):
230
+ bases.append(base.id)
231
+ base_str = f"({', '.join(bases)})" if bases else ""
232
+ return f"class {node.name}{base_str}"
233
+
234
+ # Extract imports
235
+ for node in ast.walk(tree):
236
+ if isinstance(node, ast.Import):
237
+ for alias in node.names:
238
+ import_node = CodeNode(
239
+ file_path=str(file_path),
240
+ node_type="import",
241
+ name=alias.name,
242
+ line_start=node.lineno,
243
+ line_end=node.end_lineno or node.lineno,
244
+ signature=f"import {alias.name}",
245
+ )
246
+ nodes.append(import_node)
247
+
248
+ elif isinstance(node, ast.ImportFrom):
249
+ module = node.module or ""
250
+ for alias in node.names:
251
+ import_node = CodeNode(
252
+ file_path=str(file_path),
253
+ node_type="import",
254
+ name=f"{module}.{alias.name}",
255
+ line_start=node.lineno,
256
+ line_end=node.end_lineno or node.lineno,
257
+ signature=f"from {module} import {alias.name}",
258
+ )
259
+ nodes.append(import_node)
260
+
261
+ # Visit all nodes
262
+ visitor = NodeVisitor()
263
+ visitor.emitter = self.emitter
264
+ visitor.visit(tree)
265
+
266
+ return nodes
267
+
268
+ def _get_assignment_signature(self, node: ast.Assign, var_name: str) -> str:
269
+ """Get assignment signature string."""
270
+ try:
271
+ # Try to get a simple representation of the value
272
+ if isinstance(node.value, ast.Constant):
273
+ if isinstance(node.value.value, str):
274
+ return f'{var_name} = "{node.value.value}"'
275
+ return f"{var_name} = {node.value.value}"
276
+ if isinstance(node.value, ast.Name):
277
+ return f"{var_name} = {node.value.id}"
278
+ if isinstance(node.value, ast.List):
279
+ return f"{var_name} = [...]"
280
+ if isinstance(node.value, ast.Dict):
281
+ return f"{var_name} = {{...}}"
282
+ return f"{var_name} = ..."
283
+ except Exception:
284
+ return f"{var_name} = ..."
@@ -678,7 +678,7 @@ class AgentDependencyLoader:
678
678
  logger.info(
679
679
  f"Auto-installing {len(results['summary']['missing_python'])} missing dependencies..."
680
680
  )
681
- success, error = self.install_missing_dependencies(
681
+ success, _error = self.install_missing_dependencies(
682
682
  results["summary"]["missing_python"]
683
683
  )
684
684
  if success:
@@ -777,7 +777,7 @@ class AgentDependencyLoader:
777
777
  import sys
778
778
 
779
779
  if sys.version_info >= (3, 13):
780
- compatible, incompatible = self.check_python_compatibility(
780
+ _compatible, incompatible = self.check_python_compatibility(
781
781
  summary["missing_python"]
782
782
  )
783
783
  if incompatible:
@@ -949,7 +949,7 @@ class AgentDependencyLoader:
949
949
  Returns:
950
950
  Cached results or None if not available/valid.
951
951
  """
952
- has_changed, current_hash = self.has_agents_changed()
952
+ has_changed, _current_hash = self.has_agents_changed()
953
953
 
954
954
  if not has_changed:
955
955
  state = self.load_deployment_state()
@@ -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,241 @@
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
+ ]
216
+
217
+ added, existing = manager.ensure_entries(entries_to_add)
218
+
219
+ return {
220
+ "status": "success",
221
+ "added": added,
222
+ "existing": existing,
223
+ "gitignore_path": str(manager.gitignore_path),
224
+ }
225
+
226
+ except PermissionError as e:
227
+ logger.error(f"Permission denied updating .gitignore: {e}")
228
+ return {
229
+ "status": "error",
230
+ "error": f"Permission denied: {e}",
231
+ "added": [],
232
+ "existing": [],
233
+ }
234
+ except FileNotFoundError as e:
235
+ logger.error(f"Project directory not found: {e}")
236
+ return {
237
+ "status": "error",
238
+ "error": f"Directory not found: {e}",
239
+ "added": [],
240
+ "existing": [],
241
+ }
@@ -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:
@@ -218,8 +218,7 @@ class RobustPackageInstaller:
218
218
  return (
219
219
  (
220
220
  # venv creates sys.base_prefix
221
- hasattr(sys, "base_prefix")
222
- and sys.base_prefix != sys.prefix
221
+ hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix
223
222
  )
224
223
  or (
225
224
  # virtualenv creates sys.real_prefix
@@ -227,8 +226,7 @@ class RobustPackageInstaller:
227
226
  )
228
227
  or (
229
228
  # VIRTUAL_ENV environment variable
230
- os.environ.get("VIRTUAL_ENV")
231
- is not None
229
+ os.environ.get("VIRTUAL_ENV") is not None
232
230
  )
233
231
  )
234
232
 
@@ -768,7 +766,7 @@ def install_with_retry(
768
766
  logging.getLogger().setLevel(logging.DEBUG)
769
767
 
770
768
  installer = RobustPackageInstaller(max_retries=max_retries)
771
- successful, failed, errors = installer.install_packages(packages)
769
+ _successful, failed, errors = installer.install_packages(packages)
772
770
 
773
771
  if verbose:
774
772
  print(installer.get_report())