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.
Files changed (129) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/WORKFLOW.md +2 -14
  3. claude_mpm/agents/agent_loader.py +3 -2
  4. claude_mpm/agents/agent_loader_integration.py +2 -1
  5. claude_mpm/agents/async_agent_loader.py +2 -2
  6. claude_mpm/agents/base_agent_loader.py +2 -2
  7. claude_mpm/agents/frontmatter_validator.py +1 -0
  8. claude_mpm/agents/system_agent_config.py +2 -1
  9. claude_mpm/cli/commands/configure.py +2 -29
  10. claude_mpm/cli/commands/doctor.py +44 -5
  11. claude_mpm/cli/commands/mpm_init.py +117 -63
  12. claude_mpm/cli/parsers/configure_parser.py +6 -15
  13. claude_mpm/cli/startup_logging.py +1 -3
  14. claude_mpm/config/agent_config.py +1 -1
  15. claude_mpm/config/paths.py +2 -1
  16. claude_mpm/core/agent_name_normalizer.py +1 -0
  17. claude_mpm/core/config.py +2 -1
  18. claude_mpm/core/config_aliases.py +2 -1
  19. claude_mpm/core/file_utils.py +0 -1
  20. claude_mpm/core/framework/__init__.py +38 -0
  21. claude_mpm/core/framework/formatters/__init__.py +11 -0
  22. claude_mpm/core/framework/formatters/capability_generator.py +367 -0
  23. claude_mpm/core/framework/formatters/content_formatter.py +288 -0
  24. claude_mpm/core/framework/formatters/context_generator.py +184 -0
  25. claude_mpm/core/framework/loaders/__init__.py +13 -0
  26. claude_mpm/core/framework/loaders/agent_loader.py +206 -0
  27. claude_mpm/core/framework/loaders/file_loader.py +223 -0
  28. claude_mpm/core/framework/loaders/instruction_loader.py +161 -0
  29. claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
  30. claude_mpm/core/framework/processors/__init__.py +11 -0
  31. claude_mpm/core/framework/processors/memory_processor.py +230 -0
  32. claude_mpm/core/framework/processors/metadata_processor.py +146 -0
  33. claude_mpm/core/framework/processors/template_processor.py +244 -0
  34. claude_mpm/core/framework_loader.py +298 -1795
  35. claude_mpm/core/log_manager.py +2 -1
  36. claude_mpm/core/tool_access_control.py +1 -0
  37. claude_mpm/core/unified_agent_registry.py +2 -1
  38. claude_mpm/core/unified_paths.py +1 -0
  39. claude_mpm/experimental/cli_enhancements.py +1 -0
  40. claude_mpm/hooks/__init__.py +9 -1
  41. claude_mpm/hooks/base_hook.py +1 -0
  42. claude_mpm/hooks/instruction_reinforcement.py +1 -0
  43. claude_mpm/hooks/kuzu_memory_hook.py +359 -0
  44. claude_mpm/hooks/validation_hooks.py +1 -1
  45. claude_mpm/scripts/mpm_doctor.py +1 -0
  46. claude_mpm/services/agents/loading/agent_profile_loader.py +1 -1
  47. claude_mpm/services/agents/loading/base_agent_manager.py +1 -1
  48. claude_mpm/services/agents/loading/framework_agent_loader.py +1 -1
  49. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -0
  50. claude_mpm/services/agents/management/agent_management_service.py +1 -1
  51. claude_mpm/services/agents/memory/memory_categorization_service.py +0 -1
  52. claude_mpm/services/agents/memory/memory_file_service.py +6 -2
  53. claude_mpm/services/agents/memory/memory_format_service.py +0 -1
  54. claude_mpm/services/agents/registry/deployed_agent_discovery.py +1 -1
  55. claude_mpm/services/async_session_logger.py +1 -1
  56. claude_mpm/services/claude_session_logger.py +1 -0
  57. claude_mpm/services/core/path_resolver.py +2 -0
  58. claude_mpm/services/diagnostics/checks/__init__.py +2 -0
  59. claude_mpm/services/diagnostics/checks/installation_check.py +126 -25
  60. claude_mpm/services/diagnostics/checks/mcp_services_check.py +399 -0
  61. claude_mpm/services/diagnostics/diagnostic_runner.py +4 -0
  62. claude_mpm/services/diagnostics/doctor_reporter.py +259 -32
  63. claude_mpm/services/event_bus/direct_relay.py +2 -1
  64. claude_mpm/services/event_bus/event_bus.py +1 -0
  65. claude_mpm/services/event_bus/relay.py +3 -2
  66. claude_mpm/services/framework_claude_md_generator/content_assembler.py +1 -1
  67. claude_mpm/services/infrastructure/daemon_manager.py +1 -1
  68. claude_mpm/services/mcp_config_manager.py +67 -4
  69. claude_mpm/services/mcp_gateway/core/process_pool.py +320 -0
  70. claude_mpm/services/mcp_gateway/core/startup_verification.py +2 -2
  71. claude_mpm/services/mcp_gateway/main.py +3 -13
  72. claude_mpm/services/mcp_gateway/server/stdio_server.py +4 -10
  73. claude_mpm/services/mcp_gateway/tools/__init__.py +14 -2
  74. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +38 -6
  75. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +527 -0
  76. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  77. claude_mpm/services/project/archive_manager.py +159 -96
  78. claude_mpm/services/project/documentation_manager.py +64 -45
  79. claude_mpm/services/project/enhanced_analyzer.py +132 -89
  80. claude_mpm/services/project/project_organizer.py +225 -131
  81. claude_mpm/services/response_tracker.py +1 -1
  82. claude_mpm/services/shared/__init__.py +2 -1
  83. claude_mpm/services/shared/service_factory.py +8 -5
  84. claude_mpm/services/socketio/server/eventbus_integration.py +1 -1
  85. claude_mpm/services/unified/__init__.py +1 -1
  86. claude_mpm/services/unified/analyzer_strategies/__init__.py +3 -3
  87. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +97 -53
  88. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +81 -40
  89. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +277 -178
  90. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +196 -112
  91. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +83 -49
  92. claude_mpm/services/unified/config_strategies/__init__.py +175 -0
  93. claude_mpm/services/unified/config_strategies/config_schema.py +735 -0
  94. claude_mpm/services/unified/config_strategies/context_strategy.py +750 -0
  95. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1009 -0
  96. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +879 -0
  97. claude_mpm/services/unified/config_strategies/unified_config_service.py +814 -0
  98. claude_mpm/services/unified/config_strategies/validation_strategy.py +1144 -0
  99. claude_mpm/services/unified/deployment_strategies/__init__.py +7 -7
  100. claude_mpm/services/unified/deployment_strategies/base.py +24 -28
  101. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +168 -88
  102. claude_mpm/services/unified/deployment_strategies/local.py +49 -34
  103. claude_mpm/services/unified/deployment_strategies/utils.py +39 -43
  104. claude_mpm/services/unified/deployment_strategies/vercel.py +30 -24
  105. claude_mpm/services/unified/interfaces.py +0 -26
  106. claude_mpm/services/unified/migration.py +17 -40
  107. claude_mpm/services/unified/strategies.py +9 -26
  108. claude_mpm/services/unified/unified_analyzer.py +48 -44
  109. claude_mpm/services/unified/unified_config.py +21 -19
  110. claude_mpm/services/unified/unified_deployment.py +21 -26
  111. claude_mpm/storage/state_storage.py +1 -0
  112. claude_mpm/utils/agent_dependency_loader.py +18 -6
  113. claude_mpm/utils/common.py +14 -12
  114. claude_mpm/utils/database_connector.py +15 -12
  115. claude_mpm/utils/error_handler.py +1 -0
  116. claude_mpm/utils/log_cleanup.py +1 -0
  117. claude_mpm/utils/path_operations.py +1 -0
  118. claude_mpm/utils/session_logging.py +1 -1
  119. claude_mpm/utils/subprocess_utils.py +1 -0
  120. claude_mpm/validation/agent_validator.py +1 -1
  121. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/METADATA +23 -17
  122. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/RECORD +126 -105
  123. claude_mpm/cli/commands/configure_tui.py +0 -1927
  124. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +0 -645
  125. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +0 -602
  126. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/WHEEL +0 -0
  127. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/entry_points.txt +0 -0
  128. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/licenses/LICENSE +0 -0
  129. {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, Set, Tuple
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
- "log",
82
- f"--since={since_date}",
83
- "--pretty=format:%H|%an|%ae|%at|%s",
84
- "--no-merges",
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
- "hash": parts[0][:8],
96
- "author": parts[1],
97
- "email": parts[2],
98
- "timestamp": datetime.fromtimestamp(int(parts[3])).isoformat(),
99
- "message": parts[4],
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
- "log",
110
- f"--since={since_date}",
111
- "--pretty=format:",
112
- "--name-only",
113
- "--no-merges",
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
- "log",
139
- f"--since={since_date}",
140
- "--pretty=format:",
141
- "--name-status",
142
- "--diff-filter=A", # Added files only
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
- "shortlog",
161
- "-sne",
162
- f"--since={since_date}",
163
- "--no-merges",
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
- "name": parts[0],
206
- "url": parts[1],
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
- "log",
228
- f"--since={since_date}",
229
- "--pretty=format:%H|%s",
230
- "--", pattern,
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
- "commit": parts[0][:8],
241
- "message": parts[1],
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
- "log",
247
- f"--since={since_date}",
248
- "--pretty=format:%H|%at|%s",
249
- "--", "CLAUDE.md",
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
- "commit": parts[0][:8],
259
- "timestamp": datetime.fromtimestamp(int(parts[1])).isoformat(),
260
- "message": parts[2],
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(kw in msg_lower for kw in ["refactor", "restructure", "reorganize"]):
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
- "file": file_path,
323
- "changes": change_count,
324
- "type": file_type,
325
- "category": self._categorize_file(file_path),
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
- elif "docs" in str(path).lower():
365
+ if "docs" in str(path).lower():
338
366
  return "documentation"
339
- elif "src" in str(path) or "lib" in str(path):
367
+ if "src" in str(path) or "lib" in str(path):
340
368
  return "source"
341
- elif "scripts" in str(path):
369
+ if "scripts" in str(path):
342
370
  return "scripts"
343
- elif path.suffix in [".yml", ".yaml", ".json", ".toml", ".ini"]:
371
+ if path.suffix in [".yml", ".yaml", ".json", ".toml", ".ini"]:
344
372
  return "configuration"
345
- elif path.suffix in [".md", ".rst", ".txt"]:
373
+ if path.suffix in [".md", ".rst", ".txt"]:
346
374
  return "documentation"
347
- else:
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 (self.project_path / "test").exists():
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("Focus on establishing core structure")
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("Consider adding tests and documentation")
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("Ensure CI/CD and testing are in place")
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("Focus on optimization and documentation")
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 = (datetime.now() - datetime.fromtimestamp(int(first_commit))).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("Create CLAUDE.md for AI agent documentation")
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
- "path": str(path.relative_to(self.project_path)),
479
- "size_mb": round(size / (1024 * 1024), 2),
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