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
@@ -21,20 +21,22 @@ Security Considerations:
21
21
 
22
22
  import json
23
23
  import logging
24
- from pathlib import Path
25
- from typing import Dict, List, Optional, Any, Tuple
26
24
  from dataclasses import dataclass, field
27
25
  from datetime import datetime
26
+ from pathlib import Path
27
+ from typing import Any, Dict, List, Optional, Tuple
28
+
28
29
  import jsonschema
29
- from jsonschema import validate, ValidationError, Draft7Validator
30
+ from jsonschema import Draft7Validator, ValidationError, validate
31
+
30
32
  from claude_mpm.config.paths import paths
31
33
  from claude_mpm.core.constants import (
32
- SystemLimits,
33
- ResourceLimits,
34
- TimeoutConfig,
35
34
  ComplexityMetrics,
36
35
  ErrorMessages,
37
- ValidationRules
36
+ ResourceLimits,
37
+ SystemLimits,
38
+ TimeoutConfig,
39
+ ValidationRules,
38
40
  )
39
41
 
40
42
  logger = logging.getLogger(__name__)
@@ -43,6 +45,7 @@ logger = logging.getLogger(__name__)
43
45
  @dataclass
44
46
  class ValidationResult:
45
47
  """Result of agent validation."""
48
+
46
49
  is_valid: bool
47
50
  errors: List[str] = field(default_factory=list)
48
51
  warnings: List[str] = field(default_factory=list)
@@ -51,7 +54,7 @@ class ValidationResult:
51
54
 
52
55
  class AgentValidator:
53
56
  """Validates agent configurations against JSON schema.
54
-
57
+
55
58
  SECURITY CRITICAL: This class is the primary defense against malicious agent
56
59
  configurations. All agent data must pass through this validator before being
57
60
  used by the system. Bypassing this validator could lead to:
@@ -60,7 +63,7 @@ class AgentValidator:
60
63
  - Data exfiltration (via file/network access)
61
64
  - Privilege escalation (via tool combinations)
62
65
  """
63
-
66
+
64
67
  # Model name mappings for normalization to tier names
65
68
  MODEL_MAPPINGS = {
66
69
  # Sonnet variations
@@ -77,19 +80,19 @@ class AgentValidator:
77
80
  "claude-3-haiku-20240307": "haiku",
78
81
  "claude-3-5-haiku-20241022": "haiku",
79
82
  }
80
-
83
+
81
84
  def __init__(self, schema_path: Optional[Path] = None):
82
85
  """Initialize the validator with the agent schema."""
83
86
  if schema_path is None:
84
87
  schema_path = paths.schemas_dir / "agent_schema.json"
85
-
88
+
86
89
  self.schema_path = schema_path
87
90
  self.schema = self._load_schema()
88
91
  self.validator = Draft7Validator(self.schema)
89
-
92
+
90
93
  def _load_schema(self) -> Dict[str, Any]:
91
94
  """Load the JSON schema from file.
92
-
95
+
93
96
  Security Considerations:
94
97
  - Schema file path is validated to exist and be a file
95
98
  - JSON parsing errors are caught and logged
@@ -101,95 +104,99 @@ class AgentValidator:
101
104
  raise FileNotFoundError(f"Schema file not found: {self.schema_path}")
102
105
  if not self.schema_path.is_file():
103
106
  raise ValueError(f"Schema path is not a file: {self.schema_path}")
104
-
105
- with open(self.schema_path, 'r') as f:
107
+
108
+ with open(self.schema_path, "r") as f:
106
109
  return json.load(f)
107
110
  except Exception as e:
108
111
  logger.error(f"Failed to load schema from {self.schema_path}: {e}")
109
112
  raise
110
-
113
+
111
114
  def _normalize_model(self, model: str) -> str:
112
115
  """Normalize model name to standard tier (opus, sonnet, haiku).
113
-
116
+
114
117
  Args:
115
118
  model: Original model name
116
-
119
+
117
120
  Returns:
118
121
  Normalized model tier name
119
122
  """
120
123
  # Direct mapping check
121
124
  if model in self.MODEL_MAPPINGS:
122
125
  return self.MODEL_MAPPINGS[model]
123
-
126
+
124
127
  # Already normalized
125
128
  if model in {"opus", "sonnet", "haiku"}:
126
129
  return model
127
-
130
+
128
131
  # Check if model contains tier name
129
132
  model_lower = model.lower()
130
133
  for tier in {"opus", "sonnet", "haiku"}:
131
134
  if tier in model_lower:
132
135
  return tier
133
-
136
+
134
137
  # Default to sonnet if unrecognized
135
138
  logger.warning(f"Unrecognized model '{model}', defaulting to 'sonnet'")
136
139
  return "sonnet"
137
-
140
+
138
141
  def validate_agent(self, agent_data: Dict[str, Any]) -> ValidationResult:
139
142
  """
140
143
  Validate a single agent configuration against the schema.
141
-
144
+
142
145
  Security Features:
143
146
  - Strict JSON Schema validation prevents unexpected fields
144
147
  - Business rule validation adds additional security checks
145
148
  - Input size limits prevent memory exhaustion
146
149
  - Agent ID format validation prevents injection attacks
147
-
150
+
148
151
  Args:
149
152
  agent_data: Agent configuration dictionary
150
-
153
+
151
154
  Returns:
152
155
  ValidationResult with validation status and any errors/warnings
153
156
  """
154
157
  result = ValidationResult(is_valid=True)
155
-
158
+
156
159
  # Normalize model name before validation
157
160
  if "capabilities" in agent_data and "model" in agent_data["capabilities"]:
158
161
  original_model = agent_data["capabilities"]["model"]
159
162
  normalized_model = self._normalize_model(original_model)
160
163
  if original_model != normalized_model:
161
164
  agent_data["capabilities"]["model"] = normalized_model
162
- result.warnings.append(f"Normalized model from '{original_model}' to '{normalized_model}'")
163
-
165
+ result.warnings.append(
166
+ f"Normalized model from '{original_model}' to '{normalized_model}'"
167
+ )
168
+
164
169
  # Perform JSON schema validation
165
170
  try:
166
171
  validate(instance=agent_data, schema=self.schema)
167
172
  except ValidationError as e:
168
173
  result.is_valid = False
169
174
  result.errors.append(f"Schema validation error: {e.message}")
170
-
175
+
171
176
  # Add path information if available
172
177
  if e.path:
173
178
  path = ".".join(str(p) for p in e.path)
174
179
  result.errors.append(f"Error at path: {path}")
175
-
180
+
176
181
  # SECURITY: Additional business rule validations beyond schema
177
182
  # These provide defense-in-depth security checks
178
183
  if result.is_valid:
179
184
  self._validate_business_rules(agent_data, result)
180
-
185
+
181
186
  # Add metadata
182
187
  result.metadata = {
183
188
  "validated_at": datetime.utcnow().isoformat(),
184
189
  "schema_version": self.schema.get("version", "1.1.0"),
185
- "agent_id": agent_data.get("id", "unknown")
190
+ "agent_id": agent_data.get("id", "unknown"),
186
191
  }
187
-
192
+
188
193
  return result
189
-
190
- def _validate_business_rules(self, agent_data: Dict[str, Any], result: ValidationResult) -> None:
194
+
195
+ def _validate_business_rules(
196
+ self, agent_data: Dict[str, Any], result: ValidationResult
197
+ ) -> None:
191
198
  """Apply additional business rule validations beyond schema.
192
-
199
+
193
200
  Security Validations:
194
201
  - Resource limits to prevent DoS attacks
195
202
  - Instruction length limits to prevent memory exhaustion
@@ -197,49 +204,61 @@ class AgentValidator:
197
204
  - Tool compatibility to prevent privilege escalation
198
205
  - Self-reference prevention in handoff agents
199
206
  """
200
-
207
+
201
208
  # Validate resource tier consistency
202
209
  resource_tier = agent_data.get("capabilities", {}).get("resource_tier")
203
210
  if resource_tier:
204
211
  self._validate_resource_tier_limits(agent_data, resource_tier, result)
205
-
212
+
206
213
  # SECURITY: Validate instruction length to prevent memory exhaustion
207
214
  # Double-check even though schema enforces this - defense in depth
208
215
  instructions = agent_data.get("instructions", "")
209
216
  if len(instructions) > SystemLimits.MAX_INSTRUCTION_LENGTH:
210
- result.errors.append(ErrorMessages.INSTRUCTION_TOO_LONG.format(
211
- limit=SystemLimits.MAX_INSTRUCTION_LENGTH,
212
- actual=len(instructions)
213
- ))
217
+ result.errors.append(
218
+ ErrorMessages.INSTRUCTION_TOO_LONG.format(
219
+ limit=SystemLimits.MAX_INSTRUCTION_LENGTH, actual=len(instructions)
220
+ )
221
+ )
214
222
  result.is_valid = False
215
-
223
+
216
224
  # Validate model compatibility with tools
217
225
  self._validate_model_tool_compatibility(agent_data, result)
218
-
226
+
219
227
  # SECURITY: Validate agent ID format to prevent injection attacks
220
228
  # Pattern enforced: ^[a-z][a-z0-9_]*$ prevents special characters
221
229
  agent_id = agent_data.get("id", "")
222
230
  if agent_id.endswith("_agent"):
223
- result.warnings.append(f"Agent ID '{agent_id}' contains deprecated '_agent' suffix")
224
-
231
+ result.warnings.append(
232
+ f"Agent ID '{agent_id}' contains deprecated '_agent' suffix"
233
+ )
234
+
225
235
  # SECURITY: Additional ID validation for defense in depth
226
- if agent_id and not agent_id.replace('_', '').replace('-', '').isalnum():
236
+ if agent_id and not agent_id.replace("_", "").replace("-", "").isalnum():
227
237
  result.errors.append(f"Agent ID '{agent_id}' contains invalid characters")
228
238
  result.is_valid = False
229
-
239
+
230
240
  # SECURITY: Validate handoff agents to prevent circular references and privilege escalation
231
241
  handoff_agents = agent_data.get("interactions", {}).get("handoff_agents", [])
232
242
  for handoff_id in handoff_agents:
233
243
  if handoff_id == agent_id:
234
- result.warnings.append(f"Agent '{agent_id}' references itself in handoff_agents")
244
+ result.warnings.append(
245
+ f"Agent '{agent_id}' references itself in handoff_agents"
246
+ )
235
247
  # SECURITY: Ensure handoff IDs follow same pattern as agent IDs
236
- if handoff_id and not handoff_id.replace('_', '').replace('-', '').isalnum():
237
- result.errors.append(f"Handoff agent ID '{handoff_id}' contains invalid characters")
248
+ if (
249
+ handoff_id
250
+ and not handoff_id.replace("_", "").replace("-", "").isalnum()
251
+ ):
252
+ result.errors.append(
253
+ f"Handoff agent ID '{handoff_id}' contains invalid characters"
254
+ )
238
255
  result.is_valid = False
239
-
240
- def _validate_resource_tier_limits(self, agent_data: Dict[str, Any], tier: str, result: ValidationResult) -> None:
256
+
257
+ def _validate_resource_tier_limits(
258
+ self, agent_data: Dict[str, Any], tier: str, result: ValidationResult
259
+ ) -> None:
241
260
  """Validate resource limits match the tier constraints.
242
-
261
+
243
262
  Security Purpose:
244
263
  - Prevents resource exhaustion attacks
245
264
  - Ensures agents can't request excessive resources
@@ -250,26 +269,26 @@ class AgentValidator:
250
269
  "intensive": {
251
270
  "memory_limit": ResourceLimits.INTENSIVE_MEMORY_RANGE,
252
271
  "cpu_limit": ResourceLimits.INTENSIVE_CPU_RANGE,
253
- "timeout": TimeoutConfig.INTENSIVE_TIMEOUT_RANGE
272
+ "timeout": TimeoutConfig.INTENSIVE_TIMEOUT_RANGE,
254
273
  },
255
274
  "standard": {
256
275
  "memory_limit": ResourceLimits.STANDARD_MEMORY_RANGE,
257
276
  "cpu_limit": ResourceLimits.STANDARD_CPU_RANGE,
258
- "timeout": TimeoutConfig.STANDARD_TIMEOUT_RANGE
277
+ "timeout": TimeoutConfig.STANDARD_TIMEOUT_RANGE,
259
278
  },
260
279
  "lightweight": {
261
280
  "memory_limit": ResourceLimits.LIGHTWEIGHT_MEMORY_RANGE,
262
281
  "cpu_limit": ResourceLimits.LIGHTWEIGHT_CPU_RANGE,
263
- "timeout": TimeoutConfig.LIGHTWEIGHT_TIMEOUT_RANGE
264
- }
282
+ "timeout": TimeoutConfig.LIGHTWEIGHT_TIMEOUT_RANGE,
283
+ },
265
284
  }
266
-
285
+
267
286
  if tier not in tier_limits:
268
287
  return
269
-
288
+
270
289
  limits = tier_limits[tier]
271
290
  capabilities = agent_data.get("capabilities", {})
272
-
291
+
273
292
  # Check memory limit
274
293
  memory = capabilities.get("memory_limit")
275
294
  if memory is not None:
@@ -279,7 +298,7 @@ class AgentValidator:
279
298
  f"Memory limit {memory}MB outside recommended range "
280
299
  f"{min_mem}-{max_mem}MB for tier '{tier}'"
281
300
  )
282
-
301
+
283
302
  # Check CPU limit
284
303
  cpu = capabilities.get("cpu_limit")
285
304
  if cpu is not None:
@@ -289,7 +308,7 @@ class AgentValidator:
289
308
  f"CPU limit {cpu}% outside recommended range "
290
309
  f"{min_cpu}-{max_cpu}% for tier '{tier}'"
291
310
  )
292
-
311
+
293
312
  # Check timeout
294
313
  timeout = capabilities.get("timeout")
295
314
  if timeout is not None:
@@ -299,49 +318,66 @@ class AgentValidator:
299
318
  f"Timeout {timeout}s outside recommended range "
300
319
  f"{min_timeout}-{max_timeout}s for tier '{tier}'"
301
320
  )
302
-
303
- def _validate_model_tool_compatibility(self, agent_data: Dict[str, Any], result: ValidationResult) -> None:
321
+
322
+ def _validate_model_tool_compatibility(
323
+ self, agent_data: Dict[str, Any], result: ValidationResult
324
+ ) -> None:
304
325
  """Validate that model and tools are compatible."""
305
326
  model = agent_data.get("capabilities", {}).get("model", "")
306
327
  tools = agent_data.get("capabilities", {}).get("tools", [])
307
-
328
+
308
329
  # Normalize model name for comparison
309
330
  normalized_model = self._normalize_model(model)
310
-
331
+
311
332
  # Haiku models shouldn't use resource-intensive tools
312
333
  if normalized_model == "haiku":
313
- intensive_tools = {"docker", "kubectl", "terraform", "aws", "gcloud", "azure"}
334
+ intensive_tools = {
335
+ "docker",
336
+ "kubectl",
337
+ "terraform",
338
+ "aws",
339
+ "gcloud",
340
+ "azure",
341
+ }
314
342
  used_intensive = set(tools) & intensive_tools
315
343
  if used_intensive:
316
344
  result.warnings.append(
317
345
  f"Haiku model '{model}' using resource-intensive tools: {used_intensive}"
318
346
  )
319
-
347
+
320
348
  # SECURITY: Network access requirement validation
321
349
  # Ensures agents can't use network tools without explicit permission
322
350
  network_tools = {"WebSearch", "WebFetch", "aws", "gcloud", "azure"}
323
351
  needs_network = bool(set(tools) & network_tools)
324
352
  has_network = agent_data.get("capabilities", {}).get("network_access", False)
325
-
353
+
326
354
  if needs_network and not has_network:
327
355
  result.warnings.append(
328
356
  f"Agent uses network tools {set(tools) & network_tools} but network_access is False"
329
357
  )
330
-
358
+
331
359
  # SECURITY: Check for potentially dangerous tool combinations
332
360
  dangerous_combos = [
333
- ({"Bash", "Write"}, "Can execute arbitrary code by writing and running scripts"),
361
+ (
362
+ {"Bash", "Write"},
363
+ "Can execute arbitrary code by writing and running scripts",
364
+ ),
334
365
  ({"docker", "kubectl"}, "Container escape potential with both tools"),
335
- ({"aws", "gcloud", "azure"}, "Multiple cloud access increases attack surface")
366
+ (
367
+ {"aws", "gcloud", "azure"},
368
+ "Multiple cloud access increases attack surface",
369
+ ),
336
370
  ]
337
-
371
+
338
372
  for combo, risk in dangerous_combos:
339
373
  if combo.issubset(set(tools)):
340
- result.warnings.append(f"Potentially dangerous tool combination: {combo} - {risk}")
341
-
374
+ result.warnings.append(
375
+ f"Potentially dangerous tool combination: {combo} - {risk}"
376
+ )
377
+
342
378
  def validate_file(self, file_path: Path) -> ValidationResult:
343
379
  """Validate an agent configuration file.
344
-
380
+
345
381
  Security Measures:
346
382
  - Path traversal protection through Path object
347
383
  - Safe JSON parsing with error handling
@@ -353,21 +389,19 @@ class AgentValidator:
353
389
  raise FileNotFoundError(f"File not found: {file_path}")
354
390
  if not file_path.is_file():
355
391
  raise ValueError(f"Path is not a file: {file_path}")
356
-
392
+
357
393
  # SECURITY: Check file size to prevent memory exhaustion
358
394
  file_size = file_path.stat().st_size
359
395
  max_size = SystemLimits.MAX_AGENT_CONFIG_SIZE
360
396
  if file_size > max_size:
361
- raise ValueError(ErrorMessages.FILE_TOO_LARGE.format(
362
- limit=max_size
363
- ))
364
- with open(file_path, 'r') as f:
397
+ raise ValueError(ErrorMessages.FILE_TOO_LARGE.format(limit=max_size))
398
+ with open(file_path, "r") as f:
365
399
  agent_data = json.load(f)
366
-
400
+
367
401
  result = self.validate_agent(agent_data)
368
402
  result.metadata["file_path"] = str(file_path)
369
403
  return result
370
-
404
+
371
405
  except json.JSONDecodeError as e:
372
406
  result = ValidationResult(is_valid=False)
373
407
  result.errors.append(f"Invalid JSON in {file_path}: {e}")
@@ -376,46 +410,48 @@ class AgentValidator:
376
410
  result = ValidationResult(is_valid=False)
377
411
  result.errors.append(f"Error reading {file_path}: {e}")
378
412
  return result
379
-
413
+
380
414
  def validate_directory(self, directory: Path) -> Dict[str, ValidationResult]:
381
415
  """Validate all agent files in a directory.
382
-
416
+
383
417
  Security Considerations:
384
418
  - Directory traversal prevention through Path.glob
385
419
  - Symlink following should be disabled in production
386
420
  - Large directory DoS prevention through file count limits
387
421
  """
388
422
  results = {}
389
-
423
+
390
424
  # SECURITY: Validate directory exists and is accessible
391
425
  if not directory.exists():
392
426
  raise FileNotFoundError(f"Directory not found: {directory}")
393
427
  if not directory.is_dir():
394
428
  raise ValueError(f"Path is not a directory: {directory}")
395
-
429
+
396
430
  # SECURITY: Limit number of files to prevent DoS
397
431
  max_files = SystemLimits.MAX_FILES_TO_VALIDATE
398
432
  file_count = 0
399
-
433
+
400
434
  for json_file in directory.glob("*.json"):
401
435
  if json_file.name == "agent_schema.json":
402
436
  continue
403
-
437
+
404
438
  # SECURITY: Skip symlinks to prevent directory traversal
405
439
  if json_file.is_symlink():
406
440
  logger.warning(f"Skipping symlink: {json_file}")
407
441
  continue
408
-
442
+
409
443
  file_count += 1
410
444
  if file_count > max_files:
411
- logger.warning(f"Reached maximum file limit ({max_files}), stopping validation")
445
+ logger.warning(
446
+ f"Reached maximum file limit ({max_files}), stopping validation"
447
+ )
412
448
  break
413
-
449
+
414
450
  logger.info(f"Validating {json_file}")
415
451
  results[json_file.name] = self.validate_file(json_file)
416
-
452
+
417
453
  return results
418
-
454
+
419
455
  def get_schema_info(self) -> Dict[str, Any]:
420
456
  """Get information about the loaded schema."""
421
457
  return {
@@ -423,32 +459,34 @@ class AgentValidator:
423
459
  "schema_title": self.schema.get("title", "Unknown"),
424
460
  "schema_description": self.schema.get("description", ""),
425
461
  "required_fields": self.schema.get("required", []),
426
- "properties": list(self.schema.get("properties", {}).keys())
462
+ "properties": list(self.schema.get("properties", {}).keys()),
427
463
  }
428
464
 
429
465
 
430
- def validate_agent_migration(old_agent: Dict[str, Any], new_agent: Dict[str, Any]) -> ValidationResult:
466
+ def validate_agent_migration(
467
+ old_agent: Dict[str, Any], new_agent: Dict[str, Any]
468
+ ) -> ValidationResult:
431
469
  """
432
470
  Validate that a migrated agent maintains compatibility.
433
-
471
+
434
472
  Security Importance:
435
473
  - Ensures privilege escalation doesn't occur during migration
436
474
  - Validates that security constraints are preserved
437
475
  - Prevents addition of dangerous tools without review
438
-
476
+
439
477
  Args:
440
478
  old_agent: Original agent configuration
441
479
  new_agent: Migrated agent configuration
442
-
480
+
443
481
  Returns:
444
482
  ValidationResult with migration validation results
445
483
  """
446
484
  result = ValidationResult(is_valid=True)
447
-
485
+
448
486
  # SECURITY: Check that core functionality is preserved without privilege escalation
449
487
  old_tools = set(old_agent.get("configuration_fields", {}).get("tools", []))
450
488
  new_tools = set(new_agent.get("capabilities", {}).get("tools", []))
451
-
489
+
452
490
  if old_tools != new_tools:
453
491
  missing = old_tools - new_tools
454
492
  added = new_tools - old_tools
@@ -460,19 +498,21 @@ def validate_agent_migration(old_agent: Dict[str, Any], new_agent: Dict[str, Any
460
498
  dangerous_tools = {"Bash", "docker", "kubectl", "aws", "gcloud", "azure"}
461
499
  dangerous_added = added & dangerous_tools
462
500
  if dangerous_added:
463
- result.errors.append(f"SECURITY: Dangerous tools added in migration: {dangerous_added}")
501
+ result.errors.append(
502
+ f"SECURITY: Dangerous tools added in migration: {dangerous_added}"
503
+ )
464
504
  result.is_valid = False
465
-
505
+
466
506
  # Check instruction preservation
467
507
  old_instructions = old_agent.get("narrative_fields", {}).get("instructions", "")
468
508
  new_instructions = new_agent.get("instructions", "")
469
-
509
+
470
510
  if old_instructions and not new_instructions:
471
511
  result.errors.append("Instructions lost in migration")
472
512
  result.is_valid = False
473
513
  elif len(old_instructions) > len(new_instructions) * 1.1: # Allow 10% reduction
474
514
  result.warnings.append("Significant instruction content reduction in migration")
475
-
515
+
476
516
  return result
477
517
 
478
518
 
@@ -486,20 +526,20 @@ def validate_agent_file(file_path: Path) -> ValidationResult:
486
526
  def validate_all_agents(directory: Path) -> Tuple[int, int, List[str]]:
487
527
  """
488
528
  Validate all agents in a directory and return summary.
489
-
529
+
490
530
  Returns:
491
531
  Tuple of (valid_count, invalid_count, error_messages)
492
532
  """
493
533
  validator = AgentValidator()
494
534
  results = validator.validate_directory(directory)
495
-
535
+
496
536
  valid_count = sum(1 for r in results.values() if r.is_valid)
497
537
  invalid_count = len(results) - valid_count
498
-
538
+
499
539
  error_messages = []
500
540
  for filename, result in results.items():
501
541
  if not result.is_valid:
502
542
  for error in result.errors:
503
543
  error_messages.append(f"{filename}: {error}")
504
-
505
- return valid_count, invalid_count, error_messages
544
+
545
+ return valid_count, invalid_count, error_messages