claude-mpm 3.4.10__py3-none-any.whl → 5.4.55__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/BUILD_NUMBER +1 -0
- claude_mpm/VERSION +1 -0
- claude_mpm/__init__.py +50 -12
- claude_mpm/__main__.py +7 -2
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +290 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
- claude_mpm/agents/MEMORY.md +72 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1402 -0
- claude_mpm/agents/WORKFLOW.md +111 -0
- claude_mpm/agents/__init__.py +92 -80
- claude_mpm/agents/agent-template.yaml +83 -0
- claude_mpm/agents/agent_loader.py +560 -745
- claude_mpm/agents/agent_loader_integration.py +53 -55
- claude_mpm/agents/agents_metadata.py +186 -27
- claude_mpm/agents/async_agent_loader.py +436 -0
- claude_mpm/agents/base_agent.json +8 -4
- claude_mpm/agents/frontmatter_validator.py +754 -0
- claude_mpm/agents/system_agent_config.py +222 -155
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/__init__.py +17 -13
- claude_mpm/agents/templates/circuit-breakers.md +1391 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/git-file-tracking.md +584 -0
- claude_mpm/agents/templates/pm-examples.md +474 -0
- claude_mpm/agents/templates/pm-red-flags.md +310 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/response-format.md +583 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/agents/templates/validation-templates.md +312 -0
- claude_mpm/cli/__init__.py +90 -128
- claude_mpm/cli/__main__.py +33 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/__init__.py +36 -12
- claude_mpm/cli/commands/agent_manager.py +1403 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +335 -0
- claude_mpm/cli/commands/agents.py +2503 -168
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +540 -0
- claude_mpm/cli/commands/analyze.py +553 -0
- claude_mpm/cli/commands/analyze_code.py +528 -0
- claude_mpm/cli/commands/auto_configure.py +1053 -0
- claude_mpm/cli/commands/cleanup.py +588 -0
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
- claude_mpm/cli/commands/config.py +586 -0
- claude_mpm/cli/commands/configure.py +2654 -0
- claude_mpm/cli/commands/configure_agent_display.py +282 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +184 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/dashboard.py +286 -0
- claude_mpm/cli/commands/debug.py +1386 -0
- claude_mpm/cli/commands/doctor.py +243 -0
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/info.py +195 -74
- claude_mpm/cli/commands/local_deploy.py +534 -0
- claude_mpm/cli/commands/mcp.py +205 -0
- claude_mpm/cli/commands/mcp_command_router.py +161 -0
- claude_mpm/cli/commands/mcp_config.py +154 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_external_commands.py +249 -0
- claude_mpm/cli/commands/mcp_install_commands.py +346 -0
- claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
- claude_mpm/cli/commands/mcp_server_commands.py +155 -0
- claude_mpm/cli/commands/mcp_setup_external.py +868 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +585 -846
- claude_mpm/cli/commands/monitor.py +228 -310
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +759 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +195 -0
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +910 -488
- claude_mpm/cli/commands/search.py +458 -0
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +1246 -0
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/commands/tickets.py +536 -53
- claude_mpm/cli/commands/uninstall.py +176 -0
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/commands/verify.py +119 -0
- claude_mpm/cli/executor.py +297 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +21 -0
- claude_mpm/cli/interactive/agent_wizard.py +1947 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parser.py +87 -563
- claude_mpm/cli/parsers/__init__.py +35 -0
- claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +575 -0
- claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
- claude_mpm/cli/parsers/analyze_parser.py +135 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
- claude_mpm/cli/parsers/base_parser.py +644 -0
- claude_mpm/cli/parsers/config_parser.py +208 -0
- claude_mpm/cli/parsers/configure_parser.py +138 -0
- claude_mpm/cli/parsers/dashboard_parser.py +113 -0
- claude_mpm/cli/parsers/debug_parser.py +319 -0
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mcp_parser.py +195 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +142 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -0
- claude_mpm/cli/parsers/run_parser.py +157 -0
- claude_mpm/cli/parsers/search_parser.py +245 -0
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +277 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/shared/__init__.py +40 -0
- claude_mpm/cli/shared/argument_patterns.py +205 -0
- claude_mpm/cli/shared/base_command.py +242 -0
- claude_mpm/cli/shared/error_handling.py +242 -0
- claude_mpm/cli/shared/output_formatters.py +241 -0
- claude_mpm/cli/startup.py +1743 -0
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/startup_logging.py +839 -0
- claude_mpm/cli/utils.py +136 -47
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +42 -64
- claude_mpm/commands/__init__.py +14 -0
- claude_mpm/commands/mpm-config.md +28 -0
- claude_mpm/commands/mpm-doctor.md +20 -0
- claude_mpm/commands/mpm-help.md +20 -0
- claude_mpm/commands/mpm-init.md +120 -0
- claude_mpm/commands/mpm-monitor.md +31 -0
- claude_mpm/commands/mpm-organize.md +120 -0
- claude_mpm/commands/mpm-postmortem.md +21 -0
- claude_mpm/commands/mpm-session-resume.md +30 -0
- claude_mpm/commands/mpm-status.md +20 -0
- claude_mpm/commands/mpm-ticket-view.md +109 -0
- claude_mpm/commands/mpm-version.md +20 -0
- claude_mpm/commands/mpm.md +31 -0
- claude_mpm/config/__init__.py +42 -2
- claude_mpm/config/agent_config.py +402 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +352 -0
- claude_mpm/config/experimental_features.py +217 -0
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/config/paths.py +258 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/config/socketio_config.py +125 -83
- claude_mpm/constants.py +132 -22
- claude_mpm/core/__init__.py +62 -36
- claude_mpm/core/agent_name_normalizer.py +71 -73
- claude_mpm/core/agent_registry.py +385 -492
- claude_mpm/core/agent_session_manager.py +81 -70
- claude_mpm/core/api_validator.py +330 -0
- claude_mpm/core/base_service.py +159 -122
- claude_mpm/core/cache.py +560 -0
- claude_mpm/core/claude_runner.py +696 -916
- claude_mpm/core/config.py +613 -122
- claude_mpm/core/config_aliases.py +74 -73
- claude_mpm/core/config_constants.py +314 -0
- claude_mpm/core/constants.py +361 -0
- claude_mpm/core/container.py +646 -104
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/error_handler.py +623 -0
- claude_mpm/core/exceptions.py +536 -0
- claude_mpm/core/factories.py +105 -109
- claude_mpm/core/file_utils.py +764 -0
- claude_mpm/core/framework/__init__.py +25 -0
- claude_mpm/core/framework/formatters/__init__.py +11 -0
- claude_mpm/core/framework/formatters/capability_generator.py +367 -0
- claude_mpm/core/framework/formatters/content_formatter.py +278 -0
- claude_mpm/core/framework/formatters/context_generator.py +185 -0
- claude_mpm/core/framework/loaders/__init__.py +13 -0
- claude_mpm/core/framework/loaders/agent_loader.py +213 -0
- claude_mpm/core/framework/loaders/file_loader.py +176 -0
- claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
- claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
- claude_mpm/core/framework/processors/__init__.py +11 -0
- claude_mpm/core/framework/processors/memory_processor.py +230 -0
- claude_mpm/core/framework/processors/metadata_processor.py +146 -0
- claude_mpm/core/framework/processors/template_processor.py +244 -0
- claude_mpm/core/framework_loader.py +485 -414
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +246 -86
- claude_mpm/core/hook_performance_config.py +147 -0
- claude_mpm/core/injectable_service.py +72 -63
- claude_mpm/core/instruction_reinforcement_hook.py +267 -0
- claude_mpm/core/interactive_session.py +670 -0
- claude_mpm/core/interfaces.py +570 -164
- claude_mpm/core/lazy.py +467 -0
- claude_mpm/core/log_manager.py +707 -0
- claude_mpm/core/logger.py +295 -134
- claude_mpm/core/logging_config.py +474 -0
- claude_mpm/core/logging_utils.py +520 -0
- claude_mpm/core/minimal_framework_loader.py +24 -22
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +594 -0
- claude_mpm/core/optimized_agent_loader.py +479 -0
- claude_mpm/core/optimized_startup.py +554 -0
- claude_mpm/core/output_style_manager.py +483 -0
- claude_mpm/core/pm_hook_interceptor.py +197 -82
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/service_registry.py +153 -116
- claude_mpm/core/session_manager.py +179 -64
- claude_mpm/core/shared/__init__.py +17 -0
- claude_mpm/core/shared/config_loader.py +326 -0
- claude_mpm/core/shared/path_resolver.py +281 -0
- claude_mpm/core/shared/singleton_manager.py +221 -0
- claude_mpm/core/socketio_pool.py +400 -137
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/tool_access_control.py +64 -57
- claude_mpm/core/types.py +307 -0
- claude_mpm/core/typing_utils.py +553 -0
- claude_mpm/core/unified_agent_registry.py +969 -0
- claude_mpm/core/unified_config.py +570 -0
- claude_mpm/core/unified_paths.py +941 -0
- claude_mpm/dashboard/__init__.py +12 -0
- claude_mpm/dashboard/api/simple_directory.py +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/__init__.py +10 -0
- claude_mpm/experimental/cli_enhancements.py +104 -89
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +76 -66
- claude_mpm/hooks/__init__.py +37 -1
- claude_mpm/hooks/base_hook.py +37 -32
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
- claude_mpm/hooks/claude_hooks/installer.py +806 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
- claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
- claude_mpm/hooks/failure_learning/__init__.py +54 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
- claude_mpm/hooks/instruction_reinforcement.py +301 -0
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +386 -0
- claude_mpm/hooks/kuzu_response_hook.py +179 -0
- claude_mpm/hooks/memory_integration_hook.py +201 -107
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/hooks/tool_call_interceptor.py +92 -76
- claude_mpm/hooks/validation_hooks.py +62 -54
- claude_mpm/init.py +518 -83
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +40 -23
- claude_mpm/models/agent_session.py +538 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/schemas/__init__.py +12 -0
- claude_mpm/scripts/__init__.py +15 -0
- claude_mpm/scripts/claude-hook-handler.sh +227 -0
- claude_mpm/scripts/launch_monitor.py +165 -0
- claude_mpm/scripts/mpm_doctor.py +322 -0
- claude_mpm/scripts/socketio_daemon.py +189 -200
- claude_mpm/scripts/start_activity_logging.py +91 -0
- claude_mpm/services/__init__.py +208 -39
- claude_mpm/services/agent_capabilities_service.py +266 -0
- claude_mpm/services/agents/__init__.py +89 -0
- claude_mpm/services/agents/agent_builder.py +514 -0
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/__init__.py +21 -0
- claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
- claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
- claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
- claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +1369 -0
- claude_mpm/services/agents/deployment/agent_validator.py +376 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
- claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
- claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +70 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +226 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +362 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +162 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +240 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +21 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +319 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
- claude_mpm/services/agents/git_source_manager.py +682 -0
- claude_mpm/services/agents/loading/__init__.py +11 -0
- claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
- claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
- claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
- claude_mpm/services/agents/local_template_manager.py +784 -0
- claude_mpm/services/agents/management/__init__.py +9 -0
- claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
- claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
- claude_mpm/services/agents/memory/__init__.py +22 -0
- claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
- claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
- claude_mpm/services/agents/memory/content_manager.py +470 -0
- claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
- claude_mpm/services/agents/memory/memory_file_service.py +129 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
- claude_mpm/services/agents/memory/template_generator.py +83 -0
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +617 -0
- claude_mpm/services/agents/registry/__init__.py +30 -0
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
- claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1202 -0
- claude_mpm/services/agents/startup_sync.py +259 -0
- claude_mpm/services/agents/toolchain_detector.py +478 -0
- claude_mpm/services/analysis/__init__.py +35 -0
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/async_session_logger.py +665 -0
- claude_mpm/services/claude_session_logger.py +321 -0
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +408 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +590 -0
- claude_mpm/services/cli/memory_crud_service.py +622 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +604 -0
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +372 -0
- claude_mpm/services/cli/startup_checker.py +362 -0
- claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
- claude_mpm/services/command_deployment_service.py +446 -0
- claude_mpm/services/command_handler_service.py +221 -0
- claude_mpm/services/communication/__init__.py +22 -0
- claude_mpm/services/core/__init__.py +108 -0
- claude_mpm/services/core/base.py +269 -0
- claude_mpm/services/core/cache_manager.py +309 -0
- claude_mpm/services/core/interfaces/__init__.py +273 -0
- claude_mpm/services/core/interfaces/agent.py +514 -0
- claude_mpm/services/core/interfaces/communication.py +316 -0
- claude_mpm/services/core/interfaces/health.py +169 -0
- claude_mpm/services/core/interfaces/infrastructure.py +357 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/service.py +405 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/interfaces.py +81 -0
- claude_mpm/services/core/memory_manager.py +682 -0
- claude_mpm/services/core/models/__init__.py +70 -0
- claude_mpm/services/core/models/agent_config.py +384 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +239 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +517 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/__init__.py +18 -0
- claude_mpm/services/diagnostics/checks/__init__.py +38 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/base_check.py +60 -0
- claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
- claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
- claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
- claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
- claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
- claude_mpm/services/diagnostics/models.py +138 -0
- claude_mpm/services/event_aggregator.py +582 -0
- claude_mpm/services/event_bus/__init__.py +18 -0
- claude_mpm/services/event_bus/config.py +186 -0
- claude_mpm/services/event_bus/direct_relay.py +312 -0
- claude_mpm/services/event_bus/event_bus.py +396 -0
- claude_mpm/services/event_bus/relay.py +326 -0
- claude_mpm/services/events/__init__.py +44 -0
- claude_mpm/services/events/consumers/__init__.py +18 -0
- claude_mpm/services/events/consumers/dead_letter.py +306 -0
- claude_mpm/services/events/consumers/logging.py +184 -0
- claude_mpm/services/events/consumers/metrics.py +241 -0
- claude_mpm/services/events/consumers/socketio.py +377 -0
- claude_mpm/services/events/core.py +480 -0
- claude_mpm/services/events/interfaces.py +214 -0
- claude_mpm/services/events/producers/__init__.py +14 -0
- claude_mpm/services/events/producers/hook.py +269 -0
- claude_mpm/services/events/producers/system.py +329 -0
- claude_mpm/services/exceptions.py +433 -353
- claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
- claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +26 -30
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +579 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/hook_installer_service.py +506 -0
- claude_mpm/services/hook_service.py +159 -111
- claude_mpm/services/infrastructure/__init__.py +52 -0
- claude_mpm/services/infrastructure/context_preservation.py +569 -0
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +209 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
- claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
- claude_mpm/services/infrastructure/monitoring/base.py +122 -0
- claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
- claude_mpm/services/infrastructure/monitoring/network.py +219 -0
- claude_mpm/services/infrastructure/monitoring/process.py +343 -0
- claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
- claude_mpm/services/infrastructure/monitoring/service.py +368 -0
- claude_mpm/services/infrastructure/monitoring.py +71 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +155 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +427 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +1542 -0
- claude_mpm/services/mcp_service_verifier.py +732 -0
- claude_mpm/services/memory/__init__.py +19 -0
- claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
- claude_mpm/services/memory/cache/__init__.py +14 -0
- claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
- claude_mpm/services/memory/cache/simple_cache.py +331 -0
- claude_mpm/services/memory/failure_tracker.py +578 -0
- claude_mpm/services/memory/indexed_memory.py +648 -0
- claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
- claude_mpm/services/memory/router.py +951 -0
- claude_mpm/services/memory_hook_service.py +470 -0
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +452 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/__init__.py +20 -0
- claude_mpm/services/monitor/daemon.py +698 -0
- claude_mpm/services/monitor/daemon_manager.py +1076 -0
- claude_mpm/services/monitor/event_emitter.py +350 -0
- claude_mpm/services/monitor/handlers/__init__.py +21 -0
- claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
- claude_mpm/services/monitor/handlers/dashboard.py +299 -0
- claude_mpm/services/monitor/handlers/file.py +264 -0
- claude_mpm/services/monitor/handlers/hooks.py +512 -0
- claude_mpm/services/monitor/management/__init__.py +18 -0
- claude_mpm/services/monitor/management/health.py +124 -0
- claude_mpm/services/monitor/management/lifecycle.py +730 -0
- claude_mpm/services/monitor/server.py +1493 -0
- claude_mpm/services/monitor_build_service.py +349 -0
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/orphan_detection.py +786 -0
- claude_mpm/services/pm_skills_deployer.py +707 -0
- claude_mpm/services/port_manager.py +597 -0
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/project/__init__.py +44 -0
- claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
- claude_mpm/services/project/analyzer_v2.py +566 -0
- claude_mpm/services/project/architecture_analyzer.py +461 -0
- claude_mpm/services/project/archive_manager.py +1045 -0
- claude_mpm/services/project/dependency_analyzer.py +462 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/documentation_manager.py +554 -0
- claude_mpm/services/project/enhanced_analyzer.py +572 -0
- claude_mpm/services/project/language_analyzer.py +265 -0
- claude_mpm/services/project/metrics_collector.py +407 -0
- claude_mpm/services/project/project_organizer.py +1009 -0
- claude_mpm/services/project/registry.py +636 -0
- claude_mpm/services/project/toolchain_analyzer.py +583 -0
- claude_mpm/services/project_port_allocator.py +596 -0
- claude_mpm/services/recovery_manager.py +293 -240
- claude_mpm/services/response_tracker.py +267 -0
- claude_mpm/services/runner_configuration_service.py +605 -0
- claude_mpm/services/self_upgrade_service.py +608 -0
- claude_mpm/services/session_management_service.py +314 -0
- claude_mpm/services/session_manager.py +380 -0
- claude_mpm/services/shared/__init__.py +21 -0
- claude_mpm/services/shared/async_service_base.py +216 -0
- claude_mpm/services/shared/config_service_base.py +301 -0
- claude_mpm/services/shared/lifecycle_service_base.py +308 -0
- claude_mpm/services/shared/manager_base.py +315 -0
- claude_mpm/services/shared/service_factory.py +309 -0
- claude_mpm/services/skills/__init__.py +21 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1324 -0
- claude_mpm/services/skills/selective_skill_deployer.py +744 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +1168 -0
- claude_mpm/services/socketio/__init__.py +25 -0
- claude_mpm/services/socketio/client_proxy.py +229 -0
- claude_mpm/services/socketio/dashboard_server.py +362 -0
- claude_mpm/services/socketio/event_normalizer.py +798 -0
- claude_mpm/services/socketio/handlers/__init__.py +30 -0
- claude_mpm/services/socketio/handlers/base.py +136 -0
- claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
- claude_mpm/services/socketio/handlers/connection.py +643 -0
- claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
- claude_mpm/services/socketio/handlers/file.py +263 -0
- claude_mpm/services/socketio/handlers/git.py +962 -0
- claude_mpm/services/socketio/handlers/hook.py +211 -0
- claude_mpm/services/socketio/handlers/memory.py +26 -0
- claude_mpm/services/socketio/handlers/project.py +24 -0
- claude_mpm/services/socketio/handlers/registry.py +214 -0
- claude_mpm/services/socketio/migration_utils.py +343 -0
- claude_mpm/services/socketio/monitor_client.py +364 -0
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +569 -0
- claude_mpm/services/socketio/server/connection_manager.py +579 -0
- claude_mpm/services/socketio/server/core.py +1079 -0
- claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
- claude_mpm/services/socketio/server/main.py +501 -0
- claude_mpm/services/socketio_client_manager.py +173 -143
- claude_mpm/services/socketio_server.py +38 -1657
- claude_mpm/services/subprocess_launcher_service.py +322 -0
- claude_mpm/services/system_instructions_service.py +270 -0
- claude_mpm/services/ticket_manager.py +25 -209
- claude_mpm/services/ticket_services/__init__.py +26 -0
- claude_mpm/services/ticket_services/crud_service.py +328 -0
- claude_mpm/services/ticket_services/formatter_service.py +290 -0
- claude_mpm/services/ticket_services/search_service.py +324 -0
- claude_mpm/services/ticket_services/validation_service.py +303 -0
- claude_mpm/services/ticket_services/workflow_service.py +244 -0
- claude_mpm/services/unified/__init__.py +65 -0
- claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
- claude_mpm/services/unified/config_strategies/__init__.py +175 -0
- claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
- claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
- claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
- claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
- claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
- claude_mpm/services/unified/deployment_strategies/base.py +553 -0
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
- claude_mpm/services/unified/deployment_strategies/local.py +607 -0
- claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
- claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
- claude_mpm/services/unified/interfaces.py +475 -0
- claude_mpm/services/unified/migration.py +509 -0
- claude_mpm/services/unified/strategies.py +534 -0
- claude_mpm/services/unified/unified_analyzer.py +542 -0
- claude_mpm/services/unified/unified_config.py +691 -0
- claude_mpm/services/unified/unified_deployment.py +466 -0
- claude_mpm/services/utility_service.py +280 -0
- claude_mpm/services/version_control/__init__.py +34 -37
- claude_mpm/services/version_control/branch_strategy.py +26 -17
- claude_mpm/services/version_control/conflict_resolution.py +52 -36
- claude_mpm/services/version_control/git_operations.py +183 -49
- claude_mpm/services/version_control/semantic_versioning.py +172 -61
- claude_mpm/services/version_control/version_parser.py +546 -0
- claude_mpm/services/version_service.py +379 -0
- claude_mpm/services/visualization/__init__.py +15 -0
- claude_mpm/services/visualization/mermaid_generator.py +937 -0
- claude_mpm/skills/__init__.py +42 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +573 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +439 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +405 -0
- claude_mpm/skills/skills_registry.py +347 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/storage/__init__.py +9 -0
- claude_mpm/storage/state_storage.py +546 -0
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/tools/__init__.py +10 -0
- claude_mpm/tools/__main__.py +208 -0
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/tools/code_tree_builder.py +631 -0
- claude_mpm/tools/code_tree_events.py +420 -0
- claude_mpm/tools/socketio_debug.py +671 -0
- claude_mpm/utils/__init__.py +8 -8
- claude_mpm/utils/agent_dependency_loader.py +1090 -0
- claude_mpm/utils/agent_filters.py +261 -0
- claude_mpm/utils/common.py +544 -0
- claude_mpm/utils/config_manager.py +168 -126
- claude_mpm/utils/console.py +11 -0
- claude_mpm/utils/database_connector.py +298 -0
- claude_mpm/utils/dependency_cache.py +373 -0
- claude_mpm/utils/dependency_manager.py +60 -59
- claude_mpm/utils/dependency_strategies.py +381 -0
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/environment_context.py +313 -0
- claude_mpm/utils/error_handler.py +78 -66
- claude_mpm/utils/file_utils.py +305 -0
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/gitignore.py +244 -0
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/log_cleanup.py +627 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/path_operations.py +110 -104
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +823 -0
- claude_mpm/utils/session_logging.py +121 -0
- claude_mpm/utils/structured_questions.py +619 -0
- claude_mpm/utils/subprocess_utils.py +343 -0
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +214 -108
- claude_mpm/validation/frontmatter_validator.py +252 -0
- claude_mpm-5.4.55.dist-info/METADATA +999 -0
- claude_mpm-5.4.55.dist-info/RECORD +868 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/entry_points.txt +1 -3
- claude_mpm-5.4.55.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.55.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
- claude_mpm/agents/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/base_agent_loader.py +0 -529
- claude_mpm/agents/schema/agent_schema.json +0 -314
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/data_engineer.json +0 -110
- claude_mpm/agents/templates/documentation.json +0 -109
- claude_mpm/agents/templates/engineer.json +0 -113
- claude_mpm/agents/templates/ops.json +0 -109
- claude_mpm/agents/templates/pm.json +0 -25
- claude_mpm/agents/templates/qa.json +0 -111
- claude_mpm/agents/templates/research.json +0 -65
- claude_mpm/agents/templates/security.json +0 -113
- claude_mpm/agents/templates/test_integration.json +0 -112
- claude_mpm/agents/templates/version_control.json +0 -107
- claude_mpm/cli/commands/ui.py +0 -57
- claude_mpm/core/simple_runner.py +0 -1046
- claude_mpm/dashboard/open_dashboard.py +0 -34
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/builtin/__init__.py +0 -1
- claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
- claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
- claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
- claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
- claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
- claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
- claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
- claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
- claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
- claude_mpm/orchestration/__init__.py +0 -6
- claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
- claude_mpm/orchestration/archive/factory.py +0 -215
- claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
- claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
- claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
- claude_mpm/orchestration/archive/orchestrator.py +0 -501
- claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
- claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
- claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
- claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
- claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
- claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
- claude_mpm/schemas/workflow_validator.py +0 -411
- claude_mpm/services/agent_deployment.py +0 -1534
- claude_mpm/services/agent_lifecycle_manager.py +0 -1169
- claude_mpm/services/agent_memory_manager.py +0 -1415
- claude_mpm/services/agent_registry.py +0 -676
- claude_mpm/services/deployed_agent_discovery.py +0 -226
- claude_mpm/services/framework_agent_loader.py +0 -337
- claude_mpm/services/framework_claude_md_generator.py +0 -621
- claude_mpm/services/health_monitor.py +0 -892
- claude_mpm/services/memory_router.py +0 -538
- claude_mpm/services/parent_directory_manager/__init__.py +0 -577
- claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
- claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
- claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
- claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
- claude_mpm/services/parent_directory_manager/operations.py +0 -186
- claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
- claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
- claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
- claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
- claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -508
- claude_mpm/ui/__init__.py +0 -1
- claude_mpm/ui/rich_terminal_ui.py +0 -295
- claude_mpm/ui/terminal_ui.py +0 -328
- claude_mpm/utils/paths.py +0 -289
- claude_mpm-3.4.10.dist-info/METADATA +0 -183
- claude_mpm-3.4.10.dist-info/RECORD +0 -201
- claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/top_level.txt +0 -0
claude_mpm/core/config.py
CHANGED
|
@@ -5,20 +5,31 @@ Handles loading configuration from files, environment variables,
|
|
|
5
5
|
and default values with proper validation and type conversion.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
import json
|
|
9
|
+
import logging
|
|
8
10
|
import os
|
|
11
|
+
import threading
|
|
9
12
|
from pathlib import Path
|
|
10
|
-
from typing import Any, Dict, Optional, Union
|
|
11
|
-
|
|
13
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
14
|
+
|
|
15
|
+
import yaml
|
|
16
|
+
|
|
17
|
+
from claude_mpm.core.logging_utils import get_logger
|
|
12
18
|
|
|
13
19
|
from ..utils.config_manager import ConfigurationManager
|
|
20
|
+
from .exceptions import ConfigurationError, FileOperationError
|
|
21
|
+
from .unified_paths import get_path_manager
|
|
14
22
|
|
|
15
|
-
logger =
|
|
23
|
+
logger = get_logger(__name__)
|
|
16
24
|
|
|
17
25
|
|
|
18
26
|
class Config:
|
|
19
27
|
"""
|
|
20
28
|
Configuration manager for Claude PM services.
|
|
21
29
|
|
|
30
|
+
Implements singleton pattern to ensure configuration is loaded only once
|
|
31
|
+
and shared across all services.
|
|
32
|
+
|
|
22
33
|
Supports loading from:
|
|
23
34
|
- Python dictionaries
|
|
24
35
|
- JSON files
|
|
@@ -26,6 +37,34 @@ class Config:
|
|
|
26
37
|
- Environment variables
|
|
27
38
|
"""
|
|
28
39
|
|
|
40
|
+
_instance = None
|
|
41
|
+
_initialized = False
|
|
42
|
+
_success_logged = (
|
|
43
|
+
False # Class-level flag to track if success message was already logged
|
|
44
|
+
)
|
|
45
|
+
_lock = threading.Lock() # Thread safety for singleton initialization
|
|
46
|
+
|
|
47
|
+
def __new__(cls, *args, **kwargs):
|
|
48
|
+
"""Implement singleton pattern to ensure single configuration instance.
|
|
49
|
+
|
|
50
|
+
WHY: Configuration was being loaded 11 times during startup, once for each service.
|
|
51
|
+
This singleton pattern ensures configuration is loaded only once and reused.
|
|
52
|
+
Thread-safe implementation prevents race conditions during concurrent initialization.
|
|
53
|
+
"""
|
|
54
|
+
if cls._instance is None:
|
|
55
|
+
with cls._lock:
|
|
56
|
+
# Double-check locking pattern for thread safety
|
|
57
|
+
if cls._instance is None:
|
|
58
|
+
cls._instance = super().__new__(cls)
|
|
59
|
+
logger.debug("Creating new Config singleton instance")
|
|
60
|
+
else:
|
|
61
|
+
logger.debug(
|
|
62
|
+
"Reusing existing Config singleton instance (concurrent init)"
|
|
63
|
+
)
|
|
64
|
+
else:
|
|
65
|
+
logger.debug("Reusing existing Config singleton instance")
|
|
66
|
+
return cls._instance
|
|
67
|
+
|
|
29
68
|
def __init__(
|
|
30
69
|
self,
|
|
31
70
|
config: Optional[Dict[str, Any]] = None,
|
|
@@ -40,41 +79,191 @@ class Config:
|
|
|
40
79
|
config_file: Path to configuration file (JSON or YAML)
|
|
41
80
|
env_prefix: Prefix for environment variables
|
|
42
81
|
"""
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
# Load from environment variables (new and legacy prefixes)
|
|
56
|
-
self._load_env_vars()
|
|
57
|
-
self._load_legacy_env_vars()
|
|
82
|
+
# Skip initialization if already done (singleton pattern)
|
|
83
|
+
# Use thread-safe check to prevent concurrent initialization
|
|
84
|
+
if Config._initialized:
|
|
85
|
+
logger.debug("Config already initialized, skipping re-initialization")
|
|
86
|
+
# If someone tries to load a different config file after initialization,
|
|
87
|
+
# log a debug message but don't reload
|
|
88
|
+
if config_file and str(config_file) != getattr(self, "_loaded_from", None):
|
|
89
|
+
logger.debug(
|
|
90
|
+
f"Ignoring config_file parameter '{config_file}' - "
|
|
91
|
+
f"configuration already loaded from '{getattr(self, '_loaded_from', 'defaults')}'"
|
|
92
|
+
)
|
|
93
|
+
return
|
|
58
94
|
|
|
59
|
-
#
|
|
60
|
-
|
|
95
|
+
# Thread-safe initialization - acquire lock for ENTIRE initialization process
|
|
96
|
+
with Config._lock:
|
|
97
|
+
# Double-check pattern - check again inside the lock
|
|
98
|
+
if Config._initialized:
|
|
99
|
+
logger.debug(
|
|
100
|
+
"Config already initialized (concurrent), skipping re-initialization"
|
|
101
|
+
)
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
Config._initialized = True
|
|
105
|
+
logger.debug("Initializing Config singleton for the first time")
|
|
106
|
+
|
|
107
|
+
# Initialize instance variables inside the lock to ensure thread safety
|
|
108
|
+
self._config: Dict[str, Any] = {}
|
|
109
|
+
self._env_prefix = env_prefix
|
|
110
|
+
self._config_mgr = ConfigurationManager(cache_enabled=True)
|
|
111
|
+
|
|
112
|
+
# Load base configuration
|
|
113
|
+
if config:
|
|
114
|
+
self._config.update(config)
|
|
115
|
+
|
|
116
|
+
# Track where configuration was loaded from
|
|
117
|
+
self._loaded_from = None
|
|
118
|
+
# Track the actual file we loaded from to prevent re-loading
|
|
119
|
+
self._actual_loaded_file = None
|
|
120
|
+
|
|
121
|
+
# Load from file if provided
|
|
122
|
+
# Note: Only ONE config file should be loaded, and success message shown only once
|
|
123
|
+
if config_file:
|
|
124
|
+
self.load_file(config_file, is_initial_load=True)
|
|
125
|
+
self._loaded_from = str(config_file)
|
|
126
|
+
else:
|
|
127
|
+
# Try to load from standard location: .claude-mpm/configuration.yaml
|
|
128
|
+
default_config = Path.cwd() / ".claude-mpm" / "configuration.yaml"
|
|
129
|
+
if default_config.exists():
|
|
130
|
+
self.load_file(default_config, is_initial_load=True)
|
|
131
|
+
self._loaded_from = str(default_config)
|
|
132
|
+
elif (
|
|
133
|
+
alt_config := Path.cwd() / ".claude-mpm" / "configuration.yml"
|
|
134
|
+
).exists():
|
|
135
|
+
# Also try .yml extension (using walrus operator for cleaner code)
|
|
136
|
+
self.load_file(alt_config, is_initial_load=True)
|
|
137
|
+
self._loaded_from = str(alt_config)
|
|
138
|
+
|
|
139
|
+
# Load from environment variables (new and legacy prefixes)
|
|
140
|
+
self._load_env_vars()
|
|
141
|
+
self._load_legacy_env_vars()
|
|
142
|
+
|
|
143
|
+
# Apply defaults
|
|
144
|
+
self._apply_defaults()
|
|
145
|
+
|
|
146
|
+
def load_file(
|
|
147
|
+
self, file_path: Union[str, Path], is_initial_load: bool = True
|
|
148
|
+
) -> None:
|
|
149
|
+
"""Load configuration from file with enhanced error handling.
|
|
150
|
+
|
|
151
|
+
WHY: Configuration loading failures can cause silent issues. We need
|
|
152
|
+
to provide clear, actionable error messages to help users fix problems.
|
|
61
153
|
|
|
62
|
-
|
|
63
|
-
|
|
154
|
+
Args:
|
|
155
|
+
file_path: Path to the configuration file
|
|
156
|
+
is_initial_load: Whether this is the initial configuration load (for logging control)
|
|
157
|
+
"""
|
|
64
158
|
file_path = Path(file_path)
|
|
65
159
|
|
|
160
|
+
# Check if we've already loaded from this exact file to prevent duplicate messages
|
|
161
|
+
if hasattr(self, "_actual_loaded_file") and self._actual_loaded_file == str(
|
|
162
|
+
file_path
|
|
163
|
+
):
|
|
164
|
+
logger.debug(
|
|
165
|
+
f"Configuration already loaded from {file_path}, skipping reload"
|
|
166
|
+
)
|
|
167
|
+
return
|
|
168
|
+
|
|
66
169
|
if not file_path.exists():
|
|
67
170
|
logger.warning(f"Configuration file not found: {file_path}")
|
|
171
|
+
logger.info(
|
|
172
|
+
f"TIP: Create a configuration file with: mkdir -p {file_path.parent} && touch {file_path}"
|
|
173
|
+
)
|
|
68
174
|
return
|
|
69
175
|
|
|
70
176
|
try:
|
|
177
|
+
# Check if file is readable
|
|
178
|
+
if not os.access(file_path, os.R_OK):
|
|
179
|
+
logger.error(f"Configuration file is not readable: {file_path}")
|
|
180
|
+
logger.info(f"TIP: Fix permissions with: chmod 644 {file_path}")
|
|
181
|
+
return
|
|
182
|
+
|
|
183
|
+
# Check file size (warn if too large)
|
|
184
|
+
file_size = file_path.stat().st_size
|
|
185
|
+
if file_size > 1024 * 1024: # 1MB
|
|
186
|
+
logger.warning(
|
|
187
|
+
f"Configuration file is large ({file_size} bytes): {file_path}"
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Try to load the configuration
|
|
71
191
|
file_config = self._config_mgr.load_auto(file_path)
|
|
72
192
|
if file_config:
|
|
73
193
|
self._config = self._config_mgr.merge_configs(self._config, file_config)
|
|
74
|
-
|
|
75
|
-
|
|
194
|
+
# Track that we've successfully loaded from this file
|
|
195
|
+
self._actual_loaded_file = str(file_path)
|
|
196
|
+
|
|
197
|
+
# Only log success message once using class-level flag to avoid duplicate messages
|
|
198
|
+
# Check if we should log success message (thread-safe for reads after initialization)
|
|
199
|
+
if is_initial_load:
|
|
200
|
+
if not Config._success_logged:
|
|
201
|
+
# Set flag IMMEDIATELY before logging to prevent any possibility of duplicate
|
|
202
|
+
# messages. No lock needed here since we're already inside __init__ lock
|
|
203
|
+
Config._success_logged = True
|
|
204
|
+
logger.debug(
|
|
205
|
+
f"✓ Successfully loaded configuration from {file_path}"
|
|
206
|
+
)
|
|
207
|
+
else:
|
|
208
|
+
# Configuration already successfully loaded before, just debug log
|
|
209
|
+
logger.debug(
|
|
210
|
+
f"Configuration already loaded, skipping success message for {file_path}"
|
|
211
|
+
)
|
|
212
|
+
else:
|
|
213
|
+
# Not initial load (shouldn't happen in normal flow, but handle gracefully)
|
|
214
|
+
logger.debug(f"Configuration reloaded from {file_path}")
|
|
215
|
+
|
|
216
|
+
# Log important configuration values for debugging
|
|
217
|
+
if logger.isEnabledFor(logging.DEBUG):
|
|
218
|
+
response_logging = file_config.get("response_logging", {})
|
|
219
|
+
if response_logging:
|
|
220
|
+
logger.debug(
|
|
221
|
+
f"Response logging enabled: {response_logging.get('enabled', False)}"
|
|
222
|
+
)
|
|
223
|
+
logger.debug(
|
|
224
|
+
f"Response logging format: {response_logging.get('format', 'json')}"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
except yaml.YAMLError as e:
|
|
228
|
+
logger.error(f"YAML syntax error in {file_path}: {e}")
|
|
229
|
+
if hasattr(e, "problem_mark"):
|
|
230
|
+
mark = e.problem_mark
|
|
231
|
+
logger.error(f"Error at line {mark.line + 1}, column {mark.column + 1}")
|
|
232
|
+
logger.info(
|
|
233
|
+
"TIP: Validate your YAML at https://www.yamllint.com/ or run: python scripts/validate_configuration.py"
|
|
234
|
+
)
|
|
235
|
+
logger.info(
|
|
236
|
+
"TIP: Common issue - YAML requires spaces, not tabs. Fix with: sed -i '' 's/\t/ /g' "
|
|
237
|
+
+ str(file_path)
|
|
238
|
+
)
|
|
239
|
+
# Store error for later retrieval
|
|
240
|
+
self._config["_load_error"] = str(e)
|
|
241
|
+
|
|
242
|
+
except json.JSONDecodeError as e:
|
|
243
|
+
logger.error(f"JSON syntax error in {file_path}: {e}")
|
|
244
|
+
logger.error(f"Error at line {e.lineno}, column {e.colno}")
|
|
245
|
+
logger.info("TIP: Validate your JSON at https://jsonlint.com/")
|
|
246
|
+
self._config["_load_error"] = str(e)
|
|
247
|
+
|
|
248
|
+
except (OSError, PermissionError) as e:
|
|
249
|
+
raise FileOperationError(
|
|
250
|
+
f"Failed to read configuration file: {e}",
|
|
251
|
+
context={
|
|
252
|
+
"file_path": str(file_path),
|
|
253
|
+
"operation": "read",
|
|
254
|
+
"error_type": type(e).__name__,
|
|
255
|
+
},
|
|
256
|
+
) from e
|
|
76
257
|
except Exception as e:
|
|
77
|
-
|
|
258
|
+
# Catch any remaining unexpected errors and wrap them as configuration errors
|
|
259
|
+
raise ConfigurationError(
|
|
260
|
+
f"Unexpected error loading configuration from {file_path}: {e}",
|
|
261
|
+
context={
|
|
262
|
+
"file_path": str(file_path),
|
|
263
|
+
"error_type": type(e).__name__,
|
|
264
|
+
"original_error": str(e),
|
|
265
|
+
},
|
|
266
|
+
) from e
|
|
78
267
|
|
|
79
268
|
def _load_env_vars(self) -> None:
|
|
80
269
|
"""Load configuration from environment variables."""
|
|
@@ -116,15 +305,14 @@ class Config:
|
|
|
116
305
|
# Boolean conversion
|
|
117
306
|
if value.lower() in ("true", "yes", "1", "on"):
|
|
118
307
|
return True
|
|
119
|
-
|
|
308
|
+
if value.lower() in ("false", "no", "0", "off"):
|
|
120
309
|
return False
|
|
121
310
|
|
|
122
311
|
# Numeric conversion
|
|
123
312
|
try:
|
|
124
313
|
if "." in value:
|
|
125
314
|
return float(value)
|
|
126
|
-
|
|
127
|
-
return int(value)
|
|
315
|
+
return int(value)
|
|
128
316
|
except ValueError:
|
|
129
317
|
pass
|
|
130
318
|
|
|
@@ -178,7 +366,7 @@ class Config:
|
|
|
178
366
|
"file_descriptors": 1000,
|
|
179
367
|
"max_clients": 1000,
|
|
180
368
|
"max_error_rate": 0.1,
|
|
181
|
-
"network_timeout": 2.0
|
|
369
|
+
"network_timeout": 2.0,
|
|
182
370
|
},
|
|
183
371
|
# Automatic recovery configuration
|
|
184
372
|
"recovery": {
|
|
@@ -189,14 +377,14 @@ class Config:
|
|
|
189
377
|
"circuit_breaker": {
|
|
190
378
|
"failure_threshold": 5,
|
|
191
379
|
"timeout_seconds": 300,
|
|
192
|
-
"success_threshold": 3
|
|
380
|
+
"success_threshold": 3,
|
|
193
381
|
},
|
|
194
382
|
"strategy": {
|
|
195
383
|
"warning_threshold": 2,
|
|
196
384
|
"critical_threshold": 1,
|
|
197
385
|
"failure_window_seconds": 300,
|
|
198
|
-
"min_recovery_interval": 60
|
|
199
|
-
}
|
|
386
|
+
"min_recovery_interval": 60,
|
|
387
|
+
},
|
|
200
388
|
},
|
|
201
389
|
# Service management
|
|
202
390
|
"graceful_shutdown_timeout": 30,
|
|
@@ -218,16 +406,39 @@ class Config:
|
|
|
218
406
|
# Task and issue tracking
|
|
219
407
|
"enable_persistent_tracking": True,
|
|
220
408
|
"fallback_tracking_method": "logging", # Options: "logging", "file", "disabled"
|
|
409
|
+
# Memory management configuration
|
|
410
|
+
"memory_management": {
|
|
411
|
+
"enabled": True,
|
|
412
|
+
"claude_json_warning_threshold_kb": 500, # Warn at 500KB
|
|
413
|
+
"claude_json_critical_threshold_kb": 1024, # Critical at 1MB
|
|
414
|
+
"auto_archive_enabled": False, # Don't auto-archive by default
|
|
415
|
+
"archive_retention_days": 90, # Keep archives for 90 days
|
|
416
|
+
"session_retention_hours": 24, # Keep active sessions for 24 hours
|
|
417
|
+
"conversation_retention_days": 30, # Keep conversations for 30 days
|
|
418
|
+
"monitor_memory_usage": True, # Monitor memory usage
|
|
419
|
+
"memory_usage_log_interval": 300, # Log memory usage every 5 minutes
|
|
420
|
+
"max_memory_usage_mb": 2048, # Warn if memory usage exceeds 2GB
|
|
421
|
+
"cleanup_on_startup": False, # Don't auto-cleanup on startup
|
|
422
|
+
"compress_archives": True, # Compress archived files
|
|
423
|
+
},
|
|
221
424
|
# Evaluation system - Phase 2 Mirascope integration
|
|
222
425
|
"enable_evaluation": True,
|
|
223
|
-
"evaluation_storage_path": str(
|
|
426
|
+
"evaluation_storage_path": str(
|
|
427
|
+
get_path_manager().get_user_config_dir() / "training"
|
|
428
|
+
),
|
|
224
429
|
"correction_capture_enabled": True,
|
|
225
430
|
"correction_storage_rotation_days": 30,
|
|
226
431
|
"evaluation_logging_enabled": True,
|
|
227
432
|
"auto_prompt_improvement": False, # Disabled by default for Phase 1
|
|
228
433
|
# Mirascope evaluation settings
|
|
229
434
|
"evaluation_provider": "auto", # auto, openai, anthropic
|
|
230
|
-
"evaluation_criteria": [
|
|
435
|
+
"evaluation_criteria": [
|
|
436
|
+
"correctness",
|
|
437
|
+
"relevance",
|
|
438
|
+
"completeness",
|
|
439
|
+
"clarity",
|
|
440
|
+
"helpfulness",
|
|
441
|
+
],
|
|
231
442
|
"evaluation_caching_enabled": True,
|
|
232
443
|
"evaluation_cache_ttl_hours": 24,
|
|
233
444
|
"evaluation_cache_max_size": 1000,
|
|
@@ -259,23 +470,23 @@ class Config:
|
|
|
259
470
|
"correction_compression_enabled": True,
|
|
260
471
|
# Agent Memory System configuration
|
|
261
472
|
"memory": {
|
|
262
|
-
"enabled": True,
|
|
263
|
-
"auto_learning": True,
|
|
473
|
+
"enabled": True, # Master switch for memory system
|
|
474
|
+
"auto_learning": True, # Automatic learning extraction (changed default to True)
|
|
264
475
|
"limits": {
|
|
265
|
-
"default_size_kb":
|
|
266
|
-
"max_sections": 10,
|
|
267
|
-
"max_items_per_section": 15,
|
|
268
|
-
"max_line_length": 120
|
|
476
|
+
"default_size_kb": 80, # Default file size limit (80KB ~20k tokens)
|
|
477
|
+
"max_sections": 10, # Maximum sections per file
|
|
478
|
+
"max_items_per_section": 15, # Maximum items per section
|
|
479
|
+
"max_line_length": 120, # Maximum line length
|
|
269
480
|
},
|
|
270
481
|
"agent_overrides": {
|
|
271
|
-
"research": {
|
|
272
|
-
"size_kb":
|
|
273
|
-
"auto_learning": True
|
|
482
|
+
"research": { # Research agent override
|
|
483
|
+
"size_kb": 120, # Can have larger memory (120KB ~30k tokens)
|
|
484
|
+
"auto_learning": True, # Enable auto learning
|
|
274
485
|
},
|
|
275
|
-
"qa": {
|
|
276
|
-
"auto_learning": True
|
|
277
|
-
}
|
|
278
|
-
}
|
|
486
|
+
"qa": {
|
|
487
|
+
"auto_learning": True
|
|
488
|
+
}, # QA agent override # Enable auto learning
|
|
489
|
+
},
|
|
279
490
|
},
|
|
280
491
|
# Socket.IO server health and recovery configuration
|
|
281
492
|
"socketio_server": {
|
|
@@ -292,8 +503,8 @@ class Config:
|
|
|
292
503
|
"memory_mb": 500,
|
|
293
504
|
"file_descriptors": 1000,
|
|
294
505
|
"max_clients": 1000,
|
|
295
|
-
"max_error_rate": 0.1
|
|
296
|
-
}
|
|
506
|
+
"max_error_rate": 0.1,
|
|
507
|
+
},
|
|
297
508
|
},
|
|
298
509
|
"recovery": {
|
|
299
510
|
"enabled": True,
|
|
@@ -302,32 +513,111 @@ class Config:
|
|
|
302
513
|
"circuit_breaker": {
|
|
303
514
|
"failure_threshold": 5,
|
|
304
515
|
"timeout_seconds": 300,
|
|
305
|
-
"success_threshold": 3
|
|
516
|
+
"success_threshold": 3,
|
|
306
517
|
},
|
|
307
518
|
"strategy": {
|
|
308
519
|
"warning_threshold": 2,
|
|
309
520
|
"critical_threshold": 1,
|
|
310
521
|
"failure_window_seconds": 300,
|
|
311
|
-
"min_recovery_interval": 60
|
|
522
|
+
"min_recovery_interval": 60,
|
|
312
523
|
},
|
|
313
524
|
"actions": {
|
|
314
525
|
"log_warning": True,
|
|
315
526
|
"clear_connections": True,
|
|
316
527
|
"restart_service": True,
|
|
317
|
-
"emergency_stop": True
|
|
528
|
+
"emergency_stop": True,
|
|
529
|
+
},
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
# Monitor server configuration (decoupled from dashboard)
|
|
533
|
+
"monitor_server": {
|
|
534
|
+
"host": "localhost",
|
|
535
|
+
"port": 8765, # Default monitor port (shared with dashboard)
|
|
536
|
+
"enable_health_monitoring": True,
|
|
537
|
+
"auto_start": False, # Don't auto-start with dashboard by default
|
|
538
|
+
"event_buffer_size": 2000, # Larger buffer for monitor server
|
|
539
|
+
"client_timeout": 60, # Timeout for inactive clients
|
|
540
|
+
},
|
|
541
|
+
# Dashboard server configuration (connects to monitor)
|
|
542
|
+
"dashboard_server": {
|
|
543
|
+
"host": "localhost",
|
|
544
|
+
"port": 8765, # Dashboard UI port
|
|
545
|
+
"monitor_host": "localhost", # Monitor server host to connect to
|
|
546
|
+
"monitor_port": 8765, # Monitor server port to connect to
|
|
547
|
+
"auto_connect_monitor": True, # Automatically connect to monitor
|
|
548
|
+
"monitor_reconnect": True, # Auto-reconnect to monitor if disconnected
|
|
549
|
+
"fallback_standalone": True, # Run in standalone mode if monitor unavailable
|
|
550
|
+
},
|
|
551
|
+
# Agent deployment configuration
|
|
552
|
+
"agent_deployment": {
|
|
553
|
+
"excluded_agents": [], # List of agent IDs to exclude from deployment
|
|
554
|
+
"exclude_dependencies": False, # Whether to exclude agent dependencies too
|
|
555
|
+
"case_sensitive": False, # Whether agent name matching is case-sensitive
|
|
556
|
+
"filter_non_mpm_agents": True, # Filter out non-MPM agents by default
|
|
557
|
+
"mpm_author_patterns": [
|
|
558
|
+
"claude mpm",
|
|
559
|
+
"claude-mpm",
|
|
560
|
+
"anthropic",
|
|
561
|
+
], # Patterns for MPM agents
|
|
562
|
+
},
|
|
563
|
+
# Instruction reinforcement system configuration
|
|
564
|
+
"instruction_reinforcement": {
|
|
565
|
+
"enabled": True,
|
|
566
|
+
"test_mode": False,
|
|
567
|
+
"injection_interval": 5,
|
|
568
|
+
"test_messages": [
|
|
569
|
+
"[TEST-REMINDER] This is an injected instruction reminder",
|
|
570
|
+
"[PM-INSTRUCTION] Remember to delegate all work to agents",
|
|
571
|
+
"[PM-INSTRUCTION] Do not use Edit, Write, or Bash tools directly",
|
|
572
|
+
"[PM-INSTRUCTION] Your role is orchestration and coordination",
|
|
573
|
+
],
|
|
574
|
+
"production_messages": [
|
|
575
|
+
"[PM-REMINDER] Delegate implementation tasks to specialized agents",
|
|
576
|
+
"[PM-REMINDER] Use Task tool for all work delegation",
|
|
577
|
+
"[PM-REMINDER] Focus on orchestration, not implementation",
|
|
578
|
+
"[PM-REMINDER] Your role is coordination and management",
|
|
579
|
+
],
|
|
580
|
+
},
|
|
581
|
+
# Session management configuration
|
|
582
|
+
"session": {
|
|
583
|
+
"auto_save": True, # Enable automatic session saving
|
|
584
|
+
"save_interval": 300, # Auto-save interval in seconds (5 minutes)
|
|
585
|
+
},
|
|
586
|
+
# Update checking configuration
|
|
587
|
+
"updates": {
|
|
588
|
+
"check_enabled": True, # Enable automatic update checks
|
|
589
|
+
"check_frequency": "daily", # Options: "always", "daily", "weekly", "never"
|
|
590
|
+
"check_claude_code": True, # Check Claude Code version compatibility
|
|
591
|
+
"auto_upgrade": False, # Automatically upgrade without prompting (use with caution)
|
|
592
|
+
"cache_ttl": 86400, # Cache update check results (24 hours)
|
|
593
|
+
},
|
|
594
|
+
# Agent synchronization configuration
|
|
595
|
+
"agent_sync": {
|
|
596
|
+
"enabled": True, # Enable automatic agent sync on startup
|
|
597
|
+
"sources": [
|
|
598
|
+
{
|
|
599
|
+
"id": "github-remote",
|
|
600
|
+
"url": "https://raw.githubusercontent.com/bobmatnyc/claude-mpm-agents/main/agents",
|
|
601
|
+
"priority": 100,
|
|
602
|
+
"enabled": True,
|
|
318
603
|
}
|
|
319
|
-
|
|
320
|
-
|
|
604
|
+
],
|
|
605
|
+
"sync_interval": "startup", # Options: "startup", "hourly", "daily", "manual"
|
|
606
|
+
"cache_dir": str(Path.home() / ".claude-mpm" / "cache" / "agents"),
|
|
607
|
+
},
|
|
321
608
|
}
|
|
322
609
|
|
|
323
610
|
# Apply defaults for missing keys
|
|
324
611
|
for key, default_value in defaults.items():
|
|
325
612
|
if key not in self._config:
|
|
326
613
|
self._config[key] = default_value
|
|
327
|
-
|
|
614
|
+
|
|
328
615
|
# Validate health and recovery configuration
|
|
329
616
|
self._validate_health_recovery_config()
|
|
330
617
|
|
|
618
|
+
# Validate session configuration
|
|
619
|
+
self._validate_session_config()
|
|
620
|
+
|
|
331
621
|
def get(self, key: str, default: Any = None) -> Any:
|
|
332
622
|
"""Get configuration value."""
|
|
333
623
|
# Support nested keys with dot notation
|
|
@@ -372,13 +662,38 @@ class Config:
|
|
|
372
662
|
elif format.lower() in ["yaml", "yml"]:
|
|
373
663
|
self._config_mgr.save_yaml(self._config, file_path)
|
|
374
664
|
else:
|
|
375
|
-
raise
|
|
665
|
+
raise ConfigurationError(
|
|
666
|
+
f"Unsupported configuration format: {format}",
|
|
667
|
+
context={
|
|
668
|
+
"format": format,
|
|
669
|
+
"supported_formats": ["json", "yaml", "yml"],
|
|
670
|
+
},
|
|
671
|
+
)
|
|
376
672
|
|
|
377
673
|
logger.info(f"Configuration saved to {file_path}")
|
|
378
674
|
|
|
675
|
+
except (OSError, PermissionError) as e:
|
|
676
|
+
raise FileOperationError(
|
|
677
|
+
f"Failed to write configuration file: {e}",
|
|
678
|
+
context={
|
|
679
|
+
"file_path": str(file_path),
|
|
680
|
+
"operation": "write",
|
|
681
|
+
"format": format,
|
|
682
|
+
"error_type": type(e).__name__,
|
|
683
|
+
},
|
|
684
|
+
) from e
|
|
379
685
|
except Exception as e:
|
|
380
|
-
|
|
381
|
-
|
|
686
|
+
# Re-raise ConfigurationError as-is, wrap others
|
|
687
|
+
if isinstance(e, ConfigurationError):
|
|
688
|
+
raise
|
|
689
|
+
raise ConfigurationError(
|
|
690
|
+
f"Unexpected error saving configuration: {e}",
|
|
691
|
+
context={
|
|
692
|
+
"file_path": str(file_path),
|
|
693
|
+
"format": format,
|
|
694
|
+
"error_type": type(e).__name__,
|
|
695
|
+
},
|
|
696
|
+
) from e
|
|
382
697
|
|
|
383
698
|
def validate(self, schema: Dict[str, Any]) -> bool:
|
|
384
699
|
"""
|
|
@@ -407,7 +722,10 @@ class Config:
|
|
|
407
722
|
return True
|
|
408
723
|
|
|
409
724
|
except Exception as e:
|
|
410
|
-
|
|
725
|
+
# Validation errors should be logged but not raise exceptions
|
|
726
|
+
# since this method returns a boolean result
|
|
727
|
+
logger.error(f"Unexpected error during configuration validation: {e}")
|
|
728
|
+
logger.debug(f"Validation error details: {type(e).__name__}: {e}")
|
|
411
729
|
return False
|
|
412
730
|
|
|
413
731
|
def __getitem__(self, key: str) -> Any:
|
|
@@ -426,89 +744,262 @@ class Config:
|
|
|
426
744
|
"""Validate health monitoring and recovery configuration."""
|
|
427
745
|
try:
|
|
428
746
|
# Validate health thresholds
|
|
429
|
-
thresholds = self.get(
|
|
430
|
-
if
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
747
|
+
thresholds = self.get("health_thresholds", {})
|
|
748
|
+
if (
|
|
749
|
+
thresholds.get("cpu_percent", 0) < 0
|
|
750
|
+
or thresholds.get("cpu_percent", 0) > 100
|
|
751
|
+
):
|
|
752
|
+
logger.warning(
|
|
753
|
+
"CPU threshold should be between 0-100, using default 80"
|
|
754
|
+
)
|
|
755
|
+
self.set("health_thresholds.cpu_percent", 80.0)
|
|
756
|
+
|
|
757
|
+
if thresholds.get("memory_mb", 0) <= 0:
|
|
758
|
+
logger.warning(
|
|
759
|
+
"Memory threshold should be positive, using default 500MB"
|
|
760
|
+
)
|
|
761
|
+
self.set("health_thresholds.memory_mb", 500)
|
|
762
|
+
|
|
763
|
+
if (
|
|
764
|
+
thresholds.get("max_error_rate", 0) < 0
|
|
765
|
+
or thresholds.get("max_error_rate", 0) > 1
|
|
766
|
+
):
|
|
767
|
+
logger.warning(
|
|
768
|
+
"Error rate threshold should be between 0-1, using default 0.1"
|
|
769
|
+
)
|
|
770
|
+
self.set("health_thresholds.max_error_rate", 0.1)
|
|
771
|
+
|
|
442
772
|
# Validate recovery configuration
|
|
443
|
-
recovery_config = self.get(
|
|
444
|
-
if recovery_config.get(
|
|
445
|
-
logger.warning(
|
|
446
|
-
|
|
447
|
-
|
|
773
|
+
recovery_config = self.get("recovery", {})
|
|
774
|
+
if recovery_config.get("max_recovery_attempts", 0) <= 0:
|
|
775
|
+
logger.warning(
|
|
776
|
+
"Max recovery attempts should be positive, using default 5"
|
|
777
|
+
)
|
|
778
|
+
self.set("recovery.max_recovery_attempts", 5)
|
|
779
|
+
|
|
448
780
|
# Validate circuit breaker configuration
|
|
449
|
-
cb_config = recovery_config.get(
|
|
450
|
-
if cb_config.get(
|
|
451
|
-
logger.warning(
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
781
|
+
cb_config = recovery_config.get("circuit_breaker", {})
|
|
782
|
+
if cb_config.get("failure_threshold", 0) <= 0:
|
|
783
|
+
logger.warning(
|
|
784
|
+
"Circuit breaker failure threshold should be positive, using default 5"
|
|
785
|
+
)
|
|
786
|
+
self.set("recovery.circuit_breaker.failure_threshold", 5)
|
|
787
|
+
|
|
788
|
+
if cb_config.get("timeout_seconds", 0) <= 0:
|
|
789
|
+
logger.warning(
|
|
790
|
+
"Circuit breaker timeout should be positive, using default 300"
|
|
791
|
+
)
|
|
792
|
+
self.set("recovery.circuit_breaker.timeout_seconds", 300)
|
|
793
|
+
|
|
458
794
|
except Exception as e:
|
|
459
795
|
logger.error(f"Error validating health/recovery configuration: {e}")
|
|
460
|
-
|
|
796
|
+
|
|
797
|
+
def _validate_session_config(self) -> None:
|
|
798
|
+
"""Validate session management configuration."""
|
|
799
|
+
try:
|
|
800
|
+
session_config = self.get("session", {})
|
|
801
|
+
|
|
802
|
+
# Validate save_interval range (60-1800 seconds)
|
|
803
|
+
save_interval = session_config.get("save_interval", 300)
|
|
804
|
+
if not isinstance(save_interval, int):
|
|
805
|
+
logger.warning(
|
|
806
|
+
f"Session save_interval must be integer, got {type(save_interval).__name__}, using default 300"
|
|
807
|
+
)
|
|
808
|
+
self.set("session.save_interval", 300)
|
|
809
|
+
elif save_interval < 60:
|
|
810
|
+
logger.warning(
|
|
811
|
+
f"Session save_interval must be at least 60 seconds, got {save_interval}, using 60"
|
|
812
|
+
)
|
|
813
|
+
self.set("session.save_interval", 60)
|
|
814
|
+
elif save_interval > 1800:
|
|
815
|
+
logger.warning(
|
|
816
|
+
f"Session save_interval must be at most 1800 seconds (30 min), got {save_interval}, using 1800"
|
|
817
|
+
)
|
|
818
|
+
self.set("session.save_interval", 1800)
|
|
819
|
+
|
|
820
|
+
# Validate auto_save is boolean
|
|
821
|
+
auto_save = session_config.get("auto_save", True)
|
|
822
|
+
if not isinstance(auto_save, bool):
|
|
823
|
+
logger.warning(
|
|
824
|
+
f"Session auto_save must be boolean, got {type(auto_save).__name__}, using True"
|
|
825
|
+
)
|
|
826
|
+
self.set("session.auto_save", True)
|
|
827
|
+
|
|
828
|
+
except Exception as e:
|
|
829
|
+
logger.error(f"Error validating session configuration: {e}")
|
|
830
|
+
|
|
461
831
|
def get_health_monitoring_config(self) -> Dict[str, Any]:
|
|
462
832
|
"""Get health monitoring configuration with defaults."""
|
|
463
833
|
base_config = {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
834
|
+
"enabled": self.get("enable_health_monitoring", True),
|
|
835
|
+
"check_interval": self.get("health_check_interval", 30),
|
|
836
|
+
"history_size": self.get("health_history_size", 100),
|
|
837
|
+
"aggregation_window": self.get("health_aggregation_window", 300),
|
|
838
|
+
"thresholds": self.get(
|
|
839
|
+
"health_thresholds",
|
|
840
|
+
{
|
|
841
|
+
"cpu_percent": 80.0,
|
|
842
|
+
"memory_mb": 500,
|
|
843
|
+
"file_descriptors": 1000,
|
|
844
|
+
"max_clients": 1000,
|
|
845
|
+
"max_error_rate": 0.1,
|
|
846
|
+
"network_timeout": 2.0,
|
|
847
|
+
},
|
|
848
|
+
),
|
|
476
849
|
}
|
|
477
|
-
|
|
850
|
+
|
|
478
851
|
# Merge with socketio-specific config if available
|
|
479
|
-
socketio_config = self.get(
|
|
852
|
+
socketio_config = self.get("socketio_server.health_monitoring", {})
|
|
480
853
|
if socketio_config:
|
|
481
854
|
base_config.update(socketio_config)
|
|
482
|
-
|
|
855
|
+
|
|
483
856
|
return base_config
|
|
484
|
-
|
|
857
|
+
|
|
485
858
|
def get_recovery_config(self) -> Dict[str, Any]:
|
|
486
859
|
"""Get recovery configuration with defaults."""
|
|
487
|
-
base_config = self.get(
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
860
|
+
base_config = self.get(
|
|
861
|
+
"recovery",
|
|
862
|
+
{
|
|
863
|
+
"enabled": True,
|
|
864
|
+
"check_interval": 60,
|
|
865
|
+
"max_recovery_attempts": 5,
|
|
866
|
+
"recovery_timeout": 30,
|
|
867
|
+
"circuit_breaker": {
|
|
868
|
+
"failure_threshold": 5,
|
|
869
|
+
"timeout_seconds": 300,
|
|
870
|
+
"success_threshold": 3,
|
|
871
|
+
},
|
|
872
|
+
"strategy": {
|
|
873
|
+
"warning_threshold": 2,
|
|
874
|
+
"critical_threshold": 1,
|
|
875
|
+
"failure_window_seconds": 300,
|
|
876
|
+
"min_recovery_interval": 60,
|
|
877
|
+
},
|
|
496
878
|
},
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
'critical_threshold': 1,
|
|
500
|
-
'failure_window_seconds': 300,
|
|
501
|
-
'min_recovery_interval': 60
|
|
502
|
-
}
|
|
503
|
-
})
|
|
504
|
-
|
|
879
|
+
)
|
|
880
|
+
|
|
505
881
|
# Merge with socketio-specific config if available
|
|
506
|
-
socketio_config = self.get(
|
|
882
|
+
socketio_config = self.get("socketio_server.recovery", {})
|
|
507
883
|
if socketio_config:
|
|
508
884
|
base_config = self._config_mgr.merge_configs(base_config, socketio_config)
|
|
509
|
-
|
|
885
|
+
|
|
510
886
|
return base_config
|
|
511
887
|
|
|
888
|
+
def validate_configuration(self) -> Tuple[bool, List[str], List[str]]:
|
|
889
|
+
"""Validate the loaded configuration programmatically.
|
|
890
|
+
|
|
891
|
+
WHY: Provide a programmatic way to validate configuration that can be
|
|
892
|
+
used by other components to check configuration health.
|
|
893
|
+
|
|
894
|
+
Returns:
|
|
895
|
+
Tuple of (is_valid, errors, warnings)
|
|
896
|
+
"""
|
|
897
|
+
errors = []
|
|
898
|
+
warnings = []
|
|
899
|
+
|
|
900
|
+
# Check if there was a load error
|
|
901
|
+
if "_load_error" in self._config:
|
|
902
|
+
errors.append(f"Configuration load error: {self._config['_load_error']}")
|
|
903
|
+
|
|
904
|
+
# Validate response_logging configuration
|
|
905
|
+
response_logging = self.get("response_logging", {})
|
|
906
|
+
if response_logging:
|
|
907
|
+
# Check enabled field
|
|
908
|
+
if "enabled" in response_logging and not isinstance(
|
|
909
|
+
response_logging["enabled"], bool
|
|
910
|
+
):
|
|
911
|
+
errors.append(
|
|
912
|
+
f"response_logging.enabled must be boolean, got {type(response_logging['enabled']).__name__}"
|
|
913
|
+
)
|
|
914
|
+
|
|
915
|
+
# Check format field
|
|
916
|
+
if "format" in response_logging:
|
|
917
|
+
valid_formats = ["json", "syslog", "journald"]
|
|
918
|
+
if response_logging["format"] not in valid_formats:
|
|
919
|
+
errors.append(
|
|
920
|
+
f"response_logging.format must be one of {valid_formats}, "
|
|
921
|
+
f"got '{response_logging['format']}'"
|
|
922
|
+
)
|
|
923
|
+
|
|
924
|
+
# Check session_directory
|
|
925
|
+
if "session_directory" in response_logging:
|
|
926
|
+
session_dir = Path(response_logging["session_directory"])
|
|
927
|
+
if session_dir.is_absolute() and not session_dir.parent.exists():
|
|
928
|
+
warnings.append(
|
|
929
|
+
f"Parent directory for session_directory does not exist: {session_dir.parent}"
|
|
930
|
+
)
|
|
931
|
+
|
|
932
|
+
# Validate memory configuration
|
|
933
|
+
memory_config = self.get("memory", {})
|
|
934
|
+
if memory_config:
|
|
935
|
+
if "enabled" in memory_config and not isinstance(
|
|
936
|
+
memory_config["enabled"], bool
|
|
937
|
+
):
|
|
938
|
+
errors.append("memory.enabled must be boolean")
|
|
939
|
+
|
|
940
|
+
# Check limits
|
|
941
|
+
limits = memory_config.get("limits", {})
|
|
942
|
+
for field in ["default_size_kb", "max_sections", "max_items_per_section"]:
|
|
943
|
+
if field in limits:
|
|
944
|
+
value = limits[field]
|
|
945
|
+
if not isinstance(value, int) or value <= 0:
|
|
946
|
+
errors.append(
|
|
947
|
+
f"memory.limits.{field} must be positive integer, got {value}"
|
|
948
|
+
)
|
|
949
|
+
|
|
950
|
+
# Validate health thresholds
|
|
951
|
+
health_thresholds = self.get("health_thresholds", {})
|
|
952
|
+
if health_thresholds:
|
|
953
|
+
cpu = health_thresholds.get("cpu_percent")
|
|
954
|
+
if cpu is not None and (
|
|
955
|
+
not isinstance(cpu, (int, float)) or cpu < 0 or cpu > 100
|
|
956
|
+
):
|
|
957
|
+
errors.append(f"health_thresholds.cpu_percent must be 0-100, got {cpu}")
|
|
958
|
+
|
|
959
|
+
mem = health_thresholds.get("memory_mb")
|
|
960
|
+
if mem is not None and (not isinstance(mem, (int, float)) or mem <= 0):
|
|
961
|
+
errors.append(
|
|
962
|
+
f"health_thresholds.memory_mb must be positive, got {mem}"
|
|
963
|
+
)
|
|
964
|
+
|
|
965
|
+
is_valid = len(errors) == 0
|
|
966
|
+
return is_valid, errors, warnings
|
|
967
|
+
|
|
968
|
+
def get_configuration_status(self) -> Dict[str, Any]:
|
|
969
|
+
"""Get detailed configuration status for debugging.
|
|
970
|
+
|
|
971
|
+
WHY: Provide a comprehensive view of configuration state for
|
|
972
|
+
troubleshooting and health checks.
|
|
973
|
+
|
|
974
|
+
Returns:
|
|
975
|
+
Dictionary with configuration status information
|
|
976
|
+
"""
|
|
977
|
+
is_valid, errors, warnings = self.validate_configuration()
|
|
978
|
+
|
|
979
|
+
return {
|
|
980
|
+
"valid": is_valid,
|
|
981
|
+
"errors": errors,
|
|
982
|
+
"warnings": warnings,
|
|
983
|
+
"loaded_from": getattr(self, "_loaded_from", "defaults"),
|
|
984
|
+
"key_count": len(self._config),
|
|
985
|
+
"has_response_logging": "response_logging" in self._config,
|
|
986
|
+
"has_memory_config": "memory" in self._config,
|
|
987
|
+
"response_logging_enabled": self.get("response_logging.enabled", False),
|
|
988
|
+
"memory_enabled": self.get("memory.enabled", False),
|
|
989
|
+
}
|
|
990
|
+
|
|
512
991
|
def __repr__(self) -> str:
|
|
513
992
|
"""String representation of configuration."""
|
|
514
993
|
return f"<Config({len(self._config)} keys)>"
|
|
994
|
+
|
|
995
|
+
@classmethod
|
|
996
|
+
def reset_singleton(cls):
|
|
997
|
+
"""Reset the singleton instance (mainly for testing purposes).
|
|
998
|
+
|
|
999
|
+
WHY: During testing, we may need to reset the singleton to test different
|
|
1000
|
+
configurations. This method allows controlled reset of the singleton state.
|
|
1001
|
+
"""
|
|
1002
|
+
cls._instance = None
|
|
1003
|
+
cls._initialized = False
|
|
1004
|
+
cls._success_logged = False
|
|
1005
|
+
logger.debug("Config singleton reset")
|