claude-mpm 5.4.41__py3-none-any.whl → 5.6.72__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (490) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
  3. claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
  4. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +161 -298
  6. claude_mpm/agents/WORKFLOW.md +2 -0
  7. claude_mpm/agents/templates/circuit-breakers.md +26 -17
  8. claude_mpm/auth/__init__.py +35 -0
  9. claude_mpm/auth/callback_server.py +328 -0
  10. claude_mpm/auth/models.py +104 -0
  11. claude_mpm/auth/oauth_manager.py +266 -0
  12. claude_mpm/auth/providers/__init__.py +12 -0
  13. claude_mpm/auth/providers/base.py +165 -0
  14. claude_mpm/auth/providers/google.py +261 -0
  15. claude_mpm/auth/token_storage.py +252 -0
  16. claude_mpm/cli/__init__.py +5 -1
  17. claude_mpm/cli/commands/agents.py +2 -4
  18. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  19. claude_mpm/cli/commands/autotodos.py +566 -0
  20. claude_mpm/cli/commands/commander.py +216 -0
  21. claude_mpm/cli/commands/configure.py +620 -21
  22. claude_mpm/cli/commands/configure_agent_display.py +3 -1
  23. claude_mpm/cli/commands/hook_errors.py +60 -60
  24. claude_mpm/cli/commands/mcp.py +29 -17
  25. claude_mpm/cli/commands/mcp_command_router.py +39 -0
  26. claude_mpm/cli/commands/mcp_service_commands.py +304 -0
  27. claude_mpm/cli/commands/monitor.py +2 -2
  28. claude_mpm/cli/commands/mpm_init/core.py +15 -8
  29. claude_mpm/cli/commands/oauth.py +481 -0
  30. claude_mpm/cli/commands/profile.py +9 -10
  31. claude_mpm/cli/commands/run.py +35 -3
  32. claude_mpm/cli/commands/skill_source.py +51 -2
  33. claude_mpm/cli/commands/skills.py +182 -32
  34. claude_mpm/cli/executor.py +129 -16
  35. claude_mpm/cli/helpers.py +1 -1
  36. claude_mpm/cli/interactive/__init__.py +10 -0
  37. claude_mpm/cli/interactive/agent_wizard.py +30 -50
  38. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  39. claude_mpm/cli/interactive/skill_selector.py +481 -0
  40. claude_mpm/cli/parsers/base_parser.py +89 -1
  41. claude_mpm/cli/parsers/commander_parser.py +116 -0
  42. claude_mpm/cli/parsers/mcp_parser.py +79 -0
  43. claude_mpm/cli/parsers/oauth_parser.py +165 -0
  44. claude_mpm/cli/parsers/profile_parser.py +0 -1
  45. claude_mpm/cli/parsers/run_parser.py +10 -0
  46. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  47. claude_mpm/cli/parsers/skills_parser.py +2 -3
  48. claude_mpm/cli/startup.py +662 -524
  49. claude_mpm/cli/startup_display.py +76 -7
  50. claude_mpm/cli/startup_logging.py +2 -2
  51. claude_mpm/cli/utils.py +7 -3
  52. claude_mpm/commander/__init__.py +78 -0
  53. claude_mpm/commander/adapters/__init__.py +60 -0
  54. claude_mpm/commander/adapters/auggie.py +260 -0
  55. claude_mpm/commander/adapters/base.py +288 -0
  56. claude_mpm/commander/adapters/claude_code.py +392 -0
  57. claude_mpm/commander/adapters/codex.py +237 -0
  58. claude_mpm/commander/adapters/communication.py +366 -0
  59. claude_mpm/commander/adapters/example_usage.py +310 -0
  60. claude_mpm/commander/adapters/mpm.py +389 -0
  61. claude_mpm/commander/adapters/registry.py +204 -0
  62. claude_mpm/commander/api/__init__.py +16 -0
  63. claude_mpm/commander/api/app.py +121 -0
  64. claude_mpm/commander/api/errors.py +133 -0
  65. claude_mpm/commander/api/routes/__init__.py +8 -0
  66. claude_mpm/commander/api/routes/events.py +184 -0
  67. claude_mpm/commander/api/routes/inbox.py +171 -0
  68. claude_mpm/commander/api/routes/messages.py +148 -0
  69. claude_mpm/commander/api/routes/projects.py +271 -0
  70. claude_mpm/commander/api/routes/sessions.py +226 -0
  71. claude_mpm/commander/api/routes/work.py +296 -0
  72. claude_mpm/commander/api/schemas.py +186 -0
  73. claude_mpm/commander/chat/__init__.py +7 -0
  74. claude_mpm/commander/chat/cli.py +149 -0
  75. claude_mpm/commander/chat/commands.py +122 -0
  76. claude_mpm/commander/chat/repl.py +1821 -0
  77. claude_mpm/commander/config.py +51 -0
  78. claude_mpm/commander/config_loader.py +115 -0
  79. claude_mpm/commander/core/__init__.py +10 -0
  80. claude_mpm/commander/core/block_manager.py +325 -0
  81. claude_mpm/commander/core/response_manager.py +323 -0
  82. claude_mpm/commander/daemon.py +603 -0
  83. claude_mpm/commander/env_loader.py +59 -0
  84. claude_mpm/commander/events/__init__.py +26 -0
  85. claude_mpm/commander/events/manager.py +392 -0
  86. claude_mpm/commander/frameworks/__init__.py +12 -0
  87. claude_mpm/commander/frameworks/base.py +233 -0
  88. claude_mpm/commander/frameworks/claude_code.py +58 -0
  89. claude_mpm/commander/frameworks/mpm.py +57 -0
  90. claude_mpm/commander/git/__init__.py +5 -0
  91. claude_mpm/commander/git/worktree_manager.py +212 -0
  92. claude_mpm/commander/inbox/__init__.py +16 -0
  93. claude_mpm/commander/inbox/dedup.py +128 -0
  94. claude_mpm/commander/inbox/inbox.py +224 -0
  95. claude_mpm/commander/inbox/models.py +70 -0
  96. claude_mpm/commander/instance_manager.py +865 -0
  97. claude_mpm/commander/llm/__init__.py +6 -0
  98. claude_mpm/commander/llm/openrouter_client.py +167 -0
  99. claude_mpm/commander/llm/summarizer.py +70 -0
  100. claude_mpm/commander/memory/__init__.py +45 -0
  101. claude_mpm/commander/memory/compression.py +347 -0
  102. claude_mpm/commander/memory/embeddings.py +230 -0
  103. claude_mpm/commander/memory/entities.py +310 -0
  104. claude_mpm/commander/memory/example_usage.py +290 -0
  105. claude_mpm/commander/memory/integration.py +325 -0
  106. claude_mpm/commander/memory/search.py +381 -0
  107. claude_mpm/commander/memory/store.py +657 -0
  108. claude_mpm/commander/models/__init__.py +18 -0
  109. claude_mpm/commander/models/events.py +127 -0
  110. claude_mpm/commander/models/project.py +162 -0
  111. claude_mpm/commander/models/work.py +214 -0
  112. claude_mpm/commander/parsing/__init__.py +20 -0
  113. claude_mpm/commander/parsing/extractor.py +132 -0
  114. claude_mpm/commander/parsing/output_parser.py +270 -0
  115. claude_mpm/commander/parsing/patterns.py +100 -0
  116. claude_mpm/commander/persistence/__init__.py +11 -0
  117. claude_mpm/commander/persistence/event_store.py +274 -0
  118. claude_mpm/commander/persistence/state_store.py +403 -0
  119. claude_mpm/commander/persistence/work_store.py +164 -0
  120. claude_mpm/commander/polling/__init__.py +13 -0
  121. claude_mpm/commander/polling/event_detector.py +104 -0
  122. claude_mpm/commander/polling/output_buffer.py +49 -0
  123. claude_mpm/commander/polling/output_poller.py +153 -0
  124. claude_mpm/commander/project_session.py +268 -0
  125. claude_mpm/commander/proxy/__init__.py +12 -0
  126. claude_mpm/commander/proxy/formatter.py +89 -0
  127. claude_mpm/commander/proxy/output_handler.py +191 -0
  128. claude_mpm/commander/proxy/relay.py +155 -0
  129. claude_mpm/commander/registry.py +410 -0
  130. claude_mpm/commander/runtime/__init__.py +10 -0
  131. claude_mpm/commander/runtime/executor.py +191 -0
  132. claude_mpm/commander/runtime/monitor.py +346 -0
  133. claude_mpm/commander/session/__init__.py +6 -0
  134. claude_mpm/commander/session/context.py +81 -0
  135. claude_mpm/commander/session/manager.py +59 -0
  136. claude_mpm/commander/tmux_orchestrator.py +362 -0
  137. claude_mpm/commander/web/__init__.py +1 -0
  138. claude_mpm/commander/work/__init__.py +30 -0
  139. claude_mpm/commander/work/executor.py +207 -0
  140. claude_mpm/commander/work/queue.py +405 -0
  141. claude_mpm/commander/workflow/__init__.py +27 -0
  142. claude_mpm/commander/workflow/event_handler.py +241 -0
  143. claude_mpm/commander/workflow/notifier.py +146 -0
  144. claude_mpm/commands/mpm-config.md +8 -0
  145. claude_mpm/commands/mpm-doctor.md +8 -0
  146. claude_mpm/commands/mpm-help.md +8 -0
  147. claude_mpm/commands/mpm-init.md +8 -0
  148. claude_mpm/commands/mpm-monitor.md +8 -0
  149. claude_mpm/commands/mpm-organize.md +8 -0
  150. claude_mpm/commands/mpm-postmortem.md +8 -0
  151. claude_mpm/commands/mpm-session-resume.md +9 -1
  152. claude_mpm/commands/mpm-status.md +8 -0
  153. claude_mpm/commands/mpm-ticket-view.md +8 -0
  154. claude_mpm/commands/mpm-version.md +8 -0
  155. claude_mpm/commands/mpm.md +8 -0
  156. claude_mpm/config/agent_presets.py +8 -7
  157. claude_mpm/config/skill_sources.py +16 -0
  158. claude_mpm/constants.py +6 -0
  159. claude_mpm/core/claude_runner.py +154 -2
  160. claude_mpm/core/config.py +35 -22
  161. claude_mpm/core/config_constants.py +74 -9
  162. claude_mpm/core/constants.py +56 -12
  163. claude_mpm/core/hook_manager.py +53 -4
  164. claude_mpm/core/interactive_session.py +12 -11
  165. claude_mpm/core/logger.py +26 -9
  166. claude_mpm/core/logging_utils.py +39 -13
  167. claude_mpm/core/network_config.py +148 -0
  168. claude_mpm/core/oneshot_session.py +7 -6
  169. claude_mpm/core/optimized_startup.py +3 -1
  170. claude_mpm/core/output_style_manager.py +66 -18
  171. claude_mpm/core/shared/config_loader.py +3 -1
  172. claude_mpm/core/socketio_pool.py +47 -15
  173. claude_mpm/core/unified_config.py +54 -8
  174. claude_mpm/core/unified_paths.py +95 -90
  175. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  176. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  177. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
  178. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
  179. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
  180. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
  181. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
  182. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
  184. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
  185. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  186. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
  187. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
  188. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
  189. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
  190. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
  191. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
  192. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  193. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  194. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
  195. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
  196. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
  197. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
  198. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
  199. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
  200. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
  201. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
  202. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  203. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
  204. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
  205. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
  206. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  207. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
  208. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  209. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
  210. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
  211. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
  212. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
  213. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
  214. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → DR8nis88.js} +2 -2
  215. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
  216. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  217. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
  218. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
  219. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
  220. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
  221. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
  222. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
  223. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  224. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
  225. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  226. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
  227. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
  228. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
  229. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
  230. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  231. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
  232. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
  233. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
  234. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
  235. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  236. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.RgBboRvH.js} +1 -1
  237. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
  238. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  239. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
  240. claude_mpm/dashboard/static/svelte-build/index.html +11 -11
  241. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  242. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  243. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  244. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  245. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  246. claude_mpm/experimental/cli_enhancements.py +2 -1
  247. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  248. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  249. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  250. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  251. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  252. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  253. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  254. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
  255. claude_mpm/hooks/claude_hooks/event_handlers.py +466 -136
  256. claude_mpm/hooks/claude_hooks/hook_handler.py +204 -104
  257. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  258. claude_mpm/hooks/claude_hooks/installer.py +291 -59
  259. claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
  260. claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
  261. claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
  262. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  263. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  264. claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
  265. claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
  266. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  267. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  268. claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
  269. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
  270. claude_mpm/hooks/claude_hooks/services/container.py +326 -0
  271. claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
  272. claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
  273. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
  274. claude_mpm/hooks/kuzu_memory_hook.py +5 -5
  275. claude_mpm/hooks/session_resume_hook.py +89 -1
  276. claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
  277. claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
  278. claude_mpm/init.py +224 -4
  279. claude_mpm/mcp/__init__.py +9 -0
  280. claude_mpm/mcp/google_workspace_server.py +610 -0
  281. claude_mpm/scripts/claude-hook-handler.sh +46 -19
  282. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  283. claude_mpm/services/agents/agent_selection_service.py +2 -2
  284. claude_mpm/services/agents/cache_git_manager.py +1 -1
  285. claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -1
  286. claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
  287. claude_mpm/services/agents/deployment/agent_template_builder.py +37 -17
  288. claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
  289. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  290. claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
  291. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +36 -8
  292. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +50 -26
  293. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  294. claude_mpm/services/agents/git_source_manager.py +21 -2
  295. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  296. claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
  297. claude_mpm/services/agents/sources/git_source_sync_service.py +116 -5
  298. claude_mpm/services/agents/startup_sync.py +5 -2
  299. claude_mpm/services/cli/__init__.py +3 -0
  300. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  301. claude_mpm/services/cli/session_resume_helper.py +10 -2
  302. claude_mpm/services/command_deployment_service.py +44 -26
  303. claude_mpm/services/delegation_detector.py +175 -0
  304. claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
  305. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  306. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  307. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  308. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  309. claude_mpm/services/diagnostics/models.py +14 -1
  310. claude_mpm/services/event_log.py +325 -0
  311. claude_mpm/services/hook_installer_service.py +77 -8
  312. claude_mpm/services/infrastructure/__init__.py +4 -0
  313. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  314. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  315. claude_mpm/services/mcp_config_manager.py +99 -19
  316. claude_mpm/services/mcp_service_registry.py +294 -0
  317. claude_mpm/services/monitor/daemon_manager.py +15 -4
  318. claude_mpm/services/monitor/management/lifecycle.py +8 -3
  319. claude_mpm/services/monitor/server.py +111 -16
  320. claude_mpm/services/pm_skills_deployer.py +302 -94
  321. claude_mpm/services/profile_manager.py +10 -4
  322. claude_mpm/services/skills/git_skill_source_manager.py +192 -29
  323. claude_mpm/services/skills/selective_skill_deployer.py +211 -46
  324. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  325. claude_mpm/services/skills_deployer.py +192 -70
  326. claude_mpm/services/socketio/handlers/hook.py +14 -7
  327. claude_mpm/services/socketio/server/main.py +12 -4
  328. claude_mpm/skills/__init__.py +2 -1
  329. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  330. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  331. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  332. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  333. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  334. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  335. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  336. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  337. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  338. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  339. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  340. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  341. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  342. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  343. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  344. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  345. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  346. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  347. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  348. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  349. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  350. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  351. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  352. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  353. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  354. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  355. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  356. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  357. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  358. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  359. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  360. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  361. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  362. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  363. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  364. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  365. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  366. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  367. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  368. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  369. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  370. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  371. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  372. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  373. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  374. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  375. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  376. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  377. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  378. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  379. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  380. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  381. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  382. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  383. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  384. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  385. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  386. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  387. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  388. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  389. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  390. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  391. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  392. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  393. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  394. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  395. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  396. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  397. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  398. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  399. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  400. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  401. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  402. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  403. claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
  404. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  405. claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
  406. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  407. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  408. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  409. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  410. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  411. claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
  412. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  413. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  414. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  415. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  416. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  417. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  418. claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
  419. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  420. claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
  421. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  422. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  423. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  424. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  425. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  426. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  427. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  428. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  429. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  430. claude_mpm/skills/bundled/security-scanning.md +112 -0
  431. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  432. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  433. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  434. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  435. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  436. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  437. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  438. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  439. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  440. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  441. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  442. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  443. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  444. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  445. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  446. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  447. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  448. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  449. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  450. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  451. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  452. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  453. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  454. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  455. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  456. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  457. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  458. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  459. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  460. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  461. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  462. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  463. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  464. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  465. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  466. claude_mpm/skills/registry.py +295 -90
  467. claude_mpm/skills/skill_manager.py +29 -23
  468. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  469. claude_mpm/utils/agent_dependency_loader.py +103 -4
  470. claude_mpm/utils/robust_installer.py +45 -24
  471. claude_mpm-5.6.72.dist-info/METADATA +416 -0
  472. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/RECORD +477 -159
  473. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/WHEEL +1 -1
  474. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/entry_points.txt +2 -0
  475. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
  476. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
  477. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
  478. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
  479. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +0 -1
  480. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
  481. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
  482. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
  483. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
  484. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
  485. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  486. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  487. claude_mpm-5.4.41.dist-info/METADATA +0 -998
  488. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE +0 -0
  489. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  490. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,362 @@
1
+ """Tmux orchestration layer for MPM Commander.
2
+
3
+ This module wraps tmux commands to manage sessions, panes, and I/O for
4
+ coordinating multiple project-level MPM instances.
5
+ """
6
+
7
+ import logging
8
+ import shutil
9
+ import subprocess # nosec B404 - Required for tmux interaction
10
+ from dataclasses import dataclass
11
+ from typing import Dict, List
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class TmuxNotFoundError(Exception):
17
+ """Raised when tmux is not installed or not found in PATH."""
18
+
19
+ def __init__(
20
+ self,
21
+ message: str = "tmux not found. Please install tmux to use commander mode.",
22
+ ):
23
+ super().__init__(message)
24
+ self.message = message
25
+
26
+
27
+ @dataclass
28
+ class TmuxOrchestrator:
29
+ """Orchestrate multiple MPM sessions via tmux.
30
+
31
+ This class provides a high-level API for managing tmux sessions and panes,
32
+ enabling the MPM Commander to coordinate multiple project-level MPM instances.
33
+
34
+ Attributes:
35
+ session_name: Name of the tmux session (default: "mpm-commander")
36
+
37
+ Example:
38
+ >>> orchestrator = TmuxOrchestrator()
39
+ >>> orchestrator.create_session()
40
+ >>> target = orchestrator.create_pane("proj1", "/path/to/project")
41
+ >>> orchestrator.send_keys(target, "echo 'Hello from pane'")
42
+ >>> output = orchestrator.capture_output(target)
43
+ >>> print(output)
44
+ >>> orchestrator.kill_session()
45
+ """
46
+
47
+ session_name: str = "mpm-commander"
48
+
49
+ def __post_init__(self):
50
+ """Verify tmux is available on initialization."""
51
+ if not shutil.which("tmux"):
52
+ raise TmuxNotFoundError()
53
+
54
+ def _run_tmux(
55
+ self, args: List[str], check: bool = True
56
+ ) -> subprocess.CompletedProcess:
57
+ """Execute tmux command and return result.
58
+
59
+ Args:
60
+ args: List of tmux command arguments
61
+ check: Whether to raise exception on non-zero exit code
62
+
63
+ Returns:
64
+ CompletedProcess with stdout/stderr captured
65
+
66
+ Raises:
67
+ TmuxNotFoundError: If tmux binary not found
68
+ subprocess.CalledProcessError: If check=True and command fails
69
+ """
70
+ cmd = ["tmux"] + args
71
+ logger.debug(f"Running tmux command: {' '.join(cmd)}")
72
+
73
+ try:
74
+ result = subprocess.run(cmd, capture_output=True, text=True, check=check) # nosec B603
75
+
76
+ if result.stdout:
77
+ logger.debug(f"tmux stdout: {result.stdout.strip()}")
78
+ if result.stderr:
79
+ logger.debug(f"tmux stderr: {result.stderr.strip()}")
80
+
81
+ return result
82
+
83
+ except FileNotFoundError as err:
84
+ raise TmuxNotFoundError() from err
85
+
86
+ def session_exists(self) -> bool:
87
+ """Check if commander session exists.
88
+
89
+ Returns:
90
+ True if session exists, False otherwise
91
+
92
+ Example:
93
+ >>> orchestrator = TmuxOrchestrator()
94
+ >>> if not orchestrator.session_exists():
95
+ ... orchestrator.create_session()
96
+ """
97
+ result = self._run_tmux(["has-session", "-t", self.session_name], check=False)
98
+ exists = result.returncode == 0
99
+ logger.debug(f"Session '{self.session_name}' exists: {exists}")
100
+ return exists
101
+
102
+ def create_session(self) -> bool:
103
+ """Create main commander tmux session if not exists.
104
+
105
+ Creates a detached tmux session for the commander. If the session
106
+ already exists, this is a no-op.
107
+
108
+ Returns:
109
+ True if session was created, False if it already existed
110
+
111
+ Example:
112
+ >>> orchestrator = TmuxOrchestrator()
113
+ >>> orchestrator.create_session()
114
+ True
115
+ >>> orchestrator.create_session() # Already exists
116
+ False
117
+ """
118
+ if self.session_exists():
119
+ logger.info(f"Session '{self.session_name}' already exists")
120
+ return False
121
+
122
+ logger.info(f"Creating tmux session '{self.session_name}'")
123
+ self._run_tmux(
124
+ [
125
+ "new-session",
126
+ "-d", # Detached
127
+ "-s",
128
+ self.session_name,
129
+ "-n",
130
+ "commander", # Window name
131
+ ]
132
+ )
133
+
134
+ return True
135
+
136
+ def create_pane(self, pane_id: str, working_dir: str) -> str:
137
+ """Create new pane for a project.
138
+
139
+ Creates a new split pane in the commander session with the specified
140
+ working directory.
141
+
142
+ Args:
143
+ pane_id: Identifier for this pane (used in logging)
144
+ working_dir: Working directory for the pane
145
+
146
+ Returns:
147
+ Tmux target string (pane ID like "%0", "%1", etc.)
148
+
149
+ Raises:
150
+ subprocess.CalledProcessError: If pane creation fails
151
+
152
+ Example:
153
+ >>> orchestrator = TmuxOrchestrator()
154
+ >>> orchestrator.create_session()
155
+ >>> target = orchestrator.create_pane("my-project", "/Users/user/projects/my-project")
156
+ >>> print(target)
157
+ %1
158
+ """
159
+ logger.info(f"Creating pane '{pane_id}' in {working_dir}")
160
+
161
+ # Create new window instead of splitting pane to avoid "no space for new pane" error
162
+ # when tmux window is too small to split
163
+ self._run_tmux(
164
+ [
165
+ "new-window",
166
+ "-t",
167
+ self.session_name,
168
+ "-c",
169
+ working_dir, # Working directory
170
+ "-P", # Print target of new pane
171
+ "-F",
172
+ "#{pane_id}", # Format: just pane ID
173
+ ]
174
+ )
175
+
176
+ # Get the newly created pane's target
177
+ # List panes and get the last one (most recently created)
178
+ result = self._run_tmux(
179
+ [
180
+ "list-panes",
181
+ "-t",
182
+ self.session_name,
183
+ "-F",
184
+ "#{pane_id}",
185
+ ]
186
+ )
187
+
188
+ panes = [p for p in result.stdout.strip().split("\n") if p]
189
+ if not panes:
190
+ raise RuntimeError(f"Failed to create pane '{pane_id}'")
191
+
192
+ # Get last pane ID (most recently created)
193
+ # Pane ID already includes % prefix and can be used directly as target
194
+ new_pane_id = panes[-1]
195
+ target = new_pane_id # Use pane ID directly as target
196
+
197
+ logger.debug(f"Created pane with target: {target}")
198
+ return target
199
+
200
+ def send_keys(self, target: str, keys: str, enter: bool = True) -> bool:
201
+ """Send keystrokes to a pane.
202
+
203
+ Args:
204
+ target: Tmux target (from create_pane)
205
+ keys: Keys to send to the pane
206
+ enter: Whether to send Enter key after keys
207
+
208
+ Returns:
209
+ True if successful
210
+
211
+ Raises:
212
+ subprocess.CalledProcessError: If target pane doesn't exist
213
+
214
+ Example:
215
+ >>> orchestrator = TmuxOrchestrator()
216
+ >>> orchestrator.create_session()
217
+ >>> target = orchestrator.create_pane("proj", "/tmp")
218
+ >>> orchestrator.send_keys(target, "echo 'Hello'")
219
+ >>> orchestrator.send_keys(target, "ls -la", enter=False)
220
+ """
221
+ logger.debug(f"Sending keys to {target}: {keys}")
222
+
223
+ args = ["send-keys", "-t", target, keys]
224
+ if enter:
225
+ args.append("Enter")
226
+
227
+ self._run_tmux(args)
228
+ return True
229
+
230
+ def capture_output(self, target: str, lines: int = 100) -> str:
231
+ """Capture recent output from pane.
232
+
233
+ Args:
234
+ target: Tmux target (from create_pane)
235
+ lines: Number of lines to capture from history
236
+
237
+ Returns:
238
+ Captured output as string
239
+
240
+ Raises:
241
+ subprocess.CalledProcessError: If target pane doesn't exist
242
+
243
+ Example:
244
+ >>> orchestrator = TmuxOrchestrator()
245
+ >>> orchestrator.create_session()
246
+ >>> target = orchestrator.create_pane("proj", "/tmp")
247
+ >>> orchestrator.send_keys(target, "echo 'Test output'")
248
+ >>> output = orchestrator.capture_output(target, lines=10)
249
+ >>> print(output)
250
+ Test output
251
+ """
252
+ logger.debug(f"Capturing {lines} lines from {target}")
253
+
254
+ result = self._run_tmux(
255
+ [
256
+ "capture-pane",
257
+ "-t",
258
+ target,
259
+ "-p", # Print to stdout
260
+ "-S",
261
+ f"-{lines}", # Start from N lines back
262
+ ]
263
+ )
264
+
265
+ return result.stdout
266
+
267
+ def list_panes(self) -> List[Dict[str, str]]:
268
+ """List all panes with their status.
269
+
270
+ Returns:
271
+ List of dicts with pane info (id, path, pid, active)
272
+
273
+ Example:
274
+ >>> orchestrator = TmuxOrchestrator()
275
+ >>> orchestrator.create_session()
276
+ >>> panes = orchestrator.list_panes()
277
+ >>> for pane in panes:
278
+ ... print(f"{pane['id']}: {pane['path']}")
279
+ %0: /Users/user/projects/proj1
280
+ %1: /Users/user/projects/proj2
281
+ """
282
+ if not self.session_exists():
283
+ logger.warning(f"Session '{self.session_name}' does not exist")
284
+ return []
285
+
286
+ logger.debug(f"Listing panes for session '{self.session_name}'")
287
+
288
+ result = self._run_tmux(
289
+ [
290
+ "list-panes",
291
+ "-t",
292
+ self.session_name,
293
+ "-F",
294
+ "#{pane_id}|#{pane_current_path}|#{pane_pid}|#{pane_active}",
295
+ ]
296
+ )
297
+
298
+ panes = []
299
+ for line in result.stdout.strip().split("\n"):
300
+ if not line:
301
+ continue
302
+
303
+ parts = line.split("|")
304
+ if len(parts) >= 4:
305
+ panes.append(
306
+ {
307
+ "id": parts[0],
308
+ "path": parts[1],
309
+ "pid": parts[2],
310
+ "active": parts[3] == "1",
311
+ }
312
+ )
313
+
314
+ logger.debug(f"Found {len(panes)} panes")
315
+ return panes
316
+
317
+ def kill_pane(self, target: str) -> bool:
318
+ """Kill a specific pane.
319
+
320
+ Args:
321
+ target: Tmux target (from create_pane or list_panes)
322
+
323
+ Returns:
324
+ True if successful
325
+
326
+ Raises:
327
+ subprocess.CalledProcessError: If target pane doesn't exist
328
+
329
+ Example:
330
+ >>> orchestrator = TmuxOrchestrator()
331
+ >>> orchestrator.create_session()
332
+ >>> target = orchestrator.create_pane("proj", "/tmp")
333
+ >>> orchestrator.kill_pane(target)
334
+ True
335
+ """
336
+ logger.info(f"Killing pane {target}")
337
+
338
+ self._run_tmux(["kill-pane", "-t", target])
339
+ return True
340
+
341
+ def kill_session(self) -> bool:
342
+ """Kill the entire commander session.
343
+
344
+ Returns:
345
+ True if session was killed, False if it didn't exist
346
+
347
+ Example:
348
+ >>> orchestrator = TmuxOrchestrator()
349
+ >>> orchestrator.create_session()
350
+ >>> orchestrator.kill_session()
351
+ True
352
+ >>> orchestrator.kill_session() # Already killed
353
+ False
354
+ """
355
+ if not self.session_exists():
356
+ logger.info(f"Session '{self.session_name}' does not exist")
357
+ return False
358
+
359
+ logger.info(f"Killing session '{self.session_name}'")
360
+ self._run_tmux(["kill-session", "-t", self.session_name])
361
+
362
+ return True
@@ -0,0 +1 @@
1
+ """Web UI module for MPM Commander."""
@@ -0,0 +1,30 @@
1
+ """Work queue and execution module for MPM Commander.
2
+
3
+ This module provides work queue management and execution capabilities:
4
+ - WorkItem: Data model for work items
5
+ - WorkState: Lifecycle states (PENDING, QUEUED, IN_PROGRESS, etc.)
6
+ - WorkPriority: Priority levels (CRITICAL, HIGH, MEDIUM, LOW)
7
+ - WorkQueue: Queue management with priority and dependencies
8
+ - WorkExecutor: Execution via RuntimeExecutor
9
+
10
+ Example:
11
+ >>> from claude_mpm.commander.work import (
12
+ ... WorkQueue, WorkExecutor, WorkItem, WorkState, WorkPriority
13
+ ... )
14
+ >>> queue = WorkQueue("proj-123")
15
+ >>> work = queue.add("Implement feature", WorkPriority.HIGH)
16
+ >>> executor = WorkExecutor(runtime, queue)
17
+ >>> await executor.execute_next()
18
+ """
19
+
20
+ from ..models.work import WorkItem, WorkPriority, WorkState
21
+ from .executor import WorkExecutor
22
+ from .queue import WorkQueue
23
+
24
+ __all__ = [
25
+ "WorkExecutor",
26
+ "WorkItem",
27
+ "WorkPriority",
28
+ "WorkQueue",
29
+ "WorkState",
30
+ ]
@@ -0,0 +1,207 @@
1
+ """Work executor for MPM Commander.
2
+
3
+ This module provides WorkExecutor which executes work items
4
+ via RuntimeExecutor and handles completion/failure callbacks.
5
+ """
6
+
7
+ import logging
8
+ from typing import Optional
9
+
10
+ from ..models.work import WorkItem
11
+ from ..runtime.executor import RuntimeExecutor
12
+ from .queue import WorkQueue
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class WorkExecutor:
18
+ """Executes work items via RuntimeExecutor.
19
+
20
+ Coordinates between work queue and runtime execution,
21
+ handling work item lifecycle and callbacks.
22
+
23
+ Attributes:
24
+ runtime: RuntimeExecutor for spawning and managing tools
25
+ queue: WorkQueue for work item management
26
+
27
+ Example:
28
+ >>> executor = WorkExecutor(runtime, queue)
29
+ >>> executed = await executor.execute_next()
30
+ >>> if executed:
31
+ ... print("Work item started")
32
+ """
33
+
34
+ def __init__(self, runtime: RuntimeExecutor, queue: WorkQueue):
35
+ """Initialize work executor.
36
+
37
+ Args:
38
+ runtime: RuntimeExecutor instance
39
+ queue: WorkQueue instance
40
+
41
+ Raises:
42
+ ValueError: If runtime or queue is None
43
+ """
44
+ if runtime is None:
45
+ raise ValueError("Runtime cannot be None")
46
+ if queue is None:
47
+ raise ValueError("Queue cannot be None")
48
+
49
+ self.runtime = runtime
50
+ self.queue = queue
51
+
52
+ logger.debug(f"Initialized WorkExecutor for project {queue.project_id}")
53
+
54
+ async def execute_next(self, pane_target: Optional[str] = None) -> bool:
55
+ """Execute next available work item.
56
+
57
+ Gets next work from queue, starts it, and executes via RuntimeExecutor.
58
+
59
+ Args:
60
+ pane_target: Optional tmux pane target for execution
61
+
62
+ Returns:
63
+ True if work was executed, False if queue empty/blocked
64
+
65
+ Example:
66
+ >>> executed = await executor.execute_next("%5")
67
+ >>> if not executed:
68
+ ... print("No work available")
69
+ """
70
+ # Get next work item
71
+ work_item = self.queue.get_next()
72
+ if not work_item:
73
+ logger.debug(f"No work available for project {self.queue.project_id}")
74
+ return False
75
+
76
+ # Execute the work item
77
+ await self.execute(work_item, pane_target)
78
+ return True
79
+
80
+ async def execute(
81
+ self, work_item: WorkItem, pane_target: Optional[str] = None
82
+ ) -> None:
83
+ """Execute a specific work item.
84
+
85
+ Marks work as IN_PROGRESS and sends to RuntimeExecutor.
86
+ Note: This is async but returns immediately - actual execution
87
+ happens in the background via tmux.
88
+
89
+ Args:
90
+ work_item: WorkItem to execute
91
+ pane_target: Optional tmux pane target for execution
92
+
93
+ Raises:
94
+ RuntimeError: If execution fails
95
+
96
+ Example:
97
+ >>> await executor.execute(work_item, "%5")
98
+ """
99
+ # Mark as in progress
100
+ if not self.queue.start(work_item.id):
101
+ logger.error(
102
+ f"Failed to start work item {work_item.id} - "
103
+ f"invalid state: {work_item.state.value}"
104
+ )
105
+ return
106
+
107
+ logger.info(
108
+ f"Executing work item {work_item.id} for project {work_item.project_id}"
109
+ )
110
+
111
+ try:
112
+ # Send work content to runtime if pane target provided
113
+ if pane_target:
114
+ await self.runtime.send_message(pane_target, work_item.content)
115
+ logger.info(
116
+ f"Work item {work_item.id} sent to pane {pane_target} for execution"
117
+ )
118
+ else:
119
+ logger.warning(
120
+ f"No pane target provided for work item {work_item.id}, "
121
+ f"work marked as in-progress but not sent to runtime"
122
+ )
123
+
124
+ # Store work item ID in metadata for callback tracking
125
+ work_item.metadata["execution_started"] = True
126
+
127
+ except Exception as e:
128
+ logger.error(f"Failed to execute work item {work_item.id}: {e}")
129
+ await self.handle_failure(work_item.id, str(e))
130
+ raise
131
+
132
+ async def handle_completion(
133
+ self, work_id: str, result: Optional[str] = None
134
+ ) -> None:
135
+ """Handle work completion callback.
136
+
137
+ Called when RuntimeExecutor completes work successfully.
138
+
139
+ Args:
140
+ work_id: Work item ID that completed
141
+ result: Optional result message
142
+
143
+ Example:
144
+ >>> await executor.handle_completion("work-123", "Feature implemented")
145
+ """
146
+ if self.queue.complete(work_id, result):
147
+ logger.info(f"Work item {work_id} completed successfully")
148
+ else:
149
+ logger.warning(f"Failed to mark work item {work_id} as completed")
150
+
151
+ async def handle_failure(self, work_id: str, error: str) -> None:
152
+ """Handle work failure callback.
153
+
154
+ Called when RuntimeExecutor encounters an error.
155
+
156
+ Args:
157
+ work_id: Work item ID that failed
158
+ error: Error message
159
+
160
+ Example:
161
+ >>> await executor.handle_failure("work-123", "Tool crashed")
162
+ """
163
+ if self.queue.fail(work_id, error):
164
+ logger.error(f"Work item {work_id} failed: {error}")
165
+ else:
166
+ logger.warning(f"Failed to mark work item {work_id} as failed")
167
+
168
+ async def handle_block(self, work_id: str, reason: str) -> bool:
169
+ """Handle work being blocked by an event.
170
+
171
+ Called when RuntimeMonitor detects a blocking event.
172
+
173
+ Args:
174
+ work_id: Work item ID that is blocked
175
+ reason: Reason for blocking (e.g., "Waiting for approval")
176
+
177
+ Returns:
178
+ True if work was successfully blocked, False otherwise
179
+
180
+ Example:
181
+ >>> success = await executor.handle_block("work-123", "Decision needed")
182
+ """
183
+ if self.queue.block(work_id, reason):
184
+ logger.info(f"Work item {work_id} blocked: {reason}")
185
+ return True
186
+ logger.warning(f"Failed to mark work item {work_id} as blocked")
187
+ return False
188
+
189
+ async def handle_unblock(self, work_id: str) -> bool:
190
+ """Handle work being unblocked after event resolution.
191
+
192
+ Called when EventHandler resolves a blocking event.
193
+
194
+ Args:
195
+ work_id: Work item ID to unblock
196
+
197
+ Returns:
198
+ True if work was successfully unblocked, False otherwise
199
+
200
+ Example:
201
+ >>> success = await executor.handle_unblock("work-123")
202
+ """
203
+ if self.queue.unblock(work_id):
204
+ logger.info(f"Work item {work_id} unblocked, resuming execution")
205
+ return True
206
+ logger.warning(f"Failed to unblock work item {work_id}")
207
+ return False