claude-mpm 5.4.96__py3-none-any.whl → 5.6.17__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 (214) 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 +216 -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 +116 -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 +124 -3
  19. claude_mpm/cli/startup_display.py +2 -1
  20. claude_mpm/cli/utils.py +7 -3
  21. claude_mpm/commander/__init__.py +78 -0
  22. claude_mpm/commander/adapters/__init__.py +60 -0
  23. claude_mpm/commander/adapters/auggie.py +260 -0
  24. claude_mpm/commander/adapters/base.py +288 -0
  25. claude_mpm/commander/adapters/claude_code.py +392 -0
  26. claude_mpm/commander/adapters/codex.py +237 -0
  27. claude_mpm/commander/adapters/communication.py +366 -0
  28. claude_mpm/commander/adapters/example_usage.py +310 -0
  29. claude_mpm/commander/adapters/mpm.py +389 -0
  30. claude_mpm/commander/adapters/registry.py +204 -0
  31. claude_mpm/commander/api/__init__.py +16 -0
  32. claude_mpm/commander/api/app.py +121 -0
  33. claude_mpm/commander/api/errors.py +133 -0
  34. claude_mpm/commander/api/routes/__init__.py +8 -0
  35. claude_mpm/commander/api/routes/events.py +184 -0
  36. claude_mpm/commander/api/routes/inbox.py +171 -0
  37. claude_mpm/commander/api/routes/messages.py +148 -0
  38. claude_mpm/commander/api/routes/projects.py +271 -0
  39. claude_mpm/commander/api/routes/sessions.py +226 -0
  40. claude_mpm/commander/api/routes/work.py +296 -0
  41. claude_mpm/commander/api/schemas.py +186 -0
  42. claude_mpm/commander/chat/__init__.py +7 -0
  43. claude_mpm/commander/chat/cli.py +111 -0
  44. claude_mpm/commander/chat/commands.py +96 -0
  45. claude_mpm/commander/chat/repl.py +310 -0
  46. claude_mpm/commander/config.py +49 -0
  47. claude_mpm/commander/config_loader.py +115 -0
  48. claude_mpm/commander/core/__init__.py +10 -0
  49. claude_mpm/commander/core/block_manager.py +325 -0
  50. claude_mpm/commander/core/response_manager.py +323 -0
  51. claude_mpm/commander/daemon.py +594 -0
  52. claude_mpm/commander/env_loader.py +59 -0
  53. claude_mpm/commander/events/__init__.py +26 -0
  54. claude_mpm/commander/events/manager.py +332 -0
  55. claude_mpm/commander/frameworks/__init__.py +12 -0
  56. claude_mpm/commander/frameworks/base.py +143 -0
  57. claude_mpm/commander/frameworks/claude_code.py +58 -0
  58. claude_mpm/commander/frameworks/mpm.py +62 -0
  59. claude_mpm/commander/inbox/__init__.py +16 -0
  60. claude_mpm/commander/inbox/dedup.py +128 -0
  61. claude_mpm/commander/inbox/inbox.py +224 -0
  62. claude_mpm/commander/inbox/models.py +70 -0
  63. claude_mpm/commander/instance_manager.py +337 -0
  64. claude_mpm/commander/llm/__init__.py +6 -0
  65. claude_mpm/commander/llm/openrouter_client.py +167 -0
  66. claude_mpm/commander/llm/summarizer.py +70 -0
  67. claude_mpm/commander/memory/__init__.py +45 -0
  68. claude_mpm/commander/memory/compression.py +347 -0
  69. claude_mpm/commander/memory/embeddings.py +230 -0
  70. claude_mpm/commander/memory/entities.py +310 -0
  71. claude_mpm/commander/memory/example_usage.py +290 -0
  72. claude_mpm/commander/memory/integration.py +325 -0
  73. claude_mpm/commander/memory/search.py +381 -0
  74. claude_mpm/commander/memory/store.py +657 -0
  75. claude_mpm/commander/models/__init__.py +18 -0
  76. claude_mpm/commander/models/events.py +121 -0
  77. claude_mpm/commander/models/project.py +162 -0
  78. claude_mpm/commander/models/work.py +214 -0
  79. claude_mpm/commander/parsing/__init__.py +20 -0
  80. claude_mpm/commander/parsing/extractor.py +132 -0
  81. claude_mpm/commander/parsing/output_parser.py +270 -0
  82. claude_mpm/commander/parsing/patterns.py +100 -0
  83. claude_mpm/commander/persistence/__init__.py +11 -0
  84. claude_mpm/commander/persistence/event_store.py +274 -0
  85. claude_mpm/commander/persistence/state_store.py +309 -0
  86. claude_mpm/commander/persistence/work_store.py +164 -0
  87. claude_mpm/commander/polling/__init__.py +13 -0
  88. claude_mpm/commander/polling/event_detector.py +104 -0
  89. claude_mpm/commander/polling/output_buffer.py +49 -0
  90. claude_mpm/commander/polling/output_poller.py +153 -0
  91. claude_mpm/commander/project_session.py +268 -0
  92. claude_mpm/commander/proxy/__init__.py +12 -0
  93. claude_mpm/commander/proxy/formatter.py +89 -0
  94. claude_mpm/commander/proxy/output_handler.py +191 -0
  95. claude_mpm/commander/proxy/relay.py +155 -0
  96. claude_mpm/commander/registry.py +410 -0
  97. claude_mpm/commander/runtime/__init__.py +10 -0
  98. claude_mpm/commander/runtime/executor.py +191 -0
  99. claude_mpm/commander/runtime/monitor.py +346 -0
  100. claude_mpm/commander/session/__init__.py +6 -0
  101. claude_mpm/commander/session/context.py +81 -0
  102. claude_mpm/commander/session/manager.py +59 -0
  103. claude_mpm/commander/tmux_orchestrator.py +361 -0
  104. claude_mpm/commander/web/__init__.py +1 -0
  105. claude_mpm/commander/work/__init__.py +30 -0
  106. claude_mpm/commander/work/executor.py +207 -0
  107. claude_mpm/commander/work/queue.py +405 -0
  108. claude_mpm/commander/workflow/__init__.py +27 -0
  109. claude_mpm/commander/workflow/event_handler.py +241 -0
  110. claude_mpm/commander/workflow/notifier.py +146 -0
  111. claude_mpm/commands/mpm-config.md +8 -0
  112. claude_mpm/commands/mpm-doctor.md +8 -0
  113. claude_mpm/commands/mpm-help.md +8 -0
  114. claude_mpm/commands/mpm-init.md +8 -0
  115. claude_mpm/commands/mpm-monitor.md +8 -0
  116. claude_mpm/commands/mpm-organize.md +8 -0
  117. claude_mpm/commands/mpm-postmortem.md +8 -0
  118. claude_mpm/commands/mpm-session-resume.md +8 -0
  119. claude_mpm/commands/mpm-status.md +8 -0
  120. claude_mpm/commands/mpm-ticket-view.md +8 -0
  121. claude_mpm/commands/mpm-version.md +8 -0
  122. claude_mpm/commands/mpm.md +8 -0
  123. claude_mpm/config/agent_presets.py +8 -7
  124. claude_mpm/config/skill_sources.py +16 -0
  125. claude_mpm/core/claude_runner.py +143 -0
  126. claude_mpm/core/config.py +32 -19
  127. claude_mpm/core/logger.py +26 -9
  128. claude_mpm/core/logging_utils.py +35 -11
  129. claude_mpm/core/output_style_manager.py +49 -12
  130. claude_mpm/core/unified_config.py +10 -6
  131. claude_mpm/core/unified_paths.py +68 -80
  132. claude_mpm/experimental/cli_enhancements.py +2 -1
  133. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.pyc +0 -0
  134. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  135. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  136. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-312.pyc +0 -0
  137. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-314.pyc +0 -0
  138. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  139. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-312.pyc +0 -0
  140. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-314.pyc +0 -0
  141. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  142. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.pyc +0 -0
  143. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-314.pyc +0 -0
  144. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  145. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-314.pyc +0 -0
  146. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  147. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-312.pyc +0 -0
  148. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-314.pyc +0 -0
  149. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  150. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc +0 -0
  151. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-314.pyc +0 -0
  152. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-312.pyc +0 -0
  153. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-314.pyc +0 -0
  154. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +29 -30
  155. claude_mpm/hooks/claude_hooks/event_handlers.py +112 -99
  156. claude_mpm/hooks/claude_hooks/hook_handler.py +81 -88
  157. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  158. claude_mpm/hooks/claude_hooks/installer.py +116 -8
  159. claude_mpm/hooks/claude_hooks/memory_integration.py +51 -31
  160. claude_mpm/hooks/claude_hooks/response_tracking.py +39 -58
  161. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-312.pyc +0 -0
  162. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-314.pyc +0 -0
  163. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  164. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  165. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-312.pyc +0 -0
  166. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-314.pyc +0 -0
  167. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-312.pyc +0 -0
  168. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-314.pyc +0 -0
  169. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  170. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc +0 -0
  171. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-314.pyc +0 -0
  172. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  173. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
  174. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-314.pyc +0 -0
  175. claude_mpm/hooks/claude_hooks/services/connection_manager.py +23 -28
  176. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +36 -103
  177. claude_mpm/hooks/claude_hooks/services/state_manager.py +23 -36
  178. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +47 -73
  179. claude_mpm/hooks/session_resume_hook.py +22 -18
  180. claude_mpm/hooks/templates/pre_tool_use_template.py +10 -2
  181. claude_mpm/scripts/claude-hook-handler.sh +43 -16
  182. claude_mpm/scripts/start_activity_logging.py +0 -0
  183. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  184. claude_mpm/services/agents/agent_selection_service.py +2 -2
  185. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  186. claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
  187. claude_mpm/services/event_log.py +8 -0
  188. claude_mpm/services/pm_skills_deployer.py +84 -6
  189. claude_mpm/services/skills/git_skill_source_manager.py +130 -10
  190. claude_mpm/services/skills/selective_skill_deployer.py +28 -0
  191. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  192. claude_mpm/services/skills_deployer.py +31 -5
  193. claude_mpm/skills/__init__.py +2 -1
  194. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  195. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  196. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  197. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  198. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  199. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  200. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  201. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  202. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  203. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  204. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  205. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  206. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  207. claude_mpm/skills/registry.py +295 -90
  208. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/METADATA +22 -6
  209. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/RECORD +213 -83
  210. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/WHEEL +0 -0
  211. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/entry_points.txt +0 -0
  212. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/licenses/LICENSE +0 -0
  213. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  214. {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/top_level.txt +0 -0
@@ -62,8 +62,13 @@ set -e
62
62
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
63
63
 
64
64
  # Determine the claude-mpm root based on installation type
65
+ # Check if we're in a UV tools installation
66
+ if [[ "$SCRIPT_DIR" == *"/.local/share/uv/tools/"* ]]; then
67
+ # UV tools installation - script is at lib/python*/site-packages/claude_mpm/scripts/
68
+ # The tool root is what we need for Python detection
69
+ CLAUDE_MPM_ROOT="$(echo "$SCRIPT_DIR" | sed 's|/lib/python.*/site-packages.*||')"
65
70
  # Check if we're in a pipx installation
66
- if [[ "$SCRIPT_DIR" == *"/.local/pipx/venvs/claude-mpm/"* ]]; then
71
+ elif [[ "$SCRIPT_DIR" == *"/.local/pipx/venvs/claude-mpm/"* ]]; then
67
72
  # pipx installation - script is at lib/python*/site-packages/claude_mpm/scripts/
68
73
  # The venv root is what we need for Python detection
69
74
  CLAUDE_MPM_ROOT="$(echo "$SCRIPT_DIR" | sed 's|/lib/python.*/site-packages/.*||')"
@@ -89,11 +94,12 @@ fi
89
94
  # STRATEGY:
90
95
  # This function implements a fallback chain to find Python with claude-mpm dependencies:
91
96
  # 1. UV-managed projects (uv.lock detected) - uses "uv run python"
92
- # 2. pipx installations - uses pipx venv Python
93
- # 3. Project-specific virtual environments (venv, .venv)
94
- # 4. Currently active virtual environment ($VIRTUAL_ENV)
95
- # 5. System python3 (may lack dependencies)
96
- # 6. System python (last resort)
97
+ # 2. UV tools installations (~/.local/share/uv/tools/) - uses tool's venv Python
98
+ # 3. pipx installations - uses pipx venv Python
99
+ # 4. Project-specific virtual environments (venv, .venv)
100
+ # 5. Currently active virtual environment ($VIRTUAL_ENV)
101
+ # 6. System python3 (may lack dependencies)
102
+ # 7. System python (last resort)
97
103
  #
98
104
  # WHY THIS APPROACH:
99
105
  # - Claude MPM requires specific packages (socketio, eventlet) not in system Python
@@ -119,12 +125,26 @@ find_python_command() {
119
125
  # 1. Check for UV project first (uv.lock or pyproject.toml with uv)
120
126
  if [ -f "$CLAUDE_MPM_ROOT/uv.lock" ]; then
121
127
  if command -v uv &> /dev/null; then
122
- echo "uv run python"
128
+ echo "uv run --directory \"$CLAUDE_MPM_ROOT\" python"
123
129
  return
124
130
  fi
125
131
  fi
126
132
 
127
- # 2. Check if we're in a pipx installation
133
+ # 2. Check if we're in a UV tools installation
134
+ if [[ "$SCRIPT_DIR" == *"/.local/share/uv/tools/"* ]]; then
135
+ # UV tools installation - extract the tool root directory
136
+ CLAUDE_MPM_ROOT="$(echo "$SCRIPT_DIR" | sed 's|/lib/python.*/site-packages.*||')"
137
+ local uv_python="$CLAUDE_MPM_ROOT/bin/python"
138
+ if [ -x "$uv_python" ]; then
139
+ if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
140
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] UV tools Python found: $uv_python" >> /tmp/claude-mpm-hook.log
141
+ fi
142
+ echo "$uv_python"
143
+ return
144
+ fi
145
+ fi
146
+
147
+ # 3. Check if we're in a pipx installation
128
148
  if [[ "$SCRIPT_DIR" == *"/.local/pipx/venvs/claude-mpm/"* ]]; then
129
149
  # pipx installation - use the pipx venv's Python directly
130
150
  if [ -f "$CLAUDE_MPM_ROOT/bin/python" ]; then
@@ -133,7 +153,7 @@ find_python_command() {
133
153
  fi
134
154
  fi
135
155
 
136
- # 3. Check for project-local virtual environment (common in development)
156
+ # 4. Check for project-local virtual environment (common in development)
137
157
  if [ -f "$CLAUDE_MPM_ROOT/venv/bin/activate" ]; then
138
158
  source "$CLAUDE_MPM_ROOT/venv/bin/activate"
139
159
  echo "$CLAUDE_MPM_ROOT/venv/bin/python"
@@ -154,7 +174,13 @@ find_python_command() {
154
174
  PYTHON_CMD=$(find_python_command)
155
175
 
156
176
  # Check installation type and set PYTHONPATH accordingly
157
- if [[ "$SCRIPT_DIR" == *"/.local/pipx/venvs/claude-mpm/"* ]]; then
177
+ if [[ "$SCRIPT_DIR" == *"/.local/share/uv/tools/"* ]]; then
178
+ # UV tools installation - claude_mpm is already in the tool's site-packages
179
+ # No need to modify PYTHONPATH
180
+ if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
181
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] UV tools installation detected" >> /tmp/claude-mpm-hook.log
182
+ fi
183
+ elif [[ "$SCRIPT_DIR" == *"/.local/pipx/venvs/claude-mpm/"* ]]; then
158
184
  # pipx installation - claude_mpm is already in the venv's site-packages
159
185
  # No need to modify PYTHONPATH
160
186
  if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
@@ -193,8 +219,8 @@ log_debug() {
193
219
 
194
220
  # Test Python works and module exists
195
221
  # Handle UV's multi-word command specially
196
- if [[ "$PYTHON_CMD" == "uv run python" ]]; then
197
- if ! uv run python -c "import claude_mpm" 2>/dev/null; then
222
+ if [[ "$PYTHON_CMD" == "uv run"* ]]; then
223
+ if ! uv run --directory "$CLAUDE_MPM_ROOT" python -c "import claude_mpm" 2>/dev/null; then
198
224
  log_debug "claude_mpm module not available, continuing without hook"
199
225
  echo '{"action": "continue"}'
200
226
  exit 0
@@ -210,10 +236,11 @@ fi
210
236
  # Run the Python hook handler with all input
211
237
  # Use exec to replace the shell process with Python
212
238
  # Handle UV's multi-word command specially
213
- if [[ "$PYTHON_CMD" == "uv run python" ]]; then
214
- exec uv run python -m claude_mpm.hooks.claude_hooks.hook_handler "$@" 2>/tmp/claude-mpm-hook-error.log
239
+ # Suppress RuntimeWarning to prevent stderr output (which causes hook errors)
240
+ if [[ "$PYTHON_CMD" == "uv run"* ]]; then
241
+ exec uv run --directory "$CLAUDE_MPM_ROOT" python -W ignore::RuntimeWarning -m claude_mpm.hooks.claude_hooks.hook_handler "$@" 2>/tmp/claude-mpm-hook-error.log
215
242
  else
216
- exec "$PYTHON_CMD" -m claude_mpm.hooks.claude_hooks.hook_handler "$@" 2>/tmp/claude-mpm-hook-error.log
243
+ exec "$PYTHON_CMD" -W ignore::RuntimeWarning -m claude_mpm.hooks.claude_hooks.hook_handler "$@" 2>/tmp/claude-mpm-hook-error.log
217
244
  fi
218
245
 
219
246
  # Note: exec replaces the shell process, so code below only runs if exec fails
@@ -224,4 +251,4 @@ if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
224
251
  fi
225
252
  # Return continue action to prevent blocking Claude Code
226
253
  echo '{"action": "continue"}'
227
- exit 0
254
+ exit 0
File without changes
@@ -30,16 +30,16 @@ class AgentRecommendationService:
30
30
  Can be used by CLI, API, or future auto-configuration features.
31
31
  """
32
32
 
33
- # Core agents always included - matches ToolchainDetector.CORE_AGENTS
33
+ # Core agents always included - Standard 6 core agents for essential PM workflow
34
+ # These agents are auto-deployed when no configuration exists
34
35
  # Uses exact agent IDs from repository for consistency
35
36
  CORE_AGENTS = {
36
- "engineer",
37
- "qa-agent",
38
- "memory-manager-agent",
39
- "local-ops-agent",
40
- "research-agent",
41
- "documentation-agent",
42
- "security-agent",
37
+ "engineer", # General-purpose implementation
38
+ "research", # Codebase exploration and analysis
39
+ "qa", # Testing and quality assurance
40
+ "documentation", # Documentation generation
41
+ "ops", # Basic deployment operations
42
+ "ticketing", # Ticket tracking (essential for PM workflow)
43
43
  }
44
44
 
45
45
  # Map detected languages to recommended engineer agents
@@ -39,10 +39,10 @@ import logging
39
39
  from pathlib import Path
40
40
  from typing import Any, Dict, List, Optional, Set, Tuple
41
41
 
42
- from src.claude_mpm.services.agents.single_tier_deployment_service import (
42
+ from claude_mpm.services.agents.single_tier_deployment_service import (
43
43
  SingleTierDeploymentService,
44
44
  )
45
- from src.claude_mpm.services.agents.toolchain_detector import ToolchainDetector
45
+ from claude_mpm.services.agents.toolchain_detector import ToolchainDetector
46
46
 
47
47
  logger = logging.getLogger(__name__)
48
48
 
@@ -10,10 +10,19 @@ Loading precedence: Project → User → System
10
10
 
11
11
  This service integrates with the main agent_loader.py to provide
12
12
  markdown-based agent profiles alongside JSON-based templates.
13
+
14
+ Auto-Deployment: When no agents are configured, the standard 6 core agents
15
+ are automatically deployed:
16
+ - engineer: General-purpose implementation
17
+ - research: Codebase exploration and analysis
18
+ - qa: Testing and quality assurance
19
+ - documentation: Documentation generation
20
+ - ops: Basic deployment operations
21
+ - ticketing: Ticket tracking (essential for PM workflow)
13
22
  """
14
23
 
15
24
  from pathlib import Path
16
- from typing import Any, Dict, Optional
25
+ from typing import Any, Dict, List, Optional
17
26
 
18
27
  from claude_mpm.agents.agent_loader import AgentTier, list_agents_by_tier
19
28
  from claude_mpm.core.logging_utils import get_logger
@@ -21,6 +30,17 @@ from claude_mpm.core.unified_paths import get_path_manager
21
30
 
22
31
  logger = get_logger(__name__)
23
32
 
33
+ # Standard 6 core agents that are auto-deployed when no agents are specified
34
+ # This list is the canonical source - other modules should import from here
35
+ CORE_AGENTS: List[str] = [
36
+ "engineer", # General-purpose implementation
37
+ "research", # Codebase exploration and analysis
38
+ "qa", # Testing and quality assurance
39
+ "documentation", # Documentation generation
40
+ "ops", # Basic deployment operations
41
+ "ticketing", # Ticket tracking (essential for PM workflow)
42
+ ]
43
+
24
44
 
25
45
  class FrameworkAgentLoader:
26
46
  """Loads agent profiles from project, user, and system directories with proper precedence"""
@@ -86,7 +106,7 @@ class FrameworkAgentLoader:
86
106
  data_claude = package_path / "data" / "agents" / "CLAUDE.md"
87
107
  if data_instructions.exists() or data_claude.exists():
88
108
  return package_path / "data"
89
- except Exception:
109
+ except Exception: # nosec B110 - intentional fallthrough to next location
90
110
  pass
91
111
 
92
112
  current = Path.cwd()
@@ -431,3 +451,56 @@ Please operate according to your profile specifications and maintain quality sta
431
451
  """
432
452
 
433
453
  return instruction.strip()
454
+
455
+ def get_core_agents(self) -> List[str]:
456
+ """
457
+ Get the standard 6 core agents for auto-deployment.
458
+
459
+ These agents are automatically deployed when no agents are specified
460
+ in the configuration. They provide essential PM workflow functionality.
461
+
462
+ Returns:
463
+ List of core agent IDs
464
+
465
+ Example:
466
+ >>> loader = FrameworkAgentLoader()
467
+ >>> core = loader.get_core_agents()
468
+ >>> 'engineer' in core
469
+ True
470
+ >>> len(core)
471
+ 6
472
+ """
473
+ return CORE_AGENTS.copy()
474
+
475
+ def get_agents_with_fallback(self) -> Dict[str, list]:
476
+ """
477
+ Get available agents, falling back to core agents if none found.
478
+
479
+ This method implements the auto-deployment logic: when no agents
480
+ are found in any tier (project, user, system), it returns the
481
+ standard 6 core agents as a fallback.
482
+
483
+ Returns:
484
+ Dictionary with agent lists by tier. If no agents found in any tier,
485
+ returns core agents under 'fallback' key.
486
+
487
+ Example:
488
+ >>> loader = FrameworkAgentLoader()
489
+ >>> loader.initialize()
490
+ >>> agents = loader.get_agents_with_fallback()
491
+ >>> if 'fallback' in agents:
492
+ ... print("Using core agents as fallback")
493
+ """
494
+ available = self.get_available_agents()
495
+
496
+ # Check if any agents are found
497
+ total_agents = sum(len(agents) for agents in available.values())
498
+
499
+ if total_agents == 0:
500
+ logger.info(
501
+ "No agents found in configuration. "
502
+ "Auto-deploying standard 6 core agents."
503
+ )
504
+ return {"fallback": CORE_AGENTS.copy()}
505
+
506
+ return available
@@ -30,12 +30,12 @@ from datetime import datetime, timezone
30
30
  from pathlib import Path
31
31
  from typing import Any, Dict, List, Optional
32
32
 
33
- from src.claude_mpm.config.agent_sources import AgentSourceConfiguration
34
- from src.claude_mpm.models.git_repository import GitRepository
35
- from src.claude_mpm.services.agents.deployment.remote_agent_discovery_service import (
33
+ from claude_mpm.config.agent_sources import AgentSourceConfiguration
34
+ from claude_mpm.models.git_repository import GitRepository
35
+ from claude_mpm.services.agents.deployment.remote_agent_discovery_service import (
36
36
  RemoteAgentDiscoveryService,
37
37
  )
38
- from src.claude_mpm.services.agents.git_source_manager import GitSourceManager
38
+ from claude_mpm.services.agents.git_source_manager import GitSourceManager
39
39
 
40
40
  logger = logging.getLogger(__name__)
41
41
 
@@ -310,8 +310,16 @@ def get_event_log(log_file: Optional[Path] = None) -> EventLog:
310
310
 
311
311
  Returns:
312
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.
313
318
  """
314
319
  global _event_log
315
320
  if _event_log is None:
316
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)
317
325
  return _event_log
@@ -50,9 +50,16 @@ from claude_mpm.core.mixins import LoggerMixin
50
50
  # Security constants
51
51
  MAX_YAML_SIZE = 10 * 1024 * 1024 # 10MB limit to prevent YAML bombs
52
52
 
53
- # Required PM skills that MUST be deployed for PM agent to function properly
54
- # These are framework management skills that PM uses for orchestration
53
+ # Tier 1: Required PM skills that MUST be deployed for PM agent to function properly
54
+ # These are core framework management skills for basic PM operation
55
55
  REQUIRED_PM_SKILLS = [
56
+ # Core command-based skills (new consolidated CLI)
57
+ "mpm",
58
+ "mpm-init",
59
+ "mpm-status",
60
+ "mpm-help",
61
+ "mpm-doctor",
62
+ # Legacy framework management skills
56
63
  "mpm-git-file-tracking",
57
64
  "mpm-pr-workflow",
58
65
  "mpm-ticketing-integration",
@@ -66,6 +73,23 @@ REQUIRED_PM_SKILLS = [
66
73
  "mpm-session-management",
67
74
  ]
68
75
 
76
+ # Tier 2: Recommended skills (deployed with standard install)
77
+ # These provide enhanced functionality for common workflows
78
+ RECOMMENDED_PM_SKILLS = [
79
+ "mpm-config",
80
+ "mpm-ticket-view",
81
+ "mpm-session-resume",
82
+ "mpm-postmortem",
83
+ ]
84
+
85
+ # Tier 3: Optional skills (deployed with full install)
86
+ # These provide additional features for advanced use cases
87
+ OPTIONAL_PM_SKILLS = [
88
+ "mpm-monitor",
89
+ "mpm-version",
90
+ "mpm-organize",
91
+ ]
92
+
69
93
 
70
94
  @dataclass
71
95
  class PMSkillInfo:
@@ -383,17 +407,45 @@ class PMSkillsDeployerService(LoggerMixin):
383
407
  self.logger.info(f"Discovered {len(skills)} bundled PM skills")
384
408
  return skills
385
409
 
410
+ def _get_skills_for_tier(self, tier: str) -> List[str]:
411
+ """Get list of skills to deploy based on tier.
412
+
413
+ Args:
414
+ tier: Deployment tier - "minimal", "standard", or "full"
415
+
416
+ Returns:
417
+ List of skill names to deploy
418
+
419
+ Raises:
420
+ ValueError: If tier is invalid
421
+ """
422
+ if tier == "minimal":
423
+ return REQUIRED_PM_SKILLS
424
+ if tier == "standard":
425
+ return REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS
426
+ if tier == "full":
427
+ return REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS + OPTIONAL_PM_SKILLS
428
+ raise ValueError(
429
+ f"Invalid tier '{tier}'. Must be 'minimal', 'standard', or 'full'"
430
+ )
431
+
386
432
  def deploy_pm_skills(
387
433
  self,
388
434
  project_dir: Path,
389
435
  force: bool = False,
436
+ tier: str = "standard",
390
437
  progress_callback: Optional[Callable[[str, int, int], None]] = None,
391
438
  ) -> DeploymentResult:
392
- """Deploy bundled PM skills to project directory.
439
+ """Deploy bundled PM skills to project directory with tier-based selection.
393
440
 
394
441
  Copies PM skills from bundled templates to .claude/skills/{name}/SKILL.md
395
442
  and updates registry with version and checksum information.
396
443
 
444
+ Deployment Tiers:
445
+ - "minimal": Only REQUIRED_PM_SKILLS (Tier 1 - core functionality)
446
+ - "standard": REQUIRED_PM_SKILLS + RECOMMENDED_PM_SKILLS (Tier 1+2 - common workflows)
447
+ - "full": All skills (Tier 1+2+3 - advanced features)
448
+
397
449
  Conflict Resolution:
398
450
  - mpm-* skills from src WIN (overwrite existing)
399
451
  - Non-mpm-* skills in .claude/skills/ are untouched
@@ -401,16 +453,42 @@ class PMSkillsDeployerService(LoggerMixin):
401
453
  Args:
402
454
  project_dir: Project root directory
403
455
  force: If True, redeploy even if skill already exists
456
+ tier: Deployment tier - "minimal", "standard" (default), or "full"
404
457
  progress_callback: Optional callback(skill_name, current, total) for progress
405
458
 
406
459
  Returns:
407
460
  DeploymentResult with deployment status and details
408
461
 
409
462
  Example:
410
- >>> result = deployer.deploy_pm_skills(Path("/project"), force=True)
463
+ >>> # Standard deployment (Tier 1 + Tier 2)
464
+ >>> result = deployer.deploy_pm_skills(Path("/project"))
411
465
  >>> print(f"Deployed: {len(result.deployed)} to .claude/skills/")
466
+ >>>
467
+ >>> # Minimal deployment (Tier 1 only)
468
+ >>> result = deployer.deploy_pm_skills(Path("/project"), tier="minimal")
469
+ >>>
470
+ >>> # Full deployment (all tiers)
471
+ >>> result = deployer.deploy_pm_skills(Path("/project"), tier="full")
412
472
  """
413
- skills = self._discover_bundled_pm_skills()
473
+ # Get tier-based skill filter
474
+ try:
475
+ tier_skills = self._get_skills_for_tier(tier)
476
+ except ValueError as e:
477
+ return DeploymentResult(
478
+ success=False,
479
+ deployed=[],
480
+ skipped=[],
481
+ errors=[{"skill": "all", "error": str(e)}],
482
+ message=str(e),
483
+ )
484
+
485
+ # Discover all bundled skills, then filter by tier
486
+ all_skills = self._discover_bundled_pm_skills()
487
+ skills = [s for s in all_skills if s["name"] in tier_skills]
488
+
489
+ self.logger.info(
490
+ f"Deploying {len(skills)}/{len(all_skills)} skills for tier '{tier}'"
491
+ )
414
492
  deployed = []
415
493
  skipped = []
416
494
  errors = []
@@ -526,7 +604,7 @@ class PMSkillsDeployerService(LoggerMixin):
526
604
 
527
605
  success = len(errors) == 0
528
606
  message = (
529
- f"Deployed {len(deployed)} skills, skipped {len(skipped)}, "
607
+ f"Deployed {len(deployed)} skills (tier: {tier}), skipped {len(skipped)}, "
530
608
  f"{len(errors)} errors"
531
609
  )
532
610