claude-mpm 3.4.10__py3-none-any.whl → 5.4.85__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1062) hide show
  1. claude_mpm/BUILD_NUMBER +1 -0
  2. claude_mpm/VERSION +1 -0
  3. claude_mpm/__init__.py +50 -12
  4. claude_mpm/__main__.py +7 -2
  5. claude_mpm/agents/BASE_AGENT.md +164 -0
  6. claude_mpm/agents/BASE_ENGINEER.md +658 -0
  7. claude_mpm/agents/CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md +405 -0
  8. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +112 -0
  9. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +186 -0
  10. claude_mpm/agents/MEMORY.md +72 -0
  11. claude_mpm/agents/PM_INSTRUCTIONS.md +1429 -0
  12. claude_mpm/agents/WORKFLOW.md +111 -0
  13. claude_mpm/agents/__init__.py +92 -80
  14. claude_mpm/agents/agent-template.yaml +83 -0
  15. claude_mpm/agents/agent_loader.py +560 -745
  16. claude_mpm/agents/agent_loader_integration.py +53 -55
  17. claude_mpm/agents/agents_metadata.py +186 -27
  18. claude_mpm/agents/async_agent_loader.py +436 -0
  19. claude_mpm/agents/base_agent.json +8 -4
  20. claude_mpm/agents/frontmatter_validator.py +754 -0
  21. claude_mpm/agents/system_agent_config.py +222 -155
  22. claude_mpm/agents/templates/README.md +465 -0
  23. claude_mpm/agents/templates/__init__.py +17 -13
  24. claude_mpm/agents/templates/circuit-breakers.md +1391 -0
  25. claude_mpm/agents/templates/context-management-examples.md +544 -0
  26. claude_mpm/agents/templates/git-file-tracking.md +584 -0
  27. claude_mpm/agents/templates/pm-examples.md +474 -0
  28. claude_mpm/agents/templates/pm-red-flags.md +310 -0
  29. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  30. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  31. claude_mpm/agents/templates/response-format.md +583 -0
  32. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  33. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  34. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  35. claude_mpm/agents/templates/validation-templates.md +312 -0
  36. claude_mpm/cli/__init__.py +94 -128
  37. claude_mpm/cli/__main__.py +33 -0
  38. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  39. claude_mpm/cli/commands/__init__.py +36 -12
  40. claude_mpm/cli/commands/agent_manager.py +1403 -0
  41. claude_mpm/cli/commands/agent_source.py +774 -0
  42. claude_mpm/cli/commands/agent_state_manager.py +335 -0
  43. claude_mpm/cli/commands/agents.py +2501 -168
  44. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  45. claude_mpm/cli/commands/agents_discover.py +338 -0
  46. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  47. claude_mpm/cli/commands/aggregate.py +540 -0
  48. claude_mpm/cli/commands/analyze.py +553 -0
  49. claude_mpm/cli/commands/analyze_code.py +528 -0
  50. claude_mpm/cli/commands/auto_configure.py +1053 -0
  51. claude_mpm/cli/commands/cleanup.py +588 -0
  52. claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
  53. claude_mpm/cli/commands/config.py +586 -0
  54. claude_mpm/cli/commands/configure.py +3253 -0
  55. claude_mpm/cli/commands/configure_agent_display.py +282 -0
  56. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  57. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  58. claude_mpm/cli/commands/configure_models.py +18 -0
  59. claude_mpm/cli/commands/configure_navigation.py +184 -0
  60. claude_mpm/cli/commands/configure_paths.py +104 -0
  61. claude_mpm/cli/commands/configure_persistence.py +254 -0
  62. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  63. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  64. claude_mpm/cli/commands/configure_validators.py +73 -0
  65. claude_mpm/cli/commands/dashboard.py +286 -0
  66. claude_mpm/cli/commands/debug.py +1386 -0
  67. claude_mpm/cli/commands/doctor.py +243 -0
  68. claude_mpm/cli/commands/hook_errors.py +277 -0
  69. claude_mpm/cli/commands/info.py +195 -74
  70. claude_mpm/cli/commands/local_deploy.py +534 -0
  71. claude_mpm/cli/commands/mcp.py +205 -0
  72. claude_mpm/cli/commands/mcp_command_router.py +161 -0
  73. claude_mpm/cli/commands/mcp_config.py +154 -0
  74. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  75. claude_mpm/cli/commands/mcp_external_commands.py +249 -0
  76. claude_mpm/cli/commands/mcp_install_commands.py +346 -0
  77. claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
  78. claude_mpm/cli/commands/mcp_server_commands.py +155 -0
  79. claude_mpm/cli/commands/mcp_setup_external.py +868 -0
  80. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  81. claude_mpm/cli/commands/memory.py +585 -846
  82. claude_mpm/cli/commands/monitor.py +228 -310
  83. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  84. claude_mpm/cli/commands/mpm_init/core.py +759 -0
  85. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  86. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  87. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  88. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  89. claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
  90. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  91. claude_mpm/cli/commands/mpm_init_handler.py +195 -0
  92. claude_mpm/cli/commands/postmortem.py +401 -0
  93. claude_mpm/cli/commands/profile.py +276 -0
  94. claude_mpm/cli/commands/run.py +910 -488
  95. claude_mpm/cli/commands/search.py +458 -0
  96. claude_mpm/cli/commands/skill_source.py +694 -0
  97. claude_mpm/cli/commands/skills.py +1398 -0
  98. claude_mpm/cli/commands/summarize.py +413 -0
  99. claude_mpm/cli/commands/tickets.py +536 -53
  100. claude_mpm/cli/commands/uninstall.py +176 -0
  101. claude_mpm/cli/commands/upgrade.py +152 -0
  102. claude_mpm/cli/commands/verify.py +119 -0
  103. claude_mpm/cli/executor.py +298 -0
  104. claude_mpm/cli/helpers.py +105 -0
  105. claude_mpm/cli/interactive/__init__.py +31 -0
  106. claude_mpm/cli/interactive/agent_wizard.py +1927 -0
  107. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  108. claude_mpm/cli/interactive/skill_selector.py +481 -0
  109. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  110. claude_mpm/cli/parser.py +87 -563
  111. claude_mpm/cli/parsers/__init__.py +35 -0
  112. claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
  113. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  114. claude_mpm/cli/parsers/agents_parser.py +575 -0
  115. claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
  116. claude_mpm/cli/parsers/analyze_parser.py +135 -0
  117. claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
  118. claude_mpm/cli/parsers/base_parser.py +649 -0
  119. claude_mpm/cli/parsers/config_parser.py +208 -0
  120. claude_mpm/cli/parsers/configure_parser.py +138 -0
  121. claude_mpm/cli/parsers/dashboard_parser.py +113 -0
  122. claude_mpm/cli/parsers/debug_parser.py +319 -0
  123. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  124. claude_mpm/cli/parsers/mcp_parser.py +195 -0
  125. claude_mpm/cli/parsers/memory_parser.py +138 -0
  126. claude_mpm/cli/parsers/monitor_parser.py +142 -0
  127. claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
  128. claude_mpm/cli/parsers/profile_parser.py +147 -0
  129. claude_mpm/cli/parsers/run_parser.py +157 -0
  130. claude_mpm/cli/parsers/search_parser.py +245 -0
  131. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  132. claude_mpm/cli/parsers/skills_parser.py +277 -0
  133. claude_mpm/cli/parsers/source_parser.py +138 -0
  134. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  135. claude_mpm/cli/shared/__init__.py +40 -0
  136. claude_mpm/cli/shared/argument_patterns.py +205 -0
  137. claude_mpm/cli/shared/base_command.py +242 -0
  138. claude_mpm/cli/shared/error_handling.py +242 -0
  139. claude_mpm/cli/shared/output_formatters.py +241 -0
  140. claude_mpm/cli/startup.py +1578 -0
  141. claude_mpm/cli/startup_display.py +480 -0
  142. claude_mpm/cli/startup_logging.py +839 -0
  143. claude_mpm/cli/utils.py +136 -47
  144. claude_mpm/cli_module/__init__.py +6 -6
  145. claude_mpm/cli_module/args.py +188 -140
  146. claude_mpm/cli_module/commands.py +79 -70
  147. claude_mpm/cli_module/migration_example.py +42 -64
  148. claude_mpm/commands/__init__.py +14 -0
  149. claude_mpm/commands/mpm-config.md +28 -0
  150. claude_mpm/commands/mpm-doctor.md +20 -0
  151. claude_mpm/commands/mpm-help.md +20 -0
  152. claude_mpm/commands/mpm-init.md +120 -0
  153. claude_mpm/commands/mpm-monitor.md +31 -0
  154. claude_mpm/commands/mpm-organize.md +120 -0
  155. claude_mpm/commands/mpm-postmortem.md +21 -0
  156. claude_mpm/commands/mpm-session-resume.md +30 -0
  157. claude_mpm/commands/mpm-status.md +20 -0
  158. claude_mpm/commands/mpm-ticket-view.md +109 -0
  159. claude_mpm/commands/mpm-version.md +20 -0
  160. claude_mpm/commands/mpm.md +31 -0
  161. claude_mpm/config/__init__.py +42 -2
  162. claude_mpm/config/agent_config.py +402 -0
  163. claude_mpm/config/agent_presets.py +488 -0
  164. claude_mpm/config/agent_sources.py +352 -0
  165. claude_mpm/config/experimental_features.py +217 -0
  166. claude_mpm/config/model_config.py +428 -0
  167. claude_mpm/config/paths.py +258 -0
  168. claude_mpm/config/skill_presets.py +392 -0
  169. claude_mpm/config/skill_sources.py +590 -0
  170. claude_mpm/config/socketio_config.py +125 -83
  171. claude_mpm/constants.py +133 -22
  172. claude_mpm/core/__init__.py +62 -36
  173. claude_mpm/core/agent_name_normalizer.py +71 -73
  174. claude_mpm/core/agent_registry.py +385 -492
  175. claude_mpm/core/agent_session_manager.py +81 -70
  176. claude_mpm/core/api_validator.py +330 -0
  177. claude_mpm/core/base_service.py +159 -122
  178. claude_mpm/core/cache.py +560 -0
  179. claude_mpm/core/claude_runner.py +696 -916
  180. claude_mpm/core/config.py +613 -122
  181. claude_mpm/core/config_aliases.py +74 -73
  182. claude_mpm/core/config_constants.py +314 -0
  183. claude_mpm/core/constants.py +361 -0
  184. claude_mpm/core/container.py +646 -104
  185. claude_mpm/core/enums.py +452 -0
  186. claude_mpm/core/error_handler.py +623 -0
  187. claude_mpm/core/exceptions.py +536 -0
  188. claude_mpm/core/factories.py +105 -109
  189. claude_mpm/core/file_utils.py +764 -0
  190. claude_mpm/core/framework/__init__.py +25 -0
  191. claude_mpm/core/framework/formatters/__init__.py +11 -0
  192. claude_mpm/core/framework/formatters/capability_generator.py +367 -0
  193. claude_mpm/core/framework/formatters/content_formatter.py +278 -0
  194. claude_mpm/core/framework/formatters/context_generator.py +185 -0
  195. claude_mpm/core/framework/loaders/__init__.py +13 -0
  196. claude_mpm/core/framework/loaders/agent_loader.py +213 -0
  197. claude_mpm/core/framework/loaders/file_loader.py +176 -0
  198. claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
  199. claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
  200. claude_mpm/core/framework/processors/__init__.py +11 -0
  201. claude_mpm/core/framework/processors/memory_processor.py +230 -0
  202. claude_mpm/core/framework/processors/metadata_processor.py +146 -0
  203. claude_mpm/core/framework/processors/template_processor.py +244 -0
  204. claude_mpm/core/framework_loader.py +485 -414
  205. claude_mpm/core/hook_error_memory.py +381 -0
  206. claude_mpm/core/hook_manager.py +246 -86
  207. claude_mpm/core/hook_performance_config.py +147 -0
  208. claude_mpm/core/injectable_service.py +72 -63
  209. claude_mpm/core/instruction_reinforcement_hook.py +267 -0
  210. claude_mpm/core/interactive_session.py +670 -0
  211. claude_mpm/core/interfaces.py +570 -164
  212. claude_mpm/core/lazy.py +467 -0
  213. claude_mpm/core/log_manager.py +707 -0
  214. claude_mpm/core/logger.py +295 -134
  215. claude_mpm/core/logging_config.py +474 -0
  216. claude_mpm/core/logging_utils.py +520 -0
  217. claude_mpm/core/minimal_framework_loader.py +24 -22
  218. claude_mpm/core/mixins.py +30 -29
  219. claude_mpm/core/oneshot_session.py +594 -0
  220. claude_mpm/core/optimized_agent_loader.py +479 -0
  221. claude_mpm/core/optimized_startup.py +554 -0
  222. claude_mpm/core/output_style_manager.py +491 -0
  223. claude_mpm/core/pm_hook_interceptor.py +197 -82
  224. claude_mpm/core/protocols/__init__.py +23 -0
  225. claude_mpm/core/protocols/runner_protocol.py +103 -0
  226. claude_mpm/core/protocols/session_protocol.py +131 -0
  227. claude_mpm/core/service_registry.py +153 -116
  228. claude_mpm/core/session_manager.py +179 -64
  229. claude_mpm/core/shared/__init__.py +17 -0
  230. claude_mpm/core/shared/config_loader.py +326 -0
  231. claude_mpm/core/shared/path_resolver.py +281 -0
  232. claude_mpm/core/shared/singleton_manager.py +221 -0
  233. claude_mpm/core/socketio_pool.py +400 -137
  234. claude_mpm/core/system_context.py +38 -0
  235. claude_mpm/core/tool_access_control.py +64 -57
  236. claude_mpm/core/types.py +307 -0
  237. claude_mpm/core/typing_utils.py +553 -0
  238. claude_mpm/core/unified_agent_registry.py +969 -0
  239. claude_mpm/core/unified_config.py +612 -0
  240. claude_mpm/core/unified_paths.py +958 -0
  241. claude_mpm/dashboard/__init__.py +12 -0
  242. claude_mpm/dashboard/api/simple_directory.py +261 -0
  243. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  244. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
  245. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
  246. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
  247. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
  248. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
  249. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
  250. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
  251. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
  252. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
  253. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
  254. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  255. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
  256. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
  257. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
  258. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
  259. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
  260. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
  261. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
  262. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
  263. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
  264. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
  265. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
  266. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
  267. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
  268. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  269. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
  270. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
  271. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  272. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
  273. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
  274. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
  275. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
  276. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
  277. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
  278. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
  279. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
  280. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
  281. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  282. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
  283. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
  284. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
  285. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
  286. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
  287. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
  288. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
  289. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
  290. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
  291. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
  292. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  293. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
  294. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
  295. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
  296. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
  297. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
  298. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
  299. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
  300. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
  301. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
  302. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
  303. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
  304. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
  305. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
  306. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
  307. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
  308. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  309. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  310. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  311. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  312. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  313. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  314. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  315. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  316. claude_mpm/experimental/__init__.py +10 -0
  317. claude_mpm/experimental/cli_enhancements.py +104 -89
  318. claude_mpm/generators/__init__.py +1 -1
  319. claude_mpm/generators/agent_profile_generator.py +76 -66
  320. claude_mpm/hooks/__init__.py +37 -1
  321. claude_mpm/hooks/base_hook.py +37 -32
  322. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  323. claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
  324. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  325. claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
  326. claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
  327. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
  328. claude_mpm/hooks/claude_hooks/installer.py +806 -0
  329. claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
  330. claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
  331. claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
  332. claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
  333. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
  334. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  335. claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
  336. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  337. claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
  338. claude_mpm/hooks/failure_learning/__init__.py +54 -0
  339. claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
  340. claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
  341. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
  342. claude_mpm/hooks/instruction_reinforcement.py +301 -0
  343. claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
  344. claude_mpm/hooks/kuzu_memory_hook.py +386 -0
  345. claude_mpm/hooks/kuzu_response_hook.py +179 -0
  346. claude_mpm/hooks/memory_integration_hook.py +201 -107
  347. claude_mpm/hooks/session_resume_hook.py +121 -0
  348. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  349. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  350. claude_mpm/hooks/tool_call_interceptor.py +92 -76
  351. claude_mpm/hooks/validation_hooks.py +62 -54
  352. claude_mpm/init.py +518 -83
  353. claude_mpm/models/__init__.py +9 -9
  354. claude_mpm/models/agent_definition.py +40 -23
  355. claude_mpm/models/agent_session.py +538 -0
  356. claude_mpm/models/git_repository.py +198 -0
  357. claude_mpm/models/resume_log.py +340 -0
  358. claude_mpm/schemas/__init__.py +12 -0
  359. claude_mpm/scripts/__init__.py +15 -0
  360. claude_mpm/scripts/claude-hook-handler.sh +227 -0
  361. claude_mpm/scripts/launch_monitor.py +165 -0
  362. claude_mpm/scripts/mpm_doctor.py +322 -0
  363. claude_mpm/scripts/socketio_daemon.py +189 -200
  364. claude_mpm/scripts/start_activity_logging.py +91 -0
  365. claude_mpm/services/__init__.py +208 -39
  366. claude_mpm/services/agent_capabilities_service.py +266 -0
  367. claude_mpm/services/agents/__init__.py +89 -0
  368. claude_mpm/services/agents/agent_builder.py +514 -0
  369. claude_mpm/services/agents/agent_preset_service.py +238 -0
  370. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  371. claude_mpm/services/agents/agent_review_service.py +280 -0
  372. claude_mpm/services/agents/agent_selection_service.py +484 -0
  373. claude_mpm/services/agents/auto_config_manager.py +796 -0
  374. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  375. claude_mpm/services/agents/cache_git_manager.py +621 -0
  376. claude_mpm/services/agents/deployment/__init__.py +21 -0
  377. claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
  378. claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
  379. claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
  380. claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
  381. claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
  382. claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
  383. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
  384. claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
  385. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
  386. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
  387. claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
  388. claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
  389. claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
  390. claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
  391. claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
  392. claude_mpm/services/agents/deployment/agent_template_builder.py +1377 -0
  393. claude_mpm/services/agents/deployment/agent_validator.py +376 -0
  394. claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
  395. claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
  396. claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
  397. claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
  398. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  399. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  400. claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
  401. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  402. claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
  403. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  404. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  405. claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
  406. claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -0
  407. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  408. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  409. claude_mpm/services/agents/deployment/facade/deployment_executor.py +70 -0
  410. claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
  411. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  412. claude_mpm/services/agents/deployment/interface_adapter.py +226 -0
  413. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  414. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  415. claude_mpm/services/agents/deployment/local_template_deployment.py +362 -0
  416. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -0
  417. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  418. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  419. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +162 -0
  420. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  421. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  422. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +240 -0
  423. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
  424. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
  425. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
  426. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
  427. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  428. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
  429. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  430. claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
  431. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
  432. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -0
  433. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  434. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  435. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  436. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  437. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  438. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  439. claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
  440. claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
  441. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  442. claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
  443. claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
  444. claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
  445. claude_mpm/services/agents/deployment/validation/__init__.py +21 -0
  446. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  447. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  448. claude_mpm/services/agents/deployment/validation/template_validator.py +319 -0
  449. claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
  450. claude_mpm/services/agents/git_source_manager.py +682 -0
  451. claude_mpm/services/agents/loading/__init__.py +11 -0
  452. claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
  453. claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
  454. claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
  455. claude_mpm/services/agents/local_template_manager.py +784 -0
  456. claude_mpm/services/agents/management/__init__.py +9 -0
  457. claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
  458. claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
  459. claude_mpm/services/agents/memory/__init__.py +22 -0
  460. claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
  461. claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
  462. claude_mpm/services/agents/memory/content_manager.py +470 -0
  463. claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
  464. claude_mpm/services/agents/memory/memory_file_service.py +129 -0
  465. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  466. claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
  467. claude_mpm/services/agents/memory/template_generator.py +83 -0
  468. claude_mpm/services/agents/observers.py +547 -0
  469. claude_mpm/services/agents/recommender.py +617 -0
  470. claude_mpm/services/agents/registry/__init__.py +30 -0
  471. claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
  472. claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
  473. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  474. claude_mpm/services/agents/sources/__init__.py +13 -0
  475. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  476. claude_mpm/services/agents/sources/git_source_sync_service.py +1205 -0
  477. claude_mpm/services/agents/startup_sync.py +262 -0
  478. claude_mpm/services/agents/toolchain_detector.py +478 -0
  479. claude_mpm/services/analysis/__init__.py +35 -0
  480. claude_mpm/services/analysis/clone_detector.py +1030 -0
  481. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  482. claude_mpm/services/analysis/postmortem_service.py +765 -0
  483. claude_mpm/services/async_session_logger.py +665 -0
  484. claude_mpm/services/claude_session_logger.py +321 -0
  485. claude_mpm/services/cli/__init__.py +18 -0
  486. claude_mpm/services/cli/agent_cleanup_service.py +408 -0
  487. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  488. claude_mpm/services/cli/agent_listing_service.py +463 -0
  489. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  490. claude_mpm/services/cli/agent_validation_service.py +590 -0
  491. claude_mpm/services/cli/memory_crud_service.py +622 -0
  492. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  493. claude_mpm/services/cli/resume_service.py +617 -0
  494. claude_mpm/services/cli/session_manager.py +604 -0
  495. claude_mpm/services/cli/session_pause_manager.py +504 -0
  496. claude_mpm/services/cli/session_resume_helper.py +372 -0
  497. claude_mpm/services/cli/startup_checker.py +362 -0
  498. claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
  499. claude_mpm/services/command_deployment_service.py +446 -0
  500. claude_mpm/services/command_handler_service.py +221 -0
  501. claude_mpm/services/communication/__init__.py +22 -0
  502. claude_mpm/services/core/__init__.py +108 -0
  503. claude_mpm/services/core/base.py +269 -0
  504. claude_mpm/services/core/cache_manager.py +309 -0
  505. claude_mpm/services/core/interfaces/__init__.py +273 -0
  506. claude_mpm/services/core/interfaces/agent.py +514 -0
  507. claude_mpm/services/core/interfaces/communication.py +316 -0
  508. claude_mpm/services/core/interfaces/health.py +169 -0
  509. claude_mpm/services/core/interfaces/infrastructure.py +357 -0
  510. claude_mpm/services/core/interfaces/model.py +281 -0
  511. claude_mpm/services/core/interfaces/process.py +372 -0
  512. claude_mpm/services/core/interfaces/project.py +121 -0
  513. claude_mpm/services/core/interfaces/restart.py +307 -0
  514. claude_mpm/services/core/interfaces/service.py +405 -0
  515. claude_mpm/services/core/interfaces/stability.py +260 -0
  516. claude_mpm/services/core/interfaces.py +81 -0
  517. claude_mpm/services/core/memory_manager.py +682 -0
  518. claude_mpm/services/core/models/__init__.py +70 -0
  519. claude_mpm/services/core/models/agent_config.py +384 -0
  520. claude_mpm/services/core/models/health.py +162 -0
  521. claude_mpm/services/core/models/process.py +239 -0
  522. claude_mpm/services/core/models/restart.py +302 -0
  523. claude_mpm/services/core/models/stability.py +264 -0
  524. claude_mpm/services/core/models/toolchain.py +306 -0
  525. claude_mpm/services/core/path_resolver.py +517 -0
  526. claude_mpm/services/core/service_container.py +520 -0
  527. claude_mpm/services/core/service_interfaces.py +436 -0
  528. claude_mpm/services/diagnostics/__init__.py +18 -0
  529. claude_mpm/services/diagnostics/checks/__init__.py +38 -0
  530. claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
  531. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  532. claude_mpm/services/diagnostics/checks/base_check.py +60 -0
  533. claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
  534. claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
  535. claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
  536. claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
  537. claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
  538. claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
  539. claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
  540. claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
  541. claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
  542. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  543. claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
  544. claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
  545. claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
  546. claude_mpm/services/diagnostics/models.py +138 -0
  547. claude_mpm/services/event_aggregator.py +582 -0
  548. claude_mpm/services/event_bus/__init__.py +18 -0
  549. claude_mpm/services/event_bus/config.py +186 -0
  550. claude_mpm/services/event_bus/direct_relay.py +312 -0
  551. claude_mpm/services/event_bus/event_bus.py +396 -0
  552. claude_mpm/services/event_bus/relay.py +326 -0
  553. claude_mpm/services/events/__init__.py +44 -0
  554. claude_mpm/services/events/consumers/__init__.py +18 -0
  555. claude_mpm/services/events/consumers/dead_letter.py +306 -0
  556. claude_mpm/services/events/consumers/logging.py +184 -0
  557. claude_mpm/services/events/consumers/metrics.py +241 -0
  558. claude_mpm/services/events/consumers/socketio.py +377 -0
  559. claude_mpm/services/events/core.py +480 -0
  560. claude_mpm/services/events/interfaces.py +214 -0
  561. claude_mpm/services/events/producers/__init__.py +14 -0
  562. claude_mpm/services/events/producers/hook.py +269 -0
  563. claude_mpm/services/events/producers/system.py +329 -0
  564. claude_mpm/services/exceptions.py +433 -353
  565. claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
  566. claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
  567. claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
  568. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
  569. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
  570. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
  571. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
  572. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
  573. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  574. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  575. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  576. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  577. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +5 -4
  578. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  579. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  580. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +26 -30
  581. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
  582. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  583. claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
  584. claude_mpm/services/git/__init__.py +21 -0
  585. claude_mpm/services/git/git_operations_service.py +579 -0
  586. claude_mpm/services/github/__init__.py +21 -0
  587. claude_mpm/services/github/github_cli_service.py +397 -0
  588. claude_mpm/services/hook_installer_service.py +506 -0
  589. claude_mpm/services/hook_service.py +159 -111
  590. claude_mpm/services/infrastructure/__init__.py +52 -0
  591. claude_mpm/services/infrastructure/context_preservation.py +569 -0
  592. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  593. claude_mpm/services/infrastructure/logging.py +209 -0
  594. claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
  595. claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
  596. claude_mpm/services/infrastructure/monitoring/base.py +122 -0
  597. claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
  598. claude_mpm/services/infrastructure/monitoring/network.py +219 -0
  599. claude_mpm/services/infrastructure/monitoring/process.py +343 -0
  600. claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
  601. claude_mpm/services/infrastructure/monitoring/service.py +368 -0
  602. claude_mpm/services/infrastructure/monitoring.py +71 -0
  603. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  604. claude_mpm/services/instructions/__init__.py +9 -0
  605. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  606. claude_mpm/services/local_ops/__init__.py +155 -0
  607. claude_mpm/services/local_ops/crash_detector.py +257 -0
  608. claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
  609. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  610. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  611. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  612. claude_mpm/services/local_ops/health_manager.py +427 -0
  613. claude_mpm/services/local_ops/log_monitor.py +396 -0
  614. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  615. claude_mpm/services/local_ops/process_manager.py +595 -0
  616. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  617. claude_mpm/services/local_ops/restart_manager.py +401 -0
  618. claude_mpm/services/local_ops/restart_policy.py +387 -0
  619. claude_mpm/services/local_ops/state_manager.py +372 -0
  620. claude_mpm/services/local_ops/unified_manager.py +600 -0
  621. claude_mpm/services/mcp_config_manager.py +1542 -0
  622. claude_mpm/services/mcp_service_verifier.py +732 -0
  623. claude_mpm/services/memory/__init__.py +19 -0
  624. claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
  625. claude_mpm/services/memory/cache/__init__.py +14 -0
  626. claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
  627. claude_mpm/services/memory/cache/simple_cache.py +331 -0
  628. claude_mpm/services/memory/failure_tracker.py +578 -0
  629. claude_mpm/services/memory/indexed_memory.py +648 -0
  630. claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
  631. claude_mpm/services/memory/router.py +951 -0
  632. claude_mpm/services/memory_hook_service.py +470 -0
  633. claude_mpm/services/model/__init__.py +147 -0
  634. claude_mpm/services/model/base_provider.py +365 -0
  635. claude_mpm/services/model/claude_provider.py +412 -0
  636. claude_mpm/services/model/model_router.py +452 -0
  637. claude_mpm/services/model/ollama_provider.py +415 -0
  638. claude_mpm/services/monitor/__init__.py +20 -0
  639. claude_mpm/services/monitor/daemon.py +698 -0
  640. claude_mpm/services/monitor/daemon_manager.py +1076 -0
  641. claude_mpm/services/monitor/event_emitter.py +350 -0
  642. claude_mpm/services/monitor/handlers/__init__.py +21 -0
  643. claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
  644. claude_mpm/services/monitor/handlers/dashboard.py +299 -0
  645. claude_mpm/services/monitor/handlers/file.py +264 -0
  646. claude_mpm/services/monitor/handlers/hooks.py +512 -0
  647. claude_mpm/services/monitor/management/__init__.py +18 -0
  648. claude_mpm/services/monitor/management/health.py +124 -0
  649. claude_mpm/services/monitor/management/lifecycle.py +730 -0
  650. claude_mpm/services/monitor/server.py +1493 -0
  651. claude_mpm/services/monitor_build_service.py +349 -0
  652. claude_mpm/services/native_agent_converter.py +356 -0
  653. claude_mpm/services/orphan_detection.py +786 -0
  654. claude_mpm/services/pm_skills_deployer.py +711 -0
  655. claude_mpm/services/port_manager.py +597 -0
  656. claude_mpm/services/pr/__init__.py +14 -0
  657. claude_mpm/services/pr/pr_template_service.py +329 -0
  658. claude_mpm/services/profile_manager.py +337 -0
  659. claude_mpm/services/project/__init__.py +44 -0
  660. claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
  661. claude_mpm/services/project/analyzer_v2.py +566 -0
  662. claude_mpm/services/project/architecture_analyzer.py +461 -0
  663. claude_mpm/services/project/archive_manager.py +1045 -0
  664. claude_mpm/services/project/dependency_analyzer.py +462 -0
  665. claude_mpm/services/project/detection_strategies.py +719 -0
  666. claude_mpm/services/project/documentation_manager.py +554 -0
  667. claude_mpm/services/project/enhanced_analyzer.py +572 -0
  668. claude_mpm/services/project/language_analyzer.py +265 -0
  669. claude_mpm/services/project/metrics_collector.py +407 -0
  670. claude_mpm/services/project/project_organizer.py +1009 -0
  671. claude_mpm/services/project/registry.py +636 -0
  672. claude_mpm/services/project/toolchain_analyzer.py +583 -0
  673. claude_mpm/services/project_port_allocator.py +596 -0
  674. claude_mpm/services/recovery_manager.py +293 -240
  675. claude_mpm/services/response_tracker.py +267 -0
  676. claude_mpm/services/runner_configuration_service.py +605 -0
  677. claude_mpm/services/self_upgrade_service.py +608 -0
  678. claude_mpm/services/session_management_service.py +314 -0
  679. claude_mpm/services/session_manager.py +380 -0
  680. claude_mpm/services/shared/__init__.py +21 -0
  681. claude_mpm/services/shared/async_service_base.py +216 -0
  682. claude_mpm/services/shared/config_service_base.py +301 -0
  683. claude_mpm/services/shared/lifecycle_service_base.py +308 -0
  684. claude_mpm/services/shared/manager_base.py +315 -0
  685. claude_mpm/services/shared/service_factory.py +309 -0
  686. claude_mpm/services/skills/__init__.py +21 -0
  687. claude_mpm/services/skills/git_skill_source_manager.py +1340 -0
  688. claude_mpm/services/skills/selective_skill_deployer.py +743 -0
  689. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  690. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  691. claude_mpm/services/skills_config.py +547 -0
  692. claude_mpm/services/skills_deployer.py +1168 -0
  693. claude_mpm/services/socketio/__init__.py +25 -0
  694. claude_mpm/services/socketio/client_proxy.py +229 -0
  695. claude_mpm/services/socketio/dashboard_server.py +362 -0
  696. claude_mpm/services/socketio/event_normalizer.py +798 -0
  697. claude_mpm/services/socketio/handlers/__init__.py +30 -0
  698. claude_mpm/services/socketio/handlers/base.py +136 -0
  699. claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
  700. claude_mpm/services/socketio/handlers/connection.py +643 -0
  701. claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
  702. claude_mpm/services/socketio/handlers/file.py +263 -0
  703. claude_mpm/services/socketio/handlers/git.py +962 -0
  704. claude_mpm/services/socketio/handlers/hook.py +211 -0
  705. claude_mpm/services/socketio/handlers/memory.py +26 -0
  706. claude_mpm/services/socketio/handlers/project.py +24 -0
  707. claude_mpm/services/socketio/handlers/registry.py +214 -0
  708. claude_mpm/services/socketio/migration_utils.py +343 -0
  709. claude_mpm/services/socketio/monitor_client.py +364 -0
  710. claude_mpm/services/socketio/server/__init__.py +18 -0
  711. claude_mpm/services/socketio/server/broadcaster.py +569 -0
  712. claude_mpm/services/socketio/server/connection_manager.py +579 -0
  713. claude_mpm/services/socketio/server/core.py +1079 -0
  714. claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
  715. claude_mpm/services/socketio/server/main.py +501 -0
  716. claude_mpm/services/socketio_client_manager.py +173 -143
  717. claude_mpm/services/socketio_server.py +38 -1657
  718. claude_mpm/services/subprocess_launcher_service.py +322 -0
  719. claude_mpm/services/system_instructions_service.py +270 -0
  720. claude_mpm/services/ticket_manager.py +25 -209
  721. claude_mpm/services/ticket_services/__init__.py +26 -0
  722. claude_mpm/services/ticket_services/crud_service.py +328 -0
  723. claude_mpm/services/ticket_services/formatter_service.py +290 -0
  724. claude_mpm/services/ticket_services/search_service.py +324 -0
  725. claude_mpm/services/ticket_services/validation_service.py +303 -0
  726. claude_mpm/services/ticket_services/workflow_service.py +244 -0
  727. claude_mpm/services/unified/__init__.py +65 -0
  728. claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
  729. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
  730. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
  731. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
  732. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
  733. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
  734. claude_mpm/services/unified/config_strategies/__init__.py +175 -0
  735. claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
  736. claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
  737. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
  738. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
  739. claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
  740. claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
  741. claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
  742. claude_mpm/services/unified/deployment_strategies/base.py +553 -0
  743. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
  744. claude_mpm/services/unified/deployment_strategies/local.py +607 -0
  745. claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
  746. claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
  747. claude_mpm/services/unified/interfaces.py +475 -0
  748. claude_mpm/services/unified/migration.py +509 -0
  749. claude_mpm/services/unified/strategies.py +534 -0
  750. claude_mpm/services/unified/unified_analyzer.py +542 -0
  751. claude_mpm/services/unified/unified_config.py +691 -0
  752. claude_mpm/services/unified/unified_deployment.py +466 -0
  753. claude_mpm/services/utility_service.py +280 -0
  754. claude_mpm/services/version_control/__init__.py +34 -37
  755. claude_mpm/services/version_control/branch_strategy.py +26 -17
  756. claude_mpm/services/version_control/conflict_resolution.py +52 -36
  757. claude_mpm/services/version_control/git_operations.py +183 -49
  758. claude_mpm/services/version_control/semantic_versioning.py +172 -61
  759. claude_mpm/services/version_control/version_parser.py +546 -0
  760. claude_mpm/services/version_service.py +379 -0
  761. claude_mpm/services/visualization/__init__.py +15 -0
  762. claude_mpm/services/visualization/mermaid_generator.py +937 -0
  763. claude_mpm/skills/__init__.py +42 -0
  764. claude_mpm/skills/agent_skills_injector.py +324 -0
  765. claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
  766. claude_mpm/skills/bundled/__init__.py +6 -0
  767. claude_mpm/skills/bundled/api-documentation.md +393 -0
  768. claude_mpm/skills/bundled/async-testing.md +571 -0
  769. claude_mpm/skills/bundled/code-review.md +143 -0
  770. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  771. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  772. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  773. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  774. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  775. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  776. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  777. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  778. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  779. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  780. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  781. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  782. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  783. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  784. claude_mpm/skills/bundled/database-migration.md +199 -0
  785. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  786. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  787. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  788. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  789. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  790. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  791. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  792. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  793. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  794. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  795. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  796. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  797. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  798. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  799. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  800. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  801. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  802. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  803. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  804. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  805. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  806. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  807. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  808. claude_mpm/skills/bundled/git-workflow.md +414 -0
  809. claude_mpm/skills/bundled/imagemagick.md +204 -0
  810. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  811. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  812. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  813. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  814. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  815. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  816. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  817. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  818. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  819. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  820. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  821. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  822. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  823. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  824. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  825. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  826. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  827. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  828. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  829. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  830. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  831. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  832. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  833. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  834. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
  835. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
  836. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  837. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  838. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  839. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  840. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  841. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  842. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
  843. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
  844. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
  845. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  846. claude_mpm/skills/bundled/pdf.md +141 -0
  847. claude_mpm/skills/bundled/performance-profiling.md +573 -0
  848. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  849. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  850. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  851. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  852. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  853. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  854. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  855. claude_mpm/skills/bundled/pm/pm-bug-reporting/pm-bug-reporting.md +248 -0
  856. claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
  857. claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
  858. claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
  859. claude_mpm/skills/bundled/pm/pm-teaching-mode/SKILL.md +657 -0
  860. claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
  861. claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
  862. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  863. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  864. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  865. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  866. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  867. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  868. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  869. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  870. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  871. claude_mpm/skills/bundled/security-scanning.md +439 -0
  872. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  873. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  874. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  875. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  876. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  877. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  878. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  879. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  880. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  881. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  882. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  883. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  884. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  885. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  886. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  887. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  888. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  889. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  890. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  891. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  892. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  893. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  894. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  895. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  896. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  897. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  898. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  899. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  900. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  901. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  902. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  903. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  904. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  905. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
  906. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
  907. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
  908. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  909. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  910. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
  911. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  912. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  913. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  914. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  915. claude_mpm/skills/bundled/xlsx.md +157 -0
  916. claude_mpm/skills/registry.py +286 -0
  917. claude_mpm/skills/skill_manager.py +405 -0
  918. claude_mpm/skills/skills_registry.py +347 -0
  919. claude_mpm/skills/skills_service.py +739 -0
  920. claude_mpm/storage/__init__.py +9 -0
  921. claude_mpm/storage/state_storage.py +546 -0
  922. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  923. claude_mpm/templates/questions/__init__.py +38 -0
  924. claude_mpm/templates/questions/base.py +193 -0
  925. claude_mpm/templates/questions/pr_strategy.py +311 -0
  926. claude_mpm/templates/questions/project_init.py +385 -0
  927. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  928. claude_mpm/ticket_wrapper.py +2 -2
  929. claude_mpm/tools/__init__.py +10 -0
  930. claude_mpm/tools/__main__.py +208 -0
  931. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  932. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  933. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  934. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  935. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  936. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  937. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  938. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  939. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  940. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  941. claude_mpm/tools/code_tree_builder.py +631 -0
  942. claude_mpm/tools/code_tree_events.py +420 -0
  943. claude_mpm/tools/socketio_debug.py +671 -0
  944. claude_mpm/utils/__init__.py +8 -8
  945. claude_mpm/utils/agent_dependency_loader.py +1189 -0
  946. claude_mpm/utils/agent_filters.py +261 -0
  947. claude_mpm/utils/common.py +544 -0
  948. claude_mpm/utils/config_manager.py +168 -126
  949. claude_mpm/utils/console.py +11 -0
  950. claude_mpm/utils/database_connector.py +298 -0
  951. claude_mpm/utils/dependency_cache.py +373 -0
  952. claude_mpm/utils/dependency_manager.py +60 -59
  953. claude_mpm/utils/dependency_strategies.py +381 -0
  954. claude_mpm/utils/display_helper.py +260 -0
  955. claude_mpm/utils/environment_context.py +313 -0
  956. claude_mpm/utils/error_handler.py +78 -66
  957. claude_mpm/utils/file_utils.py +305 -0
  958. claude_mpm/utils/framework_detection.py +12 -11
  959. claude_mpm/utils/git_analyzer.py +407 -0
  960. claude_mpm/utils/gitignore.py +244 -0
  961. claude_mpm/utils/import_migration_example.py +12 -60
  962. claude_mpm/utils/imports.py +48 -45
  963. claude_mpm/utils/log_cleanup.py +627 -0
  964. claude_mpm/utils/migration.py +372 -0
  965. claude_mpm/utils/path_operations.py +110 -104
  966. claude_mpm/utils/progress.py +387 -0
  967. claude_mpm/utils/robust_installer.py +844 -0
  968. claude_mpm/utils/session_logging.py +121 -0
  969. claude_mpm/utils/structured_questions.py +619 -0
  970. claude_mpm/utils/subprocess_utils.py +343 -0
  971. claude_mpm/validation/__init__.py +1 -1
  972. claude_mpm/validation/agent_validator.py +214 -108
  973. claude_mpm/validation/frontmatter_validator.py +252 -0
  974. claude_mpm-5.4.85.dist-info/METADATA +1023 -0
  975. claude_mpm-5.4.85.dist-info/RECORD +980 -0
  976. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/entry_points.txt +1 -3
  977. claude_mpm-5.4.85.dist-info/licenses/LICENSE +94 -0
  978. claude_mpm-5.4.85.dist-info/licenses/LICENSE-FAQ.md +153 -0
  979. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
  980. claude_mpm/agents/INSTRUCTIONS.md +0 -352
  981. claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
  982. claude_mpm/agents/base_agent_loader.py +0 -529
  983. claude_mpm/agents/schema/agent_schema.json +0 -314
  984. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
  985. claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
  986. claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
  987. claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
  988. claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
  989. claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
  990. claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
  991. claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
  992. claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
  993. claude_mpm/agents/templates/data_engineer.json +0 -110
  994. claude_mpm/agents/templates/documentation.json +0 -109
  995. claude_mpm/agents/templates/engineer.json +0 -113
  996. claude_mpm/agents/templates/ops.json +0 -109
  997. claude_mpm/agents/templates/pm.json +0 -25
  998. claude_mpm/agents/templates/qa.json +0 -111
  999. claude_mpm/agents/templates/research.json +0 -65
  1000. claude_mpm/agents/templates/security.json +0 -113
  1001. claude_mpm/agents/templates/test_integration.json +0 -112
  1002. claude_mpm/agents/templates/version_control.json +0 -107
  1003. claude_mpm/cli/commands/ui.py +0 -57
  1004. claude_mpm/core/simple_runner.py +0 -1046
  1005. claude_mpm/dashboard/open_dashboard.py +0 -34
  1006. claude_mpm/deployment_paths.py +0 -261
  1007. claude_mpm/hooks/builtin/__init__.py +0 -1
  1008. claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
  1009. claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
  1010. claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
  1011. claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
  1012. claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
  1013. claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
  1014. claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
  1015. claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
  1016. claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
  1017. claude_mpm/orchestration/__init__.py +0 -6
  1018. claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
  1019. claude_mpm/orchestration/archive/factory.py +0 -215
  1020. claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
  1021. claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
  1022. claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
  1023. claude_mpm/orchestration/archive/orchestrator.py +0 -501
  1024. claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
  1025. claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
  1026. claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
  1027. claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
  1028. claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
  1029. claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
  1030. claude_mpm/schemas/workflow_validator.py +0 -411
  1031. claude_mpm/services/agent_deployment.py +0 -1534
  1032. claude_mpm/services/agent_lifecycle_manager.py +0 -1169
  1033. claude_mpm/services/agent_memory_manager.py +0 -1415
  1034. claude_mpm/services/agent_registry.py +0 -676
  1035. claude_mpm/services/deployed_agent_discovery.py +0 -226
  1036. claude_mpm/services/framework_agent_loader.py +0 -337
  1037. claude_mpm/services/framework_claude_md_generator.py +0 -621
  1038. claude_mpm/services/health_monitor.py +0 -892
  1039. claude_mpm/services/memory_router.py +0 -538
  1040. claude_mpm/services/parent_directory_manager/__init__.py +0 -577
  1041. claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
  1042. claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
  1043. claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
  1044. claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
  1045. claude_mpm/services/parent_directory_manager/operations.py +0 -186
  1046. claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
  1047. claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
  1048. claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
  1049. claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
  1050. claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
  1051. claude_mpm/services/standalone_socketio_server.py +0 -1300
  1052. claude_mpm/services/ticket_manager_di.py +0 -318
  1053. claude_mpm/services/ticketing_service_original.py +0 -508
  1054. claude_mpm/ui/__init__.py +0 -1
  1055. claude_mpm/ui/rich_terminal_ui.py +0 -295
  1056. claude_mpm/ui/terminal_ui.py +0 -328
  1057. claude_mpm/utils/paths.py +0 -289
  1058. claude_mpm-3.4.10.dist-info/METADATA +0 -183
  1059. claude_mpm-3.4.10.dist-info/RECORD +0 -201
  1060. claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
  1061. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/WHEEL +0 -0
  1062. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1079 @@
1
+ """
2
+ SocketIO Server Core for claude-mpm.
3
+
4
+ WHY: This module contains the core server management functionality extracted from
5
+ the monolithic socketio_server.py file. It handles server lifecycle, static file
6
+ serving, and basic server setup.
7
+
8
+ DESIGN DECISION: Separated core server logic from event handling and broadcasting
9
+ to create focused, maintainable modules.
10
+ """
11
+
12
+ import asyncio
13
+ import threading
14
+ import time
15
+ from collections import deque
16
+ from datetime import datetime, timezone
17
+ from pathlib import Path
18
+ from typing import Any, Dict, Set
19
+
20
+ try:
21
+ import aiohttp
22
+ import socketio
23
+ from aiohttp import web
24
+
25
+ SOCKETIO_AVAILABLE = True
26
+ except ImportError:
27
+ SOCKETIO_AVAILABLE = False
28
+ socketio = None
29
+ aiohttp = None
30
+ web = None
31
+
32
+ # Import VersionService for dynamic version retrieval
33
+ import contextlib
34
+
35
+ from claude_mpm.services.version_service import VersionService
36
+
37
+ from ....core.constants import SystemLimits, TimeoutConfig
38
+ from ....core.logging_config import get_logger
39
+ from ....core.unified_paths import get_project_root, get_scripts_dir
40
+ from ...exceptions import SocketIOServerError as MPMConnectionError
41
+
42
+
43
+ class SocketIOServerCore:
44
+ """Core server management functionality for SocketIO server.
45
+
46
+ WHY: This class handles the basic server lifecycle, static file serving,
47
+ and core server setup. It's separated from event handling to reduce complexity.
48
+ """
49
+
50
+ def __init__(self, host: str = "localhost", port: int = 8765):
51
+ self.host = host
52
+ self.port = port
53
+ self.logger = get_logger(__name__ + ".SocketIOServer")
54
+ self.running = False
55
+ self.server_thread = None
56
+ self.loop = None
57
+ self.app = None
58
+ self.runner = None
59
+ self.site = None
60
+
61
+ # Socket.IO server instance
62
+ self.sio = None
63
+
64
+ # Connection tracking
65
+ self.connected_clients: Set[str] = set()
66
+ self.client_info: Dict[str, Dict[str, Any]] = {}
67
+
68
+ # Event buffering for reliability
69
+ self.event_buffer = deque(
70
+ maxlen=getattr(SystemLimits, "MAX_EVENTS_BUFFER", 1000)
71
+ )
72
+ self.buffer_lock = threading.Lock()
73
+
74
+ # Performance tracking
75
+ self.stats = {
76
+ "events_sent": 0,
77
+ "events_buffered": 0,
78
+ "connections_total": 0,
79
+ "start_time": None,
80
+ }
81
+
82
+ # Static files path
83
+ self.static_path = None
84
+
85
+ # Heartbeat task
86
+ self.heartbeat_task = None
87
+ self.heartbeat_interval = 60 # seconds
88
+ self.main_server = None # Reference to main server for session data
89
+
90
+ def start_sync(self):
91
+ """Start the Socket.IO server in a background thread (synchronous version)."""
92
+ if not SOCKETIO_AVAILABLE:
93
+ self.logger.warning("Socket.IO not available - server not started")
94
+ return
95
+
96
+ if self.running:
97
+ self.logger.warning("Socket.IO server already running")
98
+ return
99
+
100
+ self.logger.info(f"Starting Socket.IO server on {self.host}:{self.port}")
101
+
102
+ # Start server in background thread
103
+ self.server_thread = threading.Thread(target=self._run_server, daemon=True)
104
+ self.server_thread.start()
105
+
106
+ # Wait for server to start
107
+ max_wait = getattr(TimeoutConfig, "SERVER_START_TIMEOUT", 30)
108
+ wait_time = 0
109
+ while not self.running and wait_time < max_wait:
110
+ time.sleep(0.1)
111
+ wait_time += 0.1
112
+
113
+ if not self.running:
114
+ raise MPMConnectionError(
115
+ f"Failed to start Socket.IO server within {max_wait}s"
116
+ )
117
+
118
+ self.logger.info(
119
+ f"Socket.IO server started successfully on {self.host}:{self.port}"
120
+ )
121
+
122
+ def stop_sync(self):
123
+ """Stop the Socket.IO server (synchronous version)."""
124
+ if not self.running:
125
+ return
126
+
127
+ self.logger.info("Stopping Socket.IO server...")
128
+ self.running = False
129
+
130
+ # Stop the server gracefully
131
+ if self.loop and not self.loop.is_closed():
132
+ asyncio.run_coroutine_threadsafe(self._stop_server(), self.loop)
133
+
134
+ def _run_server(self):
135
+ """Run the server event loop."""
136
+ try:
137
+ # Create new event loop for this thread
138
+ # WHY: We create and assign the loop immediately to minimize the race
139
+ # condition window where other threads might try to access it.
140
+ self.loop = asyncio.new_event_loop()
141
+ asyncio.set_event_loop(self.loop)
142
+
143
+ self.logger.debug("Event loop created and set for background thread")
144
+
145
+ # Run the server
146
+ self.loop.run_until_complete(self._start_server())
147
+
148
+ except Exception as e:
149
+ self.logger.error(f"Socket.IO server error: {e}")
150
+ self.running = False
151
+ finally:
152
+ if self.loop and not self.loop.is_closed():
153
+ self.loop.close()
154
+
155
+ async def _start_server(self):
156
+ """Start the Socket.IO server with aiohttp."""
157
+ try:
158
+ # Import centralized configuration for consistency
159
+ from ....config.socketio_config import CONNECTION_CONFIG
160
+
161
+ # Create Socket.IO server with centralized configuration
162
+ # CRITICAL: These values MUST match client settings to prevent disconnections
163
+ self.sio = socketio.AsyncServer(
164
+ cors_allowed_origins="*",
165
+ logger=False, # Disable Socket.IO's own logging
166
+ engineio_logger=False,
167
+ ping_interval=CONNECTION_CONFIG[
168
+ "ping_interval"
169
+ ], # 45 seconds from config
170
+ ping_timeout=CONNECTION_CONFIG[
171
+ "ping_timeout"
172
+ ], # 20 seconds from config
173
+ max_http_buffer_size=CONNECTION_CONFIG[
174
+ "max_http_buffer_size"
175
+ ], # 100MB from config
176
+ )
177
+
178
+ # Create aiohttp application
179
+ self.app = web.Application()
180
+ self.sio.attach(self.app)
181
+
182
+ # CRITICAL: Register event handlers BEFORE starting the server
183
+ # This ensures handlers are ready when clients connect
184
+ if self.main_server and hasattr(self.main_server, "_register_events_async"):
185
+ self.logger.info(
186
+ "Registering Socket.IO event handlers before server start"
187
+ )
188
+ await self.main_server._register_events_async()
189
+ else:
190
+ self.logger.warning("Main server not available for event registration")
191
+
192
+ # Setup HTTP API endpoints for receiving events from hook handlers
193
+ self._setup_http_api()
194
+
195
+ # Setup simple directory API
196
+ self._setup_directory_api()
197
+
198
+ # Find and serve static files
199
+ self._setup_static_files()
200
+
201
+ # Create and start the server
202
+ self.runner = web.AppRunner(self.app)
203
+ await self.runner.setup()
204
+
205
+ self.site = web.TCPSite(
206
+ self.runner, self.host, self.port, reuse_address=True, reuse_port=True
207
+ )
208
+ await self.site.start()
209
+
210
+ self.running = True
211
+ self.stats["start_time"] = datetime.now(timezone.utc)
212
+
213
+ self.logger.info(
214
+ f"Socket.IO server listening on http://{self.host}:{self.port}"
215
+ )
216
+ if self.static_path:
217
+ self.logger.info(f"Serving static files from: {self.static_path}")
218
+
219
+ # Conditionally start heartbeat task based on configuration
220
+ from ....config.socketio_config import CONNECTION_CONFIG
221
+
222
+ if CONNECTION_CONFIG.get("enable_extra_heartbeat", False):
223
+ self.heartbeat_task = asyncio.create_task(self._heartbeat_loop())
224
+ self.logger.info("Started system heartbeat task")
225
+ else:
226
+ self.logger.info(
227
+ "System heartbeat disabled (using Socket.IO ping/pong instead)"
228
+ )
229
+
230
+ # Keep the server running
231
+ while self.running:
232
+ await asyncio.sleep(1)
233
+
234
+ except Exception as e:
235
+ self.logger.error(f"Failed to start Socket.IO server: {e}")
236
+ self.running = False
237
+ raise
238
+
239
+ async def _stop_server(self):
240
+ """Stop the server gracefully."""
241
+ try:
242
+ # Cancel heartbeat task
243
+ if self.heartbeat_task and not self.heartbeat_task.done():
244
+ self.heartbeat_task.cancel()
245
+ with contextlib.suppress(asyncio.CancelledError):
246
+ await self.heartbeat_task
247
+ self.logger.info("Stopped system heartbeat task")
248
+
249
+ if self.site:
250
+ await self.site.stop()
251
+ self.site = None
252
+
253
+ if self.runner:
254
+ await self.runner.cleanup()
255
+ self.runner = None
256
+
257
+ self.logger.info("Socket.IO server stopped")
258
+
259
+ except Exception as e:
260
+ self.logger.error(f"Error stopping Socket.IO server: {e}")
261
+
262
+ def _setup_http_api(self):
263
+ """Setup HTTP API endpoints for receiving events from hook handlers.
264
+
265
+ WHY: Hook handlers are ephemeral processes that spawn and die quickly.
266
+ Using HTTP POST allows them to send events without managing persistent
267
+ connections, eliminating disconnection issues.
268
+ """
269
+
270
+ async def api_events_handler(request):
271
+ """Handle POST /api/events from hook handlers."""
272
+ try:
273
+ # Parse JSON payload
274
+ payload = await request.json()
275
+
276
+ # Extract event data from payload (handles both direct and wrapped formats)
277
+ # ConnectionManagerService sends: {"namespace": "...", "event": "...", "data": {...}}
278
+ # Direct hook events may send data directly
279
+ # CRITICAL: Check if payload has the expected event structure (type, subtype, timestamp)
280
+ # If it does, use it directly. Only extract 'data' field if it's a wrapper object.
281
+ if "type" in payload and "subtype" in payload:
282
+ # Payload is already in normalized format, use it directly
283
+ event_data = payload
284
+ elif "data" in payload and isinstance(payload.get("data"), dict):
285
+ # Payload is a wrapper with 'data' field (from ConnectionManagerService)
286
+ event_data = payload["data"]
287
+ else:
288
+ # Fallback: use entire payload
289
+ event_data = payload
290
+
291
+ # Log receipt with more detail
292
+ event_type = (
293
+ event_data.get("subtype")
294
+ or event_data.get("hook_event_name")
295
+ or "unknown"
296
+ )
297
+ self.logger.info(f"📨 Received HTTP event: {event_type}")
298
+ self.logger.debug(f"Event data keys: {list(event_data.keys())}")
299
+ self.logger.debug(f"Connected clients: {len(self.connected_clients)}")
300
+
301
+ # Transform hook event format to claude_event format if needed
302
+ if "hook_event_name" in event_data and "event" not in event_data:
303
+ # This is a raw hook event, transform it
304
+ from claude_mpm.services.socketio.event_normalizer import (
305
+ EventNormalizer,
306
+ )
307
+
308
+ normalizer = EventNormalizer()
309
+
310
+ # Map hook event names to dashboard subtypes
311
+ # Comprehensive mapping of all known Claude Code hook event types
312
+ subtype_map = {
313
+ # User interaction events
314
+ "UserPromptSubmit": "user_prompt_submit",
315
+ "UserPromptCancel": "user_prompt_cancel",
316
+ # Tool execution events
317
+ "PreToolUse": "pre_tool_use",
318
+ "PostToolUse": "post_tool_use",
319
+ "ToolStart": "tool_start",
320
+ "ToolUse": "tool_use",
321
+ # Assistant events
322
+ "AssistantResponse": "assistant_response",
323
+ # Session lifecycle events
324
+ "Start": "start",
325
+ "Stop": "stop",
326
+ "SessionStart": "session_start",
327
+ # Subagent events
328
+ "SubagentStart": "subagent_start",
329
+ "SubagentStop": "subagent_stop",
330
+ "SubagentEvent": "subagent_event",
331
+ # Task events
332
+ "Task": "task",
333
+ "TaskStart": "task_start",
334
+ "TaskComplete": "task_complete",
335
+ # File operation events
336
+ "FileWrite": "file_write",
337
+ "Write": "write",
338
+ # System events
339
+ "Notification": "notification",
340
+ }
341
+
342
+ # Helper function to convert PascalCase to snake_case
343
+ def to_snake_case(name: str) -> str:
344
+ """Convert PascalCase event names to snake_case.
345
+
346
+ Examples:
347
+ UserPromptSubmit → user_prompt_submit
348
+ PreToolUse → pre_tool_use
349
+ TaskComplete → task_complete
350
+ """
351
+ import re
352
+
353
+ return re.sub(r"(?<!^)(?=[A-Z])", "_", name).lower()
354
+
355
+ # Get hook event name and map to subtype
356
+ hook_event_name = event_data.get("hook_event_name", "unknown")
357
+ subtype = subtype_map.get(
358
+ hook_event_name, to_snake_case(hook_event_name)
359
+ )
360
+
361
+ # Debug log for unmapped events to discover new event types
362
+ if (
363
+ hook_event_name not in subtype_map
364
+ and hook_event_name != "unknown"
365
+ ):
366
+ self.logger.debug(
367
+ f"Unmapped hook event: {hook_event_name} → {subtype}"
368
+ )
369
+
370
+ # Create the format expected by normalizer
371
+ raw_event = {
372
+ "type": "hook",
373
+ "subtype": subtype,
374
+ "timestamp": event_data.get("timestamp"),
375
+ "data": event_data.get("hook_input_data", {}),
376
+ "source": "claude_hooks",
377
+ "session_id": event_data.get("session_id"),
378
+ }
379
+
380
+ normalized = normalizer.normalize(raw_event, source="hook")
381
+ event_data = normalized.to_dict()
382
+ self.logger.debug(
383
+ f"Normalized event: type={event_data.get('type')}, subtype={event_data.get('subtype')}"
384
+ )
385
+
386
+ # Publish to EventBus for cross-component communication
387
+ # WHY: This allows other parts of the system to react to hook events
388
+ # without coupling to Socket.IO directly
389
+ try:
390
+ from claude_mpm.services.event_bus import EventBus
391
+
392
+ event_bus = EventBus.get_instance()
393
+ event_type = f"hook.{event_data.get('subtype', 'unknown')}"
394
+ event_bus.publish(event_type, event_data)
395
+ self.logger.debug(f"Published to EventBus: {event_type}")
396
+ except Exception as e:
397
+ # Non-fatal: EventBus publication failure shouldn't break event flow
398
+ self.logger.warning(f"Failed to publish to EventBus: {e}")
399
+
400
+ # Broadcast to all connected dashboard clients via SocketIO
401
+ if self.sio:
402
+ # CRITICAL: Use the main server's broadcaster for proper event handling
403
+ # The broadcaster handles retries, connection management, and buffering
404
+ if (
405
+ self.main_server
406
+ and hasattr(self.main_server, "broadcaster")
407
+ and self.main_server.broadcaster
408
+ ):
409
+ # The broadcaster expects raw event data and will normalize it
410
+ # Since we already normalized it, we need to pass it in a way that won't double-normalize
411
+ # We'll emit directly through the broadcaster's sio with proper handling
412
+
413
+ # Add to event buffer and history
414
+ with self.buffer_lock:
415
+ self.event_buffer.append(event_data)
416
+ self.stats["events_buffered"] = len(self.event_buffer)
417
+
418
+ # Add to main server's event history UNCONDITIONALLY
419
+ # WHY: event_history is always initialized in SocketIOServer.__init__
420
+ # This ensures events persist for new clients who connect later
421
+ if self.main_server and hasattr(
422
+ self.main_server, "event_history"
423
+ ):
424
+ self.main_server.event_history.append(event_data)
425
+ self.logger.debug(
426
+ f"Added to history (total: {len(self.main_server.event_history)})"
427
+ )
428
+ else:
429
+ # CRITICAL: Log warning if event_history is not available
430
+ # This indicates a configuration or initialization problem
431
+ self.logger.warning(
432
+ "event_history not initialized on main_server! "
433
+ "Events will not persist for new clients."
434
+ )
435
+
436
+ # Use the broadcaster's sio to emit (it's the same as self.sio)
437
+ # This ensures the event goes through the proper channels
438
+ await self.sio.emit("claude_event", event_data)
439
+
440
+ # Update broadcaster stats
441
+ if hasattr(self.main_server.broadcaster, "stats"):
442
+ self.main_server.broadcaster.stats["events_sent"] = (
443
+ self.main_server.broadcaster.stats.get("events_sent", 0)
444
+ + 1
445
+ )
446
+
447
+ self.logger.info(
448
+ f"✅ Event broadcasted: {event_data.get('subtype', 'unknown')} to {len(self.connected_clients)} clients"
449
+ )
450
+ self.logger.debug(
451
+ f"Connected client IDs: {list(self.connected_clients) if self.connected_clients else 'None'}"
452
+ )
453
+ else:
454
+ # Fallback: Direct emit if broadcaster not available (shouldn't happen)
455
+ self.logger.warning(
456
+ "Broadcaster not available, using direct emit"
457
+ )
458
+ await self.sio.emit("claude_event", event_data)
459
+
460
+ # Update stats manually if using fallback
461
+ self.stats["events_sent"] = self.stats.get("events_sent", 0) + 1
462
+
463
+ # Add to event buffer for late-joining clients
464
+ with self.buffer_lock:
465
+ self.event_buffer.append(event_data)
466
+ self.stats["events_buffered"] = len(self.event_buffer)
467
+
468
+ # Add to main server's event history (fallback path)
469
+ # WHY: Ensure events persist even when broadcaster is unavailable
470
+ if self.main_server and hasattr(
471
+ self.main_server, "event_history"
472
+ ):
473
+ self.main_server.event_history.append(event_data)
474
+ self.logger.debug(
475
+ f"Added to history via fallback (total: {len(self.main_server.event_history)})"
476
+ )
477
+ else:
478
+ self.logger.warning(
479
+ "event_history not initialized on main_server (fallback path)! "
480
+ "Events will not persist for new clients."
481
+ )
482
+
483
+ # Return 204 No Content for success
484
+ self.logger.debug(f"✅ HTTP event processed successfully: {event_type}")
485
+ return web.Response(status=204)
486
+
487
+ except Exception as e:
488
+ self.logger.error(f"Error handling HTTP event: {e}")
489
+ return web.Response(status=500, text=str(e))
490
+
491
+ # Register the HTTP POST endpoint
492
+ self.app.router.add_post("/api/events", api_events_handler)
493
+ self.logger.info("✅ HTTP API endpoint registered at /api/events")
494
+
495
+ # Add health check endpoint
496
+ async def health_handler(request):
497
+ """Handle GET /api/health for health checks."""
498
+ try:
499
+ # Get server status
500
+ uptime_seconds = 0
501
+ if self.stats.get("start_time"):
502
+ uptime_seconds = int(
503
+ (
504
+ datetime.now(timezone.utc) - self.stats["start_time"]
505
+ ).total_seconds()
506
+ )
507
+
508
+ health_data = {
509
+ "status": "healthy",
510
+ "service": "claude-mpm-socketio",
511
+ "timestamp": datetime.now(timezone.utc).isoformat(),
512
+ "uptime_seconds": uptime_seconds,
513
+ "connected_clients": len(self.connected_clients),
514
+ "total_events": self.stats.get("events_sent", 0),
515
+ "buffered_events": self.stats.get("events_buffered", 0),
516
+ }
517
+
518
+ return web.json_response(health_data)
519
+ except Exception as e:
520
+ self.logger.error(f"Error in health check: {e}")
521
+ return web.json_response(
522
+ {
523
+ "status": "unhealthy",
524
+ "service": "claude-mpm-socketio",
525
+ "error": str(e),
526
+ },
527
+ status=503,
528
+ )
529
+
530
+ self.app.router.add_get("/api/health", health_handler)
531
+ self.app.router.add_get("/health", health_handler) # Alias for convenience
532
+ self.logger.info(
533
+ "✅ Health check endpoints registered at /api/health and /health"
534
+ )
535
+
536
+ # Add working directory endpoint
537
+ async def working_directory_handler(request):
538
+ """Handle GET /api/working-directory to provide current working directory."""
539
+ from pathlib import Path
540
+
541
+ try:
542
+ working_dir = str(Path.cwd())
543
+ home_dir = str(Path.home())
544
+
545
+ return web.json_response(
546
+ {
547
+ "working_directory": working_dir,
548
+ "home_directory": home_dir,
549
+ "process_cwd": working_dir,
550
+ "session_id": getattr(self, "session_id", None),
551
+ }
552
+ )
553
+ except Exception as e:
554
+ self.logger.error(f"Error getting working directory: {e}")
555
+ return web.json_response(
556
+ {
557
+ "working_directory": "/Users/masa/Projects/claude-mpm",
558
+ "home_directory": "/Users/masa",
559
+ "error": str(e),
560
+ },
561
+ status=500,
562
+ )
563
+
564
+ self.app.router.add_get("/api/working-directory", working_directory_handler)
565
+ self.logger.info(
566
+ "✅ Working directory endpoint registered at /api/working-directory"
567
+ )
568
+
569
+ # Add file reading endpoint for source viewer
570
+ async def file_read_handler(request):
571
+ """Handle GET /api/file/read for reading source files."""
572
+
573
+ file_path = request.query.get("path", "")
574
+
575
+ if not file_path:
576
+ return web.json_response({"error": "No path provided"}, status=400)
577
+
578
+ abs_path = Path(Path(file_path).resolve().expanduser())
579
+
580
+ # Security check - ensure file is within the project
581
+ try:
582
+ project_root = Path.cwd()
583
+ if not abs_path.startswith(project_root):
584
+ return web.json_response({"error": "Access denied"}, status=403)
585
+ except Exception:
586
+ pass
587
+
588
+ if not Path(abs_path).exists():
589
+ return web.json_response({"error": "File not found"}, status=404)
590
+
591
+ if not Path(abs_path).is_file():
592
+ return web.json_response({"error": "Not a file"}, status=400)
593
+
594
+ try:
595
+ # Read file with appropriate encoding
596
+ encodings = ["utf-8", "latin-1", "cp1252"]
597
+ content = None
598
+
599
+ for encoding in encodings:
600
+ try:
601
+ with Path(abs_path).open(
602
+ encoding=encoding,
603
+ ) as f:
604
+ content = f.read()
605
+ break
606
+ except UnicodeDecodeError:
607
+ continue
608
+
609
+ if content is None:
610
+ return web.json_response(
611
+ {"error": "Could not decode file"}, status=400
612
+ )
613
+
614
+ return web.json_response(
615
+ {
616
+ "path": abs_path,
617
+ "name": Path(abs_path).name,
618
+ "content": content,
619
+ "lines": len(content.splitlines()),
620
+ "size": Path(abs_path).stat().st_size,
621
+ }
622
+ )
623
+
624
+ except PermissionError:
625
+ return web.json_response({"error": "Permission denied"}, status=403)
626
+ except Exception as e:
627
+ return web.json_response({"error": str(e)}, status=500)
628
+
629
+ self.app.router.add_get("/api/file/read", file_read_handler)
630
+ self.logger.info("✅ File reading API registered at /api/file/read")
631
+
632
+ # Add files listing endpoint for file browser
633
+ async def files_list_handler(request):
634
+ """Handle GET /api/files for listing files in working directory."""
635
+
636
+ try:
637
+ # Get working directory from query params or use current directory
638
+ working_dir = request.query.get("path", str(Path.cwd()))
639
+ abs_working_dir = Path(working_dir).resolve().expanduser()
640
+
641
+ # Security check - ensure directory is accessible
642
+ if not abs_working_dir.exists():
643
+ return web.json_response(
644
+ {"error": "Directory not found"}, status=404
645
+ )
646
+
647
+ if not abs_working_dir.is_dir():
648
+ return web.json_response(
649
+ {"error": "Path is not a directory"}, status=400
650
+ )
651
+
652
+ # Collect files and directories
653
+ files = []
654
+ directories = []
655
+
656
+ # Common patterns to exclude
657
+ exclude_patterns = {
658
+ ".git",
659
+ ".venv",
660
+ "venv",
661
+ "node_modules",
662
+ "__pycache__",
663
+ ".pytest_cache",
664
+ ".mypy_cache",
665
+ "dist",
666
+ "build",
667
+ ".next",
668
+ "coverage",
669
+ ".coverage",
670
+ ".tox",
671
+ ".eggs",
672
+ "*.egg-info",
673
+ }
674
+
675
+ for entry in abs_working_dir.iterdir():
676
+ # Skip hidden files and excluded patterns
677
+ if entry.name.startswith("."):
678
+ # Allow .py, .ts, .md, etc. files but skip directories like .git
679
+ if entry.is_dir():
680
+ continue
681
+
682
+ # Skip excluded directories
683
+ if entry.name in exclude_patterns:
684
+ continue
685
+
686
+ try:
687
+ stat_info = entry.stat()
688
+ entry_data = {
689
+ "name": entry.name,
690
+ "path": str(entry),
691
+ "type": "directory" if entry.is_dir() else "file",
692
+ "size": stat_info.st_size if entry.is_file() else 0,
693
+ "modified": stat_info.st_mtime,
694
+ }
695
+
696
+ if entry.is_dir():
697
+ directories.append(entry_data)
698
+ else:
699
+ # Add file extension for syntax highlighting
700
+ entry_data["extension"] = entry.suffix.lower()
701
+ files.append(entry_data)
702
+ except (PermissionError, OSError):
703
+ # Skip files we can't access
704
+ continue
705
+
706
+ # Sort directories and files alphabetically
707
+ directories.sort(key=lambda x: x["name"].lower())
708
+ files.sort(key=lambda x: x["name"].lower())
709
+
710
+ return web.json_response(
711
+ {
712
+ "success": True,
713
+ "path": str(abs_working_dir),
714
+ "directories": directories,
715
+ "files": files,
716
+ "total_files": len(files),
717
+ "total_directories": len(directories),
718
+ }
719
+ )
720
+
721
+ except Exception as e:
722
+ self.logger.error(f"Error listing files: {e}")
723
+ return web.json_response({"error": str(e)}, status=500)
724
+
725
+ self.app.router.add_get("/api/files", files_list_handler)
726
+ self.logger.info("✅ Files listing API registered at /api/files")
727
+
728
+ # Add git history endpoint
729
+ async def git_history_handler(request):
730
+ """Handle POST /api/git-history for getting file git history."""
731
+ import subprocess
732
+
733
+ try:
734
+ # Parse JSON body
735
+ data = await request.json()
736
+ file_path = data.get("path", "")
737
+ limit = data.get("limit", 10)
738
+
739
+ if not file_path:
740
+ return web.json_response(
741
+ {"success": False, "error": "No path provided", "commits": []},
742
+ status=400,
743
+ )
744
+
745
+ abs_path = Path(Path(file_path).resolve().expanduser())
746
+
747
+ if not Path(abs_path).exists():
748
+ return web.json_response(
749
+ {"success": False, "error": "File not found", "commits": []},
750
+ status=404,
751
+ )
752
+
753
+ # Get git log for file
754
+ result = subprocess.run(
755
+ [
756
+ "git",
757
+ "log",
758
+ f"-{limit}",
759
+ "--pretty=format:%H|%an|%ar|%s",
760
+ "--",
761
+ abs_path,
762
+ ],
763
+ check=False,
764
+ capture_output=True,
765
+ text=True,
766
+ cwd=Path(abs_path).parent,
767
+ )
768
+
769
+ commits = []
770
+ if result.returncode == 0 and result.stdout:
771
+ for line in result.stdout.strip().split("\n"):
772
+ if line:
773
+ parts = line.split("|", 3)
774
+ if len(parts) == 4:
775
+ commits.append(
776
+ {
777
+ "hash": parts[0][:7], # Short hash
778
+ "author": parts[1],
779
+ "date": parts[2],
780
+ "message": parts[3],
781
+ }
782
+ )
783
+
784
+ return web.json_response({"success": True, "commits": commits})
785
+
786
+ except Exception as e:
787
+ self.logger.error(f"Error getting git history: {e}")
788
+ return web.json_response(
789
+ {"success": False, "error": str(e), "commits": []}, status=500
790
+ )
791
+
792
+ self.app.router.add_post("/api/git-history", git_history_handler)
793
+ self.logger.info("✅ Git history API registered at /api/git-history")
794
+
795
+ def _setup_directory_api(self):
796
+ """Setup simple directory listing API.
797
+
798
+ WHY: Provides a dead-simple way to list directory contents via HTTP GET
799
+ without complex WebSocket interactions.
800
+ """
801
+ try:
802
+ from claude_mpm.dashboard.api.simple_directory import register_routes
803
+
804
+ register_routes(self.app)
805
+ self.logger.info(
806
+ "✅ Simple directory API registered at /api/directory/list"
807
+ )
808
+ except Exception as e:
809
+ self.logger.error(f"Failed to setup directory API: {e}")
810
+
811
+ def _setup_static_files(self):
812
+ """Setup static file serving for the Svelte dashboard."""
813
+ try:
814
+ # Add debug logging for deployment context
815
+ try:
816
+ from ....core.unified_paths import PathContext
817
+
818
+ deployment_context = PathContext.detect_deployment_context()
819
+ self.logger.debug(
820
+ f"Setting up static files in {deployment_context.value} mode"
821
+ )
822
+ except Exception as e:
823
+ self.logger.debug(f"Could not detect deployment context: {e}")
824
+
825
+ # Find Svelte build directory
826
+ svelte_build_path = self._find_static_path()
827
+
828
+ if svelte_build_path and svelte_build_path.exists():
829
+ self.logger.info(f"✅ Svelte dashboard found at: {svelte_build_path}")
830
+ self.dashboard_path = svelte_build_path
831
+
832
+ # Serve Svelte index.html at root
833
+ async def index_handler(request):
834
+ index_file = svelte_build_path / "index.html"
835
+ if index_file.exists():
836
+ self.logger.debug(
837
+ f"Serving Svelte dashboard from: {index_file}"
838
+ )
839
+ return web.FileResponse(index_file)
840
+ self.logger.warning(f"Svelte index.html not found at: {index_file}")
841
+ return web.Response(text="Dashboard not available", status=404)
842
+
843
+ self.app.router.add_get("/", index_handler)
844
+
845
+ # Serve Svelte app assets at /_app/ (needed for SvelteKit builds)
846
+ svelte_app_path = svelte_build_path / "_app"
847
+ if svelte_app_path.exists():
848
+ self.app.router.add_static(
849
+ "/_app/", svelte_app_path, name="svelte_app"
850
+ )
851
+ self.logger.info(
852
+ f"✅ Svelte dashboard available at http://{self.host}:{self.port}/ (build: {svelte_build_path})"
853
+ )
854
+ else:
855
+ self.logger.warning(
856
+ f"⚠️ Svelte _app directory not found at: {svelte_app_path}"
857
+ )
858
+
859
+ # Serve version.json from Svelte build directory
860
+ async def version_handler(request):
861
+ version_file = svelte_build_path / "version.json"
862
+ if version_file.exists():
863
+ self.logger.debug(f"Serving version.json from: {version_file}")
864
+ return web.FileResponse(version_file)
865
+ # Return default version info if file doesn't exist
866
+ return web.json_response(
867
+ {
868
+ "version": "1.0.0",
869
+ "build": 1,
870
+ "formatted_build": "0001",
871
+ "full_version": "v1.0.0-0001",
872
+ }
873
+ )
874
+
875
+ self.app.router.add_get("/version.json", version_handler)
876
+
877
+ else:
878
+ self.logger.warning(
879
+ "⚠️ Svelte dashboard not found, serving fallback response"
880
+ )
881
+
882
+ # Fallback handler
883
+ async def fallback_handler(request):
884
+ return web.Response(
885
+ text="Socket.IO server running - Dashboard not available",
886
+ status=200,
887
+ )
888
+
889
+ self.app.router.add_get("/", fallback_handler)
890
+
891
+ except Exception as e:
892
+ self.logger.error(f"❌ Error setting up static files: {e}")
893
+ import traceback
894
+
895
+ self.logger.debug(f"Static file setup traceback: {traceback.format_exc()}")
896
+
897
+ # Ensure we always have a basic handler
898
+ async def error_handler(request):
899
+ return web.Response(
900
+ text="Socket.IO server running - Static files unavailable",
901
+ status=200,
902
+ )
903
+
904
+ self.app.router.add_get("/", error_handler)
905
+
906
+ def _find_static_path(self):
907
+ """Find the Svelte build directory using multiple approaches.
908
+
909
+ WHY: The dashboard is now pure Svelte, located at dashboard/static/svelte-build/.
910
+ We search for this specific structure across different deployment contexts.
911
+ """
912
+ # Get deployment-context-aware paths
913
+ try:
914
+ from ....core.unified_paths import get_path_manager
915
+
916
+ path_manager = get_path_manager()
917
+
918
+ # Use package root for installed packages (including pipx)
919
+ package_root = path_manager.package_root
920
+ self.logger.debug(f"Package root: {package_root}")
921
+
922
+ # Use project root for development
923
+ project_root = get_project_root()
924
+ self.logger.debug(f"Project root: {project_root}")
925
+
926
+ except Exception as e:
927
+ self.logger.debug(f"Could not get path manager: {e}")
928
+ package_root = None
929
+ project_root = get_project_root()
930
+
931
+ # Try multiple possible locations for Svelte build directory
932
+ possible_paths = [
933
+ # Package-based paths (for pipx and pip installations)
934
+ package_root / "dashboard" / "static" / "svelte-build"
935
+ if package_root
936
+ else None,
937
+ # Project-based paths (for development)
938
+ project_root
939
+ / "src"
940
+ / "claude_mpm"
941
+ / "dashboard"
942
+ / "static"
943
+ / "svelte-build",
944
+ project_root / "dashboard" / "static" / "svelte-build",
945
+ # Package installation locations (fallback)
946
+ Path(__file__).parent.parent.parent
947
+ / "dashboard"
948
+ / "static"
949
+ / "svelte-build",
950
+ # Scripts directory (for standalone installations)
951
+ get_scripts_dir() / "dashboard" / "static" / "svelte-build",
952
+ # Current working directory
953
+ Path.cwd() / "src" / "claude_mpm" / "dashboard" / "static" / "svelte-build",
954
+ Path.cwd() / "dashboard" / "static" / "svelte-build",
955
+ ]
956
+
957
+ # Filter out None values
958
+ possible_paths = [p for p in possible_paths if p is not None]
959
+ self.logger.debug(
960
+ f"Searching {len(possible_paths)} possible Svelte build locations"
961
+ )
962
+
963
+ for path in possible_paths:
964
+ self.logger.debug(f"Checking for Svelte build at: {path}")
965
+ try:
966
+ if path.exists() and path.is_dir():
967
+ # Check if it contains expected Svelte build files
968
+ if (path / "index.html").exists():
969
+ self.logger.info(f"✅ Found Svelte build at: {path}")
970
+ return path
971
+ self.logger.debug(f"Directory exists but no index.html: {path}")
972
+ else:
973
+ self.logger.debug(f"Path does not exist: {path}")
974
+ except Exception as e:
975
+ self.logger.debug(f"Error checking path {path}: {e}")
976
+
977
+ self.logger.warning(
978
+ "⚠️ Svelte build not found - dashboard will not be available"
979
+ )
980
+ self.logger.debug(f"Searched paths: {[str(p) for p in possible_paths]}")
981
+ return None
982
+
983
+ def get_connection_count(self) -> int:
984
+ """Get number of connected clients.
985
+
986
+ WHY: Provides interface compliance for monitoring.
987
+
988
+ Returns:
989
+ Number of connected clients
990
+ """
991
+ return len(self.connected_clients)
992
+
993
+ def is_running(self) -> bool:
994
+ """Check if server is running.
995
+
996
+ WHY: Provides interface compliance for status checking.
997
+
998
+ Returns:
999
+ True if server is active
1000
+ """
1001
+ return self.running
1002
+
1003
+ async def _heartbeat_loop(self):
1004
+ """Send periodic heartbeat events to connected clients.
1005
+
1006
+ WHY: This provides a way to verify the event flow is working and
1007
+ track server health and active sessions without relying on hook events.
1008
+ """
1009
+ while self.running:
1010
+ try:
1011
+ # Wait for the interval
1012
+ await asyncio.sleep(self.heartbeat_interval)
1013
+
1014
+ if not self.sio:
1015
+ continue
1016
+
1017
+ # Calculate uptime
1018
+ uptime_seconds = 0
1019
+ if self.stats.get("start_time"):
1020
+ uptime_seconds = int(
1021
+ (
1022
+ datetime.now(timezone.utc) - self.stats["start_time"]
1023
+ ).total_seconds()
1024
+ )
1025
+
1026
+ # Get active sessions from main server if available
1027
+ active_sessions = []
1028
+ if self.main_server and hasattr(
1029
+ self.main_server, "get_active_sessions"
1030
+ ):
1031
+ try:
1032
+ active_sessions = self.main_server.get_active_sessions()
1033
+ except Exception as e:
1034
+ self.logger.debug(f"Could not get active sessions: {e}")
1035
+
1036
+ # Prepare heartbeat data (using new schema)
1037
+ heartbeat_data = {
1038
+ "type": "system",
1039
+ "subtype": "heartbeat",
1040
+ "timestamp": datetime.now(timezone.utc).isoformat(),
1041
+ "source": "server",
1042
+ "data": {
1043
+ "uptime_seconds": uptime_seconds,
1044
+ "connected_clients": len(self.connected_clients),
1045
+ "total_events": self.stats.get("events_sent", 0),
1046
+ "active_sessions": active_sessions,
1047
+ "server_info": {
1048
+ "version": VersionService().get_version(),
1049
+ "port": self.port,
1050
+ },
1051
+ },
1052
+ }
1053
+
1054
+ # Add to event history UNCONDITIONALLY
1055
+ # WHY: Heartbeat events should persist for new clients too
1056
+ if self.main_server and hasattr(self.main_server, "event_history"):
1057
+ self.main_server.event_history.append(heartbeat_data)
1058
+ self.logger.debug(
1059
+ f"Heartbeat added to history (total: {len(self.main_server.event_history)})"
1060
+ )
1061
+ else:
1062
+ self.logger.warning("event_history not initialized for heartbeat!")
1063
+
1064
+ # Emit heartbeat to all connected clients (already using new schema)
1065
+ await self.sio.emit("system_event", heartbeat_data)
1066
+
1067
+ self.logger.info(
1068
+ f"System heartbeat sent - clients: {len(self.connected_clients)}, "
1069
+ f"uptime: {uptime_seconds}s, events: {self.stats.get('events_sent', 0)}, "
1070
+ f"sessions: {len(active_sessions)}"
1071
+ )
1072
+
1073
+ except asyncio.CancelledError:
1074
+ # Task was cancelled, exit gracefully
1075
+ break
1076
+ except Exception as e:
1077
+ self.logger.error(f"Error in heartbeat loop: {e}")
1078
+ # Continue running even if one heartbeat fails
1079
+ await asyncio.sleep(5) # Short delay before retry