claude-mpm 3.4.10__py3-none-any.whl → 5.4.55__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (950) hide show
  1. claude_mpm/BUILD_NUMBER +1 -0
  2. claude_mpm/VERSION +1 -0
  3. claude_mpm/__init__.py +50 -12
  4. claude_mpm/__main__.py +7 -2
  5. claude_mpm/agents/BASE_AGENT.md +164 -0
  6. claude_mpm/agents/BASE_ENGINEER.md +658 -0
  7. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +290 -0
  8. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
  9. claude_mpm/agents/MEMORY.md +72 -0
  10. claude_mpm/agents/PM_INSTRUCTIONS.md +1402 -0
  11. claude_mpm/agents/WORKFLOW.md +111 -0
  12. claude_mpm/agents/__init__.py +92 -80
  13. claude_mpm/agents/agent-template.yaml +83 -0
  14. claude_mpm/agents/agent_loader.py +560 -745
  15. claude_mpm/agents/agent_loader_integration.py +53 -55
  16. claude_mpm/agents/agents_metadata.py +186 -27
  17. claude_mpm/agents/async_agent_loader.py +436 -0
  18. claude_mpm/agents/base_agent.json +8 -4
  19. claude_mpm/agents/frontmatter_validator.py +754 -0
  20. claude_mpm/agents/system_agent_config.py +222 -155
  21. claude_mpm/agents/templates/README.md +465 -0
  22. claude_mpm/agents/templates/__init__.py +17 -13
  23. claude_mpm/agents/templates/circuit-breakers.md +1391 -0
  24. claude_mpm/agents/templates/context-management-examples.md +544 -0
  25. claude_mpm/agents/templates/git-file-tracking.md +584 -0
  26. claude_mpm/agents/templates/pm-examples.md +474 -0
  27. claude_mpm/agents/templates/pm-red-flags.md +310 -0
  28. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  29. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  30. claude_mpm/agents/templates/response-format.md +583 -0
  31. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  32. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  33. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  34. claude_mpm/agents/templates/validation-templates.md +312 -0
  35. claude_mpm/cli/__init__.py +90 -128
  36. claude_mpm/cli/__main__.py +33 -0
  37. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  38. claude_mpm/cli/commands/__init__.py +36 -12
  39. claude_mpm/cli/commands/agent_manager.py +1403 -0
  40. claude_mpm/cli/commands/agent_source.py +774 -0
  41. claude_mpm/cli/commands/agent_state_manager.py +335 -0
  42. claude_mpm/cli/commands/agents.py +2503 -168
  43. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  44. claude_mpm/cli/commands/agents_discover.py +338 -0
  45. claude_mpm/cli/commands/aggregate.py +540 -0
  46. claude_mpm/cli/commands/analyze.py +553 -0
  47. claude_mpm/cli/commands/analyze_code.py +528 -0
  48. claude_mpm/cli/commands/auto_configure.py +1053 -0
  49. claude_mpm/cli/commands/cleanup.py +588 -0
  50. claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
  51. claude_mpm/cli/commands/config.py +586 -0
  52. claude_mpm/cli/commands/configure.py +2654 -0
  53. claude_mpm/cli/commands/configure_agent_display.py +282 -0
  54. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  55. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  56. claude_mpm/cli/commands/configure_models.py +18 -0
  57. claude_mpm/cli/commands/configure_navigation.py +184 -0
  58. claude_mpm/cli/commands/configure_paths.py +104 -0
  59. claude_mpm/cli/commands/configure_persistence.py +254 -0
  60. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  61. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  62. claude_mpm/cli/commands/configure_validators.py +73 -0
  63. claude_mpm/cli/commands/dashboard.py +286 -0
  64. claude_mpm/cli/commands/debug.py +1386 -0
  65. claude_mpm/cli/commands/doctor.py +243 -0
  66. claude_mpm/cli/commands/hook_errors.py +277 -0
  67. claude_mpm/cli/commands/info.py +195 -74
  68. claude_mpm/cli/commands/local_deploy.py +534 -0
  69. claude_mpm/cli/commands/mcp.py +205 -0
  70. claude_mpm/cli/commands/mcp_command_router.py +161 -0
  71. claude_mpm/cli/commands/mcp_config.py +154 -0
  72. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  73. claude_mpm/cli/commands/mcp_external_commands.py +249 -0
  74. claude_mpm/cli/commands/mcp_install_commands.py +346 -0
  75. claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
  76. claude_mpm/cli/commands/mcp_server_commands.py +155 -0
  77. claude_mpm/cli/commands/mcp_setup_external.py +868 -0
  78. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  79. claude_mpm/cli/commands/memory.py +585 -846
  80. claude_mpm/cli/commands/monitor.py +228 -310
  81. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  82. claude_mpm/cli/commands/mpm_init/core.py +759 -0
  83. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  84. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  85. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  86. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  87. claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
  88. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  89. claude_mpm/cli/commands/mpm_init_handler.py +195 -0
  90. claude_mpm/cli/commands/postmortem.py +401 -0
  91. claude_mpm/cli/commands/profile.py +276 -0
  92. claude_mpm/cli/commands/run.py +910 -488
  93. claude_mpm/cli/commands/search.py +458 -0
  94. claude_mpm/cli/commands/skill_source.py +694 -0
  95. claude_mpm/cli/commands/skills.py +1246 -0
  96. claude_mpm/cli/commands/summarize.py +413 -0
  97. claude_mpm/cli/commands/tickets.py +536 -53
  98. claude_mpm/cli/commands/uninstall.py +176 -0
  99. claude_mpm/cli/commands/upgrade.py +152 -0
  100. claude_mpm/cli/commands/verify.py +119 -0
  101. claude_mpm/cli/executor.py +297 -0
  102. claude_mpm/cli/helpers.py +105 -0
  103. claude_mpm/cli/interactive/__init__.py +21 -0
  104. claude_mpm/cli/interactive/agent_wizard.py +1947 -0
  105. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  106. claude_mpm/cli/parser.py +87 -563
  107. claude_mpm/cli/parsers/__init__.py +35 -0
  108. claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
  109. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  110. claude_mpm/cli/parsers/agents_parser.py +575 -0
  111. claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
  112. claude_mpm/cli/parsers/analyze_parser.py +135 -0
  113. claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
  114. claude_mpm/cli/parsers/base_parser.py +644 -0
  115. claude_mpm/cli/parsers/config_parser.py +208 -0
  116. claude_mpm/cli/parsers/configure_parser.py +138 -0
  117. claude_mpm/cli/parsers/dashboard_parser.py +113 -0
  118. claude_mpm/cli/parsers/debug_parser.py +319 -0
  119. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  120. claude_mpm/cli/parsers/mcp_parser.py +195 -0
  121. claude_mpm/cli/parsers/memory_parser.py +138 -0
  122. claude_mpm/cli/parsers/monitor_parser.py +142 -0
  123. claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
  124. claude_mpm/cli/parsers/profile_parser.py +147 -0
  125. claude_mpm/cli/parsers/run_parser.py +157 -0
  126. claude_mpm/cli/parsers/search_parser.py +245 -0
  127. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  128. claude_mpm/cli/parsers/skills_parser.py +277 -0
  129. claude_mpm/cli/parsers/source_parser.py +138 -0
  130. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  131. claude_mpm/cli/shared/__init__.py +40 -0
  132. claude_mpm/cli/shared/argument_patterns.py +205 -0
  133. claude_mpm/cli/shared/base_command.py +242 -0
  134. claude_mpm/cli/shared/error_handling.py +242 -0
  135. claude_mpm/cli/shared/output_formatters.py +241 -0
  136. claude_mpm/cli/startup.py +1743 -0
  137. claude_mpm/cli/startup_display.py +480 -0
  138. claude_mpm/cli/startup_logging.py +839 -0
  139. claude_mpm/cli/utils.py +136 -47
  140. claude_mpm/cli_module/__init__.py +6 -6
  141. claude_mpm/cli_module/args.py +188 -140
  142. claude_mpm/cli_module/commands.py +79 -70
  143. claude_mpm/cli_module/migration_example.py +42 -64
  144. claude_mpm/commands/__init__.py +14 -0
  145. claude_mpm/commands/mpm-config.md +28 -0
  146. claude_mpm/commands/mpm-doctor.md +20 -0
  147. claude_mpm/commands/mpm-help.md +20 -0
  148. claude_mpm/commands/mpm-init.md +120 -0
  149. claude_mpm/commands/mpm-monitor.md +31 -0
  150. claude_mpm/commands/mpm-organize.md +120 -0
  151. claude_mpm/commands/mpm-postmortem.md +21 -0
  152. claude_mpm/commands/mpm-session-resume.md +30 -0
  153. claude_mpm/commands/mpm-status.md +20 -0
  154. claude_mpm/commands/mpm-ticket-view.md +109 -0
  155. claude_mpm/commands/mpm-version.md +20 -0
  156. claude_mpm/commands/mpm.md +31 -0
  157. claude_mpm/config/__init__.py +42 -2
  158. claude_mpm/config/agent_config.py +402 -0
  159. claude_mpm/config/agent_presets.py +488 -0
  160. claude_mpm/config/agent_sources.py +352 -0
  161. claude_mpm/config/experimental_features.py +217 -0
  162. claude_mpm/config/model_config.py +428 -0
  163. claude_mpm/config/paths.py +258 -0
  164. claude_mpm/config/skill_presets.py +392 -0
  165. claude_mpm/config/skill_sources.py +590 -0
  166. claude_mpm/config/socketio_config.py +125 -83
  167. claude_mpm/constants.py +132 -22
  168. claude_mpm/core/__init__.py +62 -36
  169. claude_mpm/core/agent_name_normalizer.py +71 -73
  170. claude_mpm/core/agent_registry.py +385 -492
  171. claude_mpm/core/agent_session_manager.py +81 -70
  172. claude_mpm/core/api_validator.py +330 -0
  173. claude_mpm/core/base_service.py +159 -122
  174. claude_mpm/core/cache.py +560 -0
  175. claude_mpm/core/claude_runner.py +696 -916
  176. claude_mpm/core/config.py +613 -122
  177. claude_mpm/core/config_aliases.py +74 -73
  178. claude_mpm/core/config_constants.py +314 -0
  179. claude_mpm/core/constants.py +361 -0
  180. claude_mpm/core/container.py +646 -104
  181. claude_mpm/core/enums.py +452 -0
  182. claude_mpm/core/error_handler.py +623 -0
  183. claude_mpm/core/exceptions.py +536 -0
  184. claude_mpm/core/factories.py +105 -109
  185. claude_mpm/core/file_utils.py +764 -0
  186. claude_mpm/core/framework/__init__.py +25 -0
  187. claude_mpm/core/framework/formatters/__init__.py +11 -0
  188. claude_mpm/core/framework/formatters/capability_generator.py +367 -0
  189. claude_mpm/core/framework/formatters/content_formatter.py +278 -0
  190. claude_mpm/core/framework/formatters/context_generator.py +185 -0
  191. claude_mpm/core/framework/loaders/__init__.py +13 -0
  192. claude_mpm/core/framework/loaders/agent_loader.py +213 -0
  193. claude_mpm/core/framework/loaders/file_loader.py +176 -0
  194. claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
  195. claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
  196. claude_mpm/core/framework/processors/__init__.py +11 -0
  197. claude_mpm/core/framework/processors/memory_processor.py +230 -0
  198. claude_mpm/core/framework/processors/metadata_processor.py +146 -0
  199. claude_mpm/core/framework/processors/template_processor.py +244 -0
  200. claude_mpm/core/framework_loader.py +485 -414
  201. claude_mpm/core/hook_error_memory.py +381 -0
  202. claude_mpm/core/hook_manager.py +246 -86
  203. claude_mpm/core/hook_performance_config.py +147 -0
  204. claude_mpm/core/injectable_service.py +72 -63
  205. claude_mpm/core/instruction_reinforcement_hook.py +267 -0
  206. claude_mpm/core/interactive_session.py +670 -0
  207. claude_mpm/core/interfaces.py +570 -164
  208. claude_mpm/core/lazy.py +467 -0
  209. claude_mpm/core/log_manager.py +707 -0
  210. claude_mpm/core/logger.py +295 -134
  211. claude_mpm/core/logging_config.py +474 -0
  212. claude_mpm/core/logging_utils.py +520 -0
  213. claude_mpm/core/minimal_framework_loader.py +24 -22
  214. claude_mpm/core/mixins.py +30 -29
  215. claude_mpm/core/oneshot_session.py +594 -0
  216. claude_mpm/core/optimized_agent_loader.py +479 -0
  217. claude_mpm/core/optimized_startup.py +554 -0
  218. claude_mpm/core/output_style_manager.py +483 -0
  219. claude_mpm/core/pm_hook_interceptor.py +197 -82
  220. claude_mpm/core/protocols/__init__.py +23 -0
  221. claude_mpm/core/protocols/runner_protocol.py +103 -0
  222. claude_mpm/core/protocols/session_protocol.py +131 -0
  223. claude_mpm/core/service_registry.py +153 -116
  224. claude_mpm/core/session_manager.py +179 -64
  225. claude_mpm/core/shared/__init__.py +17 -0
  226. claude_mpm/core/shared/config_loader.py +326 -0
  227. claude_mpm/core/shared/path_resolver.py +281 -0
  228. claude_mpm/core/shared/singleton_manager.py +221 -0
  229. claude_mpm/core/socketio_pool.py +400 -137
  230. claude_mpm/core/system_context.py +38 -0
  231. claude_mpm/core/tool_access_control.py +64 -57
  232. claude_mpm/core/types.py +307 -0
  233. claude_mpm/core/typing_utils.py +553 -0
  234. claude_mpm/core/unified_agent_registry.py +969 -0
  235. claude_mpm/core/unified_config.py +570 -0
  236. claude_mpm/core/unified_paths.py +941 -0
  237. claude_mpm/dashboard/__init__.py +12 -0
  238. claude_mpm/dashboard/api/simple_directory.py +261 -0
  239. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  240. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
  241. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
  242. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
  243. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
  244. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
  245. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
  246. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
  247. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
  248. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
  249. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
  250. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  251. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
  252. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
  253. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
  254. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
  255. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
  256. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
  257. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
  258. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
  259. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
  260. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
  261. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
  262. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
  263. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
  264. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  265. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
  266. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
  267. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  268. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
  269. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
  270. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
  271. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
  272. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
  273. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
  274. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
  275. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
  276. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
  277. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  278. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
  279. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
  280. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
  281. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
  282. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
  283. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
  284. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
  285. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
  286. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
  287. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
  288. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  289. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
  290. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
  291. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
  292. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
  293. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
  294. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
  295. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
  296. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
  297. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
  298. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
  299. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
  300. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
  301. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
  302. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
  303. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
  304. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  305. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  306. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  307. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  308. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  309. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  310. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  311. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  312. claude_mpm/experimental/__init__.py +10 -0
  313. claude_mpm/experimental/cli_enhancements.py +104 -89
  314. claude_mpm/generators/__init__.py +1 -1
  315. claude_mpm/generators/agent_profile_generator.py +76 -66
  316. claude_mpm/hooks/__init__.py +37 -1
  317. claude_mpm/hooks/base_hook.py +37 -32
  318. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  319. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  320. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  321. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  322. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  323. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  324. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  325. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  326. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  327. claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
  328. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  329. claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
  330. claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
  331. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
  332. claude_mpm/hooks/claude_hooks/installer.py +806 -0
  333. claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
  334. claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
  335. claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
  336. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  337. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  338. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  339. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  340. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  341. claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
  342. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
  343. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  344. claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
  345. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  346. claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
  347. claude_mpm/hooks/failure_learning/__init__.py +54 -0
  348. claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
  349. claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
  350. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
  351. claude_mpm/hooks/instruction_reinforcement.py +301 -0
  352. claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
  353. claude_mpm/hooks/kuzu_memory_hook.py +386 -0
  354. claude_mpm/hooks/kuzu_response_hook.py +179 -0
  355. claude_mpm/hooks/memory_integration_hook.py +201 -107
  356. claude_mpm/hooks/session_resume_hook.py +121 -0
  357. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  358. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  359. claude_mpm/hooks/tool_call_interceptor.py +92 -76
  360. claude_mpm/hooks/validation_hooks.py +62 -54
  361. claude_mpm/init.py +518 -83
  362. claude_mpm/models/__init__.py +9 -9
  363. claude_mpm/models/agent_definition.py +40 -23
  364. claude_mpm/models/agent_session.py +538 -0
  365. claude_mpm/models/git_repository.py +198 -0
  366. claude_mpm/models/resume_log.py +340 -0
  367. claude_mpm/schemas/__init__.py +12 -0
  368. claude_mpm/scripts/__init__.py +15 -0
  369. claude_mpm/scripts/claude-hook-handler.sh +227 -0
  370. claude_mpm/scripts/launch_monitor.py +165 -0
  371. claude_mpm/scripts/mpm_doctor.py +322 -0
  372. claude_mpm/scripts/socketio_daemon.py +189 -200
  373. claude_mpm/scripts/start_activity_logging.py +91 -0
  374. claude_mpm/services/__init__.py +208 -39
  375. claude_mpm/services/agent_capabilities_service.py +266 -0
  376. claude_mpm/services/agents/__init__.py +89 -0
  377. claude_mpm/services/agents/agent_builder.py +514 -0
  378. claude_mpm/services/agents/agent_preset_service.py +238 -0
  379. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  380. claude_mpm/services/agents/agent_review_service.py +280 -0
  381. claude_mpm/services/agents/agent_selection_service.py +484 -0
  382. claude_mpm/services/agents/auto_config_manager.py +796 -0
  383. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  384. claude_mpm/services/agents/cache_git_manager.py +621 -0
  385. claude_mpm/services/agents/deployment/__init__.py +21 -0
  386. claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
  387. claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
  388. claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
  389. claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
  390. claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
  391. claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
  392. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
  393. claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
  394. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
  395. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
  396. claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
  397. claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
  398. claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
  399. claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
  400. claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
  401. claude_mpm/services/agents/deployment/agent_template_builder.py +1369 -0
  402. claude_mpm/services/agents/deployment/agent_validator.py +376 -0
  403. claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
  404. claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
  405. claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
  406. claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
  407. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  408. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  409. claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
  410. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  411. claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
  412. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  413. claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
  414. claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -0
  415. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  416. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  417. claude_mpm/services/agents/deployment/facade/deployment_executor.py +70 -0
  418. claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
  419. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  420. claude_mpm/services/agents/deployment/interface_adapter.py +226 -0
  421. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  422. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  423. claude_mpm/services/agents/deployment/local_template_deployment.py +362 -0
  424. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -0
  425. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  426. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  427. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +162 -0
  428. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  429. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  430. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +240 -0
  431. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
  432. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
  433. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
  434. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
  435. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  436. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
  437. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  438. claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
  439. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
  440. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -0
  441. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  442. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  443. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  444. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  445. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  446. claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
  447. claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
  448. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  449. claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
  450. claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
  451. claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
  452. claude_mpm/services/agents/deployment/validation/__init__.py +21 -0
  453. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  454. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  455. claude_mpm/services/agents/deployment/validation/template_validator.py +319 -0
  456. claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
  457. claude_mpm/services/agents/git_source_manager.py +682 -0
  458. claude_mpm/services/agents/loading/__init__.py +11 -0
  459. claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
  460. claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
  461. claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
  462. claude_mpm/services/agents/local_template_manager.py +784 -0
  463. claude_mpm/services/agents/management/__init__.py +9 -0
  464. claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
  465. claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
  466. claude_mpm/services/agents/memory/__init__.py +22 -0
  467. claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
  468. claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
  469. claude_mpm/services/agents/memory/content_manager.py +470 -0
  470. claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
  471. claude_mpm/services/agents/memory/memory_file_service.py +129 -0
  472. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  473. claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
  474. claude_mpm/services/agents/memory/template_generator.py +83 -0
  475. claude_mpm/services/agents/observers.py +547 -0
  476. claude_mpm/services/agents/recommender.py +617 -0
  477. claude_mpm/services/agents/registry/__init__.py +30 -0
  478. claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
  479. claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
  480. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  481. claude_mpm/services/agents/sources/__init__.py +13 -0
  482. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  483. claude_mpm/services/agents/sources/git_source_sync_service.py +1202 -0
  484. claude_mpm/services/agents/startup_sync.py +259 -0
  485. claude_mpm/services/agents/toolchain_detector.py +478 -0
  486. claude_mpm/services/analysis/__init__.py +35 -0
  487. claude_mpm/services/analysis/clone_detector.py +1030 -0
  488. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  489. claude_mpm/services/analysis/postmortem_service.py +765 -0
  490. claude_mpm/services/async_session_logger.py +665 -0
  491. claude_mpm/services/claude_session_logger.py +321 -0
  492. claude_mpm/services/cli/__init__.py +18 -0
  493. claude_mpm/services/cli/agent_cleanup_service.py +408 -0
  494. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  495. claude_mpm/services/cli/agent_listing_service.py +463 -0
  496. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  497. claude_mpm/services/cli/agent_validation_service.py +590 -0
  498. claude_mpm/services/cli/memory_crud_service.py +622 -0
  499. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  500. claude_mpm/services/cli/resume_service.py +617 -0
  501. claude_mpm/services/cli/session_manager.py +604 -0
  502. claude_mpm/services/cli/session_pause_manager.py +504 -0
  503. claude_mpm/services/cli/session_resume_helper.py +372 -0
  504. claude_mpm/services/cli/startup_checker.py +362 -0
  505. claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
  506. claude_mpm/services/command_deployment_service.py +446 -0
  507. claude_mpm/services/command_handler_service.py +221 -0
  508. claude_mpm/services/communication/__init__.py +22 -0
  509. claude_mpm/services/core/__init__.py +108 -0
  510. claude_mpm/services/core/base.py +269 -0
  511. claude_mpm/services/core/cache_manager.py +309 -0
  512. claude_mpm/services/core/interfaces/__init__.py +273 -0
  513. claude_mpm/services/core/interfaces/agent.py +514 -0
  514. claude_mpm/services/core/interfaces/communication.py +316 -0
  515. claude_mpm/services/core/interfaces/health.py +169 -0
  516. claude_mpm/services/core/interfaces/infrastructure.py +357 -0
  517. claude_mpm/services/core/interfaces/model.py +281 -0
  518. claude_mpm/services/core/interfaces/process.py +372 -0
  519. claude_mpm/services/core/interfaces/project.py +121 -0
  520. claude_mpm/services/core/interfaces/restart.py +307 -0
  521. claude_mpm/services/core/interfaces/service.py +405 -0
  522. claude_mpm/services/core/interfaces/stability.py +260 -0
  523. claude_mpm/services/core/interfaces.py +81 -0
  524. claude_mpm/services/core/memory_manager.py +682 -0
  525. claude_mpm/services/core/models/__init__.py +70 -0
  526. claude_mpm/services/core/models/agent_config.py +384 -0
  527. claude_mpm/services/core/models/health.py +162 -0
  528. claude_mpm/services/core/models/process.py +239 -0
  529. claude_mpm/services/core/models/restart.py +302 -0
  530. claude_mpm/services/core/models/stability.py +264 -0
  531. claude_mpm/services/core/models/toolchain.py +306 -0
  532. claude_mpm/services/core/path_resolver.py +517 -0
  533. claude_mpm/services/core/service_container.py +520 -0
  534. claude_mpm/services/core/service_interfaces.py +436 -0
  535. claude_mpm/services/diagnostics/__init__.py +18 -0
  536. claude_mpm/services/diagnostics/checks/__init__.py +38 -0
  537. claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
  538. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  539. claude_mpm/services/diagnostics/checks/base_check.py +60 -0
  540. claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
  541. claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
  542. claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
  543. claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
  544. claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
  545. claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
  546. claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
  547. claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
  548. claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
  549. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  550. claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
  551. claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
  552. claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
  553. claude_mpm/services/diagnostics/models.py +138 -0
  554. claude_mpm/services/event_aggregator.py +582 -0
  555. claude_mpm/services/event_bus/__init__.py +18 -0
  556. claude_mpm/services/event_bus/config.py +186 -0
  557. claude_mpm/services/event_bus/direct_relay.py +312 -0
  558. claude_mpm/services/event_bus/event_bus.py +396 -0
  559. claude_mpm/services/event_bus/relay.py +326 -0
  560. claude_mpm/services/events/__init__.py +44 -0
  561. claude_mpm/services/events/consumers/__init__.py +18 -0
  562. claude_mpm/services/events/consumers/dead_letter.py +306 -0
  563. claude_mpm/services/events/consumers/logging.py +184 -0
  564. claude_mpm/services/events/consumers/metrics.py +241 -0
  565. claude_mpm/services/events/consumers/socketio.py +377 -0
  566. claude_mpm/services/events/core.py +480 -0
  567. claude_mpm/services/events/interfaces.py +214 -0
  568. claude_mpm/services/events/producers/__init__.py +14 -0
  569. claude_mpm/services/events/producers/hook.py +269 -0
  570. claude_mpm/services/events/producers/system.py +329 -0
  571. claude_mpm/services/exceptions.py +433 -353
  572. claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
  573. claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
  574. claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
  575. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
  576. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
  577. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
  578. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
  579. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
  580. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  581. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  582. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  583. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  584. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +5 -4
  585. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  586. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  587. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +26 -30
  588. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
  589. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  590. claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
  591. claude_mpm/services/git/__init__.py +21 -0
  592. claude_mpm/services/git/git_operations_service.py +579 -0
  593. claude_mpm/services/github/__init__.py +21 -0
  594. claude_mpm/services/github/github_cli_service.py +397 -0
  595. claude_mpm/services/hook_installer_service.py +506 -0
  596. claude_mpm/services/hook_service.py +159 -111
  597. claude_mpm/services/infrastructure/__init__.py +52 -0
  598. claude_mpm/services/infrastructure/context_preservation.py +569 -0
  599. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  600. claude_mpm/services/infrastructure/logging.py +209 -0
  601. claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
  602. claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
  603. claude_mpm/services/infrastructure/monitoring/base.py +122 -0
  604. claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
  605. claude_mpm/services/infrastructure/monitoring/network.py +219 -0
  606. claude_mpm/services/infrastructure/monitoring/process.py +343 -0
  607. claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
  608. claude_mpm/services/infrastructure/monitoring/service.py +368 -0
  609. claude_mpm/services/infrastructure/monitoring.py +71 -0
  610. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  611. claude_mpm/services/instructions/__init__.py +9 -0
  612. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  613. claude_mpm/services/local_ops/__init__.py +155 -0
  614. claude_mpm/services/local_ops/crash_detector.py +257 -0
  615. claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
  616. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  617. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  618. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  619. claude_mpm/services/local_ops/health_manager.py +427 -0
  620. claude_mpm/services/local_ops/log_monitor.py +396 -0
  621. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  622. claude_mpm/services/local_ops/process_manager.py +595 -0
  623. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  624. claude_mpm/services/local_ops/restart_manager.py +401 -0
  625. claude_mpm/services/local_ops/restart_policy.py +387 -0
  626. claude_mpm/services/local_ops/state_manager.py +372 -0
  627. claude_mpm/services/local_ops/unified_manager.py +600 -0
  628. claude_mpm/services/mcp_config_manager.py +1542 -0
  629. claude_mpm/services/mcp_service_verifier.py +732 -0
  630. claude_mpm/services/memory/__init__.py +19 -0
  631. claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
  632. claude_mpm/services/memory/cache/__init__.py +14 -0
  633. claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
  634. claude_mpm/services/memory/cache/simple_cache.py +331 -0
  635. claude_mpm/services/memory/failure_tracker.py +578 -0
  636. claude_mpm/services/memory/indexed_memory.py +648 -0
  637. claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
  638. claude_mpm/services/memory/router.py +951 -0
  639. claude_mpm/services/memory_hook_service.py +470 -0
  640. claude_mpm/services/model/__init__.py +147 -0
  641. claude_mpm/services/model/base_provider.py +365 -0
  642. claude_mpm/services/model/claude_provider.py +412 -0
  643. claude_mpm/services/model/model_router.py +452 -0
  644. claude_mpm/services/model/ollama_provider.py +415 -0
  645. claude_mpm/services/monitor/__init__.py +20 -0
  646. claude_mpm/services/monitor/daemon.py +698 -0
  647. claude_mpm/services/monitor/daemon_manager.py +1076 -0
  648. claude_mpm/services/monitor/event_emitter.py +350 -0
  649. claude_mpm/services/monitor/handlers/__init__.py +21 -0
  650. claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
  651. claude_mpm/services/monitor/handlers/dashboard.py +299 -0
  652. claude_mpm/services/monitor/handlers/file.py +264 -0
  653. claude_mpm/services/monitor/handlers/hooks.py +512 -0
  654. claude_mpm/services/monitor/management/__init__.py +18 -0
  655. claude_mpm/services/monitor/management/health.py +124 -0
  656. claude_mpm/services/monitor/management/lifecycle.py +730 -0
  657. claude_mpm/services/monitor/server.py +1493 -0
  658. claude_mpm/services/monitor_build_service.py +349 -0
  659. claude_mpm/services/native_agent_converter.py +356 -0
  660. claude_mpm/services/orphan_detection.py +786 -0
  661. claude_mpm/services/pm_skills_deployer.py +707 -0
  662. claude_mpm/services/port_manager.py +597 -0
  663. claude_mpm/services/pr/__init__.py +14 -0
  664. claude_mpm/services/pr/pr_template_service.py +329 -0
  665. claude_mpm/services/profile_manager.py +337 -0
  666. claude_mpm/services/project/__init__.py +44 -0
  667. claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
  668. claude_mpm/services/project/analyzer_v2.py +566 -0
  669. claude_mpm/services/project/architecture_analyzer.py +461 -0
  670. claude_mpm/services/project/archive_manager.py +1045 -0
  671. claude_mpm/services/project/dependency_analyzer.py +462 -0
  672. claude_mpm/services/project/detection_strategies.py +719 -0
  673. claude_mpm/services/project/documentation_manager.py +554 -0
  674. claude_mpm/services/project/enhanced_analyzer.py +572 -0
  675. claude_mpm/services/project/language_analyzer.py +265 -0
  676. claude_mpm/services/project/metrics_collector.py +407 -0
  677. claude_mpm/services/project/project_organizer.py +1009 -0
  678. claude_mpm/services/project/registry.py +636 -0
  679. claude_mpm/services/project/toolchain_analyzer.py +583 -0
  680. claude_mpm/services/project_port_allocator.py +596 -0
  681. claude_mpm/services/recovery_manager.py +293 -240
  682. claude_mpm/services/response_tracker.py +267 -0
  683. claude_mpm/services/runner_configuration_service.py +605 -0
  684. claude_mpm/services/self_upgrade_service.py +608 -0
  685. claude_mpm/services/session_management_service.py +314 -0
  686. claude_mpm/services/session_manager.py +380 -0
  687. claude_mpm/services/shared/__init__.py +21 -0
  688. claude_mpm/services/shared/async_service_base.py +216 -0
  689. claude_mpm/services/shared/config_service_base.py +301 -0
  690. claude_mpm/services/shared/lifecycle_service_base.py +308 -0
  691. claude_mpm/services/shared/manager_base.py +315 -0
  692. claude_mpm/services/shared/service_factory.py +309 -0
  693. claude_mpm/services/skills/__init__.py +21 -0
  694. claude_mpm/services/skills/git_skill_source_manager.py +1324 -0
  695. claude_mpm/services/skills/selective_skill_deployer.py +744 -0
  696. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  697. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  698. claude_mpm/services/skills_config.py +547 -0
  699. claude_mpm/services/skills_deployer.py +1168 -0
  700. claude_mpm/services/socketio/__init__.py +25 -0
  701. claude_mpm/services/socketio/client_proxy.py +229 -0
  702. claude_mpm/services/socketio/dashboard_server.py +362 -0
  703. claude_mpm/services/socketio/event_normalizer.py +798 -0
  704. claude_mpm/services/socketio/handlers/__init__.py +30 -0
  705. claude_mpm/services/socketio/handlers/base.py +136 -0
  706. claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
  707. claude_mpm/services/socketio/handlers/connection.py +643 -0
  708. claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
  709. claude_mpm/services/socketio/handlers/file.py +263 -0
  710. claude_mpm/services/socketio/handlers/git.py +962 -0
  711. claude_mpm/services/socketio/handlers/hook.py +211 -0
  712. claude_mpm/services/socketio/handlers/memory.py +26 -0
  713. claude_mpm/services/socketio/handlers/project.py +24 -0
  714. claude_mpm/services/socketio/handlers/registry.py +214 -0
  715. claude_mpm/services/socketio/migration_utils.py +343 -0
  716. claude_mpm/services/socketio/monitor_client.py +364 -0
  717. claude_mpm/services/socketio/server/__init__.py +18 -0
  718. claude_mpm/services/socketio/server/broadcaster.py +569 -0
  719. claude_mpm/services/socketio/server/connection_manager.py +579 -0
  720. claude_mpm/services/socketio/server/core.py +1079 -0
  721. claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
  722. claude_mpm/services/socketio/server/main.py +501 -0
  723. claude_mpm/services/socketio_client_manager.py +173 -143
  724. claude_mpm/services/socketio_server.py +38 -1657
  725. claude_mpm/services/subprocess_launcher_service.py +322 -0
  726. claude_mpm/services/system_instructions_service.py +270 -0
  727. claude_mpm/services/ticket_manager.py +25 -209
  728. claude_mpm/services/ticket_services/__init__.py +26 -0
  729. claude_mpm/services/ticket_services/crud_service.py +328 -0
  730. claude_mpm/services/ticket_services/formatter_service.py +290 -0
  731. claude_mpm/services/ticket_services/search_service.py +324 -0
  732. claude_mpm/services/ticket_services/validation_service.py +303 -0
  733. claude_mpm/services/ticket_services/workflow_service.py +244 -0
  734. claude_mpm/services/unified/__init__.py +65 -0
  735. claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
  736. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
  737. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
  738. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
  739. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
  740. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
  741. claude_mpm/services/unified/config_strategies/__init__.py +175 -0
  742. claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
  743. claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
  744. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
  745. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
  746. claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
  747. claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
  748. claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
  749. claude_mpm/services/unified/deployment_strategies/base.py +553 -0
  750. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
  751. claude_mpm/services/unified/deployment_strategies/local.py +607 -0
  752. claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
  753. claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
  754. claude_mpm/services/unified/interfaces.py +475 -0
  755. claude_mpm/services/unified/migration.py +509 -0
  756. claude_mpm/services/unified/strategies.py +534 -0
  757. claude_mpm/services/unified/unified_analyzer.py +542 -0
  758. claude_mpm/services/unified/unified_config.py +691 -0
  759. claude_mpm/services/unified/unified_deployment.py +466 -0
  760. claude_mpm/services/utility_service.py +280 -0
  761. claude_mpm/services/version_control/__init__.py +34 -37
  762. claude_mpm/services/version_control/branch_strategy.py +26 -17
  763. claude_mpm/services/version_control/conflict_resolution.py +52 -36
  764. claude_mpm/services/version_control/git_operations.py +183 -49
  765. claude_mpm/services/version_control/semantic_versioning.py +172 -61
  766. claude_mpm/services/version_control/version_parser.py +546 -0
  767. claude_mpm/services/version_service.py +379 -0
  768. claude_mpm/services/visualization/__init__.py +15 -0
  769. claude_mpm/services/visualization/mermaid_generator.py +937 -0
  770. claude_mpm/skills/__init__.py +42 -0
  771. claude_mpm/skills/agent_skills_injector.py +324 -0
  772. claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
  773. claude_mpm/skills/bundled/__init__.py +6 -0
  774. claude_mpm/skills/bundled/api-documentation.md +393 -0
  775. claude_mpm/skills/bundled/async-testing.md +571 -0
  776. claude_mpm/skills/bundled/code-review.md +143 -0
  777. claude_mpm/skills/bundled/database-migration.md +199 -0
  778. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  779. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  780. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  781. claude_mpm/skills/bundled/git-workflow.md +414 -0
  782. claude_mpm/skills/bundled/imagemagick.md +204 -0
  783. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  784. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  785. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
  786. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
  787. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
  788. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
  789. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
  790. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  791. claude_mpm/skills/bundled/pdf.md +141 -0
  792. claude_mpm/skills/bundled/performance-profiling.md +573 -0
  793. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  794. claude_mpm/skills/bundled/security-scanning.md +439 -0
  795. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  796. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  797. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
  798. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
  799. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
  800. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
  801. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  802. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  803. claude_mpm/skills/bundled/xlsx.md +157 -0
  804. claude_mpm/skills/registry.py +286 -0
  805. claude_mpm/skills/skill_manager.py +405 -0
  806. claude_mpm/skills/skills_registry.py +347 -0
  807. claude_mpm/skills/skills_service.py +739 -0
  808. claude_mpm/storage/__init__.py +9 -0
  809. claude_mpm/storage/state_storage.py +546 -0
  810. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  811. claude_mpm/templates/questions/__init__.py +38 -0
  812. claude_mpm/templates/questions/base.py +193 -0
  813. claude_mpm/templates/questions/pr_strategy.py +311 -0
  814. claude_mpm/templates/questions/project_init.py +385 -0
  815. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  816. claude_mpm/ticket_wrapper.py +2 -2
  817. claude_mpm/tools/__init__.py +10 -0
  818. claude_mpm/tools/__main__.py +208 -0
  819. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  820. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  821. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  822. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  823. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  824. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  825. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  826. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  827. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  828. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  829. claude_mpm/tools/code_tree_builder.py +631 -0
  830. claude_mpm/tools/code_tree_events.py +420 -0
  831. claude_mpm/tools/socketio_debug.py +671 -0
  832. claude_mpm/utils/__init__.py +8 -8
  833. claude_mpm/utils/agent_dependency_loader.py +1090 -0
  834. claude_mpm/utils/agent_filters.py +261 -0
  835. claude_mpm/utils/common.py +544 -0
  836. claude_mpm/utils/config_manager.py +168 -126
  837. claude_mpm/utils/console.py +11 -0
  838. claude_mpm/utils/database_connector.py +298 -0
  839. claude_mpm/utils/dependency_cache.py +373 -0
  840. claude_mpm/utils/dependency_manager.py +60 -59
  841. claude_mpm/utils/dependency_strategies.py +381 -0
  842. claude_mpm/utils/display_helper.py +260 -0
  843. claude_mpm/utils/environment_context.py +313 -0
  844. claude_mpm/utils/error_handler.py +78 -66
  845. claude_mpm/utils/file_utils.py +305 -0
  846. claude_mpm/utils/framework_detection.py +12 -11
  847. claude_mpm/utils/git_analyzer.py +407 -0
  848. claude_mpm/utils/gitignore.py +244 -0
  849. claude_mpm/utils/import_migration_example.py +12 -60
  850. claude_mpm/utils/imports.py +48 -45
  851. claude_mpm/utils/log_cleanup.py +627 -0
  852. claude_mpm/utils/migration.py +372 -0
  853. claude_mpm/utils/path_operations.py +110 -104
  854. claude_mpm/utils/progress.py +387 -0
  855. claude_mpm/utils/robust_installer.py +823 -0
  856. claude_mpm/utils/session_logging.py +121 -0
  857. claude_mpm/utils/structured_questions.py +619 -0
  858. claude_mpm/utils/subprocess_utils.py +343 -0
  859. claude_mpm/validation/__init__.py +1 -1
  860. claude_mpm/validation/agent_validator.py +214 -108
  861. claude_mpm/validation/frontmatter_validator.py +252 -0
  862. claude_mpm-5.4.55.dist-info/METADATA +999 -0
  863. claude_mpm-5.4.55.dist-info/RECORD +868 -0
  864. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/entry_points.txt +1 -3
  865. claude_mpm-5.4.55.dist-info/licenses/LICENSE +94 -0
  866. claude_mpm-5.4.55.dist-info/licenses/LICENSE-FAQ.md +153 -0
  867. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
  868. claude_mpm/agents/INSTRUCTIONS.md +0 -352
  869. claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
  870. claude_mpm/agents/base_agent_loader.py +0 -529
  871. claude_mpm/agents/schema/agent_schema.json +0 -314
  872. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
  873. claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
  874. claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
  875. claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
  876. claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
  877. claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
  878. claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
  879. claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
  880. claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
  881. claude_mpm/agents/templates/data_engineer.json +0 -110
  882. claude_mpm/agents/templates/documentation.json +0 -109
  883. claude_mpm/agents/templates/engineer.json +0 -113
  884. claude_mpm/agents/templates/ops.json +0 -109
  885. claude_mpm/agents/templates/pm.json +0 -25
  886. claude_mpm/agents/templates/qa.json +0 -111
  887. claude_mpm/agents/templates/research.json +0 -65
  888. claude_mpm/agents/templates/security.json +0 -113
  889. claude_mpm/agents/templates/test_integration.json +0 -112
  890. claude_mpm/agents/templates/version_control.json +0 -107
  891. claude_mpm/cli/commands/ui.py +0 -57
  892. claude_mpm/core/simple_runner.py +0 -1046
  893. claude_mpm/dashboard/open_dashboard.py +0 -34
  894. claude_mpm/deployment_paths.py +0 -261
  895. claude_mpm/hooks/builtin/__init__.py +0 -1
  896. claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
  897. claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
  898. claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
  899. claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
  900. claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
  901. claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
  902. claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
  903. claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
  904. claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
  905. claude_mpm/orchestration/__init__.py +0 -6
  906. claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
  907. claude_mpm/orchestration/archive/factory.py +0 -215
  908. claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
  909. claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
  910. claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
  911. claude_mpm/orchestration/archive/orchestrator.py +0 -501
  912. claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
  913. claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
  914. claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
  915. claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
  916. claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
  917. claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
  918. claude_mpm/schemas/workflow_validator.py +0 -411
  919. claude_mpm/services/agent_deployment.py +0 -1534
  920. claude_mpm/services/agent_lifecycle_manager.py +0 -1169
  921. claude_mpm/services/agent_memory_manager.py +0 -1415
  922. claude_mpm/services/agent_registry.py +0 -676
  923. claude_mpm/services/deployed_agent_discovery.py +0 -226
  924. claude_mpm/services/framework_agent_loader.py +0 -337
  925. claude_mpm/services/framework_claude_md_generator.py +0 -621
  926. claude_mpm/services/health_monitor.py +0 -892
  927. claude_mpm/services/memory_router.py +0 -538
  928. claude_mpm/services/parent_directory_manager/__init__.py +0 -577
  929. claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
  930. claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
  931. claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
  932. claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
  933. claude_mpm/services/parent_directory_manager/operations.py +0 -186
  934. claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
  935. claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
  936. claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
  937. claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
  938. claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
  939. claude_mpm/services/standalone_socketio_server.py +0 -1300
  940. claude_mpm/services/ticket_manager_di.py +0 -318
  941. claude_mpm/services/ticketing_service_original.py +0 -508
  942. claude_mpm/ui/__init__.py +0 -1
  943. claude_mpm/ui/rich_terminal_ui.py +0 -295
  944. claude_mpm/ui/terminal_ui.py +0 -328
  945. claude_mpm/utils/paths.py +0 -289
  946. claude_mpm-3.4.10.dist-info/METADATA +0 -183
  947. claude_mpm-3.4.10.dist-info/RECORD +0 -201
  948. claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
  949. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/WHEEL +0 -0
  950. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/top_level.txt +0 -0
@@ -1,44 +1,33 @@
1
1
  """Claude runner with both exec and subprocess launch methods."""
2
2
 
3
- import json
4
3
  import os
5
- import subprocess
6
- import sys
7
- import time
8
- from datetime import datetime
9
4
  from pathlib import Path
10
5
  from typing import Optional
11
- import uuid
12
-
13
- try:
14
- from claude_mpm.services.agent_deployment import AgentDeploymentService
15
- from claude_mpm.services.ticket_manager import TicketManager
16
- from claude_mpm.services.hook_service import HookService
17
- from claude_mpm.core.config import Config
18
- from claude_mpm.core.logger import get_logger, get_project_logger, ProjectLogger
19
- except ImportError:
20
- from claude_mpm.services.agent_deployment import AgentDeploymentService
21
- from claude_mpm.services.ticket_manager import TicketManager
22
- from claude_mpm.services.hook_service import HookService
23
- from claude_mpm.core.config import Config
24
- from claude_mpm.core.logger import get_logger, get_project_logger, ProjectLogger
6
+
7
+ # Core imports that don't cause circular dependencies
8
+ from claude_mpm.core.container import get_container
9
+ from claude_mpm.core.interfaces import AgentDeploymentInterface
10
+ from claude_mpm.core.logging_config import get_logger
11
+ from claude_mpm.services.core.interfaces import RunnerConfigurationInterface
12
+
13
+ # Type checking imports to avoid circular dependencies
25
14
 
26
15
 
27
16
  class ClaudeRunner:
28
17
  """
29
18
  Claude runner that replaces the entire orchestrator system.
30
-
19
+
31
20
  This does exactly what we need:
32
21
  1. Deploy native agents to .claude/agents/
33
22
  2. Run Claude CLI with either exec or subprocess
34
23
  3. Extract tickets if needed
35
24
  4. Handle both interactive and non-interactive modes
36
-
25
+
37
26
  Supports two launch methods:
38
27
  - exec: Replace current process (default for backward compatibility)
39
28
  - subprocess: Launch as child process for more control
40
29
  """
41
-
30
+
42
31
  def __init__(
43
32
  self,
44
33
  enable_tickets: bool = True,
@@ -46,984 +35,775 @@ class ClaudeRunner:
46
35
  claude_args: Optional[list] = None,
47
36
  launch_method: str = "exec", # "exec" or "subprocess"
48
37
  enable_websocket: bool = False,
49
- websocket_port: int = 8765
38
+ websocket_port: int = 8765,
39
+ use_native_agents: bool = False, # Use --agents flag instead of file deployment
50
40
  ):
51
- """Initialize the Claude runner."""
52
- self.enable_tickets = enable_tickets
53
- self.log_level = log_level
54
- self.logger = get_logger("claude_runner")
55
- self.claude_args = claude_args or []
56
- self.launch_method = launch_method
57
- self.enable_websocket = enable_websocket
58
- self.websocket_port = websocket_port
59
-
60
- # Initialize project logger for session logging
61
- self.project_logger = None
62
- if log_level != "OFF":
63
- try:
64
- self.project_logger = get_project_logger(log_level)
65
- self.project_logger.log_system(
66
- f"Initializing ClaudeRunner with {launch_method} launcher",
67
- level="INFO",
68
- component="runner"
69
- )
70
- except Exception as e:
71
- self.logger.warning(f"Failed to initialize project logger: {e}")
72
-
73
- # Initialize services
74
- self.deployment_service = AgentDeploymentService()
75
- if enable_tickets:
76
- try:
77
- self.ticket_manager = TicketManager()
78
- except (ImportError, TypeError, Exception) as e:
79
- self.logger.warning(f"Ticket manager not available: {e}")
80
- self.ticket_manager = None
81
- self.enable_tickets = False
82
-
83
- # Initialize hook service and register memory hooks
84
- self.config = Config()
85
- self.hook_service = HookService(self.config)
86
- self._register_memory_hooks()
87
-
88
- # Load system instructions
89
- self.system_instructions = self._load_system_instructions()
90
-
91
- # Track if we need to create session logs
92
- self.session_log_file = None
93
- if self.project_logger and log_level != "OFF":
94
- try:
95
- # Create a system.jsonl file in the session directory
96
- self.session_log_file = self.project_logger.session_dir / "system.jsonl"
97
- self._log_session_event({
41
+ """Initialize the Claude runner.
42
+
43
+ Args:
44
+ enable_tickets: Enable ticket extraction (deprecated)
45
+ log_level: Logging level
46
+ claude_args: Additional arguments for Claude CLI
47
+ launch_method: "exec" or "subprocess" launch mode
48
+ enable_websocket: Enable WebSocket server
49
+ websocket_port: WebSocket server port
50
+ use_native_agents: Use --agents CLI flag instead of .claude/agents/ deployment
51
+ """
52
+ self.logger = get_logger(__name__)
53
+
54
+ # Initialize configuration service
55
+ container = get_container()
56
+ if not container.is_registered(RunnerConfigurationInterface):
57
+ from claude_mpm.services.runner_configuration_service import (
58
+ RunnerConfigurationService,
59
+ )
60
+
61
+ container.register_singleton(
62
+ RunnerConfigurationInterface, RunnerConfigurationService
63
+ )
64
+
65
+ try:
66
+ self.configuration_service = container.get(RunnerConfigurationInterface)
67
+ except Exception as e:
68
+ self.logger.error(
69
+ "Failed to initialize configuration service", exc_info=True
70
+ )
71
+ raise RuntimeError(
72
+ f"Configuration service initialization failed: {e}"
73
+ ) from e
74
+
75
+ # Initialize configuration using the service
76
+ config_data = self.configuration_service.initialize_configuration(
77
+ enable_tickets=enable_tickets,
78
+ log_level=log_level,
79
+ claude_args=claude_args,
80
+ launch_method=launch_method,
81
+ enable_websocket=enable_websocket,
82
+ websocket_port=websocket_port,
83
+ use_native_agents=use_native_agents,
84
+ )
85
+
86
+ # Set configuration attributes
87
+ self.enable_tickets = config_data["enable_tickets"]
88
+ self.log_level = config_data["log_level"]
89
+ self.claude_args = config_data["claude_args"]
90
+ self.launch_method = config_data["launch_method"]
91
+ self.enable_websocket = config_data["enable_websocket"]
92
+ self.websocket_port = config_data["websocket_port"]
93
+ self.use_native_agents = config_data.get("use_native_agents", False)
94
+ self.config = config_data["config"]
95
+
96
+ # Initialize project logger using the service
97
+ self.project_logger = self.configuration_service.initialize_project_logger(
98
+ self.log_level
99
+ )
100
+
101
+ # Initialize services using dependency injection and configuration service
102
+ user_working_dir = self.configuration_service.get_user_working_directory()
103
+
104
+ # Register core services
105
+ self.configuration_service.register_core_services(container, user_working_dir)
106
+
107
+ try:
108
+ self.deployment_service = container.get(AgentDeploymentInterface)
109
+ except Exception as e:
110
+ self.logger.error("Failed to resolve AgentDeploymentService", exc_info=True)
111
+ raise RuntimeError(
112
+ f"Agent deployment service initialization failed: {e}"
113
+ ) from e
114
+
115
+ # Ticket manager disabled - use claude-mpm tickets CLI commands instead
116
+ self.ticket_manager = None
117
+ self.enable_tickets = False
118
+
119
+ # Initialize response logger using configuration service
120
+ self.response_logger = self.configuration_service.initialize_response_logger(
121
+ self.config, self.project_logger
122
+ )
123
+
124
+ # Initialize hook service using configuration service
125
+ self.hook_service = self.configuration_service.register_hook_service(
126
+ container, self.config
127
+ )
128
+
129
+ # Initialize memory hook service using configuration service
130
+ self.memory_hook_service = (
131
+ self.configuration_service.register_memory_hook_service(
132
+ container, self.hook_service
133
+ )
134
+ )
135
+ if self.memory_hook_service:
136
+ self.memory_hook_service.register_memory_hooks()
137
+
138
+ # Initialize agent capabilities service using configuration service
139
+ self.agent_capabilities_service = (
140
+ self.configuration_service.register_agent_capabilities_service(container)
141
+ )
142
+
143
+ # Initialize system instructions service using configuration service
144
+ self.system_instructions_service = (
145
+ self.configuration_service.register_system_instructions_service(
146
+ container, self.agent_capabilities_service
147
+ )
148
+ )
149
+
150
+ # Initialize Socket.IO server reference first
151
+ self.websocket_server = None
152
+
153
+ # Initialize subprocess launcher service using configuration service
154
+ self.subprocess_launcher_service = (
155
+ self.configuration_service.register_subprocess_launcher_service(
156
+ container, self.project_logger, self.websocket_server
157
+ )
158
+ )
159
+
160
+ # Initialize version service using configuration service
161
+ self.version_service = self.configuration_service.register_version_service(
162
+ container
163
+ )
164
+
165
+ # Initialize command handler service using configuration service
166
+ self.command_handler_service = (
167
+ self.configuration_service.register_command_handler_service(
168
+ container, self.project_logger
169
+ )
170
+ )
171
+
172
+ # Initialize session management service using configuration service
173
+ # Note: This must be done after other services are initialized since it depends on the runner
174
+ self.session_management_service = (
175
+ self.configuration_service.register_session_management_service(
176
+ container, self
177
+ )
178
+ )
179
+
180
+ # Initialize utility service using configuration service
181
+ self.utility_service = self.configuration_service.register_utility_service(
182
+ container
183
+ )
184
+
185
+ # Load system instructions using the service
186
+ if self.system_instructions_service:
187
+ self.system_instructions = (
188
+ self.system_instructions_service.load_system_instructions()
189
+ )
190
+ else:
191
+ self.system_instructions = self._load_system_instructions()
192
+
193
+ # Deploy output style early (before Claude Code launches)
194
+ # This ensures the "Claude MPM" output style is active on startup
195
+ self._deploy_output_style()
196
+
197
+ # Create session log file using configuration service
198
+ self.session_log_file = self.configuration_service.create_session_log_file(
199
+ self.project_logger, self.log_level, config_data
200
+ )
201
+
202
+ # Log session start event if we have a session log file
203
+ if self.session_log_file:
204
+ self._log_session_event(
205
+ {
98
206
  "event": "session_start",
99
207
  "runner": "ClaudeRunner",
100
- "enable_tickets": enable_tickets,
101
- "log_level": log_level,
102
- "launch_method": launch_method
103
- })
104
- except Exception as e:
105
- self.logger.debug(f"Failed to create session log file: {e}")
106
-
107
- # Initialize Socket.IO server reference
108
- self.websocket_server = None
109
-
208
+ "enable_tickets": self.enable_tickets,
209
+ "log_level": self.log_level,
210
+ "launch_method": self.launch_method,
211
+ }
212
+ )
213
+
110
214
  def setup_agents(self) -> bool:
111
215
  """Deploy native agents to .claude/agents/."""
112
216
  try:
113
217
  if self.project_logger:
114
218
  self.project_logger.log_system(
115
- "Starting agent deployment",
116
- level="INFO",
117
- component="deployment"
219
+ "Starting agent deployment", level="INFO", component="deployment"
118
220
  )
119
-
221
+
120
222
  results = self.deployment_service.deploy_agents()
121
-
223
+
122
224
  if results["deployed"] or results.get("updated", []):
123
- deployed_count = len(results['deployed'])
124
- updated_count = len(results.get('updated', []))
125
-
225
+ deployed_count = len(results["deployed"])
226
+ updated_count = len(results.get("updated", []))
227
+
126
228
  if deployed_count > 0:
127
229
  print(f"✓ Deployed {deployed_count} native agents")
128
230
  if updated_count > 0:
129
231
  print(f"✓ Updated {updated_count} agents")
130
-
232
+
131
233
  if self.project_logger:
132
234
  self.project_logger.log_system(
133
235
  f"Agent deployment successful: {deployed_count} deployed, {updated_count} updated",
134
236
  level="INFO",
135
- component="deployment"
237
+ component="deployment",
136
238
  )
137
-
239
+
138
240
  # Set Claude environment
139
241
  self.deployment_service.set_claude_environment()
140
242
  return True
141
- else:
142
- self.logger.info("All agents already up to date")
143
- if self.project_logger:
144
- self.project_logger.log_system(
145
- "All agents already up to date",
146
- level="INFO",
147
- component="deployment"
148
- )
149
- return True
150
-
151
- except Exception as e:
152
- self.logger.error(f"Agent deployment failed: {e}")
153
- print(f"⚠️ Agent deployment failed: {e}")
243
+ self.logger.info("All agents already up to date")
154
244
  if self.project_logger:
155
245
  self.project_logger.log_system(
156
- f"Agent deployment failed: {e}",
157
- level="ERROR",
158
- component="deployment"
246
+ "All agents already up to date",
247
+ level="INFO",
248
+ component="deployment",
249
+ )
250
+ return True
251
+
252
+ except PermissionError as e:
253
+ error_msg = f"Permission denied deploying agents to .claude/agents/: {e}"
254
+ self.logger.error(error_msg)
255
+ print(f"❌ {error_msg}")
256
+ print(
257
+ "💡 Try running with appropriate permissions or check directory ownership"
258
+ )
259
+ if self.project_logger:
260
+ self.project_logger.log_system(
261
+ error_msg, level="ERROR", component="deployment"
159
262
  )
160
263
  return False
161
-
162
- def run_interactive(self, initial_context: Optional[str] = None):
163
- """Run Claude in interactive mode."""
164
- # Connect to Socket.IO server if enabled
165
- if self.enable_websocket:
166
- try:
167
- # Use Socket.IO client proxy to connect to monitoring server
168
- from claude_mpm.services.socketio_server import SocketIOClientProxy
169
- self.websocket_server = SocketIOClientProxy(port=self.websocket_port)
170
- self.websocket_server.start()
171
- self.logger.info("Connected to Socket.IO monitoring server")
172
-
173
- # Generate session ID
174
- session_id = str(uuid.uuid4())
175
- working_dir = os.getcwd()
176
-
177
- # Notify session start
178
- self.websocket_server.session_started(
179
- session_id=session_id,
180
- launch_method=self.launch_method,
181
- working_dir=working_dir
264
+
265
+ except FileNotFoundError as e:
266
+ error_msg = f"Agent files not found: {e}"
267
+ self.logger.error(error_msg)
268
+ print(f"❌ {error_msg}")
269
+ print("💡 Ensure claude-mpm is properly installed")
270
+ if self.project_logger:
271
+ self.project_logger.log_system(
272
+ error_msg, level="ERROR", component="deployment"
182
273
  )
183
- except Exception as e:
184
- self.logger.warning(f"Failed to connect to Socket.IO server: {e}")
185
- self.websocket_server = None
186
-
187
- # Get version with robust fallback mechanisms
188
- version_str = self._get_version()
189
-
190
- # Print styled welcome box
191
- print("\033[32m╭───────────────────────────────────────────────────╮\033[0m")
192
- print("\033[32m│\033[0m ✻ Claude MPM - Interactive Session \033[32m│\033[0m")
193
- print(f"\033[32m│\033[0m Version {version_str:<40}\033[32m│\033[0m")
194
- print("\033[32m│ │\033[0m")
195
- print("\033[32m│\033[0m Type '/agents' to see available agents \033[32m│\033[0m")
196
- print("\033[32m╰───────────────────────────────────────────────────╯\033[0m")
197
- print("") # Add blank line after box
198
-
199
- if self.project_logger:
200
- self.project_logger.log_system(
201
- "Starting interactive session",
202
- level="INFO",
203
- component="session"
204
- )
205
-
206
- # Setup agents
207
- if not self.setup_agents():
208
- print("Continuing without native agents...")
209
-
210
- # Build command with system instructions
211
- cmd = [
212
- "claude",
213
- "--model", "opus",
214
- "--dangerously-skip-permissions"
215
- ]
216
-
217
- # Add any custom Claude arguments
218
- if self.claude_args:
219
- cmd.extend(self.claude_args)
220
-
221
- # Add system instructions if available
222
- system_prompt = self._create_system_prompt()
223
- if system_prompt and system_prompt != create_simple_context():
224
- cmd.extend(["--append-system-prompt", system_prompt])
225
-
226
- # Run interactive Claude directly
274
+ return False
275
+
276
+ except ImportError as e:
277
+ error_msg = f"Missing required module for agent deployment: {e}"
278
+ self.logger.error(error_msg)
279
+ print(f"⚠️ {error_msg}")
280
+ print("💡 Some agent features may be limited")
281
+ if self.project_logger:
282
+ self.project_logger.log_system(
283
+ error_msg, level="WARNING", component="deployment"
284
+ )
285
+ return False
286
+
287
+ except Exception as e:
288
+ error_msg = f"Unexpected error during agent deployment: {e}"
289
+ self.logger.error(error_msg)
290
+ print(f"⚠️ {error_msg}")
291
+ if self.project_logger:
292
+ self.project_logger.log_system(
293
+ error_msg, level="ERROR", component="deployment"
294
+ )
295
+ # Continue without agents rather than failing completely
296
+ return False
297
+
298
+ def ensure_project_agents(self) -> bool:
299
+ """Ensure system agents are available in the project directory.
300
+
301
+ Deploys system agents to project's .claude/agents/ directory
302
+ if they don't exist or are outdated. This ensures agents are
303
+ available for Claude Code to use. Project-specific JSON templates
304
+ should be placed in .claude-mpm/agents/.
305
+
306
+ Returns:
307
+ bool: True if agents are available, False on error
308
+ """
227
309
  try:
228
- # Use execvp to replace the current process with Claude
229
- # This should avoid any subprocess issues
230
-
231
- # Clean environment
232
- clean_env = os.environ.copy()
233
- claude_vars_to_remove = [
234
- 'CLAUDE_CODE_ENTRYPOINT', 'CLAUDECODE', 'CLAUDE_CONFIG_DIR',
235
- 'CLAUDE_MAX_PARALLEL_SUBAGENTS', 'CLAUDE_TIMEOUT'
236
- ]
237
- for var in claude_vars_to_remove:
238
- clean_env.pop(var, None)
239
-
240
- # Set the correct working directory for Claude Code
241
- # If CLAUDE_MPM_USER_PWD is set, use that as the working directory
242
- if 'CLAUDE_MPM_USER_PWD' in clean_env:
243
- user_pwd = clean_env['CLAUDE_MPM_USER_PWD']
244
- clean_env['CLAUDE_WORKSPACE'] = user_pwd
245
- # Also change to that directory before launching Claude
246
- try:
247
- os.chdir(user_pwd)
248
- self.logger.info(f"Changed working directory to: {user_pwd}")
249
- except Exception as e:
250
- self.logger.warning(f"Could not change to user directory {user_pwd}: {e}")
251
-
252
- print("Launching Claude...")
253
-
310
+ # Use the correct user directory, not the framework directory
311
+ if "CLAUDE_MPM_USER_PWD" in os.environ:
312
+ project_dir = Path(os.environ["CLAUDE_MPM_USER_PWD"])
313
+ else:
314
+ project_dir = Path.cwd()
315
+
316
+ project_agents_dir = project_dir / ".claude-mpm" / "agents"
317
+
318
+ # Create directory if it doesn't exist
319
+ project_agents_dir.mkdir(parents=True, exist_ok=True)
320
+
254
321
  if self.project_logger:
255
322
  self.project_logger.log_system(
256
- f"Launching Claude interactive mode with {self.launch_method}",
323
+ f"Ensuring agents are available in project: {project_agents_dir}",
257
324
  level="INFO",
258
- component="session"
325
+ component="deployment",
259
326
  )
260
- self._log_session_event({
261
- "event": "launching_claude_interactive",
262
- "command": " ".join(cmd),
263
- "method": self.launch_method
264
- })
265
-
266
- # Notify WebSocket clients
267
- if self.websocket_server:
268
- self.websocket_server.claude_status_changed(
269
- status="starting",
270
- message="Launching Claude interactive session"
327
+
328
+ # Deploy agents to project's .claude/agents directory (not .claude-mpm)
329
+ # This ensures all system agents are deployed regardless of version
330
+ # .claude-mpm/agents/ should only contain JSON source templates
331
+ # .claude/agents/ should contain the built MD files for Claude Code
332
+ results = self.deployment_service.deploy_agents(
333
+ target_dir=project_dir / ".claude",
334
+ force_rebuild=False,
335
+ deployment_mode="project",
336
+ )
337
+
338
+ if results["deployed"] or results.get("updated", []):
339
+ deployed_count = len(results["deployed"])
340
+ updated_count = len(results.get("updated", []))
341
+
342
+ if deployed_count > 0:
343
+ self.logger.info(f"Deployed {deployed_count} agents to project")
344
+ if updated_count > 0:
345
+ self.logger.info(f"Updated {updated_count} agents in project")
346
+
347
+ return True
348
+ if results.get("skipped", []):
349
+ # Agents already exist and are current
350
+ self.logger.debug(
351
+ f"Project agents up to date: {len(results['skipped'])} agents"
271
352
  )
272
-
273
- # Launch using selected method
274
- if self.launch_method == "subprocess":
275
- self._launch_subprocess_interactive(cmd, clean_env)
276
- else:
277
- # Default to exec for backward compatibility
278
- if self.websocket_server:
279
- # Notify before exec (we won't be able to after)
280
- self.websocket_server.claude_status_changed(
281
- status="running",
282
- message="Claude process started (exec mode)"
283
- )
284
- os.execvpe(cmd[0], cmd, clean_env)
285
-
353
+ return True
354
+ self.logger.warning("No agents deployed to project")
355
+ return False
356
+
286
357
  except Exception as e:
287
- print(f"Failed to launch Claude: {e}")
358
+ self.logger.error(f"Failed to ensure project agents: {e}")
288
359
  if self.project_logger:
289
360
  self.project_logger.log_system(
290
- f"Failed to launch Claude: {e}",
361
+ f"Failed to ensure project agents: {e}",
291
362
  level="ERROR",
292
- component="session"
293
- )
294
- self._log_session_event({
295
- "event": "interactive_launch_failed",
296
- "error": str(e),
297
- "exception_type": type(e).__name__
298
- })
299
-
300
- # Notify WebSocket clients of error
301
- if self.websocket_server:
302
- self.websocket_server.claude_status_changed(
303
- status="error",
304
- message=f"Failed to launch Claude: {e}"
363
+ component="deployment",
305
364
  )
306
- # Fallback to subprocess
307
- try:
308
- # Use the same clean_env we prepared earlier
309
- subprocess.run(cmd, stdin=None, stdout=None, stderr=None, env=clean_env)
310
- if self.project_logger:
311
- self.project_logger.log_system(
312
- "Interactive session completed (subprocess fallback)",
313
- level="INFO",
314
- component="session"
315
- )
316
- self._log_session_event({
317
- "event": "interactive_session_complete",
318
- "fallback": True
319
- })
320
- except Exception as fallback_error:
321
- print(f"Fallback also failed: {fallback_error}")
322
- if self.project_logger:
323
- self.project_logger.log_system(
324
- f"Fallback launch failed: {fallback_error}",
325
- level="ERROR",
326
- component="session"
327
- )
328
- self._log_session_event({
329
- "event": "interactive_fallback_failed",
330
- "error": str(fallback_error),
331
- "exception_type": type(fallback_error).__name__
332
- })
333
-
334
- def run_oneshot(self, prompt: str, context: Optional[str] = None) -> bool:
335
- """Run Claude with a single prompt and return success status."""
336
- start_time = time.time()
337
-
338
- # Connect to Socket.IO server if enabled
339
- if self.enable_websocket:
340
- try:
341
- # Use Socket.IO client proxy to connect to monitoring server
342
- from claude_mpm.services.socketio_server import SocketIOClientProxy
343
- self.websocket_server = SocketIOClientProxy(port=self.websocket_port)
344
- self.websocket_server.start()
345
- self.logger.info("Connected to Socket.IO monitoring server")
346
-
347
- # Generate session ID
348
- session_id = str(uuid.uuid4())
349
- working_dir = os.getcwd()
350
-
351
- # Notify session start
352
- self.websocket_server.session_started(
353
- session_id=session_id,
354
- launch_method="oneshot",
355
- working_dir=working_dir
356
- )
357
- except Exception as e:
358
- self.logger.warning(f"Failed to connect to Socket.IO server: {e}")
359
- self.websocket_server = None
360
-
361
- # Check for /mpm: commands
362
- if prompt.strip().startswith("/mpm:"):
363
- return self._handle_mpm_command(prompt.strip())
364
-
365
- if self.project_logger:
366
- self.project_logger.log_system(
367
- f"Starting non-interactive session with prompt: {prompt[:100]}",
368
- level="INFO",
369
- component="session"
370
- )
371
-
372
- # Setup agents
373
- if not self.setup_agents():
374
- print("Continuing without native agents...")
375
-
376
- # Combine context and prompt
377
- full_prompt = prompt
378
- if context:
379
- full_prompt = f"{context}\n\n{prompt}"
380
-
381
- # Build command with system instructions
382
- cmd = [
383
- "claude",
384
- "--model", "opus",
385
- "--dangerously-skip-permissions"
386
- ]
387
-
388
- # Add any custom Claude arguments
389
- if self.claude_args:
390
- cmd.extend(self.claude_args)
391
-
392
- # Add print and prompt
393
- cmd.extend(["--print", full_prompt])
394
-
395
- # Add system instructions if available
396
- system_prompt = self._create_system_prompt()
397
- if system_prompt and system_prompt != create_simple_context():
398
- # Insert system prompt before the user prompt
399
- cmd.insert(-2, "--append-system-prompt")
400
- cmd.insert(-2, system_prompt)
401
-
365
+ return False
366
+
367
+ def deploy_project_agents_to_claude(self) -> bool:
368
+ """Deploy project agents from .claude-mpm/agents/ to .claude/agents/.
369
+
370
+ This method handles the deployment of project-specific agents (JSON format)
371
+ from the project's agents directory to Claude's agent directory.
372
+ Project agents take precedence over system agents.
373
+
374
+ WHY: Project agents allow teams to define custom, project-specific agents
375
+ that override system agents. These are stored in JSON format in
376
+ .claude-mpm/agents/ and need to be deployed to .claude/agents/
377
+ as MD files for Claude to use them.
378
+
379
+ Returns:
380
+ bool: True if deployment successful or no agents to deploy, False on error
381
+ """
402
382
  try:
403
- # Set up environment with correct working directory
404
- env = os.environ.copy()
405
-
406
- # Set the correct working directory for Claude Code
407
- if 'CLAUDE_MPM_USER_PWD' in env:
408
- user_pwd = env['CLAUDE_MPM_USER_PWD']
409
- env['CLAUDE_WORKSPACE'] = user_pwd
410
- # Change to that directory before running Claude
411
- try:
412
- original_cwd = os.getcwd()
413
- os.chdir(user_pwd)
414
- self.logger.info(f"Changed working directory to: {user_pwd}")
415
- except Exception as e:
416
- self.logger.warning(f"Could not change to user directory {user_pwd}: {e}")
417
- original_cwd = None
383
+ # Use the correct user directory, not the framework directory
384
+ if "CLAUDE_MPM_USER_PWD" in os.environ:
385
+ project_dir = Path(os.environ["CLAUDE_MPM_USER_PWD"])
418
386
  else:
419
- original_cwd = None
420
-
421
- # Run Claude
387
+ project_dir = Path.cwd()
388
+
389
+ project_agents_dir = project_dir / ".claude-mpm" / "agents"
390
+ claude_agents_dir = project_dir / ".claude" / "agents"
391
+
392
+ # Check if project agents directory exists
393
+ if not project_agents_dir.exists():
394
+ self.logger.debug("No project agents directory found")
395
+ return True # Not an error - just no project agents
396
+
397
+ # Get JSON agent files from agents directory
398
+ json_files = list(project_agents_dir.glob("*.json"))
399
+ if not json_files:
400
+ self.logger.debug("No JSON agents in project")
401
+ return True
402
+
403
+ # Create .claude/agents directory if needed
404
+ claude_agents_dir.mkdir(parents=True, exist_ok=True)
405
+
406
+ self.logger.info(
407
+ f"Deploying {len(json_files)} project agents to .claude/agents/"
408
+ )
422
409
  if self.project_logger:
423
410
  self.project_logger.log_system(
424
- "Executing Claude subprocess",
411
+ f"Deploying project agents from {project_agents_dir} to {claude_agents_dir}",
425
412
  level="INFO",
426
- component="session"
427
- )
428
-
429
- # Notify WebSocket clients
430
- if self.websocket_server:
431
- self.websocket_server.claude_status_changed(
432
- status="running",
433
- message="Executing Claude oneshot command"
413
+ component="deployment",
434
414
  )
435
-
436
- result = subprocess.run(cmd, capture_output=True, text=True, env=env)
437
-
438
- # Restore original directory if we changed it
439
- if original_cwd:
415
+
416
+ deployed_count = 0
417
+ updated_count = 0
418
+ errors = []
419
+
420
+ # Deploy each JSON agent
421
+ # CRITICAL: PM (Project Manager) must NEVER be deployed as it's the main Claude instance
422
+ EXCLUDED_AGENTS = {"pm", "project_manager"}
423
+
424
+ # Initialize deployment service with proper base agent path
425
+ # Use the existing deployment service's base agent path if available
426
+ base_agent_path = project_agents_dir / "base_agent.json"
427
+ if not base_agent_path.exists():
428
+ # Fall back to system base agent
429
+ base_agent_path = self.deployment_service.base_agent_path
430
+
431
+ # Lazy import to avoid circular dependencies
432
+ from claude_mpm.services.agents.deployment import AgentDeploymentService
433
+
434
+ # Create a single deployment service instance for all agents
435
+ project_deployment = AgentDeploymentService(
436
+ templates_dir=project_agents_dir,
437
+ base_agent_path=base_agent_path,
438
+ working_directory=project_dir, # Pass the project directory
439
+ )
440
+
441
+ # Load base agent data once
442
+ base_agent_data = {}
443
+ if base_agent_path and base_agent_path.exists():
440
444
  try:
441
- os.chdir(original_cwd)
442
- except Exception:
443
- pass
444
- execution_time = time.time() - start_time
445
-
446
- if result.returncode == 0:
447
- response = result.stdout.strip()
448
- print(response)
449
-
450
- # Broadcast output to WebSocket clients
451
- if self.websocket_server and response:
452
- self.websocket_server.claude_output(response, "stdout")
453
-
454
- if self.project_logger:
455
- # Log successful completion
456
- self.project_logger.log_system(
457
- f"Non-interactive session completed successfully in {execution_time:.2f}s",
458
- level="INFO",
459
- component="session"
460
- )
461
-
462
- # Log session event
463
- self._log_session_event({
464
- "event": "session_complete",
465
- "success": True,
466
- "execution_time": execution_time,
467
- "response_length": len(response)
468
- })
469
-
470
- # Log agent invocation if we detect delegation patterns
471
- if self._contains_delegation(response):
472
- self.project_logger.log_system(
473
- "Detected potential agent delegation in response",
474
- level="INFO",
475
- component="delegation"
445
+ import json
446
+
447
+ base_agent_data = json.loads(base_agent_path.read_text())
448
+ except Exception as e:
449
+ self.logger.warning(f"Could not load base agent: {e}")
450
+
451
+ for json_file in json_files:
452
+ try:
453
+ agent_name = json_file.stem
454
+
455
+ # Skip PM agent - it's the main Claude instance, not a subagent
456
+ if agent_name.lower() in EXCLUDED_AGENTS:
457
+ self.logger.info(
458
+ f"Skipping {agent_name} (PM is the main Claude instance)"
476
459
  )
477
- self._log_session_event({
478
- "event": "delegation_detected",
479
- "prompt": prompt[:200],
480
- "indicators": [p for p in ["Task(", "subagent_type=", "engineer agent", "qa agent"]
481
- if p.lower() in response.lower()]
482
- })
483
-
484
- # Notify WebSocket clients about delegation
485
- if self.websocket_server:
486
- # Try to extract agent name
487
- agent_name = self._extract_agent_from_response(response)
488
- if agent_name:
489
- self.websocket_server.agent_delegated(
490
- agent=agent_name,
491
- task=prompt[:100],
492
- status="detected"
493
- )
494
-
495
- # Extract tickets if enabled
496
- if self.enable_tickets and self.ticket_manager and response:
497
- self._extract_tickets(response)
498
-
499
- return True
500
- else:
501
- error_msg = result.stderr or "Unknown error"
502
- print(f"Error: {error_msg}")
503
-
504
- # Broadcast error to WebSocket clients
505
- if self.websocket_server:
506
- self.websocket_server.claude_output(error_msg, "stderr")
507
- self.websocket_server.claude_status_changed(
508
- status="error",
509
- message=f"Command failed with code {result.returncode}"
510
- )
511
-
460
+ continue
461
+
462
+ target_file = claude_agents_dir / f"{agent_name}.md"
463
+
464
+ # Check if agent needs update
465
+ needs_update = True
466
+ if target_file.exists():
467
+ # Check if it's a project agent (has project marker)
468
+ existing_content = target_file.read_text()
469
+ if (
470
+ "author: claude-mpm-project" in existing_content
471
+ or "source: project" in existing_content
472
+ ) and target_file.stat().st_mtime >= json_file.stat().st_mtime:
473
+ needs_update = False
474
+ self.logger.debug(
475
+ f"Project agent {agent_name} is up to date"
476
+ )
477
+
478
+ if needs_update:
479
+ # Build the agent markdown using the pre-initialized service and base agent data
480
+ # Use template_builder service instead of removed _build_agent_markdown method
481
+ agent_content = (
482
+ project_deployment.template_builder.build_agent_markdown(
483
+ agent_name,
484
+ json_file,
485
+ base_agent_data,
486
+ source_info="project",
487
+ )
488
+ )
489
+
490
+ # Mark as project agent
491
+ agent_content = agent_content.replace(
492
+ "author: claude-mpm", "author: claude-mpm-project"
493
+ )
494
+
495
+ # Write the agent file
496
+ is_update = target_file.exists()
497
+ target_file.write_text(agent_content)
498
+
499
+ if is_update:
500
+ updated_count += 1
501
+ self.logger.info(f"Updated project agent: {agent_name}")
502
+ else:
503
+ deployed_count += 1
504
+ self.logger.info(f"Deployed project agent: {agent_name}")
505
+
506
+ except Exception as e:
507
+ error_msg = f"Failed to deploy project agent {json_file.name}: {e}"
508
+ self.logger.error(error_msg)
509
+ errors.append(error_msg)
510
+
511
+ # Report results
512
+ if deployed_count > 0 or updated_count > 0:
513
+ print(
514
+ f"✓ Deployed {deployed_count} project agents, updated {updated_count}"
515
+ )
512
516
  if self.project_logger:
513
517
  self.project_logger.log_system(
514
- f"Non-interactive session failed: {error_msg}",
515
- level="ERROR",
516
- component="session"
518
+ f"Project agent deployment: {deployed_count} deployed, {updated_count} updated",
519
+ level="INFO",
520
+ component="deployment",
517
521
  )
518
- self._log_session_event({
519
- "event": "session_failed",
520
- "success": False,
521
- "error": error_msg,
522
- "return_code": result.returncode
523
- })
524
-
522
+
523
+ if errors:
524
+ for error in errors:
525
+ print(f"⚠️ {error}")
525
526
  return False
526
-
527
+
528
+ return True
529
+
527
530
  except Exception as e:
528
- print(f"Error: {e}")
529
-
531
+ error_msg = f"Failed to deploy project agents: {e}"
532
+ self.logger.error(error_msg)
533
+ print(f"⚠️ {error_msg}")
530
534
  if self.project_logger:
531
535
  self.project_logger.log_system(
532
- f"Exception during non-interactive session: {e}",
533
- level="ERROR",
534
- component="session"
536
+ error_msg, level="ERROR", component="deployment"
535
537
  )
536
- self._log_session_event({
537
- "event": "session_exception",
538
- "success": False,
539
- "exception": str(e),
540
- "exception_type": type(e).__name__
541
- })
542
-
543
538
  return False
544
- finally:
545
- # Ensure logs are flushed
546
- if self.project_logger:
547
- try:
548
- # Log session summary
549
- summary = self.project_logger.get_session_summary()
550
- self.project_logger.log_system(
551
- f"Session {summary['session_id']} completed",
552
- level="INFO",
553
- component="session"
554
- )
555
- except Exception as e:
556
- self.logger.debug(f"Failed to log session summary: {e}")
557
-
558
- # End WebSocket session
559
- if self.websocket_server:
560
- self.websocket_server.claude_status_changed(
561
- status="stopped",
562
- message="Session completed"
563
- )
564
- self.websocket_server.session_ended()
565
-
539
+
540
+ def run_interactive(self, initial_context: Optional[str] = None):
541
+ """Run Claude in interactive mode using the session management service.
542
+
543
+ Delegates to the SessionManagementService for session orchestration.
544
+
545
+ Args:
546
+ initial_context: Optional initial context to pass to Claude
547
+ """
548
+ if self.session_management_service:
549
+ self.session_management_service.run_interactive_session(initial_context)
550
+ else:
551
+ self.logger.error("Session management service not available")
552
+ print("Error: Session management service not available")
553
+
554
+ def run_oneshot(self, prompt: str, context: Optional[str] = None) -> bool:
555
+ """Run Claude with a single prompt using the session management service.
556
+
557
+ Delegates to the SessionManagementService for session orchestration.
558
+
559
+ Args:
560
+ prompt: The command or prompt to execute
561
+ context: Optional context to prepend to the prompt
562
+
563
+ Returns:
564
+ bool: True if successful, False otherwise
565
+ """
566
+ if self.session_management_service:
567
+ return self.session_management_service.run_oneshot_session(prompt, context)
568
+ self.logger.error("Session management service not available")
569
+ print("Error: Session management service not available")
570
+ return False
571
+
566
572
  def _extract_tickets(self, text: str):
567
- """Extract tickets from Claude's response."""
568
- if not self.ticket_manager:
569
- return
570
-
571
- try:
572
- # Use the ticket manager's extraction logic if available
573
- if hasattr(self.ticket_manager, 'extract_tickets_from_text'):
574
- tickets = self.ticket_manager.extract_tickets_from_text(text)
575
- if tickets:
576
- print(f"\n📋 Extracted {len(tickets)} tickets")
577
- for ticket in tickets[:3]: # Show first 3
578
- print(f" - [{ticket.get('id', 'N/A')}] {ticket.get('title', 'No title')}")
579
- if len(tickets) > 3:
580
- print(f" ... and {len(tickets) - 3} more")
581
- else:
582
- self.logger.debug("Ticket extraction method not available")
583
- except Exception as e:
584
- self.logger.debug(f"Ticket extraction failed: {e}")
573
+ """Extract tickets from Claude's response (disabled - use claude-mpm tickets CLI)."""
574
+ # Ticket extraction disabled - users should use claude-mpm tickets CLI commands
585
575
 
586
576
  def _load_system_instructions(self) -> Optional[str]:
587
- """Load and process system instructions from agents/INSTRUCTIONS.md.
588
-
589
- WHY: Process template variables like {{capabilities-list}} to include
590
- dynamic agent capabilities in the PM's system instructions.
577
+ """Load and process system instructions.
578
+
579
+ Delegates to the SystemInstructionsService for loading and processing.
591
580
  """
592
- try:
593
- # Find the INSTRUCTIONS.md file
594
- module_path = Path(__file__).parent.parent
595
- instructions_path = module_path / "agents" / "INSTRUCTIONS.md"
596
-
597
- if not instructions_path.exists():
598
- self.logger.warning(f"System instructions not found: {instructions_path}")
599
- return None
600
-
601
- # Read raw instructions
602
- raw_instructions = instructions_path.read_text()
603
-
604
- # Process template variables if ContentAssembler is available
605
- try:
606
- from claude_mpm.services.framework_claude_md_generator.content_assembler import ContentAssembler
607
- assembler = ContentAssembler()
608
- processed_instructions = assembler.apply_template_variables(raw_instructions)
609
- self.logger.info("Loaded and processed PM framework system instructions with dynamic capabilities")
610
- return processed_instructions
611
- except ImportError:
612
- self.logger.warning("ContentAssembler not available, using raw instructions")
613
- return raw_instructions
614
- except Exception as e:
615
- self.logger.warning(f"Failed to process template variables: {e}, using raw instructions")
616
- return raw_instructions
617
-
618
- except Exception as e:
619
- self.logger.error(f"Failed to load system instructions: {e}")
620
- return None
581
+ if self.system_instructions_service:
582
+ return self.system_instructions_service.load_system_instructions()
583
+ # Fallback if service is not available
584
+ self.logger.warning(
585
+ "System instructions service not available, using basic fallback"
586
+ )
587
+ return None
588
+
589
+ def _process_base_pm_content(self, base_pm_content: str) -> str:
590
+ """Process BASE_PM.md content with dynamic injections.
591
+
592
+ Delegates to the SystemInstructionsService for processing.
593
+ """
594
+ if self.system_instructions_service:
595
+ return self.system_instructions_service.process_base_pm_content(
596
+ base_pm_content
597
+ )
598
+ # Fallback if service is not available
599
+ self.logger.warning(
600
+ "System instructions service not available for BASE_PM processing"
601
+ )
602
+ return base_pm_content
603
+
604
+ def _strip_metadata_comments(self, content: str) -> str:
605
+ """Strip HTML metadata comments from content.
606
+
607
+ Delegates to the SystemInstructionsService for processing.
608
+ """
609
+ if self.system_instructions_service:
610
+ return self.system_instructions_service.strip_metadata_comments(content)
611
+ # Fallback if service is not available
612
+ self.logger.warning(
613
+ "System instructions service not available for metadata stripping"
614
+ )
615
+ return content
616
+
617
+ def _generate_deployed_agent_capabilities(self) -> str:
618
+ """Generate agent capabilities from deployed agents.
619
+
620
+ Delegates to the AgentCapabilitiesService for agent discovery and formatting.
621
+ """
622
+ if self.agent_capabilities_service:
623
+ return (
624
+ self.agent_capabilities_service.generate_deployed_agent_capabilities()
625
+ )
626
+ # Fallback if service is not available
627
+ self.logger.warning("Agent capabilities service not available, using fallback")
628
+ return self._get_fallback_capabilities()
629
+
630
+ def _get_fallback_capabilities(self) -> str:
631
+ """Return fallback agent capabilities when deployed agents can't be read."""
632
+ # Delegate to the service if available, otherwise use basic fallback
633
+ if self.agent_capabilities_service:
634
+ return self.agent_capabilities_service._get_fallback_capabilities()
635
+ return """
636
+ ## Available Agent Capabilities
637
+
638
+ You have the following specialized agents available for delegation:
639
+
640
+ - **Engineer Agent**: Code implementation and development
641
+ - **Research Agent**: Investigation and analysis
642
+ - **QA Agent**: Testing and quality assurance
643
+ - **Documentation Agent**: Documentation creation and maintenance
644
+
645
+ Use these agents to delegate specialized work via the Task tool.
646
+ """
621
647
 
622
648
  def _create_system_prompt(self) -> str:
623
- """Create the complete system prompt including instructions."""
649
+ """Create the complete system prompt including instructions.
650
+
651
+ Delegates to the SystemInstructionsService for prompt creation.
652
+ """
653
+ if self.system_instructions_service:
654
+ return self.system_instructions_service.create_system_prompt(
655
+ self.system_instructions
656
+ )
657
+ # Fallback if service is not available
624
658
  if self.system_instructions:
625
659
  return self.system_instructions
626
- else:
627
- # Fallback to basic context
628
- return create_simple_context()
629
-
660
+ return create_simple_context()
661
+
630
662
  def _contains_delegation(self, text: str) -> bool:
631
- """Check if text contains signs of agent delegation."""
632
- # Look for common delegation patterns
633
- delegation_patterns = [
634
- "Task(",
635
- "subagent_type=",
636
- "delegating to",
637
- "asking the",
638
- "engineer agent",
639
- "qa agent",
640
- "documentation agent",
641
- "research agent",
642
- "security agent",
643
- "ops agent",
644
- "version_control agent",
645
- "data_engineer agent"
646
- ]
647
-
648
- text_lower = text.lower()
649
- return any(pattern.lower() in text_lower for pattern in delegation_patterns)
650
-
663
+ """Check if text contains signs of agent delegation using the utility service."""
664
+ if self.utility_service:
665
+ return self.utility_service.contains_delegation(text)
666
+ # Fallback if service not available
667
+ return False
668
+
651
669
  def _extract_agent_from_response(self, text: str) -> Optional[str]:
652
- """Try to extract agent name from delegation response."""
653
- # Look for common patterns
654
- import re
655
-
656
- # Pattern 1: subagent_type="agent_name"
657
- match = re.search(r'subagent_type=["\']([^"\']*)["\'\)]', text)
658
- if match:
659
- return match.group(1)
660
-
661
- # Pattern 2: "engineer agent" etc
662
- agent_names = [
663
- "engineer", "qa", "documentation", "research",
664
- "security", "ops", "version_control", "data_engineer"
665
- ]
666
- text_lower = text.lower()
667
- for agent in agent_names:
668
- if f"{agent} agent" in text_lower or f"agent: {agent}" in text_lower:
669
- return agent
670
-
670
+ """Try to extract agent name from delegation response using the utility service."""
671
+ if self.utility_service:
672
+ return self.utility_service.extract_agent_from_response(text)
673
+ # Fallback if service not available
671
674
  return None
672
-
675
+
673
676
  def _handle_mpm_command(self, prompt: str) -> bool:
674
- """Handle /mpm: commands directly without going to Claude."""
675
- try:
676
- # Extract command and arguments
677
- command_line = prompt[5:].strip() # Remove "/mpm:"
678
- parts = command_line.split()
679
-
680
- if not parts:
681
- print("No command specified. Available commands: test")
682
- return True
683
-
684
- command = parts[0]
685
- args = parts[1:]
686
-
687
- # Handle commands
688
- if command == "test":
689
- print("Hello World")
690
- if self.project_logger:
691
- self.project_logger.log_system(
692
- "Executed /mpm:test command",
693
- level="INFO",
694
- component="command"
695
- )
696
- return True
697
- elif command == "agents":
698
- # Handle agents command - display deployed agent versions
699
- # WHY: This provides users with a quick way to check deployed agent versions
700
- # directly from within Claude Code, maintaining consistency with CLI behavior
701
- try:
702
- from claude_mpm.cli import _get_agent_versions_display
703
- agent_versions = _get_agent_versions_display()
704
- if agent_versions:
705
- print(agent_versions)
706
- else:
707
- print("No deployed agents found")
708
- print("\nTo deploy agents, run: claude-mpm --mpm:agents deploy")
709
-
710
- if self.project_logger:
711
- self.project_logger.log_system(
712
- "Executed /mpm:agents command",
713
- level="INFO",
714
- component="command"
715
- )
716
- return True
717
- except Exception as e:
718
- print(f"Error getting agent versions: {e}")
719
- return False
720
- else:
721
- print(f"Unknown command: {command}")
722
- print("Available commands: test, agents")
723
- return True
724
-
725
- except Exception as e:
726
- print(f"Error executing command: {e}")
727
- if self.project_logger:
728
- self.project_logger.log_system(
729
- f"Failed to execute /mpm: command: {e}",
730
- level="ERROR",
731
- component="command"
732
- )
733
- return False
734
-
677
+ """Handle /mpm: commands using the command handler service.
678
+
679
+ Delegates to the CommandHandlerService for command processing.
680
+ """
681
+ if self.command_handler_service:
682
+ return self.command_handler_service.handle_mpm_command(prompt)
683
+ # Fallback if service not available
684
+ print("Command handler service not available")
685
+ return False
686
+
735
687
  def _log_session_event(self, event_data: dict):
736
- """Log an event to the session log file."""
737
- if self.session_log_file:
738
- try:
739
- log_entry = {
740
- "timestamp": datetime.now().isoformat(),
741
- **event_data
742
- }
743
-
744
- with open(self.session_log_file, 'a') as f:
745
- f.write(json.dumps(log_entry) + '\n')
746
- except Exception as e:
747
- self.logger.debug(f"Failed to log session event: {e}")
748
-
688
+ """Log an event to the session log file using the utility service."""
689
+ if self.utility_service:
690
+ self.utility_service.log_session_event(self.session_log_file, event_data)
691
+ else:
692
+ # Fallback if service not available
693
+ self.logger.debug("Utility service not available for session logging")
694
+
749
695
  def _get_version(self) -> str:
696
+ """Get version string using the version service.
697
+
698
+ Delegates to the VersionService for version detection and formatting.
750
699
  """
751
- Robust version determination with multiple fallback mechanisms.
752
-
753
- WHY: The version display is critical for debugging and user experience.
754
- This implementation ensures we always show the correct version rather than
755
- defaulting to v0.0.0, even in edge cases where imports might fail.
756
-
757
- DESIGN DECISION: We try multiple methods in order of preference:
758
- 1. Package import (__version__) - fastest for normal installations
759
- 2. importlib.metadata - standard for installed packages
760
- 3. VERSION file reading - fallback for development environments
761
- 4. Only then default to v0.0.0 with detailed error logging
762
-
763
- Returns version string formatted as "vX.Y.Z"
764
- """
765
- version = "0.0.0"
766
- method_used = "default"
767
-
768
- # Method 1: Try package import (fastest, most common)
769
- try:
770
- from claude_mpm import __version__
771
- version = __version__
772
- method_used = "package_import"
773
- self.logger.debug(f"Version obtained via package import: {version}")
774
- except ImportError as e:
775
- self.logger.debug(f"Package import failed: {e}")
776
- except Exception as e:
777
- self.logger.warning(f"Unexpected error in package import: {e}")
778
-
779
- # Method 2: Try importlib.metadata (standard for installed packages)
780
- if version == "0.0.0":
781
- try:
782
- import importlib.metadata
783
- version = importlib.metadata.version('claude-mpm')
784
- method_used = "importlib_metadata"
785
- self.logger.debug(f"Version obtained via importlib.metadata: {version}")
786
- except importlib.metadata.PackageNotFoundError:
787
- self.logger.debug("Package not found in importlib.metadata (likely development install)")
788
- except ImportError:
789
- self.logger.debug("importlib.metadata not available (Python < 3.8)")
790
- except Exception as e:
791
- self.logger.warning(f"Unexpected error in importlib.metadata: {e}")
792
-
793
- # Method 3: Try reading VERSION file directly (development fallback)
794
- if version == "0.0.0":
795
- try:
796
- # Calculate path relative to this file
797
- version_file = Path(__file__).parent.parent.parent.parent / "VERSION"
798
- if version_file.exists():
799
- version = version_file.read_text().strip()
800
- method_used = "version_file"
801
- self.logger.debug(f"Version obtained via VERSION file: {version}")
802
- else:
803
- self.logger.debug(f"VERSION file not found at: {version_file}")
804
- except Exception as e:
805
- self.logger.warning(f"Failed to read VERSION file: {e}")
806
-
807
- # Log final result
808
- if version == "0.0.0":
809
- self.logger.error(
810
- "All version detection methods failed. This indicates a packaging or installation issue."
811
- )
812
- else:
813
- self.logger.debug(f"Final version: {version} (method: {method_used})")
814
-
815
- return f"v{version}"
816
-
817
- def _register_memory_hooks(self):
818
- """Register memory integration hooks with the hook service.
819
-
820
- WHY: This activates the memory system by registering hooks that automatically
821
- inject agent memory before delegation and extract learnings after delegation.
822
- This is the critical connection point between the memory system and the CLI.
823
-
824
- DESIGN DECISION: We register hooks here instead of in __init__ to ensure
825
- all services are initialized first. Hooks are only registered if the memory
826
- system is enabled in configuration.
700
+ if self.version_service:
701
+ return self.version_service.get_version()
702
+ # Fallback if service not available
703
+ return "v0.0.0"
704
+
705
+ def _deploy_output_style(self) -> None:
706
+ """Deploy the Claude MPM output style before Claude Code launches.
707
+
708
+ This method ensures the output style is set to "Claude MPM" on startup
709
+ by deploying the style file and updating Claude Code settings.
710
+ Only works for Claude Code >= 1.0.83.
827
711
  """
828
712
  try:
829
- # Only register if memory system is enabled
830
- if not self.config.get('memory.enabled', True):
831
- self.logger.debug("Memory system disabled - skipping hook registration")
713
+ from claude_mpm.core.output_style_manager import OutputStyleManager
714
+
715
+ # Create OutputStyleManager instance
716
+ output_style_manager = OutputStyleManager()
717
+
718
+ # Check if Claude Code supports output styles
719
+ if not output_style_manager.supports_output_styles():
720
+ self.logger.debug(
721
+ f"Claude Code version {output_style_manager.claude_version or 'unknown'} "
722
+ "does not support output styles (requires >= 1.0.83)"
723
+ )
832
724
  return
833
-
834
- # Import hook classes (lazy import to avoid circular dependencies)
835
- from claude_mpm.hooks.memory_integration_hook import (
836
- MemoryPreDelegationHook,
837
- MemoryPostDelegationHook
725
+
726
+ # Check if output style is already deployed and active
727
+ settings_file = Path.home() / ".claude" / "settings.json"
728
+ if settings_file.exists():
729
+ try:
730
+ import json
731
+
732
+ settings = json.loads(settings_file.read_text())
733
+ if settings.get("activeOutputStyle") == "claude-mpm":
734
+ # Already active, check if file exists
735
+ output_style_file = (
736
+ Path.home() / ".claude" / "output-styles" / "claude-mpm.md"
737
+ )
738
+ if output_style_file.exists():
739
+ self.logger.debug(
740
+ "Output style 'Claude MPM' already deployed and active"
741
+ )
742
+ return
743
+ except Exception:
744
+ pass # Continue with deployment if we can't read settings
745
+
746
+ # Read the OUTPUT_STYLE.md content if it exists
747
+ output_style_path = (
748
+ Path(__file__).parent.parent / "agents" / "OUTPUT_STYLE.md"
838
749
  )
839
-
840
- # Register pre-delegation hook for memory injection
841
- pre_hook = MemoryPreDelegationHook(self.config)
842
- success = self.hook_service.register_hook(pre_hook)
843
- if success:
844
- self.logger.info(f"✅ Registered memory pre-delegation hook (priority: {pre_hook.priority})")
845
- else:
846
- self.logger.warning("❌ Failed to register memory pre-delegation hook")
847
-
848
- # Register post-delegation hook if auto-learning is enabled
849
- if self.config.get('memory.auto_learning', True): # Default to True now
850
- post_hook = MemoryPostDelegationHook(self.config)
851
- success = self.hook_service.register_hook(post_hook)
852
- if success:
853
- self.logger.info(f"✅ Registered memory post-delegation hook (priority: {post_hook.priority})")
854
- else:
855
- self.logger.warning("❌ Failed to register memory post-delegation hook")
750
+
751
+ if output_style_path.exists():
752
+ # Use existing OUTPUT_STYLE.md content
753
+ output_style_content = output_style_path.read_text()
754
+ self.logger.debug("Using existing OUTPUT_STYLE.md content")
856
755
  else:
857
- self.logger.info("ℹ️ Auto-learning disabled - skipping post-delegation hook")
858
-
859
- # Log summary of registered hooks
860
- hooks = self.hook_service.list_hooks()
861
- pre_count = len(hooks.get('pre_delegation', []))
862
- post_count = len(hooks.get('post_delegation', []))
863
- self.logger.info(f"📋 Hook Service initialized: {pre_count} pre-delegation, {post_count} post-delegation hooks")
864
-
865
- except Exception as e:
866
- self.logger.error(f"❌ Failed to register memory hooks: {e}")
867
- # Don't fail the entire initialization - memory system is optional
868
-
869
- def _launch_subprocess_interactive(self, cmd: list, env: dict):
870
- """Launch Claude as a subprocess with PTY for interactive mode."""
871
- import pty
872
- import select
873
- import termios
874
- import tty
875
- import signal
876
-
877
- # Save original terminal settings
878
- original_tty = None
879
- if sys.stdin.isatty():
880
- original_tty = termios.tcgetattr(sys.stdin)
881
-
882
- # Create PTY
883
- master_fd, slave_fd = pty.openpty()
884
-
885
- try:
886
- # Start Claude process
887
- process = subprocess.Popen(
888
- cmd,
889
- stdin=slave_fd,
890
- stdout=slave_fd,
891
- stderr=slave_fd,
892
- env=env
893
- )
894
-
895
- # Close slave in parent
896
- os.close(slave_fd)
897
-
898
- if self.project_logger:
899
- self.project_logger.log_system(
900
- f"Claude subprocess started with PID {process.pid}",
901
- level="INFO",
902
- component="subprocess"
756
+ # Extract output style content from framework instructions
757
+ output_style_content = (
758
+ output_style_manager.extract_output_style_content()
903
759
  )
904
-
905
- # Notify WebSocket clients
906
- if self.websocket_server:
907
- self.websocket_server.claude_status_changed(
908
- status="running",
909
- pid=process.pid,
910
- message="Claude subprocess started"
760
+ self.logger.debug("Extracted output style from framework instructions")
761
+
762
+ # Deploy the output style
763
+ deployed = output_style_manager.deploy_output_style(output_style_content)
764
+
765
+ if deployed:
766
+ self.logger.info(
767
+ "✅ Output style 'Claude MPM' deployed and activated on startup"
911
768
  )
912
-
913
- # Set terminal to raw mode for proper interaction
914
- if sys.stdin.isatty():
915
- tty.setraw(sys.stdin)
916
-
917
- # Handle Ctrl+C gracefully
918
- def signal_handler(signum, frame):
919
- if process.poll() is None:
920
- process.terminate()
921
- raise KeyboardInterrupt()
922
-
923
- signal.signal(signal.SIGINT, signal_handler)
924
-
925
- # I/O loop
926
- while True:
927
- # Check if process is still running
928
- if process.poll() is not None:
929
- break
930
-
931
- # Check for data from Claude or stdin
932
- r, _, _ = select.select([master_fd, sys.stdin], [], [], 0)
933
-
934
- if master_fd in r:
935
- try:
936
- data = os.read(master_fd, 4096)
937
- if data:
938
- os.write(sys.stdout.fileno(), data)
939
- # Broadcast output to WebSocket clients
940
- if self.websocket_server:
941
- try:
942
- # Decode and send
943
- output = data.decode('utf-8', errors='replace')
944
- self.websocket_server.claude_output(output, "stdout")
945
- except Exception as e:
946
- self.logger.debug(f"Failed to broadcast output: {e}")
947
- else:
948
- break # EOF
949
- except OSError:
950
- break
951
-
952
- if sys.stdin in r:
953
- try:
954
- data = os.read(sys.stdin.fileno(), 4096)
955
- if data:
956
- os.write(master_fd, data)
957
- except OSError:
958
- break
959
-
960
- # Wait for process to complete
961
- process.wait()
962
-
769
+ if self.project_logger:
770
+ self.project_logger.log_system(
771
+ "Output style 'Claude MPM' deployed and activated on startup",
772
+ level="INFO",
773
+ component="output_style",
774
+ )
775
+ else:
776
+ self.logger.warning("Failed to deploy output style")
777
+
778
+ except ImportError as e:
779
+ self.logger.warning(f"Could not import OutputStyleManager: {e}")
780
+ except Exception as e:
781
+ # Don't fail startup if output style deployment fails
782
+ self.logger.warning(f"Error deploying output style: {e}")
963
783
  if self.project_logger:
964
784
  self.project_logger.log_system(
965
- f"Claude subprocess exited with code {process.returncode}",
966
- level="INFO",
967
- component="subprocess"
968
- )
969
-
970
- # Notify WebSocket clients
971
- if self.websocket_server:
972
- self.websocket_server.claude_status_changed(
973
- status="stopped",
974
- message=f"Claude subprocess exited with code {process.returncode}"
785
+ f"Output style deployment error: {e}",
786
+ level="WARNING",
787
+ component="output_style",
975
788
  )
976
-
977
- finally:
978
- # Restore terminal
979
- if original_tty and sys.stdin.isatty():
980
- termios.tcsetattr(sys.stdin, termios.TCSADRAIN, original_tty)
981
-
982
- # Close PTY
983
- try:
984
- os.close(master_fd)
985
- except:
986
- pass
987
-
988
- # Ensure process is terminated
989
- if 'process' in locals() and process.poll() is None:
990
- process.terminate()
991
- try:
992
- process.wait(timeout=2)
993
- except subprocess.TimeoutExpired:
994
- process.kill()
995
- process.wait()
996
-
997
- # End WebSocket session if in subprocess mode
998
- if self.websocket_server:
999
- self.websocket_server.session_ended()
1000
-
1001
-
1002
- def create_simple_context() -> str:
1003
- """Create basic context for Claude."""
1004
- return """You are Claude Code running in Claude MPM (Multi-Agent Project Manager).
1005
-
1006
- You have access to native subagents via the Task tool with subagent_type parameter:
1007
- - engineer: For coding, implementation, and technical tasks
1008
- - qa: For testing, validation, and quality assurance
1009
- - documentation: For docs, guides, and explanations
1010
- - research: For investigation and analysis
1011
- - security: For security-related tasks
1012
- - ops: For deployment and infrastructure
1013
- - version-control: For git and version management
1014
- - data-engineer: For data processing and APIs
1015
-
1016
- Use these agents by calling: Task(description="task description", subagent_type="agent_name")
1017
789
 
1018
- IMPORTANT: The Task tool accepts both naming formats:
1019
- - Capitalized format: "Research", "Engineer", "QA", "Version Control", "Data Engineer"
1020
- - Lowercase format: "research", "engineer", "qa", "version-control", "data-engineer"
790
+ def _launch_subprocess_interactive(self, cmd: list, env: dict):
791
+ """Launch Claude as a subprocess with PTY for interactive mode.
1021
792
 
1022
- Both formats work correctly. When you see capitalized names (matching TodoWrite prefixes),
1023
- automatically normalize them to lowercase-hyphenated format for the Task tool.
793
+ Delegates to the SubprocessLauncherService for subprocess management.
794
+ """
795
+ if self.subprocess_launcher_service:
796
+ self.subprocess_launcher_service.launch_subprocess_interactive(cmd, env)
797
+ else:
798
+ # Fallback if service is not available
799
+ self.logger.warning(
800
+ "Subprocess launcher service not available, cannot launch subprocess"
801
+ )
802
+ raise RuntimeError("Subprocess launcher service not available")
1024
803
 
1025
- Work efficiently and delegate appropriately to subagents when needed."""
1026
804
 
805
+ # Moved to claude_mpm.core.system_context to avoid circular imports
806
+ from claude_mpm.core.system_context import create_simple_context
1027
807
 
1028
808
  # Backward compatibility alias
1029
809
  SimpleClaudeRunner = ClaudeRunner
@@ -1043,4 +823,4 @@ def run_claude_oneshot(prompt: str, context: Optional[str] = None) -> bool:
1043
823
  runner = ClaudeRunner()
1044
824
  if context is None:
1045
825
  context = create_simple_context()
1046
- return runner.run_oneshot(prompt, context)
826
+ return runner.run_oneshot(prompt, context)