claude-mpm 5.4.85__py3-none-any.whl → 5.6.1__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/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +8 -5
- claude_mpm/agents/{CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md → CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md} +14 -6
- claude_mpm/agents/PM_INSTRUCTIONS.md +101 -703
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +46 -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 +2 -2
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/executor.py +119 -16
- claude_mpm/cli/parsers/base_parser.py +71 -1
- claude_mpm/cli/parsers/commander_parser.py +83 -0
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/startup.py +54 -16
- claude_mpm/cli/startup_display.py +72 -5
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +72 -0
- claude_mpm/commander/adapters/__init__.py +31 -0
- claude_mpm/commander/adapters/base.py +191 -0
- claude_mpm/commander/adapters/claude_code.py +361 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +105 -0
- claude_mpm/commander/api/errors.py +112 -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 +215 -0
- claude_mpm/commander/api/routes/work.py +260 -0
- claude_mpm/commander/api/schemas.py +182 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +107 -0
- claude_mpm/commander/chat/commands.py +96 -0
- claude_mpm/commander/chat/repl.py +310 -0
- claude_mpm/commander/config.py +49 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/daemon.py +398 -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 +143 -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 +337 -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/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 +404 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +316 -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 +189 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +219 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +8 -0
- claude_mpm/commands/mpm-doctor.md +8 -0
- claude_mpm/commands/mpm-help.md +8 -0
- claude_mpm/commands/mpm-init.md +8 -0
- claude_mpm/commands/mpm-monitor.md +8 -0
- claude_mpm/commands/mpm-organize.md +8 -0
- claude_mpm/commands/mpm-postmortem.md +8 -0
- claude_mpm/commands/mpm-session-resume.md +9 -1
- claude_mpm/commands/mpm-status.md +8 -0
- claude_mpm/commands/mpm-ticket-view.md +8 -0
- claude_mpm/commands/mpm-version.md +8 -0
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/core/config.py +5 -0
- claude_mpm/core/hook_manager.py +51 -3
- claude_mpm/core/logger.py +10 -7
- claude_mpm/core/logging_utils.py +4 -2
- claude_mpm/core/output_style_manager.py +15 -5
- claude_mpm/core/unified_config.py +10 -6
- 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/{Cs_tUR18.js → 1WZnGYqX.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CDuw-vjf.js → 67pF3qNn.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bTOqqlTd.js → 6RxdMKe4.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DwBR2MJi.js → 8cZrfX0h.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{ZGh7QtNv.js → 9a6T2nm-.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D9lljYKQ.js → B443AUzu.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{RJiighC3.js → B8AwtY2H.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uuIeMWc-.js → BF15LAsF.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D3k0OPJN.js → BRcwIQNr.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CyWMqx4W.js → BV6nKitt.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CiIAseT4.js → BViJ8lZt.js} +5 -5
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CBBdVcY8.js → BcQ-Q0FE.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BovzEFCE.js → Bpyvgze_.js} +1 -1
- 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/{eNVUfhuA.js → C3rbW_a-.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{GYwsonyD.js → C8WYN38h.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BIF9m_hv.js → C9I8FlXH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B0uc0UOD.js → CIQcWgO2.js} +3 -3
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Be7GpZd6.js → CIctN7YN.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Bh0LDWpI.js → CKrS_JZW.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DUrLdbGD.js → CR6P9C4A.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7xVLGWV.js → CRRR9MD_.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dhb8PKl3.js → CSXtMOf0.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BPYeabCQ.js → CT-sbxSk.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{sQeU3Y1z.js → CWm6DJsp.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CnA0NrzZ.js → CpqQ1Kzn.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4B-KCzX.js → D2nGpDRe.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DGkLK5U1.js → D9iCMida.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BofRWZRR.js → D9ykgMoY.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DmxopI1J.js → DL2Ldur1.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C30mlcqg.js → DPfltzjH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Vzk33B_K.js → DR8nis88.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DI7hHRFL.js → DUliQN2b.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4JcI4KD.js → DXlhR01x.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bT1r9zLR.js → D_lyTybS.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DZX00Y4g.js → DngoTTgh.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzZX-COe.js → DqkmHtDC.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7RN905-.js → DsDh8EYs.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DLVjFsZ3.js → DypDmXgd.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{iEWssX7S.js → IPYC-LnN.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DaimHw_p.js → JpevfAFt.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DY1XQ8fi.js → R8CEIRAd.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dle-35c7.js → Zxy7qc-l.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C_Usid8X.js → qtd3IeO4.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzeYkLYB.js → ulBFON_C.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cfqx1Qun.js → wQVh1CoA.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/{app.D6-I5TpK.js → app.Dr7t0z2J.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.m1gL8KXf.js → 0.RgBboRvH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{1.CgNOuw-d.js → 1.DG-KkbDf.js} +1 -1
- 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 -1
- claude_mpm/dashboard/static/svelte-build/index.html +9 -9
- 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/auto_pause_handler.py +486 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +250 -11
- claude_mpm/hooks/claude_hooks/hook_handler.py +106 -89
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +69 -5
- claude_mpm/hooks/claude_hooks/response_tracking.py +3 -1
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +20 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +14 -77
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +30 -6
- claude_mpm/hooks/session_resume_hook.py +85 -1
- claude_mpm/init.py +1 -1
- claude_mpm/scripts/claude-hook-handler.sh +36 -10
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/cache_git_manager.py +1 -1
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +3 -0
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- 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/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
- 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/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 +8 -2
- claude_mpm/services/monitor/server.py +106 -16
- claude_mpm/services/pm_skills_deployer.py +259 -87
- claude_mpm/services/skills/git_skill_source_manager.py +51 -2
- claude_mpm/services/skills/selective_skill_deployer.py +114 -16
- claude_mpm/services/skills/skill_discovery_service.py +57 -3
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/main.py +12 -4
- 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-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -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-session-management/SKILL.md +312 -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/{pm-teaching-mode → mpm-teaching-mode}/SKILL.md +2 -2
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/skill_manager.py +4 -4
- claude_mpm-5.6.1.dist-info/METADATA +391 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.1.dist-info}/RECORD +244 -145
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +0 -24
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +0 -323
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +0 -1
- claude_mpm-5.4.85.dist-info/METADATA +0 -1023
- /claude_mpm/skills/bundled/pm/{pm-bug-reporting/pm-bug-reporting.md → mpm-bug-reporting/SKILL.md} +0 -0
- /claude_mpm/skills/bundled/pm/{pm-delegation-patterns → mpm-delegation-patterns}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-git-file-tracking → mpm-git-file-tracking}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-pr-workflow → mpm-pr-workflow}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-ticketing-integration → mpm-ticketing-integration}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-verification-protocols → mpm-verification-protocols}/SKILL.md +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.1.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.1.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.1.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.1.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""Delegation Pattern Detector for PM outputs.
|
|
2
|
+
|
|
3
|
+
WHY this is needed:
|
|
4
|
+
- Detect when PM asks user to do something manually instead of delegating
|
|
5
|
+
- Convert manual instructions into actionable autotodos
|
|
6
|
+
- Enforce delegation principle in PM workflow
|
|
7
|
+
- Help PM recognize delegation opportunities
|
|
8
|
+
|
|
9
|
+
DESIGN DECISION: Pattern-based detection
|
|
10
|
+
- Simple regex patterns to catch common delegation anti-patterns
|
|
11
|
+
- Extract action items from PM's output
|
|
12
|
+
- Format as autotodos for PM to see and delegate properly
|
|
13
|
+
- Non-invasive - just surfaces patterns for review
|
|
14
|
+
|
|
15
|
+
Examples of patterns to detect:
|
|
16
|
+
- "Make sure .env.local is in your .gitignore"
|
|
17
|
+
- "You'll need to run npm install"
|
|
18
|
+
- "Please run the tests manually"
|
|
19
|
+
- "Remember to update the README"
|
|
20
|
+
- "Don't forget to commit your changes"
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import re
|
|
24
|
+
from typing import Any, Dict, List, Tuple
|
|
25
|
+
|
|
26
|
+
from ..core.logger import get_logger
|
|
27
|
+
|
|
28
|
+
# Delegation anti-patterns with capture groups for action extraction
|
|
29
|
+
# Each pattern is (regex_pattern, todo_template)
|
|
30
|
+
# {match} in template will be replaced with captured text
|
|
31
|
+
USER_DELEGATION_PATTERNS: List[Tuple[str, str]] = [
|
|
32
|
+
# "Make sure (to) X" → "Verify: X"
|
|
33
|
+
(r"(?i)make sure (?:to |that |you )?(.+)", "Verify: {match}"),
|
|
34
|
+
# "You'll/will need to X" → "Task: X"
|
|
35
|
+
(r"(?i)you(?:'ll| will)? need to (.+)", "Task: {match}"),
|
|
36
|
+
# "Please run/execute/do X" → "Execute: X"
|
|
37
|
+
(r"(?i)please (?:run|execute|do) (.+)", "Execute: {match}"),
|
|
38
|
+
# "Remember to X" → "Task: X"
|
|
39
|
+
(r"(?i)remember to (.+)", "Task: {match}"),
|
|
40
|
+
# "Don't forget to X" → "Task: X"
|
|
41
|
+
(r"(?i)don'?t forget to (.+)", "Task: {match}"),
|
|
42
|
+
# "You should/can/could X" → "Suggested: X"
|
|
43
|
+
(r"(?i)you (?:should|can|could) (.+)", "Suggested: {match}"),
|
|
44
|
+
# "Be sure to X" → "Task: X"
|
|
45
|
+
(r"(?i)be sure to (.+)", "Task: {match}"),
|
|
46
|
+
# "Don't forget X" (without 'to') → "Task: X"
|
|
47
|
+
(r"(?i)don'?t forget (.+)", "Task: {match}"),
|
|
48
|
+
# "You may want to X" → "Suggested: X"
|
|
49
|
+
(r"(?i)you may want to (.+)", "Suggested: {match}"),
|
|
50
|
+
# "It's important to X" → "Task: X"
|
|
51
|
+
(r"(?i)it'?s important to (.+)", "Task: {match}"),
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class DelegationDetector:
|
|
56
|
+
"""Detects delegation anti-patterns in PM outputs.
|
|
57
|
+
|
|
58
|
+
WHY this design:
|
|
59
|
+
- Pattern-based detection for common manual instruction phrases
|
|
60
|
+
- Extract actionable tasks from PM's text
|
|
61
|
+
- Format as autotodos for PM visibility
|
|
62
|
+
- Simple and extensible (add new patterns easily)
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def __init__(self):
|
|
66
|
+
self.logger = get_logger("delegation_detector")
|
|
67
|
+
|
|
68
|
+
def detect_user_delegation(self, text: str) -> List[Dict[str, Any]]:
|
|
69
|
+
"""Detect delegation anti-patterns in text.
|
|
70
|
+
|
|
71
|
+
Scans text for patterns where PM is asking user to do something
|
|
72
|
+
manually instead of delegating to an agent.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
text: PM output text to scan
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
List of detected patterns with:
|
|
79
|
+
- pattern_type: Type of pattern matched
|
|
80
|
+
- original_text: Original sentence matched
|
|
81
|
+
- suggested_todo: Formatted todo text
|
|
82
|
+
- action: Extracted action text
|
|
83
|
+
"""
|
|
84
|
+
detections = []
|
|
85
|
+
|
|
86
|
+
# Split into sentences for better pattern matching
|
|
87
|
+
# Split on period followed by space/newline, or just newline
|
|
88
|
+
# This avoids splitting on periods in filenames like .env.local
|
|
89
|
+
sentences = re.split(r"(?:\.\s+|\n+)", text)
|
|
90
|
+
|
|
91
|
+
for sentence in sentences:
|
|
92
|
+
sentence = sentence.strip()
|
|
93
|
+
if not sentence:
|
|
94
|
+
continue
|
|
95
|
+
|
|
96
|
+
# Try each pattern
|
|
97
|
+
for pattern, todo_template in USER_DELEGATION_PATTERNS:
|
|
98
|
+
match = re.search(pattern, sentence, re.IGNORECASE)
|
|
99
|
+
if match:
|
|
100
|
+
# Extract the captured action
|
|
101
|
+
action = match.group(1).strip()
|
|
102
|
+
|
|
103
|
+
# Skip if action is too short (likely false positive)
|
|
104
|
+
if len(action) < 5:
|
|
105
|
+
continue
|
|
106
|
+
|
|
107
|
+
# Format todo using template
|
|
108
|
+
suggested_todo = todo_template.format(match=action)
|
|
109
|
+
|
|
110
|
+
# Determine pattern type from template prefix
|
|
111
|
+
pattern_type = todo_template.split(":")[0]
|
|
112
|
+
|
|
113
|
+
detection = {
|
|
114
|
+
"pattern_type": pattern_type,
|
|
115
|
+
"original_text": sentence.strip(),
|
|
116
|
+
"suggested_todo": suggested_todo,
|
|
117
|
+
"action": action,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
detections.append(detection)
|
|
121
|
+
self.logger.debug(
|
|
122
|
+
f"Detected delegation pattern: {pattern_type} - {action}"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Only match first pattern per sentence
|
|
126
|
+
break
|
|
127
|
+
|
|
128
|
+
return detections
|
|
129
|
+
|
|
130
|
+
def format_as_autotodo(self, detection: Dict[str, Any]) -> Dict[str, str]:
|
|
131
|
+
"""Format a detection as an autotodo.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
detection: Detection dict from detect_user_delegation
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Dictionary with todo fields (content, activeForm, status)
|
|
138
|
+
"""
|
|
139
|
+
pattern_type = detection["pattern_type"]
|
|
140
|
+
suggested_todo = detection["suggested_todo"]
|
|
141
|
+
action = detection["action"]
|
|
142
|
+
|
|
143
|
+
# Create todo content
|
|
144
|
+
content = f"[Delegation] {suggested_todo}"
|
|
145
|
+
|
|
146
|
+
# Active form for in-progress display
|
|
147
|
+
active_form = f"Delegating: {action[:30]}..."
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
"content": content,
|
|
151
|
+
"activeForm": active_form,
|
|
152
|
+
"status": "pending",
|
|
153
|
+
"metadata": {
|
|
154
|
+
"pattern_type": pattern_type,
|
|
155
|
+
"original_text": detection["original_text"],
|
|
156
|
+
"action": action,
|
|
157
|
+
"source": "delegation_detector",
|
|
158
|
+
},
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
# Global instance
|
|
163
|
+
_delegation_detector: DelegationDetector | None = None
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def get_delegation_detector() -> DelegationDetector:
|
|
167
|
+
"""Get the global delegation detector instance.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
DelegationDetector instance
|
|
171
|
+
"""
|
|
172
|
+
global _delegation_detector
|
|
173
|
+
if _delegation_detector is None:
|
|
174
|
+
_delegation_detector = DelegationDetector()
|
|
175
|
+
return _delegation_detector
|
|
@@ -69,6 +69,13 @@ class AgentSourcesCheck(BaseDiagnosticCheck):
|
|
|
69
69
|
fix_command="claude-mpm agent-source add https://github.com/bobmatnyc/claude-mpm-agents",
|
|
70
70
|
fix_description="Add default system repository",
|
|
71
71
|
sub_results=sub_results if self.verbose else [],
|
|
72
|
+
explanation=(
|
|
73
|
+
"Agent sources define where Claude MPM discovers specialized agents. "
|
|
74
|
+
"Without configured sources, no agents can be deployed or delegated to. "
|
|
75
|
+
"This is a critical component for multi-agent workflows."
|
|
76
|
+
),
|
|
77
|
+
severity="critical",
|
|
78
|
+
doc_link="https://github.com/bobmatnyc/claude-mpm/blob/main/docs/guides/agent-sources.md",
|
|
72
79
|
)
|
|
73
80
|
|
|
74
81
|
# Check 2: Configuration is valid YAML
|
|
@@ -141,16 +148,30 @@ class AgentSourcesCheck(BaseDiagnosticCheck):
|
|
|
141
148
|
r for r in sub_results if r.status == ValidationSeverity.WARNING
|
|
142
149
|
]
|
|
143
150
|
|
|
151
|
+
# Determine status and enhanced troubleshooting info (issue #125)
|
|
144
152
|
if error_results:
|
|
145
153
|
status = ValidationSeverity.ERROR
|
|
146
154
|
message = f"Agent sources have {len(error_results)} critical issue(s)"
|
|
147
155
|
fix_command = None
|
|
148
156
|
fix_description = None
|
|
157
|
+
severity = "critical"
|
|
158
|
+
explanation = (
|
|
159
|
+
"Agent sources are the foundation of Claude MPM's delegation system. "
|
|
160
|
+
"Critical errors prevent agent discovery and deployment, blocking "
|
|
161
|
+
"multi-agent workflows entirely."
|
|
162
|
+
)
|
|
163
|
+
doc_link = "https://github.com/bobmatnyc/claude-mpm/blob/main/docs/guides/agent-sources.md"
|
|
149
164
|
elif warning_results:
|
|
150
165
|
status = ValidationSeverity.WARNING
|
|
151
166
|
message = f"Agent sources have {len(warning_results)} minor issue(s)"
|
|
152
167
|
fix_command = "claude-mpm agent-source update"
|
|
153
168
|
fix_description = "Update all sources to refresh cache"
|
|
169
|
+
severity = "medium"
|
|
170
|
+
explanation = (
|
|
171
|
+
"Some agent sources have issues but the system can still function. "
|
|
172
|
+
"You may have limited agent availability or outdated cache."
|
|
173
|
+
)
|
|
174
|
+
doc_link = "https://github.com/bobmatnyc/claude-mpm/blob/main/docs/guides/agent-sources.md"
|
|
154
175
|
else:
|
|
155
176
|
status = OperationResult.SUCCESS
|
|
156
177
|
enabled_count = details["enabled_sources"]
|
|
@@ -158,6 +179,12 @@ class AgentSourcesCheck(BaseDiagnosticCheck):
|
|
|
158
179
|
message = f"All checks passed ({enabled_count} source(s), {agents_count} agent(s))"
|
|
159
180
|
fix_command = None
|
|
160
181
|
fix_description = None
|
|
182
|
+
severity = "info"
|
|
183
|
+
explanation = (
|
|
184
|
+
"Agent sources are properly configured and agents are discoverable. "
|
|
185
|
+
"You can delegate tasks to specialized agents."
|
|
186
|
+
)
|
|
187
|
+
doc_link = ""
|
|
161
188
|
|
|
162
189
|
return DiagnosticResult(
|
|
163
190
|
category=self.category,
|
|
@@ -167,6 +194,9 @@ class AgentSourcesCheck(BaseDiagnosticCheck):
|
|
|
167
194
|
fix_command=fix_command,
|
|
168
195
|
fix_description=fix_description,
|
|
169
196
|
sub_results=sub_results if self.verbose else [],
|
|
197
|
+
explanation=explanation,
|
|
198
|
+
severity=severity,
|
|
199
|
+
doc_link=doc_link,
|
|
170
200
|
)
|
|
171
201
|
|
|
172
202
|
except Exception as e:
|
|
@@ -63,12 +63,36 @@ class ConfigurationCheck(BaseDiagnosticCheck):
|
|
|
63
63
|
status = OperationResult.SUCCESS
|
|
64
64
|
message = "Configuration is valid"
|
|
65
65
|
|
|
66
|
+
# Add enhanced troubleshooting info (issue #125)
|
|
67
|
+
severity = "medium"
|
|
68
|
+
explanation = ""
|
|
69
|
+
doc_link = ""
|
|
70
|
+
|
|
71
|
+
if status == ValidationSeverity.ERROR:
|
|
72
|
+
severity = "high"
|
|
73
|
+
explanation = (
|
|
74
|
+
"Configuration files control how Claude MPM behaves. Critical errors "
|
|
75
|
+
"in configuration may prevent features from working correctly or cause "
|
|
76
|
+
"unexpected behavior."
|
|
77
|
+
)
|
|
78
|
+
doc_link = "https://github.com/bobmatnyc/claude-mpm/blob/main/docs/configuration.md"
|
|
79
|
+
elif status == ValidationSeverity.WARNING:
|
|
80
|
+
severity = "low"
|
|
81
|
+
explanation = (
|
|
82
|
+
"Configuration has minor issues that may affect optional features. "
|
|
83
|
+
"Core functionality should still work."
|
|
84
|
+
)
|
|
85
|
+
doc_link = "https://github.com/bobmatnyc/claude-mpm/blob/main/docs/configuration.md"
|
|
86
|
+
|
|
66
87
|
return DiagnosticResult(
|
|
67
88
|
category=self.category,
|
|
68
89
|
status=status,
|
|
69
90
|
message=message,
|
|
70
91
|
details=details,
|
|
71
92
|
sub_results=sub_results if self.verbose else [],
|
|
93
|
+
explanation=explanation,
|
|
94
|
+
severity=severity,
|
|
95
|
+
doc_link=doc_link,
|
|
72
96
|
)
|
|
73
97
|
|
|
74
98
|
except Exception as e:
|
|
@@ -65,12 +65,34 @@ class InstallationCheck(BaseDiagnosticCheck):
|
|
|
65
65
|
status = OperationResult.SUCCESS
|
|
66
66
|
message = "Installation is healthy"
|
|
67
67
|
|
|
68
|
+
# Determine severity and explanation based on status (issue #125)
|
|
69
|
+
severity = "medium"
|
|
70
|
+
explanation = ""
|
|
71
|
+
doc_link = ""
|
|
72
|
+
|
|
73
|
+
if status == ValidationSeverity.ERROR:
|
|
74
|
+
severity = "high"
|
|
75
|
+
explanation = (
|
|
76
|
+
"Claude MPM installation verification failed. Critical components are missing "
|
|
77
|
+
"or misconfigured, which will prevent the system from functioning properly."
|
|
78
|
+
)
|
|
79
|
+
doc_link = "https://github.com/bobmatnyc/claude-mpm/blob/main/docs/installation.md"
|
|
80
|
+
elif status == ValidationSeverity.WARNING:
|
|
81
|
+
severity = "medium"
|
|
82
|
+
explanation = (
|
|
83
|
+
"Installation is functional but has minor issues. These may affect "
|
|
84
|
+
"performance or features but won't prevent basic operation."
|
|
85
|
+
)
|
|
86
|
+
|
|
68
87
|
return DiagnosticResult(
|
|
69
88
|
category=self.category,
|
|
70
89
|
status=status,
|
|
71
90
|
message=message,
|
|
72
91
|
details=details,
|
|
73
92
|
sub_results=sub_results if self.verbose else [],
|
|
93
|
+
explanation=explanation,
|
|
94
|
+
severity=severity,
|
|
95
|
+
doc_link=doc_link,
|
|
74
96
|
)
|
|
75
97
|
|
|
76
98
|
except Exception as e:
|
|
@@ -216,12 +216,35 @@ class MCPServicesCheck(BaseDiagnosticCheck):
|
|
|
216
216
|
status = ValidationSeverity.WARNING
|
|
217
217
|
message = f"All {total_services} MCP services installed but connections not tested"
|
|
218
218
|
|
|
219
|
+
# Enhanced troubleshooting info (issue #125)
|
|
220
|
+
severity = "medium"
|
|
221
|
+
explanation = ""
|
|
222
|
+
doc_link = ""
|
|
223
|
+
|
|
224
|
+
if status == ValidationSeverity.ERROR:
|
|
225
|
+
severity = "high"
|
|
226
|
+
explanation = (
|
|
227
|
+
"MCP services provide enhanced capabilities like vector search, browser automation, "
|
|
228
|
+
"and ticket management. Critical errors prevent these services from functioning."
|
|
229
|
+
)
|
|
230
|
+
doc_link = "https://github.com/bobmatnyc/claude-mpm/blob/main/docs/mcp-services.md"
|
|
231
|
+
elif status == ValidationSeverity.WARNING:
|
|
232
|
+
severity = "low"
|
|
233
|
+
explanation = (
|
|
234
|
+
"MCP services are optional but provide powerful features. "
|
|
235
|
+
"Some services may not be installed or configured properly."
|
|
236
|
+
)
|
|
237
|
+
doc_link = "https://github.com/bobmatnyc/claude-mpm/blob/main/docs/mcp-services.md"
|
|
238
|
+
|
|
219
239
|
return DiagnosticResult(
|
|
220
240
|
category=self.category,
|
|
221
241
|
status=status,
|
|
222
242
|
message=message,
|
|
223
243
|
details=details,
|
|
224
244
|
sub_results=sub_results if self.verbose else [],
|
|
245
|
+
explanation=explanation,
|
|
246
|
+
severity=severity,
|
|
247
|
+
doc_link=doc_link,
|
|
225
248
|
)
|
|
226
249
|
|
|
227
250
|
except Exception as e:
|
|
@@ -28,6 +28,15 @@ class DoctorReporter:
|
|
|
28
28
|
OperationResult.SKIPPED: "⏭️ ",
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
# Severity level emojis (issue #125)
|
|
32
|
+
SEVERITY_SYMBOLS = {
|
|
33
|
+
"critical": "🔴",
|
|
34
|
+
"high": "🟠",
|
|
35
|
+
"medium": "🟡",
|
|
36
|
+
"low": "🟢",
|
|
37
|
+
"info": "🔵",
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
# ANSI color codes
|
|
32
41
|
COLORS = {
|
|
33
42
|
"reset": "\033[0m",
|
|
@@ -93,8 +102,15 @@ class DoctorReporter:
|
|
|
93
102
|
symbol = self.STATUS_SYMBOLS.get(result.status, "?")
|
|
94
103
|
color = self._get_status_color(result.status)
|
|
95
104
|
|
|
105
|
+
# Add severity indicator if present (issue #125)
|
|
106
|
+
severity_prefix = ""
|
|
107
|
+
if result.severity and result.severity != "medium":
|
|
108
|
+
severity_symbol = self.SEVERITY_SYMBOLS.get(result.severity, "")
|
|
109
|
+
if severity_symbol:
|
|
110
|
+
severity_prefix = f"{severity_symbol} {result.severity.upper()}: "
|
|
111
|
+
|
|
96
112
|
# Main result line
|
|
97
|
-
line = f"{indent_str}{symbol} {result.category}: "
|
|
113
|
+
line = f"{indent_str}{severity_prefix}{symbol} {result.category}: "
|
|
98
114
|
|
|
99
115
|
if result.status == OperationResult.SUCCESS:
|
|
100
116
|
line += self._color("OK", color)
|
|
@@ -111,6 +127,15 @@ class DoctorReporter:
|
|
|
111
127
|
message_indent = " " + indent_str
|
|
112
128
|
print(f"{message_indent}{result.message}")
|
|
113
129
|
|
|
130
|
+
# Explanation (issue #125)
|
|
131
|
+
if result.explanation:
|
|
132
|
+
# Format multi-line explanations with proper indentation
|
|
133
|
+
explanation_lines = result.explanation.split("\n")
|
|
134
|
+
for explanation_line in explanation_lines:
|
|
135
|
+
print(
|
|
136
|
+
f"{message_indent}{self._color(explanation_line.strip(), 'gray')}"
|
|
137
|
+
)
|
|
138
|
+
|
|
114
139
|
# Details (in verbose mode)
|
|
115
140
|
if self.verbose and result.details:
|
|
116
141
|
for key, value in result.details.items():
|
|
@@ -126,6 +151,11 @@ class DoctorReporter:
|
|
|
126
151
|
if result.fix_description:
|
|
127
152
|
print(f"{fix_indent} {self._color(result.fix_description, 'gray')}")
|
|
128
153
|
|
|
154
|
+
# Documentation link (issue #125)
|
|
155
|
+
if result.doc_link:
|
|
156
|
+
doc_indent = " " + indent_str
|
|
157
|
+
print(f"{doc_indent}{self._color('📖 Docs:', 'blue')} {result.doc_link}")
|
|
158
|
+
|
|
129
159
|
# Sub-results (in verbose mode)
|
|
130
160
|
if self.verbose and result.sub_results:
|
|
131
161
|
for sub_result in result.sub_results:
|
|
@@ -51,9 +51,14 @@ class DiagnosticResult:
|
|
|
51
51
|
fix_description: Optional[str] = None
|
|
52
52
|
sub_results: List["DiagnosticResult"] = field(default_factory=list)
|
|
53
53
|
|
|
54
|
+
# Enhanced troubleshooting fields (issue #125)
|
|
55
|
+
explanation: str = "" # What this check means and why it matters
|
|
56
|
+
severity: str = "medium" # critical, high, medium, low, info
|
|
57
|
+
doc_link: str = "" # Link to relevant documentation
|
|
58
|
+
|
|
54
59
|
def to_dict(self) -> Dict[str, Any]:
|
|
55
60
|
"""Convert to dictionary for JSON serialization."""
|
|
56
|
-
|
|
61
|
+
result = {
|
|
57
62
|
"category": self.category,
|
|
58
63
|
"status": self.status.value,
|
|
59
64
|
"message": self.message,
|
|
@@ -62,6 +67,14 @@ class DiagnosticResult:
|
|
|
62
67
|
"fix_description": self.fix_description,
|
|
63
68
|
"sub_results": [r.to_dict() for r in self.sub_results],
|
|
64
69
|
}
|
|
70
|
+
# Include enhanced fields if present
|
|
71
|
+
if self.explanation:
|
|
72
|
+
result["explanation"] = self.explanation
|
|
73
|
+
if self.severity != "medium":
|
|
74
|
+
result["severity"] = self.severity
|
|
75
|
+
if self.doc_link:
|
|
76
|
+
result["doc_link"] = self.doc_link
|
|
77
|
+
return result
|
|
65
78
|
|
|
66
79
|
@property
|
|
67
80
|
def has_issues(self) -> bool:
|