claude-mpm 5.4.96__py3-none-any.whl → 5.6.10__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.

Files changed (191) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/{CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md → CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md} +14 -6
  3. claude_mpm/agents/PM_INSTRUCTIONS.md +44 -10
  4. claude_mpm/agents/WORKFLOW.md +2 -0
  5. claude_mpm/agents/templates/circuit-breakers.md +26 -17
  6. claude_mpm/cli/commands/autotodos.py +45 -5
  7. claude_mpm/cli/commands/commander.py +46 -0
  8. claude_mpm/cli/commands/hook_errors.py +60 -60
  9. claude_mpm/cli/commands/run.py +35 -3
  10. claude_mpm/cli/commands/skill_source.py +51 -2
  11. claude_mpm/cli/commands/skills.py +5 -3
  12. claude_mpm/cli/executor.py +32 -17
  13. claude_mpm/cli/parsers/base_parser.py +17 -0
  14. claude_mpm/cli/parsers/commander_parser.py +83 -0
  15. claude_mpm/cli/parsers/run_parser.py +10 -0
  16. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  17. claude_mpm/cli/parsers/skills_parser.py +5 -0
  18. claude_mpm/cli/startup.py +20 -2
  19. claude_mpm/cli/utils.py +7 -3
  20. claude_mpm/commander/__init__.py +72 -0
  21. claude_mpm/commander/adapters/__init__.py +31 -0
  22. claude_mpm/commander/adapters/base.py +191 -0
  23. claude_mpm/commander/adapters/claude_code.py +361 -0
  24. claude_mpm/commander/adapters/communication.py +366 -0
  25. claude_mpm/commander/api/__init__.py +16 -0
  26. claude_mpm/commander/api/app.py +105 -0
  27. claude_mpm/commander/api/errors.py +133 -0
  28. claude_mpm/commander/api/routes/__init__.py +8 -0
  29. claude_mpm/commander/api/routes/events.py +184 -0
  30. claude_mpm/commander/api/routes/inbox.py +171 -0
  31. claude_mpm/commander/api/routes/messages.py +148 -0
  32. claude_mpm/commander/api/routes/projects.py +271 -0
  33. claude_mpm/commander/api/routes/sessions.py +228 -0
  34. claude_mpm/commander/api/routes/work.py +260 -0
  35. claude_mpm/commander/api/schemas.py +182 -0
  36. claude_mpm/commander/chat/__init__.py +7 -0
  37. claude_mpm/commander/chat/cli.py +107 -0
  38. claude_mpm/commander/chat/commands.py +96 -0
  39. claude_mpm/commander/chat/repl.py +310 -0
  40. claude_mpm/commander/config.py +49 -0
  41. claude_mpm/commander/config_loader.py +115 -0
  42. claude_mpm/commander/daemon.py +398 -0
  43. claude_mpm/commander/events/__init__.py +26 -0
  44. claude_mpm/commander/events/manager.py +332 -0
  45. claude_mpm/commander/frameworks/__init__.py +12 -0
  46. claude_mpm/commander/frameworks/base.py +143 -0
  47. claude_mpm/commander/frameworks/claude_code.py +58 -0
  48. claude_mpm/commander/frameworks/mpm.py +62 -0
  49. claude_mpm/commander/inbox/__init__.py +16 -0
  50. claude_mpm/commander/inbox/dedup.py +128 -0
  51. claude_mpm/commander/inbox/inbox.py +224 -0
  52. claude_mpm/commander/inbox/models.py +70 -0
  53. claude_mpm/commander/instance_manager.py +337 -0
  54. claude_mpm/commander/llm/__init__.py +6 -0
  55. claude_mpm/commander/llm/openrouter_client.py +167 -0
  56. claude_mpm/commander/llm/summarizer.py +70 -0
  57. claude_mpm/commander/models/__init__.py +18 -0
  58. claude_mpm/commander/models/events.py +121 -0
  59. claude_mpm/commander/models/project.py +162 -0
  60. claude_mpm/commander/models/work.py +214 -0
  61. claude_mpm/commander/parsing/__init__.py +20 -0
  62. claude_mpm/commander/parsing/extractor.py +132 -0
  63. claude_mpm/commander/parsing/output_parser.py +270 -0
  64. claude_mpm/commander/parsing/patterns.py +100 -0
  65. claude_mpm/commander/persistence/__init__.py +11 -0
  66. claude_mpm/commander/persistence/event_store.py +274 -0
  67. claude_mpm/commander/persistence/state_store.py +309 -0
  68. claude_mpm/commander/persistence/work_store.py +164 -0
  69. claude_mpm/commander/polling/__init__.py +13 -0
  70. claude_mpm/commander/polling/event_detector.py +104 -0
  71. claude_mpm/commander/polling/output_buffer.py +49 -0
  72. claude_mpm/commander/polling/output_poller.py +153 -0
  73. claude_mpm/commander/project_session.py +268 -0
  74. claude_mpm/commander/proxy/__init__.py +12 -0
  75. claude_mpm/commander/proxy/formatter.py +89 -0
  76. claude_mpm/commander/proxy/output_handler.py +191 -0
  77. claude_mpm/commander/proxy/relay.py +155 -0
  78. claude_mpm/commander/registry.py +404 -0
  79. claude_mpm/commander/runtime/__init__.py +10 -0
  80. claude_mpm/commander/runtime/executor.py +191 -0
  81. claude_mpm/commander/runtime/monitor.py +316 -0
  82. claude_mpm/commander/session/__init__.py +6 -0
  83. claude_mpm/commander/session/context.py +81 -0
  84. claude_mpm/commander/session/manager.py +59 -0
  85. claude_mpm/commander/tmux_orchestrator.py +361 -0
  86. claude_mpm/commander/web/__init__.py +1 -0
  87. claude_mpm/commander/work/__init__.py +30 -0
  88. claude_mpm/commander/work/executor.py +189 -0
  89. claude_mpm/commander/work/queue.py +405 -0
  90. claude_mpm/commander/workflow/__init__.py +27 -0
  91. claude_mpm/commander/workflow/event_handler.py +219 -0
  92. claude_mpm/commander/workflow/notifier.py +146 -0
  93. claude_mpm/commands/mpm-config.md +8 -0
  94. claude_mpm/commands/mpm-doctor.md +8 -0
  95. claude_mpm/commands/mpm-help.md +8 -0
  96. claude_mpm/commands/mpm-init.md +8 -0
  97. claude_mpm/commands/mpm-monitor.md +8 -0
  98. claude_mpm/commands/mpm-organize.md +8 -0
  99. claude_mpm/commands/mpm-postmortem.md +8 -0
  100. claude_mpm/commands/mpm-session-resume.md +8 -0
  101. claude_mpm/commands/mpm-status.md +8 -0
  102. claude_mpm/commands/mpm-ticket-view.md +8 -0
  103. claude_mpm/commands/mpm-version.md +8 -0
  104. claude_mpm/commands/mpm.md +8 -0
  105. claude_mpm/config/agent_presets.py +8 -7
  106. claude_mpm/config/skill_sources.py +16 -0
  107. claude_mpm/core/config.py +32 -19
  108. claude_mpm/core/logger.py +26 -9
  109. claude_mpm/core/logging_utils.py +35 -11
  110. claude_mpm/core/output_style_manager.py +15 -5
  111. claude_mpm/core/unified_config.py +10 -6
  112. claude_mpm/core/unified_paths.py +68 -80
  113. claude_mpm/experimental/cli_enhancements.py +2 -1
  114. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.pyc +0 -0
  115. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  116. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  117. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-312.pyc +0 -0
  118. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-314.pyc +0 -0
  119. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  120. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-312.pyc +0 -0
  121. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-314.pyc +0 -0
  122. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  123. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.pyc +0 -0
  124. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-314.pyc +0 -0
  125. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  126. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-314.pyc +0 -0
  127. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  128. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-312.pyc +0 -0
  129. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-314.pyc +0 -0
  130. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  131. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc +0 -0
  132. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-314.pyc +0 -0
  133. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-312.pyc +0 -0
  134. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-314.pyc +0 -0
  135. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +29 -30
  136. claude_mpm/hooks/claude_hooks/event_handlers.py +90 -99
  137. claude_mpm/hooks/claude_hooks/hook_handler.py +81 -88
  138. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  139. claude_mpm/hooks/claude_hooks/installer.py +116 -8
  140. claude_mpm/hooks/claude_hooks/memory_integration.py +51 -31
  141. claude_mpm/hooks/claude_hooks/response_tracking.py +39 -58
  142. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-312.pyc +0 -0
  143. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-314.pyc +0 -0
  144. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  145. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-312.pyc +0 -0
  146. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-314.pyc +0 -0
  147. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-312.pyc +0 -0
  148. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-314.pyc +0 -0
  149. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  150. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc +0 -0
  151. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-314.pyc +0 -0
  152. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  153. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
  154. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-314.pyc +0 -0
  155. claude_mpm/hooks/claude_hooks/services/connection_manager.py +23 -28
  156. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +36 -103
  157. claude_mpm/hooks/claude_hooks/services/state_manager.py +23 -36
  158. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +47 -73
  159. claude_mpm/hooks/session_resume_hook.py +22 -18
  160. claude_mpm/hooks/templates/pre_tool_use_template.py +10 -2
  161. claude_mpm/scripts/claude-hook-handler.sh +43 -16
  162. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  163. claude_mpm/services/agents/agent_selection_service.py +2 -2
  164. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  165. claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
  166. claude_mpm/services/event_log.py +8 -0
  167. claude_mpm/services/pm_skills_deployer.py +84 -6
  168. claude_mpm/services/skills/git_skill_source_manager.py +130 -10
  169. claude_mpm/services/skills/selective_skill_deployer.py +28 -0
  170. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  171. claude_mpm/services/skills_deployer.py +31 -5
  172. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  173. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  174. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  175. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  176. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  177. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  178. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  179. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  180. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  181. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  182. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  183. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  184. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/METADATA +18 -4
  185. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/RECORD +190 -79
  186. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  187. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/WHEEL +0 -0
  188. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/entry_points.txt +0 -0
  189. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/licenses/LICENSE +0 -0
  190. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  191. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,146 @@
1
+ """Basic notification delivery for events.
2
+
3
+ This module provides Notifier which sends notifications for events.
4
+ Currently supports logging, with extensibility for future channels
5
+ (Slack, email, webhooks).
6
+ """
7
+
8
+ import logging
9
+ from dataclasses import dataclass
10
+
11
+ from ..models.events import Event
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ @dataclass
17
+ class NotifierConfig:
18
+ """Configuration for notifier.
19
+
20
+ Attributes:
21
+ log_level: Logging level for notifications (default: INFO)
22
+
23
+ Future attributes:
24
+ slack_webhook: URL for Slack webhook notifications
25
+ email_config: SMTP configuration for email notifications
26
+ webhook_urls: List of webhook URLs for custom integrations
27
+ """
28
+
29
+ log_level: str = "INFO"
30
+ # Future: slack_webhook, email_config, webhook_urls
31
+
32
+
33
+ class Notifier:
34
+ """Sends notifications for events.
35
+
36
+ Currently implements logging-based notifications with configurable
37
+ log levels. Designed for extensibility to support future notification
38
+ channels like Slack, email, and webhooks.
39
+
40
+ Attributes:
41
+ config: Notifier configuration
42
+
43
+ Example:
44
+ >>> config = NotifierConfig(log_level="INFO")
45
+ >>> notifier = Notifier(config)
46
+ >>> await notifier.notify(event)
47
+ >>> await notifier.notify_resolution(event, "User responded")
48
+ """
49
+
50
+ def __init__(self, config: NotifierConfig | None = None) -> None:
51
+ """Initialize notifier.
52
+
53
+ Args:
54
+ config: Optional NotifierConfig (uses defaults if not provided)
55
+ """
56
+ self.config = config or NotifierConfig()
57
+
58
+ # Map log level string to logging level
59
+ level_map = {
60
+ "DEBUG": logging.DEBUG,
61
+ "INFO": logging.INFO,
62
+ "WARNING": logging.WARNING,
63
+ "ERROR": logging.ERROR,
64
+ "CRITICAL": logging.CRITICAL,
65
+ }
66
+ self._log_level = level_map.get(self.config.log_level.upper(), logging.INFO)
67
+
68
+ logger.debug("Notifier initialized with log level: %s", self.config.log_level)
69
+
70
+ async def notify(self, event: Event) -> None:
71
+ """Send notification for an event.
72
+
73
+ Currently logs the event at the configured log level. Future versions
74
+ will support additional notification channels.
75
+
76
+ Args:
77
+ event: Event to notify about
78
+
79
+ Example:
80
+ >>> await notifier.notify(event)
81
+ # Logs: [HIGH] Event evt_123: Choose deployment target
82
+ """
83
+ # Format notification message
84
+ message = self._format_event(event)
85
+
86
+ # Log notification
87
+ logger.log(
88
+ self._log_level,
89
+ "Event notification: %s",
90
+ message,
91
+ )
92
+
93
+ # Future: Send to Slack, email, webhooks
94
+ # if self.config.slack_webhook:
95
+ # await self._send_slack(event)
96
+ # if self.config.email_config:
97
+ # await self._send_email(event)
98
+
99
+ async def notify_resolution(self, event: Event, response: str) -> None:
100
+ """Notify that an event was resolved.
101
+
102
+ Logs the resolution with the user's response. Future versions will
103
+ send resolution notifications to configured channels.
104
+
105
+ Args:
106
+ event: Event that was resolved
107
+ response: User's response to the event
108
+
109
+ Example:
110
+ >>> await notifier.notify_resolution(event, "Deploy to staging")
111
+ # Logs: Event evt_123 resolved: Deploy to staging
112
+ """
113
+ message = f"Event {event.id} resolved: {response[:100]}"
114
+
115
+ logger.log(
116
+ self._log_level,
117
+ "Event resolution: %s",
118
+ message,
119
+ )
120
+
121
+ # Future: Send resolution notifications to channels
122
+
123
+ def _format_event(self, event: Event) -> str:
124
+ """Format event for notification display.
125
+
126
+ Args:
127
+ event: Event to format
128
+
129
+ Returns:
130
+ Formatted notification string
131
+
132
+ Example:
133
+ >>> msg = notifier._format_event(event)
134
+ '[HIGH] evt_123 (proj_456): Choose deployment target'
135
+ """
136
+ parts = [
137
+ f"[{event.priority.value.upper()}]",
138
+ f"{event.id}",
139
+ f"({event.project_id})",
140
+ f"{event.title}",
141
+ ]
142
+
143
+ if event.options:
144
+ parts.append(f"Options: {', '.join(event.options)}")
145
+
146
+ return " ".join(parts)
@@ -5,7 +5,15 @@ aliases: [mpm-config]
5
5
  migration_target: /mpm/config
6
6
  category: config
7
7
  description: Manage Claude MPM configuration
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-config"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-config` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-config` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-config
10
18
 
11
19
  Unified configuration management with auto-detection.
@@ -5,7 +5,15 @@ aliases: [mpm-doctor]
5
5
  migration_target: /mpm/system:doctor
6
6
  category: system
7
7
  description: Run diagnostic checks on Claude MPM installation
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-doctor"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-doctor` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-doctor` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-doctor
10
18
 
11
19
  Run comprehensive diagnostics on Claude MPM installation.
@@ -5,7 +5,15 @@ aliases: [mpm-help]
5
5
  migration_target: /mpm/system:help
6
6
  category: system
7
7
  description: Display help for Claude MPM commands
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-help"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-help` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-help` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-help
10
18
 
11
19
  Show help for MPM commands. Delegates to PM agent.
@@ -5,7 +5,15 @@ aliases: [mpm-init]
5
5
  migration_target: /mpm/system:init
6
6
  category: system
7
7
  description: Initialize or update project for Claude Code and MPM
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-init"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-init` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-init` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-init
10
18
 
11
19
  Initialize or intelligently update project for Claude Code and Claude MPM.
@@ -5,7 +5,15 @@ aliases: [mpm-monitor]
5
5
  migration_target: /mpm/system:monitor
6
6
  category: system
7
7
  description: Control monitoring server and dashboard
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-monitor"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-monitor` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-monitor` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-monitor
10
18
 
11
19
  Manage Socket.IO monitoring server for real-time dashboard.
@@ -5,7 +5,15 @@ aliases: [mpm-organize]
5
5
  migration_target: /mpm/system:organize
6
6
  category: system
7
7
  description: Organize project files with intelligent consolidation
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-organize"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-organize` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-organize` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-organize
10
18
 
11
19
  Organize ALL project files with intelligent detection, consolidation, and pruning.
@@ -5,7 +5,15 @@ aliases: [mpm-postmortem]
5
5
  migration_target: /mpm/analysis:postmortem
6
6
  category: analysis
7
7
  description: Analyze session errors and suggest improvements
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-postmortem"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-postmortem` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-postmortem` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-postmortem
10
18
 
11
19
  Analyze session errors and generate improvement suggestions.
@@ -5,7 +5,15 @@ aliases: [mpm-session-resume]
5
5
  migration_target: /mpm/session:resume
6
6
  category: session
7
7
  description: Load context from paused session
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-session-resume"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-session-resume` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-session-resume` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-session-resume
10
18
 
11
19
  Load and display context from most recent paused session.
@@ -5,7 +5,15 @@ aliases: [mpm-status]
5
5
  migration_target: /mpm/system:status
6
6
  category: system
7
7
  description: Display Claude MPM system status
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-status"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-status` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-status` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-status
10
18
 
11
19
  Show MPM system status. Delegates to PM agent.
@@ -5,7 +5,15 @@ aliases: [mpm-ticket-view]
5
5
  migration_target: /mpm/ticket:view
6
6
  category: tickets
7
7
  description: Orchestrate ticketing agent for project management workflows
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-ticket-view"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-ticket-view` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-ticket-view` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-ticket
10
18
 
11
19
  High-level ticketing workflows delegating to ticketing agent.
@@ -5,7 +5,15 @@ aliases: [mpm-version]
5
5
  migration_target: /mpm/system:version
6
6
  category: system
7
7
  description: Show version information
8
+ deprecated: true
9
+ deprecated_in: "5.5.0"
10
+ replacement: "skill:mpm-version"
8
11
  ---
12
+
13
+ > **Deprecated:** This command file is deprecated in favor of the `mpm-version` skill.
14
+ > For Claude Code 2.1.3+, use the skill-based `/mpm-version` command instead.
15
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
16
+
9
17
  # /mpm-version
10
18
 
11
19
  Display version information for MPM, agents, and skills.
@@ -6,7 +6,15 @@ migration_target: /mpm
6
6
  category: system
7
7
  deprecated_aliases: []
8
8
  description: Access Claude MPM functionality and manage multi-agent orchestration
9
+ deprecated: true
10
+ deprecated_in: "5.5.0"
11
+ replacement: "skill:mpm"
9
12
  ---
13
+
14
+ > **Deprecated:** This command file is deprecated in favor of the `mpm` skill.
15
+ > For Claude Code 2.1.3+, use the skill-based `/mpm` command instead.
16
+ > This file is kept for backward compatibility with Claude Code < 2.1.3.
17
+
10
18
  # Claude MPM - Multi-Agent Project Manager
11
19
 
12
20
  Access Claude MPM functionality and manage your multi-agent orchestration.
@@ -25,12 +25,17 @@ from typing import Any, Callable, Dict, List, Union
25
25
  PresetResolver = Union[List[str], Callable[[], List[str]]]
26
26
 
27
27
  # Core agents included in ALL presets (MIN and MAX)
28
+ # Standard 9 core agents for essential PM workflow functionality
28
29
  CORE_AGENTS = [
29
30
  "claude-mpm/mpm-agent-manager", # Agent lifecycle management
30
31
  "claude-mpm/mpm-skills-manager", # Skills management
31
- "universal/research", # Codebase investigation
32
+ "engineer/core/engineer", # General-purpose implementation
33
+ "universal/research", # Codebase exploration and analysis
34
+ "qa/qa", # Testing and quality assurance
35
+ "qa/web-qa", # Browser-based testing specialist
32
36
  "documentation/documentation", # Documentation generation
33
- "engineer/core/engineer", # General-purpose engineering
37
+ "ops/core/ops", # Basic deployment operations
38
+ "documentation/ticketing", # Ticket tracking (essential for PM workflow)
34
39
  ]
35
40
 
36
41
  PRESETS: Dict[str, Dict[str, Any]] = {
@@ -39,11 +44,7 @@ PRESETS: Dict[str, Dict[str, Any]] = {
39
44
  # ========================================
40
45
  "minimal": {
41
46
  "description": "Core agents only - universal starter kit",
42
- "agents": CORE_AGENTS
43
- + [
44
- "qa/qa",
45
- "ops/core/ops",
46
- ],
47
+ "agents": CORE_AGENTS, # All 8 core agents (no additional needed)
47
48
  "use_cases": ["Any project type", "Quick start", "Learning"],
48
49
  },
49
50
  # ========================================
@@ -54,6 +54,7 @@ class SkillSource:
54
54
  branch: Git branch to use (default: "main")
55
55
  priority: Priority for skill resolution (lower = higher precedence)
56
56
  enabled: Whether this source should be synced
57
+ token: Optional GitHub token or env var reference (e.g., "$MY_TOKEN")
57
58
 
58
59
  Priority System:
59
60
  - 0: Reserved for system repository (highest precedence)
@@ -61,6 +62,12 @@ class SkillSource:
61
62
  - 100-999: Normal priority custom sources
62
63
  - 1000+: Low priority custom sources
63
64
 
65
+ Token Authentication:
66
+ - Direct token: "ghp_xxxxx" (stored in config, not recommended)
67
+ - Env var reference: "$PRIVATE_REPO_TOKEN" (resolved at runtime)
68
+ - If None, falls back to GITHUB_TOKEN or GH_TOKEN env vars
69
+ - Priority: source.token > GITHUB_TOKEN > GH_TOKEN
70
+
64
71
  Example:
65
72
  >>> source = SkillSource(
66
73
  ... id="system",
@@ -70,6 +77,12 @@ class SkillSource:
70
77
  ... )
71
78
  >>> source.validate()
72
79
  []
80
+ >>> private_source = SkillSource(
81
+ ... id="private",
82
+ ... type="git",
83
+ ... url="https://github.com/myorg/private-skills",
84
+ ... token="$PRIVATE_REPO_TOKEN"
85
+ ... )
73
86
  """
74
87
 
75
88
  id: str
@@ -78,6 +91,7 @@ class SkillSource:
78
91
  branch: str = "main"
79
92
  priority: int = 100
80
93
  enabled: bool = True
94
+ token: Optional[str] = None
81
95
 
82
96
  def __post_init__(self):
83
97
  """Validate skill source configuration after initialization.
@@ -262,6 +276,7 @@ class SkillSourceConfiguration:
262
276
  branch=source_data.get("branch", "main"),
263
277
  priority=source_data.get("priority", 100),
264
278
  enabled=source_data.get("enabled", True),
279
+ token=source_data.get("token"),
265
280
  )
266
281
  sources.append(source)
267
282
  except (KeyError, ValueError) as e:
@@ -326,6 +341,7 @@ class SkillSourceConfiguration:
326
341
  "branch": source.branch,
327
342
  "priority": source.priority,
328
343
  "enabled": source.enabled,
344
+ **({"token": source.token} if source.token else {}),
329
345
  }
330
346
  for source in sources
331
347
  ]
claude_mpm/core/config.py CHANGED
@@ -12,11 +12,10 @@ import threading
12
12
  from pathlib import Path
13
13
  from typing import Any, Dict, List, Optional, Tuple, Union
14
14
 
15
- import yaml
16
-
17
15
  from claude_mpm.core.logging_utils import get_logger
18
16
 
19
- from ..utils.config_manager import ConfigurationManager
17
+ # Lazy import ConfigurationManager to avoid importing yaml at module level
18
+ # This prevents hook errors when yaml isn't available in the execution environment
20
19
  from .exceptions import ConfigurationError, FileOperationError
21
20
  from .unified_paths import get_path_manager
22
21
 
@@ -104,6 +103,9 @@ class Config:
104
103
  Config._initialized = True
105
104
  logger.debug("Initializing Config singleton for the first time")
106
105
 
106
+ # Lazy import ConfigurationManager at runtime to avoid yaml import at module level
107
+ from ..utils.config_manager import ConfigurationManager
108
+
107
109
  # Initialize instance variables inside the lock to ensure thread safety
108
110
  self._config: Dict[str, Any] = {}
109
111
  self._env_prefix = env_prefix
@@ -224,21 +226,6 @@ class Config:
224
226
  f"Response logging format: {response_logging.get('format', 'json')}"
225
227
  )
226
228
 
227
- except yaml.YAMLError as e:
228
- logger.error(f"YAML syntax error in {file_path}: {e}")
229
- if hasattr(e, "problem_mark"):
230
- mark = e.problem_mark
231
- logger.error(f"Error at line {mark.line + 1}, column {mark.column + 1}")
232
- logger.info(
233
- "TIP: Validate your YAML at https://www.yamllint.com/ or run: python scripts/validate_configuration.py"
234
- )
235
- logger.info(
236
- "TIP: Common issue - YAML requires spaces, not tabs. Fix with: sed -i '' 's/\t/ /g' "
237
- + str(file_path)
238
- )
239
- # Store error for later retrieval
240
- self._config["_load_error"] = str(e)
241
-
242
229
  except json.JSONDecodeError as e:
243
230
  logger.error(f"JSON syntax error in {file_path}: {e}")
244
231
  logger.error(f"Error at line {e.lineno}, column {e.colno}")
@@ -255,7 +242,28 @@ class Config:
255
242
  },
256
243
  ) from e
257
244
  except Exception as e:
258
- # Catch any remaining unexpected errors and wrap them as configuration errors
245
+ # Handle YAML errors without importing yaml at module level
246
+ # ConfigurationManager.load_yaml raises yaml.YAMLError, but we don't want to import yaml
247
+ # Check if it's a YAML error by class name to avoid import
248
+ if e.__class__.__name__ == "YAMLError":
249
+ logger.error(f"YAML syntax error in {file_path}: {e}")
250
+ if hasattr(e, "problem_mark"):
251
+ mark = e.problem_mark
252
+ logger.error(
253
+ f"Error at line {mark.line + 1}, column {mark.column + 1}"
254
+ )
255
+ logger.info(
256
+ "TIP: Validate your YAML at https://www.yamllint.com/ or run: python scripts/validate_configuration.py"
257
+ )
258
+ logger.info(
259
+ "TIP: Common issue - YAML requires spaces, not tabs. Fix with: sed -i '' 's/\t/ /g' "
260
+ + str(file_path)
261
+ )
262
+ # Store error for later retrieval
263
+ self._config["_load_error"] = str(e)
264
+ return # Don't re-raise, we handled it
265
+
266
+ # Not a YAML error, wrap as configuration error
259
267
  raise ConfigurationError(
260
268
  f"Unexpected error loading configuration from {file_path}: {e}",
261
269
  context={
@@ -605,6 +613,11 @@ class Config:
605
613
  "sync_interval": "startup", # Options: "startup", "hourly", "daily", "manual"
606
614
  "cache_dir": str(Path.home() / ".claude-mpm" / "cache" / "agents"),
607
615
  },
616
+ # Autotodos configuration
617
+ "autotodos": {
618
+ "auto_inject_on_startup": True, # Auto-inject pending todos on PM session start
619
+ "max_todos_per_session": 10, # Max todos to inject per session
620
+ },
608
621
  }
609
622
 
610
623
  # Apply defaults for missing keys
claude_mpm/core/logger.py CHANGED
@@ -214,19 +214,22 @@ def setup_logging(
214
214
 
215
215
  # Console handler
216
216
  if console_output:
217
+ # MUST use stderr to avoid corrupting hook JSON output
218
+ # WHY stderr: Hook handlers output JSON to stdout. Logging to stdout
219
+ # corrupts this JSON and causes "hook error" messages from Claude Code.
217
220
  if use_streaming:
218
221
  # Use streaming handler for single-line INFO messages
219
- console_handler = StreamingHandler(sys.stdout)
222
+ console_handler = StreamingHandler(sys.stderr)
220
223
  console_handler.setFormatter(simple_formatter)
221
224
  elif use_rich and not json_format:
222
225
  # Rich support has been removed, use standard handler
223
- console_handler = logging.StreamHandler(sys.stdout)
226
+ console_handler = logging.StreamHandler(sys.stderr)
224
227
  console_handler.setFormatter(simple_formatter)
225
228
  else:
226
- console_handler = logging.StreamHandler(sys.stdout)
229
+ console_handler = logging.StreamHandler(sys.stderr)
227
230
  console_handler.setFormatter(formatter if json_format else simple_formatter)
228
231
 
229
- console_handler.setLevel(logging.INFO)
232
+ console_handler.setLevel(log_level) # Respect the requested log level
230
233
  logger.addHandler(console_handler)
231
234
 
232
235
  # File handler
@@ -263,7 +266,7 @@ def setup_logging(
263
266
  if deleted_count > 0:
264
267
  # Log to the new file handler that we're about to add
265
268
  pass # Deletion count will be logged when logger is ready
266
- except Exception:
269
+ except Exception: # nosec B110 - intentional: logging should not break app
267
270
  pass # Ignore cleanup errors
268
271
 
269
272
  # Also create a symlink to latest log (with thread safety)
@@ -305,7 +308,7 @@ def setup_logging(
305
308
  # Fallback: try to create a regular file with reference to actual log
306
309
  try:
307
310
  latest_link.write_text(f"Latest log: {log_file.name}\n")
308
- except Exception:
311
+ except Exception: # nosec B110 - intentional: logging should not break app
309
312
  pass # Silently fail - logging should not break the application
310
313
  except Exception as e:
311
314
  # Catch any other unexpected errors to ensure logging doesn't break
@@ -381,15 +384,29 @@ def cleanup_old_mpm_logs(
381
384
  try:
382
385
  log_file.unlink()
383
386
  deleted_count += 1
384
- except Exception:
387
+ except Exception: # nosec B110 - intentional: log cleanup is best-effort
385
388
  pass # Ignore deletion errors
386
389
 
387
390
  return deleted_count
388
391
 
389
392
 
390
393
  def get_logger(name: str) -> logging.Logger:
391
- """Get a logger instance."""
392
- return logging.getLogger(f"claude_mpm.{name}")
394
+ """Get a logger instance.
395
+
396
+ CRITICAL: Respects startup suppression mode (CRITICAL+1) to prevent
397
+ early INFO logs before setup_logging() is called.
398
+ """
399
+ logger = logging.getLogger(f"claude_mpm.{name}")
400
+
401
+ # Check if root logger is suppressed (startup.py sets CRITICAL+1)
402
+ root_logger = logging.getLogger()
403
+ if root_logger.level > logging.CRITICAL:
404
+ # Suppression active - ensure this logger is also suppressed
405
+ logger.setLevel(logging.CRITICAL + 1)
406
+ logger.handlers = []
407
+ logger.propagate = False
408
+
409
+ return logger
393
410
 
394
411
 
395
412
  def setup_streaming_logger(name: str, level: str = "INFO") -> logging.Logger:
@@ -103,21 +103,45 @@ class LoggerFactory:
103
103
 
104
104
  # Set up root logger
105
105
  root_logger = logging.getLogger()
106
- root_logger.setLevel(LoggingConfig.LEVELS.get(cls._log_level, logging.INFO))
106
+
107
+ # CRITICAL FIX: Respect existing root logger suppression
108
+ # If root logger is already set to CRITICAL+1 (suppressed by startup.py),
109
+ # don't override it. This prevents logging from appearing during startup
110
+ # before the CLI's setup_logging() runs.
111
+ current_level = root_logger.level
112
+ desired_level = LoggingConfig.LEVELS.get(cls._log_level, logging.INFO)
113
+
114
+ # Only set level if current is unset (0) or lower than desired
115
+ # CRITICAL+1 is 51, so this check preserves suppression
116
+ should_configure_logging = current_level == 0 or (
117
+ current_level < desired_level and current_level <= logging.CRITICAL
118
+ )
119
+
120
+ if should_configure_logging:
121
+ root_logger.setLevel(desired_level)
122
+ # else: root logger is suppressed (CRITICAL+1), keep it suppressed
107
123
 
108
124
  # Remove existing handlers
109
125
  root_logger.handlers = []
110
126
 
111
- # Console handler
112
- console_handler = logging.StreamHandler(sys.stdout)
113
- console_handler.setLevel(LoggingConfig.LEVELS.get(cls._log_level, logging.INFO))
114
- console_formatter = logging.Formatter(
115
- log_format or LoggingConfig.DEFAULT_FORMAT,
116
- date_format or LoggingConfig.DATE_FORMAT,
117
- )
118
- console_handler.setFormatter(console_formatter)
119
- root_logger.addHandler(console_handler)
120
- cls._handlers["console"] = console_handler
127
+ # CRITICAL FIX: Don't add handlers if logging is suppressed
128
+ # If root logger is at CRITICAL+1 (startup suppression), don't add any handlers
129
+ # This prevents early imports from logging before CLI setup_logging() runs
130
+ if should_configure_logging:
131
+ # Console handler - MUST use stderr to avoid corrupting hook JSON output
132
+ # WHY stderr: Hook handlers output JSON to stdout. Logging to stdout
133
+ # corrupts this JSON and causes "hook error" messages from Claude Code.
134
+ console_handler = logging.StreamHandler(sys.stderr)
135
+ console_handler.setLevel(
136
+ LoggingConfig.LEVELS.get(cls._log_level, logging.INFO)
137
+ )
138
+ console_formatter = logging.Formatter(
139
+ log_format or LoggingConfig.DEFAULT_FORMAT,
140
+ date_format or LoggingConfig.DATE_FORMAT,
141
+ )
142
+ console_handler.setFormatter(console_formatter)
143
+ root_logger.addHandler(console_handler)
144
+ cls._handlers["console"] = console_handler
121
145
 
122
146
  # File handler (optional)
123
147
  if log_to_file and cls._log_dir: