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,403 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Discovery Module
4
+ ================
5
+
6
+ Handles directory traversal and file discovery for code analysis.
7
+
8
+ WHY: Separates file system operations from analysis logic,
9
+ providing efficient directory scanning with proper filtering.
10
+ """
11
+
12
+ from datetime import datetime, timezone
13
+ from pathlib import Path
14
+ from typing import ClassVar, Dict, List, Optional, Set
15
+
16
+ from ...core.logging_config import get_logger
17
+ from ..code_tree_events import CodeTreeEventEmitter
18
+ from .gitignore import GitignoreManager
19
+
20
+
21
+ class DiscoveryManager:
22
+ """Manages file and directory discovery for code analysis."""
23
+
24
+ # Define code file extensions at class level for directory filtering
25
+ CODE_EXTENSIONS: ClassVar[Set[str]] = {
26
+ ".py",
27
+ ".js",
28
+ ".jsx",
29
+ ".ts",
30
+ ".tsx",
31
+ ".mjs",
32
+ ".cjs",
33
+ ".java",
34
+ ".cpp",
35
+ ".c",
36
+ ".h",
37
+ ".hpp",
38
+ ".cs",
39
+ ".go",
40
+ ".rs",
41
+ ".rb",
42
+ ".php",
43
+ ".swift",
44
+ ".kt",
45
+ ".scala",
46
+ ".r",
47
+ ".m",
48
+ ".mm",
49
+ ".sh",
50
+ ".bash",
51
+ ".zsh",
52
+ ".fish",
53
+ ".ps1",
54
+ ".bat",
55
+ ".cmd",
56
+ ".sql",
57
+ ".html",
58
+ ".css",
59
+ ".scss",
60
+ ".sass",
61
+ ".less",
62
+ ".xml",
63
+ ".json",
64
+ ".yaml",
65
+ ".yml",
66
+ ".toml",
67
+ ".ini",
68
+ ".cfg",
69
+ ".conf",
70
+ ".md",
71
+ ".rst",
72
+ ".txt",
73
+ }
74
+
75
+ # File extensions to language mapping
76
+ LANGUAGE_MAP: ClassVar[Dict[str, str]] = {
77
+ ".py": "python",
78
+ ".js": "javascript",
79
+ ".jsx": "javascript",
80
+ ".ts": "typescript",
81
+ ".tsx": "typescript",
82
+ ".mjs": "javascript",
83
+ ".cjs": "javascript",
84
+ }
85
+
86
+ def __init__(
87
+ self,
88
+ gitignore_manager: GitignoreManager,
89
+ emitter: Optional[CodeTreeEventEmitter] = None,
90
+ ):
91
+ """Initialize discovery manager.
92
+
93
+ Args:
94
+ gitignore_manager: GitignoreManager instance for filtering
95
+ emitter: Optional event emitter
96
+ """
97
+ self.logger = get_logger(__name__)
98
+ self.gitignore_manager = gitignore_manager
99
+ self.emitter = emitter
100
+ self._last_working_dir = None
101
+
102
+ def has_code_files(
103
+ self, directory: Path, depth: int = 5, current_depth: int = 0
104
+ ) -> bool:
105
+ """Check if directory contains code files up to 5 levels deep.
106
+
107
+ Args:
108
+ directory: Directory to check
109
+ depth: Maximum depth to search
110
+ current_depth: Current recursion depth
111
+
112
+ Returns:
113
+ True if directory contains code files within depth levels
114
+ """
115
+ if current_depth >= depth:
116
+ return False
117
+
118
+ # Skip checking these directories entirely
119
+ SKIP_DIRS = {
120
+ "node_modules",
121
+ "__pycache__",
122
+ ".git",
123
+ ".venv",
124
+ "venv",
125
+ "dist",
126
+ "build",
127
+ ".tox",
128
+ "htmlcov",
129
+ ".pytest_cache",
130
+ ".mypy_cache",
131
+ "coverage",
132
+ ".idea",
133
+ ".vscode",
134
+ "env",
135
+ ".coverage",
136
+ "__MACOSX",
137
+ ".ipynb_checkpoints",
138
+ }
139
+ # Skip directories in the skip list or egg-info directories
140
+ if directory.name in SKIP_DIRS or directory.name.endswith(".egg-info"):
141
+ return False
142
+
143
+ try:
144
+ for item in directory.iterdir():
145
+ # Skip hidden items in scan
146
+ if item.name.startswith("."):
147
+ continue
148
+
149
+ if item.is_file():
150
+ # Check if it's a code file
151
+ ext = item.suffix.lower()
152
+ if ext in self.CODE_EXTENSIONS:
153
+ return True
154
+ elif item.is_dir() and current_depth < depth - 1:
155
+ # Skip egg-info directories in the recursive check too
156
+ if item.name.endswith(".egg-info"):
157
+ continue
158
+ if self.has_code_files(item, depth, current_depth + 1):
159
+ return True
160
+
161
+ except (PermissionError, OSError):
162
+ pass
163
+
164
+ return False
165
+
166
+ def discover_top_level(
167
+ self, directory: Path, ignore_patterns: Optional[List[str]] = None
168
+ ) -> Dict[str, any]:
169
+ """Discover only top-level directories and files for lazy loading.
170
+
171
+ Args:
172
+ directory: Root directory to discover
173
+ ignore_patterns: Patterns to ignore
174
+
175
+ Returns:
176
+ Dictionary with top-level structure
177
+ """
178
+ # CRITICAL FIX: Use the directory parameter as the base for relative paths
179
+ # NOT the current working directory. This ensures we only show items
180
+ # within the requested directory, not parent directories.
181
+ Path(directory).absolute()
182
+
183
+ # Emit discovery start event
184
+ if self.emitter:
185
+ self.emitter.emit(
186
+ "info",
187
+ {
188
+ "type": "discovery.start",
189
+ "action": "scanning_directory",
190
+ "path": str(directory),
191
+ "message": f"Starting discovery of {directory.name}",
192
+ "timestamp": datetime.now(timezone.utc).isoformat(),
193
+ },
194
+ )
195
+
196
+ result = {
197
+ "path": str(directory),
198
+ "name": directory.name,
199
+ "type": "directory",
200
+ "children": [],
201
+ }
202
+
203
+ try:
204
+ # Clear cache if working directory changed
205
+ if self._last_working_dir != directory:
206
+ self.gitignore_manager.clear_cache()
207
+ self._last_working_dir = directory
208
+
209
+ # Get immediate children only (no recursion)
210
+ files_count = 0
211
+ dirs_count = 0
212
+ ignored_count = 0
213
+
214
+ for item in directory.iterdir():
215
+ # Use gitignore manager for filtering with the directory as working dir
216
+ if self.gitignore_manager.should_ignore(item, directory):
217
+ if self.emitter:
218
+ self.emitter.emit(
219
+ "info",
220
+ {
221
+ "type": "filter.gitignore",
222
+ "path": str(item),
223
+ "reason": "gitignore pattern",
224
+ "message": f"Ignored by gitignore: {item.name}",
225
+ "timestamp": datetime.now(timezone.utc).isoformat(),
226
+ },
227
+ )
228
+ ignored_count += 1
229
+ continue
230
+
231
+ # Also check additional patterns if provided
232
+ if ignore_patterns and any(p in str(item) for p in ignore_patterns):
233
+ if self.emitter:
234
+ self.emitter.emit(
235
+ "info",
236
+ {
237
+ "type": "filter.pattern",
238
+ "path": str(item),
239
+ "reason": "custom pattern",
240
+ "message": f"Ignored by pattern: {item.name}",
241
+ "timestamp": datetime.now(timezone.utc).isoformat(),
242
+ },
243
+ )
244
+ ignored_count += 1
245
+ continue
246
+
247
+ if item.is_dir():
248
+ # Check if directory contains code files (recursively checking subdirectories)
249
+ # Important: We want to include directories even if they only have code
250
+ # in subdirectories (like src/claude_mpm/*.py)
251
+ if not self.has_code_files(item, depth=5):
252
+ if self.emitter:
253
+ self.emitter.emit(
254
+ "info",
255
+ {
256
+ "type": "filter.no_code",
257
+ "path": str(item.name),
258
+ "reason": "no code files",
259
+ "message": f"Skipped directory without code: {item.name}",
260
+ "timestamp": datetime.now(timezone.utc).isoformat(),
261
+ },
262
+ )
263
+ ignored_count += 1
264
+ continue
265
+
266
+ # Directory - return just the item name
267
+ # The frontend will construct the full path by combining parent path with child name
268
+ path_str = item.name
269
+
270
+ # Emit directory found event
271
+ if self.emitter:
272
+ self.emitter.emit(
273
+ "info",
274
+ {
275
+ "type": "discovery.directory",
276
+ "path": str(item),
277
+ "message": f"Found directory: {item.name}",
278
+ "timestamp": datetime.now(timezone.utc).isoformat(),
279
+ },
280
+ )
281
+ dirs_count += 1
282
+
283
+ child = {
284
+ "path": path_str,
285
+ "name": item.name,
286
+ "type": "directory",
287
+ "discovered": False,
288
+ "children": [],
289
+ }
290
+ result["children"].append(child)
291
+
292
+ elif item.is_file():
293
+ # Check if it's a supported code file or a special file we want to show
294
+ supported_extensions = {
295
+ ".py",
296
+ ".js",
297
+ ".jsx",
298
+ ".ts",
299
+ ".tsx",
300
+ ".mjs",
301
+ ".cjs",
302
+ }
303
+ if item.suffix in supported_extensions or item.name in [
304
+ ".gitignore",
305
+ ".env.example",
306
+ ".env.sample",
307
+ ]:
308
+ # File - mark for lazy analysis
309
+ language = self.get_language(item)
310
+
311
+ # File path should be just the item name
312
+ # The frontend will construct the full path by combining parent path with child name
313
+ path_str = item.name
314
+
315
+ # Emit file found event
316
+ if self.emitter:
317
+ self.emitter.emit(
318
+ "info",
319
+ {
320
+ "type": "discovery.file",
321
+ "path": str(item),
322
+ "language": language,
323
+ "size": item.stat().st_size,
324
+ "message": f"Found file: {item.name} ({language})",
325
+ "timestamp": datetime.now(timezone.utc).isoformat(),
326
+ },
327
+ )
328
+ files_count += 1
329
+
330
+ child = {
331
+ "path": path_str,
332
+ "name": item.name,
333
+ "type": "file",
334
+ "language": language,
335
+ "size": item.stat().st_size,
336
+ "analyzed": False,
337
+ }
338
+ result["children"].append(child)
339
+
340
+ if self.emitter:
341
+ self.emitter.emit_file_discovered(
342
+ path_str, language, item.stat().st_size
343
+ )
344
+
345
+ except PermissionError as e:
346
+ self.logger.warning(f"Permission denied accessing {directory}: {e}")
347
+ if self.emitter:
348
+ self.emitter.emit_error(str(directory), f"Permission denied: {e}")
349
+
350
+ # Emit discovery complete event with stats
351
+ if self.emitter:
352
+ self.emitter.emit(
353
+ "info",
354
+ {
355
+ "type": "discovery.complete",
356
+ "path": str(directory),
357
+ "stats": {
358
+ "files": files_count,
359
+ "directories": dirs_count,
360
+ "ignored": ignored_count,
361
+ },
362
+ "message": f"Discovery complete: {files_count} files, {dirs_count} directories, {ignored_count} ignored",
363
+ "timestamp": datetime.now(timezone.utc).isoformat(),
364
+ },
365
+ )
366
+
367
+ return result
368
+
369
+ def discover_directory(
370
+ self, dir_path: str, ignore_patterns: Optional[List[str]] = None
371
+ ) -> Dict[str, any]:
372
+ """Discover contents of a specific directory for lazy loading.
373
+
374
+ Args:
375
+ dir_path: Directory path to discover
376
+ ignore_patterns: Patterns to ignore
377
+
378
+ Returns:
379
+ Dictionary with directory contents
380
+ """
381
+ directory = Path(dir_path)
382
+ if not directory.exists() or not directory.is_dir():
383
+ return {"error": f"Invalid directory: {dir_path}"}
384
+
385
+ # Clear cache if working directory changed
386
+ if self._last_working_dir != directory.parent:
387
+ self.gitignore_manager.clear_cache()
388
+ self._last_working_dir = directory.parent
389
+
390
+ # The discover_top_level method will emit all the INFO events
391
+ return self.discover_top_level(directory, ignore_patterns)
392
+
393
+ def get_language(self, file_path: Path) -> str:
394
+ """Determine language from file extension.
395
+
396
+ Args:
397
+ file_path: Path to file
398
+
399
+ Returns:
400
+ Language string
401
+ """
402
+ ext = file_path.suffix.lower()
403
+ return self.LANGUAGE_MAP.get(ext, "unknown")
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Events Module
4
+ =============
5
+
6
+ Handles event emission for code tree analysis progress updates.
7
+
8
+ WHY: Decouples event emission from analysis logic, allowing
9
+ flexible event handling and real-time UI updates.
10
+ """
11
+
12
+ from datetime import datetime, timezone
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 CodeTreeEventEmitter
18
+ from .models import CodeNode
19
+
20
+
21
+ class EventManager:
22
+ """Manages event emission during code tree analysis."""
23
+
24
+ def __init__(self, emitter: Optional[CodeTreeEventEmitter] = None):
25
+ """Initialize event manager.
26
+
27
+ Args:
28
+ emitter: Optional event emitter
29
+ """
30
+ self.logger = get_logger(__name__)
31
+ self.emitter = emitter
32
+
33
+ def emit_analysis_start(self, path: Path, language: str) -> None:
34
+ """Emit analysis start event.
35
+
36
+ Args:
37
+ path: File path being analyzed
38
+ language: Programming language
39
+ """
40
+ if self.emitter:
41
+ self.emitter.emit(
42
+ "info",
43
+ {
44
+ "type": "analysis.start",
45
+ "file": str(path),
46
+ "language": language,
47
+ "message": f"Analyzing: {path.name}",
48
+ "timestamp": datetime.now(timezone.utc).isoformat(),
49
+ },
50
+ )
51
+
52
+ def emit_cache_hit(self, path: Path) -> None:
53
+ """Emit cache hit event.
54
+
55
+ Args:
56
+ path: File path with cache hit
57
+ """
58
+ if self.emitter:
59
+ self.emitter.emit(
60
+ "info",
61
+ {
62
+ "type": "cache.hit",
63
+ "file": str(path),
64
+ "message": f"Using cached analysis for {path.name}",
65
+ "timestamp": datetime.now(timezone.utc).isoformat(),
66
+ },
67
+ )
68
+
69
+ def emit_cache_miss(self, path: Path) -> None:
70
+ """Emit cache miss event.
71
+
72
+ Args:
73
+ path: File path with cache miss
74
+ """
75
+ if self.emitter:
76
+ self.emitter.emit(
77
+ "info",
78
+ {
79
+ "type": "cache.miss",
80
+ "file": str(path),
81
+ "message": f"Cache miss, analyzing fresh: {path.name}",
82
+ "timestamp": datetime.now(timezone.utc).isoformat(),
83
+ },
84
+ )
85
+
86
+ def emit_parsing_start(self, path: Path) -> None:
87
+ """Emit parsing start event.
88
+
89
+ Args:
90
+ path: File path being parsed
91
+ """
92
+ if self.emitter:
93
+ self.emitter.emit(
94
+ "info",
95
+ {
96
+ "type": "analysis.parse",
97
+ "file": str(path),
98
+ "message": f"Parsing file content: {path.name}",
99
+ "timestamp": datetime.now(timezone.utc).isoformat(),
100
+ },
101
+ )
102
+
103
+ def emit_node_found(self, node: CodeNode, path: Path) -> None:
104
+ """Emit node found event.
105
+
106
+ Args:
107
+ node: CodeNode that was found
108
+ path: File path containing the node
109
+ """
110
+ if self.emitter:
111
+ self.emitter.emit(
112
+ "info",
113
+ {
114
+ "type": f"analysis.{node.node_type}",
115
+ "name": node.name,
116
+ "file": str(path),
117
+ "line_start": node.line_start,
118
+ "complexity": node.complexity,
119
+ "message": f"Found {node.node_type}: {node.name}",
120
+ "timestamp": datetime.now(timezone.utc).isoformat(),
121
+ },
122
+ )
123
+
124
+ def emit_analysis_complete(
125
+ self, path: Path, filtered_nodes: List[dict], duration: float
126
+ ) -> None:
127
+ """Emit analysis complete event.
128
+
129
+ Args:
130
+ path: File path that was analyzed
131
+ filtered_nodes: List of filtered node dictionaries
132
+ duration: Analysis duration in seconds
133
+ """
134
+ if not self.emitter:
135
+ return
136
+
137
+ stats = self._calculate_node_stats(filtered_nodes)
138
+ self.emitter.emit(
139
+ "info",
140
+ {
141
+ "type": "analysis.complete",
142
+ "file": str(path),
143
+ "stats": stats,
144
+ "duration": duration,
145
+ "message": f"Analysis complete: {stats['classes']} classes, {stats['functions']} functions, {stats['methods']} methods",
146
+ "timestamp": datetime.now(timezone.utc).isoformat(),
147
+ },
148
+ )
149
+ self.emitter.emit_file_analyzed(str(path), filtered_nodes, duration)
150
+
151
+ def _calculate_node_stats(self, filtered_nodes: List[dict]) -> dict:
152
+ """Calculate statistics from filtered nodes.
153
+
154
+ Args:
155
+ filtered_nodes: List of filtered node dictionaries
156
+
157
+ Returns:
158
+ Dictionary of node statistics
159
+ """
160
+ classes_count = sum(1 for n in filtered_nodes if n["type"] == "class")
161
+ functions_count = sum(1 for n in filtered_nodes if n["type"] == "function")
162
+ methods_count = sum(1 for n in filtered_nodes if n["type"] == "method")
163
+ return {
164
+ "classes": classes_count,
165
+ "functions": functions_count,
166
+ "methods": methods_count,
167
+ "total_nodes": len(filtered_nodes),
168
+ }