claude-mpm 4.7.2__py3-none-any.whl → 4.7.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/PM_INSTRUCTIONS.md +0 -1
- claude_mpm/agents/templates/project_organizer.json +3 -3
- claude_mpm/cli/commands/mpm_init.py +458 -0
- claude_mpm/cli/commands/mpm_init_handler.py +4 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +37 -7
- claude_mpm/commands/mpm-help.md +4 -1
- claude_mpm/commands/mpm-init.md +47 -3
- claude_mpm/commands/mpm-monitor.md +409 -0
- claude_mpm/commands/mpm-organize.md +23 -10
- claude_mpm/dashboard/static/built/shared/page-structure.js +0 -2
- claude_mpm/dashboard/static/index-hub-backup.html +713 -0
- claude_mpm/dashboard/static/index.html +529 -607
- claude_mpm/dashboard/static/production/main.html +0 -17
- claude_mpm/dashboard/templates/index.html +0 -17
- claude_mpm/services/project/enhanced_analyzer.py +31 -4
- {claude_mpm-4.7.2.dist-info → claude_mpm-4.7.4.dist-info}/METADATA +1 -1
- {claude_mpm-4.7.2.dist-info → claude_mpm-4.7.4.dist-info}/RECORD +22 -21
- claude_mpm/dashboard/static/monitors-index.html +0 -218
- {claude_mpm-4.7.2.dist-info → claude_mpm-4.7.4.dist-info}/WHEEL +0 -0
- {claude_mpm-4.7.2.dist-info → claude_mpm-4.7.4.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.7.2.dist-info → claude_mpm-4.7.4.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.7.2.dist-info → claude_mpm-4.7.4.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.7.
|
1
|
+
4.7.4
|
@@ -110,7 +110,6 @@ These commands start with `/mpm-` and are Claude MPM system commands:
|
|
110
110
|
- `/mpm-init` - Initialize MPM project (use SlashCommand tool)
|
111
111
|
- `/mpm-status` - Check MPM service status (use SlashCommand tool)
|
112
112
|
- `/mpm-monitor` - Control monitoring services (use SlashCommand tool)
|
113
|
-
- `/mpm-browser-monitor` - Control browser monitoring (use SlashCommand tool)
|
114
113
|
|
115
114
|
### How to Execute MPM Commands
|
116
115
|
✅ **CORRECT**: Use SlashCommand tool
|
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"schema_version": "1.2.0",
|
3
3
|
"agent_id": "project-organizer",
|
4
|
-
"agent_version": "1.
|
4
|
+
"agent_version": "1.2.0",
|
5
5
|
"agent_type": "ops",
|
6
6
|
"metadata": {
|
7
7
|
"name": "Project Organizer Agent",
|
@@ -15,7 +15,7 @@
|
|
15
15
|
],
|
16
16
|
"author": "Claude MPM Team",
|
17
17
|
"created_at": "2025-08-15T00:00:00.000000Z",
|
18
|
-
"updated_at": "2025-
|
18
|
+
"updated_at": "2025-10-08T00:00:00.000000Z",
|
19
19
|
"color": "purple"
|
20
20
|
},
|
21
21
|
"capabilities": {
|
@@ -47,7 +47,7 @@
|
|
47
47
|
]
|
48
48
|
}
|
49
49
|
},
|
50
|
-
"instructions": "# Project Organizer Agent\n\n**Inherits from**: BASE_OPS_AGENT.md\n**Focus**: Intelligent project structure management and organization\n\n## Core Expertise\n\nLearn existing patterns, enforce consistent structure,
|
50
|
+
"instructions": "# Project Organizer Agent\n\n**Inherits from**: BASE_OPS_AGENT.md\n**Focus**: Intelligent project structure management and organization\n\n## Core Expertise\n\nLearn existing patterns, enforce consistent structure, suggest optimal file placement, and maintain organization documentation.\n\n## Organization Standard Management\n\n**CRITICAL**: Always ensure organization standards are documented and accessible.\n\n### Standard Documentation Protocol\n\n1. **Verify Organization Standard Exists**\n - Check if `docs/reference/PROJECT_ORGANIZATION.md` exists\n - If missing, create it with current organization rules\n - If exists, verify it's up to date with current patterns\n\n2. **Update CLAUDE.md Linking**\n - Verify CLAUDE.md links to PROJECT_ORGANIZATION.md\n - Add link in \"Project Structure Requirements\" section if missing\n - Format: `See [docs/reference/PROJECT_ORGANIZATION.md](docs/reference/PROJECT_ORGANIZATION.md)`\n\n3. **Keep Standard Current**\n - Update standard when new patterns are established\n - Document framework-specific rules as discovered\n - Add version and timestamp to changes\n\n### Organization Standard Location\n- **Primary**: `docs/reference/PROJECT_ORGANIZATION.md`\n- **Reference from**: CLAUDE.md, /mpm-organize command docs\n- **Format**: Markdown with comprehensive rules, examples, and tables\n\n## Pattern Detection Protocol\n\n### 1. Structure Analysis\n- Scan directory hierarchy and patterns\n- Identify naming conventions (camelCase, kebab-case, snake_case)\n- Map file type locations\n- Detect framework-specific conventions\n- Identify organization type (feature/type/domain-based)\n\n### 2. Pattern Categories\n- **By Feature**: `/features/auth/`, `/features/dashboard/`\n- **By Type**: `/controllers/`, `/models/`, `/views/`\n- **By Domain**: `/user/`, `/product/`, `/order/`\n- **Mixed**: Combination approaches\n- **Test Organization**: Colocated vs separate\n\n## File Placement Logic\n\n### Decision Process\n1. Consult PROJECT_ORGANIZATION.md for official rules\n2. Analyze file purpose and type\n3. Apply learned project patterns\n4. Consider framework requirements\n5. Provide clear reasoning\n\n### Framework Handling\n- **Next.js**: Respect pages/app, public, API routes\n- **Django**: Maintain app structure, migrations, templates\n- **Rails**: Follow MVC, assets pipeline, migrations\n- **React**: Component organization, hooks, utils\n\n## Organization Enforcement\n\n### Validation Steps\n1. Check files against PROJECT_ORGANIZATION.md rules\n2. Flag convention violations\n3. Generate safe move operations\n4. Use `git mv` for version control\n5. Update import paths\n6. Update organization standard if needed\n\n### Batch Reorganization\n```bash\n# Analyze violations\nfind . -type f | while read file; do\n expected=$(determine_location \"$file\")\n [ \"$file\" != \"$expected\" ] && echo \"Move: $file -> $expected\"\ndone\n\n# Execute with backup\ntar -czf backup_$(date +%Y%m%d).tar.gz .\n# Run moves with git mv\n```\n\n## Documentation Maintenance\n\n### PROJECT_ORGANIZATION.md Requirements\n- Comprehensive directory structure\n- File placement rules by type and purpose\n- Naming conventions for all file types\n- Framework-specific organization rules\n- Migration procedures\n- Version history\n\n### CLAUDE.md Updates\n- Keep organization quick reference current\n- Link to PROJECT_ORGANIZATION.md prominently\n- Update when major structure changes occur\n\n## Organizer-Specific Todo Patterns\n\n**Analysis**:\n- `[Organizer] Detect project organization patterns`\n- `[Organizer] Identify framework conventions`\n- `[Organizer] Verify organization standard exists`\n\n**Placement**:\n- `[Organizer] Suggest location for API service`\n- `[Organizer] Plan feature module structure`\n\n**Enforcement**:\n- `[Organizer] Validate file organization`\n- `[Organizer] Generate reorganization plan`\n\n**Documentation**:\n- `[Organizer] Update PROJECT_ORGANIZATION.md`\n- `[Organizer] Update CLAUDE.md organization links`\n- `[Organizer] Document naming conventions`\n\n## Safety Measures\n\n- Create backups before reorganization\n- Preserve git history with git mv\n- Update imports after moves\n- Test build after changes\n- Respect .gitignore patterns\n- Document all organization changes\n\n## Success Criteria\n\n- Accurately detect patterns (90%+)\n- Correctly suggest locations\n- Maintain up-to-date documentation (PROJECT_ORGANIZATION.md)\n- Ensure CLAUDE.md links are current\n- Adapt to user corrections\n- Provide clear reasoning",
|
51
51
|
"knowledge": {
|
52
52
|
"domain_expertise": [
|
53
53
|
"Project structure patterns",
|
@@ -61,6 +61,10 @@ class MPMInitCommand:
|
|
61
61
|
preserve_custom: bool = True,
|
62
62
|
skip_archive: bool = False,
|
63
63
|
dry_run: bool = False,
|
64
|
+
quick_update: bool = False,
|
65
|
+
non_interactive: bool = False,
|
66
|
+
days: int = 30,
|
67
|
+
export: Optional[str] = None,
|
64
68
|
) -> Dict:
|
65
69
|
"""
|
66
70
|
Initialize project with Agentic Coder Optimizer standards.
|
@@ -78,6 +82,10 @@ class MPMInitCommand:
|
|
78
82
|
preserve_custom: Preserve custom sections when updating
|
79
83
|
skip_archive: Skip archiving existing files
|
80
84
|
dry_run: Show what would be done without making changes
|
85
|
+
quick_update: Perform lightweight update based on recent git activity
|
86
|
+
non_interactive: Non-interactive mode - display report only without prompting
|
87
|
+
days: Number of days for git history analysis (7, 14, 30, 60, or 90)
|
88
|
+
export: Export report to file (path or "auto" for default location)
|
81
89
|
|
82
90
|
Returns:
|
83
91
|
Dict containing initialization results
|
@@ -90,6 +98,13 @@ class MPMInitCommand:
|
|
90
98
|
if review_only:
|
91
99
|
return self._run_review_mode()
|
92
100
|
|
101
|
+
if quick_update:
|
102
|
+
return self._run_quick_update_mode(
|
103
|
+
days=days,
|
104
|
+
non_interactive=non_interactive,
|
105
|
+
export=export,
|
106
|
+
)
|
107
|
+
|
93
108
|
if has_existing and not force and not update_mode:
|
94
109
|
# Auto-select update mode if organize_files or dry_run is specified
|
95
110
|
if organize_files or dry_run:
|
@@ -572,6 +587,419 @@ The final CLAUDE.md should be a comprehensive, well-organized guide that any AI
|
|
572
587
|
|
573
588
|
console.print("\n" + "=" * 60 + "\n")
|
574
589
|
|
590
|
+
def _run_quick_update_mode(
|
591
|
+
self,
|
592
|
+
days: int = 30,
|
593
|
+
non_interactive: bool = False,
|
594
|
+
export: Optional[str] = None,
|
595
|
+
) -> Dict:
|
596
|
+
"""Run quick update mode - lightweight update based on recent git activity."""
|
597
|
+
console.print("\n[bold cyan]⚡ Quick Update Mode[/bold cyan]\n")
|
598
|
+
console.print(
|
599
|
+
f"[dim]Analyzing recent git activity ({days} days) for lightweight documentation update...[/dim]\n"
|
600
|
+
)
|
601
|
+
|
602
|
+
if not self.analyzer.is_git_repo:
|
603
|
+
console.print(
|
604
|
+
"[yellow]⚠️ Not a git repository. Quick update requires git.[/yellow]"
|
605
|
+
)
|
606
|
+
console.print(
|
607
|
+
"[dim]Tip: Use `/mpm-init --review` for non-git projects.[/dim]\n"
|
608
|
+
)
|
609
|
+
return {
|
610
|
+
"status": "error",
|
611
|
+
"message": "Quick update requires a git repository",
|
612
|
+
}
|
613
|
+
|
614
|
+
claude_md = self.project_path / "CLAUDE.md"
|
615
|
+
if not claude_md.exists():
|
616
|
+
console.print(
|
617
|
+
"[yellow]⚠️ CLAUDE.md not found. Quick update requires existing documentation.[/yellow]"
|
618
|
+
)
|
619
|
+
console.print(
|
620
|
+
"[dim]Tip: Use `/mpm-init` to create initial documentation.[/dim]\n"
|
621
|
+
)
|
622
|
+
return {
|
623
|
+
"status": "error",
|
624
|
+
"message": "Quick update requires existing CLAUDE.md",
|
625
|
+
}
|
626
|
+
|
627
|
+
with Progress(
|
628
|
+
SpinnerColumn(),
|
629
|
+
TextColumn("[progress.description]{task.description}"),
|
630
|
+
console=console,
|
631
|
+
) as progress:
|
632
|
+
# Analyze git history
|
633
|
+
task = progress.add_task(
|
634
|
+
f"[cyan]Analyzing git history ({days} days)...", total=None
|
635
|
+
)
|
636
|
+
git_analysis = self.analyzer.analyze_git_history(days_back=days)
|
637
|
+
progress.update(task, description="[green]✓ Git analysis complete")
|
638
|
+
|
639
|
+
# Analyze current documentation
|
640
|
+
task = progress.add_task(
|
641
|
+
"[cyan]Checking documentation status...", total=None
|
642
|
+
)
|
643
|
+
doc_analysis = self.doc_manager.analyze_existing_content()
|
644
|
+
progress.update(task, description="[green]✓ Documentation analyzed")
|
645
|
+
|
646
|
+
# Generate activity report
|
647
|
+
activity_report = self._generate_activity_report(
|
648
|
+
git_analysis, doc_analysis, days
|
649
|
+
)
|
650
|
+
|
651
|
+
# Display the report
|
652
|
+
self._display_activity_report(activity_report)
|
653
|
+
|
654
|
+
# Export report if requested
|
655
|
+
if export:
|
656
|
+
export_path = self._export_activity_report(activity_report, export)
|
657
|
+
console.print(f"\n[green]✅ Report exported to: {export_path}[/green]")
|
658
|
+
|
659
|
+
# Handle non-interactive mode
|
660
|
+
if non_interactive:
|
661
|
+
console.print(
|
662
|
+
"\n[cyan]ℹ️ Non-interactive mode: Report displayed, no changes made.[/cyan]"
|
663
|
+
)
|
664
|
+
return {
|
665
|
+
"status": "success",
|
666
|
+
"mode": "quick_update",
|
667
|
+
"activity_report": activity_report,
|
668
|
+
"changes_made": False,
|
669
|
+
"non_interactive": True,
|
670
|
+
}
|
671
|
+
|
672
|
+
# Offer to append activity notes to CLAUDE.md
|
673
|
+
console.print("\n[bold]Update Options:[/bold]")
|
674
|
+
console.print(" [1] Append activity summary to CLAUDE.md")
|
675
|
+
console.print(" [2] Display report only (no changes)")
|
676
|
+
console.print(" [3] Cancel")
|
677
|
+
|
678
|
+
from rich.prompt import Prompt
|
679
|
+
|
680
|
+
choice = Prompt.ask("\nSelect option", choices=["1", "2", "3"], default="2")
|
681
|
+
|
682
|
+
if choice == "1":
|
683
|
+
# Append activity notes
|
684
|
+
self._append_activity_notes(claude_md, activity_report)
|
685
|
+
console.print("\n[green]✅ Activity notes appended to CLAUDE.md[/green]")
|
686
|
+
|
687
|
+
# Archive the update
|
688
|
+
self.archive_manager.auto_archive_before_update(
|
689
|
+
claude_md, update_reason="Quick update - recent activity summary"
|
690
|
+
)
|
691
|
+
|
692
|
+
return {
|
693
|
+
"status": "success",
|
694
|
+
"mode": "quick_update",
|
695
|
+
"activity_report": activity_report,
|
696
|
+
"changes_made": True,
|
697
|
+
}
|
698
|
+
if choice == "2":
|
699
|
+
console.print("\n[cyan]Report generated - no changes made[/cyan]")
|
700
|
+
return {
|
701
|
+
"status": "success",
|
702
|
+
"mode": "quick_update",
|
703
|
+
"activity_report": activity_report,
|
704
|
+
"changes_made": False,
|
705
|
+
}
|
706
|
+
console.print("\n[yellow]Quick update cancelled[/yellow]")
|
707
|
+
return {"status": "cancelled", "message": "Quick update cancelled"}
|
708
|
+
|
709
|
+
def _generate_activity_report(
|
710
|
+
self, git_analysis: Dict, doc_analysis: Dict, days: int = 30
|
711
|
+
) -> Dict:
|
712
|
+
"""Generate activity report from git analysis and documentation status."""
|
713
|
+
from datetime import datetime, timezone
|
714
|
+
|
715
|
+
report = {
|
716
|
+
"period": f"Last {days} days",
|
717
|
+
"generated_at": datetime.now(timezone.utc).isoformat(),
|
718
|
+
"summary": {},
|
719
|
+
"recommendations": [],
|
720
|
+
}
|
721
|
+
|
722
|
+
# Git activity summary
|
723
|
+
if git_analysis.get("git_available"):
|
724
|
+
recent_commits = git_analysis.get("recent_commits", [])
|
725
|
+
changed_files = git_analysis.get("changed_files", {})
|
726
|
+
authors = git_analysis.get("authors", {})
|
727
|
+
branch_info = git_analysis.get("branch_info", {})
|
728
|
+
|
729
|
+
report["summary"] = {
|
730
|
+
"total_commits": len(recent_commits),
|
731
|
+
"total_authors": authors.get("total_authors", 0),
|
732
|
+
"files_changed": changed_files.get("total_files", 0),
|
733
|
+
"current_branch": branch_info.get("current_branch", "unknown"),
|
734
|
+
"has_uncommitted": branch_info.get("has_uncommitted_changes", False),
|
735
|
+
"uncommitted_count": branch_info.get("uncommitted_files", 0),
|
736
|
+
}
|
737
|
+
|
738
|
+
# Recent commits (last 10)
|
739
|
+
report["recent_commits"] = recent_commits[:10]
|
740
|
+
|
741
|
+
# Most changed files
|
742
|
+
most_changed = changed_files.get("most_changed", {})
|
743
|
+
report["hot_files"] = list(most_changed.items())[:10]
|
744
|
+
|
745
|
+
# Active branches
|
746
|
+
branches = branch_info.get("branches", [])
|
747
|
+
report["active_branches"] = [
|
748
|
+
b for b in branches if not b.startswith("remotes/")
|
749
|
+
][:5]
|
750
|
+
|
751
|
+
# Generate recommendations
|
752
|
+
if len(recent_commits) > 20:
|
753
|
+
report["recommendations"].append(
|
754
|
+
"High activity detected - consider updating architecture docs"
|
755
|
+
)
|
756
|
+
|
757
|
+
if changed_files.get("total_files", 0) > 50:
|
758
|
+
report["recommendations"].append(
|
759
|
+
"Many files changed - review CLAUDE.md for accuracy"
|
760
|
+
)
|
761
|
+
|
762
|
+
if branch_info.get("has_uncommitted_changes"):
|
763
|
+
report["recommendations"].append(
|
764
|
+
"Uncommitted changes detected - commit before updating docs"
|
765
|
+
)
|
766
|
+
|
767
|
+
# Check for documentation changes
|
768
|
+
doc_changes = git_analysis.get("documentation_changes", {})
|
769
|
+
if not doc_changes.get("has_recent_doc_changes"):
|
770
|
+
report["recommendations"].append(
|
771
|
+
"No recent doc updates - CLAUDE.md may be outdated"
|
772
|
+
)
|
773
|
+
|
774
|
+
# Documentation freshness
|
775
|
+
if doc_analysis.get("exists"):
|
776
|
+
report["doc_status"] = {
|
777
|
+
"size": doc_analysis.get("size", 0),
|
778
|
+
"lines": doc_analysis.get("lines", 0),
|
779
|
+
"has_priority_index": doc_analysis.get("has_priority_index", False),
|
780
|
+
"has_priority_markers": doc_analysis.get("has_priority_markers", False),
|
781
|
+
"last_modified": doc_analysis.get("last_modified", "unknown"),
|
782
|
+
}
|
783
|
+
|
784
|
+
if not doc_analysis.get("has_priority_markers"):
|
785
|
+
report["recommendations"].append(
|
786
|
+
"Add priority markers (🔴🟡🟢⚪) to CLAUDE.md"
|
787
|
+
)
|
788
|
+
|
789
|
+
return report
|
790
|
+
|
791
|
+
def _export_activity_report(self, report: Dict, export_path: str) -> Path:
|
792
|
+
"""Export activity report to a markdown file."""
|
793
|
+
from datetime import datetime, timezone
|
794
|
+
from pathlib import Path
|
795
|
+
|
796
|
+
# Determine export path
|
797
|
+
if export_path == "auto":
|
798
|
+
# Generate default path with timestamp
|
799
|
+
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
|
800
|
+
reports_dir = self.project_path / "docs" / "reports"
|
801
|
+
reports_dir.mkdir(parents=True, exist_ok=True)
|
802
|
+
file_path = reports_dir / f"activity-report-{timestamp}.md"
|
803
|
+
else:
|
804
|
+
# Use provided path
|
805
|
+
file_path = Path(export_path)
|
806
|
+
if not file_path.is_absolute():
|
807
|
+
file_path = self.project_path / file_path
|
808
|
+
# Create parent directory if needed
|
809
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
810
|
+
|
811
|
+
# Generate markdown content
|
812
|
+
summary = report.get("summary", {})
|
813
|
+
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
|
814
|
+
|
815
|
+
content = f"""# Activity Report
|
816
|
+
|
817
|
+
**Generated**: {timestamp}
|
818
|
+
**Analysis Period**: {report.get('period', 'Last 30 days')}
|
819
|
+
|
820
|
+
## Summary
|
821
|
+
|
822
|
+
- **Total Commits**: {summary.get('total_commits', 0)}
|
823
|
+
- **Active Contributors**: {summary.get('total_authors', 0)}
|
824
|
+
- **Files Modified**: {summary.get('files_changed', 0)}
|
825
|
+
- **Current Branch**: {summary.get('current_branch', 'unknown')}
|
826
|
+
"""
|
827
|
+
|
828
|
+
if summary.get("has_uncommitted"):
|
829
|
+
content += f"- **⚠️ Uncommitted Changes**: {summary.get('uncommitted_count', 0)} files\n"
|
830
|
+
|
831
|
+
# Recent commits
|
832
|
+
recent_commits = report.get("recent_commits", [])
|
833
|
+
if recent_commits:
|
834
|
+
content += "\n## Recent Commits\n\n"
|
835
|
+
for commit in recent_commits[:10]:
|
836
|
+
content += (
|
837
|
+
f"- `{commit['hash']}` {commit['message']} - {commit['author']}\n"
|
838
|
+
)
|
839
|
+
|
840
|
+
# Hot files
|
841
|
+
hot_files = report.get("hot_files", [])
|
842
|
+
if hot_files:
|
843
|
+
content += "\n## Most Changed Files\n\n"
|
844
|
+
for hot_file_path, changes in hot_files[:10]:
|
845
|
+
content += f"- `{hot_file_path}`: {changes} changes\n"
|
846
|
+
|
847
|
+
# Active branches
|
848
|
+
branches = report.get("active_branches", [])
|
849
|
+
if branches:
|
850
|
+
content += "\n## Active Branches\n\n"
|
851
|
+
for branch in branches:
|
852
|
+
marker = "→" if branch == summary.get("current_branch") else " "
|
853
|
+
content += f"{marker} {branch}\n"
|
854
|
+
|
855
|
+
# Documentation status
|
856
|
+
doc_status = report.get("doc_status", {})
|
857
|
+
if doc_status:
|
858
|
+
content += "\n## CLAUDE.md Status\n\n"
|
859
|
+
content += f"- **Size**: {doc_status.get('size', 0):,} characters\n"
|
860
|
+
content += f"- **Lines**: {doc_status.get('lines', 0)}\n"
|
861
|
+
content += f"- **Priority Markers**: {'✓' if doc_status.get('has_priority_markers') else '✗'}\n"
|
862
|
+
content += (
|
863
|
+
f"- **Last Modified**: {doc_status.get('last_modified', 'unknown')}\n"
|
864
|
+
)
|
865
|
+
|
866
|
+
# Recommendations
|
867
|
+
recommendations = report.get("recommendations", [])
|
868
|
+
if recommendations:
|
869
|
+
content += "\n## Recommendations\n\n"
|
870
|
+
for rec in recommendations:
|
871
|
+
content += f"- {rec}\n"
|
872
|
+
|
873
|
+
content += (
|
874
|
+
"\n---\n\n*Generated by Claude MPM `/mpm-init --quick-update --export`*\n"
|
875
|
+
)
|
876
|
+
|
877
|
+
# Write to file
|
878
|
+
file_path.write_text(content, encoding="utf-8")
|
879
|
+
|
880
|
+
return file_path
|
881
|
+
|
882
|
+
def _display_activity_report(self, report: Dict) -> None:
|
883
|
+
"""Display the activity report in a formatted manner."""
|
884
|
+
console.print("\n" + "=" * 60)
|
885
|
+
console.print("[bold]RECENT ACTIVITY SUMMARY[/bold]")
|
886
|
+
console.print("=" * 60 + "\n")
|
887
|
+
|
888
|
+
summary = report.get("summary", {})
|
889
|
+
period = report.get("period", "Last 30 days")
|
890
|
+
|
891
|
+
# Summary statistics
|
892
|
+
console.print(f"[bold cyan]📊 Activity Overview ({period.lower()})[/bold cyan]")
|
893
|
+
console.print(f" Total commits: {summary.get('total_commits', 0)}")
|
894
|
+
console.print(f" Active contributors: {summary.get('total_authors', 0)}")
|
895
|
+
console.print(f" Files modified: {summary.get('files_changed', 0)}")
|
896
|
+
console.print(f" Current branch: {summary.get('current_branch', 'unknown')}")
|
897
|
+
|
898
|
+
if summary.get("has_uncommitted"):
|
899
|
+
console.print(
|
900
|
+
f" [yellow]⚠️ Uncommitted changes: {summary.get('uncommitted_count', 0)} files[/yellow]"
|
901
|
+
)
|
902
|
+
|
903
|
+
# Recent commits
|
904
|
+
recent_commits = report.get("recent_commits", [])
|
905
|
+
if recent_commits:
|
906
|
+
console.print("\n[bold cyan]📝 Recent Commits (last 10)[/bold cyan]")
|
907
|
+
for commit in recent_commits[:10]:
|
908
|
+
console.print(
|
909
|
+
f" [{commit['hash']}] {commit['message'][:60]} - {commit['author']}"
|
910
|
+
)
|
911
|
+
|
912
|
+
# Hot files
|
913
|
+
hot_files = report.get("hot_files", [])
|
914
|
+
if hot_files:
|
915
|
+
console.print("\n[bold cyan]🔥 Most Changed Files[/bold cyan]")
|
916
|
+
for file_path, changes in hot_files[:10]:
|
917
|
+
console.print(f" {file_path}: {changes} changes")
|
918
|
+
|
919
|
+
# Active branches
|
920
|
+
branches = report.get("active_branches", [])
|
921
|
+
if branches:
|
922
|
+
console.print("\n[bold cyan]🌿 Active Branches[/bold cyan]")
|
923
|
+
for branch in branches:
|
924
|
+
marker = "→" if branch == summary.get("current_branch") else " "
|
925
|
+
console.print(f" {marker} {branch}")
|
926
|
+
|
927
|
+
# Documentation status
|
928
|
+
doc_status = report.get("doc_status", {})
|
929
|
+
if doc_status:
|
930
|
+
console.print("\n[bold cyan]📚 CLAUDE.md Status[/bold cyan]")
|
931
|
+
console.print(f" Size: {doc_status.get('size', 0):,} characters")
|
932
|
+
console.print(f" Lines: {doc_status.get('lines', 0)}")
|
933
|
+
console.print(
|
934
|
+
f" Priority markers: {'✓' if doc_status.get('has_priority_markers') else '✗'}"
|
935
|
+
)
|
936
|
+
console.print(
|
937
|
+
f" Last modified: {doc_status.get('last_modified', 'unknown')}"
|
938
|
+
)
|
939
|
+
|
940
|
+
# Recommendations
|
941
|
+
recommendations = report.get("recommendations", [])
|
942
|
+
if recommendations:
|
943
|
+
console.print("\n[bold cyan]💡 Recommendations[/bold cyan]")
|
944
|
+
for rec in recommendations:
|
945
|
+
console.print(f" → {rec}")
|
946
|
+
|
947
|
+
console.print("\n" + "=" * 60 + "\n")
|
948
|
+
|
949
|
+
def _append_activity_notes(self, claude_md_path: Path, report: Dict) -> None:
|
950
|
+
"""Append activity notes to CLAUDE.md."""
|
951
|
+
from datetime import datetime, timezone
|
952
|
+
|
953
|
+
# Generate activity summary section
|
954
|
+
summary = report.get("summary", {})
|
955
|
+
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
|
956
|
+
|
957
|
+
activity_section = f"""
|
958
|
+
|
959
|
+
---
|
960
|
+
|
961
|
+
## 📈 Recent Activity Summary
|
962
|
+
|
963
|
+
**Last Updated**: {timestamp}
|
964
|
+
**Analysis Period**: {report.get('period', 'Last 30 days')}
|
965
|
+
|
966
|
+
### Activity Metrics
|
967
|
+
- **Commits**: {summary.get('total_commits', 0)}
|
968
|
+
- **Contributors**: {summary.get('total_authors', 0)}
|
969
|
+
- **Files Changed**: {summary.get('files_changed', 0)}
|
970
|
+
- **Current Branch**: {summary.get('current_branch', 'unknown')}
|
971
|
+
"""
|
972
|
+
|
973
|
+
if summary.get("has_uncommitted"):
|
974
|
+
activity_section += f"- **⚠️ Uncommitted Changes**: {summary.get('uncommitted_count', 0)} files\n"
|
975
|
+
|
976
|
+
# Add recent commits
|
977
|
+
recent_commits = report.get("recent_commits", [])
|
978
|
+
if recent_commits:
|
979
|
+
activity_section += "\n### Recent Commits\n"
|
980
|
+
for commit in recent_commits[:5]:
|
981
|
+
activity_section += f"- `{commit['hash']}` {commit['message'][:60]} ({commit['author']})\n"
|
982
|
+
|
983
|
+
# Add hot files
|
984
|
+
hot_files = report.get("hot_files", [])
|
985
|
+
if hot_files:
|
986
|
+
activity_section += "\n### Most Active Files\n"
|
987
|
+
for file_path, changes in hot_files[:5]:
|
988
|
+
activity_section += f"- `{file_path}`: {changes} changes\n"
|
989
|
+
|
990
|
+
# Add recommendations
|
991
|
+
recommendations = report.get("recommendations", [])
|
992
|
+
if recommendations:
|
993
|
+
activity_section += "\n### 💡 Recommendations\n"
|
994
|
+
for rec in recommendations:
|
995
|
+
activity_section += f"- {rec}\n"
|
996
|
+
|
997
|
+
activity_section += "\n---\n"
|
998
|
+
|
999
|
+
# Append to file
|
1000
|
+
with open(claude_md_path, "a", encoding="utf-8") as f:
|
1001
|
+
f.write(activity_section)
|
1002
|
+
|
575
1003
|
def _run_dry_run_mode(self, organize_files: bool, has_existing: bool) -> Dict:
|
576
1004
|
"""Run dry-run mode to show what would be done without making changes."""
|
577
1005
|
console.print("\n[bold cyan]🔍 Dry Run Mode - Preview Changes[/bold cyan]\n")
|
@@ -1082,6 +1510,28 @@ preserving valuable project-specific information while refreshing standard secti
|
|
1082
1510
|
default=True,
|
1083
1511
|
help="Enable/disable AST analysis for enhanced documentation (default: enabled)",
|
1084
1512
|
)
|
1513
|
+
@click.option(
|
1514
|
+
"--quick-update",
|
1515
|
+
is_flag=True,
|
1516
|
+
help="Perform lightweight update based on recent git activity (default: 30 days)",
|
1517
|
+
)
|
1518
|
+
@click.option(
|
1519
|
+
"--non-interactive",
|
1520
|
+
is_flag=True,
|
1521
|
+
help="Non-interactive mode - display report only without prompting (use with --quick-update)",
|
1522
|
+
)
|
1523
|
+
@click.option(
|
1524
|
+
"--days",
|
1525
|
+
type=int,
|
1526
|
+
default=30,
|
1527
|
+
help="Number of days for git history analysis in quick update mode (default: 30)",
|
1528
|
+
)
|
1529
|
+
@click.option(
|
1530
|
+
"--export",
|
1531
|
+
type=str,
|
1532
|
+
default=None,
|
1533
|
+
help="Export activity report to file (default: docs/reports/activity-report-{timestamp}.md)",
|
1534
|
+
)
|
1085
1535
|
@click.argument(
|
1086
1536
|
"project_path",
|
1087
1537
|
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
@@ -1100,6 +1550,10 @@ def mpm_init(
|
|
1100
1550
|
skip_archive,
|
1101
1551
|
verbose,
|
1102
1552
|
ast_analysis,
|
1553
|
+
quick_update,
|
1554
|
+
non_interactive,
|
1555
|
+
days,
|
1556
|
+
export,
|
1103
1557
|
project_path,
|
1104
1558
|
):
|
1105
1559
|
"""
|
@@ -1141,6 +1595,10 @@ def mpm_init(
|
|
1141
1595
|
organize_files=organize,
|
1142
1596
|
preserve_custom=preserve_custom,
|
1143
1597
|
skip_archive=skip_archive,
|
1598
|
+
quick_update=quick_update,
|
1599
|
+
non_interactive=non_interactive,
|
1600
|
+
days=days,
|
1601
|
+
export=export,
|
1144
1602
|
)
|
1145
1603
|
|
1146
1604
|
# Exit with appropriate code
|
@@ -63,6 +63,10 @@ def manage_mpm_init(args):
|
|
63
63
|
"preserve_custom": getattr(args, "preserve_custom", True),
|
64
64
|
"skip_archive": getattr(args, "skip_archive", False),
|
65
65
|
"dry_run": getattr(args, "dry_run", False),
|
66
|
+
"quick_update": getattr(args, "quick_update", False),
|
67
|
+
"non_interactive": getattr(args, "non_interactive", False),
|
68
|
+
"days": getattr(args, "days", 30),
|
69
|
+
"export": getattr(args, "export", None),
|
66
70
|
}
|
67
71
|
|
68
72
|
# Execute initialization (now synchronous)
|
@@ -30,13 +30,18 @@ def add_mpm_init_subparser(subparsers: Any) -> None:
|
|
30
30
|
),
|
31
31
|
epilog=(
|
32
32
|
"Examples:\n"
|
33
|
-
" claude-mpm mpm-init
|
34
|
-
" claude-mpm mpm-init --review
|
35
|
-
" claude-mpm mpm-init --update
|
36
|
-
" claude-mpm mpm-init --
|
37
|
-
" claude-mpm mpm-init --
|
38
|
-
" claude-mpm mpm-init --
|
39
|
-
" claude-mpm mpm-init
|
33
|
+
" claude-mpm mpm-init # Initialize/update current directory\n"
|
34
|
+
" claude-mpm mpm-init --review # Review project state without changes\n"
|
35
|
+
" claude-mpm mpm-init --update # Update existing CLAUDE.md\n"
|
36
|
+
" claude-mpm mpm-init --quick-update # Quick update based on recent git activity\n"
|
37
|
+
" claude-mpm mpm-init --quick-update --non-interactive # View activity report only\n"
|
38
|
+
" claude-mpm mpm-init --quick-update --days 7 # Analyze last 7 days\n"
|
39
|
+
" claude-mpm mpm-init --quick-update --export # Export report to default location\n"
|
40
|
+
" claude-mpm mpm-init --quick-update --export report.md # Export to specific file\n"
|
41
|
+
" claude-mpm mpm-init --organize # Organize project structure\n"
|
42
|
+
" claude-mpm mpm-init --project-type web # Initialize as web project\n"
|
43
|
+
" claude-mpm mpm-init --framework react # Initialize with React framework\n"
|
44
|
+
" claude-mpm mpm-init /path/to/project --force # Force reinitialize project"
|
40
45
|
),
|
41
46
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
42
47
|
)
|
@@ -81,6 +86,31 @@ def add_mpm_init_subparser(subparsers: Any) -> None:
|
|
81
86
|
action="store_true",
|
82
87
|
help="Update existing CLAUDE.md instead of recreating (smart merge)",
|
83
88
|
)
|
89
|
+
init_group.add_argument(
|
90
|
+
"--quick-update",
|
91
|
+
action="store_true",
|
92
|
+
help="Perform lightweight update based on recent git activity (default: 30 days)",
|
93
|
+
)
|
94
|
+
init_group.add_argument(
|
95
|
+
"--non-interactive",
|
96
|
+
action="store_true",
|
97
|
+
help="Non-interactive mode - display report only without prompting for changes (use with --quick-update)",
|
98
|
+
)
|
99
|
+
init_group.add_argument(
|
100
|
+
"--days",
|
101
|
+
type=int,
|
102
|
+
default=30,
|
103
|
+
choices=[7, 14, 30, 60, 90],
|
104
|
+
help="Number of days for git history analysis in quick update mode (default: 30)",
|
105
|
+
)
|
106
|
+
init_group.add_argument(
|
107
|
+
"--export",
|
108
|
+
type=str,
|
109
|
+
nargs="?",
|
110
|
+
const="auto",
|
111
|
+
metavar="PATH",
|
112
|
+
help="Export activity report to file (default: docs/reports/activity-report-{timestamp}.md)",
|
113
|
+
)
|
84
114
|
init_group.add_argument(
|
85
115
|
"--review",
|
86
116
|
action="store_true",
|
claude_mpm/commands/mpm-help.md
CHANGED
@@ -75,9 +75,12 @@ Available Commands:
|
|
75
75
|
/mpm-organize [--dry-run] [--force]
|
76
76
|
Organize project file structure
|
77
77
|
|
78
|
-
/mpm-init
|
78
|
+
/mpm-init [update]
|
79
79
|
Initialize or update project documentation
|
80
80
|
|
81
|
+
/mpm-monitor [start|stop|restart|status|port]
|
82
|
+
Manage Socket.IO monitoring server and dashboard
|
83
|
+
|
81
84
|
Use '/mpm-help <command>' for detailed help on a specific command.
|
82
85
|
```
|
83
86
|
|