claude-mpm 5.4.65__py3-none-any.whl → 5.6.10__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (313) 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 +107 -1928
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +119 -689
  6. claude_mpm/agents/WORKFLOW.md +2 -0
  7. claude_mpm/agents/templates/circuit-breakers.md +26 -17
  8. claude_mpm/cli/__init__.py +5 -1
  9. claude_mpm/cli/commands/agents.py +2 -4
  10. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  11. claude_mpm/cli/commands/autotodos.py +566 -0
  12. claude_mpm/cli/commands/commander.py +46 -0
  13. claude_mpm/cli/commands/configure.py +620 -21
  14. claude_mpm/cli/commands/hook_errors.py +60 -60
  15. claude_mpm/cli/commands/monitor.py +2 -2
  16. claude_mpm/cli/commands/mpm_init/core.py +2 -2
  17. claude_mpm/cli/commands/run.py +35 -3
  18. claude_mpm/cli/commands/skill_source.py +51 -2
  19. claude_mpm/cli/commands/skills.py +171 -17
  20. claude_mpm/cli/executor.py +120 -16
  21. claude_mpm/cli/interactive/__init__.py +10 -0
  22. claude_mpm/cli/interactive/agent_wizard.py +30 -50
  23. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  24. claude_mpm/cli/interactive/skill_selector.py +481 -0
  25. claude_mpm/cli/parsers/base_parser.py +76 -1
  26. claude_mpm/cli/parsers/commander_parser.py +83 -0
  27. claude_mpm/cli/parsers/run_parser.py +10 -0
  28. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  29. claude_mpm/cli/parsers/skills_parser.py +5 -0
  30. claude_mpm/cli/startup.py +203 -359
  31. claude_mpm/cli/startup_display.py +72 -5
  32. claude_mpm/cli/startup_logging.py +2 -2
  33. claude_mpm/cli/utils.py +7 -3
  34. claude_mpm/commander/__init__.py +72 -0
  35. claude_mpm/commander/adapters/__init__.py +31 -0
  36. claude_mpm/commander/adapters/base.py +191 -0
  37. claude_mpm/commander/adapters/claude_code.py +361 -0
  38. claude_mpm/commander/adapters/communication.py +366 -0
  39. claude_mpm/commander/api/__init__.py +16 -0
  40. claude_mpm/commander/api/app.py +105 -0
  41. claude_mpm/commander/api/errors.py +133 -0
  42. claude_mpm/commander/api/routes/__init__.py +8 -0
  43. claude_mpm/commander/api/routes/events.py +184 -0
  44. claude_mpm/commander/api/routes/inbox.py +171 -0
  45. claude_mpm/commander/api/routes/messages.py +148 -0
  46. claude_mpm/commander/api/routes/projects.py +271 -0
  47. claude_mpm/commander/api/routes/sessions.py +228 -0
  48. claude_mpm/commander/api/routes/work.py +260 -0
  49. claude_mpm/commander/api/schemas.py +182 -0
  50. claude_mpm/commander/chat/__init__.py +7 -0
  51. claude_mpm/commander/chat/cli.py +107 -0
  52. claude_mpm/commander/chat/commands.py +96 -0
  53. claude_mpm/commander/chat/repl.py +310 -0
  54. claude_mpm/commander/config.py +49 -0
  55. claude_mpm/commander/config_loader.py +115 -0
  56. claude_mpm/commander/daemon.py +398 -0
  57. claude_mpm/commander/events/__init__.py +26 -0
  58. claude_mpm/commander/events/manager.py +332 -0
  59. claude_mpm/commander/frameworks/__init__.py +12 -0
  60. claude_mpm/commander/frameworks/base.py +143 -0
  61. claude_mpm/commander/frameworks/claude_code.py +58 -0
  62. claude_mpm/commander/frameworks/mpm.py +62 -0
  63. claude_mpm/commander/inbox/__init__.py +16 -0
  64. claude_mpm/commander/inbox/dedup.py +128 -0
  65. claude_mpm/commander/inbox/inbox.py +224 -0
  66. claude_mpm/commander/inbox/models.py +70 -0
  67. claude_mpm/commander/instance_manager.py +337 -0
  68. claude_mpm/commander/llm/__init__.py +6 -0
  69. claude_mpm/commander/llm/openrouter_client.py +167 -0
  70. claude_mpm/commander/llm/summarizer.py +70 -0
  71. claude_mpm/commander/models/__init__.py +18 -0
  72. claude_mpm/commander/models/events.py +121 -0
  73. claude_mpm/commander/models/project.py +162 -0
  74. claude_mpm/commander/models/work.py +214 -0
  75. claude_mpm/commander/parsing/__init__.py +20 -0
  76. claude_mpm/commander/parsing/extractor.py +132 -0
  77. claude_mpm/commander/parsing/output_parser.py +270 -0
  78. claude_mpm/commander/parsing/patterns.py +100 -0
  79. claude_mpm/commander/persistence/__init__.py +11 -0
  80. claude_mpm/commander/persistence/event_store.py +274 -0
  81. claude_mpm/commander/persistence/state_store.py +309 -0
  82. claude_mpm/commander/persistence/work_store.py +164 -0
  83. claude_mpm/commander/polling/__init__.py +13 -0
  84. claude_mpm/commander/polling/event_detector.py +104 -0
  85. claude_mpm/commander/polling/output_buffer.py +49 -0
  86. claude_mpm/commander/polling/output_poller.py +153 -0
  87. claude_mpm/commander/project_session.py +268 -0
  88. claude_mpm/commander/proxy/__init__.py +12 -0
  89. claude_mpm/commander/proxy/formatter.py +89 -0
  90. claude_mpm/commander/proxy/output_handler.py +191 -0
  91. claude_mpm/commander/proxy/relay.py +155 -0
  92. claude_mpm/commander/registry.py +404 -0
  93. claude_mpm/commander/runtime/__init__.py +10 -0
  94. claude_mpm/commander/runtime/executor.py +191 -0
  95. claude_mpm/commander/runtime/monitor.py +316 -0
  96. claude_mpm/commander/session/__init__.py +6 -0
  97. claude_mpm/commander/session/context.py +81 -0
  98. claude_mpm/commander/session/manager.py +59 -0
  99. claude_mpm/commander/tmux_orchestrator.py +361 -0
  100. claude_mpm/commander/web/__init__.py +1 -0
  101. claude_mpm/commander/work/__init__.py +30 -0
  102. claude_mpm/commander/work/executor.py +189 -0
  103. claude_mpm/commander/work/queue.py +405 -0
  104. claude_mpm/commander/workflow/__init__.py +27 -0
  105. claude_mpm/commander/workflow/event_handler.py +219 -0
  106. claude_mpm/commander/workflow/notifier.py +146 -0
  107. claude_mpm/commands/mpm-config.md +8 -0
  108. claude_mpm/commands/mpm-doctor.md +8 -0
  109. claude_mpm/commands/mpm-help.md +8 -0
  110. claude_mpm/commands/mpm-init.md +8 -0
  111. claude_mpm/commands/mpm-monitor.md +8 -0
  112. claude_mpm/commands/mpm-organize.md +8 -0
  113. claude_mpm/commands/mpm-postmortem.md +8 -0
  114. claude_mpm/commands/mpm-session-resume.md +9 -1
  115. claude_mpm/commands/mpm-status.md +8 -0
  116. claude_mpm/commands/mpm-ticket-view.md +8 -0
  117. claude_mpm/commands/mpm-version.md +8 -0
  118. claude_mpm/commands/mpm.md +8 -0
  119. claude_mpm/config/agent_presets.py +8 -7
  120. claude_mpm/config/skill_sources.py +16 -0
  121. claude_mpm/constants.py +1 -0
  122. claude_mpm/core/claude_runner.py +2 -2
  123. claude_mpm/core/config.py +32 -19
  124. claude_mpm/core/hook_manager.py +51 -3
  125. claude_mpm/core/interactive_session.py +7 -7
  126. claude_mpm/core/logger.py +26 -9
  127. claude_mpm/core/logging_utils.py +35 -11
  128. claude_mpm/core/output_style_manager.py +31 -13
  129. claude_mpm/core/unified_config.py +54 -8
  130. claude_mpm/core/unified_paths.py +95 -90
  131. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  132. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  133. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cs_tUR18.js → 1WZnGYqX.js} +1 -1
  134. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CDuw-vjf.js → 67pF3qNn.js} +1 -1
  135. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bTOqqlTd.js → 6RxdMKe4.js} +1 -1
  136. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DwBR2MJi.js → 8cZrfX0h.js} +1 -1
  137. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{ZGh7QtNv.js → 9a6T2nm-.js} +1 -1
  138. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D9lljYKQ.js → B443AUzu.js} +1 -1
  139. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{RJiighC3.js → B8AwtY2H.js} +1 -1
  140. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uuIeMWc-.js → BF15LAsF.js} +1 -1
  141. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D3k0OPJN.js → BRcwIQNr.js} +1 -1
  142. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CyWMqx4W.js → BV6nKitt.js} +1 -1
  143. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CiIAseT4.js → BViJ8lZt.js} +5 -5
  144. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CBBdVcY8.js → BcQ-Q0FE.js} +1 -1
  145. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BovzEFCE.js → Bpyvgze_.js} +1 -1
  146. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  147. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  148. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{eNVUfhuA.js → C3rbW_a-.js} +1 -1
  149. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{GYwsonyD.js → C8WYN38h.js} +1 -1
  150. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BIF9m_hv.js → C9I8FlXH.js} +1 -1
  151. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B0uc0UOD.js → CIQcWgO2.js} +3 -3
  152. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Be7GpZd6.js → CIctN7YN.js} +1 -1
  153. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Bh0LDWpI.js → CKrS_JZW.js} +2 -2
  154. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DUrLdbGD.js → CR6P9C4A.js} +1 -1
  155. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7xVLGWV.js → CRRR9MD_.js} +1 -1
  156. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  157. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dhb8PKl3.js → CSXtMOf0.js} +1 -1
  158. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BPYeabCQ.js → CT-sbxSk.js} +1 -1
  159. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{sQeU3Y1z.js → CWm6DJsp.js} +1 -1
  160. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CnA0NrzZ.js → CpqQ1Kzn.js} +1 -1
  161. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4B-KCzX.js → D2nGpDRe.js} +1 -1
  162. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DGkLK5U1.js → D9iCMida.js} +1 -1
  163. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BofRWZRR.js → D9ykgMoY.js} +1 -1
  164. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DmxopI1J.js → DL2Ldur1.js} +1 -1
  165. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C30mlcqg.js → DPfltzjH.js} +1 -1
  166. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Vzk33B_K.js → DR8nis88.js} +2 -2
  167. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DI7hHRFL.js → DUliQN2b.js} +1 -1
  168. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4JcI4KD.js → DXlhR01x.js} +1 -1
  169. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bT1r9zLR.js → D_lyTybS.js} +1 -1
  170. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DZX00Y4g.js → DngoTTgh.js} +1 -1
  171. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzZX-COe.js → DqkmHtDC.js} +1 -1
  172. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7RN905-.js → DsDh8EYs.js} +1 -1
  173. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DLVjFsZ3.js → DypDmXgd.js} +1 -1
  174. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{iEWssX7S.js → IPYC-LnN.js} +1 -1
  175. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  176. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DaimHw_p.js → JpevfAFt.js} +1 -1
  177. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DY1XQ8fi.js → R8CEIRAd.js} +1 -1
  178. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dle-35c7.js → Zxy7qc-l.js} +2 -2
  179. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  180. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C_Usid8X.js → qtd3IeO4.js} +2 -2
  181. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzeYkLYB.js → ulBFON_C.js} +2 -2
  182. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cfqx1Qun.js → wQVh1CoA.js} +1 -1
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/{app.D6-I5TpK.js → app.Dr7t0z2J.js} +2 -2
  184. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  185. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.m1gL8KXf.js → 0.RgBboRvH.js} +1 -1
  186. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{1.CgNOuw-d.js → 1.DG-KkbDf.js} +1 -1
  187. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  188. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
  189. claude_mpm/dashboard/static/svelte-build/index.html +9 -9
  190. claude_mpm/experimental/cli_enhancements.py +2 -1
  191. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  192. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  193. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  194. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  195. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-312.pyc +0 -0
  196. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-314.pyc +0 -0
  197. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  198. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-312.pyc +0 -0
  199. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-314.pyc +0 -0
  200. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  201. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.pyc +0 -0
  202. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-314.pyc +0 -0
  203. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  204. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-314.pyc +0 -0
  205. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  206. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-312.pyc +0 -0
  207. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-314.pyc +0 -0
  208. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  209. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc +0 -0
  210. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-314.pyc +0 -0
  211. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-314.pyc +0 -0
  212. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
  213. claude_mpm/hooks/claude_hooks/event_handlers.py +283 -87
  214. claude_mpm/hooks/claude_hooks/hook_handler.py +106 -89
  215. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  216. claude_mpm/hooks/claude_hooks/installer.py +116 -8
  217. claude_mpm/hooks/claude_hooks/memory_integration.py +51 -31
  218. claude_mpm/hooks/claude_hooks/response_tracking.py +42 -59
  219. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-314.pyc +0 -0
  220. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  221. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-312.pyc +0 -0
  222. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-314.pyc +0 -0
  223. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-314.pyc +0 -0
  224. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  225. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc +0 -0
  226. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-314.pyc +0 -0
  227. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  228. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
  229. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-314.pyc +0 -0
  230. claude_mpm/hooks/claude_hooks/services/connection_manager.py +39 -24
  231. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +36 -103
  232. claude_mpm/hooks/claude_hooks/services/state_manager.py +23 -36
  233. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +73 -75
  234. claude_mpm/hooks/session_resume_hook.py +89 -1
  235. claude_mpm/hooks/templates/pre_tool_use_template.py +10 -2
  236. claude_mpm/init.py +1 -1
  237. claude_mpm/scripts/claude-hook-handler.sh +43 -16
  238. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  239. claude_mpm/services/agents/agent_selection_service.py +2 -2
  240. claude_mpm/services/agents/cache_git_manager.py +1 -1
  241. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  242. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +3 -0
  243. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  244. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  245. claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
  246. claude_mpm/services/agents/startup_sync.py +5 -2
  247. claude_mpm/services/cli/__init__.py +3 -0
  248. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  249. claude_mpm/services/cli/session_resume_helper.py +10 -2
  250. claude_mpm/services/delegation_detector.py +175 -0
  251. claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
  252. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  253. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  254. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  255. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  256. claude_mpm/services/diagnostics/models.py +14 -1
  257. claude_mpm/services/event_log.py +325 -0
  258. claude_mpm/services/infrastructure/__init__.py +4 -0
  259. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  260. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  261. claude_mpm/services/monitor/daemon_manager.py +15 -4
  262. claude_mpm/services/monitor/management/lifecycle.py +8 -2
  263. claude_mpm/services/monitor/server.py +106 -16
  264. claude_mpm/services/pm_skills_deployer.py +259 -87
  265. claude_mpm/services/skills/git_skill_source_manager.py +135 -11
  266. claude_mpm/services/skills/selective_skill_deployer.py +142 -26
  267. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  268. claude_mpm/services/skills_deployer.py +31 -5
  269. claude_mpm/services/socketio/handlers/hook.py +14 -7
  270. claude_mpm/services/socketio/server/main.py +12 -4
  271. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  272. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  273. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  274. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  275. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  276. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  277. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  278. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  279. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  280. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  281. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  282. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  283. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  284. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  285. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  286. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  287. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  288. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  289. claude_mpm/skills/skill_manager.py +4 -4
  290. claude_mpm/utils/agent_dependency_loader.py +4 -2
  291. claude_mpm/utils/robust_installer.py +10 -6
  292. claude_mpm-5.6.10.dist-info/METADATA +391 -0
  293. {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/RECORD +303 -181
  294. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +0 -1
  295. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +0 -1
  296. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +0 -1
  297. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +0 -24
  298. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +0 -1
  299. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +0 -1
  300. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +0 -323
  301. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +0 -1
  302. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +0 -1
  303. claude_mpm-5.4.65.dist-info/METADATA +0 -999
  304. /claude_mpm/skills/bundled/pm/{pm-delegation-patterns → mpm-delegation-patterns}/SKILL.md +0 -0
  305. /claude_mpm/skills/bundled/pm/{pm-git-file-tracking → mpm-git-file-tracking}/SKILL.md +0 -0
  306. /claude_mpm/skills/bundled/pm/{pm-pr-workflow → mpm-pr-workflow}/SKILL.md +0 -0
  307. /claude_mpm/skills/bundled/pm/{pm-ticketing-integration → mpm-ticketing-integration}/SKILL.md +0 -0
  308. /claude_mpm/skills/bundled/pm/{pm-verification-protocols → mpm-verification-protocols}/SKILL.md +0 -0
  309. {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/WHEEL +0 -0
  310. {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/entry_points.txt +0 -0
  311. {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/licenses/LICENSE +0 -0
  312. {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  313. {claude_mpm-5.4.65.dist-info → claude_mpm-5.6.10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,271 @@
1
+ """Project management endpoints for MPM Commander API.
2
+
3
+ This module implements REST endpoints for registering, listing, and managing
4
+ projects in the MPM Commander.
5
+ """
6
+
7
+ from pathlib import Path
8
+ from typing import List
9
+
10
+ from fastapi import APIRouter, Response
11
+
12
+ from ...models import ProjectState
13
+ from ..errors import InvalidPathError, ProjectAlreadyExistsError, ProjectNotFoundError
14
+ from ..schemas import ProjectResponse, RegisterProjectRequest, SessionResponse
15
+
16
+ router = APIRouter()
17
+
18
+
19
+ def _get_registry():
20
+ """Get registry instance from app global."""
21
+ from ..app import registry
22
+
23
+ if registry is None:
24
+ raise RuntimeError("Registry not initialized")
25
+ return registry
26
+
27
+
28
+ def _project_to_response(project) -> ProjectResponse:
29
+ """Convert Project model to ProjectResponse schema.
30
+
31
+ Args:
32
+ project: Project instance
33
+
34
+ Returns:
35
+ ProjectResponse with all project data
36
+ """
37
+ # Convert sessions dict to list of SessionResponse
38
+ session_responses = [
39
+ SessionResponse(
40
+ id=session.id,
41
+ project_id=session.project_id,
42
+ runtime=session.runtime,
43
+ tmux_target=session.tmux_target,
44
+ status=session.status,
45
+ created_at=session.created_at,
46
+ )
47
+ for session in project.sessions.values()
48
+ ]
49
+
50
+ return ProjectResponse(
51
+ id=project.id,
52
+ path=project.path,
53
+ name=project.name,
54
+ state=project.state.value,
55
+ state_reason=project.state_reason,
56
+ sessions=session_responses,
57
+ pending_events_count=len(project.pending_events),
58
+ last_activity=project.last_activity,
59
+ created_at=project.created_at,
60
+ )
61
+
62
+
63
+ @router.get("/projects", response_model=List[ProjectResponse])
64
+ async def list_projects() -> List[ProjectResponse]:
65
+ """List all registered projects.
66
+
67
+ Returns:
68
+ List of project information (may be empty)
69
+
70
+ Example:
71
+ GET /api/projects
72
+ Response: [
73
+ {
74
+ "id": "abc-123",
75
+ "path": "/Users/user/projects/my-app",
76
+ "name": "my-app",
77
+ "state": "idle",
78
+ "state_reason": null,
79
+ "sessions": [],
80
+ "pending_events_count": 0,
81
+ "last_activity": "2025-01-12T10:00:00Z",
82
+ "created_at": "2025-01-12T09:00:00Z"
83
+ }
84
+ ]
85
+ """
86
+ registry = _get_registry()
87
+ projects = registry.list_all()
88
+ return [_project_to_response(p) for p in projects]
89
+
90
+
91
+ @router.get("/projects/{project_id}", response_model=ProjectResponse)
92
+ async def get_project(project_id: str) -> ProjectResponse:
93
+ """Get project details by ID.
94
+
95
+ Args:
96
+ project_id: Unique project identifier
97
+
98
+ Returns:
99
+ Project information
100
+
101
+ Raises:
102
+ ProjectNotFoundError: If project_id doesn't exist
103
+
104
+ Example:
105
+ GET /api/projects/abc-123
106
+ Response: {
107
+ "id": "abc-123",
108
+ "path": "/Users/user/projects/my-app",
109
+ "name": "my-app",
110
+ "state": "idle",
111
+ ...
112
+ }
113
+ """
114
+ registry = _get_registry()
115
+ project = registry.get(project_id)
116
+
117
+ if project is None:
118
+ raise ProjectNotFoundError(project_id)
119
+
120
+ return _project_to_response(project)
121
+
122
+
123
+ @router.post("/projects", response_model=ProjectResponse, status_code=201)
124
+ async def register_project(req: RegisterProjectRequest) -> ProjectResponse:
125
+ """Register a new project.
126
+
127
+ Args:
128
+ req: Registration request with path and optional name
129
+
130
+ Returns:
131
+ Newly registered project information
132
+
133
+ Raises:
134
+ InvalidPathError: If path doesn't exist or isn't a directory
135
+ ProjectAlreadyExistsError: If path already registered
136
+
137
+ Example:
138
+ POST /api/projects
139
+ Body: {
140
+ "path": "/Users/user/projects/my-app",
141
+ "name": "My App"
142
+ }
143
+ Response: {
144
+ "id": "abc-123",
145
+ "path": "/Users/user/projects/my-app",
146
+ "name": "My App",
147
+ "state": "idle",
148
+ ...
149
+ }
150
+ """
151
+ registry = _get_registry()
152
+
153
+ # Validate path exists and is directory
154
+ path_obj = Path(req.path)
155
+ if not path_obj.exists() or not path_obj.is_dir():
156
+ raise InvalidPathError(req.path)
157
+
158
+ try:
159
+ project = registry.register(req.path, req.name)
160
+ return _project_to_response(project)
161
+ except ValueError as e:
162
+ # Registry raises ValueError for duplicate registration
163
+ error_msg = str(e)
164
+ if "already registered" in error_msg.lower():
165
+ raise ProjectAlreadyExistsError(req.path) from e
166
+ # Re-raise as InvalidPathError for other validation errors
167
+ raise InvalidPathError(req.path) from e
168
+
169
+
170
+ @router.delete("/projects/{project_id}", status_code=204)
171
+ async def unregister_project(project_id: str) -> Response:
172
+ """Unregister a project.
173
+
174
+ Args:
175
+ project_id: Unique project identifier
176
+
177
+ Returns:
178
+ Empty response with 204 status
179
+
180
+ Raises:
181
+ ProjectNotFoundError: If project_id doesn't exist
182
+
183
+ Example:
184
+ DELETE /api/projects/abc-123
185
+ Response: 204 No Content
186
+ """
187
+ registry = _get_registry()
188
+
189
+ try:
190
+ registry.unregister(project_id)
191
+ return Response(status_code=204)
192
+ except KeyError as e:
193
+ raise ProjectNotFoundError(project_id) from e
194
+
195
+
196
+ @router.post("/projects/{project_id}/pause", response_model=ProjectResponse)
197
+ async def pause_project(project_id: str) -> ProjectResponse:
198
+ """Pause a project.
199
+
200
+ Sets project state to PAUSED to prevent automatic work processing.
201
+
202
+ Args:
203
+ project_id: Unique project identifier
204
+
205
+ Returns:
206
+ Updated project information
207
+
208
+ Raises:
209
+ ProjectNotFoundError: If project_id doesn't exist
210
+
211
+ Example:
212
+ POST /api/projects/abc-123/pause
213
+ Response: {
214
+ "id": "abc-123",
215
+ "state": "paused",
216
+ "state_reason": "Manually paused via API",
217
+ ...
218
+ }
219
+ """
220
+ registry = _get_registry()
221
+ project = registry.get(project_id)
222
+
223
+ if project is None:
224
+ raise ProjectNotFoundError(project_id)
225
+
226
+ registry.update_state(
227
+ project_id,
228
+ ProjectState.PAUSED,
229
+ reason="Manually paused via API",
230
+ )
231
+
232
+ return _project_to_response(project)
233
+
234
+
235
+ @router.post("/projects/{project_id}/resume", response_model=ProjectResponse)
236
+ async def resume_project(project_id: str) -> ProjectResponse:
237
+ """Resume a paused project.
238
+
239
+ Sets project state back to IDLE to allow work processing.
240
+
241
+ Args:
242
+ project_id: Unique project identifier
243
+
244
+ Returns:
245
+ Updated project information
246
+
247
+ Raises:
248
+ ProjectNotFoundError: If project_id doesn't exist
249
+
250
+ Example:
251
+ POST /api/projects/abc-123/resume
252
+ Response: {
253
+ "id": "abc-123",
254
+ "state": "idle",
255
+ "state_reason": "Resumed via API",
256
+ ...
257
+ }
258
+ """
259
+ registry = _get_registry()
260
+ project = registry.get(project_id)
261
+
262
+ if project is None:
263
+ raise ProjectNotFoundError(project_id)
264
+
265
+ registry.update_state(
266
+ project_id,
267
+ ProjectState.IDLE,
268
+ reason="Resumed via API",
269
+ )
270
+
271
+ return _project_to_response(project)
@@ -0,0 +1,228 @@
1
+ """Session management endpoints for MPM Commander API.
2
+
3
+ This module implements REST endpoints for creating and managing tool sessions
4
+ (Claude Code, Aider, etc.) within projects.
5
+ """
6
+
7
+ import logging
8
+ import subprocess # nosec B404 - needed for tmux error handling
9
+ import uuid
10
+ from typing import List
11
+
12
+ from fastapi import APIRouter, Response
13
+
14
+ from ...models import ToolSession
15
+ from ..errors import (
16
+ InvalidRuntimeError,
17
+ ProjectNotFoundError,
18
+ SessionNotFoundError,
19
+ TmuxNoSpaceError,
20
+ )
21
+ from ..schemas import CreateSessionRequest, SessionResponse
22
+
23
+ router = APIRouter()
24
+ logger = logging.getLogger(__name__)
25
+
26
+ # Valid runtime adapters (Phase 1: claude-code only)
27
+ VALID_RUNTIMES = {"claude-code"}
28
+
29
+
30
+ def _get_registry():
31
+ """Get registry instance from app global."""
32
+ from ..app import registry
33
+
34
+ if registry is None:
35
+ raise RuntimeError("Registry not initialized")
36
+ return registry
37
+
38
+
39
+ def _get_tmux():
40
+ """Get tmux orchestrator instance from app global."""
41
+ from ..app import tmux
42
+
43
+ if tmux is None:
44
+ raise RuntimeError("Tmux orchestrator not initialized")
45
+ return tmux
46
+
47
+
48
+ def _session_to_response(session: ToolSession) -> SessionResponse:
49
+ """Convert ToolSession model to SessionResponse schema.
50
+
51
+ Args:
52
+ session: ToolSession instance
53
+
54
+ Returns:
55
+ SessionResponse with session data
56
+ """
57
+ return SessionResponse(
58
+ id=session.id,
59
+ project_id=session.project_id,
60
+ runtime=session.runtime,
61
+ tmux_target=session.tmux_target,
62
+ status=session.status,
63
+ created_at=session.created_at,
64
+ )
65
+
66
+
67
+ @router.get("/projects/{project_id}/sessions", response_model=List[SessionResponse])
68
+ async def list_sessions(project_id: str) -> List[SessionResponse]:
69
+ """List all sessions for a project.
70
+
71
+ Args:
72
+ project_id: Unique project identifier
73
+
74
+ Returns:
75
+ List of session information (may be empty)
76
+
77
+ Raises:
78
+ ProjectNotFoundError: If project_id doesn't exist
79
+
80
+ Example:
81
+ GET /api/projects/abc-123/sessions
82
+ Response: [
83
+ {
84
+ "id": "sess-456",
85
+ "project_id": "abc-123",
86
+ "runtime": "claude-code",
87
+ "tmux_target": "%1",
88
+ "status": "running",
89
+ "created_at": "2025-01-12T10:00:00Z"
90
+ }
91
+ ]
92
+ """
93
+ registry = _get_registry()
94
+ project = registry.get(project_id)
95
+
96
+ if project is None:
97
+ raise ProjectNotFoundError(project_id)
98
+
99
+ # Convert sessions dict to list of responses
100
+ return [_session_to_response(s) for s in project.sessions.values()]
101
+
102
+
103
+ @router.post(
104
+ "/projects/{project_id}/sessions", response_model=SessionResponse, status_code=201
105
+ )
106
+ async def create_session(project_id: str, req: CreateSessionRequest) -> SessionResponse:
107
+ """Create a new session for a project.
108
+
109
+ Creates a new tmux pane and initializes the specified runtime adapter.
110
+
111
+ Args:
112
+ project_id: Unique project identifier
113
+ req: Session creation request
114
+
115
+ Returns:
116
+ Newly created session information
117
+
118
+ Raises:
119
+ ProjectNotFoundError: If project_id doesn't exist
120
+ InvalidRuntimeError: If runtime is not supported
121
+ TmuxNoSpaceError: If tmux has no space for new pane
122
+
123
+ Example:
124
+ POST /api/projects/abc-123/sessions
125
+ Body: {
126
+ "runtime": "claude-code",
127
+ "agent_prompt": "You are a helpful coding assistant"
128
+ }
129
+ Response: {
130
+ "id": "sess-456",
131
+ "project_id": "abc-123",
132
+ "runtime": "claude-code",
133
+ "tmux_target": "%1",
134
+ "status": "initializing",
135
+ "created_at": "2025-01-12T10:00:00Z"
136
+ }
137
+ """
138
+ registry = _get_registry()
139
+ tmux_orch = _get_tmux()
140
+
141
+ # Validate project exists
142
+ project = registry.get(project_id)
143
+ if project is None:
144
+ raise ProjectNotFoundError(project_id)
145
+
146
+ # Validate runtime
147
+ if req.runtime not in VALID_RUNTIMES:
148
+ raise InvalidRuntimeError(req.runtime)
149
+
150
+ # Generate session ID
151
+ session_id = str(uuid.uuid4())
152
+
153
+ # Create tmux pane for session
154
+ try:
155
+ tmux_target = tmux_orch.create_pane(
156
+ pane_id=f"{project.name}-{req.runtime}",
157
+ working_dir=project.path,
158
+ )
159
+ except subprocess.CalledProcessError as e:
160
+ stderr = e.stderr.decode() if e.stderr else ""
161
+ if "no space for new pane" in stderr.lower():
162
+ raise TmuxNoSpaceError() from None
163
+ raise # Re-raise other subprocess errors
164
+
165
+ # Create session object
166
+ session = ToolSession(
167
+ id=session_id,
168
+ project_id=project_id,
169
+ runtime=req.runtime,
170
+ tmux_target=tmux_target,
171
+ status="initializing",
172
+ )
173
+
174
+ # Add session to project
175
+ registry.add_session(project_id, session)
176
+
177
+ # TODO: Start runtime adapter in pane (Phase 2)
178
+ # For Phase 1, session stays in "initializing" state
179
+
180
+ return _session_to_response(session)
181
+
182
+
183
+ @router.delete("/sessions/{session_id}", status_code=204)
184
+ async def stop_session(session_id: str) -> Response:
185
+ """Stop and remove a session.
186
+
187
+ Kills the tmux pane and removes the session from its project.
188
+
189
+ Args:
190
+ session_id: Unique session identifier
191
+
192
+ Returns:
193
+ Empty response with 204 status
194
+
195
+ Raises:
196
+ SessionNotFoundError: If session_id doesn't exist
197
+
198
+ Example:
199
+ DELETE /api/sessions/sess-456
200
+ Response: 204 No Content
201
+ """
202
+ registry = _get_registry()
203
+ tmux_orch = _get_tmux()
204
+
205
+ # Find session across all projects
206
+ session = None
207
+ parent_project_id = None
208
+
209
+ for project in registry.list_all():
210
+ if session_id in project.sessions:
211
+ session = project.sessions[session_id]
212
+ parent_project_id = project.id
213
+ break
214
+
215
+ if session is None or parent_project_id is None:
216
+ raise SessionNotFoundError(session_id)
217
+
218
+ # Kill tmux pane
219
+ try:
220
+ tmux_orch.kill_pane(session.tmux_target)
221
+ except Exception as e:
222
+ # Pane may already be dead, continue with cleanup
223
+ logger.debug("Failed to kill pane (may already be dead): %s", e)
224
+
225
+ # Remove session from project
226
+ registry.remove_session(parent_project_id, session_id)
227
+
228
+ return Response(status_code=204)