claude-mpm 3.4.10__py3-none-any.whl → 5.4.85__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_FOUNDERS_OUTPUT_STYLE.md +405 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +112 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +186 -0
- claude_mpm/agents/MEMORY.md +72 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1429 -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 +94 -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 +2501 -168
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/agents_reconcile.py +197 -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 +3253 -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 +1398 -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 +298 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +31 -0
- claude_mpm/cli/interactive/agent_wizard.py +1927 -0
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -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 +649 -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 +1578 -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 +133 -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 +491 -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 +612 -0
- claude_mpm/core/unified_paths.py +958 -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/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/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 +1377 -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_reconciler.py +577 -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/startup_reconciliation.py +138 -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 +1205 -0
- claude_mpm/services/agents/startup_sync.py +262 -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 +711 -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 +1340 -0
- claude_mpm/services/skills/selective_skill_deployer.py +743 -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/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -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/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -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/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -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/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -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/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/pm-bug-reporting/pm-bug-reporting.md +248 -0
- claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/pm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +439 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -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/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -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 +1189 -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 +844 -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.85.dist-info/METADATA +1023 -0
- claude_mpm-5.4.85.dist-info/RECORD +980 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/entry_points.txt +1 -3
- claude_mpm-5.4.85.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.85.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.85.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,730 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Daemon Lifecycle Management for Unified Monitor
|
|
3
|
+
===============================================
|
|
4
|
+
|
|
5
|
+
WHY: This module provides proper daemon process lifecycle management including
|
|
6
|
+
daemonization, PID file management, and graceful shutdown for the unified
|
|
7
|
+
monitor daemon.
|
|
8
|
+
|
|
9
|
+
DESIGN DECISIONS:
|
|
10
|
+
- Standard Unix daemon patterns
|
|
11
|
+
- PID file management for process tracking
|
|
12
|
+
- Proper signal handling for graceful shutdown
|
|
13
|
+
- Log file redirection for daemon mode
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import os
|
|
18
|
+
import signal
|
|
19
|
+
import socket
|
|
20
|
+
import sys
|
|
21
|
+
import tempfile
|
|
22
|
+
import time
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Optional, Tuple
|
|
25
|
+
|
|
26
|
+
from ....core.enums import OperationResult
|
|
27
|
+
from ....core.logging_config import get_logger
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class DaemonLifecycle:
|
|
31
|
+
"""Manages daemon process lifecycle for the unified monitor.
|
|
32
|
+
|
|
33
|
+
WHY: Provides proper daemon process management with PID files, signal
|
|
34
|
+
handling, and graceful shutdown capabilities.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, pid_file: str, log_file: Optional[str] = None, port: int = 8765):
|
|
38
|
+
"""Initialize daemon lifecycle manager.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
pid_file: Path to PID file
|
|
42
|
+
log_file: Path to log file for daemon mode
|
|
43
|
+
port: Port number for startup verification
|
|
44
|
+
"""
|
|
45
|
+
self.pid_file = Path(pid_file)
|
|
46
|
+
self.log_file = Path(log_file) if log_file else None
|
|
47
|
+
self.port = port
|
|
48
|
+
self.logger = get_logger(__name__)
|
|
49
|
+
# Create a temporary file for startup status communication
|
|
50
|
+
self.startup_status_file = None
|
|
51
|
+
|
|
52
|
+
def daemonize(self) -> bool:
|
|
53
|
+
"""Daemonize the current process.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
True if daemonization successful, False otherwise
|
|
57
|
+
"""
|
|
58
|
+
try:
|
|
59
|
+
# Clean up any existing asyncio event loops before forking
|
|
60
|
+
self._cleanup_event_loops()
|
|
61
|
+
|
|
62
|
+
# Create a temporary file for startup status communication
|
|
63
|
+
with tempfile.NamedTemporaryFile(
|
|
64
|
+
mode="w", delete=False, suffix=".status"
|
|
65
|
+
) as f:
|
|
66
|
+
self.startup_status_file = f.name
|
|
67
|
+
f.write("starting")
|
|
68
|
+
|
|
69
|
+
# First fork
|
|
70
|
+
pid = os.fork()
|
|
71
|
+
if pid > 0:
|
|
72
|
+
# Parent process - wait for child to confirm startup
|
|
73
|
+
return self._parent_wait_for_startup(pid)
|
|
74
|
+
except OSError as e:
|
|
75
|
+
self.logger.error(f"First fork failed: {e}")
|
|
76
|
+
self._report_startup_error(f"First fork failed: {e}")
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
# Decouple from parent environment
|
|
80
|
+
os.chdir("/")
|
|
81
|
+
os.setsid()
|
|
82
|
+
os.umask(0)
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
# Second fork
|
|
86
|
+
pid = os.fork()
|
|
87
|
+
if pid > 0:
|
|
88
|
+
# First child process exits
|
|
89
|
+
sys.exit(0)
|
|
90
|
+
except OSError as e:
|
|
91
|
+
self.logger.error(f"Second fork failed: {e}")
|
|
92
|
+
self._report_startup_error(f"Second fork failed: {e}")
|
|
93
|
+
return False
|
|
94
|
+
|
|
95
|
+
# Set up error logging before redirecting streams
|
|
96
|
+
self._setup_early_error_logging()
|
|
97
|
+
|
|
98
|
+
# Write PID file first (before stream redirection)
|
|
99
|
+
try:
|
|
100
|
+
self.write_pid_file()
|
|
101
|
+
except Exception as e:
|
|
102
|
+
self._report_startup_error(f"Failed to write PID file: {e}")
|
|
103
|
+
return False
|
|
104
|
+
|
|
105
|
+
# Redirect standard file descriptors
|
|
106
|
+
self._redirect_streams()
|
|
107
|
+
|
|
108
|
+
# Setup signal handlers
|
|
109
|
+
self._setup_signal_handlers()
|
|
110
|
+
|
|
111
|
+
self.logger.info(f"Daemon process started with PID {os.getpid()}")
|
|
112
|
+
|
|
113
|
+
# Report successful startup (after basic setup but before server start)
|
|
114
|
+
self._report_startup_success()
|
|
115
|
+
return True
|
|
116
|
+
|
|
117
|
+
def _redirect_streams(self):
|
|
118
|
+
"""Redirect standard streams for daemon mode."""
|
|
119
|
+
try:
|
|
120
|
+
# Flush streams
|
|
121
|
+
sys.stdout.flush()
|
|
122
|
+
sys.stderr.flush()
|
|
123
|
+
|
|
124
|
+
# Redirect stdin to /dev/null
|
|
125
|
+
with Path("/dev/null").open() as null_in:
|
|
126
|
+
os.dup2(null_in.fileno(), sys.stdin.fileno())
|
|
127
|
+
|
|
128
|
+
# Redirect stdout and stderr
|
|
129
|
+
if self.log_file:
|
|
130
|
+
# Redirect to log file
|
|
131
|
+
with self.log_file.open("a") as log_out:
|
|
132
|
+
os.dup2(log_out.fileno(), sys.stdout.fileno())
|
|
133
|
+
os.dup2(log_out.fileno(), sys.stderr.fileno())
|
|
134
|
+
else:
|
|
135
|
+
# Default to a daemon log file instead of /dev/null for errors
|
|
136
|
+
default_log = Path.home() / ".claude-mpm" / "monitor-daemon.log"
|
|
137
|
+
default_log.parent.mkdir(parents=True, exist_ok=True)
|
|
138
|
+
with default_log.open("a") as log_out:
|
|
139
|
+
os.dup2(log_out.fileno(), sys.stdout.fileno())
|
|
140
|
+
os.dup2(log_out.fileno(), sys.stderr.fileno())
|
|
141
|
+
|
|
142
|
+
except Exception as e:
|
|
143
|
+
self.logger.error(f"Error redirecting streams: {e}")
|
|
144
|
+
self._report_startup_error(f"Failed to redirect streams: {e}")
|
|
145
|
+
|
|
146
|
+
def write_pid_file(self):
|
|
147
|
+
"""Write PID to PID file."""
|
|
148
|
+
try:
|
|
149
|
+
# Ensure parent directory exists
|
|
150
|
+
self.pid_file.parent.mkdir(parents=True, exist_ok=True)
|
|
151
|
+
|
|
152
|
+
# Write PID
|
|
153
|
+
with self.pid_file.open("w") as f:
|
|
154
|
+
f.write(str(os.getpid()))
|
|
155
|
+
|
|
156
|
+
self.logger.debug(f"PID file written: {self.pid_file}")
|
|
157
|
+
|
|
158
|
+
except Exception as e:
|
|
159
|
+
self.logger.error(f"Error writing PID file: {e}")
|
|
160
|
+
raise
|
|
161
|
+
|
|
162
|
+
def _setup_signal_handlers(self):
|
|
163
|
+
"""Setup signal handlers for graceful shutdown."""
|
|
164
|
+
|
|
165
|
+
def signal_handler(signum, frame):
|
|
166
|
+
self.logger.info(f"Received signal {signum}, initiating shutdown")
|
|
167
|
+
self.cleanup()
|
|
168
|
+
sys.exit(0)
|
|
169
|
+
|
|
170
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
|
171
|
+
signal.signal(signal.SIGINT, signal_handler)
|
|
172
|
+
|
|
173
|
+
def is_running(self) -> bool:
|
|
174
|
+
"""Check if daemon is currently running.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
True if daemon is running, False otherwise
|
|
178
|
+
"""
|
|
179
|
+
try:
|
|
180
|
+
pid = self.get_pid()
|
|
181
|
+
if pid is None:
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
# Check if process exists
|
|
185
|
+
os.kill(pid, 0) # Signal 0 just checks if process exists
|
|
186
|
+
return True
|
|
187
|
+
|
|
188
|
+
except (OSError, ProcessLookupError):
|
|
189
|
+
# Process doesn't exist
|
|
190
|
+
self._cleanup_stale_pid_file()
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
def get_pid(self) -> Optional[int]:
|
|
194
|
+
"""Get PID from PID file.
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
PID if found, None otherwise
|
|
198
|
+
"""
|
|
199
|
+
try:
|
|
200
|
+
if not self.pid_file.exists():
|
|
201
|
+
return None
|
|
202
|
+
|
|
203
|
+
with self.pid_file.open() as f:
|
|
204
|
+
pid_str = f.read().strip()
|
|
205
|
+
return int(pid_str) if pid_str else None
|
|
206
|
+
|
|
207
|
+
except (OSError, ValueError):
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
def stop_daemon(self) -> bool:
|
|
211
|
+
"""Stop the running daemon.
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
True if stopped successfully, False otherwise
|
|
215
|
+
"""
|
|
216
|
+
try:
|
|
217
|
+
pid = self.get_pid()
|
|
218
|
+
if pid is None:
|
|
219
|
+
self.logger.warning("No PID file found, daemon may not be running")
|
|
220
|
+
return False
|
|
221
|
+
|
|
222
|
+
# Send SIGTERM for graceful shutdown
|
|
223
|
+
self.logger.info(f"Stopping daemon with PID {pid}")
|
|
224
|
+
os.kill(pid, signal.SIGTERM)
|
|
225
|
+
|
|
226
|
+
# Wait for process to exit
|
|
227
|
+
for _ in range(30): # Wait up to 30 seconds
|
|
228
|
+
if not self.is_running():
|
|
229
|
+
self.logger.info("Daemon stopped successfully")
|
|
230
|
+
return True
|
|
231
|
+
time.sleep(1)
|
|
232
|
+
|
|
233
|
+
# Force kill if still running
|
|
234
|
+
self.logger.warning("Daemon didn't stop gracefully, forcing kill")
|
|
235
|
+
os.kill(pid, signal.SIGKILL)
|
|
236
|
+
|
|
237
|
+
# Wait a bit more
|
|
238
|
+
for _ in range(5):
|
|
239
|
+
if not self.is_running():
|
|
240
|
+
self.logger.info("Daemon force-killed successfully")
|
|
241
|
+
return True
|
|
242
|
+
time.sleep(1)
|
|
243
|
+
|
|
244
|
+
self.logger.error("Failed to stop daemon")
|
|
245
|
+
return False
|
|
246
|
+
|
|
247
|
+
except ProcessLookupError:
|
|
248
|
+
# Process already dead
|
|
249
|
+
self._cleanup_stale_pid_file()
|
|
250
|
+
self.logger.info("Daemon was already stopped")
|
|
251
|
+
return True
|
|
252
|
+
except Exception as e:
|
|
253
|
+
self.logger.error(f"Error stopping daemon: {e}")
|
|
254
|
+
return False
|
|
255
|
+
|
|
256
|
+
def restart_daemon(self) -> bool:
|
|
257
|
+
"""Restart the daemon.
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
True if restarted successfully, False otherwise
|
|
261
|
+
"""
|
|
262
|
+
self.logger.info("Restarting daemon")
|
|
263
|
+
|
|
264
|
+
# Stop first
|
|
265
|
+
if not self.stop_daemon():
|
|
266
|
+
return False
|
|
267
|
+
|
|
268
|
+
# Wait a moment
|
|
269
|
+
time.sleep(2)
|
|
270
|
+
|
|
271
|
+
# Start again (this would need to be called from the main daemon)
|
|
272
|
+
# For now, just return True as the actual restart logic is in the daemon
|
|
273
|
+
return True
|
|
274
|
+
|
|
275
|
+
def cleanup(self):
|
|
276
|
+
"""Cleanup daemon resources."""
|
|
277
|
+
try:
|
|
278
|
+
# Remove PID file
|
|
279
|
+
if self.pid_file.exists():
|
|
280
|
+
self.pid_file.unlink()
|
|
281
|
+
self.logger.debug(f"PID file removed: {self.pid_file}")
|
|
282
|
+
|
|
283
|
+
except Exception as e:
|
|
284
|
+
self.logger.error(f"Error during cleanup: {e}")
|
|
285
|
+
|
|
286
|
+
def _cleanup_stale_pid_file(self):
|
|
287
|
+
"""Remove stale PID file."""
|
|
288
|
+
try:
|
|
289
|
+
if self.pid_file.exists():
|
|
290
|
+
self.pid_file.unlink()
|
|
291
|
+
self.logger.debug("Removed stale PID file")
|
|
292
|
+
except Exception as e:
|
|
293
|
+
self.logger.error(f"Error removing stale PID file: {e}")
|
|
294
|
+
|
|
295
|
+
def _cleanup_event_loops(self):
|
|
296
|
+
"""Clean up any existing asyncio event loops before forking.
|
|
297
|
+
|
|
298
|
+
This prevents the 'I/O operation on closed kqueue object' error
|
|
299
|
+
that occurs when forked processes inherit event loops.
|
|
300
|
+
"""
|
|
301
|
+
try:
|
|
302
|
+
import asyncio
|
|
303
|
+
import gc
|
|
304
|
+
|
|
305
|
+
# Try to get the current event loop
|
|
306
|
+
try:
|
|
307
|
+
loop = asyncio.get_event_loop()
|
|
308
|
+
if loop and loop.is_running():
|
|
309
|
+
# Can't close a running loop, but we can stop it
|
|
310
|
+
loop.stop()
|
|
311
|
+
self.logger.debug("Stopped running event loop before fork")
|
|
312
|
+
elif loop:
|
|
313
|
+
# Close the loop if it exists and is not running
|
|
314
|
+
loop.close()
|
|
315
|
+
self.logger.debug("Closed event loop before fork")
|
|
316
|
+
except RuntimeError:
|
|
317
|
+
# No event loop in current thread
|
|
318
|
+
pass
|
|
319
|
+
|
|
320
|
+
# Clear the event loop policy to ensure clean state
|
|
321
|
+
asyncio.set_event_loop(None)
|
|
322
|
+
|
|
323
|
+
# Force garbage collection to clean up any loop resources
|
|
324
|
+
gc.collect()
|
|
325
|
+
|
|
326
|
+
except ImportError:
|
|
327
|
+
# asyncio not available (unlikely but handle it)
|
|
328
|
+
pass
|
|
329
|
+
except Exception as e:
|
|
330
|
+
self.logger.debug(f"Error cleaning up event loops before fork: {e}")
|
|
331
|
+
|
|
332
|
+
def get_status(self) -> dict:
|
|
333
|
+
"""Get daemon status information.
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
Dictionary with status information
|
|
337
|
+
"""
|
|
338
|
+
pid = self.get_pid()
|
|
339
|
+
running = self.is_running()
|
|
340
|
+
|
|
341
|
+
status = {
|
|
342
|
+
"running": running,
|
|
343
|
+
"pid": pid,
|
|
344
|
+
"pid_file": str(self.pid_file),
|
|
345
|
+
"log_file": str(self.log_file) if self.log_file else None,
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if running and pid:
|
|
349
|
+
try:
|
|
350
|
+
# Get process info
|
|
351
|
+
import psutil
|
|
352
|
+
|
|
353
|
+
process = psutil.Process(pid)
|
|
354
|
+
status.update(
|
|
355
|
+
{
|
|
356
|
+
"cpu_percent": process.cpu_percent(),
|
|
357
|
+
"memory_info": process.memory_info()._asdict(),
|
|
358
|
+
"create_time": process.create_time(),
|
|
359
|
+
"status": process.status(),
|
|
360
|
+
}
|
|
361
|
+
)
|
|
362
|
+
except ImportError:
|
|
363
|
+
# psutil not available
|
|
364
|
+
pass
|
|
365
|
+
except Exception as e:
|
|
366
|
+
self.logger.debug(f"Error getting process info: {e}")
|
|
367
|
+
|
|
368
|
+
return status
|
|
369
|
+
|
|
370
|
+
def _parent_wait_for_startup(self, child_pid: int, timeout: float = 10.0) -> bool:
|
|
371
|
+
"""Parent process waits for child daemon to report startup status.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
child_pid: PID of the child process
|
|
375
|
+
timeout: Maximum time to wait for startup
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
True if child started successfully, False otherwise
|
|
379
|
+
"""
|
|
380
|
+
import time
|
|
381
|
+
|
|
382
|
+
start_time = time.time()
|
|
383
|
+
|
|
384
|
+
# Wait for child to update status file
|
|
385
|
+
while time.time() - start_time < timeout:
|
|
386
|
+
try:
|
|
387
|
+
# Check if status file exists and read it
|
|
388
|
+
if self.startup_status_file and Path(self.startup_status_file).exists():
|
|
389
|
+
with self.startup_status_file.open() as f:
|
|
390
|
+
status = f.read().strip()
|
|
391
|
+
|
|
392
|
+
if status == OperationResult.SUCCESS:
|
|
393
|
+
# Child started successfully
|
|
394
|
+
self._cleanup_status_file()
|
|
395
|
+
return True
|
|
396
|
+
if status.startswith("error:"):
|
|
397
|
+
# Child reported an error
|
|
398
|
+
error_msg = status[6:] # Remove "error:" prefix
|
|
399
|
+
self.logger.error(f"Daemon startup failed: {error_msg}")
|
|
400
|
+
print(
|
|
401
|
+
f"Error: Failed to start monitor daemon: {error_msg}",
|
|
402
|
+
file=sys.stderr,
|
|
403
|
+
)
|
|
404
|
+
self._cleanup_status_file()
|
|
405
|
+
return False
|
|
406
|
+
if status == "starting":
|
|
407
|
+
# Still starting, continue waiting
|
|
408
|
+
pass
|
|
409
|
+
|
|
410
|
+
# Also check if child process is still alive
|
|
411
|
+
try:
|
|
412
|
+
os.kill(child_pid, 0) # Check if process exists
|
|
413
|
+
except ProcessLookupError:
|
|
414
|
+
# Child process died
|
|
415
|
+
self.logger.error("Child daemon process died during startup")
|
|
416
|
+
print(
|
|
417
|
+
"Error: Monitor daemon process died during startup",
|
|
418
|
+
file=sys.stderr,
|
|
419
|
+
)
|
|
420
|
+
self._cleanup_status_file()
|
|
421
|
+
return False
|
|
422
|
+
|
|
423
|
+
except Exception as e:
|
|
424
|
+
self.logger.debug(f"Error checking startup status: {e}")
|
|
425
|
+
|
|
426
|
+
time.sleep(0.1) # Check every 100ms
|
|
427
|
+
|
|
428
|
+
# Timeout reached
|
|
429
|
+
self.logger.error(f"Daemon startup timed out after {timeout} seconds")
|
|
430
|
+
print(
|
|
431
|
+
f"Error: Monitor daemon startup timed out after {timeout} seconds",
|
|
432
|
+
file=sys.stderr,
|
|
433
|
+
)
|
|
434
|
+
self._cleanup_status_file()
|
|
435
|
+
return False
|
|
436
|
+
|
|
437
|
+
def _report_startup_success(self):
|
|
438
|
+
"""Report successful startup to parent process."""
|
|
439
|
+
if self.startup_status_file:
|
|
440
|
+
try:
|
|
441
|
+
with self.startup_status_file.open("w") as f:
|
|
442
|
+
f.write(OperationResult.SUCCESS)
|
|
443
|
+
except Exception as e:
|
|
444
|
+
self.logger.error(f"Failed to report startup success: {e}")
|
|
445
|
+
|
|
446
|
+
def _report_startup_error(self, error_msg: str):
|
|
447
|
+
"""Report startup error to parent process.
|
|
448
|
+
|
|
449
|
+
Args:
|
|
450
|
+
error_msg: Error message to report
|
|
451
|
+
"""
|
|
452
|
+
if self.startup_status_file:
|
|
453
|
+
try:
|
|
454
|
+
with self.startup_status_file.open("w") as f:
|
|
455
|
+
f.write(f"error:{error_msg}")
|
|
456
|
+
except Exception:
|
|
457
|
+
pass # Can't report if file write fails
|
|
458
|
+
|
|
459
|
+
def _cleanup_status_file(self):
|
|
460
|
+
"""Clean up the temporary status file."""
|
|
461
|
+
if self.startup_status_file:
|
|
462
|
+
try:
|
|
463
|
+
Path(self.startup_status_file).unlink(missing_ok=True)
|
|
464
|
+
except Exception:
|
|
465
|
+
pass # Ignore cleanup errors
|
|
466
|
+
finally:
|
|
467
|
+
self.startup_status_file = None
|
|
468
|
+
|
|
469
|
+
def _setup_early_error_logging(self):
|
|
470
|
+
"""Set up error logging before stream redirection.
|
|
471
|
+
|
|
472
|
+
This ensures we can capture and report errors that occur during
|
|
473
|
+
daemon initialization, especially port binding errors.
|
|
474
|
+
"""
|
|
475
|
+
try:
|
|
476
|
+
# If no log file specified, create a default one
|
|
477
|
+
if not self.log_file:
|
|
478
|
+
default_log = Path.home() / ".claude-mpm" / "monitor-daemon.log"
|
|
479
|
+
default_log.parent.mkdir(parents=True, exist_ok=True)
|
|
480
|
+
self.log_file = default_log
|
|
481
|
+
|
|
482
|
+
# Configure logger to write to file immediately
|
|
483
|
+
import logging
|
|
484
|
+
|
|
485
|
+
# Use RotatingFileHandler for automatic log rotation
|
|
486
|
+
# 5MB max size, 5 backup files (consistent with project logging standards)
|
|
487
|
+
file_handler = logging.handlers.RotatingFileHandler(
|
|
488
|
+
self.log_file,
|
|
489
|
+
maxBytes=5 * 1024 * 1024, # 5MB
|
|
490
|
+
backupCount=5,
|
|
491
|
+
)
|
|
492
|
+
file_handler.setLevel(logging.DEBUG)
|
|
493
|
+
formatter = logging.Formatter(
|
|
494
|
+
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
495
|
+
)
|
|
496
|
+
file_handler.setFormatter(formatter)
|
|
497
|
+
self.logger.addHandler(file_handler)
|
|
498
|
+
|
|
499
|
+
except Exception as e:
|
|
500
|
+
# If we can't set up logging, at least try to report the error
|
|
501
|
+
self._report_startup_error(f"Failed to setup error logging: {e}")
|
|
502
|
+
|
|
503
|
+
def verify_port_available(
|
|
504
|
+
self, host: str = "localhost"
|
|
505
|
+
) -> Tuple[bool, Optional[str]]:
|
|
506
|
+
"""Verify that the port is available for binding.
|
|
507
|
+
|
|
508
|
+
Args:
|
|
509
|
+
host: Host to check port on
|
|
510
|
+
|
|
511
|
+
Returns:
|
|
512
|
+
Tuple of (is_available, error_message)
|
|
513
|
+
"""
|
|
514
|
+
try:
|
|
515
|
+
test_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
516
|
+
test_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
517
|
+
test_sock.bind((host, self.port))
|
|
518
|
+
test_sock.close()
|
|
519
|
+
return True, None
|
|
520
|
+
except OSError as e:
|
|
521
|
+
error_msg = f"Port {self.port} is already in use or cannot be bound: {e}"
|
|
522
|
+
return False, error_msg
|
|
523
|
+
|
|
524
|
+
def is_our_service(self, host: str = "localhost") -> Tuple[bool, Optional[int]]:
|
|
525
|
+
"""Check if the service on the port is our Socket.IO service.
|
|
526
|
+
|
|
527
|
+
This uses multiple detection methods:
|
|
528
|
+
1. Check health endpoint for service signature
|
|
529
|
+
2. Check Socket.IO namespace availability
|
|
530
|
+
3. Check process ownership if PID file exists
|
|
531
|
+
|
|
532
|
+
Args:
|
|
533
|
+
host: Host to check
|
|
534
|
+
|
|
535
|
+
Returns:
|
|
536
|
+
Tuple of (is_ours, pid_if_found)
|
|
537
|
+
"""
|
|
538
|
+
self.logger.debug(f"Checking if service on {host}:{self.port} is ours")
|
|
539
|
+
|
|
540
|
+
try:
|
|
541
|
+
# Method 1: Check health endpoint
|
|
542
|
+
import urllib.error
|
|
543
|
+
import urllib.request
|
|
544
|
+
|
|
545
|
+
health_url = f"http://{host}:{self.port}/health"
|
|
546
|
+
self.logger.debug(f"Checking health endpoint: {health_url}")
|
|
547
|
+
|
|
548
|
+
try:
|
|
549
|
+
req = urllib.request.Request(health_url)
|
|
550
|
+
req.add_header("User-Agent", "claude-mpm-monitor")
|
|
551
|
+
|
|
552
|
+
with urllib.request.urlopen(req, timeout=3) as response:
|
|
553
|
+
if response.status == 200:
|
|
554
|
+
data = json.loads(response.read().decode())
|
|
555
|
+
self.logger.debug(f"Health endpoint response: {data}")
|
|
556
|
+
|
|
557
|
+
# Check for our service signature
|
|
558
|
+
service_name = data.get("service")
|
|
559
|
+
if service_name == "claude-mpm-monitor":
|
|
560
|
+
# Try to get PID from response
|
|
561
|
+
pid = data.get("pid")
|
|
562
|
+
if pid:
|
|
563
|
+
self.logger.info(
|
|
564
|
+
f"Found our claude-mpm-monitor service via health endpoint, PID: {pid}"
|
|
565
|
+
)
|
|
566
|
+
return True, pid
|
|
567
|
+
# Service is ours but no PID in response
|
|
568
|
+
# Try to get from PID file
|
|
569
|
+
file_pid = self.get_pid()
|
|
570
|
+
self.logger.info(
|
|
571
|
+
f"Found our claude-mpm-monitor service via health endpoint, PID from file: {file_pid}"
|
|
572
|
+
)
|
|
573
|
+
return True, file_pid
|
|
574
|
+
self.logger.debug(
|
|
575
|
+
f"Service name '{service_name}' does not match 'claude-mpm-monitor'"
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
except urllib.error.URLError as e:
|
|
579
|
+
self.logger.debug(f"Health endpoint not accessible: {e}")
|
|
580
|
+
except urllib.error.HTTPError as e:
|
|
581
|
+
self.logger.debug(f"Health endpoint HTTP error: {e}")
|
|
582
|
+
except json.JSONDecodeError as e:
|
|
583
|
+
self.logger.debug(f"Health endpoint invalid JSON: {e}")
|
|
584
|
+
except Exception as e:
|
|
585
|
+
self.logger.debug(f"Health endpoint check failed: {e}")
|
|
586
|
+
|
|
587
|
+
# Method 2: Check if PID file exists and process matches
|
|
588
|
+
pid = self.get_pid()
|
|
589
|
+
if pid:
|
|
590
|
+
self.logger.debug(f"Checking PID from file: {pid}")
|
|
591
|
+
try:
|
|
592
|
+
# Check if process exists
|
|
593
|
+
os.kill(pid, 0)
|
|
594
|
+
self.logger.debug(f"Process {pid} exists")
|
|
595
|
+
|
|
596
|
+
# Process exists, check if it's using our port
|
|
597
|
+
# This requires psutil for accurate port checking
|
|
598
|
+
try:
|
|
599
|
+
import psutil
|
|
600
|
+
|
|
601
|
+
process = psutil.Process(pid)
|
|
602
|
+
|
|
603
|
+
# Check process command line for our service
|
|
604
|
+
cmdline = " ".join(process.cmdline())
|
|
605
|
+
if "claude_mpm" in cmdline or "claude-mpm" in cmdline:
|
|
606
|
+
if "monitor" in cmdline:
|
|
607
|
+
self.logger.info(
|
|
608
|
+
f"Found our claude-mpm monitor process via PID file, PID: {pid}"
|
|
609
|
+
)
|
|
610
|
+
return True, pid
|
|
611
|
+
|
|
612
|
+
# Also check if it's listening on our port
|
|
613
|
+
connections = process.connections()
|
|
614
|
+
for conn in connections:
|
|
615
|
+
if conn.laddr.port == self.port and conn.status == "LISTEN":
|
|
616
|
+
self.logger.info(
|
|
617
|
+
f"Found process {pid} listening on our port {self.port}"
|
|
618
|
+
)
|
|
619
|
+
# Double-check it's a Python process (likely ours)
|
|
620
|
+
if "python" in process.name().lower():
|
|
621
|
+
self.logger.info(
|
|
622
|
+
"Confirmed as Python process, assuming it's our service"
|
|
623
|
+
)
|
|
624
|
+
return True, pid
|
|
625
|
+
|
|
626
|
+
except ImportError:
|
|
627
|
+
# psutil not available, but we have a PID file and process exists
|
|
628
|
+
# Assume it's ours since we manage the PID file
|
|
629
|
+
self.logger.info(
|
|
630
|
+
f"Found process with our PID file: {pid}, assuming it's ours (psutil not available)"
|
|
631
|
+
)
|
|
632
|
+
return True, pid
|
|
633
|
+
except psutil.NoSuchProcess:
|
|
634
|
+
self.logger.debug(f"Process {pid} no longer exists")
|
|
635
|
+
except psutil.AccessDenied:
|
|
636
|
+
# Can't access process info, but it exists - likely ours
|
|
637
|
+
self.logger.info(
|
|
638
|
+
f"Process {pid} exists but access denied, assuming it's ours"
|
|
639
|
+
)
|
|
640
|
+
return True, pid
|
|
641
|
+
except Exception as e:
|
|
642
|
+
self.logger.debug(f"Error checking process {pid}: {e}")
|
|
643
|
+
|
|
644
|
+
except (OSError, ProcessLookupError):
|
|
645
|
+
# Process doesn't exist
|
|
646
|
+
self.logger.debug(f"Process {pid} does not exist")
|
|
647
|
+
self._cleanup_stale_pid_file()
|
|
648
|
+
|
|
649
|
+
# Method 3: Try Socket.IO connection to check namespace
|
|
650
|
+
try:
|
|
651
|
+
import socketio
|
|
652
|
+
|
|
653
|
+
sio_client = socketio.Client()
|
|
654
|
+
|
|
655
|
+
# Try to connect with a short timeout
|
|
656
|
+
connected = False
|
|
657
|
+
|
|
658
|
+
def on_connect():
|
|
659
|
+
nonlocal connected
|
|
660
|
+
connected = True
|
|
661
|
+
|
|
662
|
+
sio_client.on("connect", on_connect)
|
|
663
|
+
|
|
664
|
+
try:
|
|
665
|
+
sio_client.connect(f"http://{host}:{self.port}", wait_timeout=2)
|
|
666
|
+
if connected:
|
|
667
|
+
# Successfully connected to Socket.IO
|
|
668
|
+
sio_client.disconnect()
|
|
669
|
+
|
|
670
|
+
# Check for orphaned process (no PID file but service running)
|
|
671
|
+
try:
|
|
672
|
+
# Try to find process using the port
|
|
673
|
+
import psutil
|
|
674
|
+
|
|
675
|
+
for proc in psutil.process_iter(["pid", "name"]):
|
|
676
|
+
try:
|
|
677
|
+
for conn in proc.connections():
|
|
678
|
+
if (
|
|
679
|
+
conn.laddr.port == self.port
|
|
680
|
+
and conn.status == "LISTEN"
|
|
681
|
+
):
|
|
682
|
+
# Found process listening on our port
|
|
683
|
+
if "python" in proc.name().lower():
|
|
684
|
+
self.logger.debug(
|
|
685
|
+
f"Found likely orphaned claude-mpm service on port {self.port}, PID: {proc.pid}"
|
|
686
|
+
)
|
|
687
|
+
return True, proc.pid
|
|
688
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
689
|
+
continue
|
|
690
|
+
except ImportError:
|
|
691
|
+
pass
|
|
692
|
+
|
|
693
|
+
# Socket.IO service exists but can't determine if it's ours
|
|
694
|
+
self.logger.debug(
|
|
695
|
+
f"Found Socket.IO service on port {self.port}, but cannot confirm ownership"
|
|
696
|
+
)
|
|
697
|
+
return False, None
|
|
698
|
+
|
|
699
|
+
except Exception:
|
|
700
|
+
pass
|
|
701
|
+
finally:
|
|
702
|
+
if sio_client.connected:
|
|
703
|
+
sio_client.disconnect()
|
|
704
|
+
|
|
705
|
+
except ImportError:
|
|
706
|
+
# socketio not available
|
|
707
|
+
pass
|
|
708
|
+
except Exception as e:
|
|
709
|
+
self.logger.debug(f"Error checking Socket.IO connection: {e}")
|
|
710
|
+
|
|
711
|
+
# Method 4: Final fallback - if we have a PID file and can't definitively say it's NOT ours
|
|
712
|
+
# This handles edge cases where the health endpoint might be temporarily unavailable
|
|
713
|
+
if pid and self.pid_file.exists():
|
|
714
|
+
try:
|
|
715
|
+
# One more check - see if process exists
|
|
716
|
+
os.kill(pid, 0)
|
|
717
|
+
self.logger.info(
|
|
718
|
+
f"PID file exists with valid process {pid}, assuming it's our stale service"
|
|
719
|
+
)
|
|
720
|
+
return True, pid
|
|
721
|
+
except (OSError, ProcessLookupError):
|
|
722
|
+
pass
|
|
723
|
+
|
|
724
|
+
# No service detected or not ours
|
|
725
|
+
self.logger.debug("Service not detected as ours")
|
|
726
|
+
return False, None
|
|
727
|
+
|
|
728
|
+
except Exception as e:
|
|
729
|
+
self.logger.error(f"Error checking if service is ours: {e}", exc_info=True)
|
|
730
|
+
return False, None
|