claude-mpm 4.11.1__py3-none-any.whl → 4.11.2__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/cli/commands/mpm_init.py +22 -3
- claude_mpm/utils/git_analyzer.py +109 -7
- {claude_mpm-4.11.1.dist-info → claude_mpm-4.11.2.dist-info}/METADATA +1 -1
- {claude_mpm-4.11.1.dist-info → claude_mpm-4.11.2.dist-info}/RECORD +9 -9
- {claude_mpm-4.11.1.dist-info → claude_mpm-4.11.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.11.1.dist-info → claude_mpm-4.11.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.11.1.dist-info → claude_mpm-4.11.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.11.1.dist-info → claude_mpm-4.11.2.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.11.
|
|
1
|
+
4.11.2
|
|
@@ -1491,12 +1491,23 @@ preserving valuable project-specific information while refreshing standard secti
|
|
|
1491
1491
|
"""
|
|
1492
1492
|
from claude_mpm.utils.git_analyzer import analyze_recent_activity
|
|
1493
1493
|
|
|
1494
|
-
# 1. Analyze git history
|
|
1494
|
+
# 1. Analyze git history with adaptive window
|
|
1495
1495
|
console.print(f"\n🔍 Analyzing last {days} days of git history...\n")
|
|
1496
1496
|
git_analysis = analyze_recent_activity(
|
|
1497
|
-
repo_path=str(self.project_path), days=days, max_commits=50
|
|
1497
|
+
repo_path=str(self.project_path), days=days, max_commits=50, min_commits=25
|
|
1498
1498
|
)
|
|
1499
1499
|
|
|
1500
|
+
# Show adaptive behavior to user
|
|
1501
|
+
if git_analysis.get("adaptive_mode"):
|
|
1502
|
+
console.print(
|
|
1503
|
+
f"[cyan]ℹ️ Note: Analyzed {git_analysis.get('actual_time_span', 'extended period')} "
|
|
1504
|
+
f"to get meaningful context[/cyan]"
|
|
1505
|
+
)
|
|
1506
|
+
if git_analysis.get("reason"):
|
|
1507
|
+
console.print(f"[dim] Reason: {git_analysis['reason']}[/dim]\n")
|
|
1508
|
+
else:
|
|
1509
|
+
console.print()
|
|
1510
|
+
|
|
1500
1511
|
if git_analysis.get("error"):
|
|
1501
1512
|
console.print(
|
|
1502
1513
|
f"[yellow]⚠️ Could not analyze git history: {git_analysis['error']}[/yellow]"
|
|
@@ -1553,7 +1564,15 @@ preserving valuable project-specific information while refreshing standard secti
|
|
|
1553
1564
|
You are Research agent analyzing git history to provide PM with intelligent project context for resuming work.
|
|
1554
1565
|
|
|
1555
1566
|
## Analysis Scope
|
|
1556
|
-
- **Time Range**: Last {days} days
|
|
1567
|
+
- **Time Range**: Last {days} days"""
|
|
1568
|
+
|
|
1569
|
+
# Add adaptive mode note if applicable
|
|
1570
|
+
if git_analysis.get("adaptive_mode"):
|
|
1571
|
+
actual_days = git_analysis.get("actual_time_span", "extended period")
|
|
1572
|
+
prompt += f""" (adaptive: {actual_days} days analyzed)
|
|
1573
|
+
- **Note**: {git_analysis.get('reason', 'Analysis window adjusted to ensure meaningful context')}"""
|
|
1574
|
+
|
|
1575
|
+
prompt += f"""
|
|
1557
1576
|
- **Commits Analyzed**: {len(commits)} commits
|
|
1558
1577
|
- **Branches**: {', '.join(branches[:5]) if branches else 'main'}
|
|
1559
1578
|
- **Contributors**: {', '.join(contributors.keys()) if contributors else 'Unknown'}
|
claude_mpm/utils/git_analyzer.py
CHANGED
|
@@ -16,19 +16,23 @@ logger = get_logger(__name__)
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def analyze_recent_activity(
|
|
19
|
-
repo_path: str = ".", days: int = 7, max_commits: int = 50
|
|
19
|
+
repo_path: str = ".", days: int = 7, max_commits: int = 50, min_commits: int = 25
|
|
20
20
|
) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
|
-
Analyze recent git activity for context reconstruction.
|
|
22
|
+
Analyze recent git activity for context reconstruction with adaptive time window.
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
Strategy:
|
|
25
|
+
1. Try to get commits from last {days} days
|
|
26
|
+
2. If fewer than {min_commits} found, expand window to get {min_commits}
|
|
27
|
+
3. Never exceed {max_commits} total
|
|
28
|
+
|
|
29
|
+
This ensures meaningful context for both high-velocity and low-velocity projects.
|
|
27
30
|
|
|
28
31
|
Args:
|
|
29
32
|
repo_path: Path to the git repository (default: current directory)
|
|
30
|
-
days: Number of days to look back (default: 7)
|
|
33
|
+
days: Number of days to look back initially (default: 7)
|
|
31
34
|
max_commits: Maximum number of commits to analyze (default: 50)
|
|
35
|
+
min_commits: Minimum commits to retrieve, will expand window if needed (default: 25)
|
|
32
36
|
|
|
33
37
|
Returns:
|
|
34
38
|
Dict containing:
|
|
@@ -38,6 +42,9 @@ def analyze_recent_activity(
|
|
|
38
42
|
- contributors: Dict[str, Dict] - Contributor statistics
|
|
39
43
|
- file_changes: Dict[str, Dict] - File change statistics
|
|
40
44
|
- has_activity: bool - Whether any activity was found
|
|
45
|
+
- adaptive_mode: bool - Whether time window was expanded
|
|
46
|
+
- actual_time_span: Optional[str] - Actual time span if adaptive mode was used
|
|
47
|
+
- reason: Optional[str] - Explanation for adaptive mode
|
|
41
48
|
- error: Optional[str] - Error message if analysis failed
|
|
42
49
|
"""
|
|
43
50
|
repo_path_obj = Path(repo_path)
|
|
@@ -48,6 +55,8 @@ def analyze_recent_activity(
|
|
|
48
55
|
"contributors": {},
|
|
49
56
|
"file_changes": {},
|
|
50
57
|
"has_activity": False,
|
|
58
|
+
"adaptive_mode": False,
|
|
59
|
+
"min_commits_target": min_commits,
|
|
51
60
|
}
|
|
52
61
|
|
|
53
62
|
try:
|
|
@@ -66,7 +75,7 @@ def analyze_recent_activity(
|
|
|
66
75
|
]
|
|
67
76
|
analysis["branches"] = list(set(branches))
|
|
68
77
|
|
|
69
|
-
# Get
|
|
78
|
+
# Step 1: Get commits from specified time window
|
|
70
79
|
result = subprocess.run(
|
|
71
80
|
[
|
|
72
81
|
"git",
|
|
@@ -88,6 +97,99 @@ def analyze_recent_activity(
|
|
|
88
97
|
|
|
89
98
|
analysis["has_activity"] = True
|
|
90
99
|
|
|
100
|
+
# Step 2: Count commit lines (lines with pipe separator) to determine if we need adaptive mode
|
|
101
|
+
temp_commits = []
|
|
102
|
+
for line in result.stdout.strip().split("\n"):
|
|
103
|
+
if "|" in line:
|
|
104
|
+
temp_commits.append(line)
|
|
105
|
+
|
|
106
|
+
# Step 3: Check if we need adaptive mode
|
|
107
|
+
if len(temp_commits) < min_commits:
|
|
108
|
+
logger.info(
|
|
109
|
+
f"Only {len(temp_commits)} commits found in last {days} days, "
|
|
110
|
+
f"expanding to get at least {min_commits} commits"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Get last N commits regardless of date
|
|
114
|
+
expanded_result = subprocess.run(
|
|
115
|
+
[
|
|
116
|
+
"git",
|
|
117
|
+
"log",
|
|
118
|
+
"--all",
|
|
119
|
+
f"-{min_commits}",
|
|
120
|
+
"--format=%h|%an|%ae|%ai|%s",
|
|
121
|
+
"--name-status",
|
|
122
|
+
],
|
|
123
|
+
cwd=str(repo_path_obj),
|
|
124
|
+
capture_output=True,
|
|
125
|
+
text=True,
|
|
126
|
+
check=True,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
if expanded_result.stdout.strip():
|
|
130
|
+
result = expanded_result
|
|
131
|
+
analysis["adaptive_mode"] = True
|
|
132
|
+
|
|
133
|
+
# Calculate actual time span
|
|
134
|
+
from datetime import datetime
|
|
135
|
+
|
|
136
|
+
commit_lines = [
|
|
137
|
+
line for line in result.stdout.strip().split("\n") if "|" in line
|
|
138
|
+
]
|
|
139
|
+
if commit_lines:
|
|
140
|
+
# Parse first and last commit dates
|
|
141
|
+
try:
|
|
142
|
+
first_parts = commit_lines[0].split("|", 4)
|
|
143
|
+
last_parts = commit_lines[-1].split("|", 4)
|
|
144
|
+
|
|
145
|
+
if len(first_parts) >= 4 and len(last_parts) >= 4:
|
|
146
|
+
# Parse ISO format dates (e.g., "2025-10-20 11:38:20 -0700")
|
|
147
|
+
# Extract just the date portion before timezone
|
|
148
|
+
first_date_str = first_parts[3].strip()
|
|
149
|
+
last_date_str = last_parts[3].strip()
|
|
150
|
+
|
|
151
|
+
# Remove timezone info for parsing
|
|
152
|
+
first_date_clean = first_date_str.split(" +")[0].split(
|
|
153
|
+
" -"
|
|
154
|
+
)[0]
|
|
155
|
+
last_date_clean = last_date_str.split(" +")[0].split(" -")[
|
|
156
|
+
0
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
# Parse as datetime
|
|
160
|
+
first_date = datetime.fromisoformat(
|
|
161
|
+
first_date_clean.replace(" ", "T")
|
|
162
|
+
)
|
|
163
|
+
last_date = datetime.fromisoformat(
|
|
164
|
+
last_date_clean.replace(" ", "T")
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
days_diff = (first_date - last_date).days
|
|
168
|
+
# Handle the case where days_diff might be 0 or 1
|
|
169
|
+
if days_diff <= 1:
|
|
170
|
+
days_diff = max(days_diff, 1)
|
|
171
|
+
|
|
172
|
+
analysis["actual_time_span"] = str(days_diff)
|
|
173
|
+
|
|
174
|
+
# Provide clear messaging based on the expansion
|
|
175
|
+
if days_diff > days:
|
|
176
|
+
analysis["reason"] = (
|
|
177
|
+
f"Expanded from {days} days to {days_diff} days "
|
|
178
|
+
f"to reach minimum {min_commits} commits for meaningful context"
|
|
179
|
+
)
|
|
180
|
+
else:
|
|
181
|
+
# High-velocity project: reached min_commits without expanding time window
|
|
182
|
+
analysis["reason"] = (
|
|
183
|
+
f"Fetched last {min_commits} commits (spanning {days_diff} days) "
|
|
184
|
+
f"to ensure meaningful context"
|
|
185
|
+
)
|
|
186
|
+
except Exception as e:
|
|
187
|
+
logger.warning(f"Could not calculate actual time span: {e}")
|
|
188
|
+
analysis["actual_time_span"] = f">{days} days"
|
|
189
|
+
analysis["reason"] = (
|
|
190
|
+
f"Expanded beyond {days} days to get minimum {min_commits} commits"
|
|
191
|
+
)
|
|
192
|
+
|
|
91
193
|
# Parse commit log
|
|
92
194
|
commits = []
|
|
93
195
|
current_commit = None
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
claude_mpm/BUILD_NUMBER,sha256=9JfxhnDtr-8l3kCP2U5TVXSErptHoga8m7XA8zqgGOc,4
|
|
2
|
-
claude_mpm/VERSION,sha256
|
|
2
|
+
claude_mpm/VERSION,sha256=oEd-0RuqAA1JoYm8CRr4YanRwGzu-u7mMGWv8tkdGfM,7
|
|
3
3
|
claude_mpm/__init__.py,sha256=UCw6j9e_tZQ3kJtTqmdfNv7MHyw9nD1jkj80WurwM2g,2064
|
|
4
4
|
claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
|
|
5
5
|
claude_mpm/constants.py,sha256=sLjJF6Kw7H4V9WWeaEYltM-77TgXqzEMX5vx4ukM5-0,5977
|
|
@@ -100,7 +100,7 @@ claude_mpm/cli/commands/mcp_setup_external.py,sha256=hfBHkaioNa0JRDhahNEc8agyrUw
|
|
|
100
100
|
claude_mpm/cli/commands/mcp_tool_commands.py,sha256=q17GzlFT3JiLTrDqwPO2tz1-fKmPO5QU449syTnKTz4,1283
|
|
101
101
|
claude_mpm/cli/commands/memory.py,sha256=O4T5HGL-Ob_QPt2dZHQvoOrVohnaDKrBjyngq1Mcv1w,26185
|
|
102
102
|
claude_mpm/cli/commands/monitor.py,sha256=Fjb68hf3dEwTFek2LV8Nh6iU0qEkY7qYlOn32IwNaNg,9566
|
|
103
|
-
claude_mpm/cli/commands/mpm_init.py,sha256
|
|
103
|
+
claude_mpm/cli/commands/mpm_init.py,sha256=-OsKIhiM6uqrodabyP47UA01o4dbz8qvIwFXf-bPp34,75219
|
|
104
104
|
claude_mpm/cli/commands/mpm_init_handler.py,sha256=FZRoo_zfEakLc_W1G_ej_bhxtaU6ybngyBP5GLxaKD4,4583
|
|
105
105
|
claude_mpm/cli/commands/run.py,sha256=PB2H55piOPTy4yo4OBgbUCjMlcz9K79wbwpxQVc9m5Q,48225
|
|
106
106
|
claude_mpm/cli/commands/search.py,sha256=alv6udvKcn-xkqeBlLuPRvfSDV1yxEX4n9mjjRT5uLM,16581
|
|
@@ -787,7 +787,7 @@ claude_mpm/utils/environment_context.py,sha256=mCnRJqQLTyaAv-7M4bp9N9WqVgfSQb5xb
|
|
|
787
787
|
claude_mpm/utils/error_handler.py,sha256=RWL7DnXttJKCgYhevUm9XlMC33rEhX2CXo1IiCtwV4g,7969
|
|
788
788
|
claude_mpm/utils/file_utils.py,sha256=pv3MEKLsn4WIOra5JoHnCm_FaJbNcKMuS3EKuXAWyLc,7859
|
|
789
789
|
claude_mpm/utils/framework_detection.py,sha256=dCY-N0HzuYS9KBg1BjDw8mJnNb22JqmKBoodjTMzd5w,1183
|
|
790
|
-
claude_mpm/utils/git_analyzer.py,sha256=
|
|
790
|
+
claude_mpm/utils/git_analyzer.py,sha256=48fmZzpuOydjdOYa9DAqivmDRLrGlA156ltMmXuFDAE,14129
|
|
791
791
|
claude_mpm/utils/import_migration_example.py,sha256=sKlV-apfkHDJzzez6uubHXjx91YF_5HPuzu2sLs_U0E,989
|
|
792
792
|
claude_mpm/utils/imports.py,sha256=IGcW0W6V-2jTmkVlO-l0Zodo3LRA3zkaumD9J2qn7dE,6654
|
|
793
793
|
claude_mpm/utils/log_cleanup.py,sha256=1d8K1V2uOFPGJJKFOk6E_AMj22sifAibOg-VQyGooWo,22301
|
|
@@ -798,9 +798,9 @@ claude_mpm/utils/subprocess_utils.py,sha256=D0izRT8anjiUb_JG72zlJR_JAw1cDkb7kalN
|
|
|
798
798
|
claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
|
|
799
799
|
claude_mpm/validation/agent_validator.py,sha256=GprtAvu80VyMXcKGsK_VhYiXWA6BjKHv7O6HKx0AB9w,20917
|
|
800
800
|
claude_mpm/validation/frontmatter_validator.py,sha256=YpJlYNNYcV8u6hIOi3_jaRsDnzhbcQpjCBE6eyBKaFY,7076
|
|
801
|
-
claude_mpm-4.11.
|
|
802
|
-
claude_mpm-4.11.
|
|
803
|
-
claude_mpm-4.11.
|
|
804
|
-
claude_mpm-4.11.
|
|
805
|
-
claude_mpm-4.11.
|
|
806
|
-
claude_mpm-4.11.
|
|
801
|
+
claude_mpm-4.11.2.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
|
|
802
|
+
claude_mpm-4.11.2.dist-info/METADATA,sha256=fxFp04Rwx9nyCdY9RKXWS0F_IhICPMPGFfk5g6rUyh0,17967
|
|
803
|
+
claude_mpm-4.11.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
804
|
+
claude_mpm-4.11.2.dist-info/entry_points.txt,sha256=Vlw3GNi-OtTpKSrez04iNrPmxNxYDpIWxmJCxiZ5Tx8,526
|
|
805
|
+
claude_mpm-4.11.2.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
|
|
806
|
+
claude_mpm-4.11.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|