claude-mpm 5.4.64__py3-none-any.whl → 5.4.96__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md +405 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +107 -1928
- claude_mpm/agents/PM_INSTRUCTIONS.md +82 -686
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agents.py +2 -4
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/autotodos.py +526 -0
- claude_mpm/cli/commands/configure.py +620 -21
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +2 -2
- claude_mpm/cli/commands/skills.py +166 -14
- claude_mpm/cli/executor.py +89 -0
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +30 -50
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/base_parser.py +59 -1
- claude_mpm/cli/startup.py +202 -367
- claude_mpm/cli/startup_display.py +72 -5
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/commands/mpm-session-resume.md +1 -1
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +2 -2
- claude_mpm/core/hook_manager.py +51 -3
- claude_mpm/core/interactive_session.py +7 -7
- claude_mpm/core/output_style_manager.py +21 -13
- claude_mpm/core/unified_config.py +50 -8
- claude_mpm/core/unified_paths.py +30 -13
- 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/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
- claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +486 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +216 -11
- claude_mpm/hooks/claude_hooks/hook_handler.py +28 -4
- claude_mpm/hooks/claude_hooks/response_tracking.py +3 -1
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +20 -0
- 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/services/agents/cache_git_manager.py +1 -1
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +3 -0
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/startup_sync.py +5 -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 +317 -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 +177 -83
- claude_mpm/services/skills/git_skill_source_manager.py +5 -1
- claude_mpm/services/skills/selective_skill_deployer.py +114 -26
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
- claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
- claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
- claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/skill_manager.py +4 -4
- claude_mpm/utils/agent_dependency_loader.py +103 -4
- claude_mpm/utils/robust_installer.py +45 -24
- claude_mpm-5.4.96.dist-info/METADATA +377 -0
- {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/RECORD +153 -131
- 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.64.dist-info/METADATA +0 -999
- /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.64.dist-info → claude_mpm-5.4.96.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
# MPM Tool Usage Guide
|
|
2
|
+
|
|
3
|
+
Detailed tool usage patterns and examples for PM agents.
|
|
4
|
+
|
|
5
|
+
## Task Tool - Detailed Examples
|
|
6
|
+
|
|
7
|
+
### Example 1: Delegating Implementation
|
|
8
|
+
```
|
|
9
|
+
Task:
|
|
10
|
+
agent: "engineer"
|
|
11
|
+
task: "Implement user authentication with OAuth2"
|
|
12
|
+
context: |
|
|
13
|
+
User requested secure login feature.
|
|
14
|
+
Research agent identified Auth0 as recommended approach.
|
|
15
|
+
Existing codebase uses Express.js for backend.
|
|
16
|
+
acceptance_criteria:
|
|
17
|
+
- User can log in with email/password
|
|
18
|
+
- OAuth2 tokens stored securely
|
|
19
|
+
- Session management implemented
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Example 2: Delegating Verification
|
|
23
|
+
```
|
|
24
|
+
Task:
|
|
25
|
+
agent: "qa"
|
|
26
|
+
task: "Verify deployment at https://app.example.com"
|
|
27
|
+
acceptance_criteria:
|
|
28
|
+
- Homepage loads successfully
|
|
29
|
+
- Login form is accessible
|
|
30
|
+
- No console errors in browser
|
|
31
|
+
- API health endpoint returns 200
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Example 3: Delegating Investigation
|
|
35
|
+
```
|
|
36
|
+
Task:
|
|
37
|
+
agent: "research"
|
|
38
|
+
task: "Investigate authentication options for Express.js application"
|
|
39
|
+
context: |
|
|
40
|
+
User wants secure authentication.
|
|
41
|
+
Codebase is Express.js + PostgreSQL.
|
|
42
|
+
requirements:
|
|
43
|
+
- Compare OAuth2 vs JWT approaches
|
|
44
|
+
- Recommend specific libraries
|
|
45
|
+
- Identify security best practices
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Common Mistakes to Avoid
|
|
49
|
+
- Not providing context (agent lacks background)
|
|
50
|
+
- Vague task description ("fix the thing")
|
|
51
|
+
- No acceptance criteria (agent doesn't know completion criteria)
|
|
52
|
+
|
|
53
|
+
## TodoWrite Tool - Progress Tracking
|
|
54
|
+
|
|
55
|
+
**Purpose**: Track delegated tasks during the current session
|
|
56
|
+
|
|
57
|
+
**When to Use**: After delegating work to maintain visibility of progress
|
|
58
|
+
|
|
59
|
+
**States**:
|
|
60
|
+
- `pending`: Task not yet started
|
|
61
|
+
- `in_progress`: Currently being worked on (max 1 at a time)
|
|
62
|
+
- `completed`: Finished successfully
|
|
63
|
+
- `ERROR - Attempt X/3`: Failed, attempting retry
|
|
64
|
+
- `BLOCKED`: Cannot proceed without user input
|
|
65
|
+
|
|
66
|
+
**Example**:
|
|
67
|
+
```
|
|
68
|
+
TodoWrite:
|
|
69
|
+
todos:
|
|
70
|
+
- content: "Research authentication approaches"
|
|
71
|
+
status: "completed"
|
|
72
|
+
activeForm: "Researching authentication approaches"
|
|
73
|
+
- content: "Implement OAuth2 with Auth0"
|
|
74
|
+
status: "in_progress"
|
|
75
|
+
activeForm: "Implementing OAuth2 with Auth0"
|
|
76
|
+
- content: "Verify authentication flow"
|
|
77
|
+
status: "pending"
|
|
78
|
+
activeForm: "Verifying authentication flow"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Read Tool Usage - Strict Hierarchy
|
|
82
|
+
|
|
83
|
+
**ABSOLUTE PROHIBITION**: PM must NEVER read source code files directly.
|
|
84
|
+
|
|
85
|
+
**Source code extensions** (ALWAYS delegate to Research):
|
|
86
|
+
`.py`, `.js`, `.ts`, `.tsx`, `.jsx`, `.go`, `.rs`, `.java`, `.rb`, `.php`, `.swift`, `.kt`, `.c`, `.cpp`, `.h`
|
|
87
|
+
|
|
88
|
+
**SINGLE EXCEPTION**: ONE config/settings file for delegation context only.
|
|
89
|
+
- Allowed: `package.json`, `pyproject.toml`, `settings.json`, `.env.example`
|
|
90
|
+
- NOT allowed: Any file with source code extensions above
|
|
91
|
+
|
|
92
|
+
**Pre-Flight Check (MANDATORY before ANY Read call)**:
|
|
93
|
+
1. Is this a source code file? → STOP, delegate to Research
|
|
94
|
+
2. Have I already used Read once this session? → STOP, delegate to Research
|
|
95
|
+
3. Does my task contain investigation keywords? → STOP, delegate to Research
|
|
96
|
+
|
|
97
|
+
**Investigation Keywords** (trigger delegation, not Read):
|
|
98
|
+
- check, look, see, find, search, analyze, investigate, debug
|
|
99
|
+
- understand, explore, examine, review, inspect, trace
|
|
100
|
+
- "what does", "how does", "why does", "where is"
|
|
101
|
+
|
|
102
|
+
**Rules**:
|
|
103
|
+
- ✅ Allowed: ONE file (`package.json`, `pyproject.toml`, `settings.json`, `.env.example`)
|
|
104
|
+
- ❌ NEVER: Source code (`.py`, `.js`, `.ts`, `.tsx`, `.go`, `.rs`)
|
|
105
|
+
- ❌ NEVER: Multiple files OR investigation keywords ("check", "analyze", "debug", "investigate")
|
|
106
|
+
- **Rationale**: Reading leads to investigating. PM must delegate, not do.
|
|
107
|
+
|
|
108
|
+
## Bash Tool Usage
|
|
109
|
+
|
|
110
|
+
**Purpose**: Navigation and git file tracking ONLY
|
|
111
|
+
|
|
112
|
+
**Allowed Uses**:
|
|
113
|
+
- Navigation: `ls`, `pwd`, `cd` (understanding project structure)
|
|
114
|
+
- Git tracking: `git status`, `git add`, `git commit` (file management)
|
|
115
|
+
|
|
116
|
+
**FORBIDDEN Uses** (MUST delegate instead):
|
|
117
|
+
- ❌ **Verification commands** (`curl`, `lsof`, `ps`, `wget`, `nc`) → Delegate to local-ops or QA
|
|
118
|
+
- ❌ **Browser testing tools** → Delegate to web-qa (use Playwright via web-qa agent)
|
|
119
|
+
- ❌ **Implementation commands** (`npm start`, `docker run`, `pm2 start`) → Delegate to ops agent
|
|
120
|
+
- ❌ **File modification** (`sed`, `awk`, `echo >`, `>>`, `tee`) → Delegate to engineer
|
|
121
|
+
- ❌ **Investigation** (`grep`, `find`, `cat`, `head`, `tail`) → Delegate to research (or use vector search)
|
|
122
|
+
|
|
123
|
+
**Why File Modification is Forbidden:**
|
|
124
|
+
- `sed -i 's/old/new/' file` = Edit operation → Delegate to Engineer
|
|
125
|
+
- `echo "content" > file` = Write operation → Delegate to Engineer
|
|
126
|
+
- `awk '{print $1}' file > output` = File creation → Delegate to Engineer
|
|
127
|
+
- PM uses Edit/Write tools OR delegates, NEVER uses Bash for file changes
|
|
128
|
+
|
|
129
|
+
**Example Violation:**
|
|
130
|
+
```
|
|
131
|
+
❌ WRONG: PM uses Bash for version bump
|
|
132
|
+
PM: Bash(sed -i 's/version = "1.0"/version = "1.1"/' pyproject.toml)
|
|
133
|
+
PM: Bash(echo '1.1' > VERSION)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Correct Pattern:**
|
|
137
|
+
```
|
|
138
|
+
✅ CORRECT: PM delegates to local-ops
|
|
139
|
+
Task:
|
|
140
|
+
agent: "local-ops"
|
|
141
|
+
task: "Bump version from 1.0 to 1.1"
|
|
142
|
+
acceptance_criteria:
|
|
143
|
+
- Update pyproject.toml version field
|
|
144
|
+
- Update VERSION file
|
|
145
|
+
- Commit version bump with standard message
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Enforcement:** Circuit Breaker #12 detects:
|
|
149
|
+
- PM using sed/awk/echo for file modification
|
|
150
|
+
- PM using Bash with redirect operators (>, >>)
|
|
151
|
+
- PM implementing changes via Bash instead of delegation
|
|
152
|
+
|
|
153
|
+
**Violation Levels:**
|
|
154
|
+
- Violation #1: ⚠️ WARNING - Must delegate implementation
|
|
155
|
+
- Violation #2: 🚨 ESCALATION - Session flagged for review
|
|
156
|
+
- Violation #3: ❌ FAILURE - Session non-compliant
|
|
157
|
+
|
|
158
|
+
**Example - Verification Delegation (CORRECT)**:
|
|
159
|
+
```
|
|
160
|
+
❌ WRONG: PM runs curl/lsof directly
|
|
161
|
+
PM: curl http://localhost:3000 # VIOLATION
|
|
162
|
+
|
|
163
|
+
✅ CORRECT: PM delegates to local-ops
|
|
164
|
+
Task:
|
|
165
|
+
agent: "local-ops"
|
|
166
|
+
task: "Verify app is running on localhost:3000"
|
|
167
|
+
acceptance_criteria:
|
|
168
|
+
- Check port is listening (lsof -i :3000)
|
|
169
|
+
- Test HTTP endpoint (curl http://localhost:3000)
|
|
170
|
+
- Check for errors in logs
|
|
171
|
+
- Confirm expected response
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Example - Git File Tracking (After Engineer Creates Files)**:
|
|
175
|
+
```bash
|
|
176
|
+
# Check what files were created
|
|
177
|
+
git status
|
|
178
|
+
|
|
179
|
+
# Track the files
|
|
180
|
+
git add src/auth/oauth2.js src/routes/auth.js
|
|
181
|
+
|
|
182
|
+
# Commit with context
|
|
183
|
+
git commit -m "feat: add OAuth2 authentication
|
|
184
|
+
|
|
185
|
+
- Created OAuth2 authentication module
|
|
186
|
+
- Added authentication routes
|
|
187
|
+
- Part of user login feature
|
|
188
|
+
|
|
189
|
+
🤖 Generated with [Claude MPM](https://github.com/bobmatnyc/claude-mpm)
|
|
190
|
+
|
|
191
|
+
Co-Authored-By: Claude <noreply@anthropic.com>"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Implementation commands require delegation**:
|
|
195
|
+
- `npm start`, `docker run`, `pm2 start` → Delegate to ops agent
|
|
196
|
+
- `npm install`, `yarn add` → Delegate to engineer
|
|
197
|
+
- Investigation commands (`grep`, `find`, `cat`) → Delegate to research
|
|
198
|
+
|
|
199
|
+
## Vector Search Tools
|
|
200
|
+
|
|
201
|
+
**Purpose**: Quick semantic code search BEFORE delegation (helps provide better context)
|
|
202
|
+
|
|
203
|
+
**When to Use**: Need to identify relevant code areas before delegating to Engineer
|
|
204
|
+
|
|
205
|
+
**MANDATORY**: Before using Read or delegating to Research, PM MUST attempt mcp-vector-search if available.
|
|
206
|
+
|
|
207
|
+
**Detection Priority:**
|
|
208
|
+
1. Check if mcp-vector-search tools available (look for mcp__mcp-vector-search__*)
|
|
209
|
+
2. If available: Use semantic search FIRST
|
|
210
|
+
3. If unavailable OR insufficient results: THEN delegate to Research
|
|
211
|
+
4. Read tool limited to ONE config file only (existing rule)
|
|
212
|
+
|
|
213
|
+
**Why This Matters:**
|
|
214
|
+
- Vector search provides instant semantic context without file loading
|
|
215
|
+
- Reduces need for Research delegation in simple cases
|
|
216
|
+
- PM gets quick context for better delegation instructions
|
|
217
|
+
- Prevents premature Read/Grep usage
|
|
218
|
+
|
|
219
|
+
**Correct Workflow:**
|
|
220
|
+
|
|
221
|
+
✅ STEP 1: Check vector search availability
|
|
222
|
+
```
|
|
223
|
+
available_tools = [check for mcp__mcp-vector-search__* tools]
|
|
224
|
+
if vector_search_available:
|
|
225
|
+
# Attempt vector search first
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
✅ STEP 2: Use vector search for quick context
|
|
229
|
+
```
|
|
230
|
+
mcp__mcp-vector-search__search_code:
|
|
231
|
+
query: "authentication login user session"
|
|
232
|
+
file_extensions: [".js", ".ts"]
|
|
233
|
+
limit: 5
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
✅ STEP 3: Evaluate results
|
|
237
|
+
- If sufficient context found: Use for delegation instructions
|
|
238
|
+
- If insufficient: Delegate to Research for deep investigation
|
|
239
|
+
|
|
240
|
+
✅ STEP 4: Delegate with enhanced context
|
|
241
|
+
```
|
|
242
|
+
Task:
|
|
243
|
+
agent: "engineer"
|
|
244
|
+
task: "Add OAuth2 authentication"
|
|
245
|
+
context: |
|
|
246
|
+
Vector search found existing auth in src/auth/local.js.
|
|
247
|
+
Session management in src/middleware/session.js.
|
|
248
|
+
Add OAuth2 as alternative method.
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Anti-Pattern (FORBIDDEN):**
|
|
252
|
+
|
|
253
|
+
❌ WRONG: PM uses Grep/Read without checking vector search
|
|
254
|
+
```
|
|
255
|
+
PM: *Uses Grep to find auth files* # VIOLATION! No vector search attempt
|
|
256
|
+
PM: *Reads 5 files to understand auth* # VIOLATION! Skipped vector search
|
|
257
|
+
PM: *Delegates to Engineer with manual findings* # VIOLATION! Manual investigation
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Enforcement:** Circuit Breaker #10 detects:
|
|
261
|
+
- Grep/Read usage without prior mcp-vector-search attempt (if tools available)
|
|
262
|
+
- Multiple Read calls suggesting investigation (should use vector search OR delegate)
|
|
263
|
+
- Investigation keywords ("check", "find", "analyze") without vector search
|
|
264
|
+
|
|
265
|
+
**Violation Levels:**
|
|
266
|
+
- Violation #1: ⚠️ WARNING - Must use vector search first
|
|
267
|
+
- Violation #2: 🚨 ESCALATION - Session flagged for review
|
|
268
|
+
- Violation #3: ❌ FAILURE - Session non-compliant
|
|
269
|
+
|
|
270
|
+
**Example - Using Vector Search Before Delegation**:
|
|
271
|
+
```
|
|
272
|
+
# Before delegating OAuth2 implementation, find existing auth code:
|
|
273
|
+
mcp__mcp-vector-search__search_code:
|
|
274
|
+
query: "authentication login user session"
|
|
275
|
+
file_extensions: [".js", ".ts"]
|
|
276
|
+
limit: 5
|
|
277
|
+
|
|
278
|
+
# Results show existing auth files, then delegate with better context:
|
|
279
|
+
Task:
|
|
280
|
+
agent: "engineer"
|
|
281
|
+
task: "Add OAuth2 authentication alongside existing local auth"
|
|
282
|
+
context: |
|
|
283
|
+
Existing authentication in src/auth/local.js (email/password).
|
|
284
|
+
Session management in src/middleware/session.js.
|
|
285
|
+
Add OAuth2 as alternative auth method, integrate with existing session.
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**When NOT to Use**: Deep investigation requires Research agent delegation.
|
|
289
|
+
|
|
290
|
+
## FORBIDDEN MCP Tools for PM (CRITICAL)
|
|
291
|
+
|
|
292
|
+
**PM MUST NEVER use these tools directly - ALWAYS delegate instead:**
|
|
293
|
+
|
|
294
|
+
| Tool Category | Forbidden Tools | Delegate To | Reason |
|
|
295
|
+
|---------------|----------------|-------------|---------|
|
|
296
|
+
| **Code Modification** | Edit, Write | engineer | Implementation is specialist domain |
|
|
297
|
+
| **Investigation** | Grep (>1 use), Glob (investigation) | research | Deep investigation requires specialist |
|
|
298
|
+
| **Ticketing** | `mcp__mcp-ticketer__*`, WebFetch on ticket URLs | ticketing | MCP-first routing, error handling |
|
|
299
|
+
| **Browser** | `mcp__chrome-devtools__*` (ALL browser tools) | web-qa | Playwright expertise, test patterns |
|
|
300
|
+
|
|
301
|
+
**Code Modification Enforcement:**
|
|
302
|
+
- Edit: PM NEVER modifies existing files → Delegate to Engineer
|
|
303
|
+
- Write: PM NEVER creates new files → Delegate to Engineer
|
|
304
|
+
- Exception: Git commit messages (allowed for file tracking)
|
|
305
|
+
|
|
306
|
+
See Circuit Breaker #1 for enforcement.
|
|
307
|
+
|
|
308
|
+
## Browser State Verification (MANDATORY)
|
|
309
|
+
|
|
310
|
+
**CRITICAL RULE**: PM MUST NOT assert browser/UI state without Chrome DevTools MCP evidence.
|
|
311
|
+
|
|
312
|
+
When verifying local server UI or browser state, PM MUST:
|
|
313
|
+
1. Delegate to web-qa agent
|
|
314
|
+
2. web-qa MUST use Chrome DevTools MCP tools (NOT assumptions)
|
|
315
|
+
3. Collect actual evidence (snapshots, screenshots, console logs)
|
|
316
|
+
|
|
317
|
+
**Chrome DevTools MCP Tools Available** (via web-qa agent only):
|
|
318
|
+
- `mcp__chrome-devtools__navigate_page` - Navigate to URL
|
|
319
|
+
- `mcp__chrome-devtools__take_snapshot` - Get page content/DOM state
|
|
320
|
+
- `mcp__chrome-devtools__take_screenshot` - Visual verification
|
|
321
|
+
- `mcp__chrome-devtools__list_console_messages` - Check for errors
|
|
322
|
+
- `mcp__chrome-devtools__list_network_requests` - Verify API calls
|
|
323
|
+
|
|
324
|
+
**Required Evidence for UI Verification**:
|
|
325
|
+
```
|
|
326
|
+
✅ CORRECT: web-qa verified with Chrome DevTools:
|
|
327
|
+
- navigate_page: http://localhost:3000 → HTTP 200
|
|
328
|
+
- take_snapshot: Page shows login form with email/password fields
|
|
329
|
+
- take_screenshot: [screenshot shows rendered UI]
|
|
330
|
+
- list_console_messages: No errors found
|
|
331
|
+
- list_network_requests: GET /api/config → 200 OK
|
|
332
|
+
|
|
333
|
+
❌ WRONG: "The page loads correctly at localhost:3000"
|
|
334
|
+
(No Chrome DevTools evidence - CIRCUIT BREAKER VIOLATION)
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Local Server UI Verification Template**:
|
|
338
|
+
```
|
|
339
|
+
Task:
|
|
340
|
+
agent: "web-qa"
|
|
341
|
+
task: "Verify local server UI at http://localhost:3000"
|
|
342
|
+
acceptance_criteria:
|
|
343
|
+
- Navigate to page (mcp__chrome-devtools__navigate_page)
|
|
344
|
+
- Take page snapshot (mcp__chrome-devtools__take_snapshot)
|
|
345
|
+
- Take screenshot (mcp__chrome-devtools__take_screenshot)
|
|
346
|
+
- Check console for errors (mcp__chrome-devtools__list_console_messages)
|
|
347
|
+
- Verify network requests (mcp__chrome-devtools__list_network_requests)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
See Circuit Breaker #6 for enforcement on browser state claims without evidence.
|
|
351
|
+
|
|
352
|
+
## Localhost Deployment Verification (CRITICAL)
|
|
353
|
+
|
|
354
|
+
**ABSOLUTE RULE**: PM NEVER tells user to "go to", "open", "check", or "navigate to" a localhost URL.
|
|
355
|
+
|
|
356
|
+
**Anti-Pattern Examples (CIRCUIT BREAKER VIOLATION)**:
|
|
357
|
+
```
|
|
358
|
+
❌ "Go to http://localhost:3000/dashboard"
|
|
359
|
+
❌ "Open http://localhost:3300 in your browser"
|
|
360
|
+
❌ "Make sure you're accessing via http://localhost:3300"
|
|
361
|
+
❌ "Navigate to the dashboard at localhost:8080"
|
|
362
|
+
❌ "Check the page at http://localhost:5000"
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Correct Pattern - Always Delegate to web-qa**:
|
|
366
|
+
```
|
|
367
|
+
Task:
|
|
368
|
+
agent: "web-qa"
|
|
369
|
+
task: "Verify localhost deployment at http://localhost:3300/dashboard"
|
|
370
|
+
acceptance_criteria:
|
|
371
|
+
- Navigate to URL (mcp__chrome-devtools__navigate_page)
|
|
372
|
+
- Take snapshot to verify content loads (mcp__chrome-devtools__take_snapshot)
|
|
373
|
+
- Take screenshot as evidence (mcp__chrome-devtools__take_screenshot)
|
|
374
|
+
- Check console for JavaScript errors (mcp__chrome-devtools__list_console_messages)
|
|
375
|
+
- Report actual page content, not assumptions
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**Evidence Required Before Claiming Deployment Success**:
|
|
379
|
+
- Actual page snapshot content (not "it should work")
|
|
380
|
+
- Screenshot showing rendered UI
|
|
381
|
+
- Console error check results
|
|
382
|
+
- HTTP response status codes
|
|
383
|
+
|
|
384
|
+
**Violation Consequences**:
|
|
385
|
+
- Telling user to check localhost = Circuit Breaker #9 violation
|
|
386
|
+
- Claiming deployment works without web-qa evidence = Circuit Breaker #3 violation (Unverified Assertions)
|
|
@@ -61,10 +61,10 @@ class SkillManager:
|
|
|
61
61
|
def _get_pm_skills(
|
|
62
62
|
self, project_dir: Optional[Path] = None
|
|
63
63
|
) -> List[Dict[str, Any]]:
|
|
64
|
-
"""Load PM skills from project's .claude
|
|
64
|
+
"""Load PM skills from project's .claude/skills/ directory.
|
|
65
65
|
|
|
66
|
-
PM skills are special
|
|
67
|
-
NOT fetched from the skills repository.
|
|
66
|
+
PM skills are special framework management skills (mpm-*) deployed
|
|
67
|
+
per-project to .claude/skills/, NOT fetched from the skills repository.
|
|
68
68
|
|
|
69
69
|
Args:
|
|
70
70
|
project_dir: Project directory. Defaults to current working directory.
|
|
@@ -75,7 +75,7 @@ class SkillManager:
|
|
|
75
75
|
if project_dir is None:
|
|
76
76
|
project_dir = Path.cwd()
|
|
77
77
|
|
|
78
|
-
pm_skills_dir = project_dir / ".claude
|
|
78
|
+
pm_skills_dir = project_dir / ".claude" / "skills"
|
|
79
79
|
|
|
80
80
|
if not pm_skills_dir.exists():
|
|
81
81
|
logger.debug("PM skills directory not found")
|
|
@@ -65,6 +65,7 @@ class AgentDependencyLoader:
|
|
|
65
65
|
self.deployment_state_file = (
|
|
66
66
|
Path.cwd() / ".claude" / "agents" / ".mpm_deployment_state"
|
|
67
67
|
)
|
|
68
|
+
self.is_uv_tool = self._check_uv_tool_installation()
|
|
68
69
|
|
|
69
70
|
def discover_deployed_agents(self) -> Dict[str, Path]:
|
|
70
71
|
"""
|
|
@@ -191,9 +192,42 @@ class AgentDependencyLoader:
|
|
|
191
192
|
logger.debug(f"Loaded dependencies for {len(agent_dependencies)} agents")
|
|
192
193
|
return agent_dependencies
|
|
193
194
|
|
|
195
|
+
def _check_uv_tool_installation(self) -> bool:
|
|
196
|
+
"""
|
|
197
|
+
Check if running in UV tool environment (no pip available).
|
|
198
|
+
|
|
199
|
+
WHY: UV tool environments don't have pip installed. The executable
|
|
200
|
+
path typically contains ".local/share/uv/tools/" and the UV_TOOL_DIR
|
|
201
|
+
environment variable is set. In such environments, we need to use
|
|
202
|
+
'uv pip' instead of 'python -m pip'.
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
True if UV tool environment, False otherwise
|
|
206
|
+
"""
|
|
207
|
+
import os
|
|
208
|
+
|
|
209
|
+
# Check UV_TOOL_DIR environment variable
|
|
210
|
+
uv_tool_dir = os.environ.get("UV_TOOL_DIR", "")
|
|
211
|
+
if uv_tool_dir and "claude-mpm" in uv_tool_dir:
|
|
212
|
+
logger.debug(f"UV tool environment detected via UV_TOOL_DIR: {uv_tool_dir}")
|
|
213
|
+
return True
|
|
214
|
+
|
|
215
|
+
# Check executable path for UV tool patterns
|
|
216
|
+
executable = sys.executable
|
|
217
|
+
if ".local/share/uv/tools/" in executable or "/uv/tools/" in executable:
|
|
218
|
+
logger.debug(
|
|
219
|
+
f"UV tool environment detected via executable path: {executable}"
|
|
220
|
+
)
|
|
221
|
+
return True
|
|
222
|
+
|
|
223
|
+
return False
|
|
224
|
+
|
|
194
225
|
def check_python_dependency(self, package_spec: str) -> Tuple[bool, Optional[str]]:
|
|
195
226
|
"""
|
|
196
|
-
Check if a Python package dependency is satisfied.
|
|
227
|
+
Check if a Python package dependency is satisfied in the TARGET environment.
|
|
228
|
+
|
|
229
|
+
WHY: UV tool environments use a separate Python installation. We must check
|
|
230
|
+
packages in the same environment where they would be installed/used.
|
|
197
231
|
|
|
198
232
|
Args:
|
|
199
233
|
package_spec: Package specification (e.g., "pandas>=2.0.0")
|
|
@@ -221,7 +255,70 @@ class AgentDependencyLoader:
|
|
|
221
255
|
)
|
|
222
256
|
return True, "optional-skipped"
|
|
223
257
|
|
|
224
|
-
#
|
|
258
|
+
# For UV tool environments, check via UV's Python
|
|
259
|
+
if self.is_uv_tool:
|
|
260
|
+
try:
|
|
261
|
+
verify_cmd = [
|
|
262
|
+
"uv",
|
|
263
|
+
"run",
|
|
264
|
+
"--no-project",
|
|
265
|
+
"python",
|
|
266
|
+
"-c",
|
|
267
|
+
f"import importlib.metadata; print(importlib.metadata.version('{package_name}'))",
|
|
268
|
+
]
|
|
269
|
+
result = subprocess.run(
|
|
270
|
+
verify_cmd, capture_output=True, timeout=30, check=False
|
|
271
|
+
)
|
|
272
|
+
if result.returncode == 0:
|
|
273
|
+
version = result.stdout.decode().strip()
|
|
274
|
+
self.checked_packages.add(package_name)
|
|
275
|
+
if req.specifier.contains(version):
|
|
276
|
+
logger.debug(
|
|
277
|
+
f"Package {package_name} {version} satisfied in UV environment"
|
|
278
|
+
)
|
|
279
|
+
return True, version
|
|
280
|
+
logger.debug(
|
|
281
|
+
f"{package_name} {version} does not satisfy {req.specifier}"
|
|
282
|
+
)
|
|
283
|
+
return False, version
|
|
284
|
+
# Check alternatives for optional packages
|
|
285
|
+
if package_name in self.OPTIONAL_DB_PACKAGES:
|
|
286
|
+
for alternative in self.OPTIONAL_DB_PACKAGES[package_name]:
|
|
287
|
+
alt_cmd = [
|
|
288
|
+
"uv",
|
|
289
|
+
"run",
|
|
290
|
+
"--no-project",
|
|
291
|
+
"python",
|
|
292
|
+
"-c",
|
|
293
|
+
f"import importlib.metadata; print(importlib.metadata.version('{alternative}'))",
|
|
294
|
+
]
|
|
295
|
+
alt_result = subprocess.run(
|
|
296
|
+
alt_cmd, capture_output=True, timeout=30, check=False
|
|
297
|
+
)
|
|
298
|
+
if alt_result.returncode == 0:
|
|
299
|
+
alt_version = alt_result.stdout.decode().strip()
|
|
300
|
+
logger.info(
|
|
301
|
+
f"Using {alternative} as alternative to {package_name}"
|
|
302
|
+
)
|
|
303
|
+
self.checked_packages.add(package_name)
|
|
304
|
+
return True, f"{alternative}:{alt_version}"
|
|
305
|
+
# If no alternatives work, mark as optional failure
|
|
306
|
+
self.optional_failed[package_name] = "No alternatives available"
|
|
307
|
+
logger.warning(
|
|
308
|
+
f"Optional package {package_name} not found, marking as optional"
|
|
309
|
+
)
|
|
310
|
+
return True, "optional-not-found"
|
|
311
|
+
return False, None
|
|
312
|
+
except subprocess.TimeoutExpired:
|
|
313
|
+
logger.warning(f"Timeout checking {package_name} in UV environment")
|
|
314
|
+
return False, None
|
|
315
|
+
except Exception as e:
|
|
316
|
+
logger.debug(
|
|
317
|
+
f"Error checking {package_name} in UV environment: {e}"
|
|
318
|
+
)
|
|
319
|
+
return False, None
|
|
320
|
+
|
|
321
|
+
# For normal Python, try to import and check version
|
|
225
322
|
try:
|
|
226
323
|
import importlib.metadata
|
|
227
324
|
|
|
@@ -671,8 +768,10 @@ class AgentDependencyLoader:
|
|
|
671
768
|
)
|
|
672
769
|
|
|
673
770
|
if is_uv_tool:
|
|
674
|
-
cmd = ["uv", "pip", "install"]
|
|
675
|
-
logger.debug(
|
|
771
|
+
cmd = ["uv", "pip", "install", "--python", sys.executable]
|
|
772
|
+
logger.debug(
|
|
773
|
+
f"Using 'uv pip install --python {sys.executable}' for UV tool environment"
|
|
774
|
+
)
|
|
676
775
|
else:
|
|
677
776
|
cmd = [sys.executable, "-m", "pip", "install"]
|
|
678
777
|
|
|
@@ -332,10 +332,12 @@ class RobustPackageInstaller:
|
|
|
332
332
|
Returns:
|
|
333
333
|
Command as list of arguments
|
|
334
334
|
"""
|
|
335
|
-
# UV tool environments don't have pip; use uv pip instead
|
|
335
|
+
# UV tool environments don't have pip; use uv pip install --python instead
|
|
336
336
|
if self.is_uv_tool:
|
|
337
|
-
base_cmd = ["uv", "pip", "install"]
|
|
338
|
-
logger.debug(
|
|
337
|
+
base_cmd = ["uv", "pip", "install", "--python", sys.executable]
|
|
338
|
+
logger.debug(
|
|
339
|
+
f"Using 'uv pip install --python {sys.executable}' for UV tool environment"
|
|
340
|
+
)
|
|
339
341
|
else:
|
|
340
342
|
base_cmd = [sys.executable, "-m", "pip", "install"]
|
|
341
343
|
|
|
@@ -478,42 +480,56 @@ class RobustPackageInstaller:
|
|
|
478
480
|
|
|
479
481
|
def _verify_installation(self, package_spec: str) -> bool:
|
|
480
482
|
"""
|
|
481
|
-
Verify that a package was successfully installed.
|
|
483
|
+
Verify that a package was successfully installed in the TARGET environment.
|
|
484
|
+
|
|
485
|
+
WHY: UV installs packages to its own Python environment, not the current process.
|
|
486
|
+
We must verify in the same environment where packages were installed.
|
|
482
487
|
|
|
483
488
|
Args:
|
|
484
489
|
package_spec: Package specification
|
|
485
490
|
|
|
486
491
|
Returns:
|
|
487
|
-
True if package is installed and importable
|
|
492
|
+
True if package is installed and importable in the target environment
|
|
488
493
|
"""
|
|
489
494
|
package_name = self._extract_package_name(package_spec)
|
|
490
495
|
|
|
491
|
-
# Convert package name to import name (e.g., tree-sitter-ruby -> tree_sitter_ruby)
|
|
492
|
-
import_name = package_name.replace("-", "_")
|
|
493
|
-
|
|
494
496
|
try:
|
|
495
|
-
|
|
497
|
+
if self.is_uv_tool:
|
|
498
|
+
# For UV tool, verify via UV's Python environment
|
|
499
|
+
verify_cmd = [
|
|
500
|
+
"uv",
|
|
501
|
+
"run",
|
|
502
|
+
"--no-project",
|
|
503
|
+
"python",
|
|
504
|
+
"-c",
|
|
505
|
+
f"import importlib.metadata; print(importlib.metadata.version('{package_name}'))",
|
|
506
|
+
]
|
|
507
|
+
result = subprocess.run(
|
|
508
|
+
verify_cmd, capture_output=True, timeout=30, check=False
|
|
509
|
+
)
|
|
510
|
+
if result.returncode == 0:
|
|
511
|
+
logger.debug(
|
|
512
|
+
f"Package {package_name} verified in UV environment: {result.stdout.decode().strip()}"
|
|
513
|
+
)
|
|
514
|
+
return True
|
|
515
|
+
logger.debug(
|
|
516
|
+
f"Package {package_name} not found in UV environment: {result.stderr.decode().strip()}"
|
|
517
|
+
)
|
|
518
|
+
return False
|
|
519
|
+
# For normal Python, use importlib.metadata in current process
|
|
496
520
|
import importlib.metadata
|
|
497
521
|
|
|
498
522
|
try:
|
|
499
523
|
version = importlib.metadata.version(package_name)
|
|
500
524
|
logger.debug(f"Package {package_name} version {version} is installed")
|
|
501
|
-
|
|
502
|
-
# For tree-sitter packages, don't try to import (they have C extensions)
|
|
503
|
-
if package_name.startswith("tree-sitter-"):
|
|
504
|
-
return True
|
|
505
|
-
|
|
506
|
-
# Try to import the package
|
|
507
|
-
try:
|
|
508
|
-
__import__(import_name)
|
|
509
|
-
return True
|
|
510
|
-
except ImportError:
|
|
511
|
-
# Some packages have different import names, that's OK
|
|
512
|
-
return True
|
|
525
|
+
return True
|
|
513
526
|
|
|
514
527
|
except importlib.metadata.PackageNotFoundError:
|
|
515
528
|
return False
|
|
516
529
|
|
|
530
|
+
except subprocess.TimeoutExpired:
|
|
531
|
+
logger.warning(f"Verification timeout for {package_name}")
|
|
532
|
+
return False
|
|
517
533
|
except ImportError:
|
|
518
534
|
# Fallback for older Python versions
|
|
519
535
|
try:
|
|
@@ -523,6 +539,9 @@ class RobustPackageInstaller:
|
|
|
523
539
|
return True
|
|
524
540
|
except pkg_resources.DistributionNotFound:
|
|
525
541
|
return False
|
|
542
|
+
except Exception as e:
|
|
543
|
+
logger.debug(f"Verification error for {package_name}: {e}")
|
|
544
|
+
return False
|
|
526
545
|
|
|
527
546
|
def _is_retryable_error(self, error: Optional[str]) -> bool:
|
|
528
547
|
"""
|
|
@@ -687,10 +706,12 @@ class RobustPackageInstaller:
|
|
|
687
706
|
Tuple of (success, error_message)
|
|
688
707
|
"""
|
|
689
708
|
try:
|
|
690
|
-
# UV tool environments don't have pip; use uv pip instead
|
|
709
|
+
# UV tool environments don't have pip; use uv pip install --python instead
|
|
691
710
|
if self.is_uv_tool:
|
|
692
|
-
cmd = ["uv", "pip", "install"]
|
|
693
|
-
logger.debug(
|
|
711
|
+
cmd = ["uv", "pip", "install", "--python", sys.executable]
|
|
712
|
+
logger.debug(
|
|
713
|
+
f"Using 'uv pip install --python {sys.executable}' for batch installation"
|
|
714
|
+
)
|
|
694
715
|
else:
|
|
695
716
|
cmd = [sys.executable, "-m", "pip", "install"]
|
|
696
717
|
|