claude-mpm 4.11.0__py3-none-any.whl → 4.11.1__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 CHANGED
@@ -1 +1 @@
1
- 4.11.0
1
+ 4.11.1
@@ -11,7 +11,6 @@ documentation with code structure analysis.
11
11
  import contextlib
12
12
  import subprocess
13
13
  import sys
14
- from datetime import datetime
15
14
  from pathlib import Path
16
15
  from typing import Any, Dict, List, Optional
17
16
 
@@ -21,9 +20,6 @@ from rich.panel import Panel
21
20
  from rich.progress import Progress, SpinnerColumn, TextColumn
22
21
  from rich.prompt import Prompt
23
22
 
24
- # Import pause/resume managers
25
- from claude_mpm.cli.commands.session_pause_manager import SessionPauseManager
26
- from claude_mpm.cli.commands.session_resume_manager import SessionResumeManager
27
23
  from claude_mpm.core.logging_utils import get_logger
28
24
 
29
25
  # Import new services
@@ -52,10 +48,6 @@ class MPMInitCommand:
52
48
  self.analyzer = EnhancedProjectAnalyzer(self.project_path)
53
49
  self.display = DisplayHelper(console)
54
50
 
55
- # Session management
56
- self.pause_manager = SessionPauseManager(self.project_path)
57
- self.resume_manager = SessionResumeManager(self.project_path)
58
-
59
51
  def initialize_project(
60
52
  self,
61
53
  project_type: Optional[str] = None,
@@ -1472,124 +1464,197 @@ preserving valuable project-specific information while refreshing standard secti
1472
1464
  logger.error(f"Initialization failed: {e}")
1473
1465
  return {"status": "error", "message": str(e)}
1474
1466
 
1475
- def handle_pause(
1467
+ def handle_context(
1476
1468
  self,
1477
- summary: Optional[str] = None,
1478
- accomplishments: Optional[List[str]] = None,
1479
- next_steps: Optional[List[str]] = None,
1469
+ session_id: Optional[str] = None,
1470
+ list_sessions: bool = False,
1471
+ days: int = 7,
1480
1472
  ) -> Dict[str, Any]:
1481
- """Handle session pause request.
1473
+ """
1474
+ Provide intelligent context for resuming work based on git history.
1475
+
1476
+ Analyzes recent commits to identify:
1477
+ - Active work streams (what was being worked on)
1478
+ - Intent and motivation (why this work)
1479
+ - Risks and blockers
1480
+ - Recommended next actions
1481
+
1482
+ This delegates to Research agent for deep analysis.
1482
1483
 
1483
1484
  Args:
1484
- summary: Summary of what was being worked on
1485
- accomplishments: List of things accomplished
1486
- next_steps: List of next steps to continue work
1485
+ session_id: Unused parameter (for compatibility)
1486
+ list_sessions: Unused parameter (for compatibility)
1487
+ days: Number of days of git history to analyze (default: 7)
1487
1488
 
1488
1489
  Returns:
1489
- Dict containing pause result
1490
+ Dict containing context result
1490
1491
  """
1491
- try:
1492
- # If no context provided, prompt for it
1493
- if not summary:
1494
- summary = Prompt.ask(
1495
- "\n[bold]What were you working on?[/bold]",
1496
- default="Working on project improvements",
1497
- )
1492
+ from claude_mpm.utils.git_analyzer import analyze_recent_activity
1498
1493
 
1499
- if not accomplishments:
1500
- console.print(
1501
- "\n[bold]List accomplishments (enter blank line to finish):[/bold]"
1502
- )
1503
- accomplishments = []
1504
- while True:
1505
- item = Prompt.ask(" Accomplishment", default="")
1506
- if not item:
1507
- break
1508
- accomplishments.append(item)
1509
-
1510
- if not next_steps:
1511
- console.print(
1512
- "\n[bold]List next steps (enter blank line to finish):[/bold]"
1513
- )
1514
- next_steps = []
1515
- while True:
1516
- item = Prompt.ask(" Next step", default="")
1517
- if not item:
1518
- break
1519
- next_steps.append(item)
1520
-
1521
- # Pause the session
1522
- return self.pause_manager.pause_session(
1523
- conversation_summary=summary,
1524
- accomplishments=accomplishments,
1525
- next_steps=next_steps,
1494
+ # 1. Analyze git history
1495
+ console.print(f"\n🔍 Analyzing last {days} days of git history...\n")
1496
+ git_analysis = analyze_recent_activity(
1497
+ repo_path=str(self.project_path), days=days, max_commits=50
1498
+ )
1499
+
1500
+ if git_analysis.get("error"):
1501
+ console.print(
1502
+ f"[yellow]⚠️ Could not analyze git history: {git_analysis['error']}[/yellow]"
1503
+ )
1504
+ console.print(
1505
+ "[dim]Ensure this is a git repository with commit history.[/dim]\n"
1526
1506
  )
1507
+ return {
1508
+ "status": "error",
1509
+ "message": git_analysis["error"],
1510
+ }
1527
1511
 
1528
- except Exception as e:
1529
- logger.error(f"Failed to pause session: {e}")
1530
- console.print(f"[red] Error pausing session: {e}[/red]")
1531
- return {"status": "error", "message": str(e)}
1512
+ if not git_analysis.get("has_activity"):
1513
+ console.print(
1514
+ f"[yellow]⚠️ No git activity found in the last {days} days.[/yellow]"
1515
+ )
1516
+ console.print("[dim]Try increasing the --days parameter.[/dim]\n")
1517
+ return {
1518
+ "status": "error",
1519
+ "message": f"No git activity in last {days} days",
1520
+ }
1532
1521
 
1533
- def handle_resume(self, session_id: Optional[str] = None) -> Dict[str, Any]:
1534
- """Handle session resume request.
1522
+ # 2. Build Research delegation prompt
1523
+ research_prompt = self._build_research_context_prompt(git_analysis, days)
1535
1524
 
1536
- Args:
1537
- session_id: Optional specific session ID to resume
1525
+ # 3. Display prompt for PM to delegate
1526
+ console.print("\n" + "=" * 80)
1527
+ console.print("📋 DELEGATE TO RESEARCH AGENT:")
1528
+ console.print("=" * 80 + "\n")
1529
+ console.print(research_prompt)
1530
+ console.print("\n" + "=" * 80 + "\n")
1538
1531
 
1539
- Returns:
1540
- Dict containing resume result
1541
- """
1542
- try:
1543
- # Check if there are any paused sessions
1544
- available_sessions = self.resume_manager.list_available_sessions()
1532
+ return {
1533
+ "status": "context_ready",
1534
+ "git_analysis": git_analysis,
1535
+ "research_prompt": research_prompt,
1536
+ "recommendation": "PM should delegate this prompt to Research agent",
1537
+ }
1545
1538
 
1546
- if not available_sessions:
1547
- console.print("\n[yellow]No paused sessions found.[/yellow]")
1548
- console.print(
1549
- "[dim]To pause a session, run: claude-mpm mpm-init pause[/dim]\n"
1550
- )
1551
- return {"status": "error", "message": "No paused sessions found"}
1539
+ def _build_research_context_prompt(
1540
+ self, git_analysis: Dict[str, Any], days: int
1541
+ ) -> str:
1542
+ """Build structured Research agent delegation prompt from git analysis."""
1552
1543
 
1553
- # If no session ID specified and multiple sessions exist, let user choose
1554
- if not session_id and len(available_sessions) > 1:
1555
- console.print("\n[bold]Available Paused Sessions:[/bold]\n")
1556
- for idx, session in enumerate(available_sessions, 1):
1557
- paused_at = session.get("paused_at", "unknown")
1558
- try:
1559
- dt = datetime.fromisoformat(paused_at.replace("Z", "+00:00"))
1560
- paused_display = dt.strftime("%Y-%m-%d %H:%M")
1561
- except Exception:
1562
- paused_display = paused_at
1544
+ # Extract key data
1545
+ commits = git_analysis.get("commits", [])
1546
+ branches = git_analysis.get("branches", [])
1547
+ contributors = git_analysis.get("contributors", {})
1548
+ file_changes = git_analysis.get("file_changes", {})
1563
1549
 
1564
- summary = session.get("summary", "No summary")
1565
- if len(summary) > 60:
1566
- summary = summary[:57] + "..."
1550
+ # Build prompt following Prompt Engineer's template
1551
+ prompt = f"""# Project Context Analysis Mission
1567
1552
 
1568
- console.print(
1569
- f" [{idx}] {session['session_id']} - {paused_display}"
1570
- )
1571
- console.print(f" {summary}\n")
1553
+ You are Research agent analyzing git history to provide PM with intelligent project context for resuming work.
1572
1554
 
1573
- choice = Prompt.ask(
1574
- "Select session to resume",
1575
- choices=[str(i) for i in range(1, len(available_sessions) + 1)],
1576
- default="1",
1577
- )
1578
- session_id = available_sessions[int(choice) - 1]["session_id"]
1555
+ ## Analysis Scope
1556
+ - **Time Range**: Last {days} days
1557
+ - **Commits Analyzed**: {len(commits)} commits
1558
+ - **Branches**: {', '.join(branches[:5]) if branches else 'main'}
1559
+ - **Contributors**: {', '.join(contributors.keys()) if contributors else 'Unknown'}
1579
1560
 
1580
- # Resume the session
1581
- result = self.resume_manager.resume_session(session_id=session_id)
1561
+ ## Your Mission
1582
1562
 
1583
- # Display resume context
1584
- if result.get("status") == "success":
1585
- console.print("\n[dim]Resume context has been displayed above.[/dim]\n")
1563
+ Analyze git history to answer these questions for PM:
1586
1564
 
1587
- return result
1565
+ 1. **What was being worked on?** (Active work streams)
1566
+ 2. **Why was this work happening?** (Intent and motivation)
1567
+ 3. **What's the natural next step?** (Continuation recommendations)
1568
+ 4. **What needs attention?** (Risks, stalls, conflicts)
1588
1569
 
1589
- except Exception as e:
1590
- logger.error(f"Failed to resume session: {e}")
1591
- console.print(f"[red]❌ Error resuming session: {e}[/red]")
1592
- return {"status": "error", "message": str(e)}
1570
+ ## Git Data Provided
1571
+
1572
+ ### Recent Commits ({min(len(commits), 10)} most recent):
1573
+ """
1574
+
1575
+ # Add recent commits
1576
+ for commit in commits[:10]:
1577
+ author = commit.get("author", "Unknown")
1578
+ timestamp = commit.get("timestamp", "Unknown date")
1579
+ message = commit.get("message", "No message")
1580
+ files = commit.get("files", [])
1581
+
1582
+ prompt += f"\n- **{timestamp}** by {author}"
1583
+ prompt += f"\n {message}"
1584
+ prompt += f"\n Files changed: {len(files)}\n"
1585
+
1586
+ # Add file change summary
1587
+ if file_changes:
1588
+ # Sort by modifications count
1589
+ sorted_files = sorted(
1590
+ file_changes.items(),
1591
+ key=lambda x: x[1].get("modifications", 0),
1592
+ reverse=True,
1593
+ )
1594
+ prompt += "\n### Most Changed Files:\n"
1595
+ for file_path, file_data in sorted_files[:10]:
1596
+ modifications = file_data.get("modifications", 0)
1597
+ file_contributors = file_data.get("contributors", [])
1598
+ prompt += f"- {file_path}: {modifications} changes ({len(file_contributors)} contributor{'s' if len(file_contributors) != 1 else ''})\n"
1599
+
1600
+ # Add contributor summary
1601
+ if contributors:
1602
+ prompt += "\n### Contributors:\n"
1603
+ sorted_contributors = sorted(
1604
+ contributors.items(),
1605
+ key=lambda x: x[1].get("commits", 0),
1606
+ reverse=True,
1607
+ )
1608
+ for name, info in sorted_contributors[:5]:
1609
+ commit_count = info.get("commits", 0)
1610
+ prompt += f"- {name}: {commit_count} commit{'s' if commit_count != 1 else ''}\n"
1611
+
1612
+ # Add analysis instructions
1613
+ prompt += """
1614
+
1615
+ ## Analysis Instructions
1616
+
1617
+ ### Phase 1: Work Stream Identification
1618
+ Group related commits into thematic work streams. For each stream:
1619
+ - **Name**: Infer from commit messages (e.g., "Authentication refactor")
1620
+ - **Status**: ongoing/completed/stalled
1621
+ - **Commits**: Count of commits in this stream
1622
+ - **Intent**: WHY this work (from commit bodies/messages)
1623
+ - **Key Files**: Most changed files in this stream
1624
+
1625
+ ### Phase 2: Risk Detection
1626
+ Identify:
1627
+ - **Stalled Work**: Work streams with no activity >3 days
1628
+ - **Anti-Patterns**: WIP commits, temp commits, debug commits
1629
+ - **Documentation Lag**: Code changes without doc updates
1630
+ - **Conflicts**: Merge conflicts or divergent branches
1631
+
1632
+ ### Phase 3: Recommendations
1633
+ Based on analysis:
1634
+ 1. **Primary Focus**: Most active/recent work to continue
1635
+ 2. **Quick Wins**: Small tasks that could be finished
1636
+ 3. **Blockers**: Issues preventing progress
1637
+ 4. **Next Steps**: Logical continuation points
1638
+
1639
+ ## Output Format
1640
+
1641
+ Provide a clear markdown summary with:
1642
+
1643
+ 1. **Active Work Streams** (What was being worked on)
1644
+ 2. **Intent Summary** (Why this work matters)
1645
+ 3. **Risks Detected** (What needs attention)
1646
+ 4. **Recommended Next Actions** (What to work on)
1647
+
1648
+ Keep it concise (<1000 words) but actionable.
1649
+
1650
+ ## Success Criteria
1651
+ - Work streams accurately reflect development themes
1652
+ - Intent captures the "why" not just "what"
1653
+ - Recommendations are specific and actionable
1654
+ - Risks are prioritized by impact
1655
+ """
1656
+
1657
+ return prompt
1593
1658
 
1594
1659
  def _display_results(self, result: Dict, verbose: bool):
1595
1660
  """Display initialization results."""
@@ -1748,9 +1813,9 @@ def mpm_init(
1748
1813
  - Optimize for AI agent understanding
1749
1814
  - Perform AST analysis for enhanced developer documentation
1750
1815
 
1751
- Session Management:
1752
- - pause: Pause the current session and save state
1753
- - resume: Resume the most recent (or specified) paused session
1816
+ Context Management:
1817
+ - resume: Analyze git history to provide context for resuming work
1818
+ - --catchup: Show recent commit history for PM context
1754
1819
 
1755
1820
  Update Mode:
1756
1821
  When CLAUDE.md exists, the command offers to update rather than recreate,
@@ -1758,8 +1823,7 @@ def mpm_init(
1758
1823
 
1759
1824
  Examples:
1760
1825
  claude-mpm mpm-init # Initialize/update current directory
1761
- claude-mpm mpm-init pause # Pause current session
1762
- claude-mpm mpm-init resume # Resume latest session
1826
+ claude-mpm mpm-init --catchup # Show recent git history for context
1763
1827
  claude-mpm mpm-init --review # Review project state without changes
1764
1828
  claude-mpm mpm-init --update # Force update mode
1765
1829
  claude-mpm mpm-init --organize # Organize misplaced files
@@ -1807,24 +1871,18 @@ def mpm_init(
1807
1871
  sys.exit(1)
1808
1872
 
1809
1873
 
1810
- @mpm_init.command(name="pause")
1874
+ @mpm_init.command(name="context")
1811
1875
  @click.option(
1812
- "--summary",
1813
- "-s",
1876
+ "--session-id",
1877
+ "-i",
1814
1878
  type=str,
1815
- help="Summary of what you were working on",
1816
- )
1817
- @click.option(
1818
- "--accomplishment",
1819
- "-a",
1820
- multiple=True,
1821
- help="Accomplishment from this session (can be used multiple times)",
1879
+ help="Unused (for compatibility) - will be removed in future version",
1822
1880
  )
1823
1881
  @click.option(
1824
- "--next-step",
1825
- "-n",
1826
- multiple=True,
1827
- help="Next step to continue work (can be used multiple times)",
1882
+ "--days",
1883
+ type=int,
1884
+ default=7,
1885
+ help="Number of days of git history to analyze (default: 7)",
1828
1886
  )
1829
1887
  @click.argument(
1830
1888
  "project_path",
@@ -1832,52 +1890,51 @@ def mpm_init(
1832
1890
  required=False,
1833
1891
  default=".",
1834
1892
  )
1835
- def pause_session(summary, accomplishment, next_step, project_path):
1893
+ def context_command(session_id, days, project_path):
1836
1894
  """
1837
- Pause the current session and save state.
1895
+ Provide intelligent context for resuming work based on git history.
1838
1896
 
1839
- This command captures:
1840
- - Conversation summary and progress
1841
- - Git repository state (commits, branch, status)
1842
- - Todo list status
1843
- - Working directory changes
1844
-
1845
- The saved state enables seamless session resumption with full context.
1897
+ Analyzes recent git history and generates a Research agent delegation
1898
+ prompt for intelligent project context reconstruction.
1846
1899
 
1847
1900
  Examples:
1848
- claude-mpm mpm-init pause
1849
- claude-mpm mpm-init pause -s "Working on authentication feature"
1850
- claude-mpm mpm-init pause -a "Implemented login" -a "Added tests"
1851
- claude-mpm mpm-init pause -n "Add logout functionality"
1901
+ claude-mpm mpm-init context # Analyze last 7 days
1902
+ claude-mpm mpm-init context --days 14 # Analyze last 14 days
1903
+ claude-mpm mpm-init context --days 30 # Analyze last 30 days
1904
+
1905
+ Note: 'resume' is deprecated, use 'context' instead.
1852
1906
  """
1853
1907
  try:
1854
1908
  command = MPMInitCommand(Path(project_path))
1855
1909
 
1856
- result = command.handle_pause(
1857
- summary=summary,
1858
- accomplishments=list(accomplishment) if accomplishment else None,
1859
- next_steps=list(next_step) if next_step else None,
1860
- )
1910
+ result = command.handle_context(session_id=session_id, days=days)
1861
1911
 
1862
- if result["status"] == "success":
1912
+ if result["status"] == "success" or result["status"] == "context_ready":
1863
1913
  sys.exit(0)
1864
1914
  else:
1865
1915
  sys.exit(1)
1866
1916
 
1867
1917
  except KeyboardInterrupt:
1868
- console.print("\n[yellow]Pause cancelled by user[/yellow]")
1918
+ console.print("\n[yellow]Context analysis cancelled by user[/yellow]")
1869
1919
  sys.exit(130)
1870
1920
  except Exception as e:
1871
- console.print(f"[red]Pause failed: {e}[/red]")
1921
+ console.print(f"[red]Context analysis failed: {e}[/red]")
1872
1922
  sys.exit(1)
1873
1923
 
1874
1924
 
1875
- @mpm_init.command(name="resume")
1925
+ # Add deprecated 'resume' alias for backward compatibility
1926
+ @mpm_init.command(name="resume", hidden=True)
1876
1927
  @click.option(
1877
1928
  "--session-id",
1878
1929
  "-i",
1879
1930
  type=str,
1880
- help="Specific session ID to resume (defaults to most recent)",
1931
+ help="Unused (for compatibility) - will be removed in future version",
1932
+ )
1933
+ @click.option(
1934
+ "--days",
1935
+ type=int,
1936
+ default=7,
1937
+ help="Number of days of git history to analyze (default: 7)",
1881
1938
  )
1882
1939
  @click.argument(
1883
1940
  "project_path",
@@ -1885,35 +1942,32 @@ def pause_session(summary, accomplishment, next_step, project_path):
1885
1942
  required=False,
1886
1943
  default=".",
1887
1944
  )
1888
- def resume_session(session_id, project_path):
1945
+ def resume_session(session_id, days, project_path):
1889
1946
  """
1890
- Resume a paused session.
1891
-
1892
- This command:
1893
- - Loads the most recent (or specified) paused session
1894
- - Checks for changes since the pause (commits, file changes, branch changes)
1895
- - Displays warnings for any conflicts
1896
- - Generates a complete context summary for seamless resumption
1947
+ [DEPRECATED] Use 'context' instead.
1897
1948
 
1898
- Examples:
1899
- claude-mpm mpm-init resume
1900
- claude-mpm mpm-init resume --session-id session-20251019-120000
1949
+ This command is deprecated and will be removed in a future version.
1950
+ Please use 'claude-mpm mpm-init context' instead.
1901
1951
  """
1952
+ console.print(
1953
+ "[yellow]⚠️ Warning: 'resume' is deprecated. Use 'context' instead.[/yellow]"
1954
+ )
1955
+ console.print("[dim]Run: claude-mpm mpm-init context[/dim]\n")
1956
+
1902
1957
  try:
1903
1958
  command = MPMInitCommand(Path(project_path))
1959
+ result = command.handle_context(session_id=session_id, days=days)
1904
1960
 
1905
- result = command.handle_resume(session_id=session_id)
1906
-
1907
- if result["status"] == "success":
1961
+ if result["status"] == "success" or result["status"] == "context_ready":
1908
1962
  sys.exit(0)
1909
1963
  else:
1910
1964
  sys.exit(1)
1911
1965
 
1912
1966
  except KeyboardInterrupt:
1913
- console.print("\n[yellow]Resume cancelled by user[/yellow]")
1967
+ console.print("\n[yellow]Context analysis cancelled by user[/yellow]")
1914
1968
  sys.exit(130)
1915
1969
  except Exception as e:
1916
- console.print(f"[red]Resume failed: {e}[/red]")
1970
+ console.print(f"[red]Context analysis failed: {e}[/red]")
1917
1971
  sys.exit(1)
1918
1972
 
1919
1973
 
@@ -25,31 +25,17 @@ def manage_mpm_init(args):
25
25
  # Import the command implementation
26
26
  from .mpm_init import MPMInitCommand
27
27
 
28
- # Handle pause/resume subcommands
28
+ # Handle context subcommands
29
29
  subcommand = getattr(args, "subcommand", None)
30
30
 
31
- if subcommand == "pause":
32
- # Get project path
33
- project_path = (
34
- Path(args.project_path) if hasattr(args, "project_path") else Path.cwd()
35
- )
36
-
37
- # Create command instance
38
- command = MPMInitCommand(project_path)
31
+ if subcommand in ("context", "resume"):
32
+ # Show deprecation warning for 'resume'
33
+ if subcommand == "resume":
34
+ console.print(
35
+ "[yellow]⚠️ Warning: 'resume' is deprecated. Use 'context' instead.[/yellow]"
36
+ )
37
+ console.print("[dim]Run: claude-mpm mpm-init context[/dim]\n")
39
38
 
40
- # Handle pause with optional arguments
41
- result = command.handle_pause(
42
- summary=getattr(args, "summary", None),
43
- accomplishments=getattr(args, "accomplishment", None),
44
- next_steps=getattr(args, "next_step", None),
45
- )
46
-
47
- # Return appropriate exit code
48
- if result.get("status") == "success":
49
- return 0
50
- return 1
51
-
52
- if subcommand == "resume":
53
39
  # Get project path
54
40
  project_path = (
55
41
  Path(args.project_path) if hasattr(args, "project_path") else Path.cwd()
@@ -58,11 +44,14 @@ def manage_mpm_init(args):
58
44
  # Create command instance
59
45
  command = MPMInitCommand(project_path)
60
46
 
61
- # Handle resume with optional session ID
62
- result = command.handle_resume(session_id=getattr(args, "session_id", None))
47
+ # Handle context with optional session ID and days
48
+ result = command.handle_context(
49
+ session_id=getattr(args, "session_id", None),
50
+ days=getattr(args, "days", 7),
51
+ )
63
52
 
64
53
  # Return appropriate exit code
65
- if result.get("status") == "success":
54
+ if result.get("status") in ("success", "context_ready"):
66
55
  return 0
67
56
  return 1
68
57