claude-mpm 5.4.85__py3-none-any.whl → 5.6.76__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 (322) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +8 -5
  3. claude_mpm/agents/{CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md → CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md} +14 -6
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +109 -706
  5. claude_mpm/agents/WORKFLOW.md +2 -0
  6. claude_mpm/agents/templates/circuit-breakers.md +26 -17
  7. claude_mpm/auth/__init__.py +35 -0
  8. claude_mpm/auth/callback_server.py +328 -0
  9. claude_mpm/auth/models.py +104 -0
  10. claude_mpm/auth/oauth_manager.py +266 -0
  11. claude_mpm/auth/providers/__init__.py +12 -0
  12. claude_mpm/auth/providers/base.py +165 -0
  13. claude_mpm/auth/providers/google.py +261 -0
  14. claude_mpm/auth/token_storage.py +252 -0
  15. claude_mpm/cli/commands/autotodos.py +566 -0
  16. claude_mpm/cli/commands/commander.py +216 -0
  17. claude_mpm/cli/commands/hook_errors.py +60 -60
  18. claude_mpm/cli/commands/mcp.py +29 -17
  19. claude_mpm/cli/commands/mcp_command_router.py +39 -0
  20. claude_mpm/cli/commands/mcp_service_commands.py +304 -0
  21. claude_mpm/cli/commands/monitor.py +2 -2
  22. claude_mpm/cli/commands/mpm_init/core.py +2 -2
  23. claude_mpm/cli/commands/oauth.py +481 -0
  24. claude_mpm/cli/commands/run.py +35 -3
  25. claude_mpm/cli/commands/skill_source.py +51 -2
  26. claude_mpm/cli/commands/skills.py +5 -3
  27. claude_mpm/cli/executor.py +128 -16
  28. claude_mpm/cli/helpers.py +1 -1
  29. claude_mpm/cli/parsers/base_parser.py +84 -1
  30. claude_mpm/cli/parsers/commander_parser.py +116 -0
  31. claude_mpm/cli/parsers/mcp_parser.py +79 -0
  32. claude_mpm/cli/parsers/oauth_parser.py +165 -0
  33. claude_mpm/cli/parsers/run_parser.py +10 -0
  34. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  35. claude_mpm/cli/parsers/skills_parser.py +5 -0
  36. claude_mpm/cli/startup.py +345 -40
  37. claude_mpm/cli/startup_display.py +76 -7
  38. claude_mpm/cli/startup_logging.py +2 -2
  39. claude_mpm/cli/startup_migrations.py +236 -0
  40. claude_mpm/cli/utils.py +7 -3
  41. claude_mpm/commander/__init__.py +78 -0
  42. claude_mpm/commander/adapters/__init__.py +60 -0
  43. claude_mpm/commander/adapters/auggie.py +260 -0
  44. claude_mpm/commander/adapters/base.py +288 -0
  45. claude_mpm/commander/adapters/claude_code.py +392 -0
  46. claude_mpm/commander/adapters/codex.py +237 -0
  47. claude_mpm/commander/adapters/communication.py +366 -0
  48. claude_mpm/commander/adapters/example_usage.py +310 -0
  49. claude_mpm/commander/adapters/mpm.py +389 -0
  50. claude_mpm/commander/adapters/registry.py +204 -0
  51. claude_mpm/commander/api/__init__.py +16 -0
  52. claude_mpm/commander/api/app.py +121 -0
  53. claude_mpm/commander/api/errors.py +133 -0
  54. claude_mpm/commander/api/routes/__init__.py +8 -0
  55. claude_mpm/commander/api/routes/events.py +184 -0
  56. claude_mpm/commander/api/routes/inbox.py +171 -0
  57. claude_mpm/commander/api/routes/messages.py +148 -0
  58. claude_mpm/commander/api/routes/projects.py +271 -0
  59. claude_mpm/commander/api/routes/sessions.py +226 -0
  60. claude_mpm/commander/api/routes/work.py +296 -0
  61. claude_mpm/commander/api/schemas.py +186 -0
  62. claude_mpm/commander/chat/__init__.py +7 -0
  63. claude_mpm/commander/chat/cli.py +149 -0
  64. claude_mpm/commander/chat/commands.py +124 -0
  65. claude_mpm/commander/chat/repl.py +1957 -0
  66. claude_mpm/commander/config.py +51 -0
  67. claude_mpm/commander/config_loader.py +115 -0
  68. claude_mpm/commander/core/__init__.py +10 -0
  69. claude_mpm/commander/core/block_manager.py +325 -0
  70. claude_mpm/commander/core/response_manager.py +323 -0
  71. claude_mpm/commander/daemon.py +603 -0
  72. claude_mpm/commander/env_loader.py +59 -0
  73. claude_mpm/commander/events/__init__.py +26 -0
  74. claude_mpm/commander/events/manager.py +392 -0
  75. claude_mpm/commander/frameworks/__init__.py +12 -0
  76. claude_mpm/commander/frameworks/base.py +233 -0
  77. claude_mpm/commander/frameworks/claude_code.py +58 -0
  78. claude_mpm/commander/frameworks/mpm.py +57 -0
  79. claude_mpm/commander/git/__init__.py +5 -0
  80. claude_mpm/commander/git/worktree_manager.py +212 -0
  81. claude_mpm/commander/inbox/__init__.py +16 -0
  82. claude_mpm/commander/inbox/dedup.py +128 -0
  83. claude_mpm/commander/inbox/inbox.py +224 -0
  84. claude_mpm/commander/inbox/models.py +70 -0
  85. claude_mpm/commander/instance_manager.py +868 -0
  86. claude_mpm/commander/llm/__init__.py +6 -0
  87. claude_mpm/commander/llm/openrouter_client.py +167 -0
  88. claude_mpm/commander/llm/summarizer.py +70 -0
  89. claude_mpm/commander/memory/__init__.py +45 -0
  90. claude_mpm/commander/memory/compression.py +347 -0
  91. claude_mpm/commander/memory/embeddings.py +230 -0
  92. claude_mpm/commander/memory/entities.py +310 -0
  93. claude_mpm/commander/memory/example_usage.py +290 -0
  94. claude_mpm/commander/memory/integration.py +325 -0
  95. claude_mpm/commander/memory/search.py +381 -0
  96. claude_mpm/commander/memory/store.py +657 -0
  97. claude_mpm/commander/models/__init__.py +18 -0
  98. claude_mpm/commander/models/events.py +127 -0
  99. claude_mpm/commander/models/project.py +162 -0
  100. claude_mpm/commander/models/work.py +214 -0
  101. claude_mpm/commander/parsing/__init__.py +20 -0
  102. claude_mpm/commander/parsing/extractor.py +132 -0
  103. claude_mpm/commander/parsing/output_parser.py +270 -0
  104. claude_mpm/commander/parsing/patterns.py +100 -0
  105. claude_mpm/commander/persistence/__init__.py +11 -0
  106. claude_mpm/commander/persistence/event_store.py +274 -0
  107. claude_mpm/commander/persistence/state_store.py +403 -0
  108. claude_mpm/commander/persistence/work_store.py +164 -0
  109. claude_mpm/commander/polling/__init__.py +13 -0
  110. claude_mpm/commander/polling/event_detector.py +104 -0
  111. claude_mpm/commander/polling/output_buffer.py +49 -0
  112. claude_mpm/commander/polling/output_poller.py +153 -0
  113. claude_mpm/commander/project_session.py +268 -0
  114. claude_mpm/commander/proxy/__init__.py +12 -0
  115. claude_mpm/commander/proxy/formatter.py +89 -0
  116. claude_mpm/commander/proxy/output_handler.py +191 -0
  117. claude_mpm/commander/proxy/relay.py +155 -0
  118. claude_mpm/commander/registry.py +410 -0
  119. claude_mpm/commander/runtime/__init__.py +10 -0
  120. claude_mpm/commander/runtime/executor.py +191 -0
  121. claude_mpm/commander/runtime/monitor.py +346 -0
  122. claude_mpm/commander/session/__init__.py +6 -0
  123. claude_mpm/commander/session/context.py +81 -0
  124. claude_mpm/commander/session/manager.py +59 -0
  125. claude_mpm/commander/tmux_orchestrator.py +362 -0
  126. claude_mpm/commander/web/__init__.py +1 -0
  127. claude_mpm/commander/work/__init__.py +30 -0
  128. claude_mpm/commander/work/executor.py +207 -0
  129. claude_mpm/commander/work/queue.py +405 -0
  130. claude_mpm/commander/workflow/__init__.py +27 -0
  131. claude_mpm/commander/workflow/event_handler.py +241 -0
  132. claude_mpm/commander/workflow/notifier.py +146 -0
  133. claude_mpm/commands/mpm-config.md +8 -0
  134. claude_mpm/commands/mpm-doctor.md +8 -0
  135. claude_mpm/commands/mpm-help.md +8 -0
  136. claude_mpm/commands/mpm-init.md +8 -0
  137. claude_mpm/commands/mpm-monitor.md +8 -0
  138. claude_mpm/commands/mpm-organize.md +8 -0
  139. claude_mpm/commands/mpm-postmortem.md +8 -0
  140. claude_mpm/commands/mpm-session-resume.md +9 -1
  141. claude_mpm/commands/mpm-status.md +8 -0
  142. claude_mpm/commands/mpm-ticket-view.md +8 -0
  143. claude_mpm/commands/mpm-version.md +8 -0
  144. claude_mpm/commands/mpm.md +8 -0
  145. claude_mpm/config/agent_presets.py +8 -7
  146. claude_mpm/config/skill_sources.py +16 -0
  147. claude_mpm/constants.py +5 -0
  148. claude_mpm/core/claude_runner.py +152 -0
  149. claude_mpm/core/config.py +35 -22
  150. claude_mpm/core/config_constants.py +74 -9
  151. claude_mpm/core/constants.py +56 -12
  152. claude_mpm/core/hook_manager.py +53 -4
  153. claude_mpm/core/interactive_session.py +5 -4
  154. claude_mpm/core/logger.py +26 -9
  155. claude_mpm/core/logging_utils.py +39 -13
  156. claude_mpm/core/network_config.py +148 -0
  157. claude_mpm/core/oneshot_session.py +7 -6
  158. claude_mpm/core/output_style_manager.py +52 -12
  159. claude_mpm/core/socketio_pool.py +47 -15
  160. claude_mpm/core/unified_config.py +10 -6
  161. claude_mpm/core/unified_paths.py +68 -80
  162. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  163. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  164. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cs_tUR18.js → 1WZnGYqX.js} +1 -1
  165. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CDuw-vjf.js → 67pF3qNn.js} +1 -1
  166. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bTOqqlTd.js → 6RxdMKe4.js} +1 -1
  167. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DwBR2MJi.js → 8cZrfX0h.js} +1 -1
  168. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{ZGh7QtNv.js → 9a6T2nm-.js} +1 -1
  169. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D9lljYKQ.js → B443AUzu.js} +1 -1
  170. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{RJiighC3.js → B8AwtY2H.js} +1 -1
  171. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uuIeMWc-.js → BF15LAsF.js} +1 -1
  172. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D3k0OPJN.js → BRcwIQNr.js} +1 -1
  173. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CyWMqx4W.js → BV6nKitt.js} +1 -1
  174. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CiIAseT4.js → BViJ8lZt.js} +5 -5
  175. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CBBdVcY8.js → BcQ-Q0FE.js} +1 -1
  176. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BovzEFCE.js → Bpyvgze_.js} +1 -1
  177. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  178. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  179. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{eNVUfhuA.js → C3rbW_a-.js} +1 -1
  180. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{GYwsonyD.js → C8WYN38h.js} +1 -1
  181. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BIF9m_hv.js → C9I8FlXH.js} +1 -1
  182. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B0uc0UOD.js → CIQcWgO2.js} +3 -3
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Be7GpZd6.js → CIctN7YN.js} +1 -1
  184. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Bh0LDWpI.js → CKrS_JZW.js} +2 -2
  185. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DUrLdbGD.js → CR6P9C4A.js} +1 -1
  186. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7xVLGWV.js → CRRR9MD_.js} +1 -1
  187. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  188. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dhb8PKl3.js → CSXtMOf0.js} +1 -1
  189. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BPYeabCQ.js → CT-sbxSk.js} +1 -1
  190. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{sQeU3Y1z.js → CWm6DJsp.js} +1 -1
  191. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CnA0NrzZ.js → CpqQ1Kzn.js} +1 -1
  192. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4B-KCzX.js → D2nGpDRe.js} +1 -1
  193. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DGkLK5U1.js → D9iCMida.js} +1 -1
  194. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BofRWZRR.js → D9ykgMoY.js} +1 -1
  195. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DmxopI1J.js → DL2Ldur1.js} +1 -1
  196. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C30mlcqg.js → DPfltzjH.js} +1 -1
  197. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Vzk33B_K.js → DR8nis88.js} +2 -2
  198. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DI7hHRFL.js → DUliQN2b.js} +1 -1
  199. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4JcI4KD.js → DXlhR01x.js} +1 -1
  200. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bT1r9zLR.js → D_lyTybS.js} +1 -1
  201. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DZX00Y4g.js → DngoTTgh.js} +1 -1
  202. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzZX-COe.js → DqkmHtDC.js} +1 -1
  203. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7RN905-.js → DsDh8EYs.js} +1 -1
  204. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DLVjFsZ3.js → DypDmXgd.js} +1 -1
  205. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{iEWssX7S.js → IPYC-LnN.js} +1 -1
  206. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  207. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DaimHw_p.js → JpevfAFt.js} +1 -1
  208. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DY1XQ8fi.js → R8CEIRAd.js} +1 -1
  209. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dle-35c7.js → Zxy7qc-l.js} +2 -2
  210. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  211. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C_Usid8X.js → qtd3IeO4.js} +2 -2
  212. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzeYkLYB.js → ulBFON_C.js} +2 -2
  213. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cfqx1Qun.js → wQVh1CoA.js} +1 -1
  214. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/{app.D6-I5TpK.js → app.Dr7t0z2J.js} +2 -2
  215. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  216. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.m1gL8KXf.js → 0.RgBboRvH.js} +1 -1
  217. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{1.CgNOuw-d.js → 1.DG-KkbDf.js} +1 -1
  218. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  219. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
  220. claude_mpm/dashboard/static/svelte-build/index.html +9 -9
  221. claude_mpm/experimental/cli_enhancements.py +2 -1
  222. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  223. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  224. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
  225. claude_mpm/hooks/claude_hooks/event_handlers.py +466 -136
  226. claude_mpm/hooks/claude_hooks/hook_handler.py +204 -104
  227. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  228. claude_mpm/hooks/claude_hooks/installer.py +291 -59
  229. claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
  230. claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
  231. claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
  232. claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
  233. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
  234. claude_mpm/hooks/claude_hooks/services/container.py +326 -0
  235. claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
  236. claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
  237. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
  238. claude_mpm/hooks/session_resume_hook.py +89 -1
  239. claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
  240. claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
  241. claude_mpm/init.py +22 -15
  242. claude_mpm/mcp/__init__.py +9 -0
  243. claude_mpm/mcp/google_workspace_server.py +610 -0
  244. claude_mpm/scripts/claude-hook-handler.sh +46 -19
  245. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  246. claude_mpm/services/agents/agent_selection_service.py +2 -2
  247. claude_mpm/services/agents/cache_git_manager.py +1 -1
  248. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +3 -0
  249. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  250. claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
  251. claude_mpm/services/cli/__init__.py +3 -0
  252. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  253. claude_mpm/services/cli/session_resume_helper.py +10 -2
  254. claude_mpm/services/command_deployment_service.py +44 -26
  255. claude_mpm/services/delegation_detector.py +175 -0
  256. claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
  257. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  258. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  259. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  260. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  261. claude_mpm/services/diagnostics/models.py +14 -1
  262. claude_mpm/services/event_log.py +325 -0
  263. claude_mpm/services/hook_installer_service.py +77 -8
  264. claude_mpm/services/infrastructure/__init__.py +4 -0
  265. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  266. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  267. claude_mpm/services/mcp_config_manager.py +99 -19
  268. claude_mpm/services/mcp_service_registry.py +294 -0
  269. claude_mpm/services/monitor/daemon_manager.py +15 -4
  270. claude_mpm/services/monitor/management/lifecycle.py +8 -2
  271. claude_mpm/services/monitor/server.py +111 -16
  272. claude_mpm/services/pm_skills_deployer.py +261 -87
  273. claude_mpm/services/skills/git_skill_source_manager.py +130 -10
  274. claude_mpm/services/skills/selective_skill_deployer.py +142 -16
  275. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  276. claude_mpm/services/skills_deployer.py +31 -5
  277. claude_mpm/services/socketio/handlers/hook.py +14 -7
  278. claude_mpm/services/socketio/server/main.py +12 -4
  279. claude_mpm/skills/__init__.py +2 -1
  280. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  281. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  282. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  283. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  284. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  285. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  286. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  287. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  288. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  289. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  290. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  291. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  292. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  293. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  294. claude_mpm/skills/bundled/pm/{pm-teaching-mode → mpm-teaching-mode}/SKILL.md +2 -2
  295. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  296. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  297. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  298. claude_mpm/skills/registry.py +295 -90
  299. claude_mpm/skills/skill_manager.py +4 -4
  300. claude_mpm-5.6.76.dist-info/METADATA +416 -0
  301. {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/RECORD +312 -175
  302. {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/WHEEL +1 -1
  303. {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/entry_points.txt +2 -0
  304. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +0 -1
  305. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +0 -1
  306. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +0 -1
  307. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +0 -24
  308. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +0 -1
  309. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +0 -1
  310. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +0 -323
  311. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +0 -1
  312. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +0 -1
  313. claude_mpm-5.4.85.dist-info/METADATA +0 -1023
  314. /claude_mpm/skills/bundled/pm/{pm-bug-reporting/pm-bug-reporting.md → mpm-bug-reporting/SKILL.md} +0 -0
  315. /claude_mpm/skills/bundled/pm/{pm-delegation-patterns → mpm-delegation-patterns}/SKILL.md +0 -0
  316. /claude_mpm/skills/bundled/pm/{pm-git-file-tracking → mpm-git-file-tracking}/SKILL.md +0 -0
  317. /claude_mpm/skills/bundled/pm/{pm-pr-workflow → mpm-pr-workflow}/SKILL.md +0 -0
  318. /claude_mpm/skills/bundled/pm/{pm-ticketing-integration → mpm-ticketing-integration}/SKILL.md +0 -0
  319. /claude_mpm/skills/bundled/pm/{pm-verification-protocols → mpm-verification-protocols}/SKILL.md +0 -0
  320. {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/licenses/LICENSE +0 -0
  321. {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  322. {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,485 @@
1
+ #!/usr/bin/env python3
2
+ """Auto-pause handler for Claude Code hooks.
3
+
4
+ WHY: Automatically pause Claude sessions when context usage reaches 90% to prevent
5
+ context window exhaustion. Integrates with existing hook infrastructure to monitor
6
+ token usage and trigger incremental pause capture.
7
+
8
+ DESIGN DECISIONS:
9
+ - Integrates with ContextUsageTracker for token tracking across hook invocations
10
+ - Uses IncrementalPauseManager for capturing actions during pause mode
11
+ - Thread-safe - handles hook calls from multiple processes via file-based state
12
+ - Emits warnings to stderr for visibility without breaking hook flow
13
+ - Only triggers auto-pause on NEW threshold crossings (prevents duplicate warnings)
14
+ - Graceful error handling - auto-pause failures don't break main hook processing
15
+
16
+ USAGE:
17
+ # Initialize handler in hook handler
18
+ auto_pause = AutoPauseHandler()
19
+
20
+ # Monitor token usage from API responses
21
+ if "usage" in metadata:
22
+ threshold_crossed = auto_pause.on_usage_update(metadata["usage"])
23
+ if threshold_crossed:
24
+ warning = auto_pause.emit_threshold_warning(threshold_crossed)
25
+ _log(f"\n⚠️ {warning}")
26
+
27
+ # Record actions during pause mode
28
+ if auto_pause.is_pause_active():
29
+ auto_pause.on_tool_call(tool_name, tool_args)
30
+ auto_pause.on_assistant_response(response_summary)
31
+
32
+ # Finalize on session end
33
+ session_file = auto_pause.on_session_end()
34
+ """
35
+
36
+ import os
37
+ from datetime import datetime, timezone
38
+ from pathlib import Path
39
+ from typing import Any, Dict, Optional
40
+
41
+ from claude_mpm.core.logger import get_logger
42
+ from claude_mpm.services.cli.incremental_pause_manager import IncrementalPauseManager
43
+ from claude_mpm.services.infrastructure.context_usage_tracker import (
44
+ ContextUsageTracker,
45
+ )
46
+
47
+ # Try to import _log from hook_handler, fall back to no-op
48
+ try:
49
+ from claude_mpm.hooks.claude_hooks.hook_handler import _log
50
+ except ImportError:
51
+
52
+ def _log(msg: str) -> None:
53
+ pass # Silent fallback
54
+
55
+
56
+ logger = get_logger(__name__)
57
+
58
+ # Debug mode
59
+ DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "false").lower() == "true"
60
+
61
+ # Warning messages for threshold crossings
62
+ THRESHOLD_WARNINGS = {
63
+ "caution": "Context usage at 70%. Consider wrapping up current work.",
64
+ "warning": "Context usage at 85%. Session nearing capacity.",
65
+ "auto_pause": "Context usage at 90%. Auto-pause activated. Actions are being recorded for session continuity.",
66
+ "critical": "Context usage at 95%. Session nearly exhausted. Wrapping up...",
67
+ }
68
+
69
+ # Maximum length for summaries to avoid storing full responses
70
+ MAX_SUMMARY_LENGTH = 500
71
+
72
+
73
+ class AutoPauseHandler:
74
+ """Handler for automatic session pausing based on context usage thresholds.
75
+
76
+ Integrates with Claude Code hooks to:
77
+ 1. Track cumulative token usage from API responses
78
+ 2. Trigger auto-pause when 90% context used
79
+ 3. Capture all subsequent actions during pause mode
80
+ 4. Emit warnings/notifications to user
81
+
82
+ Features:
83
+ - File-based state persistence (works across hook process restarts)
84
+ - Thread-safe through atomic file operations
85
+ - Graceful error handling (failures don't break main hook flow)
86
+ - Only emits warnings on NEW threshold crossings
87
+ - Summarizes long content to prevent memory bloat
88
+ """
89
+
90
+ def __init__(self, project_path: Optional[Path] = None):
91
+ """Initialize auto-pause handler.
92
+
93
+ Args:
94
+ project_path: Project root path (default: current directory)
95
+ """
96
+ self.project_path = (project_path or Path.cwd()).resolve()
97
+
98
+ # Initialize services
99
+ self.tracker = ContextUsageTracker(self.project_path)
100
+ self.pause_manager = IncrementalPauseManager(self.project_path)
101
+
102
+ # Track previous threshold to detect NEW crossings
103
+ self._previous_threshold: Optional[str] = None
104
+
105
+ # Load initial state
106
+ try:
107
+ current_state = self.tracker.get_current_state()
108
+ self._previous_threshold = current_state.threshold_reached
109
+
110
+ if DEBUG:
111
+ _log(
112
+ f"AutoPauseHandler initialized: "
113
+ f"{current_state.percentage_used:.1f}% context used, "
114
+ f"threshold: {current_state.threshold_reached}"
115
+ )
116
+ except Exception as e:
117
+ logger.error(f"Failed to initialize AutoPauseHandler: {e}")
118
+ # Continue with None - will initialize on first update
119
+
120
+ def on_usage_update(self, usage: Dict[str, Any]) -> Optional[str]:
121
+ """Process token usage from a Claude API response.
122
+
123
+ Args:
124
+ usage: Dict with 'input_tokens', 'output_tokens',
125
+ 'cache_creation_input_tokens', 'cache_read_input_tokens'
126
+
127
+ Returns:
128
+ Threshold name if a NEW threshold was crossed ('caution', 'warning',
129
+ 'auto_pause', 'critical'), or None if no new threshold crossed.
130
+
131
+ Raises:
132
+ ValueError: If usage data is invalid
133
+ """
134
+ try:
135
+ # Extract token counts
136
+ input_tokens = usage.get("input_tokens", 0)
137
+ output_tokens = usage.get("output_tokens", 0)
138
+ cache_creation = usage.get("cache_creation_input_tokens", 0)
139
+ cache_read = usage.get("cache_read_input_tokens", 0)
140
+
141
+ # Validate token counts
142
+ if any(
143
+ t < 0 for t in [input_tokens, output_tokens, cache_creation, cache_read]
144
+ ):
145
+ raise ValueError("Token counts cannot be negative")
146
+
147
+ # Update cumulative usage
148
+ state = self.tracker.update_usage(
149
+ input_tokens=input_tokens,
150
+ output_tokens=output_tokens,
151
+ cache_creation=cache_creation,
152
+ cache_read=cache_read,
153
+ )
154
+
155
+ # Check if we crossed a NEW threshold
156
+ current_threshold = state.threshold_reached
157
+ new_threshold_crossed = None
158
+
159
+ if current_threshold != self._previous_threshold:
160
+ # Determine if this is a higher threshold
161
+ threshold_order = ["caution", "warning", "auto_pause", "critical"]
162
+
163
+ prev_idx = (
164
+ threshold_order.index(self._previous_threshold)
165
+ if self._previous_threshold in threshold_order
166
+ else -1
167
+ )
168
+ curr_idx = (
169
+ threshold_order.index(current_threshold)
170
+ if current_threshold in threshold_order
171
+ else -1
172
+ )
173
+
174
+ if curr_idx > prev_idx:
175
+ new_threshold_crossed = current_threshold
176
+ self._previous_threshold = current_threshold
177
+
178
+ if DEBUG:
179
+ _log(
180
+ f"Context threshold crossed: {current_threshold} "
181
+ f"({state.percentage_used:.1f}%)"
182
+ )
183
+
184
+ # Trigger auto-pause if threshold reached
185
+ if current_threshold in ["auto_pause", "critical"]:
186
+ self._trigger_auto_pause(state)
187
+
188
+ return new_threshold_crossed
189
+
190
+ except Exception as e:
191
+ logger.error(f"Failed to update usage: {e}")
192
+ if DEBUG:
193
+ _log(f"❌ Usage update failed: {e}")
194
+ # Don't propagate error - auto-pause is optional
195
+ return None
196
+
197
+ def on_tool_call(self, tool_name: str, tool_args: Dict[str, Any]) -> None:
198
+ """Record a tool call if auto-pause is active.
199
+
200
+ Args:
201
+ tool_name: Name of the tool being called
202
+ tool_args: Tool arguments dictionary
203
+
204
+ Raises:
205
+ RuntimeError: If append operation fails (optional, logged only)
206
+ """
207
+ if not self.is_pause_active():
208
+ return
209
+
210
+ try:
211
+ # Summarize tool args to avoid storing large data
212
+ args_summary = self._summarize_dict(tool_args)
213
+
214
+ # Get current context percentage
215
+ state = self.tracker.get_current_state()
216
+
217
+ # Record action
218
+ self.pause_manager.append_action(
219
+ action_type="tool_call",
220
+ action_data={
221
+ "tool": tool_name,
222
+ "args_summary": args_summary,
223
+ "timestamp": datetime.now(timezone.utc).isoformat(),
224
+ },
225
+ context_percentage=state.percentage_used / 100,
226
+ )
227
+
228
+ if DEBUG:
229
+ _log(f"Recorded tool call during pause: {tool_name}")
230
+
231
+ except Exception as e:
232
+ logger.error(f"Failed to record tool call: {e}")
233
+ if DEBUG:
234
+ _log(f"❌ Failed to record tool call: {e}")
235
+
236
+ def on_assistant_response(self, response_summary: str) -> None:
237
+ """Record an assistant response if auto-pause is active.
238
+
239
+ Args:
240
+ response_summary: Summary of assistant response (will be truncated)
241
+
242
+ Raises:
243
+ RuntimeError: If append operation fails (optional, logged only)
244
+ """
245
+ if not self.is_pause_active():
246
+ return
247
+
248
+ try:
249
+ # Truncate long responses
250
+ summary = self._truncate_text(response_summary, MAX_SUMMARY_LENGTH)
251
+
252
+ # Get current context percentage
253
+ state = self.tracker.get_current_state()
254
+
255
+ # Record action
256
+ self.pause_manager.append_action(
257
+ action_type="assistant_response",
258
+ action_data={
259
+ "summary": summary,
260
+ "timestamp": datetime.now(timezone.utc).isoformat(),
261
+ },
262
+ context_percentage=state.percentage_used / 100,
263
+ )
264
+
265
+ if DEBUG:
266
+ _log(
267
+ f"Recorded assistant response during pause (length: {len(summary)})"
268
+ )
269
+
270
+ except Exception as e:
271
+ logger.error(f"Failed to record assistant response: {e}")
272
+ if DEBUG:
273
+ _log(f"❌ Failed to record assistant response: {e}")
274
+
275
+ def on_user_message(self, message_summary: str) -> None:
276
+ """Record a user message if auto-pause is active.
277
+
278
+ Args:
279
+ message_summary: Summary of user message (will be truncated)
280
+
281
+ Raises:
282
+ RuntimeError: If append operation fails (optional, logged only)
283
+ """
284
+ if not self.is_pause_active():
285
+ return
286
+
287
+ try:
288
+ # Truncate long messages
289
+ summary = self._truncate_text(message_summary, MAX_SUMMARY_LENGTH)
290
+
291
+ # Get current context percentage
292
+ state = self.tracker.get_current_state()
293
+
294
+ # Record action
295
+ self.pause_manager.append_action(
296
+ action_type="user_message",
297
+ action_data={
298
+ "summary": summary,
299
+ "timestamp": datetime.now(timezone.utc).isoformat(),
300
+ },
301
+ context_percentage=state.percentage_used / 100,
302
+ )
303
+
304
+ if DEBUG:
305
+ _log(f"Recorded user message during pause (length: {len(summary)})")
306
+
307
+ except Exception as e:
308
+ logger.error(f"Failed to record user message: {e}")
309
+ if DEBUG:
310
+ _log(f"❌ Failed to record user message: {e}")
311
+
312
+ def on_session_end(self) -> Optional[Path]:
313
+ """Called when session ends. Finalizes any active pause.
314
+
315
+ Returns:
316
+ Path to finalized session file, or None if no pause was active.
317
+
318
+ Raises:
319
+ RuntimeError: If finalization fails
320
+ """
321
+ if not self.is_pause_active():
322
+ if DEBUG:
323
+ _log("No active pause to finalize")
324
+ return None
325
+
326
+ try:
327
+ # Finalize the pause session
328
+ session_path = self.pause_manager.finalize_pause(create_full_snapshot=True)
329
+
330
+ if session_path and DEBUG:
331
+ _log(f"✅ Session finalized: {session_path.name}")
332
+
333
+ return session_path
334
+
335
+ except Exception as e:
336
+ logger.error(f"Failed to finalize pause session: {e}")
337
+ if DEBUG:
338
+ _log(f"❌ Failed to finalize pause: {e}")
339
+ raise
340
+
341
+ def is_pause_active(self) -> bool:
342
+ """Check if auto-pause mode is currently active.
343
+
344
+ Returns:
345
+ True if auto-pause has been triggered and is capturing actions
346
+ """
347
+ return self.pause_manager.is_pause_active()
348
+
349
+ def get_status(self) -> Dict[str, Any]:
350
+ """Get current status for display/logging.
351
+
352
+ Returns:
353
+ Dict with: context_percentage, threshold_reached,
354
+ pause_active, actions_recorded, etc.
355
+ """
356
+ try:
357
+ state = self.tracker.get_current_state()
358
+ pause_summary = self.pause_manager.get_pause_summary()
359
+
360
+ status = {
361
+ "context_percentage": round(state.percentage_used, 2),
362
+ "threshold_reached": state.threshold_reached,
363
+ "auto_pause_active": state.auto_pause_active,
364
+ "pause_active": self.is_pause_active(),
365
+ "session_id": state.session_id,
366
+ "total_tokens": (
367
+ state.cumulative_input_tokens + state.cumulative_output_tokens
368
+ ),
369
+ "budget": ContextUsageTracker.CONTEXT_BUDGET,
370
+ }
371
+
372
+ # Add pause details if active
373
+ if pause_summary:
374
+ status["pause_details"] = {
375
+ "action_count": pause_summary["action_count"],
376
+ "duration_seconds": pause_summary["duration_seconds"],
377
+ "context_range": pause_summary["context_range"],
378
+ "last_action_type": pause_summary["last_action_type"],
379
+ }
380
+
381
+ return status
382
+
383
+ except Exception as e:
384
+ logger.error(f"Failed to get status: {e}")
385
+ return {"error": str(e)}
386
+
387
+ def emit_threshold_warning(self, threshold: str) -> str:
388
+ """Generate a warning message for threshold crossing.
389
+
390
+ Args:
391
+ threshold: Threshold name ('caution', 'warning', 'auto_pause', 'critical')
392
+
393
+ Returns:
394
+ User-friendly warning message string
395
+ """
396
+ warning = THRESHOLD_WARNINGS.get(
397
+ threshold, f"Context usage threshold reached: {threshold}"
398
+ )
399
+
400
+ # Add context percentage to warning
401
+ try:
402
+ state = self.tracker.get_current_state()
403
+ warning = f"{warning} ({state.percentage_used:.1f}%)"
404
+ except Exception:
405
+ pass # nosec B110 - Intentionally ignore formatting errors, warning is already constructed
406
+
407
+ return warning
408
+
409
+ def _trigger_auto_pause(self, state) -> None:
410
+ """Trigger auto-pause and start recording actions.
411
+
412
+ Args:
413
+ state: Current context usage state
414
+
415
+ Raises:
416
+ RuntimeError: If pause cannot be started
417
+ """
418
+ try:
419
+ # Check if pause is already active
420
+ if self.is_pause_active():
421
+ if DEBUG:
422
+ _log("Auto-pause already active, skipping trigger")
423
+ return
424
+
425
+ # Start incremental pause
426
+ session_id = self.pause_manager.start_incremental_pause(
427
+ context_percentage=state.percentage_used / 100,
428
+ initial_state=state.__dict__,
429
+ )
430
+
431
+ if DEBUG:
432
+ _log(
433
+ f"✅ Auto-pause triggered: {session_id} "
434
+ f"({state.percentage_used:.1f}% context used)"
435
+ )
436
+
437
+ except Exception as e:
438
+ logger.error(f"Failed to trigger auto-pause: {e}")
439
+ if DEBUG:
440
+ _log(f"❌ Failed to trigger auto-pause: {e}")
441
+ # Don't propagate - auto-pause is optional
442
+
443
+ def _summarize_dict(
444
+ self, data: Dict[str, Any], max_items: int = 10
445
+ ) -> Dict[str, Any]:
446
+ """Create a summary of a dictionary by limiting items and truncating values.
447
+
448
+ Args:
449
+ data: Dictionary to summarize
450
+ max_items: Maximum number of items to include
451
+
452
+ Returns:
453
+ Summarized dictionary
454
+ """
455
+ summary = {}
456
+
457
+ for i, (key, value) in enumerate(data.items()):
458
+ if i >= max_items:
459
+ summary["..."] = f"({len(data) - max_items} more items)"
460
+ break
461
+
462
+ # Truncate string values
463
+ if isinstance(value, str):
464
+ summary[key] = self._truncate_text(value, 100)
465
+ elif isinstance(value, (list, dict)):
466
+ summary[key] = f"<{type(value).__name__} with {len(value)} items>"
467
+ else:
468
+ summary[key] = str(value)[:100]
469
+
470
+ return summary
471
+
472
+ def _truncate_text(self, text: str, max_length: int) -> str:
473
+ """Truncate text to maximum length with ellipsis.
474
+
475
+ Args:
476
+ text: Text to truncate
477
+ max_length: Maximum length
478
+
479
+ Returns:
480
+ Truncated text with "..." suffix if truncated
481
+ """
482
+ if len(text) <= max_length:
483
+ return text
484
+
485
+ return text[: max_length - 3] + "..."