claude-mpm 5.4.55__py3-none-any.whl → 5.6.1__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 (401) 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 +111 -686
  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/skills.py +166 -14
  19. claude_mpm/cli/executor.py +120 -16
  20. claude_mpm/cli/interactive/__init__.py +10 -0
  21. claude_mpm/cli/interactive/agent_wizard.py +30 -50
  22. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  23. claude_mpm/cli/interactive/skill_selector.py +481 -0
  24. claude_mpm/cli/parsers/base_parser.py +76 -1
  25. claude_mpm/cli/parsers/commander_parser.py +83 -0
  26. claude_mpm/cli/parsers/run_parser.py +10 -0
  27. claude_mpm/cli/startup.py +276 -403
  28. claude_mpm/cli/startup_display.py +72 -5
  29. claude_mpm/cli/startup_logging.py +2 -2
  30. claude_mpm/cli/utils.py +7 -3
  31. claude_mpm/commander/__init__.py +72 -0
  32. claude_mpm/commander/adapters/__init__.py +31 -0
  33. claude_mpm/commander/adapters/base.py +191 -0
  34. claude_mpm/commander/adapters/claude_code.py +361 -0
  35. claude_mpm/commander/adapters/communication.py +366 -0
  36. claude_mpm/commander/api/__init__.py +16 -0
  37. claude_mpm/commander/api/app.py +105 -0
  38. claude_mpm/commander/api/errors.py +112 -0
  39. claude_mpm/commander/api/routes/__init__.py +8 -0
  40. claude_mpm/commander/api/routes/events.py +184 -0
  41. claude_mpm/commander/api/routes/inbox.py +171 -0
  42. claude_mpm/commander/api/routes/messages.py +148 -0
  43. claude_mpm/commander/api/routes/projects.py +271 -0
  44. claude_mpm/commander/api/routes/sessions.py +215 -0
  45. claude_mpm/commander/api/routes/work.py +260 -0
  46. claude_mpm/commander/api/schemas.py +182 -0
  47. claude_mpm/commander/chat/__init__.py +7 -0
  48. claude_mpm/commander/chat/cli.py +107 -0
  49. claude_mpm/commander/chat/commands.py +96 -0
  50. claude_mpm/commander/chat/repl.py +310 -0
  51. claude_mpm/commander/config.py +49 -0
  52. claude_mpm/commander/config_loader.py +115 -0
  53. claude_mpm/commander/daemon.py +398 -0
  54. claude_mpm/commander/events/__init__.py +26 -0
  55. claude_mpm/commander/events/manager.py +332 -0
  56. claude_mpm/commander/frameworks/__init__.py +12 -0
  57. claude_mpm/commander/frameworks/base.py +143 -0
  58. claude_mpm/commander/frameworks/claude_code.py +58 -0
  59. claude_mpm/commander/frameworks/mpm.py +62 -0
  60. claude_mpm/commander/inbox/__init__.py +16 -0
  61. claude_mpm/commander/inbox/dedup.py +128 -0
  62. claude_mpm/commander/inbox/inbox.py +224 -0
  63. claude_mpm/commander/inbox/models.py +70 -0
  64. claude_mpm/commander/instance_manager.py +337 -0
  65. claude_mpm/commander/llm/__init__.py +6 -0
  66. claude_mpm/commander/llm/openrouter_client.py +167 -0
  67. claude_mpm/commander/llm/summarizer.py +70 -0
  68. claude_mpm/commander/models/__init__.py +18 -0
  69. claude_mpm/commander/models/events.py +121 -0
  70. claude_mpm/commander/models/project.py +162 -0
  71. claude_mpm/commander/models/work.py +214 -0
  72. claude_mpm/commander/parsing/__init__.py +20 -0
  73. claude_mpm/commander/parsing/extractor.py +132 -0
  74. claude_mpm/commander/parsing/output_parser.py +270 -0
  75. claude_mpm/commander/parsing/patterns.py +100 -0
  76. claude_mpm/commander/persistence/__init__.py +11 -0
  77. claude_mpm/commander/persistence/event_store.py +274 -0
  78. claude_mpm/commander/persistence/state_store.py +309 -0
  79. claude_mpm/commander/persistence/work_store.py +164 -0
  80. claude_mpm/commander/polling/__init__.py +13 -0
  81. claude_mpm/commander/polling/event_detector.py +104 -0
  82. claude_mpm/commander/polling/output_buffer.py +49 -0
  83. claude_mpm/commander/polling/output_poller.py +153 -0
  84. claude_mpm/commander/project_session.py +268 -0
  85. claude_mpm/commander/proxy/__init__.py +12 -0
  86. claude_mpm/commander/proxy/formatter.py +89 -0
  87. claude_mpm/commander/proxy/output_handler.py +191 -0
  88. claude_mpm/commander/proxy/relay.py +155 -0
  89. claude_mpm/commander/registry.py +404 -0
  90. claude_mpm/commander/runtime/__init__.py +10 -0
  91. claude_mpm/commander/runtime/executor.py +191 -0
  92. claude_mpm/commander/runtime/monitor.py +316 -0
  93. claude_mpm/commander/session/__init__.py +6 -0
  94. claude_mpm/commander/session/context.py +81 -0
  95. claude_mpm/commander/session/manager.py +59 -0
  96. claude_mpm/commander/tmux_orchestrator.py +361 -0
  97. claude_mpm/commander/web/__init__.py +1 -0
  98. claude_mpm/commander/work/__init__.py +30 -0
  99. claude_mpm/commander/work/executor.py +189 -0
  100. claude_mpm/commander/work/queue.py +405 -0
  101. claude_mpm/commander/workflow/__init__.py +27 -0
  102. claude_mpm/commander/workflow/event_handler.py +219 -0
  103. claude_mpm/commander/workflow/notifier.py +146 -0
  104. claude_mpm/commands/mpm-config.md +8 -0
  105. claude_mpm/commands/mpm-doctor.md +8 -0
  106. claude_mpm/commands/mpm-help.md +8 -0
  107. claude_mpm/commands/mpm-init.md +8 -0
  108. claude_mpm/commands/mpm-monitor.md +8 -0
  109. claude_mpm/commands/mpm-organize.md +8 -0
  110. claude_mpm/commands/mpm-postmortem.md +8 -0
  111. claude_mpm/commands/mpm-session-resume.md +9 -1
  112. claude_mpm/commands/mpm-status.md +8 -0
  113. claude_mpm/commands/mpm-ticket-view.md +8 -0
  114. claude_mpm/commands/mpm-version.md +8 -0
  115. claude_mpm/commands/mpm.md +8 -0
  116. claude_mpm/config/agent_presets.py +8 -7
  117. claude_mpm/constants.py +1 -0
  118. claude_mpm/core/claude_runner.py +2 -2
  119. claude_mpm/core/config.py +5 -0
  120. claude_mpm/core/hook_manager.py +51 -3
  121. claude_mpm/core/interactive_session.py +7 -7
  122. claude_mpm/core/logger.py +10 -7
  123. claude_mpm/core/logging_utils.py +4 -2
  124. claude_mpm/core/output_style_manager.py +31 -13
  125. claude_mpm/core/unified_config.py +54 -8
  126. claude_mpm/core/unified_paths.py +30 -13
  127. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  128. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  129. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cs_tUR18.js → 1WZnGYqX.js} +1 -1
  130. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CDuw-vjf.js → 67pF3qNn.js} +1 -1
  131. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bTOqqlTd.js → 6RxdMKe4.js} +1 -1
  132. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DwBR2MJi.js → 8cZrfX0h.js} +1 -1
  133. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{ZGh7QtNv.js → 9a6T2nm-.js} +1 -1
  134. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D9lljYKQ.js → B443AUzu.js} +1 -1
  135. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{RJiighC3.js → B8AwtY2H.js} +1 -1
  136. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uuIeMWc-.js → BF15LAsF.js} +1 -1
  137. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D3k0OPJN.js → BRcwIQNr.js} +1 -1
  138. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CyWMqx4W.js → BV6nKitt.js} +1 -1
  139. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CiIAseT4.js → BViJ8lZt.js} +5 -5
  140. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CBBdVcY8.js → BcQ-Q0FE.js} +1 -1
  141. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BovzEFCE.js → Bpyvgze_.js} +1 -1
  142. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  143. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  144. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{eNVUfhuA.js → C3rbW_a-.js} +1 -1
  145. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{GYwsonyD.js → C8WYN38h.js} +1 -1
  146. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BIF9m_hv.js → C9I8FlXH.js} +1 -1
  147. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B0uc0UOD.js → CIQcWgO2.js} +3 -3
  148. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Be7GpZd6.js → CIctN7YN.js} +1 -1
  149. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Bh0LDWpI.js → CKrS_JZW.js} +2 -2
  150. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DUrLdbGD.js → CR6P9C4A.js} +1 -1
  151. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7xVLGWV.js → CRRR9MD_.js} +1 -1
  152. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  153. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dhb8PKl3.js → CSXtMOf0.js} +1 -1
  154. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BPYeabCQ.js → CT-sbxSk.js} +1 -1
  155. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{sQeU3Y1z.js → CWm6DJsp.js} +1 -1
  156. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CnA0NrzZ.js → CpqQ1Kzn.js} +1 -1
  157. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4B-KCzX.js → D2nGpDRe.js} +1 -1
  158. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DGkLK5U1.js → D9iCMida.js} +1 -1
  159. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BofRWZRR.js → D9ykgMoY.js} +1 -1
  160. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DmxopI1J.js → DL2Ldur1.js} +1 -1
  161. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C30mlcqg.js → DPfltzjH.js} +1 -1
  162. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Vzk33B_K.js → DR8nis88.js} +2 -2
  163. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DI7hHRFL.js → DUliQN2b.js} +1 -1
  164. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4JcI4KD.js → DXlhR01x.js} +1 -1
  165. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bT1r9zLR.js → D_lyTybS.js} +1 -1
  166. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DZX00Y4g.js → DngoTTgh.js} +1 -1
  167. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzZX-COe.js → DqkmHtDC.js} +1 -1
  168. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7RN905-.js → DsDh8EYs.js} +1 -1
  169. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DLVjFsZ3.js → DypDmXgd.js} +1 -1
  170. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{iEWssX7S.js → IPYC-LnN.js} +1 -1
  171. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  172. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DaimHw_p.js → JpevfAFt.js} +1 -1
  173. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DY1XQ8fi.js → R8CEIRAd.js} +1 -1
  174. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dle-35c7.js → Zxy7qc-l.js} +2 -2
  175. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  176. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C_Usid8X.js → qtd3IeO4.js} +2 -2
  177. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzeYkLYB.js → ulBFON_C.js} +2 -2
  178. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cfqx1Qun.js → wQVh1CoA.js} +1 -1
  179. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/{app.D6-I5TpK.js → app.Dr7t0z2J.js} +2 -2
  180. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  181. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.m1gL8KXf.js → 0.RgBboRvH.js} +1 -1
  182. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{1.CgNOuw-d.js → 1.DG-KkbDf.js} +1 -1
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  184. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
  185. claude_mpm/dashboard/static/svelte-build/index.html +9 -9
  186. claude_mpm/experimental/cli_enhancements.py +2 -1
  187. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  188. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  189. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +486 -0
  190. claude_mpm/hooks/claude_hooks/event_handlers.py +250 -11
  191. claude_mpm/hooks/claude_hooks/hook_handler.py +106 -89
  192. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  193. claude_mpm/hooks/claude_hooks/installer.py +69 -5
  194. claude_mpm/hooks/claude_hooks/response_tracking.py +3 -1
  195. claude_mpm/hooks/claude_hooks/services/connection_manager.py +20 -0
  196. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +14 -77
  197. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +30 -6
  198. claude_mpm/hooks/session_resume_hook.py +85 -1
  199. claude_mpm/init.py +1 -1
  200. claude_mpm/scripts/claude-hook-handler.sh +36 -10
  201. claude_mpm/scripts/start_activity_logging.py +0 -0
  202. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  203. claude_mpm/services/agents/cache_git_manager.py +1 -1
  204. claude_mpm/services/agents/deployment/agent_template_builder.py +8 -0
  205. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  206. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +3 -0
  207. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  208. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  209. claude_mpm/services/agents/sources/git_source_sync_service.py +7 -4
  210. claude_mpm/services/agents/startup_sync.py +5 -2
  211. claude_mpm/services/cli/__init__.py +3 -0
  212. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  213. claude_mpm/services/cli/session_resume_helper.py +10 -2
  214. claude_mpm/services/delegation_detector.py +175 -0
  215. claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
  216. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  217. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  218. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  219. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  220. claude_mpm/services/diagnostics/models.py +14 -1
  221. claude_mpm/services/event_log.py +325 -0
  222. claude_mpm/services/infrastructure/__init__.py +4 -0
  223. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  224. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  225. claude_mpm/services/monitor/daemon_manager.py +15 -4
  226. claude_mpm/services/monitor/management/lifecycle.py +8 -2
  227. claude_mpm/services/monitor/server.py +106 -16
  228. claude_mpm/services/pm_skills_deployer.py +261 -85
  229. claude_mpm/services/skills/git_skill_source_manager.py +75 -10
  230. claude_mpm/services/skills/selective_skill_deployer.py +177 -80
  231. claude_mpm/services/skills/skill_discovery_service.py +57 -3
  232. claude_mpm/services/socketio/handlers/hook.py +14 -7
  233. claude_mpm/services/socketio/server/main.py +12 -4
  234. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  235. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  236. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  237. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  238. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  239. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  240. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  241. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  242. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  243. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  244. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  245. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  246. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  247. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  248. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  249. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  250. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  251. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  252. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  253. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  254. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  255. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  256. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  257. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  258. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  259. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  260. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  261. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  262. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  263. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  264. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  265. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  266. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  267. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  268. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  269. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  270. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  271. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  272. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  273. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  274. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  275. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  276. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  277. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  278. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  279. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  280. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  281. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  282. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  283. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  284. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  285. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  286. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  287. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  288. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  289. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  290. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  291. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  292. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  293. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  294. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  295. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  296. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  297. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  298. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  299. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  300. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  301. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  302. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  303. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  304. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  305. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  306. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  307. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  308. claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
  309. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  310. claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
  311. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  312. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  313. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  314. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  315. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  316. claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
  317. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  318. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  319. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  320. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  321. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  322. claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
  323. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  324. claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
  325. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  326. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  327. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  328. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  329. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  330. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  331. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  332. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  333. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  334. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  335. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  336. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  337. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  338. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  339. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  340. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  341. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  342. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  343. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  344. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  345. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  346. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  347. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  348. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  349. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  350. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  351. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  352. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  353. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  354. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  355. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  356. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  357. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  358. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  359. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  360. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  361. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  362. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  363. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  364. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  365. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  366. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  367. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  368. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  369. claude_mpm/skills/skill_manager.py +4 -4
  370. claude_mpm/utils/agent_dependency_loader.py +103 -4
  371. claude_mpm/utils/robust_installer.py +45 -24
  372. claude_mpm-5.6.1.dist-info/METADATA +391 -0
  373. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/RECORD +377 -166
  374. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +0 -1
  375. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +0 -1
  376. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +0 -1
  377. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +0 -24
  378. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +0 -1
  379. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +0 -1
  380. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +0 -323
  381. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +0 -1
  382. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +0 -1
  383. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  384. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  385. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  386. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  387. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  388. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  389. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  390. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  391. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  392. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  393. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  394. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  395. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  396. claude_mpm-5.4.55.dist-info/METADATA +0 -999
  397. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/WHEEL +0 -0
  398. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/entry_points.txt +0 -0
  399. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/licenses/LICENSE +0 -0
  400. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  401. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,561 @@
1
+ """Incremental Pause Manager Service.
2
+
3
+ WHY: Captures actions incrementally after auto-pause threshold (90%) is crossed to
4
+ record the "wind-down" period before session ends. Uses append-only JSONL format
5
+ for efficient incremental capture with crash safety.
6
+
7
+ DESIGN DECISIONS:
8
+ - JSONL format for append-only writes (one action per line)
9
+ - Atomic appends using file locking for concurrent safety
10
+ - Delegates to SessionPauseManager for final snapshot generation
11
+ - Tracks pause lifecycle: start -> append actions -> finalize/discard
12
+ - Session ID matches pattern from SessionPauseManager for consistency
13
+
14
+ USAGE:
15
+ manager = IncrementalPauseManager()
16
+
17
+ # Start incremental pause at 90% threshold
18
+ session_id = manager.start_incremental_pause(
19
+ context_percentage=0.90,
20
+ initial_state=tracker.get_current_state().__dict__
21
+ )
22
+
23
+ # Record actions during wind-down
24
+ manager.append_action(
25
+ action_type="tool_call",
26
+ action_data={"tool": "Read", "path": "/some/file.py"},
27
+ context_percentage=0.92
28
+ )
29
+
30
+ # Finalize when session ends
31
+ final_path = manager.finalize_pause()
32
+ """
33
+
34
+ import json
35
+ from dataclasses import asdict, dataclass
36
+ from datetime import datetime, timezone
37
+ from pathlib import Path
38
+ from typing import Any, Dict, List, Optional
39
+
40
+ from claude_mpm.core.logger import get_logger
41
+ from claude_mpm.services.cli.session_pause_manager import SessionPauseManager
42
+
43
+ logger = get_logger(__name__)
44
+
45
+
46
+ @dataclass
47
+ class PauseAction:
48
+ """Single action recorded during incremental pause.
49
+
50
+ Attributes:
51
+ type: Action type ('tool_call', 'assistant_response', 'user_message',
52
+ 'system_event', 'pause_started', 'pause_finalized')
53
+ timestamp: ISO format timestamp
54
+ session_id: Unique session identifier
55
+ data: Action-specific data dictionary
56
+ context_percentage: Context usage when action recorded (0.0-1.0)
57
+ """
58
+
59
+ type: str
60
+ timestamp: str
61
+ session_id: str
62
+ data: Dict[str, Any]
63
+ context_percentage: float
64
+
65
+ def to_json_line(self) -> str:
66
+ """Convert to JSON line for JSONL format.
67
+
68
+ Returns:
69
+ JSON string with newline appended
70
+ """
71
+ return json.dumps(asdict(self), ensure_ascii=False, default=str) + "\n"
72
+
73
+ @classmethod
74
+ def from_json_line(cls, line: str) -> "PauseAction":
75
+ """Parse from JSON line.
76
+
77
+ Args:
78
+ line: JSON string (with or without newline)
79
+
80
+ Returns:
81
+ PauseAction instance
82
+
83
+ Raises:
84
+ json.JSONDecodeError: If line is not valid JSON
85
+ ValueError: If required fields are missing
86
+ """
87
+ data = json.loads(line.strip())
88
+ return cls(**data)
89
+
90
+
91
+ class IncrementalPauseManager:
92
+ """Manages incremental capture of actions during auto-pause wind-down.
93
+
94
+ Features:
95
+ - Append-only JSONL file for efficient incremental writes
96
+ - Atomic file operations with file locking
97
+ - Session lifecycle tracking (start -> append -> finalize/discard)
98
+ - Integration with SessionPauseManager for final snapshots
99
+ - Crash-safe recording (each action appended atomically)
100
+
101
+ The incremental pause captures the "tail" of a session after the 90%
102
+ threshold is crossed, allowing us to record final actions before the
103
+ user decides to pause or continue.
104
+ """
105
+
106
+ ACTIVE_PAUSE_FILE = "ACTIVE-PAUSE.jsonl"
107
+
108
+ def __init__(self, project_path: Optional[Path] = None):
109
+ """Initialize incremental pause manager.
110
+
111
+ Args:
112
+ project_path: Project root path (default: current directory)
113
+ """
114
+ self.project_path = (project_path or Path.cwd()).resolve()
115
+ self.sessions_dir = self.project_path / ".claude-mpm" / "sessions"
116
+ self.sessions_dir.mkdir(parents=True, exist_ok=True)
117
+ self.active_pause_path = self.sessions_dir / self.ACTIVE_PAUSE_FILE
118
+
119
+ logger.debug(f"IncrementalPauseManager initialized: {self.active_pause_path}")
120
+
121
+ def is_pause_active(self) -> bool:
122
+ """Check if there's an active incremental pause in progress.
123
+
124
+ Returns:
125
+ True if ACTIVE-PAUSE.jsonl exists
126
+ """
127
+ return self.active_pause_path.exists()
128
+
129
+ def start_incremental_pause(
130
+ self, context_percentage: float, initial_state: Dict[str, Any]
131
+ ) -> str:
132
+ """Start a new incremental pause session.
133
+
134
+ Args:
135
+ context_percentage: Current context usage (e.g., 0.90 for 90%)
136
+ initial_state: Initial context snapshot (from ContextUsageTracker)
137
+
138
+ Returns:
139
+ session_id: Unique identifier for this pause session
140
+
141
+ Raises:
142
+ RuntimeError: If pause is already active
143
+ """
144
+ if self.is_pause_active():
145
+ logger.warning("Incremental pause already active, cannot start new pause")
146
+ raise RuntimeError(
147
+ "An incremental pause is already active. "
148
+ "Call finalize_pause() or discard_pause() first."
149
+ )
150
+
151
+ # Generate session ID matching SessionPauseManager pattern
152
+ session_id = f"session-{datetime.now(timezone.utc).strftime('%Y%m%d-%H%M%S')}"
153
+
154
+ # Create initial pause_started action
155
+ start_action = PauseAction(
156
+ type="pause_started",
157
+ timestamp=datetime.now(timezone.utc).isoformat(),
158
+ session_id=session_id,
159
+ data={
160
+ "context_percentage": context_percentage,
161
+ "initial_state": initial_state,
162
+ "reason": "Auto-pause threshold exceeded (90%+)",
163
+ },
164
+ context_percentage=context_percentage,
165
+ )
166
+
167
+ # Write initial action to file
168
+ try:
169
+ with self.active_pause_path.open("w") as f:
170
+ f.write(start_action.to_json_line())
171
+
172
+ logger.info(
173
+ f"Incremental pause started: {session_id} "
174
+ f"(context: {context_percentage:.1%})"
175
+ )
176
+ return session_id
177
+
178
+ except Exception as e:
179
+ logger.error(f"Failed to start incremental pause: {e}")
180
+ # Clean up partial file if created
181
+ if self.active_pause_path.exists():
182
+ self.active_pause_path.unlink()
183
+ raise RuntimeError(f"Failed to start incremental pause: {e}") from e
184
+
185
+ def append_action(
186
+ self, action_type: str, action_data: Dict[str, Any], context_percentage: float
187
+ ) -> None:
188
+ """Append an action to the active pause file.
189
+
190
+ Args:
191
+ action_type: Type of action ('tool_call', 'assistant_response',
192
+ 'user_message', 'system_event')
193
+ action_data: Action-specific data to record
194
+ context_percentage: Current context usage (0.0-1.0)
195
+
196
+ Raises:
197
+ RuntimeError: If no active pause session exists
198
+ """
199
+ if not self.is_pause_active():
200
+ logger.warning(
201
+ f"Cannot append action '{action_type}': no active pause session"
202
+ )
203
+ raise RuntimeError(
204
+ "No active pause session. Call start_incremental_pause() first."
205
+ )
206
+
207
+ # Get session ID from first line
208
+ try:
209
+ session_id = self._get_session_id()
210
+
211
+ action = PauseAction(
212
+ type=action_type,
213
+ timestamp=datetime.now(timezone.utc).isoformat(),
214
+ session_id=session_id,
215
+ data=action_data,
216
+ context_percentage=context_percentage,
217
+ )
218
+
219
+ # Append to file atomically
220
+ with self.active_pause_path.open("a") as f:
221
+ f.write(action.to_json_line())
222
+ f.flush() # Ensure data is written to disk
223
+
224
+ logger.debug(
225
+ f"Appended action '{action_type}' to pause session "
226
+ f"(context: {context_percentage:.1%})"
227
+ )
228
+
229
+ except Exception as e:
230
+ logger.error(f"Failed to append action to pause session: {e}")
231
+ raise RuntimeError(f"Failed to append action: {e}") from e
232
+
233
+ def get_recorded_actions(self) -> List[PauseAction]:
234
+ """Read all actions from the current pause session.
235
+
236
+ Returns:
237
+ List of PauseAction objects in chronological order
238
+
239
+ Raises:
240
+ RuntimeError: If no active pause session exists
241
+ """
242
+ if not self.is_pause_active():
243
+ raise RuntimeError("No active pause session")
244
+
245
+ try:
246
+ actions = []
247
+ with self.active_pause_path.open("r") as f:
248
+ for line in f:
249
+ if line.strip():
250
+ actions.append(PauseAction.from_json_line(line))
251
+
252
+ logger.debug(f"Read {len(actions)} actions from pause session")
253
+ return actions
254
+
255
+ except Exception as e:
256
+ logger.error(f"Failed to read recorded actions: {e}")
257
+ raise RuntimeError(f"Failed to read actions: {e}") from e
258
+
259
+ def finalize_pause(self, create_full_snapshot: bool = True) -> Optional[Path]:
260
+ """Finalize the incremental pause into a complete session snapshot.
261
+
262
+ This method:
263
+ 1. Appends a 'pause_finalized' action
264
+ 2. Optionally delegates to SessionPauseManager to create JSON/YAML/MD files
265
+ 3. Removes the ACTIVE-PAUSE.jsonl file
266
+ 4. Returns path to the finalized session file
267
+
268
+ Args:
269
+ create_full_snapshot: If True, use SessionPauseManager to create
270
+ complete session files
271
+
272
+ Returns:
273
+ Path to the finalized session file, or None if no active pause
274
+
275
+ Raises:
276
+ RuntimeError: If finalization fails
277
+ """
278
+ if not self.is_pause_active():
279
+ logger.warning("No active pause session to finalize")
280
+ return None
281
+
282
+ try:
283
+ # Read all recorded actions
284
+ actions = self.get_recorded_actions()
285
+
286
+ if not actions:
287
+ logger.warning("No actions recorded in pause session, discarding")
288
+ self.discard_pause()
289
+ return None
290
+
291
+ # Get session metadata from first action (pause_started)
292
+ first_action = actions[0]
293
+ if first_action.type != "pause_started":
294
+ raise RuntimeError("First action is not 'pause_started'")
295
+
296
+ session_id = first_action.session_id
297
+ initial_state = first_action.data.get("initial_state", {})
298
+
299
+ # Calculate final statistics
300
+ total_actions = len(actions)
301
+ final_percentage = actions[-1].context_percentage
302
+ pause_started_at = first_action.timestamp
303
+ pause_finalized_at = datetime.now(timezone.utc).isoformat()
304
+
305
+ # Append finalization action
306
+ self.append_action(
307
+ action_type="pause_finalized",
308
+ action_data={
309
+ "total_actions": total_actions,
310
+ "final_percentage": final_percentage,
311
+ "pause_started_at": pause_started_at,
312
+ "duration_seconds": self._calculate_duration(
313
+ pause_started_at, pause_finalized_at
314
+ ),
315
+ },
316
+ context_percentage=final_percentage,
317
+ )
318
+
319
+ # Create full snapshot if requested
320
+ if create_full_snapshot:
321
+ logger.info("Creating full session snapshot via SessionPauseManager")
322
+ pause_manager = SessionPauseManager(self.project_path)
323
+
324
+ # Build enriched state from initial_state and recorded actions
325
+ enriched_state = self._build_enriched_state(
326
+ initial_state, actions, session_id
327
+ )
328
+
329
+ # Use SessionPauseManager's internal method to save state
330
+ # (we'll build the state dict ourselves)
331
+ session_path = self.sessions_dir / f"{session_id}.json"
332
+ pause_manager.storage.write_json(
333
+ enriched_state, session_path, atomic=True
334
+ )
335
+
336
+ # Also create YAML and Markdown
337
+ yaml_path = self.sessions_dir / f"{session_id}.yaml"
338
+ pause_manager._save_yaml(enriched_state, yaml_path)
339
+
340
+ md_path = self.sessions_dir / f"{session_id}.md"
341
+ md_content = pause_manager._generate_markdown(enriched_state)
342
+ md_path.write_text(md_content)
343
+
344
+ # Update LATEST-SESSION pointer
345
+ pause_manager._update_latest_pointer(session_id)
346
+
347
+ logger.info(f"Full session snapshot created: {session_path}")
348
+
349
+ # Archive the JSONL file (rename instead of delete for debugging)
350
+ archive_path = self.sessions_dir / f"{session_id}-incremental.jsonl"
351
+ self.active_pause_path.rename(archive_path)
352
+
353
+ logger.info(
354
+ f"Incremental pause finalized: {session_id} "
355
+ f"({total_actions} actions, {final_percentage:.1%} context)"
356
+ )
357
+
358
+ return session_path if create_full_snapshot else archive_path
359
+
360
+ except Exception as e:
361
+ logger.error(f"Failed to finalize pause session: {e}")
362
+ raise RuntimeError(f"Failed to finalize pause: {e}") from e
363
+
364
+ def discard_pause(self) -> bool:
365
+ """Discard the current incremental pause without finalizing.
366
+
367
+ Returns:
368
+ True if pause was discarded, False if no active pause
369
+
370
+ Raises:
371
+ RuntimeError: If discard operation fails
372
+ """
373
+ if not self.is_pause_active():
374
+ logger.debug("No active pause session to discard")
375
+ return False
376
+
377
+ try:
378
+ session_id = self._get_session_id()
379
+ self.active_pause_path.unlink()
380
+
381
+ logger.info(f"Incremental pause discarded: {session_id}")
382
+ return True
383
+
384
+ except Exception as e:
385
+ logger.error(f"Failed to discard pause session: {e}")
386
+ raise RuntimeError(f"Failed to discard pause: {e}") from e
387
+
388
+ def get_pause_summary(self) -> Optional[Dict[str, Any]]:
389
+ """Get summary of current pause session.
390
+
391
+ Returns:
392
+ Summary dictionary with:
393
+ - session_id: Session identifier
394
+ - action_count: Number of recorded actions
395
+ - duration_seconds: Time since pause started
396
+ - context_range: (start_percentage, current_percentage)
397
+ - pause_started_at: ISO timestamp
398
+ Returns None if no active pause
399
+
400
+ Raises:
401
+ RuntimeError: If reading summary fails
402
+ """
403
+ if not self.is_pause_active():
404
+ return None
405
+
406
+ try:
407
+ actions = self.get_recorded_actions()
408
+
409
+ if not actions:
410
+ return None
411
+
412
+ first_action = actions[0]
413
+ last_action = actions[-1]
414
+
415
+ pause_started_at = first_action.timestamp
416
+ current_time = datetime.now(timezone.utc).isoformat()
417
+
418
+ return {
419
+ "session_id": first_action.session_id,
420
+ "action_count": len(actions),
421
+ "duration_seconds": self._calculate_duration(
422
+ pause_started_at, current_time
423
+ ),
424
+ "context_range": (
425
+ first_action.context_percentage,
426
+ last_action.context_percentage,
427
+ ),
428
+ "pause_started_at": pause_started_at,
429
+ "last_action_type": last_action.type,
430
+ "last_updated": last_action.timestamp,
431
+ }
432
+
433
+ except Exception as e:
434
+ logger.error(f"Failed to get pause summary: {e}")
435
+ raise RuntimeError(f"Failed to get summary: {e}") from e
436
+
437
+ def _get_session_id(self) -> str:
438
+ """Extract session ID from first line of active pause file.
439
+
440
+ Returns:
441
+ Session identifier
442
+
443
+ Raises:
444
+ RuntimeError: If file is empty or corrupted
445
+ """
446
+ try:
447
+ with self.active_pause_path.open("r") as f:
448
+ first_line = f.readline()
449
+
450
+ if not first_line:
451
+ raise RuntimeError("Active pause file is empty")
452
+
453
+ first_action = PauseAction.from_json_line(first_line)
454
+ return first_action.session_id
455
+
456
+ except Exception as e:
457
+ logger.error(f"Failed to read session ID: {e}")
458
+ raise RuntimeError(f"Failed to read session ID: {e}") from e
459
+
460
+ def _calculate_duration(self, start_iso: str, end_iso: str) -> int:
461
+ """Calculate duration between two ISO timestamps.
462
+
463
+ Args:
464
+ start_iso: Start timestamp (ISO format)
465
+ end_iso: End timestamp (ISO format)
466
+
467
+ Returns:
468
+ Duration in seconds
469
+
470
+ Raises:
471
+ ValueError: If timestamps are invalid
472
+ """
473
+ try:
474
+ start_dt = datetime.fromisoformat(start_iso.replace("Z", "+00:00"))
475
+ end_dt = datetime.fromisoformat(end_iso.replace("Z", "+00:00"))
476
+ return int((end_dt - start_dt).total_seconds())
477
+
478
+ except Exception as e:
479
+ logger.warning(f"Failed to calculate duration: {e}")
480
+ return 0
481
+
482
+ def _build_enriched_state(
483
+ self,
484
+ initial_state: Dict[str, Any],
485
+ actions: List[PauseAction],
486
+ session_id: str,
487
+ ) -> Dict[str, Any]:
488
+ """Build enriched state dictionary from initial state and recorded actions.
489
+
490
+ Args:
491
+ initial_state: Initial context snapshot
492
+ actions: List of recorded actions
493
+ session_id: Session identifier
494
+
495
+ Returns:
496
+ Enriched state dictionary compatible with SessionPauseManager
497
+ """
498
+ # Extract action summaries
499
+ tool_calls = [a for a in actions if a.type == "tool_call"]
500
+ assistant_responses = [a for a in actions if a.type == "assistant_response"]
501
+
502
+ # Build accomplishments from actions
503
+ accomplishments = []
504
+ for response in assistant_responses:
505
+ if "summary" in response.data:
506
+ accomplishments.append(response.data["summary"])
507
+
508
+ # Calculate session duration
509
+ first_action = actions[0]
510
+ last_action = actions[-1]
511
+ duration_seconds = self._calculate_duration(
512
+ first_action.timestamp, last_action.timestamp
513
+ )
514
+
515
+ # Build state dictionary
516
+ pause_manager = SessionPauseManager(self.project_path)
517
+ base_state = pause_manager._capture_state(session_id, None)
518
+
519
+ # Enrich with incremental pause data
520
+ base_state["paused_at"] = last_action.timestamp
521
+ base_state["duration_hours"] = round(duration_seconds / 3600, 2)
522
+ base_state["context_usage"] = {
523
+ "tokens_used": int(
524
+ last_action.context_percentage * ContextUsageTracker.CONTEXT_BUDGET
525
+ ),
526
+ "tokens_total": ContextUsageTracker.CONTEXT_BUDGET,
527
+ "percentage": last_action.context_percentage * 100,
528
+ }
529
+
530
+ base_state["conversation"]["primary_task"] = (
531
+ "Auto-pause triggered at 90% context"
532
+ )
533
+ base_state["conversation"]["current_phase"] = "Wind-down"
534
+ base_state["conversation"]["summary"] = (
535
+ f"Session auto-paused after {len(actions)} actions. "
536
+ f"Context usage: {first_action.context_percentage:.1%} -> {last_action.context_percentage:.1%}"
537
+ )
538
+ base_state["conversation"]["accomplishments"] = accomplishments[
539
+ :10
540
+ ] # Limit to 10
541
+
542
+ # Add incremental pause metadata
543
+ base_state["incremental_pause"] = {
544
+ "enabled": True,
545
+ "action_count": len(actions),
546
+ "duration_seconds": duration_seconds,
547
+ "context_range": [
548
+ first_action.context_percentage,
549
+ last_action.context_percentage,
550
+ ],
551
+ "tool_calls": len(tool_calls),
552
+ "actions_summary": [
553
+ {"type": a.type, "timestamp": a.timestamp} for a in actions[-10:]
554
+ ], # Last 10 actions
555
+ }
556
+
557
+ return base_state
558
+
559
+
560
+ # Import for type hints and usage
561
+ from claude_mpm.services.infrastructure.context_usage_tracker import ContextUsageTracker
@@ -14,7 +14,7 @@ DESIGN DECISIONS:
14
14
  """
15
15
 
16
16
  import json
17
- import subprocess
17
+ import subprocess # nosec B404 - subprocess needed for git commands
18
18
  from datetime import datetime, timezone
19
19
  from pathlib import Path
20
20
  from typing import Any, Dict, List, Optional, Tuple
@@ -50,9 +50,11 @@ class SessionResumeHelper:
50
50
 
51
51
  if self.pause_dir.exists():
52
52
  session_files.extend(list(self.pause_dir.glob("session-*.json")))
53
+ session_files.extend(list(self.pause_dir.glob("session-*.md")))
53
54
 
54
55
  if self.legacy_pause_dir.exists():
55
56
  session_files.extend(list(self.legacy_pause_dir.glob("session-*.json")))
57
+ session_files.extend(list(self.legacy_pause_dir.glob("session-*.md")))
56
58
 
57
59
  return len(session_files) > 0
58
60
 
@@ -67,9 +69,11 @@ class SessionResumeHelper:
67
69
 
68
70
  if self.pause_dir.exists():
69
71
  session_files.extend(list(self.pause_dir.glob("session-*.json")))
72
+ session_files.extend(list(self.pause_dir.glob("session-*.md")))
70
73
 
71
74
  if self.legacy_pause_dir.exists():
72
75
  session_files.extend(list(self.legacy_pause_dir.glob("session-*.json")))
76
+ session_files.extend(list(self.legacy_pause_dir.glob("session-*.md")))
73
77
 
74
78
  if not session_files:
75
79
  return None
@@ -112,7 +116,7 @@ class SessionResumeHelper:
112
116
  "--all",
113
117
  ]
114
118
 
115
- result = subprocess.run(
119
+ result = subprocess.run( # nosec B603 - git command with safe args
116
120
  cmd,
117
121
  cwd=self.project_path,
118
122
  capture_output=True,
@@ -332,9 +336,11 @@ class SessionResumeHelper:
332
336
 
333
337
  if self.pause_dir.exists():
334
338
  session_files.extend(list(self.pause_dir.glob("session-*.json")))
339
+ session_files.extend(list(self.pause_dir.glob("session-*.md")))
335
340
 
336
341
  if self.legacy_pause_dir.exists():
337
342
  session_files.extend(list(self.legacy_pause_dir.glob("session-*.json")))
343
+ session_files.extend(list(self.legacy_pause_dir.glob("session-*.md")))
338
344
 
339
345
  return len(session_files)
340
346
 
@@ -348,9 +354,11 @@ class SessionResumeHelper:
348
354
 
349
355
  if self.pause_dir.exists():
350
356
  session_files.extend(list(self.pause_dir.glob("session-*.json")))
357
+ session_files.extend(list(self.pause_dir.glob("session-*.md")))
351
358
 
352
359
  if self.legacy_pause_dir.exists():
353
360
  session_files.extend(list(self.legacy_pause_dir.glob("session-*.json")))
361
+ session_files.extend(list(self.legacy_pause_dir.glob("session-*.md")))
354
362
 
355
363
  if not session_files:
356
364
  return []