claude-mpm 3.9.11__py3-none-any.whl → 4.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +2 -2
  3. claude_mpm/__main__.py +3 -2
  4. claude_mpm/agents/__init__.py +85 -79
  5. claude_mpm/agents/agent_loader.py +464 -1003
  6. claude_mpm/agents/agent_loader_integration.py +45 -45
  7. claude_mpm/agents/agents_metadata.py +29 -30
  8. claude_mpm/agents/async_agent_loader.py +156 -138
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/base_agent_loader.py +179 -151
  11. claude_mpm/agents/frontmatter_validator.py +229 -130
  12. claude_mpm/agents/schema/agent_schema.json +1 -1
  13. claude_mpm/agents/system_agent_config.py +213 -147
  14. claude_mpm/agents/templates/__init__.py +13 -13
  15. claude_mpm/agents/templates/code_analyzer.json +2 -2
  16. claude_mpm/agents/templates/data_engineer.json +1 -1
  17. claude_mpm/agents/templates/documentation.json +23 -11
  18. claude_mpm/agents/templates/engineer.json +22 -6
  19. claude_mpm/agents/templates/memory_manager.json +1 -1
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +1 -1
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +79 -51
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +20 -20
  33. claude_mpm/cli/commands/agents.py +279 -247
  34. claude_mpm/cli/commands/aggregate.py +138 -157
  35. claude_mpm/cli/commands/cleanup.py +147 -147
  36. claude_mpm/cli/commands/config.py +93 -76
  37. claude_mpm/cli/commands/info.py +17 -16
  38. claude_mpm/cli/commands/mcp.py +140 -905
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +203 -81
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +305 -197
  50. claude_mpm/cli/parser.py +24 -1156
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +104 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +71 -73
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +35 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +233 -199
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +30 -13
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
  298. claude_mpm/services/mcp_gateway/main.py +287 -137
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +19 -533
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +2 -2
  358. claude_mpm/storage/state_storage.py +177 -181
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +27 -1
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/cli/commands/run_guarded.py +0 -511
  385. claude_mpm/config/memory_guardian_config.py +0 -325
  386. claude_mpm/config/memory_guardian_yaml.py +0 -335
  387. claude_mpm/core/config_paths.py +0 -150
  388. claude_mpm/core/memory_aware_runner.py +0 -353
  389. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  390. claude_mpm/deployment_paths.py +0 -261
  391. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  392. claude_mpm/models/state_models.py +0 -433
  393. claude_mpm/services/agent/__init__.py +0 -24
  394. claude_mpm/services/agent/deployment.py +0 -2548
  395. claude_mpm/services/agent/management.py +0 -598
  396. claude_mpm/services/agent/registry.py +0 -813
  397. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  398. claude_mpm/services/communication/socketio.py +0 -1935
  399. claude_mpm/services/communication/websocket.py +0 -479
  400. claude_mpm/services/framework_claude_md_generator.py +0 -624
  401. claude_mpm/services/health_monitor.py +0 -893
  402. claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
  403. claude_mpm/services/infrastructure/health_monitor.py +0 -775
  404. claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
  405. claude_mpm/services/infrastructure/memory_guardian.py +0 -944
  406. claude_mpm/services/infrastructure/restart_protection.py +0 -642
  407. claude_mpm/services/infrastructure/state_manager.py +0 -774
  408. claude_mpm/services/mcp_gateway/manager.py +0 -334
  409. claude_mpm/services/optimized_hook_service.py +0 -542
  410. claude_mpm/services/project_analyzer.py +0 -864
  411. claude_mpm/services/project_registry.py +0 -608
  412. claude_mpm/services/standalone_socketio_server.py +0 -1300
  413. claude_mpm/services/ticket_manager_di.py +0 -318
  414. claude_mpm/services/ticketing_service_original.py +0 -510
  415. claude_mpm/utils/paths.py +0 -395
  416. claude_mpm/utils/platform_memory.py +0 -524
  417. claude_mpm-3.9.11.dist-info/RECORD +0 -306
  418. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  419. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,323 @@
1
+ """Agent validator for deployed agent files."""
2
+
3
+ import re
4
+ from pathlib import Path
5
+ from typing import Any, Dict, Optional
6
+
7
+ import yaml
8
+
9
+ from claude_mpm.core.logger import get_logger
10
+
11
+ from .validation_result import ValidationResult
12
+
13
+
14
+ class AgentValidator:
15
+ """Validator for deployed agent markdown files.
16
+
17
+ This validator checks deployed agent .md files for:
18
+ - Valid YAML frontmatter
19
+ - Required frontmatter fields
20
+ - Proper markdown structure
21
+ - Content validation
22
+ """
23
+
24
+ def __init__(self):
25
+ """Initialize the agent validator."""
26
+ self.logger = get_logger(__name__)
27
+
28
+ # Required frontmatter fields
29
+ self.required_frontmatter_fields = {
30
+ "name": str,
31
+ "description": str,
32
+ "author": str,
33
+ "version": str,
34
+ "model": str,
35
+ "tools": list,
36
+ }
37
+
38
+ def validate_agent_file(self, agent_file: Path) -> ValidationResult:
39
+ """Validate a deployed agent file.
40
+
41
+ Args:
42
+ agent_file: Path to agent markdown file
43
+
44
+ Returns:
45
+ ValidationResult with validation outcome
46
+ """
47
+ result = ValidationResult(is_valid=True)
48
+
49
+ # Check if file exists
50
+ if not agent_file.exists():
51
+ result.add_error(f"Agent file does not exist: {agent_file}")
52
+ return result
53
+
54
+ # Check if it's a file
55
+ if not agent_file.is_file():
56
+ result.add_error(f"Agent path is not a file: {agent_file}")
57
+ return result
58
+
59
+ try:
60
+ # Read file content
61
+ content = agent_file.read_text(encoding="utf-8")
62
+
63
+ # Validate frontmatter
64
+ frontmatter_result = self._validate_frontmatter(content)
65
+ result = result.merge(frontmatter_result)
66
+
67
+ # Validate markdown structure
68
+ markdown_result = self._validate_markdown_structure(content)
69
+ result = result.merge(markdown_result)
70
+
71
+ # Add metadata
72
+ result.metadata["agent_file"] = str(agent_file)
73
+ result.metadata["agent_name"] = agent_file.stem
74
+
75
+ except UnicodeDecodeError as e:
76
+ result.add_error(f"File encoding error: {e}")
77
+ except Exception as e:
78
+ result.add_error(f"Unexpected error reading agent file: {e}")
79
+
80
+ return result
81
+
82
+ def _validate_frontmatter(self, content: str) -> ValidationResult:
83
+ """Validate YAML frontmatter in agent file.
84
+
85
+ Args:
86
+ content: File content
87
+
88
+ Returns:
89
+ ValidationResult for frontmatter validation
90
+ """
91
+ result = ValidationResult(is_valid=True)
92
+
93
+ # Check if content starts with frontmatter
94
+ if not content.startswith("---"):
95
+ result.add_error("Agent file must start with YAML frontmatter (---)")
96
+ return result
97
+
98
+ # Extract frontmatter
99
+ frontmatter_match = re.match(r"^---\n(.*?)\n---", content, re.DOTALL)
100
+ if not frontmatter_match:
101
+ result.add_error("Invalid frontmatter format - missing closing ---")
102
+ return result
103
+
104
+ frontmatter_content = frontmatter_match.group(1)
105
+
106
+ try:
107
+ # Parse YAML
108
+ frontmatter_data = yaml.safe_load(frontmatter_content)
109
+
110
+ if not isinstance(frontmatter_data, dict):
111
+ result.add_error("Frontmatter must be a YAML dictionary")
112
+ return result
113
+
114
+ # Validate required fields
115
+ self._validate_frontmatter_fields(frontmatter_data, result)
116
+
117
+ # Validate specific field values
118
+ self._validate_frontmatter_values(frontmatter_data, result)
119
+
120
+ except yaml.YAMLError as e:
121
+ result.add_error(f"Invalid YAML in frontmatter: {e}")
122
+
123
+ return result
124
+
125
+ def _validate_frontmatter_fields(
126
+ self, frontmatter: Dict[str, Any], result: ValidationResult
127
+ ) -> None:
128
+ """Validate frontmatter fields.
129
+
130
+ Args:
131
+ frontmatter: Frontmatter dictionary
132
+ result: ValidationResult to update
133
+ """
134
+ for field, expected_type in self.required_frontmatter_fields.items():
135
+ if field not in frontmatter:
136
+ result.add_error(f"Missing required frontmatter field: {field}")
137
+ else:
138
+ value = frontmatter[field]
139
+ if not isinstance(value, expected_type):
140
+ result.add_error(
141
+ f"Frontmatter field '{field}' should be {expected_type.__name__}, got {type(value).__name__}",
142
+ field_name=field,
143
+ )
144
+
145
+ def _validate_frontmatter_values(
146
+ self, frontmatter: Dict[str, Any], result: ValidationResult
147
+ ) -> None:
148
+ """Validate frontmatter field values.
149
+
150
+ Args:
151
+ frontmatter: Frontmatter dictionary
152
+ result: ValidationResult to update
153
+ """
154
+ # Validate name
155
+ if "name" in frontmatter:
156
+ name = frontmatter["name"]
157
+ if not name or not str(name).strip():
158
+ result.add_error("Agent name cannot be empty", field_name="name")
159
+
160
+ # Validate description
161
+ if "description" in frontmatter:
162
+ description = frontmatter["description"]
163
+ if not description or not str(description).strip():
164
+ result.add_error(
165
+ "Agent description cannot be empty", field_name="description"
166
+ )
167
+
168
+ # Validate author
169
+ if "author" in frontmatter:
170
+ author = frontmatter["author"]
171
+ if not author or not str(author).strip():
172
+ result.add_error("Agent author cannot be empty", field_name="author")
173
+
174
+ # Validate version
175
+ if "version" in frontmatter:
176
+ version = frontmatter["version"]
177
+ if not self._is_valid_version(str(version)):
178
+ result.add_warning(
179
+ f"Version '{version}' does not follow semantic versioning",
180
+ field_name="version",
181
+ suggestion="Use semantic versioning (e.g., '1.0.0')",
182
+ )
183
+
184
+ # Validate model
185
+ if "model" in frontmatter:
186
+ model = frontmatter["model"]
187
+ valid_models = ["sonnet", "haiku", "opus"]
188
+ if model not in valid_models:
189
+ result.add_warning(
190
+ f"Unknown model '{model}'",
191
+ field_name="model",
192
+ suggestion=f"Use one of: {', '.join(valid_models)}",
193
+ )
194
+
195
+ # Validate tools
196
+ if "tools" in frontmatter:
197
+ tools = frontmatter["tools"]
198
+ if not isinstance(tools, list):
199
+ result.add_error("Tools should be a list", field_name="tools")
200
+ elif len(tools) == 0:
201
+ result.add_warning("No tools specified", field_name="tools")
202
+ else:
203
+ # Check for common tool names
204
+ for tool in tools:
205
+ if not isinstance(tool, str):
206
+ result.add_warning(
207
+ f"Tool '{tool}' should be a string", field_name="tools"
208
+ )
209
+
210
+ def _validate_markdown_structure(self, content: str) -> ValidationResult:
211
+ """Validate markdown structure of agent file.
212
+
213
+ Args:
214
+ content: File content
215
+
216
+ Returns:
217
+ ValidationResult for markdown validation
218
+ """
219
+ result = ValidationResult(is_valid=True)
220
+
221
+ # Remove frontmatter for markdown analysis
222
+ content_without_frontmatter = re.sub(
223
+ r"^---\n.*?\n---\n", "", content, flags=re.DOTALL
224
+ )
225
+
226
+ # Check if there's content after frontmatter
227
+ if not content_without_frontmatter.strip():
228
+ result.add_warning("Agent file has no content after frontmatter")
229
+ return result
230
+
231
+ # Check for basic markdown structure
232
+ lines = content_without_frontmatter.split("\n")
233
+
234
+ # Look for at least one heading or substantial content
235
+ has_heading = any(line.strip().startswith("#") for line in lines)
236
+ has_content = any(len(line.strip()) > 10 for line in lines)
237
+
238
+ if not has_heading and not has_content:
239
+ result.add_warning("Agent file appears to have minimal content")
240
+
241
+ # Check for common sections
242
+ content_lower = content_without_frontmatter.lower()
243
+ if "instruction" not in content_lower and "prompt" not in content_lower:
244
+ result.add_info("Agent file may benefit from explicit instructions section")
245
+
246
+ return result
247
+
248
+ def _is_valid_version(self, version: str) -> bool:
249
+ """Check if version follows semantic versioning.
250
+
251
+ Args:
252
+ version: Version string to validate
253
+
254
+ Returns:
255
+ True if version is valid semantic version
256
+ """
257
+ # Simple semantic version pattern
258
+ pattern = r"^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$"
259
+ return bool(re.match(pattern, version))
260
+
261
+ def repair_agent_file(
262
+ self, agent_file: Path, dry_run: bool = True
263
+ ) -> ValidationResult:
264
+ """Attempt to repair common issues in agent file.
265
+
266
+ Args:
267
+ agent_file: Path to agent file
268
+ dry_run: If True, don't actually modify the file
269
+
270
+ Returns:
271
+ ValidationResult with repair information
272
+ """
273
+ result = ValidationResult(is_valid=True)
274
+
275
+ try:
276
+ content = agent_file.read_text(encoding="utf-8")
277
+ original_content = content
278
+
279
+ # Try to fix common frontmatter issues
280
+ content = self._repair_frontmatter(content, result)
281
+
282
+ # If changes were made and not dry run, write back
283
+ if content != original_content:
284
+ if not dry_run:
285
+ agent_file.write_text(content, encoding="utf-8")
286
+ result.add_info(f"Repaired agent file: {agent_file}")
287
+ else:
288
+ result.add_info(f"Would repair agent file: {agent_file} (dry run)")
289
+ else:
290
+ result.add_info("No repairs needed")
291
+
292
+ except Exception as e:
293
+ result.add_error(f"Failed to repair agent file: {e}")
294
+
295
+ return result
296
+
297
+ def _repair_frontmatter(self, content: str, result: ValidationResult) -> str:
298
+ """Attempt to repair frontmatter issues.
299
+
300
+ Args:
301
+ content: File content
302
+ result: ValidationResult to update with repair info
303
+
304
+ Returns:
305
+ Repaired content
306
+ """
307
+ # This is a simplified repair - in practice, you'd want more sophisticated logic
308
+ if not content.startswith("---"):
309
+ result.add_info("Added missing frontmatter delimiters")
310
+ # Add basic frontmatter if missing
311
+ basic_frontmatter = """---
312
+ name: "Unknown Agent"
313
+ description: "Agent description needed"
314
+ author: "claude-mpm"
315
+ version: "1.0.0"
316
+ model: "sonnet"
317
+ tools: []
318
+ ---
319
+
320
+ """
321
+ return basic_frontmatter + content
322
+
323
+ return content
@@ -0,0 +1,238 @@
1
+ """Main deployment validator service."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ from claude_mpm.core.logger import get_logger
7
+
8
+ from .agent_validator import AgentValidator
9
+ from .template_validator import TemplateValidator
10
+ from .validation_result import ValidationResult
11
+
12
+
13
+ class DeploymentValidator:
14
+ """Main validator for deployment operations.
15
+
16
+ This service orchestrates validation of templates, agents,
17
+ and deployment environments.
18
+ """
19
+
20
+ def __init__(self):
21
+ """Initialize the deployment validator."""
22
+ self.logger = get_logger(__name__)
23
+ self.template_validator = TemplateValidator()
24
+ self.agent_validator = AgentValidator()
25
+
26
+ def validate_template_files(
27
+ self, template_files: List[Path]
28
+ ) -> Dict[str, ValidationResult]:
29
+ """Validate multiple template files.
30
+
31
+ Args:
32
+ template_files: List of template file paths
33
+
34
+ Returns:
35
+ Dictionary mapping file paths to validation results
36
+ """
37
+ results = {}
38
+
39
+ for template_file in template_files:
40
+ self.logger.debug(f"Validating template: {template_file}")
41
+ result = self.template_validator.validate_template_file(template_file)
42
+ results[str(template_file)] = result
43
+
44
+ if not result.is_valid:
45
+ self.logger.warning(
46
+ f"Template validation failed for {template_file}: {result}"
47
+ )
48
+ elif result.has_warnings:
49
+ self.logger.info(
50
+ f"Template validation warnings for {template_file}: {result.warning_count} warnings"
51
+ )
52
+
53
+ return results
54
+
55
+ def validate_agent_files(
56
+ self, agent_files: List[Path]
57
+ ) -> Dict[str, ValidationResult]:
58
+ """Validate multiple agent files.
59
+
60
+ Args:
61
+ agent_files: List of agent file paths
62
+
63
+ Returns:
64
+ Dictionary mapping file paths to validation results
65
+ """
66
+ results = {}
67
+
68
+ for agent_file in agent_files:
69
+ self.logger.debug(f"Validating agent: {agent_file}")
70
+ result = self.agent_validator.validate_agent_file(agent_file)
71
+ results[str(agent_file)] = result
72
+
73
+ if not result.is_valid:
74
+ self.logger.warning(
75
+ f"Agent validation failed for {agent_file}: {result}"
76
+ )
77
+ elif result.has_warnings:
78
+ self.logger.info(
79
+ f"Agent validation warnings for {agent_file}: {result.warning_count} warnings"
80
+ )
81
+
82
+ return results
83
+
84
+ def validate_deployment_environment(
85
+ self, target_dir: Path, templates_dir: Optional[Path] = None
86
+ ) -> ValidationResult:
87
+ """Validate deployment environment.
88
+
89
+ Args:
90
+ target_dir: Target deployment directory
91
+ templates_dir: Optional templates directory
92
+
93
+ Returns:
94
+ ValidationResult for environment validation
95
+ """
96
+ result = ValidationResult(is_valid=True)
97
+
98
+ # Validate target directory
99
+ if not target_dir.exists():
100
+ try:
101
+ target_dir.mkdir(parents=True, exist_ok=True)
102
+ result.add_info(f"Created target directory: {target_dir}")
103
+ except Exception as e:
104
+ result.add_error(f"Cannot create target directory {target_dir}: {e}")
105
+ return result
106
+
107
+ if not target_dir.is_dir():
108
+ result.add_error(f"Target path is not a directory: {target_dir}")
109
+ return result
110
+
111
+ # Check if target directory is writable
112
+ test_file = target_dir / ".write_test"
113
+ try:
114
+ test_file.write_text("test")
115
+ test_file.unlink()
116
+ result.add_info("Target directory is writable")
117
+ except Exception as e:
118
+ result.add_error(f"Target directory is not writable: {target_dir} - {e}")
119
+
120
+ # Validate templates directory if provided
121
+ if templates_dir:
122
+ if not templates_dir.exists():
123
+ result.add_error(f"Templates directory does not exist: {templates_dir}")
124
+ elif not templates_dir.is_dir():
125
+ result.add_error(f"Templates path is not a directory: {templates_dir}")
126
+ else:
127
+ # Check for template files
128
+ template_files = list(templates_dir.glob("*.json"))
129
+ if not template_files:
130
+ result.add_warning(f"No template files found in: {templates_dir}")
131
+ else:
132
+ result.add_info(f"Found {len(template_files)} template files")
133
+
134
+ return result
135
+
136
+ def validate_deployment_context(self, context) -> ValidationResult:
137
+ """Validate deployment context.
138
+
139
+ Args:
140
+ context: Deployment context (pipeline or deployment context)
141
+
142
+ Returns:
143
+ ValidationResult for context validation
144
+ """
145
+ result = ValidationResult(is_valid=True)
146
+
147
+ # Validate target directory
148
+ target_dir = getattr(context, "actual_target_dir", None) or getattr(
149
+ context, "target_dir", None
150
+ )
151
+ if target_dir:
152
+ env_result = self.validate_deployment_environment(target_dir)
153
+ result = result.merge(env_result)
154
+ else:
155
+ result.add_error("No target directory specified in context")
156
+
157
+ # Validate template files
158
+ template_files = getattr(context, "template_files", [])
159
+ if template_files:
160
+ template_results = self.validate_template_files(template_files)
161
+
162
+ # Aggregate template validation results
163
+ total_templates = len(template_results)
164
+ valid_templates = sum(1 for r in template_results.values() if r.is_valid)
165
+
166
+ if valid_templates == total_templates:
167
+ result.add_info(f"All {total_templates} templates are valid")
168
+ else:
169
+ invalid_count = total_templates - valid_templates
170
+ result.add_error(
171
+ f"{invalid_count} of {total_templates} templates are invalid"
172
+ )
173
+
174
+ # Add template validation details to metadata
175
+ result.metadata["template_validation"] = {
176
+ "total": total_templates,
177
+ "valid": valid_templates,
178
+ "invalid": total_templates - valid_templates,
179
+ "details": {path: r.to_dict() for path, r in template_results.items()},
180
+ }
181
+ else:
182
+ result.add_warning("No template files to validate")
183
+
184
+ return result
185
+
186
+ def repair_agent_files(
187
+ self, agent_files: List[Path], dry_run: bool = True
188
+ ) -> Dict[str, ValidationResult]:
189
+ """Repair multiple agent files.
190
+
191
+ Args:
192
+ agent_files: List of agent file paths
193
+ dry_run: If True, don't actually modify files
194
+
195
+ Returns:
196
+ Dictionary mapping file paths to repair results
197
+ """
198
+ results = {}
199
+
200
+ for agent_file in agent_files:
201
+ self.logger.debug(f"Repairing agent: {agent_file}")
202
+ result = self.agent_validator.repair_agent_file(agent_file, dry_run=dry_run)
203
+ results[str(agent_file)] = result
204
+
205
+ if not result.is_valid:
206
+ self.logger.error(f"Agent repair failed for {agent_file}: {result}")
207
+ else:
208
+ self.logger.info(f"Agent repair completed for {agent_file}")
209
+
210
+ return results
211
+
212
+ def get_validation_summary(
213
+ self, results: Dict[str, ValidationResult]
214
+ ) -> Dict[str, Any]:
215
+ """Get summary of validation results.
216
+
217
+ Args:
218
+ results: Dictionary of validation results
219
+
220
+ Returns:
221
+ Summary dictionary
222
+ """
223
+ total = len(results)
224
+ valid = sum(1 for r in results.values() if r.is_valid)
225
+ invalid = total - valid
226
+
227
+ total_errors = sum(r.error_count for r in results.values())
228
+ total_warnings = sum(r.warning_count for r in results.values())
229
+
230
+ return {
231
+ "total_files": total,
232
+ "valid_files": valid,
233
+ "invalid_files": invalid,
234
+ "total_errors": total_errors,
235
+ "total_warnings": total_warnings,
236
+ "success_rate": (valid / total * 100) if total > 0 else 0,
237
+ "details": {path: r.to_dict() for path, r in results.items()},
238
+ }