claude-mpm 4.7.8__py3-none-any.whl → 4.7.11__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/cli/__init__.py +82 -0
- claude_mpm/cli/commands/mpm_init.py +151 -1
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/parsers/base_parser.py +5 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +5 -0
- claude_mpm/commands/mpm-init.md +17 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/services/core/memory_manager.py +11 -24
- claude_mpm/services/self_upgrade_service.py +342 -0
- {claude_mpm-4.7.8.dist-info → claude_mpm-4.7.11.dist-info}/METADATA +1 -1
- {claude_mpm-4.7.8.dist-info → claude_mpm-4.7.11.dist-info}/RECORD +16 -14
- {claude_mpm-4.7.8.dist-info → claude_mpm-4.7.11.dist-info}/WHEEL +0 -0
- {claude_mpm-4.7.8.dist-info → claude_mpm-4.7.11.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.7.8.dist-info → claude_mpm-4.7.11.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.7.8.dist-info → claude_mpm-4.7.11.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.7.
|
1
|
+
4.7.11
|
claude_mpm/cli/__init__.py
CHANGED
@@ -36,6 +36,7 @@ from .commands import ( # run_guarded_session is imported lazily to avoid loadi
|
|
36
36
|
)
|
37
37
|
from .commands.analyze_code import manage_analyze_code
|
38
38
|
from .commands.dashboard import manage_dashboard
|
39
|
+
from .commands.upgrade import upgrade
|
39
40
|
from .parser import create_parser, preprocess_args
|
40
41
|
from .utils import ensure_directories, setup_logging
|
41
42
|
|
@@ -232,6 +233,9 @@ def main(argv: Optional[list] = None):
|
|
232
233
|
# Re-enabled: MCP pre-warming is safe with subprocess daemon (v4.2.40)
|
233
234
|
# The subprocess approach avoids fork() issues entirely
|
234
235
|
_verify_mcp_gateway_startup()
|
236
|
+
|
237
|
+
# Check for updates (non-blocking, async)
|
238
|
+
_check_for_updates_async()
|
235
239
|
else:
|
236
240
|
# Still need directories for configure command to work
|
237
241
|
ensure_directories()
|
@@ -544,6 +548,83 @@ def _verify_mcp_gateway_startup():
|
|
544
548
|
# Continue execution - MCP gateway issues shouldn't block startup
|
545
549
|
|
546
550
|
|
551
|
+
def _check_for_updates_async():
|
552
|
+
"""
|
553
|
+
Check for updates in background thread (non-blocking).
|
554
|
+
|
555
|
+
WHY: Users should be notified of new versions and have an easy way to upgrade
|
556
|
+
without manually checking PyPI/npm. This runs asynchronously on startup to avoid
|
557
|
+
blocking the CLI.
|
558
|
+
|
559
|
+
DESIGN DECISION: This is non-blocking and non-critical - failures are logged
|
560
|
+
but don't prevent startup. Only runs for pip/pipx/npm installations, skips
|
561
|
+
editable/development installations.
|
562
|
+
"""
|
563
|
+
|
564
|
+
def run_update_check():
|
565
|
+
"""Inner function to run in background thread."""
|
566
|
+
loop = None
|
567
|
+
try:
|
568
|
+
import asyncio
|
569
|
+
|
570
|
+
from ..core.logger import get_logger
|
571
|
+
from ..services.self_upgrade_service import SelfUpgradeService
|
572
|
+
|
573
|
+
logger = get_logger("upgrade_check")
|
574
|
+
|
575
|
+
# Create new event loop for this thread
|
576
|
+
loop = asyncio.new_event_loop()
|
577
|
+
asyncio.set_event_loop(loop)
|
578
|
+
|
579
|
+
# Create upgrade service and check for updates
|
580
|
+
upgrade_service = SelfUpgradeService()
|
581
|
+
|
582
|
+
# Skip for editable installs (development mode)
|
583
|
+
from ..services.self_upgrade_service import InstallationMethod
|
584
|
+
|
585
|
+
if upgrade_service.installation_method == InstallationMethod.EDITABLE:
|
586
|
+
logger.debug("Skipping version check for editable installation")
|
587
|
+
return
|
588
|
+
|
589
|
+
# Check and prompt for upgrade if available (non-blocking)
|
590
|
+
loop.run_until_complete(upgrade_service.check_and_prompt_on_startup())
|
591
|
+
|
592
|
+
except Exception as e:
|
593
|
+
# Non-critical - log but don't fail startup
|
594
|
+
try:
|
595
|
+
from ..core.logger import get_logger
|
596
|
+
|
597
|
+
logger = get_logger("upgrade_check")
|
598
|
+
logger.debug(f"Update check failed (non-critical): {e}")
|
599
|
+
except Exception:
|
600
|
+
pass # Avoid any errors in error handling
|
601
|
+
finally:
|
602
|
+
# Properly clean up event loop
|
603
|
+
if loop is not None:
|
604
|
+
try:
|
605
|
+
# Cancel all running tasks
|
606
|
+
pending = asyncio.all_tasks(loop)
|
607
|
+
for task in pending:
|
608
|
+
task.cancel()
|
609
|
+
# Wait for tasks to complete cancellation
|
610
|
+
if pending:
|
611
|
+
loop.run_until_complete(
|
612
|
+
asyncio.gather(*pending, return_exceptions=True)
|
613
|
+
)
|
614
|
+
except Exception:
|
615
|
+
pass # Ignore cleanup errors
|
616
|
+
finally:
|
617
|
+
loop.close()
|
618
|
+
# Clear the event loop reference to help with cleanup
|
619
|
+
asyncio.set_event_loop(None)
|
620
|
+
|
621
|
+
# Run update check in background thread to avoid blocking startup
|
622
|
+
import threading
|
623
|
+
|
624
|
+
update_check_thread = threading.Thread(target=run_update_check, daemon=True)
|
625
|
+
update_check_thread.start()
|
626
|
+
|
627
|
+
|
547
628
|
def _ensure_run_attributes(args):
|
548
629
|
"""
|
549
630
|
Ensure run command attributes exist when defaulting to run.
|
@@ -657,6 +738,7 @@ def _execute_command(command: str, args) -> int:
|
|
657
738
|
CLICommands.CLEANUP.value: cleanup_memory,
|
658
739
|
CLICommands.MCP.value: manage_mcp,
|
659
740
|
CLICommands.DOCTOR.value: run_doctor,
|
741
|
+
CLICommands.UPGRADE.value: upgrade,
|
660
742
|
"debug": manage_debug, # Add debug command
|
661
743
|
"mpm-init": None, # Will be handled separately with lazy import
|
662
744
|
}
|
@@ -12,7 +12,7 @@ import contextlib
|
|
12
12
|
import subprocess
|
13
13
|
import sys
|
14
14
|
from pathlib import Path
|
15
|
-
from typing import Dict, List, Optional
|
15
|
+
from typing import Any, Dict, List, Optional
|
16
16
|
|
17
17
|
import click
|
18
18
|
from rich.console import Console
|
@@ -63,6 +63,7 @@ class MPMInitCommand:
|
|
63
63
|
skip_archive: bool = False,
|
64
64
|
dry_run: bool = False,
|
65
65
|
quick_update: bool = False,
|
66
|
+
catchup: bool = False,
|
66
67
|
non_interactive: bool = False,
|
67
68
|
days: int = 30,
|
68
69
|
export: Optional[str] = None,
|
@@ -84,6 +85,7 @@ class MPMInitCommand:
|
|
84
85
|
skip_archive: Skip archiving existing files
|
85
86
|
dry_run: Show what would be done without making changes
|
86
87
|
quick_update: Perform lightweight update based on recent git activity
|
88
|
+
catchup: Show recent commit history from all branches for PM context
|
87
89
|
non_interactive: Non-interactive mode - display report only without prompting
|
88
90
|
days: Number of days for git history analysis (7, 14, 30, 60, or 90)
|
89
91
|
export: Export report to file (path or "auto" for default location)
|
@@ -99,6 +101,11 @@ class MPMInitCommand:
|
|
99
101
|
if review_only:
|
100
102
|
return self._run_review_mode()
|
101
103
|
|
104
|
+
if catchup:
|
105
|
+
data = self._catchup()
|
106
|
+
self._display_catchup(data)
|
107
|
+
return {"status": "success", "mode": "catchup", "catchup_data": data}
|
108
|
+
|
102
109
|
if quick_update:
|
103
110
|
return self._run_quick_update_mode(
|
104
111
|
days=days,
|
@@ -679,6 +686,142 @@ The final CLAUDE.md should be a comprehensive, well-organized guide that any AI
|
|
679
686
|
console.print("\n[yellow]Quick update cancelled[/yellow]")
|
680
687
|
return {"status": "cancelled", "message": "Quick update cancelled"}
|
681
688
|
|
689
|
+
def _catchup(self) -> Dict[str, Any]:
|
690
|
+
"""Get recent commit history for PM context.
|
691
|
+
|
692
|
+
Returns:
|
693
|
+
Dict containing commit history and contributor stats
|
694
|
+
"""
|
695
|
+
from collections import Counter
|
696
|
+
from datetime import datetime
|
697
|
+
from subprocess import run
|
698
|
+
|
699
|
+
try:
|
700
|
+
# Get last 25 commits from all branches with author info
|
701
|
+
result = run(
|
702
|
+
["git", "log", "--all", "--format=%h|%an|%ai|%s", "-25"],
|
703
|
+
capture_output=True,
|
704
|
+
text=True,
|
705
|
+
check=True,
|
706
|
+
cwd=str(self.project_path),
|
707
|
+
)
|
708
|
+
|
709
|
+
commits = []
|
710
|
+
authors = []
|
711
|
+
|
712
|
+
for line in result.stdout.strip().split("\n"):
|
713
|
+
if not line:
|
714
|
+
continue
|
715
|
+
|
716
|
+
parts = line.split("|", 3)
|
717
|
+
if len(parts) == 4:
|
718
|
+
hash_val, author, date_str, message = parts
|
719
|
+
|
720
|
+
# Parse date
|
721
|
+
try:
|
722
|
+
dt = datetime.fromisoformat(date_str.replace(" ", "T", 1))
|
723
|
+
date_display = dt.strftime("%Y-%m-%d %H:%M")
|
724
|
+
except Exception:
|
725
|
+
date_display = date_str[:16]
|
726
|
+
|
727
|
+
commits.append(
|
728
|
+
{
|
729
|
+
"hash": hash_val,
|
730
|
+
"author": author,
|
731
|
+
"date": date_display,
|
732
|
+
"message": message,
|
733
|
+
}
|
734
|
+
)
|
735
|
+
authors.append(author)
|
736
|
+
|
737
|
+
# Calculate contributor stats
|
738
|
+
author_counts = Counter(authors)
|
739
|
+
|
740
|
+
return {
|
741
|
+
"commits": commits,
|
742
|
+
"total_commits": len(commits),
|
743
|
+
"contributors": dict(author_counts),
|
744
|
+
"contributor_count": len(author_counts),
|
745
|
+
}
|
746
|
+
|
747
|
+
except Exception as e:
|
748
|
+
console.print(f"[yellow]Could not retrieve commit history: {e}[/yellow]")
|
749
|
+
return {
|
750
|
+
"commits": [],
|
751
|
+
"total_commits": 0,
|
752
|
+
"contributors": {},
|
753
|
+
"contributor_count": 0,
|
754
|
+
"error": str(e),
|
755
|
+
}
|
756
|
+
|
757
|
+
def _display_catchup(self, data: Dict[str, Any]) -> None:
|
758
|
+
"""Display catchup information to console.
|
759
|
+
|
760
|
+
Args:
|
761
|
+
data: Commit history data from _catchup()
|
762
|
+
"""
|
763
|
+
from rich.panel import Panel
|
764
|
+
from rich.table import Table
|
765
|
+
|
766
|
+
if data.get("error"):
|
767
|
+
console.print(
|
768
|
+
Panel(
|
769
|
+
"[yellow]Not a git repository or no commits found[/yellow]",
|
770
|
+
title="⚠️ Catchup Status",
|
771
|
+
border_style="yellow",
|
772
|
+
)
|
773
|
+
)
|
774
|
+
return
|
775
|
+
|
776
|
+
# Display contributor summary
|
777
|
+
if data["contributors"]:
|
778
|
+
console.print("\n[bold cyan]👥 Active Contributors[/bold cyan]")
|
779
|
+
for author, count in sorted(
|
780
|
+
data["contributors"].items(), key=lambda x: x[1], reverse=True
|
781
|
+
):
|
782
|
+
console.print(
|
783
|
+
f" • [green]{author}[/green]: {count} commit{'s' if count != 1 else ''}"
|
784
|
+
)
|
785
|
+
|
786
|
+
# Display commit history table
|
787
|
+
if data["commits"]:
|
788
|
+
console.print(
|
789
|
+
f"\n[bold cyan]📝 Last {data['total_commits']} Commits[/bold cyan]"
|
790
|
+
)
|
791
|
+
|
792
|
+
table = Table(
|
793
|
+
show_header=True, header_style="bold magenta", border_style="dim"
|
794
|
+
)
|
795
|
+
table.add_column("#", style="dim", width=3)
|
796
|
+
table.add_column("Hash", style="yellow", width=8)
|
797
|
+
table.add_column("Author", style="green", width=20)
|
798
|
+
table.add_column("Date", style="cyan", width=16)
|
799
|
+
table.add_column("Message", style="white")
|
800
|
+
|
801
|
+
for idx, commit in enumerate(data["commits"], 1):
|
802
|
+
# Truncate message if too long
|
803
|
+
msg = commit["message"]
|
804
|
+
if len(msg) > 80:
|
805
|
+
msg = msg[:77] + "..."
|
806
|
+
|
807
|
+
# Truncate author if too long
|
808
|
+
author = commit["author"]
|
809
|
+
if len(author) > 18:
|
810
|
+
author = author[:18] + "..."
|
811
|
+
|
812
|
+
table.add_row(str(idx), commit["hash"], author, commit["date"], msg)
|
813
|
+
|
814
|
+
console.print(table)
|
815
|
+
|
816
|
+
# Display PM recommendations
|
817
|
+
console.print("\n[bold cyan]💡 PM Recommendations[/bold cyan]")
|
818
|
+
console.print(
|
819
|
+
f" • Total activity: {data['total_commits']} commits from {data['contributor_count']} contributor{'s' if data['contributor_count'] != 1 else ''}"
|
820
|
+
)
|
821
|
+
console.print(" • Review commit messages for recent project context")
|
822
|
+
console.print(" • Identify development patterns and focus areas")
|
823
|
+
console.print(" • Use this context to inform current work priorities\n")
|
824
|
+
|
682
825
|
def _generate_activity_report(
|
683
826
|
self, git_analysis: Dict, doc_analysis: Dict, days: int = 30
|
684
827
|
) -> Dict:
|
@@ -1463,6 +1606,11 @@ preserving valuable project-specific information while refreshing standard secti
|
|
1463
1606
|
is_flag=True,
|
1464
1607
|
help="Perform lightweight update based on recent git activity (default: 30 days)",
|
1465
1608
|
)
|
1609
|
+
@click.option(
|
1610
|
+
"--catchup",
|
1611
|
+
is_flag=True,
|
1612
|
+
help="Show recent commit history from all branches for PM context",
|
1613
|
+
)
|
1466
1614
|
@click.option(
|
1467
1615
|
"--non-interactive",
|
1468
1616
|
is_flag=True,
|
@@ -1499,6 +1647,7 @@ def mpm_init(
|
|
1499
1647
|
verbose,
|
1500
1648
|
ast_analysis,
|
1501
1649
|
quick_update,
|
1650
|
+
catchup,
|
1502
1651
|
non_interactive,
|
1503
1652
|
days,
|
1504
1653
|
export,
|
@@ -1544,6 +1693,7 @@ def mpm_init(
|
|
1544
1693
|
preserve_custom=preserve_custom,
|
1545
1694
|
skip_archive=skip_archive,
|
1546
1695
|
quick_update=quick_update,
|
1696
|
+
catchup=catchup,
|
1547
1697
|
non_interactive=non_interactive,
|
1548
1698
|
days=days,
|
1549
1699
|
export=export,
|
@@ -0,0 +1,152 @@
|
|
1
|
+
"""
|
2
|
+
Upgrade command implementation for claude-mpm.
|
3
|
+
|
4
|
+
WHY: This module provides a manual upgrade command that allows users to check
|
5
|
+
for and install the latest version of claude-mpm without waiting for the
|
6
|
+
automatic startup check.
|
7
|
+
|
8
|
+
DESIGN DECISIONS:
|
9
|
+
- Use BaseCommand for consistent CLI patterns
|
10
|
+
- Leverage SelfUpgradeService for upgrade functionality
|
11
|
+
- Support multiple installation methods (pip, pipx, npm)
|
12
|
+
- Skip editable/development installations (must upgrade manually)
|
13
|
+
- Provide clear feedback on available updates and upgrade progress
|
14
|
+
"""
|
15
|
+
|
16
|
+
import asyncio
|
17
|
+
|
18
|
+
from ..shared import BaseCommand, CommandResult
|
19
|
+
|
20
|
+
|
21
|
+
class UpgradeCommand(BaseCommand):
|
22
|
+
"""Upgrade command using shared utilities."""
|
23
|
+
|
24
|
+
def __init__(self):
|
25
|
+
super().__init__("upgrade")
|
26
|
+
|
27
|
+
def validate_args(self, args) -> str:
|
28
|
+
"""Validate command arguments."""
|
29
|
+
# Upgrade command doesn't require specific validation
|
30
|
+
return None
|
31
|
+
|
32
|
+
def run(self, args) -> CommandResult:
|
33
|
+
"""Execute the upgrade command."""
|
34
|
+
try:
|
35
|
+
from ...services.self_upgrade_service import (
|
36
|
+
InstallationMethod,
|
37
|
+
SelfUpgradeService,
|
38
|
+
)
|
39
|
+
|
40
|
+
# Create upgrade service
|
41
|
+
upgrade_service = SelfUpgradeService()
|
42
|
+
|
43
|
+
# Check installation method
|
44
|
+
if upgrade_service.installation_method == InstallationMethod.EDITABLE:
|
45
|
+
self.logger.info(
|
46
|
+
"Editable installation detected - upgrade must be done manually"
|
47
|
+
)
|
48
|
+
print("\n⚠️ Editable Installation Detected")
|
49
|
+
print(
|
50
|
+
"\nYou are running claude-mpm from an editable installation (development mode)."
|
51
|
+
)
|
52
|
+
print("To upgrade, run:")
|
53
|
+
print(" cd /path/to/claude-mpm")
|
54
|
+
print(" git pull")
|
55
|
+
print(" pip install -e .")
|
56
|
+
return CommandResult.success_result(
|
57
|
+
"Upgrade information provided for editable installation"
|
58
|
+
)
|
59
|
+
|
60
|
+
# Check for updates
|
61
|
+
print("\n🔍 Checking for updates...")
|
62
|
+
loop = asyncio.new_event_loop()
|
63
|
+
asyncio.set_event_loop(loop)
|
64
|
+
try:
|
65
|
+
update_info = loop.run_until_complete(
|
66
|
+
upgrade_service.check_for_update()
|
67
|
+
)
|
68
|
+
finally:
|
69
|
+
loop.close()
|
70
|
+
|
71
|
+
if not update_info or not update_info.get("update_available"):
|
72
|
+
print(
|
73
|
+
f"\n✅ You are already on the latest version (v{upgrade_service.current_version})"
|
74
|
+
)
|
75
|
+
return CommandResult.success_result("Already on latest version")
|
76
|
+
|
77
|
+
# Display update information
|
78
|
+
current = update_info["current"]
|
79
|
+
latest = update_info["latest"]
|
80
|
+
method = update_info.get("installation_method", "unknown")
|
81
|
+
|
82
|
+
print("\n🎉 New version available!")
|
83
|
+
print(f" Current: v{current}")
|
84
|
+
print(f" Latest: v{latest}")
|
85
|
+
print(f" Installation method: {method}")
|
86
|
+
|
87
|
+
# Check if --yes flag is set for non-interactive upgrade
|
88
|
+
force_upgrade = getattr(args, "yes", False) or getattr(args, "force", False)
|
89
|
+
|
90
|
+
if not force_upgrade:
|
91
|
+
# Prompt user for confirmation
|
92
|
+
if not upgrade_service.prompt_for_upgrade(update_info):
|
93
|
+
print("\n⏸️ Upgrade cancelled by user")
|
94
|
+
return CommandResult.success_result("Upgrade cancelled by user")
|
95
|
+
|
96
|
+
# Perform upgrade
|
97
|
+
success, message = upgrade_service.perform_upgrade(update_info)
|
98
|
+
print(f"\n{message}")
|
99
|
+
|
100
|
+
if success:
|
101
|
+
# Restart after successful upgrade
|
102
|
+
upgrade_service.restart_after_upgrade()
|
103
|
+
# Note: This line won't be reached as restart replaces process
|
104
|
+
return CommandResult.success_result(f"Upgraded to v{latest}")
|
105
|
+
return CommandResult.error_result("Upgrade failed")
|
106
|
+
|
107
|
+
except Exception as e:
|
108
|
+
self.logger.error(f"Error during upgrade: {e}", exc_info=True)
|
109
|
+
return CommandResult.error_result(f"Error during upgrade: {e}")
|
110
|
+
|
111
|
+
|
112
|
+
def add_upgrade_parser(subparsers):
|
113
|
+
"""
|
114
|
+
Add upgrade command parser.
|
115
|
+
|
116
|
+
WHY: This command helps users check for and install the latest version of
|
117
|
+
claude-mpm without waiting for the automatic startup check.
|
118
|
+
|
119
|
+
Args:
|
120
|
+
subparsers: The subparser action object to add the upgrade command to
|
121
|
+
"""
|
122
|
+
parser = subparsers.add_parser(
|
123
|
+
"upgrade",
|
124
|
+
help="Check for and install latest claude-mpm version",
|
125
|
+
description="Check for updates and upgrade claude-mpm to the latest version from PyPI/npm",
|
126
|
+
)
|
127
|
+
|
128
|
+
parser.add_argument(
|
129
|
+
"-y",
|
130
|
+
"--yes",
|
131
|
+
action="store_true",
|
132
|
+
help="Skip confirmation prompt and upgrade immediately if available",
|
133
|
+
)
|
134
|
+
|
135
|
+
parser.add_argument(
|
136
|
+
"--force",
|
137
|
+
action="store_true",
|
138
|
+
help="Force upgrade even if already on latest version (alias for --yes)",
|
139
|
+
)
|
140
|
+
|
141
|
+
return parser
|
142
|
+
|
143
|
+
|
144
|
+
def upgrade(args):
|
145
|
+
"""
|
146
|
+
Main entry point for upgrade command.
|
147
|
+
|
148
|
+
This function maintains backward compatibility while using the new BaseCommand pattern.
|
149
|
+
"""
|
150
|
+
command = UpgradeCommand()
|
151
|
+
result = command.execute(args)
|
152
|
+
return result.exit_code
|
@@ -423,6 +423,11 @@ def create_parser(
|
|
423
423
|
|
424
424
|
add_doctor_parser(subparsers)
|
425
425
|
|
426
|
+
# Add upgrade command
|
427
|
+
from ..commands.upgrade import add_upgrade_parser
|
428
|
+
|
429
|
+
add_upgrade_parser(subparsers)
|
430
|
+
|
426
431
|
# Add verify command for MCP service verification
|
427
432
|
from ..commands.verify import add_parser as add_verify_parser
|
428
433
|
|
@@ -91,6 +91,11 @@ def add_mpm_init_subparser(subparsers: Any) -> None:
|
|
91
91
|
action="store_true",
|
92
92
|
help="Perform lightweight update based on recent git activity (default: 30 days)",
|
93
93
|
)
|
94
|
+
init_group.add_argument(
|
95
|
+
"--catchup",
|
96
|
+
action="store_true",
|
97
|
+
help="Show recent commit history from all branches for PM context",
|
98
|
+
)
|
94
99
|
init_group.add_argument(
|
95
100
|
"--non-interactive",
|
96
101
|
action="store_true",
|
claude_mpm/commands/mpm-init.md
CHANGED
@@ -146,6 +146,23 @@ Fast update based on recent 30-day git activity. Generates activity report and u
|
|
146
146
|
|
147
147
|
**Note**: Typing `/mpm-init update` executes `claude-mpm mpm-init --quick-update` automatically.
|
148
148
|
|
149
|
+
### Catchup Mode
|
150
|
+
|
151
|
+
Show recent commit history to provide PM with project context:
|
152
|
+
|
153
|
+
```bash
|
154
|
+
/mpm-init catchup
|
155
|
+
```
|
156
|
+
|
157
|
+
This displays:
|
158
|
+
- Last 25 commits from all branches
|
159
|
+
- Author attribution (WHO did WHAT)
|
160
|
+
- Temporal context (WHEN)
|
161
|
+
- Contributor activity summary
|
162
|
+
- PM recommendations based on commit patterns
|
163
|
+
|
164
|
+
Useful for understanding recent development activity and getting PM up to speed on project changes.
|
165
|
+
|
149
166
|
### Review Project State
|
150
167
|
```bash
|
151
168
|
/mpm-init --review
|
claude_mpm/constants.py
CHANGED
@@ -40,9 +40,11 @@ class MemoryManager(IMemoryManager):
|
|
40
40
|
4. Legacy format migration (e.g., PM.md -> PM_memories.md)
|
41
41
|
5. Memory caching for performance
|
42
42
|
|
43
|
-
Memory
|
44
|
-
-
|
45
|
-
-
|
43
|
+
Memory Scope:
|
44
|
+
- Project-level ONLY: ./.claude-mpm/memories/ (project-scoped isolation)
|
45
|
+
- User-level memories are NOT loaded to prevent cross-project contamination
|
46
|
+
|
47
|
+
Note: As of v4.7.10+, memories are strictly project-scoped for complete isolation.
|
46
48
|
"""
|
47
49
|
|
48
50
|
def __init__(
|
@@ -279,7 +281,10 @@ class MemoryManager(IMemoryManager):
|
|
279
281
|
|
280
282
|
def _load_actual_memories(self, deployed_agents: Set[str]) -> Dict[str, Any]:
|
281
283
|
"""
|
282
|
-
Load actual memories from
|
284
|
+
Load actual memories from project directory only.
|
285
|
+
|
286
|
+
Memories are project-scoped to ensure complete isolation between projects.
|
287
|
+
User-level memories are no longer supported to prevent cross-project contamination.
|
283
288
|
|
284
289
|
Args:
|
285
290
|
deployed_agents: Set of deployed agent names
|
@@ -287,32 +292,14 @@ class MemoryManager(IMemoryManager):
|
|
287
292
|
Returns:
|
288
293
|
Dictionary with actual_memories and agent_memories
|
289
294
|
"""
|
290
|
-
# Define memory
|
291
|
-
user_memories_dir = Path.home() / ".claude-mpm" / "memories"
|
295
|
+
# Define project memory directory (project-scoped only)
|
292
296
|
project_memories_dir = Path.cwd() / ".claude-mpm" / "memories"
|
293
297
|
|
294
298
|
# Dictionary to store aggregated memories
|
295
299
|
pm_memories = []
|
296
300
|
agent_memories_dict = {}
|
297
301
|
|
298
|
-
# Load memories from
|
299
|
-
if user_memories_dir.exists():
|
300
|
-
self.logger.info(
|
301
|
-
f"Loading user-level memory files from: {user_memories_dir}"
|
302
|
-
)
|
303
|
-
self._load_memories_from_directory(
|
304
|
-
user_memories_dir,
|
305
|
-
deployed_agents,
|
306
|
-
pm_memories,
|
307
|
-
agent_memories_dict,
|
308
|
-
"user",
|
309
|
-
)
|
310
|
-
else:
|
311
|
-
self.logger.debug(
|
312
|
-
f"No user memories directory found at: {user_memories_dir}"
|
313
|
-
)
|
314
|
-
|
315
|
-
# Load memories from project directory (overrides user memories)
|
302
|
+
# Load memories from project directory only
|
316
303
|
if project_memories_dir.exists():
|
317
304
|
self.logger.info(
|
318
305
|
f"Loading project-level memory files from: {project_memories_dir}"
|
@@ -0,0 +1,342 @@
|
|
1
|
+
"""
|
2
|
+
Self-Upgrade Service
|
3
|
+
====================
|
4
|
+
|
5
|
+
Handles version checking and self-upgrade functionality for claude-mpm.
|
6
|
+
Supports pip, pipx, and npm installations with automatic detection.
|
7
|
+
|
8
|
+
WHY: Users should be notified of updates and have an easy way to upgrade
|
9
|
+
without manually running installation commands.
|
10
|
+
|
11
|
+
DESIGN DECISIONS:
|
12
|
+
- Detects installation method (pip/pipx/npm/editable)
|
13
|
+
- Non-blocking version checks with caching
|
14
|
+
- Interactive upgrade prompts with confirmation
|
15
|
+
- Automatic restart after upgrade
|
16
|
+
- Graceful failure handling (never breaks existing installation)
|
17
|
+
"""
|
18
|
+
|
19
|
+
import os
|
20
|
+
import subprocess
|
21
|
+
import sys
|
22
|
+
from datetime import datetime, timezone
|
23
|
+
from pathlib import Path
|
24
|
+
from typing import Dict, Optional, Tuple
|
25
|
+
|
26
|
+
from packaging import version
|
27
|
+
|
28
|
+
from ..core.logger import get_logger
|
29
|
+
from ..core.unified_paths import PathContext
|
30
|
+
from .mcp_gateway.utils.package_version_checker import PackageVersionChecker
|
31
|
+
|
32
|
+
|
33
|
+
class InstallationMethod:
|
34
|
+
"""Installation method enumeration."""
|
35
|
+
|
36
|
+
PIP = "pip"
|
37
|
+
PIPX = "pipx"
|
38
|
+
NPM = "npm"
|
39
|
+
EDITABLE = "editable"
|
40
|
+
UNKNOWN = "unknown"
|
41
|
+
|
42
|
+
|
43
|
+
class SelfUpgradeService:
|
44
|
+
"""
|
45
|
+
Service for checking and performing self-upgrades.
|
46
|
+
|
47
|
+
Capabilities:
|
48
|
+
- Detect current installation method
|
49
|
+
- Check PyPI/npm for latest version
|
50
|
+
- Prompt user for upgrade confirmation
|
51
|
+
- Execute upgrade command
|
52
|
+
- Restart after upgrade
|
53
|
+
"""
|
54
|
+
|
55
|
+
def __init__(self):
|
56
|
+
"""Initialize the self-upgrade service."""
|
57
|
+
self.logger = get_logger("SelfUpgradeService")
|
58
|
+
self.version_checker = PackageVersionChecker()
|
59
|
+
self.current_version = self._get_current_version()
|
60
|
+
self.installation_method = self._detect_installation_method()
|
61
|
+
|
62
|
+
def _get_current_version(self) -> str:
|
63
|
+
"""
|
64
|
+
Get the current installed version.
|
65
|
+
|
66
|
+
Returns:
|
67
|
+
Version string (e.g., "4.7.10")
|
68
|
+
"""
|
69
|
+
try:
|
70
|
+
from .. import __version__
|
71
|
+
|
72
|
+
return __version__
|
73
|
+
except ImportError:
|
74
|
+
# Fallback to VERSION file
|
75
|
+
try:
|
76
|
+
version_file = Path(__file__).parent.parent / "VERSION"
|
77
|
+
if version_file.exists():
|
78
|
+
return version_file.read_text().strip()
|
79
|
+
except Exception:
|
80
|
+
pass
|
81
|
+
|
82
|
+
return "unknown"
|
83
|
+
|
84
|
+
def _detect_installation_method(self) -> str:
|
85
|
+
"""
|
86
|
+
Detect how claude-mpm was installed.
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
Installation method constant
|
90
|
+
"""
|
91
|
+
# Check for editable install
|
92
|
+
if PathContext.detect_deployment_context().name in [
|
93
|
+
"DEVELOPMENT",
|
94
|
+
"EDITABLE_INSTALL",
|
95
|
+
]:
|
96
|
+
return InstallationMethod.EDITABLE
|
97
|
+
|
98
|
+
# Check for pipx by looking at executable path
|
99
|
+
executable = sys.executable
|
100
|
+
if "pipx" in executable:
|
101
|
+
return InstallationMethod.PIPX
|
102
|
+
|
103
|
+
# Check if npm wrapper is present
|
104
|
+
try:
|
105
|
+
result = subprocess.run(
|
106
|
+
["npm", "list", "-g", "claude-mpm"],
|
107
|
+
check=False,
|
108
|
+
capture_output=True,
|
109
|
+
text=True,
|
110
|
+
timeout=5,
|
111
|
+
)
|
112
|
+
if result.returncode == 0 and "claude-mpm" in result.stdout:
|
113
|
+
return InstallationMethod.NPM
|
114
|
+
except Exception:
|
115
|
+
pass
|
116
|
+
|
117
|
+
# Default to pip
|
118
|
+
return InstallationMethod.PIP
|
119
|
+
|
120
|
+
async def check_for_update(
|
121
|
+
self, cache_ttl: Optional[int] = None
|
122
|
+
) -> Optional[Dict[str, any]]:
|
123
|
+
"""
|
124
|
+
Check if an update is available.
|
125
|
+
|
126
|
+
Args:
|
127
|
+
cache_ttl: Cache time-to-live in seconds (default: 24 hours)
|
128
|
+
|
129
|
+
Returns:
|
130
|
+
Dict with update info or None:
|
131
|
+
{
|
132
|
+
"current": "4.7.10",
|
133
|
+
"latest": "4.7.11",
|
134
|
+
"update_available": True,
|
135
|
+
"installation_method": "pipx",
|
136
|
+
"upgrade_command": "pipx upgrade claude-mpm"
|
137
|
+
}
|
138
|
+
"""
|
139
|
+
if self.current_version == "unknown":
|
140
|
+
self.logger.warning("Cannot check for updates: version unknown")
|
141
|
+
return None
|
142
|
+
|
143
|
+
# Check PyPI for Python installations
|
144
|
+
if self.installation_method in [
|
145
|
+
InstallationMethod.PIP,
|
146
|
+
InstallationMethod.PIPX,
|
147
|
+
]:
|
148
|
+
result = await self.version_checker.check_for_update(
|
149
|
+
"claude-mpm", self.current_version, cache_ttl
|
150
|
+
)
|
151
|
+
if result and result.get("update_available"):
|
152
|
+
result["installation_method"] = self.installation_method
|
153
|
+
result["upgrade_command"] = self._get_upgrade_command()
|
154
|
+
return result
|
155
|
+
|
156
|
+
# Check npm for npm installations
|
157
|
+
elif self.installation_method == InstallationMethod.NPM:
|
158
|
+
npm_version = await self._check_npm_version()
|
159
|
+
if npm_version:
|
160
|
+
current_ver = version.parse(self.current_version)
|
161
|
+
latest_ver = version.parse(npm_version)
|
162
|
+
if latest_ver > current_ver:
|
163
|
+
return {
|
164
|
+
"current": self.current_version,
|
165
|
+
"latest": npm_version,
|
166
|
+
"update_available": True,
|
167
|
+
"installation_method": InstallationMethod.NPM,
|
168
|
+
"upgrade_command": self._get_upgrade_command(),
|
169
|
+
"checked_at": datetime.now(timezone.utc).isoformat(),
|
170
|
+
}
|
171
|
+
|
172
|
+
return None
|
173
|
+
|
174
|
+
async def _check_npm_version(self) -> Optional[str]:
|
175
|
+
"""
|
176
|
+
Check npm registry for latest version.
|
177
|
+
|
178
|
+
Returns:
|
179
|
+
Latest version string or None
|
180
|
+
"""
|
181
|
+
try:
|
182
|
+
result = subprocess.run(
|
183
|
+
["npm", "view", "claude-mpm", "version"],
|
184
|
+
check=False,
|
185
|
+
capture_output=True,
|
186
|
+
text=True,
|
187
|
+
timeout=10,
|
188
|
+
)
|
189
|
+
if result.returncode == 0:
|
190
|
+
return result.stdout.strip()
|
191
|
+
except Exception as e:
|
192
|
+
self.logger.debug(f"npm version check failed: {e}")
|
193
|
+
|
194
|
+
return None
|
195
|
+
|
196
|
+
def _get_upgrade_command(self) -> str:
|
197
|
+
"""
|
198
|
+
Get the appropriate upgrade command for current installation method.
|
199
|
+
|
200
|
+
Returns:
|
201
|
+
Shell command string to upgrade claude-mpm
|
202
|
+
"""
|
203
|
+
if self.installation_method == InstallationMethod.PIPX:
|
204
|
+
return "pipx upgrade claude-mpm"
|
205
|
+
if self.installation_method == InstallationMethod.NPM:
|
206
|
+
return "npm update -g claude-mpm"
|
207
|
+
if self.installation_method == InstallationMethod.PIP:
|
208
|
+
return f"{sys.executable} -m pip install --upgrade claude-mpm"
|
209
|
+
if self.installation_method == InstallationMethod.EDITABLE:
|
210
|
+
return "git pull && pip install -e ."
|
211
|
+
return "pip install --upgrade claude-mpm"
|
212
|
+
|
213
|
+
def prompt_for_upgrade(self, update_info: Dict[str, any]) -> bool:
|
214
|
+
"""
|
215
|
+
Prompt user to upgrade.
|
216
|
+
|
217
|
+
Args:
|
218
|
+
update_info: Update information dict
|
219
|
+
|
220
|
+
Returns:
|
221
|
+
True if user confirms upgrade, False otherwise
|
222
|
+
"""
|
223
|
+
current = update_info["current"]
|
224
|
+
latest = update_info["latest"]
|
225
|
+
method = update_info.get("installation_method", "unknown")
|
226
|
+
|
227
|
+
print("\n🎉 New version available!")
|
228
|
+
print(f" Current: v{current}")
|
229
|
+
print(f" Latest: v{latest}")
|
230
|
+
print(f" Installation method: {method}")
|
231
|
+
print(f"\nTo upgrade, run: {update_info['upgrade_command']}")
|
232
|
+
|
233
|
+
try:
|
234
|
+
response = input("\nWould you like to upgrade now? [y/N]: ").strip().lower()
|
235
|
+
return response in ["y", "yes"]
|
236
|
+
except (KeyboardInterrupt, EOFError):
|
237
|
+
print("\n")
|
238
|
+
return False
|
239
|
+
|
240
|
+
def perform_upgrade(self, update_info: Dict[str, any]) -> Tuple[bool, str]:
|
241
|
+
"""
|
242
|
+
Perform the upgrade.
|
243
|
+
|
244
|
+
Args:
|
245
|
+
update_info: Update information dict
|
246
|
+
|
247
|
+
Returns:
|
248
|
+
Tuple of (success: bool, message: str)
|
249
|
+
"""
|
250
|
+
command = update_info["upgrade_command"]
|
251
|
+
|
252
|
+
# Don't upgrade editable installs automatically
|
253
|
+
if self.installation_method == InstallationMethod.EDITABLE:
|
254
|
+
return (
|
255
|
+
False,
|
256
|
+
"Editable installation detected. Please update manually with: git pull && pip install -e .",
|
257
|
+
)
|
258
|
+
|
259
|
+
print("\n⏳ Upgrading claude-mpm...")
|
260
|
+
print(f" Running: {command}")
|
261
|
+
|
262
|
+
try:
|
263
|
+
# Execute upgrade command
|
264
|
+
result = subprocess.run(
|
265
|
+
command,
|
266
|
+
check=False,
|
267
|
+
shell=True,
|
268
|
+
capture_output=True,
|
269
|
+
text=True,
|
270
|
+
timeout=300, # 5 minutes
|
271
|
+
)
|
272
|
+
|
273
|
+
if result.returncode == 0:
|
274
|
+
return (True, f"✅ Successfully upgraded to v{update_info['latest']}")
|
275
|
+
error_msg = result.stderr or result.stdout or "Unknown error"
|
276
|
+
return (False, f"❌ Upgrade failed: {error_msg}")
|
277
|
+
|
278
|
+
except subprocess.TimeoutExpired:
|
279
|
+
return (False, "❌ Upgrade timed out")
|
280
|
+
except Exception as e:
|
281
|
+
return (False, f"❌ Upgrade failed: {e!s}")
|
282
|
+
|
283
|
+
def restart_after_upgrade(self) -> None:
|
284
|
+
"""
|
285
|
+
Restart claude-mpm after a successful upgrade.
|
286
|
+
|
287
|
+
Preserves original command line arguments.
|
288
|
+
"""
|
289
|
+
print("\n🔄 Restarting claude-mpm...")
|
290
|
+
|
291
|
+
try:
|
292
|
+
# Get current command line arguments
|
293
|
+
args = sys.argv[:]
|
294
|
+
|
295
|
+
# Replace current process with new one
|
296
|
+
if self.installation_method == InstallationMethod.PIPX:
|
297
|
+
# Use pipx run
|
298
|
+
os.execvp("pipx", ["pipx", "run", "claude-mpm", *args[1:]])
|
299
|
+
elif self.installation_method == InstallationMethod.NPM:
|
300
|
+
# Use npm executable
|
301
|
+
os.execvp("claude-mpm", args)
|
302
|
+
else:
|
303
|
+
# Use Python executable
|
304
|
+
os.execvp(sys.executable, [sys.executable, *args])
|
305
|
+
|
306
|
+
except Exception as e:
|
307
|
+
self.logger.error(f"Failed to restart: {e}")
|
308
|
+
print(f"\n⚠️ Restart failed: {e}")
|
309
|
+
print("Please restart claude-mpm manually.")
|
310
|
+
|
311
|
+
async def check_and_prompt_on_startup(
|
312
|
+
self, auto_upgrade: bool = False
|
313
|
+
) -> Optional[Dict[str, any]]:
|
314
|
+
"""
|
315
|
+
Check for updates on startup and optionally prompt user.
|
316
|
+
|
317
|
+
Args:
|
318
|
+
auto_upgrade: If True, upgrade without prompting (use with caution)
|
319
|
+
|
320
|
+
Returns:
|
321
|
+
Update info if available, None otherwise
|
322
|
+
"""
|
323
|
+
# Skip for editable installs
|
324
|
+
if self.installation_method == InstallationMethod.EDITABLE:
|
325
|
+
return None
|
326
|
+
|
327
|
+
try:
|
328
|
+
update_info = await self.check_for_update()
|
329
|
+
|
330
|
+
if update_info and update_info.get("update_available"):
|
331
|
+
if auto_upgrade or self.prompt_for_upgrade(update_info):
|
332
|
+
success, message = self.perform_upgrade(update_info)
|
333
|
+
print(message)
|
334
|
+
if success:
|
335
|
+
self.restart_after_upgrade()
|
336
|
+
|
337
|
+
return update_info
|
338
|
+
|
339
|
+
except Exception as e:
|
340
|
+
self.logger.debug(f"Startup version check failed: {e}")
|
341
|
+
|
342
|
+
return None
|
@@ -1,8 +1,8 @@
|
|
1
1
|
claude_mpm/BUILD_NUMBER,sha256=9JfxhnDtr-8l3kCP2U5TVXSErptHoga8m7XA8zqgGOc,4
|
2
|
-
claude_mpm/VERSION,sha256=
|
2
|
+
claude_mpm/VERSION,sha256=8NJI62Tp7GTnD5qeEDJUZAnPvuDLKbXAbLj5maMHLnM,7
|
3
3
|
claude_mpm/__init__.py,sha256=UCw6j9e_tZQ3kJtTqmdfNv7MHyw9nD1jkj80WurwM2g,2064
|
4
4
|
claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
|
5
|
-
claude_mpm/constants.py,sha256=
|
5
|
+
claude_mpm/constants.py,sha256=sLjJF6Kw7H4V9WWeaEYltM-77TgXqzEMX5vx4ukM5-0,5977
|
6
6
|
claude_mpm/init.py,sha256=HFJR_JmTHa53FAhbGusm3P1iXT6VR6V7S-YJz4pOZ1Q,15967
|
7
7
|
claude_mpm/ticket_wrapper.py,sha256=qe5xY579t7_7fK5nyeAfHN_fr7CXdeOD3jfXEc8-7yo,828
|
8
8
|
claude_mpm/agents/BASE_AGENT_TEMPLATE.md,sha256=aK9qxS1FRpm_8VaB5GI2I6YA9Wr8dGHuea_txMFe44M,5524
|
@@ -64,7 +64,7 @@ claude_mpm/agents/templates/.claude-mpm/memories/README.md,sha256=vEiG7cPjHRZfwX
|
|
64
64
|
claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md,sha256=KMZSJrQi-wHOwfl2C0m3A4PpC4QuBtDolAtVybGahKc,77
|
65
65
|
claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md,sha256=UBm4BycXtdaa-_l1VCh0alTGGOUSsnCbpKwbFuI-mUY,2219
|
66
66
|
claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md,sha256=oPvFSYFnmJ4TkbTe4AZnNHWaJMJ-xqZP2WM6scUKQKo,13089
|
67
|
-
claude_mpm/cli/__init__.py,sha256=
|
67
|
+
claude_mpm/cli/__init__.py,sha256=Ed8uPUqS5FmIAMxxIPxpo5JJX2ZWXIe5v-vx8K9jBEE,29373
|
68
68
|
claude_mpm/cli/__main__.py,sha256=WnVGBwe10InxuZjJRFdwuMF6Gh16aXox6zFgxr0sRXk,847
|
69
69
|
claude_mpm/cli/parser.py,sha256=Vqx9n-6Xo1uNhXR4rThmgWpZXTr0nOtkgDf3oMS9b0g,5855
|
70
70
|
claude_mpm/cli/startup_logging.py,sha256=RTuyd6CbhiFQz7Z07LDDhK_ZAnZfuJ9B0NghVSntHFI,29390
|
@@ -96,12 +96,13 @@ claude_mpm/cli/commands/mcp_setup_external.py,sha256=hfBHkaioNa0JRDhahNEc8agyrUw
|
|
96
96
|
claude_mpm/cli/commands/mcp_tool_commands.py,sha256=q17GzlFT3JiLTrDqwPO2tz1-fKmPO5QU449syTnKTz4,1283
|
97
97
|
claude_mpm/cli/commands/memory.py,sha256=O4T5HGL-Ob_QPt2dZHQvoOrVohnaDKrBjyngq1Mcv1w,26185
|
98
98
|
claude_mpm/cli/commands/monitor.py,sha256=Fjb68hf3dEwTFek2LV8Nh6iU0qEkY7qYlOn32IwNaNg,9566
|
99
|
-
claude_mpm/cli/commands/mpm_init.py,sha256=
|
99
|
+
claude_mpm/cli/commands/mpm_init.py,sha256=njopKyRBzBT_FL-3LrqishRSeKtIESehzWinhUqmRpM,65724
|
100
100
|
claude_mpm/cli/commands/mpm_init_handler.py,sha256=b1CSwZYJ89wMorKzPOKS-RVxOKR2kT9yv9KQLvKkd2U,3532
|
101
101
|
claude_mpm/cli/commands/run.py,sha256=PB2H55piOPTy4yo4OBgbUCjMlcz9K79wbwpxQVc9m5Q,48225
|
102
102
|
claude_mpm/cli/commands/search.py,sha256=_0qbUnop8v758MHsB0fAop8FVxwygD59tec_-iN7pLE,9806
|
103
103
|
claude_mpm/cli/commands/tickets.py,sha256=kl2dklTBnG3Y4jUUJ_PcEVsTx4CtVJfkGWboWBx_mQM,21234
|
104
104
|
claude_mpm/cli/commands/uninstall.py,sha256=KGlVG6veEs1efLVjrZ3wSty7e1zVR9wpt-VXQA1RzWw,5945
|
105
|
+
claude_mpm/cli/commands/upgrade.py,sha256=NYMVONNlj78WHoQ6eyVInroE95AeQxUY2_TpjYFTdYE,5409
|
105
106
|
claude_mpm/cli/commands/verify.py,sha256=wmu2UYINK15q2e34TdlTyamvtLDE7r3Oj_XT9zpT5Kk,3687
|
106
107
|
claude_mpm/cli/interactive/__init__.py,sha256=vQqUCgPFvLYA1Vkq-5pnY7Ow3A-IgdM0SByfNL1ZLTk,433
|
107
108
|
claude_mpm/cli/interactive/agent_wizard.py,sha256=v3nKcLusU49ewjCqvgUWsG35UGc82pC7_Uv-ZzAHZ-c,36201
|
@@ -110,7 +111,7 @@ claude_mpm/cli/parsers/agent_manager_parser.py,sha256=TQEIm638ELM4X_AAGcn6WrJxlt
|
|
110
111
|
claude_mpm/cli/parsers/agents_parser.py,sha256=R-9ESNXdjqr5iCEIcmbb2EPvcswW9UfJzMj5bAkgI4U,9042
|
111
112
|
claude_mpm/cli/parsers/analyze_code_parser.py,sha256=cpJSMFbc3mqB4qrMBIEZiikzPekC2IQX-cjt9U2fHW4,5356
|
112
113
|
claude_mpm/cli/parsers/analyze_parser.py,sha256=E00Ao0zwzbJPchs_AJt-aoQ7LQEtJPXRCNQ6Piivb4o,3908
|
113
|
-
claude_mpm/cli/parsers/base_parser.py,sha256=
|
114
|
+
claude_mpm/cli/parsers/base_parser.py,sha256=iGYJ_-wIXkL4iVclJgrzQ2kz_of3CIqCwIM-FnFKEQI,14298
|
114
115
|
claude_mpm/cli/parsers/config_parser.py,sha256=wp6NbV8_p9txP28MXFcQrri0JDIfGFM7u4aJbYJXcYQ,2699
|
115
116
|
claude_mpm/cli/parsers/configure_parser.py,sha256=t3cwAQX3BfljDDRJH3i0LplpRprw5jdKcI9Uy3M8xtE,4382
|
116
117
|
claude_mpm/cli/parsers/dashboard_parser.py,sha256=JBCM6v_iZhADr_Fwtk_d3up9AOod1avMab-vkNE61gE,3460
|
@@ -118,7 +119,7 @@ claude_mpm/cli/parsers/debug_parser.py,sha256=F7MZdmiXiPfiIPMv21ZUqB2cMT8Ho1LDmp
|
|
118
119
|
claude_mpm/cli/parsers/mcp_parser.py,sha256=2j6ULhdu55Z2k_-Gu2QxIsFoTQFbDCEMSGePXSuPoQQ,6532
|
119
120
|
claude_mpm/cli/parsers/memory_parser.py,sha256=ZwCDxJEgp-w03L-1tZsWTgisiwamP42s424bA5bvDJc,4760
|
120
121
|
claude_mpm/cli/parsers/monitor_parser.py,sha256=PeoznSi_5Bw6THK_Espl8M20o6dKvvBSmFzAbovkaFQ,4920
|
121
|
-
claude_mpm/cli/parsers/mpm_init_parser.py,sha256=
|
122
|
+
claude_mpm/cli/parsers/mpm_init_parser.py,sha256=iTMd3RjnHzz89Q0O5Lr0MYI_vOUuXQOHHI6D-Zy8PUE,7823
|
122
123
|
claude_mpm/cli/parsers/run_parser.py,sha256=cs34qNonFZG8uYxTYEt0rXi2LcPz3pw8D8hxiywih6w,4927
|
123
124
|
claude_mpm/cli/parsers/search_parser.py,sha256=L8-65kndg-zutSKpzj-eCvTNkeySCZ-WlSHdhk7pEak,6916
|
124
125
|
claude_mpm/cli/parsers/tickets_parser.py,sha256=FYl-VNH7PrZzfZUCcjnf6F7g6JXnL8YDxwrmR5svIcg,6966
|
@@ -136,7 +137,7 @@ claude_mpm/commands/mpm-agents.md,sha256=JnYPJ-eWvIEEtiCB6iPu182P2xDBRvU3ArVXQ7h
|
|
136
137
|
claude_mpm/commands/mpm-config.md,sha256=79Eb-srRpEVV3HCHDHZc8SKec6_LVP6HbXDEVkZKLgw,2929
|
137
138
|
claude_mpm/commands/mpm-doctor.md,sha256=ut5LhFKVRw-2ecjMSPsnaTiRuFXa6Q9t-Wgl3CCnQvk,590
|
138
139
|
claude_mpm/commands/mpm-help.md,sha256=zfhpE0Fd-wW5zWmYYAMRMT-xYK8saqbw-HXRD7csJHI,2850
|
139
|
-
claude_mpm/commands/mpm-init.md,sha256=
|
140
|
+
claude_mpm/commands/mpm-init.md,sha256=5Jqb99qqJ_hQ_41lGmyTyDUhm7V7wQiLCYvksd3tZEo,10696
|
140
141
|
claude_mpm/commands/mpm-monitor.md,sha256=onTHf9Yac1KkdZdENtY2Q5jyw0A-vZLYgoKkPCtZLUY,12193
|
141
142
|
claude_mpm/commands/mpm-organize.md,sha256=T-ysjhwgfW9irjUj02vuY_1jeMdabO_zxcShyjmqsiM,10153
|
142
143
|
claude_mpm/commands/mpm-status.md,sha256=oaM4ybL4ffp55nkT9F0mp_5H4tF-wX9mbqK-LEKEqUU,1919
|
@@ -427,6 +428,7 @@ claude_mpm/services/project_port_allocator.py,sha256=L_EPuX_vGdv8vWWRVTpRk7F-v7u
|
|
427
428
|
claude_mpm/services/recovery_manager.py,sha256=ptUYsguF6oKWnJnzPRSBuzUFVDXIcvsS3svT6MBTqCQ,25686
|
428
429
|
claude_mpm/services/response_tracker.py,sha256=wBPgI5fH40xc7NHcCXQFOTPFTPSVbAZPqXIauXOJA5g,9575
|
429
430
|
claude_mpm/services/runner_configuration_service.py,sha256=Qs84yrZfQv-DC0I2Xah1Qt9eunH4gS7LNMZ0mmymcqA,21311
|
431
|
+
claude_mpm/services/self_upgrade_service.py,sha256=PuzHFQ3fQx7I9rmINLWs86o2KVyr-1StolLR-xnkOrQ,11246
|
430
432
|
claude_mpm/services/session_management_service.py,sha256=axGZXpexWcYGnOMt5o8UQnFJUN3aVyjXRpFAcFrNKeg,10060
|
431
433
|
claude_mpm/services/session_manager.py,sha256=ElguSoiy725VWS2iEqtcn0dUPIRrQrrON74aUzrWjRE,5147
|
432
434
|
claude_mpm/services/socketio_client_manager.py,sha256=cZjIsnoi2VPXFA-5pNhoz5Vv3qv0iuSTy510TgAJU4U,18179
|
@@ -546,7 +548,7 @@ claude_mpm/services/core/__init__.py,sha256=evEayLlBqJvxMZhrhuK6aagXmNrKGSj8Jm9O
|
|
546
548
|
claude_mpm/services/core/base.py,sha256=iA-F7DgGp-FJIMvQTiHQ68RkG_k-AtUWlArJPMw6ZPk,7297
|
547
549
|
claude_mpm/services/core/cache_manager.py,sha256=dBHvvI6M67kaxFtAubi4IsWfbDZSct1siyKHTmCIrW8,11567
|
548
550
|
claude_mpm/services/core/interfaces.py,sha256=FbLhWiOUMlvBfqjYBCeoWgsmRscQGBKteRMW-BGz4hQ,1261
|
549
|
-
claude_mpm/services/core/memory_manager.py,sha256=
|
551
|
+
claude_mpm/services/core/memory_manager.py,sha256=aajBuvBzTq0-EZrjnBjGRdUSaa6MpbfqHAtCePnn7aQ,26258
|
550
552
|
claude_mpm/services/core/path_resolver.py,sha256=VtqiOEUlskAr9nRsaS9uXQSSjDD8dIrYfNML0zLY2zo,17764
|
551
553
|
claude_mpm/services/core/service_container.py,sha256=3hDwFUahxFZnokPzwgXqBP9swvZhLztKQqwe9xEHgsw,18497
|
552
554
|
claude_mpm/services/core/service_interfaces.py,sha256=dlNp0K4gaMcLiNSZxXjsL-kto6vipYw87pBuFK7oVNo,10770
|
@@ -786,9 +788,9 @@ claude_mpm/utils/subprocess_utils.py,sha256=D0izRT8anjiUb_JG72zlJR_JAw1cDkb7kalN
|
|
786
788
|
claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
|
787
789
|
claude_mpm/validation/agent_validator.py,sha256=GprtAvu80VyMXcKGsK_VhYiXWA6BjKHv7O6HKx0AB9w,20917
|
788
790
|
claude_mpm/validation/frontmatter_validator.py,sha256=YpJlYNNYcV8u6hIOi3_jaRsDnzhbcQpjCBE6eyBKaFY,7076
|
789
|
-
claude_mpm-4.7.
|
790
|
-
claude_mpm-4.7.
|
791
|
-
claude_mpm-4.7.
|
792
|
-
claude_mpm-4.7.
|
793
|
-
claude_mpm-4.7.
|
794
|
-
claude_mpm-4.7.
|
791
|
+
claude_mpm-4.7.11.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
|
792
|
+
claude_mpm-4.7.11.dist-info/METADATA,sha256=xrQscwKCC7qPBxPTM3pLS0WWsrH6ale3r3620JQqids,17518
|
793
|
+
claude_mpm-4.7.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
794
|
+
claude_mpm-4.7.11.dist-info/entry_points.txt,sha256=Vlw3GNi-OtTpKSrez04iNrPmxNxYDpIWxmJCxiZ5Tx8,526
|
795
|
+
claude_mpm-4.7.11.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
|
796
|
+
claude_mpm-4.7.11.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|