claude-mpm 4.1.26__py3-none-any.whl → 4.24.0__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 (845) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/__init__.py +20 -5
  4. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +118 -0
  5. claude_mpm/agents/BASE_DOCUMENTATION.md +53 -0
  6. claude_mpm/agents/BASE_ENGINEER.md +658 -0
  7. claude_mpm/agents/BASE_OPS.md +219 -0
  8. claude_mpm/agents/BASE_PM.md +420 -158
  9. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +787 -0
  10. claude_mpm/agents/BASE_QA.md +167 -0
  11. claude_mpm/agents/BASE_RESEARCH.md +53 -0
  12. claude_mpm/agents/OUTPUT_STYLE.md +299 -29
  13. claude_mpm/agents/PM_INSTRUCTIONS.md +1159 -0
  14. claude_mpm/agents/WORKFLOW.md +355 -191
  15. claude_mpm/agents/agent_loader.py +40 -10
  16. claude_mpm/agents/agent_loader_integration.py +3 -2
  17. claude_mpm/agents/async_agent_loader.py +3 -3
  18. claude_mpm/agents/base_agent_loader.py +11 -9
  19. claude_mpm/agents/frontmatter_validator.py +291 -251
  20. claude_mpm/agents/system_agent_config.py +3 -2
  21. claude_mpm/agents/templates/README.md +465 -0
  22. claude_mpm/agents/templates/agent-manager.json +7 -4
  23. claude_mpm/agents/templates/{agentic_coder_optimizer.json → agentic-coder-optimizer.json} +33 -7
  24. claude_mpm/agents/templates/api_qa.json +16 -4
  25. claude_mpm/agents/templates/circuit_breakers.md +638 -0
  26. claude_mpm/agents/templates/clerk-ops.json +235 -0
  27. claude_mpm/agents/templates/code_analyzer.json +10 -4
  28. claude_mpm/agents/templates/content-agent.json +358 -0
  29. claude_mpm/agents/templates/dart_engineer.json +307 -0
  30. claude_mpm/agents/templates/data_engineer.json +87 -14
  31. claude_mpm/agents/templates/documentation.json +76 -13
  32. claude_mpm/agents/templates/engineer.json +43 -9
  33. claude_mpm/agents/templates/gcp_ops_agent.json +253 -0
  34. claude_mpm/agents/templates/git_file_tracking.md +584 -0
  35. claude_mpm/agents/templates/golang_engineer.json +270 -0
  36. claude_mpm/agents/templates/imagemagick.json +5 -2
  37. claude_mpm/agents/templates/java_engineer.json +346 -0
  38. claude_mpm/agents/templates/javascript_engineer_agent.json +380 -0
  39. claude_mpm/agents/templates/local_ops_agent.json +1840 -0
  40. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +400 -0
  41. claude_mpm/agents/templates/memory_manager.json +6 -3
  42. claude_mpm/agents/templates/nextjs_engineer.json +285 -0
  43. claude_mpm/agents/templates/ops.json +14 -4
  44. claude_mpm/agents/templates/php-engineer.json +287 -0
  45. claude_mpm/agents/templates/pm_examples.md +474 -0
  46. claude_mpm/agents/templates/pm_red_flags.md +262 -0
  47. claude_mpm/agents/templates/product_owner.json +338 -0
  48. claude_mpm/agents/templates/project_organizer.json +19 -5
  49. claude_mpm/agents/templates/prompt-engineer.json +737 -0
  50. claude_mpm/agents/templates/python_engineer.json +387 -0
  51. claude_mpm/agents/templates/qa.json +25 -5
  52. claude_mpm/agents/templates/react_engineer.json +239 -0
  53. claude_mpm/agents/templates/refactoring_engineer.json +15 -5
  54. claude_mpm/agents/templates/research.json +46 -21
  55. claude_mpm/agents/templates/response_format.md +583 -0
  56. claude_mpm/agents/templates/ruby-engineer.json +280 -0
  57. claude_mpm/agents/templates/rust_engineer.json +275 -0
  58. claude_mpm/agents/templates/security.json +59 -10
  59. claude_mpm/agents/templates/svelte-engineer.json +225 -0
  60. claude_mpm/agents/templates/tauri_engineer.json +274 -0
  61. claude_mpm/agents/templates/ticketing.json +16 -7
  62. claude_mpm/agents/templates/typescript_engineer.json +285 -0
  63. claude_mpm/agents/templates/validation_templates.md +312 -0
  64. claude_mpm/agents/templates/vercel_ops_agent.json +164 -33
  65. claude_mpm/agents/templates/version_control.json +16 -4
  66. claude_mpm/agents/templates/web_qa.json +167 -21
  67. claude_mpm/agents/templates/web_ui.json +18 -5
  68. claude_mpm/cli/__init__.py +38 -378
  69. claude_mpm/cli/commands/__init__.py +2 -0
  70. claude_mpm/cli/commands/agent_manager.py +675 -20
  71. claude_mpm/cli/commands/agent_state_manager.py +186 -0
  72. claude_mpm/cli/commands/agents.py +722 -150
  73. claude_mpm/cli/commands/agents_detect.py +380 -0
  74. claude_mpm/cli/commands/agents_recommend.py +309 -0
  75. claude_mpm/cli/commands/aggregate.py +10 -6
  76. claude_mpm/cli/commands/analyze.py +15 -10
  77. claude_mpm/cli/commands/analyze_code.py +8 -4
  78. claude_mpm/cli/commands/auto_configure.py +570 -0
  79. claude_mpm/cli/commands/cleanup.py +12 -12
  80. claude_mpm/cli/commands/config.py +47 -13
  81. claude_mpm/cli/commands/configure.py +469 -1064
  82. claude_mpm/cli/commands/configure_agent_display.py +261 -0
  83. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  84. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  85. claude_mpm/cli/commands/configure_models.py +18 -0
  86. claude_mpm/cli/commands/configure_navigation.py +167 -0
  87. claude_mpm/cli/commands/configure_paths.py +104 -0
  88. claude_mpm/cli/commands/configure_persistence.py +254 -0
  89. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  90. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  91. claude_mpm/cli/commands/configure_validators.py +73 -0
  92. claude_mpm/cli/commands/dashboard.py +50 -52
  93. claude_mpm/cli/commands/debug.py +7 -7
  94. claude_mpm/cli/commands/doctor.py +43 -7
  95. claude_mpm/cli/commands/info.py +3 -4
  96. claude_mpm/cli/commands/local_deploy.py +537 -0
  97. claude_mpm/cli/commands/mcp.py +17 -10
  98. claude_mpm/cli/commands/mcp_command_router.py +11 -0
  99. claude_mpm/cli/commands/mcp_config.py +154 -0
  100. claude_mpm/cli/commands/mcp_external_commands.py +249 -0
  101. claude_mpm/cli/commands/mcp_install_commands.py +101 -32
  102. claude_mpm/cli/commands/mcp_pipx_config.py +2 -2
  103. claude_mpm/cli/commands/mcp_setup_external.py +868 -0
  104. claude_mpm/cli/commands/memory.py +55 -21
  105. claude_mpm/cli/commands/monitor.py +160 -70
  106. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  107. claude_mpm/cli/commands/mpm_init/core.py +525 -0
  108. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  109. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  110. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  111. claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
  112. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  113. claude_mpm/cli/commands/mpm_init_handler.py +114 -4
  114. claude_mpm/cli/commands/run.py +169 -42
  115. claude_mpm/cli/commands/search.py +458 -0
  116. claude_mpm/cli/commands/skills.py +488 -0
  117. claude_mpm/cli/commands/uninstall.py +176 -0
  118. claude_mpm/cli/commands/upgrade.py +152 -0
  119. claude_mpm/cli/commands/verify.py +119 -0
  120. claude_mpm/cli/executor.py +204 -0
  121. claude_mpm/cli/helpers.py +105 -0
  122. claude_mpm/cli/interactive/__init__.py +21 -0
  123. claude_mpm/cli/interactive/agent_wizard.py +962 -0
  124. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  125. claude_mpm/cli/parser.py +79 -2
  126. claude_mpm/cli/parsers/__init__.py +7 -1
  127. claude_mpm/cli/parsers/agent_manager_parser.py +161 -1
  128. claude_mpm/cli/parsers/agents_parser.py +116 -0
  129. claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
  130. claude_mpm/cli/parsers/base_parser.py +143 -3
  131. claude_mpm/cli/parsers/configure_parser.py +11 -15
  132. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  133. claude_mpm/cli/parsers/mcp_parser.py +15 -0
  134. claude_mpm/cli/parsers/monitor_parser.py +12 -2
  135. claude_mpm/cli/parsers/mpm_init_parser.py +179 -9
  136. claude_mpm/cli/parsers/run_parser.py +5 -0
  137. claude_mpm/cli/parsers/search_parser.py +245 -0
  138. claude_mpm/cli/parsers/skills_parser.py +137 -0
  139. claude_mpm/cli/shared/argument_patterns.py +20 -13
  140. claude_mpm/cli/shared/base_command.py +2 -2
  141. claude_mpm/cli/shared/output_formatters.py +28 -19
  142. claude_mpm/cli/startup.py +562 -0
  143. claude_mpm/cli/startup_logging.py +179 -13
  144. claude_mpm/cli/utils.py +53 -2
  145. claude_mpm/commands/mpm-agents-detect.md +168 -0
  146. claude_mpm/commands/mpm-agents-recommend.md +214 -0
  147. claude_mpm/commands/mpm-agents.md +118 -8
  148. claude_mpm/commands/mpm-auto-configure.md +269 -0
  149. claude_mpm/commands/mpm-config.md +137 -14
  150. claude_mpm/commands/mpm-help.md +285 -5
  151. claude_mpm/commands/mpm-init.md +374 -15
  152. claude_mpm/commands/mpm-monitor.md +409 -0
  153. claude_mpm/commands/mpm-organize.md +295 -0
  154. claude_mpm/commands/mpm-resume.md +372 -0
  155. claude_mpm/commands/mpm-status.md +71 -9
  156. claude_mpm/commands/mpm-tickets.md +56 -7
  157. claude_mpm/commands/mpm-version.md +113 -0
  158. claude_mpm/commands/mpm.md +2 -0
  159. claude_mpm/config/agent_config.py +4 -4
  160. claude_mpm/config/experimental_features.py +7 -7
  161. claude_mpm/config/model_config.py +428 -0
  162. claude_mpm/config/paths.py +3 -2
  163. claude_mpm/config/socketio_config.py +3 -3
  164. claude_mpm/constants.py +15 -1
  165. claude_mpm/core/__init__.py +53 -17
  166. claude_mpm/core/agent_name_normalizer.py +3 -2
  167. claude_mpm/core/agent_registry.py +2 -2
  168. claude_mpm/core/agent_session_manager.py +10 -10
  169. claude_mpm/core/api_validator.py +330 -0
  170. claude_mpm/core/base_service.py +33 -23
  171. claude_mpm/core/cache.py +9 -9
  172. claude_mpm/core/claude_runner.py +19 -8
  173. claude_mpm/core/config.py +85 -8
  174. claude_mpm/core/config_aliases.py +7 -6
  175. claude_mpm/core/constants.py +65 -0
  176. claude_mpm/core/container.py +11 -5
  177. claude_mpm/core/enums.py +452 -0
  178. claude_mpm/core/error_handler.py +623 -0
  179. claude_mpm/core/factories.py +1 -1
  180. claude_mpm/core/file_utils.py +764 -0
  181. claude_mpm/core/framework/__init__.py +38 -0
  182. claude_mpm/core/framework/formatters/__init__.py +11 -0
  183. claude_mpm/core/framework/formatters/capability_generator.py +367 -0
  184. claude_mpm/core/framework/formatters/content_formatter.py +288 -0
  185. claude_mpm/core/framework/formatters/context_generator.py +185 -0
  186. claude_mpm/core/framework/loaders/__init__.py +13 -0
  187. claude_mpm/core/framework/loaders/agent_loader.py +210 -0
  188. claude_mpm/core/framework/loaders/file_loader.py +223 -0
  189. claude_mpm/core/framework/loaders/instruction_loader.py +161 -0
  190. claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
  191. claude_mpm/core/framework/processors/__init__.py +11 -0
  192. claude_mpm/core/framework/processors/memory_processor.py +230 -0
  193. claude_mpm/core/framework/processors/metadata_processor.py +146 -0
  194. claude_mpm/core/framework/processors/template_processor.py +244 -0
  195. claude_mpm/core/framework_loader.py +321 -1631
  196. claude_mpm/core/hook_manager.py +8 -6
  197. claude_mpm/core/injectable_service.py +11 -8
  198. claude_mpm/core/instruction_reinforcement_hook.py +4 -3
  199. claude_mpm/core/interactive_session.py +55 -8
  200. claude_mpm/core/interfaces.py +56 -1
  201. claude_mpm/core/lazy.py +3 -3
  202. claude_mpm/core/log_manager.py +92 -23
  203. claude_mpm/core/logger.py +19 -14
  204. claude_mpm/core/logging_config.py +6 -2
  205. claude_mpm/core/logging_utils.py +520 -0
  206. claude_mpm/core/oneshot_session.py +51 -7
  207. claude_mpm/core/optimized_agent_loader.py +9 -9
  208. claude_mpm/core/optimized_startup.py +1 -1
  209. claude_mpm/core/output_style_manager.py +12 -192
  210. claude_mpm/core/pm_hook_interceptor.py +18 -12
  211. claude_mpm/core/service_registry.py +7 -3
  212. claude_mpm/core/session_manager.py +14 -12
  213. claude_mpm/core/shared/config_loader.py +1 -1
  214. claude_mpm/core/socketio_pool.py +15 -15
  215. claude_mpm/core/tool_access_control.py +3 -2
  216. claude_mpm/core/types.py +4 -11
  217. claude_mpm/core/typing_utils.py +7 -6
  218. claude_mpm/core/unified_agent_registry.py +115 -11
  219. claude_mpm/core/unified_config.py +6 -6
  220. claude_mpm/core/unified_paths.py +23 -20
  221. claude_mpm/dashboard/analysis_runner.py +4 -4
  222. claude_mpm/dashboard/api/simple_directory.py +261 -0
  223. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +188 -0
  224. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +156 -0
  225. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +38 -0
  226. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +92 -0
  227. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +248 -0
  228. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +61 -0
  229. claude_mpm/dashboard/static/archive/test_activity_connection.html +179 -0
  230. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +68 -0
  231. claude_mpm/dashboard/static/archive/test_dashboard.html +409 -0
  232. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +519 -0
  233. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +181 -0
  234. claude_mpm/dashboard/static/archive/test_file_data.html +315 -0
  235. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +243 -0
  236. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +234 -0
  237. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +117 -0
  238. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +115 -0
  239. claude_mpm/dashboard/static/archive/test_file_viewer.html +224 -0
  240. claude_mpm/dashboard/static/archive/test_final_activity.html +220 -0
  241. claude_mpm/dashboard/static/archive/test_tab_fix.html +139 -0
  242. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +1 -0
  243. claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
  244. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +777 -0
  245. claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
  246. claude_mpm/dashboard/static/built/components/build-tracker.js +333 -0
  247. claude_mpm/dashboard/static/built/components/code-simple.js +857 -0
  248. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +353 -0
  249. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +235 -0
  250. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +409 -0
  251. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +435 -0
  252. claude_mpm/dashboard/static/built/components/code-tree.js +1 -1
  253. claude_mpm/dashboard/static/built/components/code-viewer.js +1 -1
  254. claude_mpm/dashboard/static/built/components/connection-debug.js +654 -0
  255. claude_mpm/dashboard/static/built/components/diff-viewer.js +891 -0
  256. claude_mpm/dashboard/static/built/components/event-processor.js +1 -1
  257. claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
  258. claude_mpm/dashboard/static/built/components/export-manager.js +1 -1
  259. claude_mpm/dashboard/static/built/components/file-change-tracker.js +443 -0
  260. claude_mpm/dashboard/static/built/components/file-change-viewer.js +690 -0
  261. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
  262. claude_mpm/dashboard/static/built/components/file-viewer.js +2 -0
  263. claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
  264. claude_mpm/dashboard/static/built/components/nav-bar.js +145 -0
  265. claude_mpm/dashboard/static/built/components/page-structure.js +429 -0
  266. claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
  267. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +1 -1
  268. claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
  269. claude_mpm/dashboard/static/built/connection-manager.js +536 -0
  270. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  271. claude_mpm/dashboard/static/built/extension-error-handler.js +164 -0
  272. claude_mpm/dashboard/static/built/react/events.js +30 -0
  273. claude_mpm/dashboard/static/built/shared/dom-helpers.js +396 -0
  274. claude_mpm/dashboard/static/built/shared/event-bus.js +330 -0
  275. claude_mpm/dashboard/static/built/shared/event-filter-service.js +540 -0
  276. claude_mpm/dashboard/static/built/shared/logger.js +385 -0
  277. claude_mpm/dashboard/static/built/shared/page-structure.js +249 -0
  278. claude_mpm/dashboard/static/built/shared/tooltip-service.js +253 -0
  279. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  280. claude_mpm/dashboard/static/built/tab-isolation-fix.js +185 -0
  281. claude_mpm/dashboard/static/css/dashboard.css +588 -6
  282. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +1 -0
  283. claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
  284. claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
  285. claude_mpm/dashboard/static/dist/components/code-tree.js +1 -1
  286. claude_mpm/dashboard/static/dist/components/code-viewer.js +1 -1
  287. claude_mpm/dashboard/static/dist/components/event-processor.js +1 -1
  288. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  289. claude_mpm/dashboard/static/dist/components/export-manager.js +1 -1
  290. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
  291. claude_mpm/dashboard/static/dist/components/file-viewer.js +2 -0
  292. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  293. claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
  294. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +1 -1
  295. claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
  296. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  297. claude_mpm/dashboard/static/dist/react/events.js +30 -0
  298. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  299. claude_mpm/dashboard/static/events.html +607 -0
  300. claude_mpm/dashboard/static/index.html +635 -0
  301. claude_mpm/dashboard/static/js/components/activity-tree.js +3 -17
  302. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +4 -1
  303. claude_mpm/dashboard/static/js/components/agent-inference.js +3 -0
  304. claude_mpm/dashboard/static/js/components/build-tracker.js +8 -0
  305. claude_mpm/dashboard/static/js/components/code-simple.js +857 -0
  306. claude_mpm/dashboard/static/js/components/diff-viewer.js +891 -0
  307. claude_mpm/dashboard/static/js/components/event-processor.js +3 -0
  308. claude_mpm/dashboard/static/js/components/event-viewer.js +39 -2
  309. claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
  310. claude_mpm/dashboard/static/js/components/file-change-tracker.js +443 -0
  311. claude_mpm/dashboard/static/js/components/file-change-viewer.js +690 -0
  312. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +30 -10
  313. claude_mpm/dashboard/static/js/components/file-viewer.js +580 -0
  314. claude_mpm/dashboard/static/js/components/module-viewer.js +26 -0
  315. claude_mpm/dashboard/static/js/components/session-manager.js +7 -7
  316. claude_mpm/dashboard/static/js/components/socket-manager.js +4 -0
  317. claude_mpm/dashboard/static/js/components/ui-state-manager.js +356 -41
  318. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +455 -23
  319. claude_mpm/dashboard/static/js/components/working-directory.js +44 -9
  320. claude_mpm/dashboard/static/js/dashboard.js +245 -132
  321. claude_mpm/dashboard/static/js/shared/dom-helpers.js +396 -0
  322. claude_mpm/dashboard/static/js/shared/event-bus.js +330 -0
  323. claude_mpm/dashboard/static/js/shared/logger.js +385 -0
  324. claude_mpm/dashboard/static/js/shared/tooltip-service.js +253 -0
  325. claude_mpm/dashboard/static/js/socket-client.js +49 -22
  326. claude_mpm/dashboard/static/js/stores/dashboard-store.js +562 -0
  327. claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
  328. claude_mpm/dashboard/static/legacy/activity.html +736 -0
  329. claude_mpm/dashboard/static/legacy/agents.html +786 -0
  330. claude_mpm/dashboard/static/legacy/files.html +747 -0
  331. claude_mpm/dashboard/static/legacy/tools.html +831 -0
  332. claude_mpm/dashboard/static/monitors.html +431 -0
  333. claude_mpm/dashboard/static/production/events.html +659 -0
  334. claude_mpm/dashboard/static/production/main.html +698 -0
  335. claude_mpm/dashboard/static/production/monitors.html +483 -0
  336. claude_mpm/dashboard/static/socket.io.min.js +7 -0
  337. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
  338. claude_mpm/dashboard/static/test-archive/dashboard.html +635 -0
  339. claude_mpm/dashboard/static/test-archive/debug-events.html +147 -0
  340. claude_mpm/dashboard/static/test-archive/test-navigation.html +256 -0
  341. claude_mpm/dashboard/static/test-archive/test-react-exports.html +180 -0
  342. claude_mpm/dashboard/static/test-archive/test_debug.html +25 -0
  343. claude_mpm/dashboard/templates/code_simple.html +153 -0
  344. claude_mpm/dashboard/templates/index.html +112 -109
  345. claude_mpm/experimental/cli_enhancements.py +4 -2
  346. claude_mpm/generators/agent_profile_generator.py +5 -3
  347. claude_mpm/hooks/__init__.py +37 -1
  348. claude_mpm/hooks/base_hook.py +5 -4
  349. claude_mpm/hooks/claude_hooks/connection_pool.py +4 -4
  350. claude_mpm/hooks/claude_hooks/event_handlers.py +21 -18
  351. claude_mpm/hooks/claude_hooks/hook_handler.py +29 -22
  352. claude_mpm/hooks/claude_hooks/installer.py +67 -22
  353. claude_mpm/hooks/claude_hooks/memory_integration.py +3 -3
  354. claude_mpm/hooks/claude_hooks/response_tracking.py +57 -17
  355. claude_mpm/hooks/claude_hooks/services/connection_manager.py +62 -64
  356. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +140 -76
  357. claude_mpm/hooks/claude_hooks/services/state_manager.py +11 -9
  358. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +3 -3
  359. claude_mpm/hooks/failure_learning/__init__.py +60 -0
  360. claude_mpm/hooks/failure_learning/failure_detection_hook.py +235 -0
  361. claude_mpm/hooks/failure_learning/fix_detection_hook.py +217 -0
  362. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +286 -0
  363. claude_mpm/hooks/instruction_reinforcement.py +301 -0
  364. claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
  365. claude_mpm/hooks/kuzu_memory_hook.py +386 -0
  366. claude_mpm/hooks/kuzu_response_hook.py +183 -0
  367. claude_mpm/hooks/memory_integration_hook.py +1 -1
  368. claude_mpm/hooks/session_resume_hook.py +121 -0
  369. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  370. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  371. claude_mpm/hooks/tool_call_interceptor.py +8 -5
  372. claude_mpm/hooks/validation_hooks.py +3 -3
  373. claude_mpm/init.py +23 -4
  374. claude_mpm/models/agent_session.py +8 -6
  375. claude_mpm/models/resume_log.py +340 -0
  376. claude_mpm/scripts/claude-hook-handler.sh +33 -7
  377. claude_mpm/scripts/launch_monitor.py +85 -0
  378. claude_mpm/scripts/mcp_server.py +3 -5
  379. claude_mpm/scripts/mpm_doctor.py +3 -2
  380. claude_mpm/scripts/socketio_daemon.py +159 -512
  381. claude_mpm/services/__init__.py +144 -160
  382. claude_mpm/services/agents/__init__.py +18 -5
  383. claude_mpm/services/agents/agent_builder.py +13 -11
  384. claude_mpm/services/agents/auto_config_manager.py +796 -0
  385. claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
  386. claude_mpm/services/agents/deployment/agent_deployment.py +38 -15
  387. claude_mpm/services/agents/deployment/agent_discovery_service.py +125 -7
  388. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +5 -5
  389. claude_mpm/services/agents/deployment/agent_format_converter.py +56 -12
  390. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +4 -2
  391. claude_mpm/services/agents/deployment/agent_operation_service.py +2 -2
  392. claude_mpm/services/agents/deployment/agent_record_service.py +4 -4
  393. claude_mpm/services/agents/deployment/agent_state_service.py +2 -2
  394. claude_mpm/services/agents/deployment/agent_template_builder.py +715 -47
  395. claude_mpm/services/agents/deployment/agent_validator.py +31 -7
  396. claude_mpm/services/agents/deployment/agent_version_manager.py +8 -5
  397. claude_mpm/services/agents/deployment/agent_versioning.py +1 -1
  398. claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
  399. claude_mpm/services/agents/deployment/deployment_config_loader.py +131 -7
  400. claude_mpm/services/agents/deployment/deployment_type_detector.py +10 -14
  401. claude_mpm/services/agents/deployment/deployment_wrapper.py +58 -0
  402. claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
  403. claude_mpm/services/agents/deployment/local_template_deployment.py +360 -0
  404. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +134 -38
  405. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +8 -7
  406. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
  407. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
  408. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +7 -5
  409. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
  410. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
  411. claude_mpm/services/agents/deployment/system_instructions_deployer.py +9 -6
  412. claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
  413. claude_mpm/services/agents/deployment/validation/template_validator.py +64 -44
  414. claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
  415. claude_mpm/services/agents/loading/agent_profile_loader.py +10 -9
  416. claude_mpm/services/agents/loading/base_agent_manager.py +16 -6
  417. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -2
  418. claude_mpm/services/agents/local_template_manager.py +744 -0
  419. claude_mpm/services/agents/management/agent_capabilities_generator.py +3 -2
  420. claude_mpm/services/agents/management/agent_management_service.py +5 -5
  421. claude_mpm/services/agents/memory/agent_memory_manager.py +32 -29
  422. claude_mpm/services/agents/memory/content_manager.py +17 -9
  423. claude_mpm/services/agents/memory/memory_categorization_service.py +4 -2
  424. claude_mpm/services/agents/memory/memory_file_service.py +32 -6
  425. claude_mpm/services/agents/memory/memory_format_service.py +6 -4
  426. claude_mpm/services/agents/memory/memory_limits_service.py +4 -2
  427. claude_mpm/services/agents/memory/template_generator.py +3 -3
  428. claude_mpm/services/agents/observers.py +547 -0
  429. claude_mpm/services/agents/recommender.py +615 -0
  430. claude_mpm/services/agents/registry/deployed_agent_discovery.py +3 -3
  431. claude_mpm/services/agents/registry/modification_tracker.py +30 -19
  432. claude_mpm/services/async_session_logger.py +141 -98
  433. claude_mpm/services/claude_session_logger.py +82 -74
  434. claude_mpm/services/cli/agent_cleanup_service.py +5 -0
  435. claude_mpm/services/cli/agent_listing_service.py +5 -5
  436. claude_mpm/services/cli/agent_validation_service.py +3 -1
  437. claude_mpm/services/cli/memory_crud_service.py +12 -7
  438. claude_mpm/services/cli/memory_output_formatter.py +2 -2
  439. claude_mpm/services/cli/resume_service.py +617 -0
  440. claude_mpm/services/cli/session_manager.py +104 -13
  441. claude_mpm/services/cli/session_pause_manager.py +504 -0
  442. claude_mpm/services/cli/session_resume_helper.py +372 -0
  443. claude_mpm/services/cli/startup_checker.py +13 -10
  444. claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
  445. claude_mpm/services/command_deployment_service.py +9 -7
  446. claude_mpm/services/command_handler_service.py +11 -5
  447. claude_mpm/services/core/__init__.py +33 -1
  448. claude_mpm/services/core/base.py +26 -11
  449. claude_mpm/services/core/interfaces/__init__.py +90 -3
  450. claude_mpm/services/core/interfaces/agent.py +184 -0
  451. claude_mpm/services/core/interfaces/health.py +172 -0
  452. claude_mpm/services/core/interfaces/model.py +281 -0
  453. claude_mpm/services/core/interfaces/process.py +372 -0
  454. claude_mpm/services/core/interfaces/project.py +121 -0
  455. claude_mpm/services/core/interfaces/restart.py +307 -0
  456. claude_mpm/services/core/interfaces/stability.py +260 -0
  457. claude_mpm/services/core/interfaces.py +56 -1
  458. claude_mpm/services/core/memory_manager.py +92 -47
  459. claude_mpm/services/core/models/__init__.py +79 -0
  460. claude_mpm/services/core/models/agent_config.py +384 -0
  461. claude_mpm/services/core/models/health.py +162 -0
  462. claude_mpm/services/core/models/process.py +239 -0
  463. claude_mpm/services/core/models/restart.py +302 -0
  464. claude_mpm/services/core/models/stability.py +264 -0
  465. claude_mpm/services/core/models/toolchain.py +306 -0
  466. claude_mpm/services/core/path_resolver.py +36 -14
  467. claude_mpm/services/diagnostics/__init__.py +2 -2
  468. claude_mpm/services/diagnostics/checks/__init__.py +4 -2
  469. claude_mpm/services/diagnostics/checks/agent_check.py +30 -32
  470. claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
  471. claude_mpm/services/diagnostics/checks/common_issues_check.py +28 -27
  472. claude_mpm/services/diagnostics/checks/configuration_check.py +26 -25
  473. claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
  474. claude_mpm/services/diagnostics/checks/installation_check.py +165 -60
  475. claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
  476. claude_mpm/services/diagnostics/checks/mcp_check.py +57 -43
  477. claude_mpm/services/diagnostics/checks/mcp_services_check.py +1066 -0
  478. claude_mpm/services/diagnostics/checks/monitor_check.py +24 -23
  479. claude_mpm/services/diagnostics/checks/startup_log_check.py +14 -11
  480. claude_mpm/services/diagnostics/diagnostic_runner.py +22 -13
  481. claude_mpm/services/diagnostics/doctor_reporter.py +275 -47
  482. claude_mpm/services/diagnostics/models.py +37 -21
  483. claude_mpm/services/event_aggregator.py +5 -3
  484. claude_mpm/services/event_bus/direct_relay.py +8 -4
  485. claude_mpm/services/event_bus/event_bus.py +51 -9
  486. claude_mpm/services/event_bus/relay.py +33 -14
  487. claude_mpm/services/events/consumers/dead_letter.py +7 -5
  488. claude_mpm/services/events/core.py +5 -6
  489. claude_mpm/services/events/producers/hook.py +6 -6
  490. claude_mpm/services/events/producers/system.py +8 -8
  491. claude_mpm/services/exceptions.py +5 -5
  492. claude_mpm/services/framework_claude_md_generator/__init__.py +1 -1
  493. claude_mpm/services/framework_claude_md_generator/content_assembler.py +5 -5
  494. claude_mpm/services/framework_claude_md_generator/content_validator.py +2 -2
  495. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +3 -3
  496. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +2 -2
  497. claude_mpm/services/framework_claude_md_generator/version_manager.py +1 -1
  498. claude_mpm/services/hook_installer_service.py +506 -0
  499. claude_mpm/services/hook_service.py +5 -6
  500. claude_mpm/services/infrastructure/context_preservation.py +13 -11
  501. claude_mpm/services/infrastructure/daemon_manager.py +9 -9
  502. claude_mpm/services/infrastructure/logging.py +2 -2
  503. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
  504. claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
  505. claude_mpm/services/infrastructure/monitoring/base.py +5 -13
  506. claude_mpm/services/infrastructure/monitoring/network.py +7 -6
  507. claude_mpm/services/infrastructure/monitoring/process.py +13 -12
  508. claude_mpm/services/infrastructure/monitoring/resources.py +8 -7
  509. claude_mpm/services/infrastructure/monitoring/service.py +16 -15
  510. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  511. claude_mpm/services/local_ops/__init__.py +165 -0
  512. claude_mpm/services/local_ops/crash_detector.py +257 -0
  513. claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
  514. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  515. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  516. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  517. claude_mpm/services/local_ops/health_manager.py +430 -0
  518. claude_mpm/services/local_ops/log_monitor.py +396 -0
  519. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  520. claude_mpm/services/local_ops/process_manager.py +595 -0
  521. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  522. claude_mpm/services/local_ops/restart_manager.py +401 -0
  523. claude_mpm/services/local_ops/restart_policy.py +387 -0
  524. claude_mpm/services/local_ops/state_manager.py +372 -0
  525. claude_mpm/services/local_ops/unified_manager.py +600 -0
  526. claude_mpm/services/mcp_config_manager.py +1612 -0
  527. claude_mpm/services/mcp_gateway/__init__.py +97 -93
  528. claude_mpm/services/mcp_gateway/auto_configure.py +43 -38
  529. claude_mpm/services/mcp_gateway/config/config_loader.py +3 -3
  530. claude_mpm/services/mcp_gateway/config/configuration.py +23 -4
  531. claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
  532. claude_mpm/services/mcp_gateway/core/base.py +20 -33
  533. claude_mpm/services/mcp_gateway/core/process_pool.py +585 -31
  534. claude_mpm/services/mcp_gateway/core/singleton_manager.py +2 -2
  535. claude_mpm/services/mcp_gateway/core/startup_verification.py +3 -3
  536. claude_mpm/services/mcp_gateway/main.py +90 -15
  537. claude_mpm/services/mcp_gateway/registry/service_registry.py +4 -2
  538. claude_mpm/services/mcp_gateway/registry/tool_registry.py +12 -9
  539. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +4 -4
  540. claude_mpm/services/mcp_gateway/server/stdio_server.py +9 -15
  541. claude_mpm/services/mcp_gateway/tools/__init__.py +14 -2
  542. claude_mpm/services/mcp_gateway/tools/base_adapter.py +15 -15
  543. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +10 -9
  544. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +654 -0
  545. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +36 -34
  546. claude_mpm/services/mcp_gateway/tools/hello_world.py +8 -8
  547. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +551 -0
  548. claude_mpm/services/mcp_gateway/utils/__init__.py +14 -0
  549. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +160 -0
  550. claude_mpm/services/mcp_gateway/utils/update_preferences.py +170 -0
  551. claude_mpm/services/mcp_service_verifier.py +729 -0
  552. claude_mpm/services/memory/builder.py +9 -8
  553. claude_mpm/services/memory/cache/shared_prompt_cache.py +2 -1
  554. claude_mpm/services/memory/cache/simple_cache.py +2 -2
  555. claude_mpm/services/memory/failure_tracker.py +578 -0
  556. claude_mpm/services/memory/indexed_memory.py +8 -8
  557. claude_mpm/services/memory/optimizer.py +8 -9
  558. claude_mpm/services/memory/router.py +3 -3
  559. claude_mpm/services/memory_hook_service.py +165 -4
  560. claude_mpm/services/model/__init__.py +147 -0
  561. claude_mpm/services/model/base_provider.py +365 -0
  562. claude_mpm/services/model/claude_provider.py +412 -0
  563. claude_mpm/services/model/model_router.py +453 -0
  564. claude_mpm/services/model/ollama_provider.py +415 -0
  565. claude_mpm/services/monitor/__init__.py +20 -0
  566. claude_mpm/services/monitor/daemon.py +671 -0
  567. claude_mpm/services/monitor/daemon_manager.py +963 -0
  568. claude_mpm/services/monitor/event_emitter.py +350 -0
  569. claude_mpm/services/monitor/handlers/__init__.py +21 -0
  570. claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
  571. claude_mpm/services/monitor/handlers/dashboard.py +299 -0
  572. claude_mpm/services/monitor/handlers/file.py +264 -0
  573. claude_mpm/services/monitor/handlers/hooks.py +512 -0
  574. claude_mpm/services/monitor/management/__init__.py +18 -0
  575. claude_mpm/services/monitor/management/health.py +124 -0
  576. claude_mpm/services/monitor/management/lifecycle.py +724 -0
  577. claude_mpm/services/monitor/server.py +817 -0
  578. claude_mpm/services/monitor_build_service.py +2 -2
  579. claude_mpm/services/native_agent_converter.py +356 -0
  580. claude_mpm/services/orphan_detection.py +786 -0
  581. claude_mpm/services/port_manager.py +2 -2
  582. claude_mpm/services/project/__init__.py +23 -0
  583. claude_mpm/services/project/analyzer.py +3 -3
  584. claude_mpm/services/project/architecture_analyzer.py +5 -5
  585. claude_mpm/services/project/archive_manager.py +1045 -0
  586. claude_mpm/services/project/dependency_analyzer.py +4 -4
  587. claude_mpm/services/project/detection_strategies.py +719 -0
  588. claude_mpm/services/project/documentation_manager.py +553 -0
  589. claude_mpm/services/project/enhanced_analyzer.py +572 -0
  590. claude_mpm/services/project/metrics_collector.py +4 -4
  591. claude_mpm/services/project/project_organizer.py +1005 -0
  592. claude_mpm/services/project/registry.py +13 -7
  593. claude_mpm/services/project/toolchain_analyzer.py +581 -0
  594. claude_mpm/services/project_port_allocator.py +596 -0
  595. claude_mpm/services/response_tracker.py +21 -10
  596. claude_mpm/services/runner_configuration_service.py +1 -0
  597. claude_mpm/services/self_upgrade_service.py +500 -0
  598. claude_mpm/services/session_management_service.py +7 -5
  599. claude_mpm/services/session_manager.py +380 -0
  600. claude_mpm/services/shared/__init__.py +2 -1
  601. claude_mpm/services/shared/async_service_base.py +16 -27
  602. claude_mpm/services/shared/config_service_base.py +17 -14
  603. claude_mpm/services/shared/lifecycle_service_base.py +1 -14
  604. claude_mpm/services/shared/service_factory.py +8 -5
  605. claude_mpm/services/socketio/client_proxy.py +60 -5
  606. claude_mpm/services/socketio/dashboard_server.py +361 -0
  607. claude_mpm/services/socketio/event_normalizer.py +10 -6
  608. claude_mpm/services/socketio/handlers/__init__.py +5 -2
  609. claude_mpm/services/socketio/handlers/base.py +2 -2
  610. claude_mpm/services/socketio/handlers/code_analysis.py +90 -27
  611. claude_mpm/services/socketio/handlers/connection.py +21 -40
  612. claude_mpm/services/socketio/handlers/connection_handler.py +13 -10
  613. claude_mpm/services/socketio/handlers/file.py +46 -10
  614. claude_mpm/services/socketio/handlers/git.py +8 -8
  615. claude_mpm/services/socketio/handlers/hook.py +29 -17
  616. claude_mpm/services/socketio/handlers/registry.py +4 -2
  617. claude_mpm/services/socketio/monitor_client.py +364 -0
  618. claude_mpm/services/socketio/server/broadcaster.py +9 -7
  619. claude_mpm/services/socketio/server/connection_manager.py +2 -2
  620. claude_mpm/services/socketio/server/core.py +141 -4
  621. claude_mpm/services/socketio/server/eventbus_integration.py +20 -14
  622. claude_mpm/services/socketio/server/main.py +23 -21
  623. claude_mpm/services/socketio_client_manager.py +4 -4
  624. claude_mpm/services/subprocess_launcher_service.py +19 -15
  625. claude_mpm/services/system_instructions_service.py +2 -2
  626. claude_mpm/services/ticket_services/formatter_service.py +1 -1
  627. claude_mpm/services/ticket_services/validation_service.py +5 -5
  628. claude_mpm/services/unified/__init__.py +65 -0
  629. claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
  630. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
  631. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
  632. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +903 -0
  633. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +746 -0
  634. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
  635. claude_mpm/services/unified/config_strategies/__init__.py +175 -0
  636. claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
  637. claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
  638. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
  639. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
  640. claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
  641. claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
  642. claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
  643. claude_mpm/services/unified/deployment_strategies/base.py +553 -0
  644. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
  645. claude_mpm/services/unified/deployment_strategies/local.py +607 -0
  646. claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
  647. claude_mpm/services/unified/deployment_strategies/vercel.py +475 -0
  648. claude_mpm/services/unified/interfaces.py +475 -0
  649. claude_mpm/services/unified/migration.py +509 -0
  650. claude_mpm/services/unified/strategies.py +534 -0
  651. claude_mpm/services/unified/unified_analyzer.py +542 -0
  652. claude_mpm/services/unified/unified_config.py +691 -0
  653. claude_mpm/services/unified/unified_deployment.py +470 -0
  654. claude_mpm/services/utility_service.py +6 -3
  655. claude_mpm/services/version_control/branch_strategy.py +2 -2
  656. claude_mpm/services/version_control/conflict_resolution.py +8 -4
  657. claude_mpm/services/version_control/git_operations.py +26 -24
  658. claude_mpm/services/version_control/semantic_versioning.py +14 -14
  659. claude_mpm/services/version_control/version_parser.py +14 -11
  660. claude_mpm/services/version_service.py +104 -1
  661. claude_mpm/skills/__init__.py +42 -0
  662. claude_mpm/skills/agent_skills_injector.py +324 -0
  663. claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
  664. claude_mpm/skills/bundled/__init__.py +6 -0
  665. claude_mpm/skills/bundled/api-documentation.md +393 -0
  666. claude_mpm/skills/bundled/async-testing.md +571 -0
  667. claude_mpm/skills/bundled/code-review.md +143 -0
  668. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  669. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  670. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  671. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  672. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  673. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  674. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  675. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  676. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  677. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  678. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  679. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  680. claude_mpm/skills/bundled/database-migration.md +199 -0
  681. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  682. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  683. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  684. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  685. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  686. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  687. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  688. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  689. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  690. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  691. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  692. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  693. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  694. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  695. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  696. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  697. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  698. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  699. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  700. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  701. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  702. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  703. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  704. claude_mpm/skills/bundled/git-workflow.md +414 -0
  705. claude_mpm/skills/bundled/imagemagick.md +204 -0
  706. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  707. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  708. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  709. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  710. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  711. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  712. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  713. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  714. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  715. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  716. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  717. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  718. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  719. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  720. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  721. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
  722. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
  723. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  724. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  725. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  726. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  727. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  728. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  729. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
  730. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
  731. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
  732. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  733. claude_mpm/skills/bundled/pdf.md +141 -0
  734. claude_mpm/skills/bundled/performance-profiling.md +573 -0
  735. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  736. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  737. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  738. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  739. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  740. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  741. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  742. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  743. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  744. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  745. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  746. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  747. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  748. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  749. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  750. claude_mpm/skills/bundled/security-scanning.md +327 -0
  751. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  752. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  753. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  754. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  755. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  756. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  757. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  758. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  759. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  760. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  761. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  762. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  763. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  764. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  765. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  766. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  767. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  768. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
  769. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
  770. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
  771. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  772. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  773. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
  774. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  775. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  776. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  777. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  778. claude_mpm/skills/bundled/xlsx.md +157 -0
  779. claude_mpm/skills/registry.py +286 -0
  780. claude_mpm/skills/skill_manager.py +310 -0
  781. claude_mpm/skills/skills_registry.py +348 -0
  782. claude_mpm/skills/skills_service.py +739 -0
  783. claude_mpm/storage/state_storage.py +31 -31
  784. claude_mpm/tools/__main__.py +1 -1
  785. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  786. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  787. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  788. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  789. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  790. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  791. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  792. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  793. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  794. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  795. claude_mpm/tools/code_tree_builder.py +6 -6
  796. claude_mpm/tools/code_tree_events.py +14 -10
  797. claude_mpm/tools/socketio_debug.py +11 -11
  798. claude_mpm/utils/agent_dependency_loader.py +108 -27
  799. claude_mpm/utils/common.py +544 -0
  800. claude_mpm/utils/config_manager.py +12 -6
  801. claude_mpm/utils/database_connector.py +298 -0
  802. claude_mpm/utils/dependency_cache.py +2 -2
  803. claude_mpm/utils/dependency_strategies.py +15 -10
  804. claude_mpm/utils/display_helper.py +260 -0
  805. claude_mpm/utils/environment_context.py +4 -3
  806. claude_mpm/utils/error_handler.py +5 -3
  807. claude_mpm/utils/file_utils.py +13 -14
  808. claude_mpm/utils/git_analyzer.py +407 -0
  809. claude_mpm/utils/log_cleanup.py +627 -0
  810. claude_mpm/utils/path_operations.py +7 -4
  811. claude_mpm/utils/robust_installer.py +133 -24
  812. claude_mpm/utils/session_logging.py +2 -2
  813. claude_mpm/utils/subprocess_utils.py +9 -8
  814. claude_mpm/validation/agent_validator.py +6 -6
  815. claude_mpm/validation/frontmatter_validator.py +6 -6
  816. claude_mpm-4.24.0.dist-info/METADATA +675 -0
  817. claude_mpm-4.24.0.dist-info/RECORD +1018 -0
  818. {claude_mpm-4.1.26.dist-info → claude_mpm-4.24.0.dist-info}/entry_points.txt +1 -0
  819. claude_mpm/agents/INSTRUCTIONS.md +0 -261
  820. claude_mpm/agents/templates/agent-manager.md +0 -619
  821. claude_mpm/cli/commands/configure_tui.py +0 -1927
  822. claude_mpm/cli/commands/mpm_init.py +0 -594
  823. claude_mpm/cli/commands/socketio_monitor.py +0 -233
  824. claude_mpm/dashboard/static/css/code-tree.css +0 -1408
  825. claude_mpm/dashboard/static/js/components/code-tree.js +0 -3220
  826. claude_mpm/dashboard/static/js/components/code-viewer.js +0 -480
  827. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
  828. claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1040
  829. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
  830. claude_mpm/scripts/socketio_daemon_hardened.py +0 -937
  831. claude_mpm/scripts/socketio_daemon_wrapper.py +0 -78
  832. claude_mpm/scripts/socketio_server_manager.py +0 -349
  833. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
  834. claude_mpm/services/cli/dashboard_launcher.py +0 -423
  835. claude_mpm/services/cli/socketio_manager.py +0 -537
  836. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +0 -286
  837. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +0 -645
  838. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +0 -602
  839. claude_mpm/services/project/analyzer_refactored.py +0 -450
  840. claude_mpm/tools/code_tree_analyzer.py +0 -1693
  841. claude_mpm-4.1.26.dist-info/METADATA +0 -332
  842. claude_mpm-4.1.26.dist-info/RECORD +0 -606
  843. {claude_mpm-4.1.26.dist-info → claude_mpm-4.24.0.dist-info}/WHEEL +0 -0
  844. {claude_mpm-4.1.26.dist-info → claude_mpm-4.24.0.dist-info}/licenses/LICENSE +0 -0
  845. {claude_mpm-4.1.26.dist-info → claude_mpm-4.24.0.dist-info}/top_level.txt +0 -0
@@ -1,35 +1,37 @@
1
- """Framework loader for Claude MPM."""
1
+ """Framework loader for Claude MPM - Refactored modular version."""
2
2
 
3
- import getpass
4
- import locale
5
- import logging
3
+ import asyncio
6
4
  import os
7
- import platform
8
- import time
9
- from datetime import datetime
10
5
  from pathlib import Path
11
- from typing import Any, Dict, Optional
12
-
13
- # Import resource handling for packaged installations
14
- try:
15
- # Python 3.9+
16
- from importlib.resources import files
17
- except ImportError:
18
- # Python 3.8 fallback
19
- try:
20
- from importlib_resources import files
21
- except ImportError:
22
- # Final fallback for development environments
23
- files = None
24
-
25
- from ..utils.imports import safe_import
6
+ from typing import Any, Dict, List, Optional, Set
7
+
8
+ # Import framework components
9
+ from claude_mpm.core.framework import (
10
+ AgentLoader,
11
+ CapabilityGenerator,
12
+ ContentFormatter,
13
+ ContextGenerator,
14
+ FileLoader,
15
+ InstructionLoader,
16
+ MemoryProcessor,
17
+ MetadataProcessor,
18
+ PackagedLoader,
19
+ TemplateProcessor,
20
+ )
21
+ from claude_mpm.core.logging_utils import get_logger
22
+ from claude_mpm.utils.imports import safe_import
26
23
 
27
- # Import with fallback support - using absolute imports as primary since we're at module level
28
- get_logger = safe_import("claude_mpm.core.logger", "core.logger", ["get_logger"])
24
+ # Import with fallback support
29
25
  AgentRegistryAdapter = safe_import(
30
26
  "claude_mpm.core.agent_registry", "core.agent_registry", ["AgentRegistryAdapter"]
31
27
  )
32
28
 
29
+ # Import API validator
30
+ try:
31
+ from claude_mpm.core.api_validator import validate_api_keys
32
+ except ImportError:
33
+ from ..core.api_validator import validate_api_keys
34
+
33
35
  # Import the service container and interfaces
34
36
  try:
35
37
  from claude_mpm.services.core.cache_manager import CacheManager
@@ -61,43 +63,13 @@ class FrameworkLoader:
61
63
  """
62
64
  Load and prepare framework instructions for injection.
63
65
 
64
- This component handles:
65
- 1. Finding the framework (claude-multiagent-pm)
66
- 2. Loading custom instructions from .claude-mpm/ directories
67
- 3. Preparing agent definitions
68
- 4. Formatting for injection
69
-
70
- Custom Instructions Loading:
71
- The framework loader supports custom instructions through .claude-mpm/ directories.
72
- It NEVER reads from .claude/ directories to avoid conflicts with Claude Code.
73
-
74
- File Loading Precedence (highest to lowest):
75
-
76
- INSTRUCTIONS.md:
77
- 1. Project: ./.claude-mpm/INSTRUCTIONS.md
78
- 2. User: ~/.claude-mpm/INSTRUCTIONS.md
79
- 3. System: (built-in framework instructions)
80
-
81
- WORKFLOW.md:
82
- 1. Project: ./.claude-mpm/WORKFLOW.md
83
- 2. User: ~/.claude-mpm/WORKFLOW.md
84
- 3. System: src/claude_mpm/agents/WORKFLOW.md
85
-
86
- MEMORY.md:
87
- 1. Project: ./.claude-mpm/MEMORY.md
88
- 2. User: ~/.claude-mpm/MEMORY.md
89
- 3. System: src/claude_mpm/agents/MEMORY.md
90
-
91
- Actual Memories:
92
- - User: ~/.claude-mpm/memories/PM_memories.md
93
- - Project: ./.claude-mpm/memories/PM_memories.md (overrides user)
94
- - Agent memories: *_memories.md files (only loaded if agent is deployed)
95
-
96
- Important Notes:
97
- - Project-level files always override user-level files
98
- - User-level files always override system defaults
99
- - The framework NEVER reads from .claude/ directories
100
- - Custom instructions are clearly labeled with their source level
66
+ This refactored version uses modular components for better maintainability
67
+ and testability while maintaining backward compatibility.
68
+
69
+ Components:
70
+ - Loaders: Handle file I/O and resource loading
71
+ - Formatters: Generate and format content sections
72
+ - Processors: Process metadata, templates, and memories
101
73
  """
102
74
 
103
75
  def __init__(
@@ -105,35 +77,80 @@ class FrameworkLoader:
105
77
  framework_path: Optional[Path] = None,
106
78
  agents_dir: Optional[Path] = None,
107
79
  service_container: Optional[ServiceContainer] = None,
80
+ config: Optional[Dict[str, Any]] = None,
108
81
  ):
109
82
  """
110
- Initialize framework loader.
83
+ Initialize framework loader with modular components.
111
84
 
112
85
  Args:
113
86
  framework_path: Explicit path to framework (auto-detected if None)
114
87
  agents_dir: Custom agents directory (overrides framework agents)
115
88
  service_container: Optional service container for dependency injection
89
+ config: Optional configuration dictionary for API validation and other settings
116
90
  """
117
91
  self.logger = get_logger("framework_loader")
118
92
  self.agents_dir = agents_dir
119
93
  self.framework_version = None
120
94
  self.framework_last_modified = None
95
+ self.config = config or {}
121
96
 
122
- # Use provided container or get global container
97
+ # Validate API keys on startup (before any other initialization)
98
+ self._validate_api_keys()
99
+
100
+ # Initialize service container
123
101
  self.container = service_container or get_global_container()
102
+ self._register_services()
103
+
104
+ # Resolve services from container
105
+ self._cache_manager = self.container.resolve(ICacheManager)
106
+ self._path_resolver = self.container.resolve(IPathResolver)
107
+ self._memory_manager = self.container.resolve(IMemoryManager)
108
+
109
+ # Initialize framework path
110
+ self.framework_path = (
111
+ framework_path or self._path_resolver.detect_framework_path()
112
+ )
113
+
114
+ # Initialize modular components
115
+ self._init_components()
116
+
117
+ # Keep cache TTL constants for backward compatibility
118
+ self._init_cache_ttl()
119
+
120
+ # Load framework content
121
+ self.framework_content = self._load_framework_content()
122
+
123
+ # Initialize agent registry
124
+ self.agent_registry = AgentRegistryAdapter(self.framework_path)
125
+
126
+ # Output style manager (deferred initialization)
127
+ self.output_style_manager = None
124
128
 
125
- # Register services if not already registered
129
+ def _validate_api_keys(self) -> None:
130
+ """Validate API keys if enabled in config."""
131
+ if self.config.get("validate_api_keys", True):
132
+ try:
133
+ self.logger.info("Validating configured API keys...")
134
+ validate_api_keys(config=self.config, strict=True)
135
+ self.logger.info("✅ API key validation completed successfully")
136
+ except ValueError as e:
137
+ self.logger.error(f"❌ API key validation failed: {e}")
138
+ raise
139
+ except Exception as e:
140
+ self.logger.error(f"❌ Unexpected error during API validation: {e}")
141
+ raise
142
+
143
+ def _register_services(self) -> None:
144
+ """Register services in the container if not already registered."""
126
145
  if not self.container.is_registered(ICacheManager):
127
- self.container.register(ICacheManager, CacheManager, True) # singleton=True
146
+ self.container.register(ICacheManager, CacheManager, True)
128
147
 
129
148
  if not self.container.is_registered(IPathResolver):
130
- # PathResolver depends on CacheManager, so resolve it first
131
149
  cache_manager = self.container.resolve(ICacheManager)
132
150
  path_resolver = PathResolver(cache_manager=cache_manager)
133
151
  self.container.register_instance(IPathResolver, path_resolver)
134
152
 
135
153
  if not self.container.is_registered(IMemoryManager):
136
- # MemoryManager depends on both CacheManager and PathResolver
137
154
  cache_manager = self.container.resolve(ICacheManager)
138
155
  path_resolver = self.container.resolve(IPathResolver)
139
156
  memory_manager = MemoryManager(
@@ -141,18 +158,26 @@ class FrameworkLoader:
141
158
  )
142
159
  self.container.register_instance(IMemoryManager, memory_manager)
143
160
 
144
- # Resolve services from container
145
- self._cache_manager = self.container.resolve(ICacheManager)
146
- self._path_resolver = self.container.resolve(IPathResolver)
147
- self._memory_manager = self.container.resolve(IMemoryManager)
148
-
149
- # Initialize framework path using PathResolver
150
- self.framework_path = (
151
- framework_path or self._path_resolver.detect_framework_path()
152
- )
153
-
154
- # Keep TTL constants for backward compatibility
155
- # These are implementation-specific, so we use defaults if not available
161
+ def _init_components(self) -> None:
162
+ """Initialize modular components."""
163
+ # Loaders
164
+ self.file_loader = FileLoader()
165
+ self.packaged_loader = PackagedLoader()
166
+ self.instruction_loader = InstructionLoader(self.framework_path)
167
+ self.agent_loader = AgentLoader(self.framework_path)
168
+
169
+ # Formatters
170
+ self.content_formatter = ContentFormatter()
171
+ self.capability_generator = CapabilityGenerator()
172
+ self.context_generator = ContextGenerator()
173
+
174
+ # Processors
175
+ self.metadata_processor = MetadataProcessor()
176
+ self.template_processor = TemplateProcessor(self.framework_path)
177
+ self.memory_processor = MemoryProcessor()
178
+
179
+ def _init_cache_ttl(self) -> None:
180
+ """Initialize cache TTL constants for backward compatibility."""
156
181
  if hasattr(self._cache_manager, "capabilities_ttl"):
157
182
  self.CAPABILITIES_CACHE_TTL = self._cache_manager.capabilities_ttl
158
183
  self.DEPLOYED_AGENTS_CACHE_TTL = self._cache_manager.deployed_agents_ttl
@@ -165,430 +190,24 @@ class FrameworkLoader:
165
190
  self.METADATA_CACHE_TTL = 60
166
191
  self.MEMORIES_CACHE_TTL = 60
167
192
 
168
- self.framework_content = self._load_framework_content()
169
-
170
- # Initialize agent registry
171
- self.agent_registry = AgentRegistryAdapter(self.framework_path)
172
-
173
- # Initialize output style manager (must be after content is loaded)
174
- self.output_style_manager = None
175
- # Defer initialization until first use to ensure content is loaded
193
+ # === Cache Management Methods (backward compatibility) ===
176
194
 
177
195
  def clear_all_caches(self) -> None:
178
196
  """Clear all caches to force reload on next access."""
179
197
  self._cache_manager.clear_all()
180
198
 
181
199
  def clear_agent_caches(self) -> None:
182
- """Clear agent-related caches (capabilities, deployed agents, metadata)."""
200
+ """Clear agent-related caches."""
183
201
  self._cache_manager.clear_agent_caches()
184
202
 
185
203
  def clear_memory_caches(self) -> None:
186
204
  """Clear memory-related caches."""
187
205
  self._cache_manager.clear_memory_caches()
188
206
 
189
- def _initialize_output_style(self) -> None:
190
- """Initialize output style management and deploy if applicable."""
191
- try:
192
- from claude_mpm.core.output_style_manager import OutputStyleManager
193
-
194
- self.output_style_manager = OutputStyleManager()
195
-
196
- # Log detailed output style status
197
- self._log_output_style_status()
198
-
199
- # Extract and save output style content (pass self to reuse loaded content)
200
- output_style_content = (
201
- self.output_style_manager.extract_output_style_content(
202
- framework_loader=self
203
- )
204
- )
205
- self.output_style_manager.save_output_style(output_style_content)
206
-
207
- # Deploy to Claude Code if supported
208
- deployed = self.output_style_manager.deploy_output_style(
209
- output_style_content
210
- )
211
-
212
- if deployed:
213
- self.logger.info("✅ Output style deployed to Claude Code >= 1.0.83")
214
- else:
215
- self.logger.info(
216
- "📝 Output style will be injected into instructions for older Claude versions"
217
- )
218
-
219
- except Exception as e:
220
- self.logger.warning(f"❌ Failed to initialize output style manager: {e}")
221
- # Continue without output style management
222
-
223
- def _log_output_style_status(self) -> None:
224
- """Log comprehensive output style status information."""
225
- if not self.output_style_manager:
226
- return
227
-
228
- # Claude version detection
229
- claude_version = self.output_style_manager.claude_version
230
- if claude_version:
231
- self.logger.info(f"Claude Code version detected: {claude_version}")
232
-
233
- # Check if version supports output styles
234
- if self.output_style_manager.supports_output_styles():
235
- self.logger.info("✅ Claude Code supports output styles (>= 1.0.83)")
236
-
237
- # Check deployment status
238
- output_style_path = self.output_style_manager.output_style_path
239
- if output_style_path.exists():
240
- self.logger.info(
241
- f"📁 Output style file exists: {output_style_path}"
242
- )
243
- else:
244
- self.logger.info(
245
- f"📝 Output style will be created at: {output_style_path}"
246
- )
247
-
248
- else:
249
- self.logger.info(
250
- f"⚠️ Claude Code {claude_version} does not support output styles (< 1.0.83)"
251
- )
252
- self.logger.info(
253
- "📝 Output style content will be injected into framework instructions"
254
- )
255
- else:
256
- self.logger.info("⚠️ Claude Code not detected or version unknown")
257
- self.logger.info(
258
- "📝 Output style content will be injected into framework instructions as fallback"
259
- )
260
-
261
- def _try_load_file(self, file_path: Path, file_type: str) -> Optional[str]:
262
- """
263
- Try to load a file with error handling.
264
-
265
- Args:
266
- file_path: Path to the file to load
267
- file_type: Description of file type for logging
268
-
269
- Returns:
270
- File content if successful, None otherwise
271
- """
272
- try:
273
- content = file_path.read_text()
274
- if hasattr(self.logger, "level") and self.logger.level <= logging.INFO:
275
- self.logger.info(f"Loaded {file_type} from: {file_path}")
276
-
277
- # Extract metadata if present
278
- import re
279
-
280
- version_match = re.search(r"<!-- FRAMEWORK_VERSION: (\d+) -->", content)
281
- if version_match:
282
- version = version_match.group(
283
- 1
284
- ) # Keep as string to preserve leading zeros
285
- self.logger.info(f"Framework version: {version}")
286
- # Store framework version if this is the main INSTRUCTIONS.md
287
- if "INSTRUCTIONS.md" in str(file_path):
288
- self.framework_version = version
289
-
290
- # Extract modification timestamp
291
- timestamp_match = re.search(r"<!-- LAST_MODIFIED: ([^>]+) -->", content)
292
- if timestamp_match:
293
- timestamp = timestamp_match.group(1).strip()
294
- self.logger.info(f"Last modified: {timestamp}")
295
- # Store timestamp if this is the main INSTRUCTIONS.md
296
- if "INSTRUCTIONS.md" in str(file_path):
297
- self.framework_last_modified = timestamp
298
-
299
- return content
300
- except Exception as e:
301
- if hasattr(self.logger, "level") and self.logger.level <= logging.ERROR:
302
- self.logger.error(f"Failed to load {file_type}: {e}")
303
- return None
304
-
305
- def _load_instructions_file(self, content: Dict[str, Any]) -> None:
306
- """
307
- Load custom INSTRUCTIONS.md from .claude-mpm directories.
308
-
309
- Precedence (highest to lowest):
310
- 1. Project-specific: ./.claude-mpm/INSTRUCTIONS.md
311
- 2. User-specific: ~/.claude-mpm/INSTRUCTIONS.md
312
-
313
- NOTE: We do NOT load CLAUDE.md files since Claude Code already picks them up automatically.
314
- This prevents duplication of instructions.
315
-
316
- Args:
317
- content: Dictionary to update with loaded instructions
318
- """
319
- # Check for project-specific INSTRUCTIONS.md first
320
- project_instructions_path = Path.cwd() / ".claude-mpm" / "INSTRUCTIONS.md"
321
- if project_instructions_path.exists():
322
- loaded_content = self._try_load_file(
323
- project_instructions_path, "project-specific INSTRUCTIONS.md"
324
- )
325
- if loaded_content:
326
- content["custom_instructions"] = loaded_content
327
- content["custom_instructions_level"] = "project"
328
- self.logger.info(
329
- "Using project-specific PM instructions from .claude-mpm/INSTRUCTIONS.md"
330
- )
331
- return
332
-
333
- # Check for user-specific INSTRUCTIONS.md
334
- user_instructions_path = Path.home() / ".claude-mpm" / "INSTRUCTIONS.md"
335
- if user_instructions_path.exists():
336
- loaded_content = self._try_load_file(
337
- user_instructions_path, "user-specific INSTRUCTIONS.md"
338
- )
339
- if loaded_content:
340
- content["custom_instructions"] = loaded_content
341
- content["custom_instructions_level"] = "user"
342
- self.logger.info(
343
- "Using user-specific PM instructions from ~/.claude-mpm/INSTRUCTIONS.md"
344
- )
345
- return
346
-
347
- def _load_workflow_instructions(self, content: Dict[str, Any]) -> None:
348
- """
349
- Load WORKFLOW.md from .claude-mpm directories.
350
-
351
- Precedence (highest to lowest):
352
- 1. Project-specific: ./.claude-mpm/WORKFLOW.md
353
- 2. User-specific: ~/.claude-mpm/WORKFLOW.md
354
- 3. System default: src/claude_mpm/agents/WORKFLOW.md or packaged
355
-
356
- NOTE: We do NOT load from .claude/ directories to avoid conflicts.
357
-
358
- Args:
359
- content: Dictionary to update with workflow instructions
360
- """
361
- # Check for project-specific WORKFLOW.md first (highest priority)
362
- project_workflow_path = Path.cwd() / ".claude-mpm" / "WORKFLOW.md"
363
- if project_workflow_path.exists():
364
- loaded_content = self._try_load_file(
365
- project_workflow_path, "project-specific WORKFLOW.md"
366
- )
367
- if loaded_content:
368
- content["workflow_instructions"] = loaded_content
369
- content["workflow_instructions_level"] = "project"
370
- self.logger.info(
371
- "Using project-specific workflow instructions from .claude-mpm/WORKFLOW.md"
372
- )
373
- return
374
-
375
- # Check for user-specific WORKFLOW.md (medium priority)
376
- user_workflow_path = Path.home() / ".claude-mpm" / "WORKFLOW.md"
377
- if user_workflow_path.exists():
378
- loaded_content = self._try_load_file(
379
- user_workflow_path, "user-specific WORKFLOW.md"
380
- )
381
- if loaded_content:
382
- content["workflow_instructions"] = loaded_content
383
- content["workflow_instructions_level"] = "user"
384
- self.logger.info(
385
- "Using user-specific workflow instructions from ~/.claude-mpm/WORKFLOW.md"
386
- )
387
- return
388
-
389
- # Fall back to system workflow (lowest priority)
390
- if self.framework_path and self.framework_path != Path("__PACKAGED__"):
391
- system_workflow_path = (
392
- self.framework_path / "src" / "claude_mpm" / "agents" / "WORKFLOW.md"
393
- )
394
- if system_workflow_path.exists():
395
- loaded_content = self._try_load_file(
396
- system_workflow_path, "system WORKFLOW.md"
397
- )
398
- if loaded_content:
399
- content["workflow_instructions"] = loaded_content
400
- content["workflow_instructions_level"] = "system"
401
- self.logger.info("Using system workflow instructions")
402
-
403
- def _load_memory_instructions(self, content: Dict[str, Any]) -> None:
404
- """
405
- Load MEMORY.md from .claude-mpm directories.
406
-
407
- Precedence (highest to lowest):
408
- 1. Project-specific: ./.claude-mpm/MEMORY.md
409
- 2. User-specific: ~/.claude-mpm/MEMORY.md
410
- 3. System default: src/claude_mpm/agents/MEMORY.md or packaged
411
-
412
- NOTE: We do NOT load from .claude/ directories to avoid conflicts.
413
-
414
- Args:
415
- content: Dictionary to update with memory instructions
416
- """
417
- # Check for project-specific MEMORY.md first (highest priority)
418
- project_memory_path = Path.cwd() / ".claude-mpm" / "MEMORY.md"
419
- if project_memory_path.exists():
420
- loaded_content = self._try_load_file(
421
- project_memory_path, "project-specific MEMORY.md"
422
- )
423
- if loaded_content:
424
- content["memory_instructions"] = loaded_content
425
- content["memory_instructions_level"] = "project"
426
- self.logger.info(
427
- "Using project-specific memory instructions from .claude-mpm/MEMORY.md"
428
- )
429
- return
430
-
431
- # Check for user-specific MEMORY.md (medium priority)
432
- user_memory_path = Path.home() / ".claude-mpm" / "MEMORY.md"
433
- if user_memory_path.exists():
434
- loaded_content = self._try_load_file(
435
- user_memory_path, "user-specific MEMORY.md"
436
- )
437
- if loaded_content:
438
- content["memory_instructions"] = loaded_content
439
- content["memory_instructions_level"] = "user"
440
- self.logger.info(
441
- "Using user-specific memory instructions from ~/.claude-mpm/MEMORY.md"
442
- )
443
- return
444
-
445
- # Fall back to system memory instructions (lowest priority)
446
- if self.framework_path and self.framework_path != Path("__PACKAGED__"):
447
- system_memory_path = (
448
- self.framework_path / "src" / "claude_mpm" / "agents" / "MEMORY.md"
449
- )
450
- if system_memory_path.exists():
451
- loaded_content = self._try_load_file(
452
- system_memory_path, "system MEMORY.md"
453
- )
454
- if loaded_content:
455
- content["memory_instructions"] = loaded_content
456
- content["memory_instructions_level"] = "system"
457
- self.logger.info("Using system memory instructions")
458
-
459
- def _get_deployed_agents(self) -> set:
460
- """
461
- Get a set of deployed agent names from .claude/agents/ directories.
462
- Uses caching to avoid repeated filesystem scans.
463
-
464
- Returns:
465
- Set of agent names (file stems) that are deployed
466
- """
467
- # Try to get from cache first
468
- cached = self._cache_manager.get_deployed_agents()
469
- if cached is not None:
470
- return cached
471
-
472
- # Cache miss or expired - perform actual scan
473
- self.logger.debug("Scanning for deployed agents (cache miss or expired)")
474
- deployed = set()
475
-
476
- # Check multiple locations for deployed agents
477
- agents_dirs = [
478
- Path.cwd() / ".claude" / "agents", # Project-specific agents
479
- Path.home() / ".claude" / "agents", # User's system agents
480
- ]
481
-
482
- for agents_dir in agents_dirs:
483
- if agents_dir.exists():
484
- for agent_file in agents_dir.glob("*.md"):
485
- if not agent_file.name.startswith("."):
486
- # Use stem to get agent name without extension
487
- deployed.add(agent_file.stem)
488
- self.logger.debug(
489
- f"Found deployed agent: {agent_file.stem} in {agents_dir}"
490
- )
491
-
492
- self.logger.debug(f"Total deployed agents found: {len(deployed)}")
493
-
494
- # Update cache
495
- self._cache_manager.set_deployed_agents(deployed)
496
-
497
- return deployed
498
-
499
- def _load_actual_memories(self, content: Dict[str, Any]) -> None:
500
- """
501
- Load actual memories using the MemoryManager service.
502
-
503
- This method delegates all memory loading operations to the MemoryManager,
504
- which handles caching, aggregation, deduplication, and legacy format migration.
505
-
506
- Args:
507
- content: Dictionary to update with actual memories
508
- """
509
- # Use MemoryManager to load all memories
510
- memories = self._memory_manager.load_memories()
511
-
512
- # Apply loaded memories to content
513
- if "actual_memories" in memories:
514
- content["actual_memories"] = memories["actual_memories"]
515
- if "agent_memories" in memories:
516
- content["agent_memories"] = memories["agent_memories"]
517
-
518
- def _load_single_agent(
519
- self, agent_file: Path
520
- ) -> tuple[Optional[str], Optional[str]]:
521
- """
522
- Load a single agent file.
523
-
524
- Args:
525
- agent_file: Path to the agent file
526
-
527
- Returns:
528
- Tuple of (agent_name, agent_content) or (None, None) on failure
529
- """
530
- try:
531
- agent_name = agent_file.stem
532
- # Skip README files
533
- if agent_name.upper() == "README":
534
- return None, None
535
- content = agent_file.read_text()
536
- self.logger.debug(f"Loaded agent: {agent_name}")
537
- return agent_name, content
538
- except Exception as e:
539
- self.logger.error(f"Failed to load agent {agent_file}: {e}")
540
- return None, None
541
-
542
- def _load_base_agent_fallback(
543
- self, content: Dict[str, Any], main_dir: Optional[Path]
544
- ) -> None:
545
- """
546
- Load base_agent.md from main directory as fallback.
547
-
548
- Args:
549
- content: Dictionary to update with base agent
550
- main_dir: Main agents directory path
551
- """
552
- if main_dir and main_dir.exists() and "base_agent" not in content["agents"]:
553
- base_agent_file = main_dir / "base_agent.md"
554
- if base_agent_file.exists():
555
- agent_name, agent_content = self._load_single_agent(base_agent_file)
556
- if agent_name and agent_content:
557
- content["agents"][agent_name] = agent_content
558
-
559
- def _load_agents_directory(
560
- self,
561
- content: Dict[str, Any],
562
- agents_dir: Optional[Path],
563
- templates_dir: Optional[Path],
564
- main_dir: Optional[Path],
565
- ) -> None:
566
- """
567
- Load agent definitions from the appropriate directory.
568
-
569
- Args:
570
- content: Dictionary to update with loaded agents
571
- agents_dir: Primary agents directory to load from
572
- templates_dir: Templates directory path
573
- main_dir: Main agents directory path
574
- """
575
- if not agents_dir or not agents_dir.exists():
576
- return
577
-
578
- content["loaded"] = True
579
-
580
- # Load all agent files
581
- for agent_file in agents_dir.glob("*.md"):
582
- agent_name, agent_content = self._load_single_agent(agent_file)
583
- if agent_name and agent_content:
584
- content["agents"][agent_name] = agent_content
585
-
586
- # If we used templates dir, also check main dir for base_agent.md
587
- if agents_dir == templates_dir:
588
- self._load_base_agent_fallback(content, main_dir)
207
+ # === Content Loading Methods ===
589
208
 
590
209
  def _load_framework_content(self) -> Dict[str, Any]:
591
- """Load framework content."""
210
+ """Load framework content using modular components."""
592
211
  content = {
593
212
  "claude_md": "",
594
213
  "agents": {},
@@ -597,242 +216,102 @@ class FrameworkLoader:
597
216
  "working_claude_md": "",
598
217
  "framework_instructions": "",
599
218
  "workflow_instructions": "",
600
- "workflow_instructions_level": "", # Track source level
219
+ "workflow_instructions_level": "",
601
220
  "memory_instructions": "",
602
- "memory_instructions_level": "", # Track source level
603
- "project_workflow": "", # Deprecated, use workflow_instructions_level
604
- "project_memory": "", # Deprecated, use memory_instructions_level
605
- "actual_memories": "", # Add field for actual memories from PM_memories.md
221
+ "memory_instructions_level": "",
222
+ "project_workflow": "", # Deprecated
223
+ "project_memory": "", # Deprecated
224
+ "actual_memories": "",
225
+ "agent_memories": {},
606
226
  }
607
227
 
608
- # Load instructions file from working directory
609
- self._load_instructions_file(content)
228
+ # Load all instructions
229
+ self.instruction_loader.load_all_instructions(content)
610
230
 
611
- if not self.framework_path:
612
- return content
231
+ # Transfer metadata from loaders
232
+ if self.file_loader.framework_version:
233
+ self.framework_version = self.file_loader.framework_version
234
+ content["version"] = self.framework_version
235
+ if self.file_loader.framework_last_modified:
236
+ self.framework_last_modified = self.file_loader.framework_last_modified
613
237
 
614
- # Check if this is a packaged installation
615
- if self.framework_path == Path("__PACKAGED__"):
616
- # Load files using importlib.resources for packaged installations
617
- self._load_packaged_framework_content(content)
618
- else:
619
- # Load from filesystem for development mode
620
- # Load framework's INSTRUCTIONS.md
621
- framework_instructions_path = (
622
- self.framework_path
623
- / "src"
624
- / "claude_mpm"
625
- / "agents"
626
- / "INSTRUCTIONS.md"
627
- )
628
- if framework_instructions_path.exists():
629
- loaded_content = self._try_load_file(
630
- framework_instructions_path, "framework INSTRUCTIONS.md"
631
- )
632
- if loaded_content:
633
- content["framework_instructions"] = loaded_content
634
- content["loaded"] = True
635
- # Add framework version to content
636
- if self.framework_version:
637
- content["instructions_version"] = self.framework_version
638
- content["version"] = (
639
- self.framework_version
640
- ) # Update main version key
641
- # Add modification timestamp to content
642
- if self.framework_last_modified:
643
- content["instructions_last_modified"] = (
644
- self.framework_last_modified
645
- )
646
-
647
- # Load BASE_PM.md for core framework requirements
648
- base_pm_path = (
649
- self.framework_path / "src" / "claude_mpm" / "agents" / "BASE_PM.md"
650
- )
651
- if base_pm_path.exists():
652
- base_pm_content = self._try_load_file(
653
- base_pm_path, "BASE_PM framework requirements"
654
- )
655
- if base_pm_content:
656
- content["base_pm_instructions"] = base_pm_content
657
-
658
- # Load WORKFLOW.md - check for project-specific first, then system
659
- self._load_workflow_instructions(content)
660
-
661
- # Load MEMORY.md - check for project-specific first, then system
662
- self._load_memory_instructions(content)
663
-
664
- # Load actual memories from .claude-mpm/memories/PM_memories.md
238
+ # Load memories
665
239
  self._load_actual_memories(content)
666
240
 
667
- # Discover agent directories using PathResolver
241
+ # Discover and load agents
668
242
  agents_dir, templates_dir, main_dir = self._path_resolver.discover_agent_paths(
669
243
  agents_dir=self.agents_dir, framework_path=self.framework_path
670
244
  )
671
-
672
- # Load agents from discovered directory
673
- self._load_agents_directory(content, agents_dir, templates_dir, main_dir)
245
+ agents = self.agent_loader.load_agents_directory(
246
+ agents_dir, templates_dir, main_dir
247
+ )
248
+ if agents:
249
+ content["agents"] = agents
250
+ content["loaded"] = True
674
251
 
675
252
  return content
676
253
 
677
- def _load_packaged_framework_content(self, content: Dict[str, Any]) -> None:
678
- """Load framework content from packaged installation using importlib.resources."""
679
- if not files:
680
- self.logger.warning(
681
- "importlib.resources not available, cannot load packaged framework"
682
- )
683
- self.logger.debug(f"files variable is: {files}")
684
- # Try alternative import methods
685
- try:
686
- from importlib import resources
687
-
688
- self.logger.info("Using importlib.resources as fallback")
689
- self._load_packaged_framework_content_fallback(content, resources)
690
- return
691
- except ImportError:
692
- self.logger.error(
693
- "No importlib.resources available, using minimal framework"
694
- )
695
- return
696
-
697
- try:
698
- # Load INSTRUCTIONS.md
699
- instructions_content = self._load_packaged_file("INSTRUCTIONS.md")
700
- if instructions_content:
701
- content["framework_instructions"] = instructions_content
702
- content["loaded"] = True
703
- # Extract and store version/timestamp metadata
704
- self._extract_metadata_from_content(
705
- instructions_content, "INSTRUCTIONS.md"
706
- )
707
- if self.framework_version:
708
- content["instructions_version"] = self.framework_version
709
- content["version"] = self.framework_version
710
- if self.framework_last_modified:
711
- content["instructions_last_modified"] = self.framework_last_modified
712
-
713
- # Load BASE_PM.md
714
- base_pm_content = self._load_packaged_file("BASE_PM.md")
715
- if base_pm_content:
716
- content["base_pm_instructions"] = base_pm_content
717
-
718
- # Load WORKFLOW.md
719
- workflow_content = self._load_packaged_file("WORKFLOW.md")
720
- if workflow_content:
721
- content["workflow_instructions"] = workflow_content
722
- content["project_workflow"] = "system"
723
-
724
- # Load MEMORY.md
725
- memory_content = self._load_packaged_file("MEMORY.md")
726
- if memory_content:
727
- content["memory_instructions"] = memory_content
728
- content["project_memory"] = "system"
254
+ def _load_actual_memories(self, content: Dict[str, Any]) -> None:
255
+ """Load actual memories using the MemoryManager service."""
256
+ memories = self._memory_manager.load_memories()
729
257
 
730
- except Exception as e:
731
- self.logger.error(f"Failed to load packaged framework content: {e}")
258
+ if "actual_memories" in memories:
259
+ content["actual_memories"] = memories["actual_memories"]
260
+ if "agent_memories" in memories:
261
+ content["agent_memories"] = memories["agent_memories"]
732
262
 
733
- def _load_packaged_framework_content_fallback(
734
- self, content: Dict[str, Any], resources
735
- ) -> None:
736
- """Load framework content using importlib.resources fallback."""
737
- try:
738
- # Load INSTRUCTIONS.md
739
- instructions_content = self._load_packaged_file_fallback(
740
- "INSTRUCTIONS.md", resources
741
- )
742
- if instructions_content:
743
- content["framework_instructions"] = instructions_content
744
- content["loaded"] = True
745
- # Extract and store version/timestamp metadata
746
- self._extract_metadata_from_content(
747
- instructions_content, "INSTRUCTIONS.md"
748
- )
749
- if self.framework_version:
750
- content["instructions_version"] = self.framework_version
751
- content["version"] = self.framework_version
752
- if self.framework_last_modified:
753
- content["instructions_last_modified"] = self.framework_last_modified
754
-
755
- # Load BASE_PM.md
756
- base_pm_content = self._load_packaged_file_fallback("BASE_PM.md", resources)
757
- if base_pm_content:
758
- content["base_pm_instructions"] = base_pm_content
759
-
760
- # Load WORKFLOW.md
761
- workflow_content = self._load_packaged_file_fallback(
762
- "WORKFLOW.md", resources
763
- )
764
- if workflow_content:
765
- content["workflow_instructions"] = workflow_content
766
- content["project_workflow"] = "system"
263
+ # === Agent Discovery Methods ===
767
264
 
768
- # Load MEMORY.md
769
- memory_content = self._load_packaged_file_fallback("MEMORY.md", resources)
770
- if memory_content:
771
- content["memory_instructions"] = memory_content
772
- content["project_memory"] = "system"
265
+ def _get_deployed_agents(self) -> Set[str]:
266
+ """Get deployed agents with caching."""
267
+ cached = self._cache_manager.get_deployed_agents()
268
+ if cached is not None:
269
+ return cached
773
270
 
774
- except Exception as e:
775
- self.logger.error(
776
- f"Failed to load packaged framework content with fallback: {e}"
777
- )
271
+ deployed = self.agent_loader.get_deployed_agents()
272
+ self._cache_manager.set_deployed_agents(deployed)
273
+ return deployed
778
274
 
779
- def _load_packaged_file_fallback(self, filename: str, resources) -> Optional[str]:
780
- """Load a file from the packaged installation using importlib.resources fallback."""
781
- try:
782
- # Try different resource loading methods
783
- try:
784
- # Method 1: resources.read_text (Python 3.9+)
785
- content = resources.read_text("claude_mpm.agents", filename)
786
- self.logger.info(f"Loaded {filename} from package using read_text")
787
- return content
788
- except AttributeError:
789
- # Method 2: resources.files (Python 3.9+)
790
- agents_files = resources.files("claude_mpm.agents")
791
- file_path = agents_files / filename
792
- if file_path.is_file():
793
- content = file_path.read_text()
794
- self.logger.info(f"Loaded {filename} from package using files")
795
- return content
796
- self.logger.warning(f"File {filename} not found in package")
797
- return None
798
- except Exception as e:
799
- self.logger.error(
800
- f"Failed to load {filename} from package with fallback: {e}"
801
- )
802
- return None
275
+ def _discover_local_json_templates(self) -> Dict[str, Dict[str, Any]]:
276
+ """Discover local JSON agent templates."""
277
+ return self.agent_loader.discover_local_json_templates()
803
278
 
804
- def _load_packaged_file(self, filename: str) -> Optional[str]:
805
- """Load a file from the packaged installation."""
806
- try:
807
- # Use importlib.resources to load file from package
808
- agents_package = files("claude_mpm.agents")
809
- file_path = agents_package / filename
810
-
811
- if file_path.is_file():
812
- content = file_path.read_text()
813
- self.logger.info(f"Loaded {filename} from package")
814
- return content
815
- self.logger.warning(f"File {filename} not found in package")
816
- return None
817
- except Exception as e:
818
- self.logger.error(f"Failed to load {filename} from package: {e}")
819
- return None
820
-
821
- def _extract_metadata_from_content(self, content: str, filename: str) -> None:
822
- """Extract metadata from content string."""
823
- import re
279
+ def _parse_agent_metadata(self, agent_file: Path) -> Optional[Dict[str, Any]]:
280
+ """Parse agent metadata with caching."""
281
+ cache_key = str(agent_file)
282
+ file_mtime = agent_file.stat().st_mtime
283
+
284
+ # Try cache first
285
+ cached_result = self._cache_manager.get_agent_metadata(cache_key)
286
+ if cached_result is not None:
287
+ cached_data, cached_mtime = cached_result
288
+ if cached_mtime == file_mtime:
289
+ self.logger.debug(f"Using cached metadata for {agent_file.name}")
290
+ return cached_data
291
+
292
+ # Cache miss - parse the file
293
+ agent_data = self.metadata_processor.parse_agent_metadata(agent_file)
294
+
295
+ # Add routing information if not present
296
+ if agent_data and "routing" not in agent_data:
297
+ template_data = self.template_processor.load_template(agent_file.stem)
298
+ if template_data:
299
+ routing = self.template_processor.extract_routing(template_data)
300
+ if routing:
301
+ agent_data["routing"] = routing
302
+ memory_routing = self.template_processor.extract_memory_routing(
303
+ template_data
304
+ )
305
+ if memory_routing:
306
+ agent_data["memory_routing"] = memory_routing
307
+
308
+ # Cache the result
309
+ if agent_data:
310
+ self._cache_manager.set_agent_metadata(cache_key, agent_data, file_mtime)
824
311
 
825
- # Extract version
826
- version_match = re.search(r"<!-- FRAMEWORK_VERSION: (\d+) -->", content)
827
- if version_match and "INSTRUCTIONS.md" in filename:
828
- self.framework_version = version_match.group(1)
829
- self.logger.info(f"Framework version: {self.framework_version}")
312
+ return agent_data
830
313
 
831
- # Extract timestamp
832
- timestamp_match = re.search(r"<!-- LAST_MODIFIED: ([^>]+) -->", content)
833
- if timestamp_match and "INSTRUCTIONS.md" in filename:
834
- self.framework_last_modified = timestamp_match.group(1).strip()
835
- self.logger.info(f"Last modified: {self.framework_last_modified}")
314
+ # === Framework Instructions Generation ===
836
315
 
837
316
  def get_framework_instructions(self) -> str:
838
317
  """
@@ -841,1010 +320,221 @@ class FrameworkLoader:
841
320
  Returns:
842
321
  Complete framework instructions ready for injection
843
322
  """
844
- # Import LogManager for prompt logging
845
- try:
846
- from .log_manager import get_log_manager
847
-
848
- log_manager = get_log_manager()
849
- except ImportError:
850
- log_manager = None
323
+ # Log the system prompt if needed
324
+ self._log_system_prompt()
851
325
 
852
326
  # Generate the instructions
853
327
  if self.framework_content["loaded"]:
854
- # Build framework from components
855
- instructions = self._format_full_framework()
856
- else:
857
- # Use minimal fallback
858
- instructions = self._format_minimal_framework()
859
-
860
- # Log the system prompt if LogManager is available
861
- if log_manager:
862
- try:
863
- import asyncio
864
- import os
865
-
866
- # Get or create event loop
867
- try:
868
- loop = asyncio.get_running_loop()
869
- except RuntimeError:
870
- loop = asyncio.new_event_loop()
871
- asyncio.set_event_loop(loop)
872
-
873
- # Prepare metadata
874
- metadata = {
875
- "framework_version": self.framework_version,
876
- "framework_loaded": self.framework_content.get("loaded", False),
877
- "session_id": os.environ.get("CLAUDE_SESSION_ID", "unknown"),
878
- "instructions_length": len(instructions),
879
- }
880
-
881
- # Log the prompt asynchronously
882
- if loop.is_running():
883
- asyncio.create_task(
884
- log_manager.log_prompt("system_prompt", instructions, metadata)
885
- )
886
- else:
887
- loop.run_until_complete(
888
- log_manager.log_prompt("system_prompt", instructions, metadata)
889
- )
890
-
891
- self.logger.debug("System prompt logged to prompts directory")
892
- except Exception as e:
893
- self.logger.debug(f"Could not log system prompt: {e}")
894
-
895
- return instructions
896
-
897
- def _strip_metadata_comments(self, content: str) -> str:
898
- """Strip metadata HTML comments from content.
899
-
900
- Removes comments like:
901
- <!-- FRAMEWORK_VERSION: 0010 -->
902
- <!-- LAST_MODIFIED: 2025-08-10T00:00:00Z -->
903
- """
904
- import re
905
-
906
- # Remove HTML comments that contain metadata
907
- cleaned = re.sub(
908
- r"<!--\s*(FRAMEWORK_VERSION|LAST_MODIFIED|WORKFLOW_VERSION|PROJECT_WORKFLOW_VERSION|CUSTOM_PROJECT_WORKFLOW)[^>]*-->\n?",
909
- "",
910
- content,
911
- )
912
- # Also remove any leading blank lines that might result
913
- return cleaned.lstrip("\n")
328
+ return self._format_full_framework()
329
+ return self._format_minimal_framework()
914
330
 
915
331
  def _format_full_framework(self) -> str:
916
- """Format full framework instructions."""
917
-
918
- # Initialize output style manager on first use (ensures content is loaded)
332
+ """Format full framework instructions using modular components."""
333
+ # Initialize output style manager on first use
919
334
  if self.output_style_manager is None:
920
335
  self._initialize_output_style()
921
336
 
922
- # Check if we need to inject output style content for older Claude versions
337
+ # Check if we need to inject output style
923
338
  inject_output_style = False
339
+ output_style_content = None
924
340
  if self.output_style_manager:
925
341
  inject_output_style = self.output_style_manager.should_inject_content()
926
342
  if inject_output_style:
927
- self.logger.info(
928
- "Injecting output style content into instructions for Claude < 1.0.83"
929
- )
930
-
931
- # If we have the full framework INSTRUCTIONS.md, use it
932
- if self.framework_content.get("framework_instructions"):
933
- instructions = self._strip_metadata_comments(
934
- self.framework_content["framework_instructions"]
935
- )
936
-
937
- # Note: We don't add working directory CLAUDE.md here since Claude Code
938
- # already picks it up automatically. This prevents duplication.
939
-
940
- # Add custom INSTRUCTIONS.md if present (overrides or extends framework instructions)
941
- if self.framework_content.get("custom_instructions"):
942
- level = self.framework_content.get(
943
- "custom_instructions_level", "unknown"
944
- )
945
- instructions += f"\n\n## Custom PM Instructions ({level} level)\n\n"
946
- instructions += "**The following custom instructions override or extend the framework defaults:**\n\n"
947
- instructions += self._strip_metadata_comments(
948
- self.framework_content["custom_instructions"]
949
- )
950
- instructions += "\n"
951
-
952
- # Add WORKFLOW.md after instructions
953
- if self.framework_content.get("workflow_instructions"):
954
- workflow_content = self._strip_metadata_comments(
955
- self.framework_content["workflow_instructions"]
956
- )
957
- level = self.framework_content.get(
958
- "workflow_instructions_level", "system"
959
- )
960
- if level != "system":
961
- instructions += f"\n\n## Workflow Instructions ({level} level)\n\n"
962
- instructions += "**The following workflow instructions override system defaults:**\n\n"
963
- instructions += f"{workflow_content}\n"
964
-
965
- # Add MEMORY.md after workflow instructions
966
- if self.framework_content.get("memory_instructions"):
967
- memory_content = self._strip_metadata_comments(
968
- self.framework_content["memory_instructions"]
969
- )
970
- level = self.framework_content.get(
971
- "memory_instructions_level", "system"
972
- )
973
- if level != "system":
974
- instructions += f"\n\n## Memory Instructions ({level} level)\n\n"
975
- instructions += "**The following memory instructions override system defaults:**\n\n"
976
- instructions += f"{memory_content}\n"
977
-
978
- # Add actual PM memories after memory instructions
979
- if self.framework_content.get("actual_memories"):
980
- instructions += "\n\n## Current PM Memories\n\n"
981
- instructions += "**The following are your accumulated memories and knowledge from this project:**\n\n"
982
- instructions += self.framework_content["actual_memories"]
983
- instructions += "\n"
984
-
985
- # Add agent memories if available
986
- if self.framework_content.get("agent_memories"):
987
- agent_memories = self.framework_content["agent_memories"]
988
- if agent_memories:
989
- instructions += "\n\n## Agent Memories\n\n"
990
- instructions += "**The following are accumulated memories from specialized agents:**\n\n"
991
-
992
- for agent_name in sorted(agent_memories.keys()):
993
- memory_content = agent_memories[agent_name]
994
- if memory_content:
995
- instructions += f"### {agent_name.replace('_', ' ').title()} Agent Memory\n\n"
996
- instructions += memory_content
997
- instructions += "\n\n"
998
-
999
- # Add dynamic agent capabilities section
1000
- instructions += self._generate_agent_capabilities_section()
1001
-
1002
- # Add enhanced temporal and user context for better awareness
1003
- instructions += self._generate_temporal_user_context()
1004
-
1005
- # Add BASE_PM.md framework requirements AFTER INSTRUCTIONS.md
1006
- if self.framework_content.get("base_pm_instructions"):
1007
- base_pm = self._strip_metadata_comments(
1008
- self.framework_content["base_pm_instructions"]
1009
- )
1010
- instructions += f"\n\n{base_pm}"
1011
-
1012
- # Inject output style content if needed (for Claude < 1.0.83)
1013
- if inject_output_style and self.output_style_manager:
1014
343
  output_style_content = self.output_style_manager.get_injectable_content(
1015
344
  framework_loader=self
1016
345
  )
1017
- if output_style_content:
1018
- instructions += "\n\n## Output Style Configuration\n"
1019
- instructions += "**Note: The following output style is injected for Claude < 1.0.83**\n\n"
1020
- instructions += output_style_content
1021
- instructions += "\n"
1022
-
1023
- # Clean up any trailing whitespace
1024
- return instructions.rstrip() + "\n"
1025
-
1026
- # Otherwise fall back to generating framework
1027
- instructions = """# Claude MPM Framework Instructions
1028
-
1029
- You are operating within the Claude Multi-Agent Project Manager (MPM) framework.
1030
-
1031
- ## Core Role
1032
- You are a multi-agent orchestrator. Your primary responsibilities are:
1033
- - Delegate all implementation work to specialized agents via Task Tool
1034
- - Coordinate multi-agent workflows and cross-agent collaboration
1035
- - Extract and track TODO/BUG/FEATURE items for ticket creation
1036
- - Maintain project visibility and strategic oversight
1037
- - NEVER perform direct implementation work yourself
1038
-
1039
- """
1040
-
1041
- # Note: We don't add working directory CLAUDE.md here since Claude Code
1042
- # already picks it up automatically. This prevents duplication.
1043
-
1044
- # Add agent definitions
1045
- if self.framework_content["agents"]:
1046
- instructions += "## Available Agents\n\n"
1047
- instructions += "You have the following specialized agents available for delegation:\n\n"
1048
-
1049
- # List agents with brief descriptions and correct IDs
1050
- agent_list = []
1051
- for agent_name in sorted(self.framework_content["agents"].keys()):
1052
- # Use the actual agent_name as the ID (it's the filename stem)
1053
- agent_id = agent_name
1054
- clean_name = agent_name.replace("-", " ").replace("_", " ").title()
1055
- if (
1056
- "engineer" in agent_name.lower()
1057
- and "data" not in agent_name.lower()
1058
- ):
1059
- agent_list.append(
1060
- f"- **Engineer Agent** (`{agent_id}`): Code implementation and development"
1061
- )
1062
- elif "qa" in agent_name.lower():
1063
- agent_list.append(
1064
- f"- **QA Agent** (`{agent_id}`): Testing and quality assurance"
1065
- )
1066
- elif "documentation" in agent_name.lower():
1067
- agent_list.append(
1068
- f"- **Documentation Agent** (`{agent_id}`): Documentation creation and maintenance"
1069
- )
1070
- elif "research" in agent_name.lower():
1071
- agent_list.append(
1072
- f"- **Research Agent** (`{agent_id}`): Investigation and analysis"
1073
- )
1074
- elif "security" in agent_name.lower():
1075
- agent_list.append(
1076
- f"- **Security Agent** (`{agent_id}`): Security analysis and protection"
1077
- )
1078
- elif "version" in agent_name.lower():
1079
- agent_list.append(
1080
- f"- **Version Control Agent** (`{agent_id}`): Git operations and version management"
1081
- )
1082
- elif "ops" in agent_name.lower():
1083
- agent_list.append(
1084
- f"- **Ops Agent** (`{agent_id}`): Deployment and operations"
1085
- )
1086
- elif "data" in agent_name.lower():
1087
- agent_list.append(
1088
- f"- **Data Engineer Agent** (`{agent_id}`): Data management and AI API integration"
1089
- )
1090
- else:
1091
- agent_list.append(
1092
- f"- **{clean_name}** (`{agent_id}`): Available for specialized tasks"
1093
- )
346
+ self.logger.info("Injecting output style content for Claude < 1.0.83")
1094
347
 
1095
- instructions += "\n".join(agent_list) + "\n\n"
1096
-
1097
- # Add full agent details
1098
- instructions += "### Agent Details\n\n"
1099
- for agent_name, agent_content in sorted(
1100
- self.framework_content["agents"].items()
1101
- ):
1102
- instructions += f"#### {agent_name.replace('-', ' ').title()}\n"
1103
- instructions += agent_content + "\n\n"
1104
-
1105
- # Add orchestration principles
1106
- instructions += """
1107
- ## Orchestration Principles
1108
- 1. **Always Delegate**: Never perform direct work - use Task Tool for all implementation
1109
- 2. **Comprehensive Context**: Provide rich, filtered context to each agent
1110
- 3. **Track Everything**: Extract all TODO/BUG/FEATURE items systematically
1111
- 4. **Cross-Agent Coordination**: Orchestrate workflows spanning multiple agents
1112
- 5. **Results Integration**: Actively receive and integrate agent results
1113
-
1114
- ## Task Tool Format
1115
- ```
1116
- **[Agent Name]**: [Clear task description with deliverables]
1117
-
1118
- TEMPORAL CONTEXT: Today is [date]. Apply date awareness to [specific considerations].
1119
-
1120
- **Task**: [Detailed task breakdown]
1121
- 1. [Specific action item 1]
1122
- 2. [Specific action item 2]
1123
- 3. [Specific action item 3]
1124
-
1125
- **Context**: [Comprehensive filtered context for this agent]
1126
- **Authority**: [Agent's decision-making scope]
1127
- **Expected Results**: [Specific deliverables needed]
1128
- **Integration**: [How results integrate with other work]
1129
- ```
1130
-
1131
- ## Ticket Extraction Patterns
1132
- Extract tickets from these patterns:
1133
- - TODO: [description] → TODO ticket
1134
- - BUG: [description] → BUG ticket
1135
- - FEATURE: [description] → FEATURE ticket
1136
- - ISSUE: [description] → ISSUE ticket
1137
- - FIXME: [description] → BUG ticket
1138
-
1139
- ---
1140
- """
1141
-
1142
- return instructions
348
+ # Generate dynamic sections
349
+ capabilities_section = self._generate_agent_capabilities_section()
350
+ context_section = self.context_generator.generate_temporal_user_context()
1143
351
 
1144
- def _generate_agent_capabilities_section(self) -> str:
1145
- """Generate dynamic agent capabilities section from deployed agents.
1146
- Uses caching to avoid repeated file I/O and parsing operations."""
352
+ # Format the complete framework
353
+ return self.content_formatter.format_full_framework(
354
+ self.framework_content,
355
+ capabilities_section,
356
+ context_section,
357
+ inject_output_style,
358
+ output_style_content,
359
+ )
1147
360
 
1148
- # Try to get from cache first
361
+ def _format_minimal_framework(self) -> str:
362
+ """Format minimal framework instructions."""
363
+ return self.content_formatter.format_minimal_framework(self.framework_content)
364
+
365
+ def _generate_agent_capabilities_section(self) -> str:
366
+ """Generate agent capabilities section with caching."""
367
+ # Try cache first
1149
368
  cached_capabilities = self._cache_manager.get_capabilities()
1150
369
  if cached_capabilities is not None:
1151
370
  return cached_capabilities
1152
371
 
1153
- # Will be used for updating cache later
1154
- current_time = time.time()
1155
-
1156
- # Cache miss or expired - generate capabilities
1157
- self.logger.debug("Generating agent capabilities (cache miss or expired)")
372
+ self.logger.debug("Generating agent capabilities (cache miss)")
1158
373
 
1159
374
  try:
1160
- from pathlib import Path
375
+ # Discover local JSON templates
376
+ local_agents = self._discover_local_json_templates()
1161
377
 
1162
- # Read directly from deployed agents in .claude/agents/
1163
- # Check multiple locations for deployed agents
1164
- # Priority order: project > user home > fallback
378
+ # Get deployed agents from .claude/agents/
379
+ deployed_agents = []
1165
380
  agents_dirs = [
1166
- Path.cwd() / ".claude" / "agents", # Project-specific agents
1167
- Path.home() / ".claude" / "agents", # User's system agents
381
+ Path.cwd() / ".claude" / "agents",
382
+ Path.home() / ".claude" / "agents",
1168
383
  ]
1169
384
 
1170
- # Collect agents from all directories with proper precedence
1171
- # Project agents override user agents with the same name
1172
- all_agents = {} # key: agent_id, value: (agent_data, priority)
1173
-
1174
- for priority, potential_dir in enumerate(agents_dirs):
1175
- if potential_dir.exists() and any(potential_dir.glob("*.md")):
1176
- self.logger.debug(f"Found agents directory at: {potential_dir}")
1177
-
1178
- # Collect agents from this directory
1179
- for agent_file in potential_dir.glob("*.md"):
1180
- if agent_file.name.startswith("."):
1181
- continue
1182
-
1183
- # Parse agent metadata (with caching)
1184
- agent_data = self._parse_agent_metadata(agent_file)
1185
- if agent_data:
1186
- agent_id = agent_data["id"]
1187
- # Only add if not already present (project has priority 0, user has priority 1)
1188
- # Lower priority number wins (project > user)
1189
- if (
1190
- agent_id not in all_agents
1191
- or priority < all_agents[agent_id][1]
1192
- ):
1193
- all_agents[agent_id] = (agent_data, priority)
1194
- self.logger.debug(
1195
- f"Added/Updated agent {agent_id} from {potential_dir} (priority {priority})"
1196
- )
1197
-
1198
- if not all_agents:
1199
- self.logger.warning(f"No agents found in any location: {agents_dirs}")
1200
- result = self._get_fallback_capabilities()
1201
- # Cache the fallback result too
1202
- self._cache_manager.set_capabilities(result)
1203
- return result
1204
-
1205
- # Log agent collection summary
1206
- project_agents = [aid for aid, (_, pri) in all_agents.items() if pri == 0]
1207
- user_agents = [aid for aid, (_, pri) in all_agents.items() if pri == 1]
1208
-
1209
- if project_agents:
1210
- self.logger.info(
1211
- f"Loaded {len(project_agents)} project agents: {', '.join(sorted(project_agents))}"
1212
- )
1213
- if user_agents:
1214
- self.logger.info(
1215
- f"Loaded {len(user_agents)} user agents: {', '.join(sorted(user_agents))}"
1216
- )
1217
-
1218
- # Build capabilities section
1219
- section = "\n\n## Available Agent Capabilities\n\n"
1220
-
1221
- # Extract just the agent data (drop priority info) and sort
1222
- deployed_agents = [agent_data for agent_data, _ in all_agents.values()]
1223
-
1224
- if not deployed_agents:
1225
- result = self._get_fallback_capabilities()
1226
- # Cache the fallback result
1227
- self._cache_manager.set_capabilities(result)
1228
- return result
1229
-
1230
- # Sort agents alphabetically by ID
1231
- deployed_agents.sort(key=lambda x: x["id"])
1232
-
1233
- # Display all agents with their rich descriptions
1234
- for agent in deployed_agents:
1235
- # Clean up display name - handle common acronyms
1236
- display_name = agent["display_name"]
1237
- display_name = (
1238
- display_name.replace("Qa ", "QA ")
1239
- .replace("Ui ", "UI ")
1240
- .replace("Api ", "API ")
1241
- )
1242
- if display_name.lower() == "qa agent":
1243
- display_name = "QA Agent"
1244
-
1245
- section += f"\n### {display_name} (`{agent['id']}`)\n"
1246
- section += f"{agent['description']}\n"
1247
-
1248
- # Add routing information if available
1249
- if agent.get("routing"):
1250
- routing = agent["routing"]
1251
-
1252
- # Format routing hints for PM usage
1253
- routing_hints = []
1254
-
1255
- if routing.get("keywords"):
1256
- # Show first 5 keywords for brevity
1257
- keywords = routing["keywords"][:5]
1258
- routing_hints.append(f"Keywords: {', '.join(keywords)}")
1259
-
1260
- if routing.get("paths"):
1261
- # Show first 3 paths for brevity
1262
- paths = routing["paths"][:3]
1263
- routing_hints.append(f"Paths: {', '.join(paths)}")
1264
-
1265
- if routing.get("priority"):
1266
- routing_hints.append(f"Priority: {routing['priority']}")
1267
-
1268
- if routing_hints:
1269
- section += f"- **Routing**: {' | '.join(routing_hints)}\n"
1270
-
1271
- # Add when_to_use if present
1272
- if routing.get("when_to_use"):
1273
- section += f"- **When to use**: {routing['when_to_use']}\n"
1274
-
1275
- # Add any additional metadata if present
1276
- if agent.get("authority"):
1277
- section += f"- **Authority**: {agent['authority']}\n"
1278
- if agent.get("primary_function"):
1279
- section += f"- **Primary Function**: {agent['primary_function']}\n"
1280
- if agent.get("handoff_to"):
1281
- section += f"- **Handoff To**: {agent['handoff_to']}\n"
1282
- if agent.get("tools") and agent["tools"] != "standard":
1283
- section += f"- **Tools**: {agent['tools']}\n"
1284
- if agent.get("model") and agent["model"] != "opus":
1285
- section += f"- **Model**: {agent['model']}\n"
1286
-
1287
- # Add memory routing information if available
1288
- if agent.get("memory_routing"):
1289
- memory_routing = agent["memory_routing"]
1290
- if memory_routing.get("description"):
1291
- section += (
1292
- f"- **Memory Routing**: {memory_routing['description']}\n"
1293
- )
1294
-
1295
- # Add simple Context-Aware Agent Selection
1296
- section += "\n## Context-Aware Agent Selection\n\n"
1297
- section += (
1298
- "Select agents based on their descriptions above. Key principles:\n"
1299
- )
1300
- section += "- **PM questions** → Answer directly (only exception)\n"
1301
- section += "- Match task requirements to agent descriptions and authority\n"
1302
- section += "- Consider agent handoff recommendations\n"
1303
- section += (
1304
- "- Use the agent ID in parentheses when delegating via Task tool\n"
385
+ for agents_dir in agents_dirs:
386
+ if agents_dir.exists():
387
+ for agent_file in agents_dir.glob("*.md"):
388
+ if not agent_file.name.startswith("."):
389
+ agent_data = self._parse_agent_metadata(agent_file)
390
+ if agent_data:
391
+ deployed_agents.append(agent_data)
392
+
393
+ # Generate capabilities section
394
+ section = self.capability_generator.generate_capabilities_section(
395
+ deployed_agents, local_agents
1305
396
  )
1306
397
 
1307
- # Add summary
1308
- section += f"\n**Total Available Agents**: {len(deployed_agents)}\n"
1309
-
1310
- # Cache the generated capabilities
398
+ # Cache the result
1311
399
  self._cache_manager.set_capabilities(section)
1312
- self.logger.debug(
1313
- f"Cached agent capabilities section ({len(section)} chars)"
1314
- )
400
+ self.logger.debug(f"Cached agent capabilities ({len(section)} chars)")
1315
401
 
1316
402
  return section
1317
403
 
1318
404
  except Exception as e:
1319
- self.logger.warning(f"Could not generate dynamic agent capabilities: {e}")
1320
- result = self._get_fallback_capabilities()
1321
- # Cache even the fallback result
1322
- self._agent_capabilities_cache = result
1323
- self._agent_capabilities_cache_time = current_time
1324
- return result
405
+ self.logger.warning(f"Could not generate agent capabilities: {e}")
406
+ fallback = self.content_formatter.get_fallback_capabilities()
407
+ self._cache_manager.set_capabilities(fallback)
408
+ return fallback
1325
409
 
1326
- def _generate_temporal_user_context(self) -> str:
1327
- """Generate enhanced temporal and user context for better PM awareness.
1328
-
1329
- Returns:
1330
- str: Formatted context string with datetime, user, and system information
1331
- """
1332
- context_lines = ["\n\n## Temporal & User Context\n"]
410
+ # === Output Style Management ===
1333
411
 
412
+ def _initialize_output_style(self) -> None:
413
+ """Initialize output style management."""
1334
414
  try:
1335
- # Get current datetime with timezone awareness
1336
- now = datetime.now()
1337
-
1338
- # Try to get timezone info - fallback to UTC offset if timezone name not available
1339
- try:
1340
- import time as time_module
1341
-
1342
- if hasattr(time_module, "tzname"):
1343
- tz_name = time_module.tzname[time_module.daylight]
1344
- tz_offset = time_module.strftime("%z")
1345
- if tz_offset:
1346
- # Format UTC offset properly (e.g., -0800 to -08:00)
1347
- tz_offset = (
1348
- f"{tz_offset[:3]}:{tz_offset[3:]}"
1349
- if len(tz_offset) >= 4
1350
- else tz_offset
1351
- )
1352
- tz_info = f"{tz_name} (UTC{tz_offset})"
1353
- else:
1354
- tz_info = tz_name
1355
- else:
1356
- tz_info = "Local Time"
1357
- except Exception:
1358
- tz_info = "Local Time"
415
+ from claude_mpm.core.output_style_manager import OutputStyleManager
1359
416
 
1360
- # Format datetime components
1361
- date_str = now.strftime("%Y-%m-%d")
1362
- time_str = now.strftime("%H:%M:%S")
1363
- day_name = now.strftime("%A")
417
+ self.output_style_manager = OutputStyleManager()
418
+ self._log_output_style_status()
1364
419
 
1365
- context_lines.append(
1366
- f"**Current DateTime**: {date_str} {time_str} {tz_info}\n"
420
+ # Extract and save output style content
421
+ output_style_content = (
422
+ self.output_style_manager.extract_output_style_content(
423
+ framework_loader=self
424
+ )
1367
425
  )
1368
- context_lines.append(f"**Day**: {day_name}\n")
426
+ self.output_style_manager.save_output_style(output_style_content)
1369
427
 
1370
- except Exception as e:
1371
- # Fallback to basic date if enhanced datetime fails
1372
- self.logger.debug(f"Error generating enhanced datetime context: {e}")
1373
- context_lines.append(
1374
- f"**Today's Date**: {datetime.now().strftime('%Y-%m-%d')}\n"
428
+ # Deploy to Claude Code if supported
429
+ deployed = self.output_style_manager.deploy_output_style(
430
+ output_style_content
1375
431
  )
1376
432
 
1377
- try:
1378
- # Get user information with safe fallbacks
1379
- username = None
1380
-
1381
- # Try multiple methods to get username
1382
- methods = [
1383
- lambda: os.environ.get("USER"),
1384
- lambda: os.environ.get("USERNAME"), # Windows fallback
1385
- lambda: getpass.getuser(),
1386
- ]
1387
-
1388
- for method in methods:
1389
- try:
1390
- username = method()
1391
- if username:
1392
- break
1393
- except Exception:
1394
- continue
1395
-
1396
- if username:
1397
- context_lines.append(f"**User**: {username}\n")
1398
-
1399
- # Add home directory if available
1400
- try:
1401
- home_dir = os.path.expanduser("~")
1402
- if home_dir and home_dir != "~":
1403
- context_lines.append(f"**Home Directory**: {home_dir}\n")
1404
- except Exception:
1405
- pass
1406
-
1407
- except Exception as e:
1408
- # User detection is optional, don't fail
1409
- self.logger.debug(f"Could not detect user information: {e}")
1410
-
1411
- try:
1412
- # Get system information
1413
- system_info = platform.system()
1414
- if system_info:
1415
- # Enhance system name for common platforms
1416
- system_names = {
1417
- "Darwin": "Darwin (macOS)",
1418
- "Linux": "Linux",
1419
- "Windows": "Windows",
1420
- }
1421
- system_display = system_names.get(system_info, system_info)
1422
- context_lines.append(f"**System**: {system_display}\n")
1423
-
1424
- # Add platform version if available
1425
- try:
1426
- platform_version = platform.release()
1427
- if platform_version:
1428
- context_lines.append(
1429
- f"**System Version**: {platform_version}\n"
1430
- )
1431
- except Exception:
1432
- pass
433
+ if deployed:
434
+ self.logger.info("✅ Output style deployed to Claude Code >= 1.0.83")
435
+ else:
436
+ self.logger.info("📝 Output style will be injected into instructions")
1433
437
 
1434
438
  except Exception as e:
1435
- # System info is optional
1436
- self.logger.debug(f"Could not detect system information: {e}")
1437
-
1438
- try:
1439
- # Add current working directory
1440
- cwd = os.getcwd()
1441
- if cwd:
1442
- context_lines.append(f"**Working Directory**: {cwd}\n")
1443
- except Exception:
1444
- pass
1445
-
1446
- try:
1447
- # Add locale information if available
1448
- current_locale = locale.getlocale()
1449
- if current_locale and current_locale[0]:
1450
- context_lines.append(f"**Locale**: {current_locale[0]}\n")
1451
- except Exception:
1452
- # Locale is optional
1453
- pass
1454
-
1455
- # Add instruction for applying context
1456
- context_lines.append(
1457
- "\nApply temporal and user awareness to all tasks, "
1458
- "decisions, and interactions.\n"
1459
- )
1460
- context_lines.append(
1461
- "Use this context for personalized responses and "
1462
- "time-sensitive operations.\n"
1463
- )
1464
-
1465
- return "".join(context_lines)
1466
-
1467
- def _parse_agent_metadata(self, agent_file: Path) -> Optional[Dict[str, Any]]:
1468
- """Parse agent metadata from deployed agent file.
1469
- Uses caching based on file path and modification time.
1470
-
1471
- Returns:
1472
- Dictionary with agent metadata directly from YAML frontmatter.
1473
- """
1474
- try:
1475
- # Check cache based on file path and modification time
1476
- cache_key = str(agent_file)
1477
- file_mtime = agent_file.stat().st_mtime
1478
- time.time()
1479
-
1480
- # Try to get from cache first
1481
- cached_result = self._cache_manager.get_agent_metadata(cache_key)
1482
- if cached_result is not None:
1483
- cached_data, cached_mtime = cached_result
1484
- # Use cache if file hasn't been modified and cache isn't too old
1485
- if cached_mtime == file_mtime:
1486
- self.logger.debug(f"Using cached metadata for {agent_file.name}")
1487
- return cached_data
1488
-
1489
- # Cache miss or expired - parse the file
1490
- self.logger.debug(
1491
- f"Parsing metadata for {agent_file.name} (cache miss or expired)"
1492
- )
1493
-
1494
- import yaml
439
+ self.logger.warning(f"❌ Failed to initialize output style manager: {e}")
1495
440
 
1496
- with open(agent_file) as f:
1497
- content = f.read()
441
+ def _log_output_style_status(self) -> None:
442
+ """Log output style status information."""
443
+ if not self.output_style_manager:
444
+ return
1498
445
 
1499
- # Default values
1500
- agent_data = {
1501
- "id": agent_file.stem,
1502
- "display_name": agent_file.stem.replace("_", " ")
1503
- .replace("-", " ")
1504
- .title(),
1505
- "description": "Specialized agent",
1506
- }
446
+ claude_version = self.output_style_manager.claude_version
447
+ if claude_version:
448
+ self.logger.info(f"Claude Code version detected: {claude_version}")
1507
449
 
1508
- # Extract YAML frontmatter if present
1509
- if content.startswith("---"):
1510
- end_marker = content.find("---", 3)
1511
- if end_marker > 0:
1512
- frontmatter = content[3:end_marker]
1513
- metadata = yaml.safe_load(frontmatter)
1514
- if metadata:
1515
- # Use name as ID for Task tool
1516
- agent_data["id"] = metadata.get("name", agent_data["id"])
1517
- agent_data["display_name"] = (
1518
- metadata.get("name", agent_data["display_name"])
1519
- .replace("-", " ")
1520
- .title()
1521
- )
1522
-
1523
- # Copy all metadata fields directly
1524
- for key, value in metadata.items():
1525
- if key not in ["name"]: # Skip already processed fields
1526
- agent_data[key] = value
1527
-
1528
- # IMPORTANT: Do NOT add spaces to tools field - it breaks deployment!
1529
- # Tools must remain as comma-separated without spaces: "Read,Write,Edit"
1530
-
1531
- # Try to load routing metadata from JSON template if not in YAML frontmatter
1532
- if "routing" not in agent_data:
1533
- routing_data = self._load_routing_from_template(agent_file.stem)
1534
- if routing_data:
1535
- agent_data["routing"] = routing_data
1536
-
1537
- # Try to load memory routing metadata from JSON template if not in YAML frontmatter
1538
- if "memory_routing" not in agent_data:
1539
- memory_routing_data = self._load_memory_routing_from_template(
1540
- agent_file.stem
450
+ if self.output_style_manager.supports_output_styles():
451
+ self.logger.info("✅ Claude Code supports output styles (>= 1.0.83)")
452
+ output_style_path = self.output_style_manager.output_style_path
453
+ if output_style_path.exists():
454
+ self.logger.info(
455
+ f"📁 Output style file exists: {output_style_path}"
456
+ )
457
+ else:
458
+ self.logger.info(
459
+ f"📝 Output style will be created at: {output_style_path}"
460
+ )
461
+ else:
462
+ self.logger.info(
463
+ f"⚠️ Claude Code {claude_version} does not support output styles"
1541
464
  )
1542
- if memory_routing_data:
1543
- agent_data["memory_routing"] = memory_routing_data
1544
-
1545
- # Cache the parsed metadata
1546
- self._cache_manager.set_agent_metadata(cache_key, agent_data, file_mtime)
1547
-
1548
- return agent_data
1549
-
1550
- except Exception as e:
1551
- self.logger.debug(f"Could not parse metadata from {agent_file}: {e}")
1552
- return None
1553
-
1554
- def _load_memory_routing_from_template(
1555
- self, agent_name: str
1556
- ) -> Optional[Dict[str, Any]]:
1557
- """Load memory routing metadata from agent JSON template.
465
+ self.logger.info(
466
+ "📝 Output style will be injected into framework instructions"
467
+ )
468
+ else:
469
+ self.logger.info("⚠️ Claude Code not detected or version unknown")
470
+ self.logger.info("📝 Output style will be injected as fallback")
1558
471
 
1559
- Args:
1560
- agent_name: Name of the agent (stem of the file)
472
+ # === Logging Methods ===
1561
473
 
1562
- Returns:
1563
- Dictionary with memory routing metadata or None if not found
1564
- """
474
+ def _log_system_prompt(self) -> None:
475
+ """Log the system prompt if LogManager is available."""
1565
476
  try:
1566
- import json
1567
-
1568
- # Check if we have a framework path
1569
- if not self.framework_path or self.framework_path == Path("__PACKAGED__"):
1570
- # For packaged installations, try to load from package resources
1571
- if files:
1572
- try:
1573
- templates_package = files("claude_mpm.agents.templates")
1574
- template_file = templates_package / f"{agent_name}.json"
1575
-
1576
- if template_file.is_file():
1577
- template_content = template_file.read_text()
1578
- template_data = json.loads(template_content)
1579
- return template_data.get("memory_routing")
1580
- except Exception as e:
1581
- self.logger.debug(
1582
- f"Could not load memory routing from packaged template for {agent_name}: {e}"
1583
- )
1584
- return None
1585
-
1586
- # For development mode, load from filesystem
1587
- templates_dir = (
1588
- self.framework_path / "src" / "claude_mpm" / "agents" / "templates"
1589
- )
1590
- template_file = templates_dir / f"{agent_name}.json"
1591
-
1592
- if template_file.exists():
1593
- with open(template_file) as f:
1594
- template_data = json.load(f)
1595
- return template_data.get("memory_routing")
1596
-
1597
- # Also check for variations in naming (underscore vs dash)
1598
- # Handle common naming variations between deployed .md files and .json templates
1599
- # Remove duplicates by using a set
1600
- alternative_names = list(
1601
- {
1602
- agent_name.replace("-", "_"), # api-qa -> api_qa
1603
- agent_name.replace("_", "-"), # api_qa -> api-qa
1604
- agent_name.replace("-", ""), # api-qa -> apiqa
1605
- agent_name.replace("_", ""), # api_qa -> apiqa
1606
- agent_name.replace("-agent", ""), # research-agent -> research
1607
- agent_name.replace("_agent", ""), # research_agent -> research
1608
- agent_name + "_agent", # research -> research_agent
1609
- agent_name + "-agent", # research -> research-agent
1610
- }
1611
- )
1612
-
1613
- for alt_name in alternative_names:
1614
- if alt_name != agent_name: # Skip the original name we already tried
1615
- alt_file = templates_dir / f"{alt_name}.json"
1616
- if alt_file.exists():
1617
- with open(alt_file) as f:
1618
- template_data = json.load(f)
1619
- return template_data.get("memory_routing")
1620
-
1621
- return None
1622
-
1623
- except Exception as e:
1624
- self.logger.debug(
1625
- f"Could not load memory routing from template for {agent_name}: {e}"
1626
- )
1627
- return None
1628
-
1629
- def _load_routing_from_template(self, agent_name: str) -> Optional[Dict[str, Any]]:
1630
- """Load routing metadata from agent JSON template.
477
+ from .log_manager import get_log_manager
1631
478
 
1632
- Args:
1633
- agent_name: Name of the agent (stem of the file)
479
+ log_manager = get_log_manager()
480
+ except ImportError:
481
+ return
1634
482
 
1635
- Returns:
1636
- Dictionary with routing metadata or None if not found
1637
- """
1638
483
  try:
1639
- import json
1640
-
1641
- # Check if we have a framework path
1642
- if not self.framework_path or self.framework_path == Path("__PACKAGED__"):
1643
- # For packaged installations, try to load from package resources
1644
- if files:
1645
- try:
1646
- templates_package = files("claude_mpm.agents.templates")
1647
- template_file = templates_package / f"{agent_name}.json"
1648
-
1649
- if template_file.is_file():
1650
- template_content = template_file.read_text()
1651
- template_data = json.loads(template_content)
1652
- return template_data.get("routing")
1653
- except Exception as e:
1654
- self.logger.debug(
1655
- f"Could not load routing from packaged template for {agent_name}: {e}"
1656
- )
1657
- return None
1658
-
1659
- # For development mode, load from filesystem
1660
- templates_dir = (
1661
- self.framework_path / "src" / "claude_mpm" / "agents" / "templates"
1662
- )
1663
- template_file = templates_dir / f"{agent_name}.json"
1664
-
1665
- if template_file.exists():
1666
- with open(template_file) as f:
1667
- template_data = json.load(f)
1668
- return template_data.get("routing")
1669
-
1670
- # Also check for variations in naming (underscore vs dash)
1671
- # Handle common naming variations between deployed .md files and .json templates
1672
- # Remove duplicates by using a set
1673
- alternative_names = list(
1674
- {
1675
- agent_name.replace("-", "_"), # api-qa -> api_qa
1676
- agent_name.replace("_", "-"), # api_qa -> api-qa
1677
- agent_name.replace("-", ""), # api-qa -> apiqa
1678
- agent_name.replace("_", ""), # api_qa -> apiqa
1679
- }
1680
- )
1681
-
1682
- for alt_name in alternative_names:
1683
- if alt_name != agent_name:
1684
- alt_file = templates_dir / f"{alt_name}.json"
1685
- if alt_file.exists():
1686
- with open(alt_file) as f:
1687
- template_data = json.load(f)
1688
- return template_data.get("routing")
1689
-
1690
- self.logger.debug(f"No JSON template found for agent: {agent_name}")
1691
- return None
1692
-
1693
- except Exception as e:
1694
- self.logger.debug(f"Could not load routing metadata for {agent_name}: {e}")
1695
- return None
1696
-
1697
- def _generate_agent_selection_guide(self, deployed_agents: list) -> str:
1698
- """Generate Context-Aware Agent Selection guide from deployed agents.
1699
-
1700
- Creates a mapping of task types to appropriate agents based on their
1701
- descriptions and capabilities.
1702
- """
1703
- guide = ""
1704
-
1705
- # Build selection mapping based on deployed agents
1706
- selection_map = {}
484
+ # Get or create event loop
485
+ try:
486
+ loop = asyncio.get_running_loop()
487
+ except RuntimeError:
488
+ loop = asyncio.new_event_loop()
489
+ asyncio.set_event_loop(loop)
490
+
491
+ # Prepare metadata
492
+ metadata = {
493
+ "framework_version": self.framework_version,
494
+ "framework_loaded": self.framework_content.get("loaded", False),
495
+ "session_id": os.environ.get("CLAUDE_SESSION_ID", "unknown"),
496
+ }
1707
497
 
1708
- for agent in deployed_agents:
1709
- agent_id = agent["id"]
1710
- desc_lower = agent["description"].lower()
498
+ # Log the prompt asynchronously
499
+ instructions = (
500
+ self._format_full_framework()
501
+ if self.framework_content["loaded"]
502
+ else self._format_minimal_framework()
503
+ )
504
+ metadata["instructions_length"] = len(instructions)
1711
505
 
1712
- # Map task types to agents based on their descriptions
1713
- if "implementation" in desc_lower or (
1714
- "engineer" in agent_id and "data" not in agent_id
1715
- ):
1716
- selection_map["Implementation tasks"] = (
1717
- f"{agent['display_name']} (`{agent_id}`)"
1718
- )
1719
- if "codebase analysis" in desc_lower or "research" in agent_id:
1720
- selection_map["Codebase analysis"] = (
1721
- f"{agent['display_name']} (`{agent_id}`)"
1722
- )
1723
- if "testing" in desc_lower or "qa" in agent_id:
1724
- selection_map["Testing/quality"] = (
1725
- f"{agent['display_name']} (`{agent_id}`)"
1726
- )
1727
- if "documentation" in desc_lower:
1728
- selection_map["Documentation"] = (
1729
- f"{agent['display_name']} (`{agent_id}`)"
1730
- )
1731
- if "security" in desc_lower or "sast" in desc_lower:
1732
- selection_map["Security operations"] = (
1733
- f"{agent['display_name']} (`{agent_id}`)"
1734
- )
1735
- if (
1736
- "deployment" in desc_lower
1737
- or "infrastructure" in desc_lower
1738
- or "ops" in agent_id
1739
- ):
1740
- selection_map["Deployment/infrastructure"] = (
1741
- f"{agent['display_name']} (`{agent_id}`)"
1742
- )
1743
- if "data" in desc_lower and (
1744
- "pipeline" in desc_lower or "etl" in desc_lower
1745
- ):
1746
- selection_map["Data pipeline/ETL"] = (
1747
- f"{agent['display_name']} (`{agent_id}`)"
1748
- )
1749
- if "git" in desc_lower or "version control" in desc_lower:
1750
- selection_map["Version control"] = (
1751
- f"{agent['display_name']} (`{agent_id}`)"
1752
- )
1753
- if "ticket" in desc_lower or "epic" in desc_lower:
1754
- selection_map["Ticket/issue management"] = (
1755
- f"{agent['display_name']} (`{agent_id}`)"
1756
- )
1757
- if "browser" in desc_lower or "e2e" in desc_lower:
1758
- selection_map["Browser/E2E testing"] = (
1759
- f"{agent['display_name']} (`{agent_id}`)"
1760
- )
1761
- if "frontend" in desc_lower or "ui" in desc_lower or "html" in desc_lower:
1762
- selection_map["Frontend/UI development"] = (
1763
- f"{agent['display_name']} (`{agent_id}`)"
506
+ if loop.is_running():
507
+ _task = asyncio.create_task(
508
+ log_manager.log_prompt("system_prompt", instructions, metadata)
509
+ ) # Fire-and-forget logging
510
+ else:
511
+ loop.run_until_complete(
512
+ log_manager.log_prompt("system_prompt", instructions, metadata)
1764
513
  )
1765
514
 
1766
- # Always include PM questions
1767
- selection_map["PM questions"] = "Answer directly (only exception)"
1768
-
1769
- # Format the selection guide
1770
- for task_type, agent_info in selection_map.items():
1771
- guide += f"- **{task_type}** → {agent_info}\n"
1772
-
1773
- return guide
1774
-
1775
- def _get_fallback_capabilities(self) -> str:
1776
- """Return fallback capabilities when dynamic discovery fails."""
1777
- return """
1778
-
1779
- ## Available Agent Capabilities
1780
-
1781
- You have the following specialized agents available for delegation:
1782
-
1783
- - **Engineer** (`engineer`): Code implementation and development
1784
- - **Research** (`research-agent`): Investigation and analysis
1785
- - **QA** (`qa-agent`): Testing and quality assurance
1786
- - **Documentation** (`documentation-agent`): Documentation creation and maintenance
1787
- - **Security** (`security-agent`): Security analysis and protection
1788
- - **Data Engineer** (`data-engineer`): Data management and pipelines
1789
- - **Ops** (`ops-agent`): Deployment and operations
1790
- - **Version Control** (`version-control`): Git operations and version management
515
+ self.logger.debug("System prompt logged to prompts directory")
516
+ except Exception as e:
517
+ self.logger.debug(f"Could not log system prompt: {e}")
1791
518
 
1792
- **IMPORTANT**: Use the exact agent ID in parentheses when delegating tasks.
1793
- """
519
+ # === Agent Registry Methods (backward compatibility) ===
1794
520
 
1795
- def _format_minimal_framework(self) -> str:
1796
- """Format minimal framework instructions when full framework not available."""
1797
- return """
1798
- # Claude PM Framework Instructions
1799
-
1800
- You are operating within a Claude PM Framework deployment.
1801
-
1802
- ## Role
1803
- You are a multi-agent orchestrator. Your primary responsibilities:
1804
- - Delegate tasks to specialized agents via Task Tool
1805
- - Coordinate multi-agent workflows
1806
- - Extract TODO/BUG/FEATURE items for ticket creation
1807
- - NEVER perform direct implementation work
1808
-
1809
- ## Core Agents
1810
- - Documentation Agent - Documentation tasks
1811
- - Engineer Agent - Code implementation
1812
- - QA Agent - Testing and validation
1813
- - Research Agent - Investigation and analysis
1814
- - Version Control Agent - Git operations
1815
-
1816
- ## Important Rules
1817
- 1. Always delegate work via Task Tool
1818
- 2. Provide comprehensive context to agents
1819
- 3. Track all TODO/BUG/FEATURE items
1820
- 4. Maintain project visibility
1821
-
1822
- ---
1823
- """
1824
-
1825
- def get_agent_list(self) -> list:
521
+ def get_agent_list(self) -> List[str]:
1826
522
  """Get list of available agents."""
1827
- # First try agent registry
1828
523
  if self.agent_registry:
1829
524
  agents = self.agent_registry.list_agents()
1830
525
  if agents:
1831
526
  return list(agents.keys())
1832
-
1833
- # Fallback to loaded content
1834
527
  return list(self.framework_content["agents"].keys())
1835
528
 
1836
529
  def get_agent_definition(self, agent_name: str) -> Optional[str]:
1837
530
  """Get specific agent definition."""
1838
- # First try agent registry
1839
531
  if self.agent_registry:
1840
532
  definition = self.agent_registry.get_agent_definition(agent_name)
1841
533
  if definition:
1842
534
  return definition
1843
-
1844
- # Fallback to loaded content
1845
535
  return self.framework_content["agents"].get(agent_name)
1846
536
 
1847
- def get_agent_hierarchy(self) -> Dict[str, list]:
537
+ def get_agent_hierarchy(self) -> Dict[str, List]:
1848
538
  """Get agent hierarchy from registry."""
1849
539
  if self.agent_registry:
1850
540
  return self.agent_registry.get_agent_hierarchy()