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
@@ -1,27 +1,30 @@
1
1
  """PM Skills Deployer Service - Deploy bundled PM skills to projects.
2
2
 
3
- WHY: PM agents require specific templates and skills for proper operation.
3
+ WHY: PM agents require specific framework management skills for proper operation.
4
4
  This service manages deployment of bundled PM skills from the claude-mpm
5
- package to individual project .claude-mpm directories with version tracking.
5
+ package to the Claude Code skills directory with version tracking.
6
6
 
7
7
  DESIGN DECISIONS:
8
- - Deploys from src/claude_mpm/skills/bundled/pm/ to .claude-mpm/skills/pm/
8
+ - Deploys from src/claude_mpm/skills/bundled/pm/ to .claude/skills/
9
+ - Skills named mpm-* (framework management skills)
10
+ - Direct deployment (no intermediate .claude-mpm/skills/pm/ step)
9
11
  - Uses package-relative paths (works for both installed and dev mode)
10
- - Supports two skill formats:
11
- 1. Directory structure: pm-skill-name/SKILL.md (new format)
12
- 2. Flat files: skill-name.md (legacy format in .claude-mpm/templates/)
13
- - Per-project deployment (NOT global like Claude Code skills)
12
+ - Supports directory structure: mpm-skill-name/SKILL.md
13
+ - Per-project deployment to .claude/skills/ (Claude Code location)
14
14
  - Version tracking via .claude-mpm/pm_skills_registry.yaml
15
15
  - Checksum validation for integrity verification
16
+ - Conflict resolution: mpm-* skills from src WIN (overwrite existing)
17
+ - Non-mpm-* skills in .claude/skills/ are untouched (user/git managed)
16
18
  - Non-blocking verification (returns warnings, doesn't halt execution)
17
19
  - Force flag to redeploy even if versions match
18
20
 
19
21
  ARCHITECTURE:
20
22
  1. Discovery: Find bundled PM skills in package (skills/bundled/pm/)
21
- 2. Deployment: Copy SKILL.md files to .claude-mpm/skills/pm/{name}.md
22
- 3. Registry: Track deployed versions and checksums
23
- 4. Verification: Check deployment status (non-blocking)
24
- 5. Updates: Compare bundled vs deployed versions
23
+ 2. Deployment: Copy SKILL.md files to .claude/skills/{name}/SKILL.md
24
+ 3. Conflict Check: Overwrite mpm-* skills, preserve non-mpm-* skills
25
+ 4. Registry: Track deployed versions and checksums
26
+ 5. Verification: Check deployment status (non-blocking)
27
+ 6. Updates: Compare bundled vs deployed versions
25
28
 
26
29
  PATH RESOLUTION:
27
30
  - Installed package: Uses __file__ to find skills/bundled/pm/
@@ -47,6 +50,47 @@ from claude_mpm.core.mixins import LoggerMixin
47
50
  # Security constants
48
51
  MAX_YAML_SIZE = 10 * 1024 * 1024 # 10MB limit to prevent YAML bombs
49
52
 
53
+ # Tier 1: Required PM skills that MUST be deployed for PM agent to function properly
54
+ # These are core framework management skills for basic PM operation
55
+ REQUIRED_PM_SKILLS = [
56
+ # Core command-based skills (new consolidated CLI)
57
+ "mpm",
58
+ "mpm-init",
59
+ "mpm-status",
60
+ "mpm-help",
61
+ "mpm-doctor",
62
+ # Legacy framework management skills
63
+ "mpm-git-file-tracking",
64
+ "mpm-pr-workflow",
65
+ "mpm-ticketing-integration",
66
+ "mpm-delegation-patterns",
67
+ "mpm-verification-protocols",
68
+ "mpm-bug-reporting",
69
+ "mpm-teaching-mode",
70
+ "mpm-agent-update-workflow",
71
+ "mpm-circuit-breaker-enforcement",
72
+ "mpm-tool-usage-guide",
73
+ "mpm-session-management",
74
+ "mpm-session-pause",
75
+ "mpm-session-resume",
76
+ ]
77
+
78
+ # Tier 2: Recommended skills (deployed with standard install)
79
+ # These provide enhanced functionality for common workflows
80
+ RECOMMENDED_PM_SKILLS = [
81
+ "mpm-config",
82
+ "mpm-ticket-view",
83
+ "mpm-postmortem",
84
+ ]
85
+
86
+ # Tier 3: Optional skills (deployed with full install)
87
+ # These provide additional features for advanced use cases
88
+ OPTIONAL_PM_SKILLS = [
89
+ "mpm-monitor",
90
+ "mpm-version",
91
+ "mpm-organize",
92
+ ]
93
+
50
94
 
51
95
  @dataclass
52
96
  class PMSkillInfo:
@@ -96,6 +140,7 @@ class VerificationResult:
96
140
  verified: Whether all skills are properly deployed
97
141
  warnings: List of warning messages
98
142
  missing_skills: List of missing skill names
143
+ corrupted_skills: List of corrupted skill names (checksum mismatch)
99
144
  outdated_skills: List of outdated skill names
100
145
  message: Summary message
101
146
  skill_count: Total number of deployed skills
@@ -104,6 +149,7 @@ class VerificationResult:
104
149
  verified: bool
105
150
  warnings: List[str]
106
151
  missing_skills: List[str]
152
+ corrupted_skills: List[str]
107
153
  outdated_skills: List[str]
108
154
  message: str
109
155
  skill_count: int = 0
@@ -130,8 +176,9 @@ class PMSkillsDeployerService(LoggerMixin):
130
176
  """Deploy and manage PM skills from bundled sources to projects.
131
177
 
132
178
  This service provides:
133
- - Discovery of bundled PM skills (templates)
134
- - Deployment to .claude-mpm/skills/pm/
179
+ - Discovery of bundled PM skills (mpm-* framework management skills)
180
+ - Deployment to .claude/skills/ (Claude Code location)
181
+ - Conflict resolution (mpm-* skills from src WIN)
135
182
  - Version tracking via pm_skills_registry.yaml
136
183
  - Checksum validation for integrity
137
184
  - Non-blocking verification (warnings only)
@@ -140,7 +187,7 @@ class PMSkillsDeployerService(LoggerMixin):
140
187
  Example:
141
188
  >>> deployer = PMSkillsDeployerService()
142
189
  >>> result = deployer.deploy_pm_skills(Path("/project/root"))
143
- >>> print(f"Deployed {len(result.deployed)} skills")
190
+ >>> print(f"Deployed {len(result.deployed)} skills to .claude/skills/")
144
191
  >>>
145
192
  >>> verify_result = deployer.verify_pm_skills(Path("/project/root"))
146
193
  >>> if not verify_result.verified:
@@ -246,9 +293,9 @@ class PMSkillsDeployerService(LoggerMixin):
246
293
  project_dir: Project root directory
247
294
 
248
295
  Returns:
249
- Path to .claude-mpm/skills/pm/
296
+ Path to .claude/skills/
250
297
  """
251
- return project_dir / ".claude-mpm" / "skills" / "pm"
298
+ return project_dir / ".claude" / "skills"
252
299
 
253
300
  def _load_registry(self, project_dir: Path) -> Dict[str, Any]:
254
301
  """Load PM skills registry with security checks.
@@ -322,14 +369,12 @@ class PMSkillsDeployerService(LoggerMixin):
322
369
  def _discover_bundled_pm_skills(self) -> List[Dict[str, Any]]:
323
370
  """Discover all PM skills in bundled templates directory.
324
371
 
325
- PM skills can be in two formats:
326
- 1. Directory structure: pm-skill-name/SKILL.md (new format)
327
- 2. Flat files: skill-name.md (legacy format for .claude-mpm/templates/)
372
+ PM skills follow mpm-skill-name/SKILL.md structure.
328
373
 
329
374
  Returns:
330
375
  List of skill dictionaries containing:
331
- - name: Skill name (directory/filename without extension)
332
- - path: Full path to skill file (SKILL.md or .md file)
376
+ - name: Skill name (directory name, e.g., mpm-git-file-tracking)
377
+ - path: Full path to skill file (SKILL.md)
333
378
  - type: File type (always 'md')
334
379
  """
335
380
  skills = []
@@ -340,11 +385,17 @@ class PMSkillsDeployerService(LoggerMixin):
340
385
  )
341
386
  return skills
342
387
 
343
- # Scan for skill directories containing SKILL.md (new format)
388
+ # Scan for skill directories containing SKILL.md
344
389
  for skill_dir in self.bundled_pm_skills_path.iterdir():
345
390
  if not skill_dir.is_dir() or skill_dir.name.startswith("."):
346
391
  continue
347
392
 
393
+ # Only process mpm* skills (framework management)
394
+ # Note: Includes both 'mpm' (core skill) and 'mpm-*' (other PM skills)
395
+ if not skill_dir.name.startswith("mpm"):
396
+ self.logger.debug(f"Skipping non-mpm skill: {skill_dir.name}")
397
+ continue
398
+
348
399
  skill_file = skill_dir / "SKILL.md"
349
400
  if skill_file.exists():
350
401
  skills.append(
@@ -355,46 +406,91 @@ class PMSkillsDeployerService(LoggerMixin):
355
406
  }
356
407
  )
357
408
 
358
- # Fallback: Scan for .md files directly (legacy format)
359
- for skill_file in self.bundled_pm_skills_path.glob("*.md"):
360
- if skill_file.name.startswith("."):
361
- continue
362
-
363
- skills.append(
364
- {
365
- "name": skill_file.stem,
366
- "path": skill_file,
367
- "type": "md",
368
- }
369
- )
370
-
371
409
  self.logger.info(f"Discovered {len(skills)} bundled PM skills")
372
410
  return skills
373
411
 
412
+ def _get_skills_for_tier(self, tier: str) -> List[str]:
413
+ """Get list of skills to deploy based on tier.
414
+
415
+ Args:
416
+ tier: Deployment tier - "minimal", "standard", or "full"
417
+
418
+ Returns:
419
+ List of skill names to deploy
420
+
421
+ Raises:
422
+ ValueError: If tier is invalid
423
+ """
424
+ if tier == "minimal":
425
+ return REQUIRED_PM_SKILLS
426
+ if tier == "standard":
427
+ return REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS
428
+ if tier == "full":
429
+ return REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS + OPTIONAL_PM_SKILLS
430
+ raise ValueError(
431
+ f"Invalid tier '{tier}'. Must be 'minimal', 'standard', or 'full'"
432
+ )
433
+
374
434
  def deploy_pm_skills(
375
435
  self,
376
436
  project_dir: Path,
377
437
  force: bool = False,
438
+ tier: str = "standard",
378
439
  progress_callback: Optional[Callable[[str, int, int], None]] = None,
379
440
  ) -> DeploymentResult:
380
- """Deploy bundled PM skills to project directory.
441
+ """Deploy bundled PM skills to project directory with tier-based selection.
381
442
 
382
- Copies PM skills from bundled templates to .claude-mpm/skills/pm/
443
+ Copies PM skills from bundled templates to .claude/skills/{name}/SKILL.md
383
444
  and updates registry with version and checksum information.
384
445
 
446
+ Deployment Tiers:
447
+ - "minimal": Only REQUIRED_PM_SKILLS (Tier 1 - core functionality)
448
+ - "standard": REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS (Tier 1+2 - common workflows)
449
+ - "full": All skills (Tier 1+2+3 - advanced features)
450
+
451
+ Conflict Resolution:
452
+ - mpm-* skills from src WIN (overwrite existing)
453
+ - Non-mpm-* skills in .claude/skills/ are untouched
454
+
385
455
  Args:
386
456
  project_dir: Project root directory
387
457
  force: If True, redeploy even if skill already exists
458
+ tier: Deployment tier - "minimal", "standard" (default), or "full"
388
459
  progress_callback: Optional callback(skill_name, current, total) for progress
389
460
 
390
461
  Returns:
391
462
  DeploymentResult with deployment status and details
392
463
 
393
464
  Example:
394
- >>> result = deployer.deploy_pm_skills(Path("/project"), force=True)
395
- >>> print(f"Deployed: {len(result.deployed)}")
465
+ >>> # Standard deployment (Tier 1 + Tier 2)
466
+ >>> result = deployer.deploy_pm_skills(Path("/project"))
467
+ >>> print(f"Deployed: {len(result.deployed)} to .claude/skills/")
468
+ >>>
469
+ >>> # Minimal deployment (Tier 1 only)
470
+ >>> result = deployer.deploy_pm_skills(Path("/project"), tier="minimal")
471
+ >>>
472
+ >>> # Full deployment (all tiers)
473
+ >>> result = deployer.deploy_pm_skills(Path("/project"), tier="full")
396
474
  """
397
- skills = self._discover_bundled_pm_skills()
475
+ # Get tier-based skill filter
476
+ try:
477
+ tier_skills = self._get_skills_for_tier(tier)
478
+ except ValueError as e:
479
+ return DeploymentResult(
480
+ success=False,
481
+ deployed=[],
482
+ skipped=[],
483
+ errors=[{"skill": "all", "error": str(e)}],
484
+ message=str(e),
485
+ )
486
+
487
+ # Discover all bundled skills, then filter by tier
488
+ all_skills = self._discover_bundled_pm_skills()
489
+ skills = [s for s in all_skills if s["name"] in tier_skills]
490
+
491
+ self.logger.info(
492
+ f"Deploying {len(skills)}/{len(all_skills)} skills for tier '{tier}'"
493
+ )
398
494
  deployed = []
399
495
  skipped = []
400
496
  errors = []
@@ -447,8 +543,12 @@ class PMSkillsDeployerService(LoggerMixin):
447
543
  if progress_callback:
448
544
  progress_callback(skill_name, idx + 1, total_skills)
449
545
 
450
- # Use skill name for target file (e.g., pm-delegation-patterns.md)
451
- target_path = deployment_dir / f"{skill_name}.md"
546
+ # Create skill directory: .claude/skills/{skill_name}/
547
+ skill_dir = deployment_dir / skill_name
548
+ skill_dir.mkdir(parents=True, exist_ok=True)
549
+
550
+ # Target path: .claude/skills/{skill_name}/SKILL.md
551
+ target_path = skill_dir / "SKILL.md"
452
552
 
453
553
  # SECURITY: Validate target path
454
554
  if not self._validate_safe_path(deployment_dir, target_path):
@@ -468,7 +568,7 @@ class PMSkillsDeployerService(LoggerMixin):
468
568
  )
469
569
  continue
470
570
 
471
- # Deploy skill
571
+ # Deploy skill (overwrites if exists - mpm-* skills WIN)
472
572
  shutil.copy2(source_path, target_path)
473
573
 
474
574
  # Add to deployed list
@@ -506,7 +606,7 @@ class PMSkillsDeployerService(LoggerMixin):
506
606
 
507
607
  success = len(errors) == 0
508
608
  message = (
509
- f"Deployed {len(deployed)} skills, skipped {len(skipped)}, "
609
+ f"Deployed {len(deployed)} skills (tier: {tier}), skipped {len(skipped)}, "
510
610
  f"{len(errors)} errors"
511
611
  )
512
612
 
@@ -520,76 +620,107 @@ class PMSkillsDeployerService(LoggerMixin):
520
620
  message=message,
521
621
  )
522
622
 
523
- def verify_pm_skills(self, project_dir: Path) -> VerificationResult:
524
- """Verify PM skills are properly deployed (non-blocking).
623
+ def verify_pm_skills(
624
+ self, project_dir: Path, auto_repair: bool = True
625
+ ) -> VerificationResult:
626
+ """Verify PM skills are properly deployed with enhanced validation.
525
627
 
526
- Checks deployment status and returns warnings without halting execution.
527
- This allows graceful degradation if PM skills are missing.
628
+ Checks ALL required PM skills for:
629
+ - Existence in deployment directory
630
+ - File integrity (non-empty, valid checksums)
631
+ - Version currency (compared to bundled source)
632
+
633
+ Auto-repair logic:
634
+ - If auto_repair=True (default), automatically deploys missing/corrupted skills
635
+ - Reports what was fixed in the result
528
636
 
529
637
  Args:
530
638
  project_dir: Project root directory
639
+ auto_repair: If True, auto-deploy missing/corrupted skills (default: True)
531
640
 
532
641
  Returns:
533
- VerificationResult with verification status and warnings
642
+ VerificationResult with detailed verification status:
643
+ - verified: True if all required skills are deployed and valid
644
+ - missing_skills: List of required skills not deployed
645
+ - corrupted_skills: List of skills with checksum mismatches
646
+ - warnings: List of warning messages
647
+ - skill_count: Total number of deployed skills
534
648
 
535
649
  Example:
536
650
  >>> result = deployer.verify_pm_skills(Path("/project"))
537
651
  >>> if not result.verified:
538
- ... for warning in result.warnings:
539
- ... print(f"WARNING: {warning}")
652
+ ... print(f"Missing: {result.missing_skills}")
653
+ ... print(f"Corrupted: {result.corrupted_skills}")
540
654
  """
541
655
  warnings = []
542
656
  missing_skills = []
657
+ corrupted_skills = []
543
658
  outdated_skills = []
544
659
 
545
660
  # Check if registry exists
546
661
  registry = self._load_registry(project_dir)
547
- if not registry:
548
- warnings.append("PM skills registry not found or invalid")
549
- missing_skills.append("all")
550
- return VerificationResult(
551
- verified=False,
552
- warnings=warnings,
553
- missing_skills=missing_skills,
554
- outdated_skills=outdated_skills,
555
- message="PM skills not deployed. Run 'claude-mpm init' to deploy.",
556
- skill_count=0,
557
- )
558
-
559
- # Check each registered skill exists
560
662
  deployment_dir = self._get_deployment_dir(project_dir)
561
- deployed_skills = registry.get("skills", [])
663
+ deployed_skills_data = registry.get("skills", []) if registry else []
562
664
 
563
- for skill in deployed_skills:
564
- skill_name = skill["name"]
565
- skill_file = deployment_dir / f"{skill_name}.md"
665
+ # Build lookup for deployed skills
666
+ deployed_lookup = {skill["name"]: skill for skill in deployed_skills_data}
566
667
 
668
+ # Check ALL required PM skills
669
+ for required_skill in REQUIRED_PM_SKILLS:
670
+ # Check if skill is in registry
671
+ if required_skill not in deployed_lookup:
672
+ warnings.append(f"Required PM skill missing: {required_skill}")
673
+ missing_skills.append(required_skill)
674
+ continue
675
+
676
+ # Check if skill file exists
677
+ skill_file = deployment_dir / required_skill / "SKILL.md"
567
678
  if not skill_file.exists():
568
- warnings.append(f"Deployed skill file missing: {skill_name}")
569
- missing_skills.append(skill_name)
679
+ warnings.append(
680
+ f"Required PM skill file missing: {required_skill}/SKILL.md"
681
+ )
682
+ missing_skills.append(required_skill)
683
+ continue
684
+
685
+ # Check if skill file is empty/corrupted
686
+ try:
687
+ file_size = skill_file.stat().st_size
688
+ if file_size == 0:
689
+ warnings.append(
690
+ f"Required PM skill file is empty: {required_skill}/SKILL.md"
691
+ )
692
+ corrupted_skills.append(required_skill)
693
+ continue
694
+ except OSError as e:
695
+ warnings.append(
696
+ f"Cannot read required PM skill file: {required_skill}/SKILL.md - {e}"
697
+ )
698
+ corrupted_skills.append(required_skill)
570
699
  continue
571
700
 
572
701
  # Verify checksum
702
+ deployed_skill = deployed_lookup[required_skill]
573
703
  current_checksum = self._compute_checksum(skill_file)
574
- expected_checksum = skill.get("checksum", "")
704
+ expected_checksum = deployed_skill.get("checksum", "")
575
705
 
576
706
  if current_checksum != expected_checksum:
577
707
  warnings.append(
578
- f"Skill checksum mismatch: {skill_name} (file may be corrupted)"
708
+ f"Required PM skill checksum mismatch: {required_skill} (file may be corrupted)"
579
709
  )
580
- outdated_skills.append(skill_name)
710
+ corrupted_skills.append(required_skill)
581
711
 
582
- # Check for available updates
712
+ # Check for available updates (bundled skills newer than deployed)
583
713
  bundled_skills = {s["name"]: s for s in self._discover_bundled_pm_skills()}
584
714
  for skill_name, bundled_skill in bundled_skills.items():
715
+ # Skip non-required skills
716
+ if skill_name not in REQUIRED_PM_SKILLS:
717
+ continue
718
+
585
719
  # Find corresponding deployed skill
586
- deployed_skill = next(
587
- (s for s in deployed_skills if s["name"] == skill_name), None
588
- )
720
+ deployed_skill = deployed_lookup.get(skill_name)
589
721
 
590
722
  if not deployed_skill:
591
- warnings.append(f"New PM skill available: {skill_name}")
592
- missing_skills.append(skill_name)
723
+ # Already tracked as missing
593
724
  continue
594
725
 
595
726
  # Check if checksums differ
@@ -597,23 +728,66 @@ class PMSkillsDeployerService(LoggerMixin):
597
728
  deployed_checksum = deployed_skill.get("checksum", "")
598
729
 
599
730
  if bundled_checksum != deployed_checksum:
600
- warnings.append(f"PM skill update available: {skill_name}")
601
- outdated_skills.append(skill_name)
731
+ # Don't add to outdated_skills if already in corrupted_skills
732
+ if skill_name not in corrupted_skills:
733
+ warnings.append(f"PM skill update available: {skill_name}")
734
+ outdated_skills.append(skill_name)
735
+
736
+ # Auto-repair if enabled and issues found
737
+ repaired_skills = []
738
+ if auto_repair and (missing_skills or corrupted_skills):
739
+ self.logger.info(
740
+ f"Auto-repairing PM skills: {len(missing_skills)} missing, "
741
+ f"{len(corrupted_skills)} corrupted"
742
+ )
743
+
744
+ # Deploy missing and corrupted skills
745
+ repair_result = self.deploy_pm_skills(project_dir, force=True)
746
+
747
+ if repair_result.success:
748
+ repaired_skills = repair_result.deployed
749
+ self.logger.info(f"Auto-repaired {len(repaired_skills)} PM skills")
750
+
751
+ # Remove repaired skills from missing/corrupted lists
752
+ missing_skills = [s for s in missing_skills if s not in repaired_skills]
753
+ corrupted_skills = [
754
+ s for s in corrupted_skills if s not in repaired_skills
755
+ ]
756
+
757
+ # Update warnings
758
+ if repaired_skills:
759
+ warnings.append(
760
+ f"Auto-repaired {len(repaired_skills)} PM skills: {', '.join(repaired_skills)}"
761
+ )
762
+ else:
763
+ warnings.append(
764
+ f"Auto-repair failed: {len(repair_result.errors)} errors"
765
+ )
766
+ self.logger.error(
767
+ f"Auto-repair failed with errors: {repair_result.errors}"
768
+ )
602
769
 
603
- verified = len(warnings) == 0
770
+ # Determine verification status
771
+ verified = len(missing_skills) == 0 and len(corrupted_skills) == 0
604
772
 
773
+ # Build message
605
774
  if verified:
606
- message = "All PM skills verified and up-to-date"
775
+ if repaired_skills:
776
+ message = f"All PM skills verified (auto-repaired {len(repaired_skills)} skills)"
777
+ else:
778
+ message = "All PM skills verified and up-to-date"
607
779
  else:
608
- message = f"{len(warnings)} verification warnings found"
780
+ issue_count = len(missing_skills) + len(corrupted_skills)
781
+ message = f"{issue_count} PM skill issues found"
609
782
 
610
783
  return VerificationResult(
611
784
  verified=verified,
612
785
  warnings=warnings,
613
786
  missing_skills=missing_skills,
787
+ corrupted_skills=corrupted_skills,
614
788
  outdated_skills=outdated_skills,
615
789
  message=message,
616
- skill_count=len(deployed_skills),
790
+ skill_count=len(deployed_skills_data),
617
791
  )
618
792
 
619
793
  def get_deployed_skills(self, project_dir: Path) -> List[PMSkillInfo]:
@@ -636,10 +810,10 @@ class PMSkillsDeployerService(LoggerMixin):
636
810
  skills = []
637
811
  for skill_data in registry.get("skills", []):
638
812
  skill_name = skill_data["name"]
639
- deployed_path = deployment_dir / f"{skill_name}.md"
813
+ deployed_path = deployment_dir / skill_name / "SKILL.md"
640
814
 
641
815
  # Find source path (may not exist if bundled skills changed)
642
- source_path = self.bundled_pm_skills_path / f"{skill_name}.md"
816
+ source_path = self.bundled_pm_skills_path / skill_name / "SKILL.md"
643
817
 
644
818
  skills.append(
645
819
  PMSkillInfo(