claude-mpm 4.4.0__py3-none-any.whl → 4.4.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/WORKFLOW.md +2 -14
- claude_mpm/agents/agent_loader.py +3 -2
- claude_mpm/agents/agent_loader_integration.py +2 -1
- claude_mpm/agents/async_agent_loader.py +2 -2
- claude_mpm/agents/base_agent_loader.py +2 -2
- claude_mpm/agents/frontmatter_validator.py +1 -0
- claude_mpm/agents/system_agent_config.py +2 -1
- claude_mpm/cli/commands/configure.py +2 -29
- claude_mpm/cli/commands/doctor.py +44 -5
- claude_mpm/cli/commands/mpm_init.py +117 -63
- claude_mpm/cli/parsers/configure_parser.py +6 -15
- claude_mpm/cli/startup_logging.py +1 -3
- claude_mpm/config/agent_config.py +1 -1
- claude_mpm/config/paths.py +2 -1
- claude_mpm/core/agent_name_normalizer.py +1 -0
- claude_mpm/core/config.py +2 -1
- claude_mpm/core/config_aliases.py +2 -1
- claude_mpm/core/file_utils.py +0 -1
- claude_mpm/core/framework/__init__.py +38 -0
- claude_mpm/core/framework/formatters/__init__.py +11 -0
- claude_mpm/core/framework/formatters/capability_generator.py +367 -0
- claude_mpm/core/framework/formatters/content_formatter.py +288 -0
- claude_mpm/core/framework/formatters/context_generator.py +184 -0
- claude_mpm/core/framework/loaders/__init__.py +13 -0
- claude_mpm/core/framework/loaders/agent_loader.py +206 -0
- claude_mpm/core/framework/loaders/file_loader.py +223 -0
- claude_mpm/core/framework/loaders/instruction_loader.py +161 -0
- claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
- claude_mpm/core/framework/processors/__init__.py +11 -0
- claude_mpm/core/framework/processors/memory_processor.py +230 -0
- claude_mpm/core/framework/processors/metadata_processor.py +146 -0
- claude_mpm/core/framework/processors/template_processor.py +244 -0
- claude_mpm/core/framework_loader.py +298 -1795
- claude_mpm/core/log_manager.py +2 -1
- claude_mpm/core/tool_access_control.py +1 -0
- claude_mpm/core/unified_agent_registry.py +2 -1
- claude_mpm/core/unified_paths.py +1 -0
- claude_mpm/experimental/cli_enhancements.py +1 -0
- claude_mpm/hooks/__init__.py +9 -1
- claude_mpm/hooks/base_hook.py +1 -0
- claude_mpm/hooks/instruction_reinforcement.py +1 -0
- claude_mpm/hooks/kuzu_memory_hook.py +359 -0
- claude_mpm/hooks/validation_hooks.py +1 -1
- claude_mpm/scripts/mpm_doctor.py +1 -0
- claude_mpm/services/agents/loading/agent_profile_loader.py +1 -1
- claude_mpm/services/agents/loading/base_agent_manager.py +1 -1
- claude_mpm/services/agents/loading/framework_agent_loader.py +1 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -0
- claude_mpm/services/agents/management/agent_management_service.py +1 -1
- claude_mpm/services/agents/memory/memory_categorization_service.py +0 -1
- claude_mpm/services/agents/memory/memory_file_service.py +6 -2
- claude_mpm/services/agents/memory/memory_format_service.py +0 -1
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +1 -1
- claude_mpm/services/async_session_logger.py +1 -1
- claude_mpm/services/claude_session_logger.py +1 -0
- claude_mpm/services/core/path_resolver.py +2 -0
- claude_mpm/services/diagnostics/checks/__init__.py +2 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +126 -25
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +399 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +4 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +259 -32
- claude_mpm/services/event_bus/direct_relay.py +2 -1
- claude_mpm/services/event_bus/event_bus.py +1 -0
- claude_mpm/services/event_bus/relay.py +3 -2
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +1 -1
- claude_mpm/services/infrastructure/daemon_manager.py +1 -1
- claude_mpm/services/mcp_config_manager.py +67 -4
- claude_mpm/services/mcp_gateway/core/process_pool.py +320 -0
- claude_mpm/services/mcp_gateway/core/startup_verification.py +2 -2
- claude_mpm/services/mcp_gateway/main.py +3 -13
- claude_mpm/services/mcp_gateway/server/stdio_server.py +4 -10
- claude_mpm/services/mcp_gateway/tools/__init__.py +14 -2
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +38 -6
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +527 -0
- claude_mpm/services/memory/cache/simple_cache.py +1 -1
- claude_mpm/services/project/archive_manager.py +159 -96
- claude_mpm/services/project/documentation_manager.py +64 -45
- claude_mpm/services/project/enhanced_analyzer.py +132 -89
- claude_mpm/services/project/project_organizer.py +225 -131
- claude_mpm/services/response_tracker.py +1 -1
- claude_mpm/services/shared/__init__.py +2 -1
- claude_mpm/services/shared/service_factory.py +8 -5
- claude_mpm/services/socketio/server/eventbus_integration.py +1 -1
- claude_mpm/services/unified/__init__.py +1 -1
- claude_mpm/services/unified/analyzer_strategies/__init__.py +3 -3
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +97 -53
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +81 -40
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +277 -178
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +196 -112
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +83 -49
- claude_mpm/services/unified/config_strategies/__init__.py +175 -0
- claude_mpm/services/unified/config_strategies/config_schema.py +735 -0
- claude_mpm/services/unified/config_strategies/context_strategy.py +750 -0
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1009 -0
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +879 -0
- claude_mpm/services/unified/config_strategies/unified_config_service.py +814 -0
- claude_mpm/services/unified/config_strategies/validation_strategy.py +1144 -0
- claude_mpm/services/unified/deployment_strategies/__init__.py +7 -7
- claude_mpm/services/unified/deployment_strategies/base.py +24 -28
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +168 -88
- claude_mpm/services/unified/deployment_strategies/local.py +49 -34
- claude_mpm/services/unified/deployment_strategies/utils.py +39 -43
- claude_mpm/services/unified/deployment_strategies/vercel.py +30 -24
- claude_mpm/services/unified/interfaces.py +0 -26
- claude_mpm/services/unified/migration.py +17 -40
- claude_mpm/services/unified/strategies.py +9 -26
- claude_mpm/services/unified/unified_analyzer.py +48 -44
- claude_mpm/services/unified/unified_config.py +21 -19
- claude_mpm/services/unified/unified_deployment.py +21 -26
- claude_mpm/storage/state_storage.py +1 -0
- claude_mpm/utils/agent_dependency_loader.py +18 -6
- claude_mpm/utils/common.py +14 -12
- claude_mpm/utils/database_connector.py +15 -12
- claude_mpm/utils/error_handler.py +1 -0
- claude_mpm/utils/log_cleanup.py +1 -0
- claude_mpm/utils/path_operations.py +1 -0
- claude_mpm/utils/session_logging.py +1 -1
- claude_mpm/utils/subprocess_utils.py +1 -0
- claude_mpm/validation/agent_validator.py +1 -1
- {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/METADATA +23 -17
- {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/RECORD +126 -105
- claude_mpm/cli/commands/configure_tui.py +0 -1927
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +0 -645
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +0 -602
- {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/WHEEL +0 -0
- {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/top_level.txt +0 -0
@@ -16,15 +16,15 @@ Author: Claude MPM Development Team
|
|
16
16
|
Created: 2025-01-26
|
17
17
|
"""
|
18
18
|
|
19
|
-
import json
|
20
19
|
import subprocess
|
21
20
|
from datetime import datetime, timedelta
|
22
21
|
from pathlib import Path
|
23
|
-
from typing import Dict, List, Optional
|
22
|
+
from typing import Dict, List, Optional
|
24
23
|
|
25
24
|
from rich.console import Console
|
26
25
|
|
27
26
|
from claude_mpm.core.logging_utils import get_logger
|
27
|
+
|
28
28
|
logger = get_logger(__name__)
|
29
29
|
console = Console()
|
30
30
|
|
@@ -77,12 +77,14 @@ class EnhancedProjectAnalyzer:
|
|
77
77
|
since_date = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d")
|
78
78
|
|
79
79
|
# Get commit log with structured format
|
80
|
-
output = self._run_git_command(
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
80
|
+
output = self._run_git_command(
|
81
|
+
[
|
82
|
+
"log",
|
83
|
+
f"--since={since_date}",
|
84
|
+
"--pretty=format:%H|%an|%ae|%at|%s",
|
85
|
+
"--no-merges",
|
86
|
+
]
|
87
|
+
)
|
86
88
|
|
87
89
|
if not output:
|
88
90
|
return []
|
@@ -91,13 +93,15 @@ class EnhancedProjectAnalyzer:
|
|
91
93
|
for line in output.splitlines():
|
92
94
|
parts = line.split("|", 4)
|
93
95
|
if len(parts) == 5:
|
94
|
-
commits.append(
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
96
|
+
commits.append(
|
97
|
+
{
|
98
|
+
"hash": parts[0][:8],
|
99
|
+
"author": parts[1],
|
100
|
+
"email": parts[2],
|
101
|
+
"timestamp": datetime.fromtimestamp(int(parts[3])).isoformat(),
|
102
|
+
"message": parts[4],
|
103
|
+
}
|
104
|
+
)
|
101
105
|
|
102
106
|
return commits[:50] # Limit to 50 most recent
|
103
107
|
|
@@ -105,13 +109,15 @@ class EnhancedProjectAnalyzer:
|
|
105
109
|
"""Get files changed in recent commits."""
|
106
110
|
since_date = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d")
|
107
111
|
|
108
|
-
output = self._run_git_command(
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
112
|
+
output = self._run_git_command(
|
113
|
+
[
|
114
|
+
"log",
|
115
|
+
f"--since={since_date}",
|
116
|
+
"--pretty=format:",
|
117
|
+
"--name-only",
|
118
|
+
"--no-merges",
|
119
|
+
]
|
120
|
+
)
|
115
121
|
|
116
122
|
if not output:
|
117
123
|
return {}
|
@@ -134,13 +140,15 @@ class EnhancedProjectAnalyzer:
|
|
134
140
|
"""Get files added in recent commits."""
|
135
141
|
since_date = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d")
|
136
142
|
|
137
|
-
output = self._run_git_command(
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
143
|
+
output = self._run_git_command(
|
144
|
+
[
|
145
|
+
"log",
|
146
|
+
f"--since={since_date}",
|
147
|
+
"--pretty=format:",
|
148
|
+
"--name-status",
|
149
|
+
"--diff-filter=A", # Added files only
|
150
|
+
]
|
151
|
+
)
|
144
152
|
|
145
153
|
if not output:
|
146
154
|
return []
|
@@ -156,12 +164,14 @@ class EnhancedProjectAnalyzer:
|
|
156
164
|
"""Get author contribution statistics."""
|
157
165
|
since_date = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d")
|
158
166
|
|
159
|
-
output = self._run_git_command(
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
167
|
+
output = self._run_git_command(
|
168
|
+
[
|
169
|
+
"shortlog",
|
170
|
+
"-sne",
|
171
|
+
f"--since={since_date}",
|
172
|
+
"--no-merges",
|
173
|
+
]
|
174
|
+
)
|
165
175
|
|
166
176
|
if not output:
|
167
177
|
return {}
|
@@ -201,10 +211,12 @@ class EnhancedProjectAnalyzer:
|
|
201
211
|
for line in remotes.splitlines():
|
202
212
|
parts = line.split()
|
203
213
|
if len(parts) >= 2:
|
204
|
-
info["remotes"].append(
|
205
|
-
|
206
|
-
|
207
|
-
|
214
|
+
info["remotes"].append(
|
215
|
+
{
|
216
|
+
"name": parts[0],
|
217
|
+
"url": parts[1],
|
218
|
+
}
|
219
|
+
)
|
208
220
|
|
209
221
|
# Check for uncommitted changes
|
210
222
|
status = self._run_git_command(["status", "--porcelain"])
|
@@ -223,12 +235,15 @@ class EnhancedProjectAnalyzer:
|
|
223
235
|
|
224
236
|
doc_changes = {}
|
225
237
|
for pattern in doc_patterns:
|
226
|
-
output = self._run_git_command(
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
238
|
+
output = self._run_git_command(
|
239
|
+
[
|
240
|
+
"log",
|
241
|
+
f"--since={since_date}",
|
242
|
+
"--pretty=format:%H|%s",
|
243
|
+
"--",
|
244
|
+
pattern,
|
245
|
+
]
|
246
|
+
)
|
232
247
|
|
233
248
|
if output:
|
234
249
|
for line in output.splitlines():
|
@@ -236,29 +251,38 @@ class EnhancedProjectAnalyzer:
|
|
236
251
|
if len(parts) == 2:
|
237
252
|
if pattern not in doc_changes:
|
238
253
|
doc_changes[pattern] = []
|
239
|
-
doc_changes[pattern].append(
|
240
|
-
|
241
|
-
|
242
|
-
|
254
|
+
doc_changes[pattern].append(
|
255
|
+
{
|
256
|
+
"commit": parts[0][:8],
|
257
|
+
"message": parts[1],
|
258
|
+
}
|
259
|
+
)
|
243
260
|
|
244
261
|
# Check CLAUDE.md specifically
|
245
|
-
claude_history = self._run_git_command(
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
262
|
+
claude_history = self._run_git_command(
|
263
|
+
[
|
264
|
+
"log",
|
265
|
+
f"--since={since_date}",
|
266
|
+
"--pretty=format:%H|%at|%s",
|
267
|
+
"--",
|
268
|
+
"CLAUDE.md",
|
269
|
+
]
|
270
|
+
)
|
251
271
|
|
252
272
|
claude_updates = []
|
253
273
|
if claude_history:
|
254
274
|
for line in claude_history.splitlines():
|
255
275
|
parts = line.split("|", 2)
|
256
276
|
if len(parts) == 3:
|
257
|
-
claude_updates.append(
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
277
|
+
claude_updates.append(
|
278
|
+
{
|
279
|
+
"commit": parts[0][:8],
|
280
|
+
"timestamp": datetime.fromtimestamp(
|
281
|
+
int(parts[1])
|
282
|
+
).isoformat(),
|
283
|
+
"message": parts[2],
|
284
|
+
}
|
285
|
+
)
|
262
286
|
|
263
287
|
return {
|
264
288
|
"documentation_commits": doc_changes,
|
@@ -284,7 +308,9 @@ class EnhancedProjectAnalyzer:
|
|
284
308
|
patterns["features"].append(commit["message"][:100])
|
285
309
|
elif any(kw in msg_lower for kw in ["fix", "bug", "resolve", "patch"]):
|
286
310
|
patterns["fixes"].append(commit["message"][:100])
|
287
|
-
elif any(
|
311
|
+
elif any(
|
312
|
+
kw in msg_lower for kw in ["refactor", "restructure", "reorganize"]
|
313
|
+
):
|
288
314
|
patterns["refactoring"].append(commit["message"][:100])
|
289
315
|
elif any(kw in msg_lower for kw in ["doc", "readme", "comment"]):
|
290
316
|
patterns["documentation"].append(commit["message"][:100])
|
@@ -318,12 +344,14 @@ class EnhancedProjectAnalyzer:
|
|
318
344
|
hot_spots = []
|
319
345
|
for file_path, change_count in list(changed_files["most_changed"].items())[:10]:
|
320
346
|
file_type = Path(file_path).suffix
|
321
|
-
hot_spots.append(
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
347
|
+
hot_spots.append(
|
348
|
+
{
|
349
|
+
"file": file_path,
|
350
|
+
"changes": change_count,
|
351
|
+
"type": file_type,
|
352
|
+
"category": self._categorize_file(file_path),
|
353
|
+
}
|
354
|
+
)
|
327
355
|
|
328
356
|
return hot_spots
|
329
357
|
|
@@ -334,18 +362,17 @@ class EnhancedProjectAnalyzer:
|
|
334
362
|
# Check directory
|
335
363
|
if "test" in str(path).lower():
|
336
364
|
return "test"
|
337
|
-
|
365
|
+
if "docs" in str(path).lower():
|
338
366
|
return "documentation"
|
339
|
-
|
367
|
+
if "src" in str(path) or "lib" in str(path):
|
340
368
|
return "source"
|
341
|
-
|
369
|
+
if "scripts" in str(path):
|
342
370
|
return "scripts"
|
343
|
-
|
371
|
+
if path.suffix in [".yml", ".yaml", ".json", ".toml", ".ini"]:
|
344
372
|
return "configuration"
|
345
|
-
|
373
|
+
if path.suffix in [".md", ".rst", ".txt"]:
|
346
374
|
return "documentation"
|
347
|
-
|
348
|
-
return "other"
|
375
|
+
return "other"
|
349
376
|
|
350
377
|
def detect_project_state(self) -> Dict:
|
351
378
|
"""Detect the current state and lifecycle phase of the project."""
|
@@ -371,7 +398,9 @@ class EnhancedProjectAnalyzer:
|
|
371
398
|
indicators.append("Has GitLab CI")
|
372
399
|
|
373
400
|
# Check for tests
|
374
|
-
if (self.project_path / "tests").exists() or (
|
401
|
+
if (self.project_path / "tests").exists() or (
|
402
|
+
self.project_path / "test"
|
403
|
+
).exists():
|
375
404
|
indicators.append("Has test directory")
|
376
405
|
|
377
406
|
# Check for documentation
|
@@ -391,33 +420,45 @@ class EnhancedProjectAnalyzer:
|
|
391
420
|
# Determine phase based on commit count
|
392
421
|
if count < 10:
|
393
422
|
state["phase"] = "initial"
|
394
|
-
state["recommendations"].append(
|
423
|
+
state["recommendations"].append(
|
424
|
+
"Focus on establishing core structure"
|
425
|
+
)
|
395
426
|
elif count < 50:
|
396
427
|
state["phase"] = "early_development"
|
397
|
-
state["recommendations"].append(
|
428
|
+
state["recommendations"].append(
|
429
|
+
"Consider adding tests and documentation"
|
430
|
+
)
|
398
431
|
elif count < 200:
|
399
432
|
state["phase"] = "active_development"
|
400
|
-
state["recommendations"].append(
|
433
|
+
state["recommendations"].append(
|
434
|
+
"Ensure CI/CD and testing are in place"
|
435
|
+
)
|
401
436
|
elif count < 1000:
|
402
437
|
state["phase"] = "maturing"
|
403
|
-
state["recommendations"].append(
|
438
|
+
state["recommendations"].append(
|
439
|
+
"Focus on optimization and documentation"
|
440
|
+
)
|
404
441
|
else:
|
405
442
|
state["phase"] = "mature"
|
406
443
|
state["recommendations"].append("Maintain backward compatibility")
|
407
444
|
|
408
445
|
# Check age
|
409
|
-
first_commit = self._run_git_command(
|
410
|
-
"log", "--reverse", "--format=%at", "-1"
|
411
|
-
|
446
|
+
first_commit = self._run_git_command(
|
447
|
+
["log", "--reverse", "--format=%at", "-1"]
|
448
|
+
)
|
412
449
|
if first_commit:
|
413
|
-
age_days = (
|
450
|
+
age_days = (
|
451
|
+
datetime.now() - datetime.fromtimestamp(int(first_commit))
|
452
|
+
).days
|
414
453
|
indicators.append(f"{age_days} days old")
|
415
454
|
|
416
455
|
state["indicators"] = indicators
|
417
456
|
|
418
457
|
# Add phase-specific recommendations
|
419
458
|
if not (self.project_path / "CLAUDE.md").exists():
|
420
|
-
state["recommendations"].append(
|
459
|
+
state["recommendations"].append(
|
460
|
+
"Create CLAUDE.md for AI agent documentation"
|
461
|
+
)
|
421
462
|
if not (self.project_path / "tests").exists():
|
422
463
|
state["recommendations"].append("Add tests directory for test organization")
|
423
464
|
if not (self.project_path / ".gitignore").exists():
|
@@ -474,10 +515,12 @@ class EnhancedProjectAnalyzer:
|
|
474
515
|
try:
|
475
516
|
size = path.stat().st_size
|
476
517
|
if size > 1024 * 1024: # Files over 1MB
|
477
|
-
stats["largest_files"].append(
|
478
|
-
|
479
|
-
|
480
|
-
|
518
|
+
stats["largest_files"].append(
|
519
|
+
{
|
520
|
+
"path": str(path.relative_to(self.project_path)),
|
521
|
+
"size_mb": round(size / (1024 * 1024), 2),
|
522
|
+
}
|
523
|
+
)
|
481
524
|
except (OSError, PermissionError):
|
482
525
|
pass
|
483
526
|
|
@@ -488,4 +531,4 @@ class EnhancedProjectAnalyzer:
|
|
488
531
|
stats["largest_files"].sort(key=lambda x: x["size_mb"], reverse=True)
|
489
532
|
stats["largest_files"] = stats["largest_files"][:10] # Top 10
|
490
533
|
|
491
|
-
return stats
|
534
|
+
return stats
|