claude-mpm 5.4.22__py3-none-any.whl → 5.6.34__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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
- claude_mpm/agents/MEMORY.md +1 -1
- claude_mpm/agents/PM_INSTRUCTIONS.md +374 -1257
- claude_mpm/agents/WORKFLOW.md +6 -253
- claude_mpm/agents/agent_loader.py +1 -1
- claude_mpm/agents/base_agent.json +31 -0
- claude_mpm/agents/frontmatter_validator.py +2 -2
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agent_state_manager.py +10 -10
- claude_mpm/cli/commands/agents.py +11 -13
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/auto_configure.py +4 -4
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/configure.py +621 -22
- claude_mpm/cli/commands/configure_agent_display.py +12 -0
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +72 -0
- claude_mpm/cli/commands/postmortem.py +1 -1
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +182 -32
- claude_mpm/cli/executor.py +130 -16
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +32 -52
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/base_parser.py +83 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -0
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +2 -3
- claude_mpm/cli/startup.py +690 -386
- claude_mpm/cli/startup_display.py +74 -6
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +78 -0
- claude_mpm/commander/adapters/__init__.py +60 -0
- claude_mpm/commander/adapters/auggie.py +260 -0
- claude_mpm/commander/adapters/base.py +288 -0
- claude_mpm/commander/adapters/claude_code.py +392 -0
- claude_mpm/commander/adapters/codex.py +237 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/adapters/example_usage.py +310 -0
- claude_mpm/commander/adapters/mpm.py +389 -0
- claude_mpm/commander/adapters/registry.py +204 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +121 -0
- claude_mpm/commander/api/errors.py +133 -0
- claude_mpm/commander/api/routes/__init__.py +8 -0
- claude_mpm/commander/api/routes/events.py +184 -0
- claude_mpm/commander/api/routes/inbox.py +171 -0
- claude_mpm/commander/api/routes/messages.py +148 -0
- claude_mpm/commander/api/routes/projects.py +271 -0
- claude_mpm/commander/api/routes/sessions.py +226 -0
- claude_mpm/commander/api/routes/work.py +296 -0
- claude_mpm/commander/api/schemas.py +186 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +146 -0
- claude_mpm/commander/chat/commands.py +96 -0
- claude_mpm/commander/chat/repl.py +310 -0
- claude_mpm/commander/config.py +51 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/core/__init__.py +10 -0
- claude_mpm/commander/core/block_manager.py +325 -0
- claude_mpm/commander/core/response_manager.py +323 -0
- claude_mpm/commander/daemon.py +603 -0
- claude_mpm/commander/env_loader.py +59 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +332 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +146 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +62 -0
- claude_mpm/commander/inbox/__init__.py +16 -0
- claude_mpm/commander/inbox/dedup.py +128 -0
- claude_mpm/commander/inbox/inbox.py +224 -0
- claude_mpm/commander/inbox/models.py +70 -0
- claude_mpm/commander/instance_manager.py +450 -0
- claude_mpm/commander/llm/__init__.py +6 -0
- claude_mpm/commander/llm/openrouter_client.py +167 -0
- claude_mpm/commander/llm/summarizer.py +70 -0
- claude_mpm/commander/memory/__init__.py +45 -0
- claude_mpm/commander/memory/compression.py +347 -0
- claude_mpm/commander/memory/embeddings.py +230 -0
- claude_mpm/commander/memory/entities.py +310 -0
- claude_mpm/commander/memory/example_usage.py +290 -0
- claude_mpm/commander/memory/integration.py +325 -0
- claude_mpm/commander/memory/search.py +381 -0
- claude_mpm/commander/memory/store.py +657 -0
- claude_mpm/commander/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +121 -0
- claude_mpm/commander/models/project.py +162 -0
- claude_mpm/commander/models/work.py +214 -0
- claude_mpm/commander/parsing/__init__.py +20 -0
- claude_mpm/commander/parsing/extractor.py +132 -0
- claude_mpm/commander/parsing/output_parser.py +270 -0
- claude_mpm/commander/parsing/patterns.py +100 -0
- claude_mpm/commander/persistence/__init__.py +11 -0
- claude_mpm/commander/persistence/event_store.py +274 -0
- claude_mpm/commander/persistence/state_store.py +309 -0
- claude_mpm/commander/persistence/work_store.py +164 -0
- claude_mpm/commander/polling/__init__.py +13 -0
- claude_mpm/commander/polling/event_detector.py +104 -0
- claude_mpm/commander/polling/output_buffer.py +49 -0
- claude_mpm/commander/polling/output_poller.py +153 -0
- claude_mpm/commander/project_session.py +268 -0
- claude_mpm/commander/proxy/__init__.py +12 -0
- claude_mpm/commander/proxy/formatter.py +89 -0
- claude_mpm/commander/proxy/output_handler.py +191 -0
- claude_mpm/commander/proxy/relay.py +155 -0
- claude_mpm/commander/registry.py +410 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +346 -0
- claude_mpm/commander/session/__init__.py +6 -0
- claude_mpm/commander/session/context.py +81 -0
- claude_mpm/commander/session/manager.py +59 -0
- claude_mpm/commander/tmux_orchestrator.py +361 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +207 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +241 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +20 -249
- claude_mpm/commands/mpm-doctor.md +16 -21
- claude_mpm/commands/mpm-help.md +12 -205
- claude_mpm/commands/mpm-init.md +88 -506
- claude_mpm/commands/mpm-monitor.md +22 -401
- claude_mpm/commands/mpm-organize.md +70 -442
- claude_mpm/commands/mpm-postmortem.md +13 -107
- claude_mpm/commands/mpm-session-resume.md +20 -363
- claude_mpm/commands/mpm-status.md +13 -69
- claude_mpm/commands/mpm-ticket-view.md +60 -495
- claude_mpm/commands/mpm-version.md +13 -107
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/config/skill_sources.py +16 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +154 -2
- claude_mpm/core/config.py +37 -26
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/framework/loaders/agent_loader.py +1 -1
- claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
- claude_mpm/core/hook_manager.py +51 -3
- claude_mpm/core/interactive_session.py +12 -11
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +39 -13
- claude_mpm/core/network_config.py +148 -0
- claude_mpm/core/oneshot_session.py +7 -6
- claude_mpm/core/optimized_startup.py +61 -0
- claude_mpm/core/output_style_manager.py +66 -18
- claude_mpm/core/shared/config_loader.py +3 -1
- claude_mpm/core/socketio_pool.py +47 -15
- claude_mpm/core/unified_agent_registry.py +1 -1
- claude_mpm/core/unified_config.py +54 -8
- claude_mpm/core/unified_paths.py +95 -90
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.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/BRcwIQNr.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DR8nis88.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.RgBboRvH.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.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/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
- claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +527 -136
- claude_mpm/hooks/claude_hooks/hook_handler.py +313 -99
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +206 -36
- claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
- claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
- claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +67 -32
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
- claude_mpm/hooks/claude_hooks/services/container.py +310 -0
- claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
- claude_mpm/hooks/kuzu_memory_hook.py +5 -5
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
- claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
- claude_mpm/init.py +276 -0
- claude_mpm/models/git_repository.py +3 -3
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- claude_mpm/services/agents/agent_builder.py +3 -3
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/cache_git_manager.py +7 -7
- claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -2
- claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
- claude_mpm/services/agents/deployment/agent_template_builder.py +39 -19
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
- claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +169 -26
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +101 -75
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/git_source_manager.py +23 -4
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/recommender.py +5 -3
- claude_mpm/services/agents/single_tier_deployment_service.py +6 -6
- claude_mpm/services/agents/sources/git_source_sync_service.py +121 -10
- claude_mpm/services/agents/startup_sync.py +27 -4
- claude_mpm/services/cli/__init__.py +3 -0
- claude_mpm/services/cli/incremental_pause_manager.py +561 -0
- claude_mpm/services/cli/session_resume_helper.py +10 -2
- claude_mpm/services/command_deployment_service.py +44 -26
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +31 -1
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
- claude_mpm/services/diagnostics/models.py +14 -1
- claude_mpm/services/event_log.py +325 -0
- claude_mpm/services/git/git_operations_service.py +8 -8
- claude_mpm/services/hook_installer_service.py +77 -8
- claude_mpm/services/infrastructure/__init__.py +4 -0
- claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
- claude_mpm/services/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +15 -3
- claude_mpm/services/monitor/server.py +571 -11
- claude_mpm/services/pm_skills_deployer.py +884 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/skills/git_skill_source_manager.py +281 -20
- claude_mpm/services/skills/selective_skill_deployer.py +211 -46
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +192 -70
- claude_mpm/services/socketio/dashboard_server.py +1 -0
- claude_mpm/services/socketio/event_normalizer.py +37 -6
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/core.py +262 -123
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/skills/__init__.py +2 -1
- 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/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/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/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/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/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/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
- claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
- claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
- claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
- claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
- claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
- claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
- claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
- claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
- claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
- claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
- claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -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 +112 -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/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/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -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/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +98 -3
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/utils/agent_dependency_loader.py +115 -4
- claude_mpm/utils/agent_filters.py +1 -1
- claude_mpm/utils/migration.py +4 -4
- claude_mpm/utils/robust_installer.py +86 -21
- claude_mpm-5.6.34.dist-info/METADATA +393 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/RECORD +486 -145
- claude_mpm-5.4.22.dist-info/METADATA +0 -996
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"""Event Log Service for persistent event storage.
|
|
2
|
+
|
|
3
|
+
WHY this is needed:
|
|
4
|
+
- Decouple event producers from consumers
|
|
5
|
+
- Persist events for later processing (e.g., autotodos CLI)
|
|
6
|
+
- Enable event-driven architecture patterns
|
|
7
|
+
- Provide audit trail of system events
|
|
8
|
+
|
|
9
|
+
DESIGN DECISION: Simple JSON file storage because:
|
|
10
|
+
- Human-readable and inspectable
|
|
11
|
+
- No additional database dependencies
|
|
12
|
+
- Fast for small event volumes
|
|
13
|
+
- Easy to clear and manage
|
|
14
|
+
- Follows existing pattern (hook_error_memory)
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
from datetime import datetime, timezone
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
21
|
+
|
|
22
|
+
from ..core.logger import get_logger
|
|
23
|
+
|
|
24
|
+
# Event status types
|
|
25
|
+
EventStatus = Literal["pending", "resolved", "archived"]
|
|
26
|
+
|
|
27
|
+
# Max message length to prevent file bloat
|
|
28
|
+
MAX_MESSAGE_LENGTH = 2000
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class EventLog:
|
|
32
|
+
"""Persistent event log with simple JSON storage.
|
|
33
|
+
|
|
34
|
+
WHY this design:
|
|
35
|
+
- Store events with timestamp, type, payload, status
|
|
36
|
+
- Support filtering by status and event type
|
|
37
|
+
- Prevent file bloat with message truncation
|
|
38
|
+
- Enable mark-as-resolved workflow
|
|
39
|
+
- Keep it simple - no complex queries needed
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self, log_file: Optional[Path] = None):
|
|
43
|
+
"""Initialize event log.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
log_file: Path to event log file (default: .claude-mpm/event_log.json)
|
|
47
|
+
"""
|
|
48
|
+
self.logger = get_logger("event_log")
|
|
49
|
+
|
|
50
|
+
# Use default location if not specified
|
|
51
|
+
if log_file is None:
|
|
52
|
+
log_file = Path.cwd() / ".claude-mpm" / "event_log.json"
|
|
53
|
+
|
|
54
|
+
self.log_file = log_file
|
|
55
|
+
self.events: List[Dict[str, Any]] = self._load_events()
|
|
56
|
+
|
|
57
|
+
def _load_events(self) -> List[Dict[str, Any]]:
|
|
58
|
+
"""Load events from disk.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
List of event records
|
|
62
|
+
"""
|
|
63
|
+
if not self.log_file.exists():
|
|
64
|
+
return []
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
content = self.log_file.read_text()
|
|
68
|
+
if not content.strip():
|
|
69
|
+
return []
|
|
70
|
+
data = json.loads(content)
|
|
71
|
+
|
|
72
|
+
# Validate structure
|
|
73
|
+
if not isinstance(data, list):
|
|
74
|
+
self.logger.warning("Event log is not a list, resetting")
|
|
75
|
+
return []
|
|
76
|
+
|
|
77
|
+
return data
|
|
78
|
+
except json.JSONDecodeError as e:
|
|
79
|
+
self.logger.warning(f"Failed to parse event log: {e}, resetting")
|
|
80
|
+
return []
|
|
81
|
+
except Exception as e:
|
|
82
|
+
self.logger.error(f"Error loading event log: {e}")
|
|
83
|
+
return []
|
|
84
|
+
|
|
85
|
+
def _save_events(self):
|
|
86
|
+
"""Persist events to disk."""
|
|
87
|
+
try:
|
|
88
|
+
# Ensure directory exists
|
|
89
|
+
self.log_file.parent.mkdir(parents=True, exist_ok=True)
|
|
90
|
+
|
|
91
|
+
# Write with pretty formatting for human readability
|
|
92
|
+
self.log_file.write_text(json.dumps(self.events, indent=2))
|
|
93
|
+
except Exception as e:
|
|
94
|
+
self.logger.error(f"Failed to save event log: {e}")
|
|
95
|
+
|
|
96
|
+
def _truncate_message(self, message: str) -> str:
|
|
97
|
+
"""Truncate message to prevent file bloat.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
message: Message to truncate
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Truncated message with ellipsis if needed
|
|
104
|
+
"""
|
|
105
|
+
if len(message) <= MAX_MESSAGE_LENGTH:
|
|
106
|
+
return message
|
|
107
|
+
|
|
108
|
+
return message[:MAX_MESSAGE_LENGTH] + "... (truncated)"
|
|
109
|
+
|
|
110
|
+
def append_event(
|
|
111
|
+
self,
|
|
112
|
+
event_type: str,
|
|
113
|
+
payload: Dict[str, Any],
|
|
114
|
+
status: EventStatus = "pending",
|
|
115
|
+
) -> str:
|
|
116
|
+
"""Append a new event to the log.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
event_type: Type of event (e.g., "autotodo.error", "hook.error")
|
|
120
|
+
payload: Event data (will be truncated if too large)
|
|
121
|
+
status: Event status (default: "pending")
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Event ID (timestamp-based for simplicity)
|
|
125
|
+
"""
|
|
126
|
+
# Truncate any message fields in payload
|
|
127
|
+
truncated_payload = payload.copy()
|
|
128
|
+
if "message" in truncated_payload:
|
|
129
|
+
truncated_payload["message"] = self._truncate_message(
|
|
130
|
+
str(truncated_payload["message"])
|
|
131
|
+
)
|
|
132
|
+
if "full_message" in truncated_payload:
|
|
133
|
+
truncated_payload["full_message"] = self._truncate_message(
|
|
134
|
+
str(truncated_payload["full_message"])
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Create event record
|
|
138
|
+
timestamp = datetime.now(timezone.utc).isoformat()
|
|
139
|
+
event = {
|
|
140
|
+
"id": timestamp, # Use timestamp as ID for simplicity
|
|
141
|
+
"timestamp": timestamp,
|
|
142
|
+
"event_type": event_type,
|
|
143
|
+
"payload": truncated_payload,
|
|
144
|
+
"status": status,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# Append and save
|
|
148
|
+
self.events.append(event)
|
|
149
|
+
self._save_events()
|
|
150
|
+
|
|
151
|
+
self.logger.debug(f"Appended event: {event_type} (status: {status})")
|
|
152
|
+
return timestamp
|
|
153
|
+
|
|
154
|
+
def list_events(
|
|
155
|
+
self,
|
|
156
|
+
event_type: Optional[str] = None,
|
|
157
|
+
status: Optional[EventStatus] = None,
|
|
158
|
+
limit: Optional[int] = None,
|
|
159
|
+
) -> List[Dict[str, Any]]:
|
|
160
|
+
"""List events with optional filtering.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
event_type: Filter by event type (e.g., "autotodo.error")
|
|
164
|
+
status: Filter by status (e.g., "pending")
|
|
165
|
+
limit: Maximum number of events to return (most recent first)
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
List of matching events
|
|
169
|
+
"""
|
|
170
|
+
# Filter events
|
|
171
|
+
filtered = self.events
|
|
172
|
+
|
|
173
|
+
if event_type:
|
|
174
|
+
filtered = [e for e in filtered if e["event_type"] == event_type]
|
|
175
|
+
|
|
176
|
+
if status:
|
|
177
|
+
filtered = [e for e in filtered if e["status"] == status]
|
|
178
|
+
|
|
179
|
+
# Sort by timestamp (most recent first)
|
|
180
|
+
filtered = sorted(filtered, key=lambda e: e["timestamp"], reverse=True)
|
|
181
|
+
|
|
182
|
+
# Apply limit
|
|
183
|
+
if limit:
|
|
184
|
+
filtered = filtered[:limit]
|
|
185
|
+
|
|
186
|
+
return filtered
|
|
187
|
+
|
|
188
|
+
def mark_resolved(self, event_id: str) -> bool:
|
|
189
|
+
"""Mark an event as resolved.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
event_id: Event ID (timestamp)
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
True if event was found and updated
|
|
196
|
+
"""
|
|
197
|
+
for event in self.events:
|
|
198
|
+
if event["id"] == event_id:
|
|
199
|
+
event["status"] = "resolved"
|
|
200
|
+
event["resolved_at"] = datetime.now(timezone.utc).isoformat()
|
|
201
|
+
self._save_events()
|
|
202
|
+
self.logger.debug(f"Marked event resolved: {event_id}")
|
|
203
|
+
return True
|
|
204
|
+
|
|
205
|
+
return False
|
|
206
|
+
|
|
207
|
+
def mark_all_resolved(
|
|
208
|
+
self, event_type: Optional[str] = None, status: EventStatus = "pending"
|
|
209
|
+
) -> int:
|
|
210
|
+
"""Mark multiple events as resolved.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
event_type: Optional filter by event type
|
|
214
|
+
status: Filter by current status (default: "pending")
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
Number of events marked as resolved
|
|
218
|
+
"""
|
|
219
|
+
count = 0
|
|
220
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
221
|
+
|
|
222
|
+
for event in self.events:
|
|
223
|
+
# Check filters
|
|
224
|
+
if event["status"] != status:
|
|
225
|
+
continue
|
|
226
|
+
if event_type and event["event_type"] != event_type:
|
|
227
|
+
continue
|
|
228
|
+
|
|
229
|
+
# Mark resolved
|
|
230
|
+
event["status"] = "resolved"
|
|
231
|
+
event["resolved_at"] = now
|
|
232
|
+
count += 1
|
|
233
|
+
|
|
234
|
+
if count > 0:
|
|
235
|
+
self._save_events()
|
|
236
|
+
self.logger.debug(f"Marked {count} events as resolved")
|
|
237
|
+
|
|
238
|
+
return count
|
|
239
|
+
|
|
240
|
+
def clear_resolved(self, older_than_days: Optional[int] = None) -> int:
|
|
241
|
+
"""Remove resolved events from the log.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
older_than_days: Only clear events older than N days
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
Number of events removed
|
|
248
|
+
"""
|
|
249
|
+
if older_than_days:
|
|
250
|
+
# Calculate cutoff timestamp
|
|
251
|
+
from datetime import timedelta
|
|
252
|
+
|
|
253
|
+
cutoff = datetime.now(timezone.utc) - timedelta(days=older_than_days)
|
|
254
|
+
cutoff_iso = cutoff.isoformat()
|
|
255
|
+
|
|
256
|
+
# Keep events that are NOT resolved OR are newer than cutoff
|
|
257
|
+
before_count = len(self.events)
|
|
258
|
+
self.events = [
|
|
259
|
+
e
|
|
260
|
+
for e in self.events
|
|
261
|
+
if e["status"] != "resolved" or e.get("resolved_at", "") > cutoff_iso
|
|
262
|
+
]
|
|
263
|
+
removed = before_count - len(self.events)
|
|
264
|
+
else:
|
|
265
|
+
# Remove all resolved events
|
|
266
|
+
before_count = len(self.events)
|
|
267
|
+
self.events = [e for e in self.events if e["status"] != "resolved"]
|
|
268
|
+
removed = before_count - len(self.events)
|
|
269
|
+
|
|
270
|
+
if removed > 0:
|
|
271
|
+
self._save_events()
|
|
272
|
+
self.logger.debug(f"Cleared {removed} resolved events")
|
|
273
|
+
|
|
274
|
+
return removed
|
|
275
|
+
|
|
276
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
277
|
+
"""Get event log statistics.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
Dictionary with event counts by status and type
|
|
281
|
+
"""
|
|
282
|
+
stats = {
|
|
283
|
+
"total_events": len(self.events),
|
|
284
|
+
"by_status": {"pending": 0, "resolved": 0, "archived": 0},
|
|
285
|
+
"by_type": {},
|
|
286
|
+
"log_file": str(self.log_file),
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
for event in self.events:
|
|
290
|
+
# Count by status
|
|
291
|
+
status = event["status"]
|
|
292
|
+
stats["by_status"][status] = stats["by_status"].get(status, 0) + 1
|
|
293
|
+
|
|
294
|
+
# Count by type
|
|
295
|
+
event_type = event["event_type"]
|
|
296
|
+
stats["by_type"][event_type] = stats["by_type"].get(event_type, 0) + 1
|
|
297
|
+
|
|
298
|
+
return stats
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
# Global instance
|
|
302
|
+
_event_log: Optional[EventLog] = None
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def get_event_log(log_file: Optional[Path] = None) -> EventLog:
|
|
306
|
+
"""Get the global event log instance.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
log_file: Optional custom log file path
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
EventLog instance
|
|
313
|
+
|
|
314
|
+
Note:
|
|
315
|
+
If log_file is provided and differs from the current instance,
|
|
316
|
+
a new EventLog is created and replaces the global instance.
|
|
317
|
+
This allows hooks to use project-specific event logs.
|
|
318
|
+
"""
|
|
319
|
+
global _event_log
|
|
320
|
+
if _event_log is None:
|
|
321
|
+
_event_log = EventLog(log_file)
|
|
322
|
+
elif log_file is not None and _event_log.log_file != log_file:
|
|
323
|
+
# Create new instance if log file differs from current
|
|
324
|
+
_event_log = EventLog(log_file)
|
|
325
|
+
return _event_log
|
|
@@ -12,10 +12,10 @@ Design Decisions:
|
|
|
12
12
|
|
|
13
13
|
Example:
|
|
14
14
|
>>> service = GitOperationsService()
|
|
15
|
-
>>> success = service.create_branch(Path("~/.claude-mpm/cache/
|
|
15
|
+
>>> success = service.create_branch(Path("~/.claude-mpm/cache/agents"), "improve/research-memory")
|
|
16
16
|
>>> if success:
|
|
17
|
-
... service.stage_files(Path("~/.claude-mpm/cache/
|
|
18
|
-
... service.commit(Path("~/.claude-mpm/cache/
|
|
17
|
+
... service.stage_files(Path("~/.claude-mpm/cache/agents"), ["agents/research.md"])
|
|
18
|
+
... service.commit(Path("~/.claude-mpm/cache/agents"), "feat: improve research agent memory handling")
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
import logging
|
|
@@ -68,7 +68,7 @@ class GitOperationsService:
|
|
|
68
68
|
|
|
69
69
|
Example:
|
|
70
70
|
>>> service = GitOperationsService()
|
|
71
|
-
>>> service.is_git_repo(Path("~/.claude-mpm/cache/
|
|
71
|
+
>>> service.is_git_repo(Path("~/.claude-mpm/cache/agents"))
|
|
72
72
|
True
|
|
73
73
|
"""
|
|
74
74
|
try:
|
|
@@ -150,7 +150,7 @@ class GitOperationsService:
|
|
|
150
150
|
Example:
|
|
151
151
|
>>> service = GitOperationsService()
|
|
152
152
|
>>> service.create_and_checkout_branch(
|
|
153
|
-
... Path("~/.claude-mpm/cache/
|
|
153
|
+
... Path("~/.claude-mpm/cache/agents"),
|
|
154
154
|
... "improve/research-memory",
|
|
155
155
|
... "main"
|
|
156
156
|
... )
|
|
@@ -245,7 +245,7 @@ class GitOperationsService:
|
|
|
245
245
|
Example:
|
|
246
246
|
>>> service = GitOperationsService()
|
|
247
247
|
>>> service.commit(
|
|
248
|
-
... Path("~/.claude-mpm/cache/
|
|
248
|
+
... Path("~/.claude-mpm/cache/agents"),
|
|
249
249
|
... "feat(agent): improve research agent memory handling\\n\\n- Add hard limit of 5 files"
|
|
250
250
|
... )
|
|
251
251
|
True
|
|
@@ -289,7 +289,7 @@ class GitOperationsService:
|
|
|
289
289
|
|
|
290
290
|
Example:
|
|
291
291
|
>>> service = GitOperationsService()
|
|
292
|
-
>>> service.push(Path("~/.claude-mpm/cache/
|
|
292
|
+
>>> service.push(Path("~/.claude-mpm/cache/agents"), "improve/research-memory")
|
|
293
293
|
True
|
|
294
294
|
"""
|
|
295
295
|
self._validate_repo(repo_path)
|
|
@@ -489,7 +489,7 @@ class GitOperationsService:
|
|
|
489
489
|
|
|
490
490
|
Example:
|
|
491
491
|
>>> service = GitOperationsService()
|
|
492
|
-
>>> valid, msg = service.validate_repo(Path("~/.claude-mpm/cache/
|
|
492
|
+
>>> valid, msg = service.validate_repo(Path("~/.claude-mpm/cache/agents"))
|
|
493
493
|
>>> if not valid:
|
|
494
494
|
... print(f"Repository invalid: {msg}")
|
|
495
495
|
"""
|
|
@@ -20,8 +20,13 @@ class HookInstallerService:
|
|
|
20
20
|
def __init__(self):
|
|
21
21
|
"""Initialize the hook installer service."""
|
|
22
22
|
self.logger = get_logger(__name__)
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
# Use project-level paths, NEVER global ~/.claude/settings.json
|
|
24
|
+
# This ensures hooks are scoped to the current project only
|
|
25
|
+
self.project_root = Path.cwd()
|
|
26
|
+
self.claude_dir = self.project_root / ".claude"
|
|
27
|
+
# Use settings.local.json for project-level hook settings
|
|
28
|
+
# Claude Code reads project-level settings from .claude/settings.local.json
|
|
29
|
+
self.settings_file = self.claude_dir / "settings.local.json"
|
|
25
30
|
|
|
26
31
|
def is_hooks_configured(self) -> bool:
|
|
27
32
|
"""Check if hooks are configured in Claude settings.
|
|
@@ -299,16 +304,77 @@ class HookInstallerService:
|
|
|
299
304
|
self.logger.debug("Creating new Claude settings")
|
|
300
305
|
|
|
301
306
|
# Configure hooks
|
|
302
|
-
|
|
303
|
-
"matcher": "*",
|
|
304
|
-
"hooks": [{"type": "command", "command": hook_script_path}],
|
|
305
|
-
}
|
|
307
|
+
new_hook_command = {"type": "command", "command": hook_script_path}
|
|
306
308
|
|
|
307
309
|
# Update settings
|
|
308
310
|
if "hooks" not in settings:
|
|
309
311
|
settings["hooks"] = {}
|
|
310
312
|
|
|
311
|
-
|
|
313
|
+
def is_our_hook(cmd: Dict[str, Any]) -> bool:
|
|
314
|
+
"""Check if a hook command belongs to claude-mpm."""
|
|
315
|
+
if cmd.get("type") != "command":
|
|
316
|
+
return False
|
|
317
|
+
command = cmd.get("command", "")
|
|
318
|
+
return (
|
|
319
|
+
"hook_wrapper.sh" in command
|
|
320
|
+
or "claude-hook-handler.sh" in command
|
|
321
|
+
or "claude-mpm" in command
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
def merge_hooks_for_event(
|
|
325
|
+
existing_hooks: list, hook_command: Dict[str, Any]
|
|
326
|
+
) -> list:
|
|
327
|
+
"""Merge new hook command into existing hooks without duplication.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
existing_hooks: Current hooks configuration for an event type
|
|
331
|
+
hook_command: The claude-mpm hook command to add
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
Updated hooks list with our hook merged in
|
|
335
|
+
"""
|
|
336
|
+
# Check if our hook already exists in any existing hook config
|
|
337
|
+
our_hook_exists = False
|
|
338
|
+
|
|
339
|
+
for hook_config in existing_hooks:
|
|
340
|
+
if "hooks" in hook_config and isinstance(
|
|
341
|
+
hook_config["hooks"], list
|
|
342
|
+
):
|
|
343
|
+
for hook in hook_config["hooks"]:
|
|
344
|
+
if is_our_hook(hook):
|
|
345
|
+
# Update existing hook command path (in case it changed)
|
|
346
|
+
hook["command"] = hook_command["command"]
|
|
347
|
+
our_hook_exists = True
|
|
348
|
+
break
|
|
349
|
+
if our_hook_exists:
|
|
350
|
+
break
|
|
351
|
+
|
|
352
|
+
if our_hook_exists:
|
|
353
|
+
# Our hook already exists, just return the updated list
|
|
354
|
+
return existing_hooks
|
|
355
|
+
|
|
356
|
+
# Our hook doesn't exist - need to add it
|
|
357
|
+
# Strategy: Add our hook to the first "*" matcher config, or create new
|
|
358
|
+
added = False
|
|
359
|
+
|
|
360
|
+
for hook_config in existing_hooks:
|
|
361
|
+
# Check if this config has matcher: "*"
|
|
362
|
+
if hook_config.get("matcher") == "*":
|
|
363
|
+
# Add our hook to this config's hooks array
|
|
364
|
+
if "hooks" not in hook_config:
|
|
365
|
+
hook_config["hooks"] = []
|
|
366
|
+
hook_config["hooks"].append(hook_command)
|
|
367
|
+
added = True
|
|
368
|
+
break
|
|
369
|
+
|
|
370
|
+
if not added:
|
|
371
|
+
# No suitable config found, create a new one
|
|
372
|
+
new_config = {"matcher": "*", "hooks": [hook_command]}
|
|
373
|
+
existing_hooks.append(new_config)
|
|
374
|
+
|
|
375
|
+
return existing_hooks
|
|
376
|
+
|
|
377
|
+
# Add hooks for all event types - MERGE instead of overwrite
|
|
312
378
|
for event_type in [
|
|
313
379
|
"UserPromptSubmit",
|
|
314
380
|
"PreToolUse",
|
|
@@ -316,7 +382,10 @@ class HookInstallerService:
|
|
|
316
382
|
"Stop",
|
|
317
383
|
"SubagentStop",
|
|
318
384
|
]:
|
|
319
|
-
settings["hooks"]
|
|
385
|
+
existing = settings["hooks"].get(event_type, [])
|
|
386
|
+
settings["hooks"][event_type] = merge_hooks_for_event(
|
|
387
|
+
existing, new_hook_command
|
|
388
|
+
)
|
|
320
389
|
|
|
321
390
|
# Write settings
|
|
322
391
|
with self.settings_file.open("w") as f:
|
|
@@ -11,8 +11,10 @@ Services:
|
|
|
11
11
|
- LoggingService: Centralized logging with structured output
|
|
12
12
|
- HealthMonitor: System health monitoring and alerting
|
|
13
13
|
- MemoryGuardian: Memory monitoring and process restart management
|
|
14
|
+
- ContextUsageTracker: Token usage tracking across hook invocations
|
|
14
15
|
"""
|
|
15
16
|
|
|
17
|
+
from .context_usage_tracker import ContextUsageState, ContextUsageTracker
|
|
16
18
|
from .logging import LoggingService
|
|
17
19
|
from .monitoring import (
|
|
18
20
|
AdvancedHealthMonitor,
|
|
@@ -36,6 +38,8 @@ except ImportError:
|
|
|
36
38
|
|
|
37
39
|
__all__ = [
|
|
38
40
|
"AdvancedHealthMonitor", # For SocketIO server monitoring
|
|
41
|
+
"ContextUsageState",
|
|
42
|
+
"ContextUsageTracker",
|
|
39
43
|
"LoggingService",
|
|
40
44
|
# New service-based monitoring API
|
|
41
45
|
"MonitoringAggregatorService",
|