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
@@ -1,616 +0,0 @@
1
- """Graceful degradation service for Memory Guardian system.
2
-
3
- Implements fallback strategies when monitoring components fail, ensuring
4
- the system continues to function even with reduced capabilities.
5
- """
6
-
7
- import asyncio
8
- import logging
9
- import os
10
- import subprocess
11
- import time
12
- from dataclasses import dataclass
13
- from datetime import datetime
14
- from enum import Enum
15
- from pathlib import Path
16
- from typing import Dict, List, Optional, Any, Callable, Set
17
-
18
- from claude_mpm.services.core.base import BaseService
19
-
20
-
21
- class DegradationLevel(Enum):
22
- """System degradation levels."""
23
- NORMAL = "normal" # Full functionality
24
- MINOR = "minor" # Some features disabled
25
- MODERATE = "moderate" # Running with reduced capabilities
26
- SEVERE = "severe" # Minimal functionality
27
- EMERGENCY = "emergency" # Emergency mode only
28
-
29
-
30
- class FeatureState(Enum):
31
- """Feature availability state."""
32
- AVAILABLE = "available"
33
- DEGRADED = "degraded"
34
- UNAVAILABLE = "unavailable"
35
-
36
-
37
- @dataclass
38
- class Feature:
39
- """System feature definition."""
40
- name: str
41
- state: FeatureState
42
- fallback_mode: Optional[str]
43
- reason: Optional[str]
44
- degraded_at: Optional[float]
45
-
46
- def to_dict(self) -> Dict[str, Any]:
47
- """Convert to dictionary."""
48
- return {
49
- 'name': self.name,
50
- 'state': self.state.value,
51
- 'fallback_mode': self.fallback_mode,
52
- 'reason': self.reason,
53
- 'degraded_at': self.degraded_at,
54
- 'degraded_at_iso': datetime.fromtimestamp(self.degraded_at).isoformat() if self.degraded_at else None
55
- }
56
-
57
-
58
- @dataclass
59
- class DegradationStatus:
60
- """System degradation status."""
61
- level: DegradationLevel
62
- features: List[Feature]
63
- active_fallbacks: List[str]
64
- notifications: List[str]
65
- timestamp: float
66
-
67
- @property
68
- def available_features(self) -> int:
69
- """Count of available features."""
70
- return sum(1 for f in self.features if f.state == FeatureState.AVAILABLE)
71
-
72
- @property
73
- def degraded_features(self) -> int:
74
- """Count of degraded features."""
75
- return sum(1 for f in self.features if f.state == FeatureState.DEGRADED)
76
-
77
- @property
78
- def unavailable_features(self) -> int:
79
- """Count of unavailable features."""
80
- return sum(1 for f in self.features if f.state == FeatureState.UNAVAILABLE)
81
-
82
- def to_dict(self) -> Dict[str, Any]:
83
- """Convert to dictionary."""
84
- return {
85
- 'level': self.level.value,
86
- 'available_features': self.available_features,
87
- 'degraded_features': self.degraded_features,
88
- 'unavailable_features': self.unavailable_features,
89
- 'features': [f.to_dict() for f in self.features],
90
- 'active_fallbacks': self.active_fallbacks,
91
- 'notifications': self.notifications,
92
- 'timestamp': self.timestamp,
93
- 'timestamp_iso': datetime.fromtimestamp(self.timestamp).isoformat()
94
- }
95
-
96
-
97
- class GracefulDegradation(BaseService):
98
- """Service for managing graceful degradation of system features."""
99
-
100
- def __init__(
101
- self,
102
- enable_notifications: bool = True,
103
- log_degradation_events: bool = True,
104
- state_file: Optional[Path] = None
105
- ):
106
- """Initialize graceful degradation service.
107
-
108
- Args:
109
- enable_notifications: Whether to show user notifications
110
- log_degradation_events: Whether to log degradation events
111
- state_file: Optional file for persisting degradation state
112
- """
113
- super().__init__("GracefulDegradation")
114
-
115
- # Configuration
116
- self.enable_notifications = enable_notifications
117
- self.log_degradation_events = log_degradation_events
118
- self.state_file = state_file
119
-
120
- # Feature registry
121
- self.features: Dict[str, Feature] = {}
122
- self.fallback_handlers: Dict[str, Callable] = {}
123
- self.recovery_handlers: Dict[str, Callable] = {}
124
-
125
- # State tracking
126
- self.degradation_level = DegradationLevel.NORMAL
127
- self.active_fallbacks: Set[str] = set()
128
- self.pending_notifications: List[str] = []
129
- self.degradation_history: List[DegradationStatus] = []
130
-
131
- # Initialize core features
132
- self._initialize_core_features()
133
-
134
- self.log_info("Graceful degradation service initialized")
135
-
136
- async def initialize(self) -> bool:
137
- """Initialize the graceful degradation service.
138
-
139
- Returns:
140
- True if initialization successful
141
- """
142
- try:
143
- self.log_info("Initializing graceful degradation service")
144
-
145
- # Check system capabilities
146
- await self._check_system_capabilities()
147
-
148
- # Start notification handler
149
- if self.enable_notifications:
150
- asyncio.create_task(self._notification_handler())
151
-
152
- self._initialized = True
153
- self.log_info("Graceful degradation service initialized successfully")
154
- return True
155
-
156
- except Exception as e:
157
- self.log_error(f"Failed to initialize graceful degradation: {e}")
158
- return False
159
-
160
- async def shutdown(self) -> None:
161
- """Shutdown the graceful degradation service."""
162
- try:
163
- self.log_info("Shutting down graceful degradation service")
164
-
165
- # Save state if configured
166
- if self.state_file:
167
- self._save_state()
168
-
169
- self._shutdown = True
170
- self.log_info("Graceful degradation service shutdown complete")
171
-
172
- except Exception as e:
173
- self.log_error(f"Error during graceful degradation shutdown: {e}")
174
-
175
- def register_feature(
176
- self,
177
- name: str,
178
- fallback_handler: Optional[Callable] = None,
179
- recovery_handler: Optional[Callable] = None
180
- ) -> None:
181
- """Register a system feature with optional fallback/recovery handlers.
182
-
183
- Args:
184
- name: Feature name
185
- fallback_handler: Handler to call when feature degrades
186
- recovery_handler: Handler to call when feature recovers
187
- """
188
- self.features[name] = Feature(
189
- name=name,
190
- state=FeatureState.AVAILABLE,
191
- fallback_mode=None,
192
- reason=None,
193
- degraded_at=None
194
- )
195
-
196
- if fallback_handler:
197
- self.fallback_handlers[name] = fallback_handler
198
-
199
- if recovery_handler:
200
- self.recovery_handlers[name] = recovery_handler
201
-
202
- self.log_debug(f"Registered feature: {name}")
203
-
204
- async def degrade_feature(
205
- self,
206
- feature_name: str,
207
- reason: str,
208
- fallback_mode: Optional[str] = None
209
- ) -> bool:
210
- """Degrade a system feature to fallback mode.
211
-
212
- Args:
213
- feature_name: Name of feature to degrade
214
- reason: Reason for degradation
215
- fallback_mode: Optional description of fallback mode
216
-
217
- Returns:
218
- True if degradation successful
219
- """
220
- if feature_name not in self.features:
221
- self.log_warning(f"Unknown feature: {feature_name}")
222
- return False
223
-
224
- feature = self.features[feature_name]
225
-
226
- if feature.state == FeatureState.UNAVAILABLE:
227
- self.log_debug(f"Feature {feature_name} already unavailable")
228
- return True
229
-
230
- # Update feature state
231
- old_state = feature.state
232
- feature.state = FeatureState.DEGRADED
233
- feature.fallback_mode = fallback_mode or "basic mode"
234
- feature.reason = reason
235
- feature.degraded_at = time.time()
236
-
237
- # Log degradation
238
- if self.log_degradation_events:
239
- self.log_warning(
240
- f"Feature degraded: {feature_name} - {reason} "
241
- f"(fallback: {feature.fallback_mode})"
242
- )
243
-
244
- # Add notification
245
- self._add_notification(
246
- f"System feature '{feature_name}' running in {feature.fallback_mode} due to: {reason}"
247
- )
248
-
249
- # Execute fallback handler if available
250
- if feature_name in self.fallback_handlers:
251
- try:
252
- await self.fallback_handlers[feature_name](reason)
253
- except Exception as e:
254
- self.log_error(f"Fallback handler failed for {feature_name}: {e}")
255
-
256
- # Add to active fallbacks
257
- self.active_fallbacks.add(feature_name)
258
-
259
- # Update degradation level
260
- self._update_degradation_level()
261
-
262
- # Record status
263
- self._record_status()
264
-
265
- return True
266
-
267
- async def disable_feature(
268
- self,
269
- feature_name: str,
270
- reason: str
271
- ) -> bool:
272
- """Completely disable a system feature.
273
-
274
- Args:
275
- feature_name: Name of feature to disable
276
- reason: Reason for disabling
277
-
278
- Returns:
279
- True if disable successful
280
- """
281
- if feature_name not in self.features:
282
- self.log_warning(f"Unknown feature: {feature_name}")
283
- return False
284
-
285
- feature = self.features[feature_name]
286
-
287
- if feature.state == FeatureState.UNAVAILABLE:
288
- self.log_debug(f"Feature {feature_name} already disabled")
289
- return True
290
-
291
- # Update feature state
292
- feature.state = FeatureState.UNAVAILABLE
293
- feature.fallback_mode = None
294
- feature.reason = reason
295
- feature.degraded_at = time.time()
296
-
297
- # Log disable
298
- if self.log_degradation_events:
299
- self.log_error(f"Feature disabled: {feature_name} - {reason}")
300
-
301
- # Add notification
302
- self._add_notification(
303
- f"System feature '{feature_name}' has been disabled: {reason}"
304
- )
305
-
306
- # Remove from active fallbacks if present
307
- self.active_fallbacks.discard(feature_name)
308
-
309
- # Update degradation level
310
- self._update_degradation_level()
311
-
312
- # Record status
313
- self._record_status()
314
-
315
- return True
316
-
317
- async def recover_feature(self, feature_name: str) -> bool:
318
- """Recover a degraded feature to normal operation.
319
-
320
- Args:
321
- feature_name: Name of feature to recover
322
-
323
- Returns:
324
- True if recovery successful
325
- """
326
- if feature_name not in self.features:
327
- self.log_warning(f"Unknown feature: {feature_name}")
328
- return False
329
-
330
- feature = self.features[feature_name]
331
-
332
- if feature.state == FeatureState.AVAILABLE:
333
- self.log_debug(f"Feature {feature_name} already available")
334
- return True
335
-
336
- # Update feature state
337
- old_state = feature.state
338
- feature.state = FeatureState.AVAILABLE
339
- feature.fallback_mode = None
340
- feature.reason = None
341
- feature.degraded_at = None
342
-
343
- # Log recovery
344
- self.log_info(f"Feature recovered: {feature_name}")
345
-
346
- # Add notification
347
- self._add_notification(
348
- f"System feature '{feature_name}' has been restored to normal operation"
349
- )
350
-
351
- # Execute recovery handler if available
352
- if feature_name in self.recovery_handlers:
353
- try:
354
- await self.recovery_handlers[feature_name]()
355
- except Exception as e:
356
- self.log_error(f"Recovery handler failed for {feature_name}: {e}")
357
-
358
- # Remove from active fallbacks
359
- self.active_fallbacks.discard(feature_name)
360
-
361
- # Update degradation level
362
- self._update_degradation_level()
363
-
364
- # Record status
365
- self._record_status()
366
-
367
- return True
368
-
369
- def get_status(self) -> DegradationStatus:
370
- """Get current degradation status.
371
-
372
- Returns:
373
- DegradationStatus object
374
- """
375
- return DegradationStatus(
376
- level=self.degradation_level,
377
- features=list(self.features.values()),
378
- active_fallbacks=list(self.active_fallbacks),
379
- notifications=list(self.pending_notifications),
380
- timestamp=time.time()
381
- )
382
-
383
- def get_feature_state(self, feature_name: str) -> Optional[FeatureState]:
384
- """Get the state of a specific feature.
385
-
386
- Args:
387
- feature_name: Name of feature
388
-
389
- Returns:
390
- FeatureState or None if feature not found
391
- """
392
- feature = self.features.get(feature_name)
393
- return feature.state if feature else None
394
-
395
- def is_degraded(self) -> bool:
396
- """Check if system is running in degraded mode.
397
-
398
- Returns:
399
- True if any features are degraded
400
- """
401
- return self.degradation_level != DegradationLevel.NORMAL
402
-
403
- async def fallback_to_basic_monitoring(self) -> bool:
404
- """Fallback to basic memory monitoring without psutil.
405
-
406
- Returns:
407
- True if fallback successful
408
- """
409
- self.log_info("Falling back to basic memory monitoring")
410
-
411
- # Degrade memory monitoring feature
412
- await self.degrade_feature(
413
- "memory_monitoring",
414
- "psutil unavailable",
415
- "basic OS commands"
416
- )
417
-
418
- # Use platform-specific commands as fallback
419
- if os.name == 'posix':
420
- # Unix-like systems
421
- self._add_notification(
422
- "Using basic memory monitoring via 'ps' command. "
423
- "Install psutil for full functionality."
424
- )
425
- elif os.name == 'nt':
426
- # Windows
427
- self._add_notification(
428
- "Using basic memory monitoring via 'wmic' command. "
429
- "Install psutil for full functionality."
430
- )
431
-
432
- return True
433
-
434
- async def fallback_to_manual_checks(self) -> bool:
435
- """Fallback to manual memory checks when automated monitoring fails.
436
-
437
- Returns:
438
- True if fallback successful
439
- """
440
- self.log_info("Falling back to manual memory checks")
441
-
442
- # Degrade automated monitoring
443
- await self.degrade_feature(
444
- "automated_monitoring",
445
- "monitoring service failure",
446
- "manual periodic checks"
447
- )
448
-
449
- self._add_notification(
450
- "Automated memory monitoring disabled. "
451
- "Manual checks will be performed periodically."
452
- )
453
-
454
- return True
455
-
456
- async def continue_without_state(self) -> bool:
457
- """Continue operation without state preservation.
458
-
459
- Returns:
460
- True if fallback successful
461
- """
462
- self.log_info("Continuing without state preservation")
463
-
464
- # Disable state preservation
465
- await self.disable_feature(
466
- "state_preservation",
467
- "storage failure"
468
- )
469
-
470
- self._add_notification(
471
- "State preservation disabled due to storage issues. "
472
- "System state will not persist across restarts."
473
- )
474
-
475
- return True
476
-
477
- def _initialize_core_features(self) -> None:
478
- """Initialize core system features."""
479
- core_features = [
480
- "memory_monitoring",
481
- "automated_monitoring",
482
- "state_preservation",
483
- "restart_protection",
484
- "health_monitoring",
485
- "process_management",
486
- "notification_system",
487
- "logging_system"
488
- ]
489
-
490
- for feature in core_features:
491
- self.register_feature(feature)
492
-
493
- async def _check_system_capabilities(self) -> None:
494
- """Check and degrade features based on system capabilities."""
495
- # Check for psutil
496
- try:
497
- import psutil
498
- except ImportError:
499
- await self.fallback_to_basic_monitoring()
500
-
501
- # Check for network connectivity
502
- try:
503
- import socket
504
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
505
- sock.settimeout(2)
506
- result = sock.connect_ex(('8.8.8.8', 53))
507
- sock.close()
508
- if result != 0:
509
- await self.degrade_feature(
510
- "health_monitoring",
511
- "no network connectivity",
512
- "local checks only"
513
- )
514
- except:
515
- await self.degrade_feature(
516
- "health_monitoring",
517
- "network check failed",
518
- "local checks only"
519
- )
520
-
521
- # Check for storage access
522
- if self.state_file:
523
- try:
524
- self.state_file.parent.mkdir(parents=True, exist_ok=True)
525
- test_file = self.state_file.parent / '.test'
526
- test_file.write_text('test')
527
- test_file.unlink()
528
- except:
529
- await self.continue_without_state()
530
-
531
- def _update_degradation_level(self) -> None:
532
- """Update overall degradation level based on feature states."""
533
- total_features = len(self.features)
534
- if total_features == 0:
535
- self.degradation_level = DegradationLevel.NORMAL
536
- return
537
-
538
- unavailable_count = sum(1 for f in self.features.values() if f.state == FeatureState.UNAVAILABLE)
539
- degraded_count = sum(1 for f in self.features.values() if f.state == FeatureState.DEGRADED)
540
-
541
- unavailable_ratio = unavailable_count / total_features
542
- degraded_ratio = degraded_count / total_features
543
-
544
- if unavailable_ratio >= 0.5:
545
- self.degradation_level = DegradationLevel.EMERGENCY
546
- elif unavailable_ratio >= 0.25:
547
- self.degradation_level = DegradationLevel.SEVERE
548
- elif degraded_ratio >= 0.5:
549
- self.degradation_level = DegradationLevel.MODERATE
550
- elif degraded_ratio >= 0.25:
551
- self.degradation_level = DegradationLevel.MINOR
552
- else:
553
- self.degradation_level = DegradationLevel.NORMAL
554
-
555
- def _add_notification(self, message: str) -> None:
556
- """Add a notification for the user.
557
-
558
- Args:
559
- message: Notification message
560
- """
561
- if self.enable_notifications:
562
- self.pending_notifications.append(message)
563
- self.log_info(f"Notification: {message}")
564
-
565
- def _record_status(self) -> None:
566
- """Record current degradation status."""
567
- status = self.get_status()
568
- self.degradation_history.append(status)
569
-
570
- # Trim history
571
- if len(self.degradation_history) > 100:
572
- self.degradation_history = self.degradation_history[-100:]
573
-
574
- async def _notification_handler(self) -> None:
575
- """Background task to handle user notifications."""
576
- while not self._shutdown:
577
- try:
578
- if self.pending_notifications:
579
- # Process pending notifications
580
- notifications = list(self.pending_notifications)
581
- self.pending_notifications.clear()
582
-
583
- for notification in notifications:
584
- # In a real implementation, this would show system notifications
585
- # For now, just log them
586
- self.log_info(f"USER NOTIFICATION: {notification}")
587
-
588
- await asyncio.sleep(5) # Check every 5 seconds
589
-
590
- except Exception as e:
591
- self.log_error(f"Error in notification handler: {e}")
592
- await asyncio.sleep(5)
593
-
594
- def _save_state(self) -> None:
595
- """Save degradation state to file."""
596
- if not self.state_file:
597
- return
598
-
599
- try:
600
- import json
601
-
602
- state = {
603
- 'degradation_level': self.degradation_level.value,
604
- 'features': [f.to_dict() for f in self.features.values()],
605
- 'active_fallbacks': list(self.active_fallbacks),
606
- 'history': [s.to_dict() for s in self.degradation_history[-10:]]
607
- }
608
-
609
- self.state_file.parent.mkdir(parents=True, exist_ok=True)
610
- with open(self.state_file, 'w') as f:
611
- json.dump(state, f, indent=2)
612
-
613
- self.log_debug(f"Saved degradation state to {self.state_file}")
614
-
615
- except Exception as e:
616
- self.log_error(f"Failed to save degradation state: {e}")