claude-mpm 4.15.6__py3-none-any.whl → 4.21.0__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/agents/BASE_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +272 -23
- claude_mpm/agents/PM_INSTRUCTIONS.md +49 -0
- claude_mpm/agents/agent_loader.py +4 -4
- claude_mpm/agents/templates/engineer.json +5 -1
- claude_mpm/agents/templates/php-engineer.json +10 -4
- claude_mpm/agents/templates/python_engineer.json +8 -3
- claude_mpm/agents/templates/rust_engineer.json +12 -7
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +525 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +67 -1
- claude_mpm/cli/commands/skills.py +488 -0
- claude_mpm/cli/executor.py +2 -0
- claude_mpm/cli/parsers/base_parser.py +7 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
- claude_mpm/cli/parsers/skills_parser.py +137 -0
- claude_mpm/cli/startup.py +57 -0
- claude_mpm/commands/mpm-auto-configure.md +52 -0
- claude_mpm/commands/mpm-help.md +3 -0
- claude_mpm/commands/mpm-init.md +112 -6
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +1 -0
- claude_mpm/config/agent_config.py +2 -2
- claude_mpm/constants.py +12 -0
- claude_mpm/core/config.py +42 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/interfaces.py +56 -1
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/hooks/__init__.py +8 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/auto_config_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
- claude_mpm/services/agents/deployment/agent_validator.py +17 -1
- claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
- claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
- claude_mpm/services/agents/local_template_manager.py +1 -1
- claude_mpm/services/agents/recommender.py +47 -0
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +87 -0
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +372 -0
- claude_mpm/services/core/interfaces.py +56 -1
- claude_mpm/services/core/models/agent_config.py +3 -0
- claude_mpm/services/core/models/process.py +4 -0
- claude_mpm/services/core/path_resolver.py +1 -1
- claude_mpm/services/diagnostics/models.py +21 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/local_ops/__init__.py +2 -0
- claude_mpm/services/mcp_config_manager.py +7 -131
- claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
- claude_mpm/services/mcp_gateway/core/process_pool.py +19 -10
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +26 -21
- claude_mpm/services/session_manager.py +205 -1
- claude_mpm/services/unified/deployment_strategies/local.py +1 -1
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +21 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +567 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +97 -9
- claude_mpm/skills/skills_registry.py +348 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/utils/agent_dependency_loader.py +2 -2
- {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.0.dist-info}/METADATA +211 -33
- {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.0.dist-info}/RECORD +192 -60
- claude_mpm/agents/INSTRUCTIONS_OLD_DEPRECATED.md +0 -602
- claude_mpm/cli/commands/mpm_init.py +0 -2008
- {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.0.dist-info}/WHEEL +0 -0
- {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.0.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.0.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.0.dist-info}/top_level.txt +0 -0
|
@@ -1,2008 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
MPM-Init Command - Initialize projects for optimal Claude Code and Claude MPM success.
|
|
3
|
-
|
|
4
|
-
This command delegates to the Agentic Coder Optimizer agent to establish clear,
|
|
5
|
-
single-path project standards for documentation, tooling, and workflows.
|
|
6
|
-
|
|
7
|
-
Enhanced with AST inspection capabilities for generating comprehensive developer
|
|
8
|
-
documentation with code structure analysis.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import contextlib
|
|
12
|
-
import subprocess
|
|
13
|
-
import sys
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
from typing import Any, Dict, List, Optional
|
|
16
|
-
|
|
17
|
-
import click
|
|
18
|
-
from rich.console import Console
|
|
19
|
-
from rich.panel import Panel
|
|
20
|
-
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
21
|
-
from rich.prompt import Prompt
|
|
22
|
-
|
|
23
|
-
from claude_mpm.core.enums import OperationResult
|
|
24
|
-
from claude_mpm.core.logging_utils import get_logger
|
|
25
|
-
|
|
26
|
-
# Import new services
|
|
27
|
-
from claude_mpm.services.project.archive_manager import ArchiveManager
|
|
28
|
-
from claude_mpm.services.project.documentation_manager import DocumentationManager
|
|
29
|
-
from claude_mpm.services.project.enhanced_analyzer import EnhancedProjectAnalyzer
|
|
30
|
-
from claude_mpm.services.project.project_organizer import ProjectOrganizer
|
|
31
|
-
from claude_mpm.utils.display_helper import DisplayHelper
|
|
32
|
-
|
|
33
|
-
logger = get_logger(__name__)
|
|
34
|
-
console = Console()
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class MPMInitCommand:
|
|
38
|
-
"""Initialize projects for optimal Claude Code and Claude MPM usage."""
|
|
39
|
-
|
|
40
|
-
def __init__(self, project_path: Optional[Path] = None):
|
|
41
|
-
"""Initialize the MPM-Init command."""
|
|
42
|
-
self.project_path = project_path or Path.cwd()
|
|
43
|
-
self.claude_mpm_script = self._find_claude_mpm_script()
|
|
44
|
-
|
|
45
|
-
# Initialize service components
|
|
46
|
-
self.doc_manager = DocumentationManager(self.project_path)
|
|
47
|
-
self.organizer = ProjectOrganizer(self.project_path)
|
|
48
|
-
self.archive_manager = ArchiveManager(self.project_path)
|
|
49
|
-
self.analyzer = EnhancedProjectAnalyzer(self.project_path)
|
|
50
|
-
self.display = DisplayHelper(console)
|
|
51
|
-
|
|
52
|
-
def initialize_project(
|
|
53
|
-
self,
|
|
54
|
-
project_type: Optional[str] = None,
|
|
55
|
-
framework: Optional[str] = None,
|
|
56
|
-
force: bool = False,
|
|
57
|
-
verbose: bool = False,
|
|
58
|
-
ast_analysis: bool = True,
|
|
59
|
-
update_mode: bool = False,
|
|
60
|
-
review_only: bool = False,
|
|
61
|
-
organize_files: bool = False,
|
|
62
|
-
preserve_custom: bool = True,
|
|
63
|
-
skip_archive: bool = False,
|
|
64
|
-
dry_run: bool = False,
|
|
65
|
-
quick_update: bool = False,
|
|
66
|
-
catchup: bool = False,
|
|
67
|
-
non_interactive: bool = False,
|
|
68
|
-
days: int = 30,
|
|
69
|
-
export: Optional[str] = None,
|
|
70
|
-
) -> Dict:
|
|
71
|
-
"""
|
|
72
|
-
Initialize project with Agentic Coder Optimizer standards.
|
|
73
|
-
|
|
74
|
-
Args:
|
|
75
|
-
project_type: Type of project (web, api, cli, library, etc.)
|
|
76
|
-
framework: Specific framework if applicable
|
|
77
|
-
force: Force initialization even if project already configured
|
|
78
|
-
verbose: Show detailed output
|
|
79
|
-
ast_analysis: Enable AST analysis for enhanced documentation
|
|
80
|
-
update_mode: Update existing CLAUDE.md instead of recreating
|
|
81
|
-
review_only: Review project state without making changes
|
|
82
|
-
organize_files: Organize misplaced files into proper directories
|
|
83
|
-
preserve_custom: Preserve custom sections when updating
|
|
84
|
-
skip_archive: Skip archiving existing files
|
|
85
|
-
dry_run: Show what would be done without making changes
|
|
86
|
-
quick_update: Perform lightweight update based on recent git activity
|
|
87
|
-
catchup: Show recent commit history from all branches for PM context
|
|
88
|
-
non_interactive: Non-interactive mode - display report only without prompting
|
|
89
|
-
days: Number of days for git history analysis (7, 14, 30, 60, or 90)
|
|
90
|
-
export: Export report to file (path or "auto" for default location)
|
|
91
|
-
|
|
92
|
-
Returns:
|
|
93
|
-
Dict containing initialization results
|
|
94
|
-
"""
|
|
95
|
-
try:
|
|
96
|
-
# Determine initialization mode
|
|
97
|
-
claude_md = self.project_path / "CLAUDE.md"
|
|
98
|
-
has_existing = claude_md.exists()
|
|
99
|
-
|
|
100
|
-
if review_only:
|
|
101
|
-
return self._run_review_mode()
|
|
102
|
-
|
|
103
|
-
if catchup:
|
|
104
|
-
data = self._catchup()
|
|
105
|
-
self._display_catchup(data)
|
|
106
|
-
return {
|
|
107
|
-
"status": OperationResult.SUCCESS,
|
|
108
|
-
"mode": "catchup",
|
|
109
|
-
"catchup_data": data,
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if quick_update:
|
|
113
|
-
return self._run_quick_update_mode(
|
|
114
|
-
days=days,
|
|
115
|
-
non_interactive=non_interactive,
|
|
116
|
-
export=export,
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
if has_existing and not force and not update_mode:
|
|
120
|
-
# Auto-select update mode if organize_files or dry_run is specified
|
|
121
|
-
if organize_files or dry_run:
|
|
122
|
-
update_mode = True
|
|
123
|
-
console.print(
|
|
124
|
-
"[cyan]Auto-selecting update mode for organization tasks.[/cyan]\n"
|
|
125
|
-
)
|
|
126
|
-
else:
|
|
127
|
-
# Offer update mode
|
|
128
|
-
console.print(
|
|
129
|
-
"[yellow]⚠️ Project already has CLAUDE.md file.[/yellow]\n"
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
# Show current documentation analysis
|
|
133
|
-
doc_analysis = self.doc_manager.analyze_existing_content()
|
|
134
|
-
self._display_documentation_status(doc_analysis)
|
|
135
|
-
|
|
136
|
-
# Ask user what to do
|
|
137
|
-
action = self._prompt_update_action()
|
|
138
|
-
|
|
139
|
-
if action == "update":
|
|
140
|
-
update_mode = True
|
|
141
|
-
elif action == "recreate":
|
|
142
|
-
force = True
|
|
143
|
-
elif action == "review":
|
|
144
|
-
return self._run_review_mode()
|
|
145
|
-
else:
|
|
146
|
-
return {
|
|
147
|
-
"status": OperationResult.CANCELLED,
|
|
148
|
-
"message": "Initialization cancelled",
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
# Handle dry-run mode
|
|
152
|
-
if dry_run:
|
|
153
|
-
return self._run_dry_run_mode(organize_files, has_existing)
|
|
154
|
-
|
|
155
|
-
# Run pre-initialization checks
|
|
156
|
-
if not review_only:
|
|
157
|
-
pre_check_result = self._run_pre_initialization_checks(
|
|
158
|
-
organize_files, skip_archive, has_existing
|
|
159
|
-
)
|
|
160
|
-
if pre_check_result.get("status") == OperationResult.ERROR:
|
|
161
|
-
return pre_check_result
|
|
162
|
-
|
|
163
|
-
# Build the delegation prompt
|
|
164
|
-
if update_mode:
|
|
165
|
-
prompt = self._build_update_prompt(
|
|
166
|
-
project_type, framework, ast_analysis, preserve_custom
|
|
167
|
-
)
|
|
168
|
-
else:
|
|
169
|
-
prompt = self._build_initialization_prompt(
|
|
170
|
-
project_type, framework, ast_analysis
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
# Show appropriate plan based on mode
|
|
174
|
-
if update_mode:
|
|
175
|
-
self._show_update_plan(ast_analysis, preserve_custom)
|
|
176
|
-
else:
|
|
177
|
-
self._show_initialization_plan(ast_analysis)
|
|
178
|
-
|
|
179
|
-
# Execute via claude-mpm run command
|
|
180
|
-
with Progress(
|
|
181
|
-
SpinnerColumn(),
|
|
182
|
-
TextColumn("[progress.description]{task.description}"),
|
|
183
|
-
console=console,
|
|
184
|
-
) as progress:
|
|
185
|
-
task_desc = (
|
|
186
|
-
"[cyan]Updating documentation..."
|
|
187
|
-
if update_mode
|
|
188
|
-
else "[cyan]Delegating to Agentic Coder Optimizer..."
|
|
189
|
-
)
|
|
190
|
-
task = progress.add_task(task_desc, total=None)
|
|
191
|
-
|
|
192
|
-
# Run the initialization through subprocess
|
|
193
|
-
result = self._run_initialization(prompt, verbose, update_mode)
|
|
194
|
-
|
|
195
|
-
complete_desc = (
|
|
196
|
-
"[green]✓ Update complete"
|
|
197
|
-
if update_mode
|
|
198
|
-
else "[green]✓ Initialization complete"
|
|
199
|
-
)
|
|
200
|
-
progress.update(task, description=complete_desc)
|
|
201
|
-
|
|
202
|
-
# Post-processing for update mode
|
|
203
|
-
if update_mode and result.get("status") == OperationResult.SUCCESS:
|
|
204
|
-
self._handle_update_post_processing()
|
|
205
|
-
|
|
206
|
-
return result
|
|
207
|
-
|
|
208
|
-
except Exception as e:
|
|
209
|
-
logger.error(f"Failed to initialize project: {e}")
|
|
210
|
-
console.print(f"[red]❌ Error: {e}[/red]")
|
|
211
|
-
return {"status": OperationResult.ERROR, "message": str(e)}
|
|
212
|
-
|
|
213
|
-
def _find_claude_mpm_script(self) -> Path:
|
|
214
|
-
"""Find the claude-mpm script location."""
|
|
215
|
-
# Try to find claude-mpm in the project scripts directory first
|
|
216
|
-
project_root = Path(__file__).parent.parent.parent.parent.parent
|
|
217
|
-
script_path = project_root / "scripts" / "claude-mpm"
|
|
218
|
-
if script_path.exists():
|
|
219
|
-
return script_path
|
|
220
|
-
# Otherwise assume it's in PATH
|
|
221
|
-
return Path("claude-mpm")
|
|
222
|
-
|
|
223
|
-
def _build_initialization_prompt(
|
|
224
|
-
self,
|
|
225
|
-
project_type: Optional[str] = None,
|
|
226
|
-
framework: Optional[str] = None,
|
|
227
|
-
ast_analysis: bool = True,
|
|
228
|
-
) -> str:
|
|
229
|
-
"""Build the initialization prompt for the agent."""
|
|
230
|
-
base_prompt = f"""Please delegate this task to the Agentic Coder Optimizer agent:
|
|
231
|
-
|
|
232
|
-
Initialize this project for optimal use with Claude Code and Claude MPM.
|
|
233
|
-
|
|
234
|
-
Project Path: {self.project_path}
|
|
235
|
-
"""
|
|
236
|
-
|
|
237
|
-
if project_type:
|
|
238
|
-
base_prompt += f"Project Type: {project_type}\n"
|
|
239
|
-
|
|
240
|
-
if framework:
|
|
241
|
-
base_prompt += f"Framework: {framework}\n"
|
|
242
|
-
|
|
243
|
-
base_prompt += """
|
|
244
|
-
Please perform the following initialization tasks:
|
|
245
|
-
|
|
246
|
-
1. **Analyze Current State**:
|
|
247
|
-
- Scan project structure and existing configurations
|
|
248
|
-
- Identify project type, language, and frameworks
|
|
249
|
-
- Check for existing documentation and tooling
|
|
250
|
-
|
|
251
|
-
2. **Create/Update CLAUDE.md**:
|
|
252
|
-
- Project overview and purpose
|
|
253
|
-
- Architecture and key components
|
|
254
|
-
- Development guidelines
|
|
255
|
-
- ONE clear way to: build, test, deploy, lint, format
|
|
256
|
-
- Links to all relevant documentation
|
|
257
|
-
- Common tasks and workflows
|
|
258
|
-
|
|
259
|
-
3. **Establish Single-Path Standards**:
|
|
260
|
-
- ONE command for each operation (build, test, lint, etc.)
|
|
261
|
-
- Clear documentation of THE way to do things
|
|
262
|
-
- Remove ambiguity in workflows
|
|
263
|
-
|
|
264
|
-
4. **Configure Development Tools**:
|
|
265
|
-
- Set up or verify linting configuration
|
|
266
|
-
- Configure code formatting standards
|
|
267
|
-
- Establish testing framework
|
|
268
|
-
- Add pre-commit hooks if needed
|
|
269
|
-
|
|
270
|
-
5. **Create Project Structure Documentation**:
|
|
271
|
-
- Document folder organization
|
|
272
|
-
- Explain where different file types belong
|
|
273
|
-
- Provide examples of proper file placement
|
|
274
|
-
|
|
275
|
-
6. **Set Up GitHub Integration** (if applicable):
|
|
276
|
-
- Create/update .github/workflows
|
|
277
|
-
- Add issue and PR templates
|
|
278
|
-
- Configure branch protection rules documentation
|
|
279
|
-
|
|
280
|
-
7. **Initialize Memory System**:
|
|
281
|
-
- Create .claude-mpm/memories/ directory
|
|
282
|
-
- Add initial memory files for key project knowledge
|
|
283
|
-
- Document memory usage patterns
|
|
284
|
-
|
|
285
|
-
8. **Generate Quick Start Guide**:
|
|
286
|
-
- Step-by-step setup instructions
|
|
287
|
-
- Common commands reference
|
|
288
|
-
- Troubleshooting guide
|
|
289
|
-
"""
|
|
290
|
-
|
|
291
|
-
if ast_analysis:
|
|
292
|
-
base_prompt += """
|
|
293
|
-
9. **Perform AST Analysis** (using Code Analyzer agent if needed):
|
|
294
|
-
- Parse code files to extract structure (classes, functions, methods)
|
|
295
|
-
- Generate comprehensive API documentation
|
|
296
|
-
- Create code architecture diagrams
|
|
297
|
-
- Document function signatures and dependencies
|
|
298
|
-
- Extract docstrings and inline comments
|
|
299
|
-
- Map code relationships and inheritance hierarchies
|
|
300
|
-
- Generate developer documentation with:
|
|
301
|
-
* Module overview and purpose
|
|
302
|
-
* Class hierarchies and relationships
|
|
303
|
-
* Function/method documentation
|
|
304
|
-
* Type annotations and parameter descriptions
|
|
305
|
-
* Code complexity metrics
|
|
306
|
-
* Dependency graphs
|
|
307
|
-
- Create DEVELOPER.md with technical architecture details
|
|
308
|
-
- Add CODE_STRUCTURE.md with AST-derived insights
|
|
309
|
-
"""
|
|
310
|
-
|
|
311
|
-
base_prompt += """
|
|
312
|
-
|
|
313
|
-
10. **Holistic CLAUDE.md Organization** (CRITICAL - Do this LAST):
|
|
314
|
-
After completing all initialization tasks, take a holistic look at the CLAUDE.md file and:
|
|
315
|
-
|
|
316
|
-
a) **Reorganize Content by Priority**:
|
|
317
|
-
- CRITICAL instructions (security, data handling, core business rules) at the TOP
|
|
318
|
-
- Project overview and purpose
|
|
319
|
-
- Key architectural decisions and constraints
|
|
320
|
-
- Development guidelines and standards
|
|
321
|
-
- Common tasks and workflows
|
|
322
|
-
- Links to additional documentation
|
|
323
|
-
- Nice-to-have or optional information at the BOTTOM
|
|
324
|
-
|
|
325
|
-
b) **Rank Instructions by Importance**:
|
|
326
|
-
- Use clear markers:
|
|
327
|
-
* 🔴 CRITICAL: Security, data handling, breaking changes, core business rules
|
|
328
|
-
* 🟡 IMPORTANT: Key workflows, architecture decisions, performance requirements
|
|
329
|
-
* 🟢 STANDARD: Common operations, coding standards, best practices
|
|
330
|
-
* ⚪ OPTIONAL: Nice-to-have features, experimental code, future considerations
|
|
331
|
-
- Group related instructions together
|
|
332
|
-
- Ensure no contradictory instructions exist
|
|
333
|
-
- Remove redundant or outdated information
|
|
334
|
-
- Add a "Priority Index" at the top listing all CRITICAL and IMPORTANT items
|
|
335
|
-
|
|
336
|
-
c) **Optimize for AI Agent Understanding**:
|
|
337
|
-
- Use consistent formatting and structure
|
|
338
|
-
- Provide clear examples for complex instructions
|
|
339
|
-
- Include "WHY" explanations for critical rules
|
|
340
|
-
- Add quick reference sections for common operations
|
|
341
|
-
- Ensure instructions are actionable and unambiguous
|
|
342
|
-
|
|
343
|
-
d) **Validate Completeness**:
|
|
344
|
-
- Ensure ALL critical project knowledge is captured
|
|
345
|
-
- Verify single-path principle (ONE way to do each task)
|
|
346
|
-
- Check that all referenced documentation exists
|
|
347
|
-
- Confirm all tools and dependencies are documented
|
|
348
|
-
- Test that a new AI agent could understand the project from CLAUDE.md alone
|
|
349
|
-
|
|
350
|
-
e) **Add Meta-Instructions Section**:
|
|
351
|
-
- Include a section about how to maintain CLAUDE.md
|
|
352
|
-
- Document when and how to update instructions
|
|
353
|
-
- Provide guidelines for instruction priority levels
|
|
354
|
-
- Add a changelog or last-updated timestamp
|
|
355
|
-
|
|
356
|
-
f) **Follow This CLAUDE.md Template Structure**:
|
|
357
|
-
```markdown
|
|
358
|
-
# Project Name - CLAUDE.md
|
|
359
|
-
|
|
360
|
-
## 🎯 Priority Index
|
|
361
|
-
### 🔴 CRITICAL Instructions
|
|
362
|
-
- [List all critical items with links to their sections]
|
|
363
|
-
|
|
364
|
-
### 🟡 IMPORTANT Instructions
|
|
365
|
-
- [List all important items with links to their sections]
|
|
366
|
-
|
|
367
|
-
## 📋 Project Overview
|
|
368
|
-
[Brief description and purpose]
|
|
369
|
-
|
|
370
|
-
## 🔴 CRITICAL: Security & Data Handling
|
|
371
|
-
[Critical security rules and data handling requirements]
|
|
372
|
-
|
|
373
|
-
## 🔴 CRITICAL: Core Business Rules
|
|
374
|
-
[Non-negotiable business logic and constraints]
|
|
375
|
-
|
|
376
|
-
## 🟡 IMPORTANT: Architecture & Design
|
|
377
|
-
[Key architectural decisions and patterns]
|
|
378
|
-
|
|
379
|
-
## 🟡 IMPORTANT: Development Workflow
|
|
380
|
-
### ONE Way to Build
|
|
381
|
-
### ONE Way to Test
|
|
382
|
-
### ONE Way to Deploy
|
|
383
|
-
|
|
384
|
-
## 🟢 STANDARD: Coding Guidelines
|
|
385
|
-
[Standard practices and conventions]
|
|
386
|
-
|
|
387
|
-
## 🟢 STANDARD: Common Tasks
|
|
388
|
-
[How to perform routine operations]
|
|
389
|
-
|
|
390
|
-
## 📚 Documentation Links
|
|
391
|
-
[Links to additional resources]
|
|
392
|
-
|
|
393
|
-
## ⚪ OPTIONAL: Future Enhancements
|
|
394
|
-
[Nice-to-have features and ideas]
|
|
395
|
-
|
|
396
|
-
## 📝 Meta: Maintaining This Document
|
|
397
|
-
- Last Updated: [timestamp]
|
|
398
|
-
- Update Frequency: [when to update]
|
|
399
|
-
- Priority Guidelines: [how to assign priorities]
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
Please ensure all documentation is clear, concise, and optimized for AI agents to understand and follow.
|
|
403
|
-
Focus on establishing ONE clear way to do ANYTHING in the project.
|
|
404
|
-
The final CLAUDE.md should be a comprehensive, well-organized guide that any AI agent can follow to work effectively on this project.
|
|
405
|
-
"""
|
|
406
|
-
|
|
407
|
-
return base_prompt
|
|
408
|
-
|
|
409
|
-
def _build_claude_mpm_command(self, verbose: bool) -> List[str]:
|
|
410
|
-
"""Build the claude-mpm run command with appropriate arguments."""
|
|
411
|
-
cmd = [str(self.claude_mpm_script)]
|
|
412
|
-
|
|
413
|
-
# Add top-level flags that go before 'run' subcommand
|
|
414
|
-
cmd.append("--no-check-dependencies")
|
|
415
|
-
|
|
416
|
-
# Now add the run subcommand
|
|
417
|
-
cmd.append("run")
|
|
418
|
-
|
|
419
|
-
# Add non-interactive mode
|
|
420
|
-
# We'll pass the prompt via stdin instead of -i flag
|
|
421
|
-
cmd.append("--non-interactive")
|
|
422
|
-
|
|
423
|
-
# Add verbose flag if requested (run subcommand argument)
|
|
424
|
-
if verbose:
|
|
425
|
-
cmd.append("--verbose")
|
|
426
|
-
|
|
427
|
-
return cmd
|
|
428
|
-
|
|
429
|
-
def _display_documentation_status(self, analysis: Dict) -> None:
|
|
430
|
-
"""Display current documentation status."""
|
|
431
|
-
self.display.display_documentation_status(analysis)
|
|
432
|
-
|
|
433
|
-
def _prompt_update_action(self) -> str:
|
|
434
|
-
"""Prompt user for update action."""
|
|
435
|
-
console.print("\n[bold]How would you like to proceed?[/bold]\n")
|
|
436
|
-
|
|
437
|
-
choices = {
|
|
438
|
-
"1": ("update", "Update existing CLAUDE.md (preserves custom content)"),
|
|
439
|
-
"2": ("recreate", "Recreate CLAUDE.md from scratch"),
|
|
440
|
-
"3": ("review", "Review project state without changes"),
|
|
441
|
-
"4": ("cancel", "Cancel operation"),
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
for key, (_, desc) in choices.items():
|
|
445
|
-
console.print(f" [{key}] {desc}")
|
|
446
|
-
|
|
447
|
-
choice = Prompt.ask(
|
|
448
|
-
"\nSelect option", choices=list(choices.keys()), default="1"
|
|
449
|
-
)
|
|
450
|
-
return choices[choice][0]
|
|
451
|
-
|
|
452
|
-
def _run_review_mode(self) -> Dict:
|
|
453
|
-
"""Run review mode to analyze project without changes."""
|
|
454
|
-
console.print("\n[bold cyan]🔍 Project Review Mode[/bold cyan]\n")
|
|
455
|
-
|
|
456
|
-
with Progress(
|
|
457
|
-
SpinnerColumn(),
|
|
458
|
-
TextColumn("[progress.description]{task.description}"),
|
|
459
|
-
console=console,
|
|
460
|
-
) as progress:
|
|
461
|
-
# Analyze project structure
|
|
462
|
-
task = progress.add_task("[cyan]Analyzing project structure...", total=None)
|
|
463
|
-
structure_report = self.organizer.verify_structure()
|
|
464
|
-
progress.update(task, description="[green]✓ Structure analysis complete")
|
|
465
|
-
|
|
466
|
-
# Analyze documentation
|
|
467
|
-
task = progress.add_task("[cyan]Analyzing documentation...", total=None)
|
|
468
|
-
doc_analysis = self.doc_manager.analyze_existing_content()
|
|
469
|
-
progress.update(
|
|
470
|
-
task, description="[green]✓ Documentation analysis complete"
|
|
471
|
-
)
|
|
472
|
-
|
|
473
|
-
# Analyze git history
|
|
474
|
-
if self.analyzer.is_git_repo:
|
|
475
|
-
task = progress.add_task("[cyan]Analyzing git history...", total=None)
|
|
476
|
-
git_analysis = self.analyzer.analyze_git_history()
|
|
477
|
-
progress.update(task, description="[green]✓ Git analysis complete")
|
|
478
|
-
else:
|
|
479
|
-
git_analysis = None
|
|
480
|
-
|
|
481
|
-
# Detect project state
|
|
482
|
-
task = progress.add_task("[cyan]Detecting project state...", total=None)
|
|
483
|
-
project_state = self.analyzer.detect_project_state()
|
|
484
|
-
progress.update(task, description="[green]✓ State detection complete")
|
|
485
|
-
|
|
486
|
-
# Display comprehensive report
|
|
487
|
-
self._display_review_report(
|
|
488
|
-
structure_report, doc_analysis, git_analysis, project_state
|
|
489
|
-
)
|
|
490
|
-
|
|
491
|
-
return {
|
|
492
|
-
"status": OperationResult.SUCCESS,
|
|
493
|
-
"mode": "review",
|
|
494
|
-
"structure_report": structure_report,
|
|
495
|
-
"documentation_analysis": doc_analysis,
|
|
496
|
-
"git_analysis": git_analysis,
|
|
497
|
-
"project_state": project_state,
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
def _display_review_report(
|
|
501
|
-
self, structure: Dict, docs: Dict, git: Optional[Dict], state: Dict
|
|
502
|
-
) -> None:
|
|
503
|
-
"""Display comprehensive review report."""
|
|
504
|
-
self.display.display_header("PROJECT REVIEW REPORT")
|
|
505
|
-
|
|
506
|
-
# Project State
|
|
507
|
-
state_data = {"Phase": state.get("phase", "unknown")}
|
|
508
|
-
if state.get("indicators"):
|
|
509
|
-
state_data["Indicators"] = state["indicators"][:5]
|
|
510
|
-
self.display.display_report_section("📊 Project State", state_data)
|
|
511
|
-
|
|
512
|
-
# Structure Report
|
|
513
|
-
structure_data = {
|
|
514
|
-
"Existing directories": len(structure.get("exists", [])),
|
|
515
|
-
"Missing directories": len(structure.get("missing", [])),
|
|
516
|
-
}
|
|
517
|
-
if structure.get("issues"):
|
|
518
|
-
structure_data["Issues found"] = len(structure["issues"])
|
|
519
|
-
structure_data["Issues"] = structure["issues"][:3]
|
|
520
|
-
self.display.display_report_section("📁 Project Structure", structure_data)
|
|
521
|
-
|
|
522
|
-
# Documentation Report
|
|
523
|
-
self.display.display_section_title("📚 Documentation Status")
|
|
524
|
-
if docs.get("exists"):
|
|
525
|
-
console.print(f" CLAUDE.md: Found ({docs.get('size', 0):,} chars)")
|
|
526
|
-
console.print(f" Sections: {len(docs.get('sections', []))}")
|
|
527
|
-
console.print(
|
|
528
|
-
f" Priority markers: {'Yes' if docs.get('has_priority_markers') else 'No'}"
|
|
529
|
-
)
|
|
530
|
-
else:
|
|
531
|
-
console.print(" CLAUDE.md: Not found")
|
|
532
|
-
|
|
533
|
-
# Git Analysis
|
|
534
|
-
if git and git.get("git_available"):
|
|
535
|
-
git_metrics = {
|
|
536
|
-
"Commits": len(git.get("recent_commits", [])),
|
|
537
|
-
"Authors": git.get("authors", {}).get("total_authors", 0),
|
|
538
|
-
"Changed files": git.get("changed_files", {}).get("total_files", 0),
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
if git.get("branch_info"):
|
|
542
|
-
branch_info = git["branch_info"]
|
|
543
|
-
git_metrics["Current branch"] = branch_info.get(
|
|
544
|
-
"current_branch", "unknown"
|
|
545
|
-
)
|
|
546
|
-
|
|
547
|
-
self.display.display_metrics_section(
|
|
548
|
-
"📈 Recent Activity (30 days)", git_metrics
|
|
549
|
-
)
|
|
550
|
-
|
|
551
|
-
if git.get("branch_info", {}).get("has_uncommitted_changes"):
|
|
552
|
-
self.display.display_metric_row(
|
|
553
|
-
"⚠️ Uncommitted changes",
|
|
554
|
-
f"{git['branch_info'].get('uncommitted_files', 0)} files",
|
|
555
|
-
warning=True,
|
|
556
|
-
)
|
|
557
|
-
|
|
558
|
-
# Recommendations
|
|
559
|
-
if state.get("recommendations"):
|
|
560
|
-
self.display.display_recommendations(state["recommendations"])
|
|
561
|
-
|
|
562
|
-
self.display.display_separator()
|
|
563
|
-
|
|
564
|
-
def _run_quick_update_mode(
|
|
565
|
-
self,
|
|
566
|
-
days: int = 30,
|
|
567
|
-
non_interactive: bool = False,
|
|
568
|
-
export: Optional[str] = None,
|
|
569
|
-
) -> Dict:
|
|
570
|
-
"""Run quick update mode - lightweight update based on recent git activity."""
|
|
571
|
-
console.print("\n[bold cyan]⚡ Quick Update Mode[/bold cyan]\n")
|
|
572
|
-
console.print(
|
|
573
|
-
f"[dim]Analyzing recent git activity ({days} days) for lightweight documentation update...[/dim]\n"
|
|
574
|
-
)
|
|
575
|
-
|
|
576
|
-
if not self.analyzer.is_git_repo:
|
|
577
|
-
console.print(
|
|
578
|
-
"[yellow]⚠️ Not a git repository. Quick update requires git.[/yellow]"
|
|
579
|
-
)
|
|
580
|
-
console.print(
|
|
581
|
-
"[dim]Tip: Use `/mpm-init --review` for non-git projects.[/dim]\n"
|
|
582
|
-
)
|
|
583
|
-
return {
|
|
584
|
-
"status": OperationResult.ERROR,
|
|
585
|
-
"message": "Quick update requires a git repository",
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
claude_md = self.project_path / "CLAUDE.md"
|
|
589
|
-
if not claude_md.exists():
|
|
590
|
-
console.print(
|
|
591
|
-
"[yellow]⚠️ CLAUDE.md not found. Quick update requires existing documentation.[/yellow]"
|
|
592
|
-
)
|
|
593
|
-
console.print(
|
|
594
|
-
"[dim]Tip: Use `/mpm-init` to create initial documentation.[/dim]\n"
|
|
595
|
-
)
|
|
596
|
-
return {
|
|
597
|
-
"status": OperationResult.ERROR,
|
|
598
|
-
"message": "Quick update requires existing CLAUDE.md",
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
with Progress(
|
|
602
|
-
SpinnerColumn(),
|
|
603
|
-
TextColumn("[progress.description]{task.description}"),
|
|
604
|
-
console=console,
|
|
605
|
-
) as progress:
|
|
606
|
-
# Analyze git history
|
|
607
|
-
task = progress.add_task(
|
|
608
|
-
f"[cyan]Analyzing git history ({days} days)...", total=None
|
|
609
|
-
)
|
|
610
|
-
git_analysis = self.analyzer.analyze_git_history(days_back=days)
|
|
611
|
-
progress.update(task, description="[green]✓ Git analysis complete")
|
|
612
|
-
|
|
613
|
-
# Analyze current documentation
|
|
614
|
-
task = progress.add_task(
|
|
615
|
-
"[cyan]Checking documentation status...", total=None
|
|
616
|
-
)
|
|
617
|
-
doc_analysis = self.doc_manager.analyze_existing_content()
|
|
618
|
-
progress.update(task, description="[green]✓ Documentation analyzed")
|
|
619
|
-
|
|
620
|
-
# Generate activity report
|
|
621
|
-
activity_report = self._generate_activity_report(
|
|
622
|
-
git_analysis, doc_analysis, days
|
|
623
|
-
)
|
|
624
|
-
|
|
625
|
-
# Display the report
|
|
626
|
-
self._display_activity_report(activity_report)
|
|
627
|
-
|
|
628
|
-
# Export report if requested
|
|
629
|
-
if export:
|
|
630
|
-
export_path = self._export_activity_report(activity_report, export)
|
|
631
|
-
console.print(f"\n[green]✅ Report exported to: {export_path}[/green]")
|
|
632
|
-
|
|
633
|
-
# Handle non-interactive mode
|
|
634
|
-
if non_interactive:
|
|
635
|
-
console.print(
|
|
636
|
-
"\n[cyan]ℹ️ Non-interactive mode: Report displayed, no changes made.[/cyan]"
|
|
637
|
-
)
|
|
638
|
-
return {
|
|
639
|
-
"status": OperationResult.SUCCESS,
|
|
640
|
-
"mode": "quick_update",
|
|
641
|
-
"activity_report": activity_report,
|
|
642
|
-
"changes_made": False,
|
|
643
|
-
"non_interactive": True,
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
# Offer to append activity notes to CLAUDE.md
|
|
647
|
-
console.print("\n[bold]Update Options:[/bold]")
|
|
648
|
-
console.print(" [1] Append activity summary to CLAUDE.md")
|
|
649
|
-
console.print(" [2] Display report only (no changes)")
|
|
650
|
-
console.print(" [3] Cancel")
|
|
651
|
-
|
|
652
|
-
from rich.prompt import Prompt
|
|
653
|
-
|
|
654
|
-
choice = Prompt.ask("\nSelect option", choices=["1", "2", "3"], default="2")
|
|
655
|
-
|
|
656
|
-
if choice == "1":
|
|
657
|
-
# Append activity notes
|
|
658
|
-
self._append_activity_notes(claude_md, activity_report)
|
|
659
|
-
console.print("\n[green]✅ Activity notes appended to CLAUDE.md[/green]")
|
|
660
|
-
|
|
661
|
-
# Archive the update
|
|
662
|
-
self.archive_manager.auto_archive_before_update(
|
|
663
|
-
claude_md, update_reason="Quick update - recent activity summary"
|
|
664
|
-
)
|
|
665
|
-
|
|
666
|
-
return {
|
|
667
|
-
"status": OperationResult.SUCCESS,
|
|
668
|
-
"mode": "quick_update",
|
|
669
|
-
"activity_report": activity_report,
|
|
670
|
-
"changes_made": True,
|
|
671
|
-
}
|
|
672
|
-
if choice == "2":
|
|
673
|
-
console.print("\n[cyan]Report generated - no changes made[/cyan]")
|
|
674
|
-
return {
|
|
675
|
-
"status": OperationResult.SUCCESS,
|
|
676
|
-
"mode": "quick_update",
|
|
677
|
-
"activity_report": activity_report,
|
|
678
|
-
"changes_made": False,
|
|
679
|
-
}
|
|
680
|
-
console.print("\n[yellow]Quick update cancelled[/yellow]")
|
|
681
|
-
return {
|
|
682
|
-
"status": OperationResult.CANCELLED,
|
|
683
|
-
"message": "Quick update cancelled",
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
def _catchup(self) -> Dict[str, Any]:
|
|
687
|
-
"""Get recent commit history for PM context.
|
|
688
|
-
|
|
689
|
-
Returns:
|
|
690
|
-
Dict containing commit history and contributor stats
|
|
691
|
-
"""
|
|
692
|
-
from collections import Counter
|
|
693
|
-
from datetime import datetime
|
|
694
|
-
from subprocess import run
|
|
695
|
-
|
|
696
|
-
try:
|
|
697
|
-
# Get last 25 commits from all branches with author info
|
|
698
|
-
result = run(
|
|
699
|
-
["git", "log", "--all", "--format=%h|%an|%ai|%s", "-25"],
|
|
700
|
-
capture_output=True,
|
|
701
|
-
text=True,
|
|
702
|
-
check=True,
|
|
703
|
-
cwd=str(self.project_path),
|
|
704
|
-
)
|
|
705
|
-
|
|
706
|
-
commits = []
|
|
707
|
-
authors = []
|
|
708
|
-
|
|
709
|
-
for line in result.stdout.strip().split("\n"):
|
|
710
|
-
if not line:
|
|
711
|
-
continue
|
|
712
|
-
|
|
713
|
-
parts = line.split("|", 3)
|
|
714
|
-
if len(parts) == 4:
|
|
715
|
-
hash_val, author, date_str, message = parts
|
|
716
|
-
|
|
717
|
-
# Parse date
|
|
718
|
-
try:
|
|
719
|
-
dt = datetime.fromisoformat(date_str.replace(" ", "T", 1))
|
|
720
|
-
date_display = dt.strftime("%Y-%m-%d %H:%M")
|
|
721
|
-
except Exception:
|
|
722
|
-
date_display = date_str[:16]
|
|
723
|
-
|
|
724
|
-
commits.append(
|
|
725
|
-
{
|
|
726
|
-
"hash": hash_val,
|
|
727
|
-
"author": author,
|
|
728
|
-
"date": date_display,
|
|
729
|
-
"message": message,
|
|
730
|
-
}
|
|
731
|
-
)
|
|
732
|
-
authors.append(author)
|
|
733
|
-
|
|
734
|
-
# Calculate contributor stats
|
|
735
|
-
author_counts = Counter(authors)
|
|
736
|
-
|
|
737
|
-
return {
|
|
738
|
-
"commits": commits,
|
|
739
|
-
"total_commits": len(commits),
|
|
740
|
-
"contributors": dict(author_counts),
|
|
741
|
-
"contributor_count": len(author_counts),
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
except Exception as e:
|
|
745
|
-
console.print(f"[yellow]Could not retrieve commit history: {e}[/yellow]")
|
|
746
|
-
return {
|
|
747
|
-
"commits": [],
|
|
748
|
-
"total_commits": 0,
|
|
749
|
-
"contributors": {},
|
|
750
|
-
"contributor_count": 0,
|
|
751
|
-
"error": str(e),
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
def _display_catchup(self, data: Dict[str, Any]) -> None:
|
|
755
|
-
"""Display catchup information to console.
|
|
756
|
-
|
|
757
|
-
Args:
|
|
758
|
-
data: Commit history data from _catchup()
|
|
759
|
-
"""
|
|
760
|
-
from rich.panel import Panel
|
|
761
|
-
from rich.table import Table
|
|
762
|
-
|
|
763
|
-
if data.get("error"):
|
|
764
|
-
console.print(
|
|
765
|
-
Panel(
|
|
766
|
-
"[yellow]Not a git repository or no commits found[/yellow]",
|
|
767
|
-
title="⚠️ Catchup Status",
|
|
768
|
-
border_style="yellow",
|
|
769
|
-
)
|
|
770
|
-
)
|
|
771
|
-
return
|
|
772
|
-
|
|
773
|
-
# Display contributor summary
|
|
774
|
-
if data["contributors"]:
|
|
775
|
-
console.print("\n[bold cyan]👥 Active Contributors[/bold cyan]")
|
|
776
|
-
for author, count in sorted(
|
|
777
|
-
data["contributors"].items(), key=lambda x: x[1], reverse=True
|
|
778
|
-
):
|
|
779
|
-
console.print(
|
|
780
|
-
f" • [green]{author}[/green]: {count} commit{'s' if count != 1 else ''}"
|
|
781
|
-
)
|
|
782
|
-
|
|
783
|
-
# Display commit history table
|
|
784
|
-
if data["commits"]:
|
|
785
|
-
console.print(
|
|
786
|
-
f"\n[bold cyan]📝 Last {data['total_commits']} Commits[/bold cyan]"
|
|
787
|
-
)
|
|
788
|
-
|
|
789
|
-
table = Table(
|
|
790
|
-
show_header=True, header_style="bold magenta", border_style="dim"
|
|
791
|
-
)
|
|
792
|
-
table.add_column("#", style="dim", width=3)
|
|
793
|
-
table.add_column("Hash", style="yellow", width=8)
|
|
794
|
-
table.add_column("Author", style="green", width=20)
|
|
795
|
-
table.add_column("Date", style="cyan", width=16)
|
|
796
|
-
table.add_column("Message", style="white")
|
|
797
|
-
|
|
798
|
-
for idx, commit in enumerate(data["commits"], 1):
|
|
799
|
-
# Truncate message if too long
|
|
800
|
-
msg = commit["message"]
|
|
801
|
-
if len(msg) > 80:
|
|
802
|
-
msg = msg[:77] + "..."
|
|
803
|
-
|
|
804
|
-
# Truncate author if too long
|
|
805
|
-
author = commit["author"]
|
|
806
|
-
if len(author) > 18:
|
|
807
|
-
author = author[:18] + "..."
|
|
808
|
-
|
|
809
|
-
table.add_row(str(idx), commit["hash"], author, commit["date"], msg)
|
|
810
|
-
|
|
811
|
-
console.print(table)
|
|
812
|
-
|
|
813
|
-
# Display PM recommendations
|
|
814
|
-
console.print("\n[bold cyan]💡 PM Recommendations[/bold cyan]")
|
|
815
|
-
console.print(
|
|
816
|
-
f" • Total activity: {data['total_commits']} commits from {data['contributor_count']} contributor{'s' if data['contributor_count'] != 1 else ''}"
|
|
817
|
-
)
|
|
818
|
-
console.print(" • Review commit messages for recent project context")
|
|
819
|
-
console.print(" • Identify development patterns and focus areas")
|
|
820
|
-
console.print(" • Use this context to inform current work priorities\n")
|
|
821
|
-
|
|
822
|
-
def _generate_activity_report(
|
|
823
|
-
self, git_analysis: Dict, doc_analysis: Dict, days: int = 30
|
|
824
|
-
) -> Dict:
|
|
825
|
-
"""Generate activity report from git analysis and documentation status."""
|
|
826
|
-
from datetime import datetime, timezone
|
|
827
|
-
|
|
828
|
-
report = {
|
|
829
|
-
"period": f"Last {days} days",
|
|
830
|
-
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
831
|
-
"summary": {},
|
|
832
|
-
"recommendations": [],
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
# Git activity summary
|
|
836
|
-
if git_analysis.get("git_available"):
|
|
837
|
-
recent_commits = git_analysis.get("recent_commits", [])
|
|
838
|
-
changed_files = git_analysis.get("changed_files", {})
|
|
839
|
-
authors = git_analysis.get("authors", {})
|
|
840
|
-
branch_info = git_analysis.get("branch_info", {})
|
|
841
|
-
|
|
842
|
-
report["summary"] = {
|
|
843
|
-
"total_commits": len(recent_commits),
|
|
844
|
-
"total_authors": authors.get("total_authors", 0),
|
|
845
|
-
"files_changed": changed_files.get("total_files", 0),
|
|
846
|
-
"current_branch": branch_info.get("current_branch", "unknown"),
|
|
847
|
-
"has_uncommitted": branch_info.get("has_uncommitted_changes", False),
|
|
848
|
-
"uncommitted_count": branch_info.get("uncommitted_files", 0),
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
# Recent commits (last 10)
|
|
852
|
-
report["recent_commits"] = recent_commits[:10]
|
|
853
|
-
|
|
854
|
-
# Most changed files
|
|
855
|
-
most_changed = changed_files.get("most_changed", {})
|
|
856
|
-
report["hot_files"] = list(most_changed.items())[:10]
|
|
857
|
-
|
|
858
|
-
# Active branches
|
|
859
|
-
branches = branch_info.get("branches", [])
|
|
860
|
-
report["active_branches"] = [
|
|
861
|
-
b for b in branches if not b.startswith("remotes/")
|
|
862
|
-
][:5]
|
|
863
|
-
|
|
864
|
-
# Generate recommendations
|
|
865
|
-
if len(recent_commits) > 20:
|
|
866
|
-
report["recommendations"].append(
|
|
867
|
-
"High activity detected - consider updating architecture docs"
|
|
868
|
-
)
|
|
869
|
-
|
|
870
|
-
if changed_files.get("total_files", 0) > 50:
|
|
871
|
-
report["recommendations"].append(
|
|
872
|
-
"Many files changed - review CLAUDE.md for accuracy"
|
|
873
|
-
)
|
|
874
|
-
|
|
875
|
-
if branch_info.get("has_uncommitted_changes"):
|
|
876
|
-
report["recommendations"].append(
|
|
877
|
-
"Uncommitted changes detected - commit before updating docs"
|
|
878
|
-
)
|
|
879
|
-
|
|
880
|
-
# Check for documentation changes
|
|
881
|
-
doc_changes = git_analysis.get("documentation_changes", {})
|
|
882
|
-
if not doc_changes.get("has_recent_doc_changes"):
|
|
883
|
-
report["recommendations"].append(
|
|
884
|
-
"No recent doc updates - CLAUDE.md may be outdated"
|
|
885
|
-
)
|
|
886
|
-
|
|
887
|
-
# Documentation freshness
|
|
888
|
-
if doc_analysis.get("exists"):
|
|
889
|
-
report["doc_status"] = {
|
|
890
|
-
"size": doc_analysis.get("size", 0),
|
|
891
|
-
"lines": doc_analysis.get("lines", 0),
|
|
892
|
-
"has_priority_index": doc_analysis.get("has_priority_index", False),
|
|
893
|
-
"has_priority_markers": doc_analysis.get("has_priority_markers", False),
|
|
894
|
-
"last_modified": doc_analysis.get("last_modified", "unknown"),
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
if not doc_analysis.get("has_priority_markers"):
|
|
898
|
-
report["recommendations"].append(
|
|
899
|
-
"Add priority markers (🔴🟡🟢⚪) to CLAUDE.md"
|
|
900
|
-
)
|
|
901
|
-
|
|
902
|
-
return report
|
|
903
|
-
|
|
904
|
-
def _export_activity_report(self, report: Dict, export_path: str) -> Path:
|
|
905
|
-
"""Export activity report to a markdown file."""
|
|
906
|
-
from datetime import datetime, timezone
|
|
907
|
-
from pathlib import Path
|
|
908
|
-
|
|
909
|
-
# Determine export path
|
|
910
|
-
if export_path == "auto":
|
|
911
|
-
# Generate default path with timestamp
|
|
912
|
-
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
|
|
913
|
-
reports_dir = self.project_path / "docs" / "reports"
|
|
914
|
-
reports_dir.mkdir(parents=True, exist_ok=True)
|
|
915
|
-
file_path = reports_dir / f"activity-report-{timestamp}.md"
|
|
916
|
-
else:
|
|
917
|
-
# Use provided path
|
|
918
|
-
file_path = Path(export_path)
|
|
919
|
-
if not file_path.is_absolute():
|
|
920
|
-
file_path = self.project_path / file_path
|
|
921
|
-
# Create parent directory if needed
|
|
922
|
-
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
923
|
-
|
|
924
|
-
# Generate markdown content
|
|
925
|
-
summary = report.get("summary", {})
|
|
926
|
-
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
|
|
927
|
-
|
|
928
|
-
content = f"""# Activity Report
|
|
929
|
-
|
|
930
|
-
**Generated**: {timestamp}
|
|
931
|
-
**Analysis Period**: {report.get('period', 'Last 30 days')}
|
|
932
|
-
|
|
933
|
-
## Summary
|
|
934
|
-
|
|
935
|
-
- **Total Commits**: {summary.get('total_commits', 0)}
|
|
936
|
-
- **Active Contributors**: {summary.get('total_authors', 0)}
|
|
937
|
-
- **Files Modified**: {summary.get('files_changed', 0)}
|
|
938
|
-
- **Current Branch**: {summary.get('current_branch', 'unknown')}
|
|
939
|
-
"""
|
|
940
|
-
|
|
941
|
-
if summary.get("has_uncommitted"):
|
|
942
|
-
content += f"- **⚠️ Uncommitted Changes**: {summary.get('uncommitted_count', 0)} files\n"
|
|
943
|
-
|
|
944
|
-
# Recent commits
|
|
945
|
-
recent_commits = report.get("recent_commits", [])
|
|
946
|
-
if recent_commits:
|
|
947
|
-
content += "\n## Recent Commits\n\n"
|
|
948
|
-
for commit in recent_commits[:10]:
|
|
949
|
-
content += (
|
|
950
|
-
f"- `{commit['hash']}` {commit['message']} - {commit['author']}\n"
|
|
951
|
-
)
|
|
952
|
-
|
|
953
|
-
# Hot files
|
|
954
|
-
hot_files = report.get("hot_files", [])
|
|
955
|
-
if hot_files:
|
|
956
|
-
content += "\n## Most Changed Files\n\n"
|
|
957
|
-
for hot_file_path, changes in hot_files[:10]:
|
|
958
|
-
content += f"- `{hot_file_path}`: {changes} changes\n"
|
|
959
|
-
|
|
960
|
-
# Active branches
|
|
961
|
-
branches = report.get("active_branches", [])
|
|
962
|
-
if branches:
|
|
963
|
-
content += "\n## Active Branches\n\n"
|
|
964
|
-
for branch in branches:
|
|
965
|
-
marker = "→" if branch == summary.get("current_branch") else " "
|
|
966
|
-
content += f"{marker} {branch}\n"
|
|
967
|
-
|
|
968
|
-
# Documentation status
|
|
969
|
-
doc_status = report.get("doc_status", {})
|
|
970
|
-
if doc_status:
|
|
971
|
-
content += "\n## CLAUDE.md Status\n\n"
|
|
972
|
-
content += f"- **Size**: {doc_status.get('size', 0):,} characters\n"
|
|
973
|
-
content += f"- **Lines**: {doc_status.get('lines', 0)}\n"
|
|
974
|
-
content += f"- **Priority Markers**: {'✓' if doc_status.get('has_priority_markers') else '✗'}\n"
|
|
975
|
-
content += (
|
|
976
|
-
f"- **Last Modified**: {doc_status.get('last_modified', 'unknown')}\n"
|
|
977
|
-
)
|
|
978
|
-
|
|
979
|
-
# Recommendations
|
|
980
|
-
recommendations = report.get("recommendations", [])
|
|
981
|
-
if recommendations:
|
|
982
|
-
content += "\n## Recommendations\n\n"
|
|
983
|
-
for rec in recommendations:
|
|
984
|
-
content += f"- {rec}\n"
|
|
985
|
-
|
|
986
|
-
content += (
|
|
987
|
-
"\n---\n\n*Generated by Claude MPM `/mpm-init --quick-update --export`*\n"
|
|
988
|
-
)
|
|
989
|
-
|
|
990
|
-
# Write to file
|
|
991
|
-
file_path.write_text(content, encoding="utf-8")
|
|
992
|
-
|
|
993
|
-
return file_path
|
|
994
|
-
|
|
995
|
-
def _display_activity_report(self, report: Dict) -> None:
|
|
996
|
-
"""Display the activity report in a formatted manner."""
|
|
997
|
-
self.display.display_header("RECENT ACTIVITY SUMMARY")
|
|
998
|
-
|
|
999
|
-
summary = report.get("summary", {})
|
|
1000
|
-
period = report.get("period", "Last 30 days")
|
|
1001
|
-
|
|
1002
|
-
# Summary statistics
|
|
1003
|
-
self.display.display_activity_summary(summary, period)
|
|
1004
|
-
|
|
1005
|
-
# Recent commits
|
|
1006
|
-
recent_commits = report.get("recent_commits", [])
|
|
1007
|
-
if recent_commits:
|
|
1008
|
-
self.display.display_commit_list(recent_commits)
|
|
1009
|
-
|
|
1010
|
-
# Hot files
|
|
1011
|
-
hot_files = report.get("hot_files", [])
|
|
1012
|
-
if hot_files:
|
|
1013
|
-
self.display.display_file_change_list(hot_files)
|
|
1014
|
-
|
|
1015
|
-
# Active branches
|
|
1016
|
-
branches = report.get("active_branches", [])
|
|
1017
|
-
current_branch = summary.get("current_branch", "unknown")
|
|
1018
|
-
if branches:
|
|
1019
|
-
self.display.display_branch_list(branches, current_branch)
|
|
1020
|
-
|
|
1021
|
-
# Documentation status
|
|
1022
|
-
doc_status = report.get("doc_status", {})
|
|
1023
|
-
if doc_status:
|
|
1024
|
-
doc_metrics = {
|
|
1025
|
-
"Size": f"{doc_status.get('size', 0):,} characters",
|
|
1026
|
-
"Lines": doc_status.get("lines", 0),
|
|
1027
|
-
"Priority markers": (
|
|
1028
|
-
"✓" if doc_status.get("has_priority_markers") else "✗"
|
|
1029
|
-
),
|
|
1030
|
-
"Last modified": doc_status.get("last_modified", "unknown"),
|
|
1031
|
-
}
|
|
1032
|
-
self.display.display_metrics_section("📚 CLAUDE.md Status", doc_metrics)
|
|
1033
|
-
|
|
1034
|
-
# Recommendations
|
|
1035
|
-
recommendations = report.get("recommendations", [])
|
|
1036
|
-
if recommendations:
|
|
1037
|
-
self.display.display_recommendations(recommendations)
|
|
1038
|
-
|
|
1039
|
-
self.display.display_separator()
|
|
1040
|
-
|
|
1041
|
-
def _append_activity_notes(self, claude_md_path: Path, report: Dict) -> None:
|
|
1042
|
-
"""Append activity notes to CLAUDE.md."""
|
|
1043
|
-
from datetime import datetime, timezone
|
|
1044
|
-
|
|
1045
|
-
# Generate activity summary section
|
|
1046
|
-
summary = report.get("summary", {})
|
|
1047
|
-
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
|
|
1048
|
-
|
|
1049
|
-
activity_section = f"""
|
|
1050
|
-
|
|
1051
|
-
---
|
|
1052
|
-
|
|
1053
|
-
## 📈 Recent Activity Summary
|
|
1054
|
-
|
|
1055
|
-
**Last Updated**: {timestamp}
|
|
1056
|
-
**Analysis Period**: {report.get('period', 'Last 30 days')}
|
|
1057
|
-
|
|
1058
|
-
### Activity Metrics
|
|
1059
|
-
- **Commits**: {summary.get('total_commits', 0)}
|
|
1060
|
-
- **Contributors**: {summary.get('total_authors', 0)}
|
|
1061
|
-
- **Files Changed**: {summary.get('files_changed', 0)}
|
|
1062
|
-
- **Current Branch**: {summary.get('current_branch', 'unknown')}
|
|
1063
|
-
"""
|
|
1064
|
-
|
|
1065
|
-
if summary.get("has_uncommitted"):
|
|
1066
|
-
activity_section += f"- **⚠️ Uncommitted Changes**: {summary.get('uncommitted_count', 0)} files\n"
|
|
1067
|
-
|
|
1068
|
-
# Add recent commits
|
|
1069
|
-
recent_commits = report.get("recent_commits", [])
|
|
1070
|
-
if recent_commits:
|
|
1071
|
-
activity_section += "\n### Recent Commits\n"
|
|
1072
|
-
for commit in recent_commits[:5]:
|
|
1073
|
-
activity_section += f"- `{commit['hash']}` {commit['message'][:60]} ({commit['author']})\n"
|
|
1074
|
-
|
|
1075
|
-
# Add hot files
|
|
1076
|
-
hot_files = report.get("hot_files", [])
|
|
1077
|
-
if hot_files:
|
|
1078
|
-
activity_section += "\n### Most Active Files\n"
|
|
1079
|
-
for file_path, changes in hot_files[:5]:
|
|
1080
|
-
activity_section += f"- `{file_path}`: {changes} changes\n"
|
|
1081
|
-
|
|
1082
|
-
# Add recommendations
|
|
1083
|
-
recommendations = report.get("recommendations", [])
|
|
1084
|
-
if recommendations:
|
|
1085
|
-
activity_section += "\n### 💡 Recommendations\n"
|
|
1086
|
-
for rec in recommendations:
|
|
1087
|
-
activity_section += f"- {rec}\n"
|
|
1088
|
-
|
|
1089
|
-
activity_section += "\n---\n"
|
|
1090
|
-
|
|
1091
|
-
# Append to file
|
|
1092
|
-
with open(claude_md_path, "a", encoding="utf-8") as f:
|
|
1093
|
-
f.write(activity_section)
|
|
1094
|
-
|
|
1095
|
-
def _run_dry_run_mode(self, organize_files: bool, has_existing: bool) -> Dict:
|
|
1096
|
-
"""Run dry-run mode to show what would be done without making changes."""
|
|
1097
|
-
console.print("\n[bold cyan]🔍 Dry Run Mode - Preview Changes[/bold cyan]\n")
|
|
1098
|
-
|
|
1099
|
-
actions_planned = []
|
|
1100
|
-
|
|
1101
|
-
# Check what organization would do
|
|
1102
|
-
if organize_files:
|
|
1103
|
-
console.print("[bold]📁 File Organization Analysis:[/bold]")
|
|
1104
|
-
|
|
1105
|
-
# Get structure validation without making changes
|
|
1106
|
-
validation = self.organizer.validate_structure()
|
|
1107
|
-
if validation.get("issues"):
|
|
1108
|
-
console.print(" [yellow]Files that would be organized:[/yellow]")
|
|
1109
|
-
for issue in validation["issues"][:10]:
|
|
1110
|
-
actions_planned.append(
|
|
1111
|
-
f"Organize: {issue.get('description', 'Unknown')}"
|
|
1112
|
-
)
|
|
1113
|
-
console.print(f" • {issue.get('description', 'Unknown')}")
|
|
1114
|
-
else:
|
|
1115
|
-
console.print(" ✅ Project structure is already well-organized")
|
|
1116
|
-
|
|
1117
|
-
# Check what documentation updates would occur
|
|
1118
|
-
if has_existing:
|
|
1119
|
-
console.print("\n[bold]📚 Documentation Updates:[/bold]")
|
|
1120
|
-
doc_analysis = self.doc_manager.analyze_existing_content()
|
|
1121
|
-
|
|
1122
|
-
if not doc_analysis.get("has_priority_markers"):
|
|
1123
|
-
actions_planned.append("Add priority markers (🔴🟡🟢⚪)")
|
|
1124
|
-
console.print(" • Add priority markers (🔴🟡🟢⚪)")
|
|
1125
|
-
|
|
1126
|
-
if doc_analysis.get("outdated_patterns"):
|
|
1127
|
-
actions_planned.append("Update outdated patterns")
|
|
1128
|
-
console.print(" • Update outdated patterns")
|
|
1129
|
-
|
|
1130
|
-
if not doc_analysis.get("has_priority_index"):
|
|
1131
|
-
actions_planned.append("Add priority index section")
|
|
1132
|
-
console.print(" • Add priority index section")
|
|
1133
|
-
|
|
1134
|
-
# Archive would be created
|
|
1135
|
-
actions_planned.append("Archive current CLAUDE.md to docs/_archive/")
|
|
1136
|
-
console.print(" • Archive current CLAUDE.md to docs/_archive/")
|
|
1137
|
-
else:
|
|
1138
|
-
console.print("\n[bold]📚 Documentation Creation:[/bold]")
|
|
1139
|
-
actions_planned.append("Create new CLAUDE.md with priority structure")
|
|
1140
|
-
console.print(" • Create new CLAUDE.md with priority structure")
|
|
1141
|
-
|
|
1142
|
-
# General improvements
|
|
1143
|
-
console.print("\n[bold]🔧 General Improvements:[/bold]")
|
|
1144
|
-
actions_planned.extend(
|
|
1145
|
-
[
|
|
1146
|
-
"Update/create .gitignore if needed",
|
|
1147
|
-
"Verify project structure compliance",
|
|
1148
|
-
"Add memory system initialization",
|
|
1149
|
-
"Set up single-path workflows",
|
|
1150
|
-
]
|
|
1151
|
-
)
|
|
1152
|
-
for action in actions_planned[-4:]:
|
|
1153
|
-
console.print(f" • {action}")
|
|
1154
|
-
|
|
1155
|
-
console.print(
|
|
1156
|
-
f"\n[bold cyan]Summary: {len(actions_planned)} actions would be performed[/bold cyan]"
|
|
1157
|
-
)
|
|
1158
|
-
console.print("\n[dim]Run without --dry-run to execute these changes.[/dim]\n")
|
|
1159
|
-
|
|
1160
|
-
return {
|
|
1161
|
-
"status": OperationResult.SUCCESS,
|
|
1162
|
-
"mode": "dry_run",
|
|
1163
|
-
"actions_planned": actions_planned,
|
|
1164
|
-
"message": "Dry run completed - no changes made",
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
def _run_pre_initialization_checks(
|
|
1168
|
-
self, organize_files: bool, skip_archive: bool, has_existing: bool
|
|
1169
|
-
) -> Dict:
|
|
1170
|
-
"""Run pre-initialization checks and preparations."""
|
|
1171
|
-
checks_passed = []
|
|
1172
|
-
warnings = []
|
|
1173
|
-
|
|
1174
|
-
# Run comprehensive project readiness check
|
|
1175
|
-
ready, actions = self.organizer.ensure_project_ready(
|
|
1176
|
-
auto_organize=organize_files,
|
|
1177
|
-
safe_mode=True, # Only perform safe operations by default
|
|
1178
|
-
)
|
|
1179
|
-
|
|
1180
|
-
if actions:
|
|
1181
|
-
checks_passed.extend(actions)
|
|
1182
|
-
|
|
1183
|
-
# Get structure validation report
|
|
1184
|
-
validation = self.organizer.validate_structure()
|
|
1185
|
-
if validation["warnings"]:
|
|
1186
|
-
warnings.extend(validation["warnings"])
|
|
1187
|
-
if validation["errors"]:
|
|
1188
|
-
warnings.extend(validation["errors"])
|
|
1189
|
-
|
|
1190
|
-
# Show structure grade
|
|
1191
|
-
if validation.get("grade"):
|
|
1192
|
-
checks_passed.append(f"Structure validation: {validation['grade']}")
|
|
1193
|
-
|
|
1194
|
-
# Archive existing documentation if needed
|
|
1195
|
-
if has_existing and not skip_archive:
|
|
1196
|
-
if self.archive_manager.auto_archive_before_update(
|
|
1197
|
-
self.project_path / "CLAUDE.md", update_reason="Before mpm-init update"
|
|
1198
|
-
):
|
|
1199
|
-
checks_passed.append("Archived existing CLAUDE.md")
|
|
1200
|
-
|
|
1201
|
-
# Check for issues in validation report
|
|
1202
|
-
if validation.get("issues"):
|
|
1203
|
-
for issue in validation["issues"]:
|
|
1204
|
-
warnings.append(issue["description"])
|
|
1205
|
-
|
|
1206
|
-
if warnings:
|
|
1207
|
-
console.print("\n[yellow]⚠️ Project issues detected:[/yellow]")
|
|
1208
|
-
for warning in warnings[:5]:
|
|
1209
|
-
console.print(f" • {warning}")
|
|
1210
|
-
console.print()
|
|
1211
|
-
|
|
1212
|
-
if checks_passed:
|
|
1213
|
-
console.print("[green]✅ Pre-initialization checks:[/green]")
|
|
1214
|
-
for check in checks_passed:
|
|
1215
|
-
console.print(f" • {check}")
|
|
1216
|
-
console.print()
|
|
1217
|
-
|
|
1218
|
-
return {
|
|
1219
|
-
"status": OperationResult.SUCCESS,
|
|
1220
|
-
"checks_passed": checks_passed,
|
|
1221
|
-
"warnings": warnings,
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
def _show_update_plan(self, ast_analysis: bool, preserve_custom: bool) -> None:
|
|
1225
|
-
"""Show update mode plan."""
|
|
1226
|
-
console.print(
|
|
1227
|
-
Panel(
|
|
1228
|
-
"[bold cyan]🔄 Claude MPM Documentation Update[/bold cyan]\n\n"
|
|
1229
|
-
"This will update your existing CLAUDE.md with:\n"
|
|
1230
|
-
"• Smart merging of new and existing content\n"
|
|
1231
|
-
+ ("• Preservation of custom sections\n" if preserve_custom else "")
|
|
1232
|
-
+ "• Priority-based reorganization (🔴🟡🟢⚪)\n"
|
|
1233
|
-
"• Updated single-path workflows\n"
|
|
1234
|
-
"• Refreshed tool configurations\n"
|
|
1235
|
-
+ (
|
|
1236
|
-
"• AST analysis for enhanced documentation\n"
|
|
1237
|
-
if ast_analysis
|
|
1238
|
-
else ""
|
|
1239
|
-
)
|
|
1240
|
-
+ "• Automatic archival of previous version\n"
|
|
1241
|
-
+ "• Holistic review and optimization\n"
|
|
1242
|
-
+ "\n[dim]Previous version will be archived in docs/_archive/[/dim]",
|
|
1243
|
-
title="Update Mode",
|
|
1244
|
-
border_style="blue",
|
|
1245
|
-
)
|
|
1246
|
-
)
|
|
1247
|
-
|
|
1248
|
-
def _show_initialization_plan(self, ast_analysis: bool) -> None:
|
|
1249
|
-
"""Show standard initialization plan."""
|
|
1250
|
-
console.print(
|
|
1251
|
-
Panel(
|
|
1252
|
-
"[bold cyan]🤖👥 Claude MPM Project Initialization[/bold cyan]\n\n"
|
|
1253
|
-
"This will set up your project with:\n"
|
|
1254
|
-
"• Clear CLAUDE.md documentation for AI agents\n"
|
|
1255
|
-
"• Single-path workflows (ONE way to do ANYTHING)\n"
|
|
1256
|
-
"• Optimized project structure\n"
|
|
1257
|
-
"• Tool configurations (linting, formatting, testing)\n"
|
|
1258
|
-
"• GitHub workflows and CI/CD setup\n"
|
|
1259
|
-
"• Memory system initialization\n"
|
|
1260
|
-
+ (
|
|
1261
|
-
"• AST analysis for comprehensive code documentation\n"
|
|
1262
|
-
if ast_analysis
|
|
1263
|
-
else ""
|
|
1264
|
-
)
|
|
1265
|
-
+ "• Holistic CLAUDE.md organization with ranked instructions\n"
|
|
1266
|
-
+ "• Priority-based content structure (🔴🟡🟢⚪)\n"
|
|
1267
|
-
+ "\n[dim]Powered by Agentic Coder Optimizer Agent[/dim]",
|
|
1268
|
-
title="MPM-Init",
|
|
1269
|
-
border_style="cyan",
|
|
1270
|
-
)
|
|
1271
|
-
)
|
|
1272
|
-
|
|
1273
|
-
def _build_update_prompt(
|
|
1274
|
-
self,
|
|
1275
|
-
project_type: Optional[str],
|
|
1276
|
-
framework: Optional[str],
|
|
1277
|
-
ast_analysis: bool,
|
|
1278
|
-
preserve_custom: bool,
|
|
1279
|
-
) -> str:
|
|
1280
|
-
"""Build prompt for update mode."""
|
|
1281
|
-
# Get existing content analysis
|
|
1282
|
-
doc_analysis = self.doc_manager.analyze_existing_content()
|
|
1283
|
-
|
|
1284
|
-
prompt = f"""Please delegate this task to the Agentic Coder Optimizer agent:
|
|
1285
|
-
|
|
1286
|
-
UPDATE existing CLAUDE.md documentation for this project.
|
|
1287
|
-
|
|
1288
|
-
Project Path: {self.project_path}
|
|
1289
|
-
Update Mode: Smart merge with existing content
|
|
1290
|
-
"""
|
|
1291
|
-
if project_type:
|
|
1292
|
-
prompt += f"Project Type: {project_type}\n"
|
|
1293
|
-
if framework:
|
|
1294
|
-
prompt += f"Framework: {framework}\n"
|
|
1295
|
-
|
|
1296
|
-
prompt += f"""
|
|
1297
|
-
Existing Documentation Analysis:
|
|
1298
|
-
- Current CLAUDE.md: {doc_analysis.get('size', 0):,} characters, {doc_analysis.get('lines', 0)} lines
|
|
1299
|
-
- Has Priority Index: {'Yes' if doc_analysis.get('has_priority_index') else 'No'}
|
|
1300
|
-
- Custom Sections: {len(doc_analysis.get('custom_sections', []))} found
|
|
1301
|
-
"""
|
|
1302
|
-
if preserve_custom and doc_analysis.get("custom_sections"):
|
|
1303
|
-
prompt += f"- Preserve Custom Sections: {', '.join(doc_analysis['custom_sections'][:5])}\n"
|
|
1304
|
-
|
|
1305
|
-
prompt += """
|
|
1306
|
-
Please perform the following UPDATE tasks:
|
|
1307
|
-
|
|
1308
|
-
1. **Review Existing Content**:
|
|
1309
|
-
- Analyze current CLAUDE.md structure and content
|
|
1310
|
-
- Identify outdated or missing information
|
|
1311
|
-
- Preserve valuable custom sections and project-specific knowledge
|
|
1312
|
-
|
|
1313
|
-
2. **Smart Content Merge**:
|
|
1314
|
-
- Update project overview if needed
|
|
1315
|
-
- Refresh architecture documentation
|
|
1316
|
-
- Update development workflows to ensure single-path principle
|
|
1317
|
-
- Merge new standard sections while preserving custom content
|
|
1318
|
-
- Remove duplicate or contradictory information
|
|
1319
|
-
|
|
1320
|
-
3. **Update Priority Organization**:
|
|
1321
|
-
- Reorganize content with priority markers (🔴🟡🟢⚪)
|
|
1322
|
-
- Ensure critical instructions are at the top
|
|
1323
|
-
- Update priority index with all important items
|
|
1324
|
-
- Validate instruction clarity and completeness
|
|
1325
|
-
|
|
1326
|
-
4. **Refresh Technical Content**:
|
|
1327
|
-
- Update build/test/deploy commands
|
|
1328
|
-
- Verify tool configurations are current
|
|
1329
|
-
- Update dependency information
|
|
1330
|
-
- Refresh API documentation if applicable
|
|
1331
|
-
"""
|
|
1332
|
-
if ast_analysis:
|
|
1333
|
-
prompt += """
|
|
1334
|
-
5. **Update Code Documentation** (using Code Analyzer agent):
|
|
1335
|
-
- Re-analyze code structure for changes
|
|
1336
|
-
- Update API documentation
|
|
1337
|
-
- Refresh architecture diagrams
|
|
1338
|
-
- Update function/class documentation
|
|
1339
|
-
"""
|
|
1340
|
-
prompt += """
|
|
1341
|
-
6. **Final Optimization**:
|
|
1342
|
-
- Ensure single-path principle throughout
|
|
1343
|
-
- Validate all links and references
|
|
1344
|
-
- Add/update timestamp in meta section
|
|
1345
|
-
- Verify AI agent readability
|
|
1346
|
-
|
|
1347
|
-
IMPORTANT: This is an UPDATE operation. Intelligently merge new content with existing,
|
|
1348
|
-
preserving valuable project-specific information while refreshing standard sections.
|
|
1349
|
-
"""
|
|
1350
|
-
return prompt
|
|
1351
|
-
|
|
1352
|
-
def _handle_update_post_processing(self) -> None:
|
|
1353
|
-
"""Handle post-processing after successful update."""
|
|
1354
|
-
# Generate update report
|
|
1355
|
-
if self.doc_manager.has_existing_documentation():
|
|
1356
|
-
latest_archive = self.archive_manager.get_latest_archive("CLAUDE.md")
|
|
1357
|
-
if latest_archive:
|
|
1358
|
-
comparison = self.archive_manager.compare_with_archive(
|
|
1359
|
-
self.project_path / "CLAUDE.md", latest_archive.name
|
|
1360
|
-
)
|
|
1361
|
-
|
|
1362
|
-
if not comparison.get("identical"):
|
|
1363
|
-
console.print("\n[bold cyan]📊 Update Summary[/bold cyan]")
|
|
1364
|
-
console.print(
|
|
1365
|
-
f" Lines changed: {comparison.get('lines_added', 0):+d}"
|
|
1366
|
-
)
|
|
1367
|
-
console.print(
|
|
1368
|
-
f" Size change: {comparison.get('size_change', 0):+,} characters"
|
|
1369
|
-
)
|
|
1370
|
-
console.print(f" Previous version: {latest_archive.name}")
|
|
1371
|
-
|
|
1372
|
-
def _run_initialization(
|
|
1373
|
-
self,
|
|
1374
|
-
prompt: str,
|
|
1375
|
-
verbose: bool,
|
|
1376
|
-
update_mode: bool = False,
|
|
1377
|
-
) -> Dict:
|
|
1378
|
-
"""Run the initialization through subprocess calling claude-mpm."""
|
|
1379
|
-
import tempfile
|
|
1380
|
-
|
|
1381
|
-
try:
|
|
1382
|
-
# Write prompt to temporary file
|
|
1383
|
-
with tempfile.NamedTemporaryFile(
|
|
1384
|
-
mode="w", suffix=".txt", delete=False
|
|
1385
|
-
) as tmp_file:
|
|
1386
|
-
tmp_file.write(prompt)
|
|
1387
|
-
prompt_file = tmp_file.name
|
|
1388
|
-
|
|
1389
|
-
try:
|
|
1390
|
-
# Build the command
|
|
1391
|
-
cmd = self._build_claude_mpm_command(verbose)
|
|
1392
|
-
# Add the input file flag
|
|
1393
|
-
cmd.extend(["-i", prompt_file])
|
|
1394
|
-
|
|
1395
|
-
# Log the command if verbose
|
|
1396
|
-
if verbose:
|
|
1397
|
-
console.print(f"[dim]Running: {' '.join(cmd)}[/dim]")
|
|
1398
|
-
console.print(f"[dim]Prompt file: {prompt_file}[/dim]")
|
|
1399
|
-
|
|
1400
|
-
# Execute the command
|
|
1401
|
-
result = subprocess.run(
|
|
1402
|
-
cmd,
|
|
1403
|
-
capture_output=True,
|
|
1404
|
-
text=True,
|
|
1405
|
-
cwd=str(self.project_path),
|
|
1406
|
-
check=False,
|
|
1407
|
-
)
|
|
1408
|
-
finally:
|
|
1409
|
-
# Clean up temporary file
|
|
1410
|
-
|
|
1411
|
-
with contextlib.suppress(Exception):
|
|
1412
|
-
Path(prompt_file).unlink()
|
|
1413
|
-
|
|
1414
|
-
# Display output if verbose
|
|
1415
|
-
if verbose and result.stdout:
|
|
1416
|
-
console.print(result.stdout)
|
|
1417
|
-
if verbose and result.stderr:
|
|
1418
|
-
console.print(f"[yellow]{result.stderr}[/yellow]")
|
|
1419
|
-
|
|
1420
|
-
# Check result - be more lenient with return codes
|
|
1421
|
-
if result.returncode == 0 or (self.project_path / "CLAUDE.md").exists():
|
|
1422
|
-
response = {
|
|
1423
|
-
"status": OperationResult.SUCCESS,
|
|
1424
|
-
"message": "Project initialized successfully",
|
|
1425
|
-
"files_created": [],
|
|
1426
|
-
"files_updated": [],
|
|
1427
|
-
"next_steps": [],
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
# Check if CLAUDE.md was created
|
|
1431
|
-
claude_md = self.project_path / "CLAUDE.md"
|
|
1432
|
-
if claude_md.exists():
|
|
1433
|
-
response["files_created"].append("CLAUDE.md")
|
|
1434
|
-
|
|
1435
|
-
# Check for other common files
|
|
1436
|
-
for file_name in ["CODE.md", "DEVELOPER.md", "STRUCTURE.md", "OPS.md"]:
|
|
1437
|
-
file_path = self.project_path / file_name
|
|
1438
|
-
if file_path.exists():
|
|
1439
|
-
response["files_created"].append(file_name)
|
|
1440
|
-
|
|
1441
|
-
# Add next steps
|
|
1442
|
-
response["next_steps"] = [
|
|
1443
|
-
"Review the generated CLAUDE.md documentation",
|
|
1444
|
-
"Verify the project structure meets your needs",
|
|
1445
|
-
"Run 'claude-mpm run' to start using the optimized setup",
|
|
1446
|
-
]
|
|
1447
|
-
|
|
1448
|
-
# Display results
|
|
1449
|
-
self._display_results(response, verbose)
|
|
1450
|
-
|
|
1451
|
-
return response
|
|
1452
|
-
# Extract meaningful error message
|
|
1453
|
-
error_msg = (
|
|
1454
|
-
result.stderr
|
|
1455
|
-
if result.stderr
|
|
1456
|
-
else result.stdout if result.stdout else "Unknown error occurred"
|
|
1457
|
-
)
|
|
1458
|
-
|
|
1459
|
-
logger.error(f"claude-mpm run failed: {error_msg}")
|
|
1460
|
-
return {
|
|
1461
|
-
"status": OperationResult.ERROR,
|
|
1462
|
-
"message": f"Initialization failed: {error_msg}",
|
|
1463
|
-
}
|
|
1464
|
-
|
|
1465
|
-
except FileNotFoundError:
|
|
1466
|
-
logger.error("claude-mpm command not found")
|
|
1467
|
-
console.print(
|
|
1468
|
-
"[red]Error: claude-mpm command not found. Ensure Claude MPM is properly installed.[/red]"
|
|
1469
|
-
)
|
|
1470
|
-
return {"status": OperationResult.ERROR, "message": "claude-mpm not found"}
|
|
1471
|
-
except Exception as e:
|
|
1472
|
-
logger.error(f"Initialization failed: {e}")
|
|
1473
|
-
return {"status": OperationResult.ERROR, "message": str(e)}
|
|
1474
|
-
|
|
1475
|
-
def handle_context(
|
|
1476
|
-
self,
|
|
1477
|
-
session_id: Optional[str] = None,
|
|
1478
|
-
list_sessions: bool = False,
|
|
1479
|
-
days: int = 7,
|
|
1480
|
-
) -> Dict[str, Any]:
|
|
1481
|
-
"""
|
|
1482
|
-
Provide intelligent context for resuming work based on git history.
|
|
1483
|
-
|
|
1484
|
-
Analyzes recent commits to identify:
|
|
1485
|
-
- Active work streams (what was being worked on)
|
|
1486
|
-
- Intent and motivation (why this work)
|
|
1487
|
-
- Risks and blockers
|
|
1488
|
-
- Recommended next actions
|
|
1489
|
-
|
|
1490
|
-
This delegates to Research agent for deep analysis.
|
|
1491
|
-
|
|
1492
|
-
Args:
|
|
1493
|
-
session_id: Unused parameter (for compatibility)
|
|
1494
|
-
list_sessions: Unused parameter (for compatibility)
|
|
1495
|
-
days: Number of days of git history to analyze (default: 7)
|
|
1496
|
-
|
|
1497
|
-
Returns:
|
|
1498
|
-
Dict containing context result
|
|
1499
|
-
"""
|
|
1500
|
-
from claude_mpm.utils.git_analyzer import analyze_recent_activity
|
|
1501
|
-
|
|
1502
|
-
# 1. Analyze git history with adaptive window
|
|
1503
|
-
console.print(f"\n🔍 Analyzing last {days} days of git history...\n")
|
|
1504
|
-
git_analysis = analyze_recent_activity(
|
|
1505
|
-
repo_path=str(self.project_path), days=days, max_commits=50, min_commits=25
|
|
1506
|
-
)
|
|
1507
|
-
|
|
1508
|
-
# Show adaptive behavior to user
|
|
1509
|
-
if git_analysis.get("adaptive_mode"):
|
|
1510
|
-
console.print(
|
|
1511
|
-
f"[cyan]ℹ️ Note: Analyzed {git_analysis.get('actual_time_span', 'extended period')} "
|
|
1512
|
-
f"to get meaningful context[/cyan]"
|
|
1513
|
-
)
|
|
1514
|
-
if git_analysis.get("reason"):
|
|
1515
|
-
console.print(f"[dim] Reason: {git_analysis['reason']}[/dim]\n")
|
|
1516
|
-
else:
|
|
1517
|
-
console.print()
|
|
1518
|
-
|
|
1519
|
-
if git_analysis.get("error"):
|
|
1520
|
-
console.print(
|
|
1521
|
-
f"[yellow]⚠️ Could not analyze git history: {git_analysis['error']}[/yellow]"
|
|
1522
|
-
)
|
|
1523
|
-
console.print(
|
|
1524
|
-
"[dim]Ensure this is a git repository with commit history.[/dim]\n"
|
|
1525
|
-
)
|
|
1526
|
-
return {
|
|
1527
|
-
"status": OperationResult.ERROR,
|
|
1528
|
-
"message": git_analysis["error"],
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
|
-
if not git_analysis.get("has_activity"):
|
|
1532
|
-
console.print(
|
|
1533
|
-
f"[yellow]⚠️ No git activity found in the last {days} days.[/yellow]"
|
|
1534
|
-
)
|
|
1535
|
-
console.print("[dim]Try increasing the --days parameter.[/dim]\n")
|
|
1536
|
-
return {
|
|
1537
|
-
"status": OperationResult.ERROR,
|
|
1538
|
-
"message": f"No git activity in last {days} days",
|
|
1539
|
-
}
|
|
1540
|
-
|
|
1541
|
-
# 2. Build Research delegation prompt
|
|
1542
|
-
research_prompt = self._build_research_context_prompt(git_analysis, days)
|
|
1543
|
-
|
|
1544
|
-
# 3. Display prompt for PM to delegate
|
|
1545
|
-
console.print("\n" + "=" * 80)
|
|
1546
|
-
console.print("📋 DELEGATE TO RESEARCH AGENT:")
|
|
1547
|
-
console.print("=" * 80 + "\n")
|
|
1548
|
-
console.print(research_prompt)
|
|
1549
|
-
console.print("\n" + "=" * 80 + "\n")
|
|
1550
|
-
|
|
1551
|
-
return {
|
|
1552
|
-
"status": OperationResult.CONTEXT_READY,
|
|
1553
|
-
"git_analysis": git_analysis,
|
|
1554
|
-
"research_prompt": research_prompt,
|
|
1555
|
-
"recommendation": "PM should delegate this prompt to Research agent",
|
|
1556
|
-
}
|
|
1557
|
-
|
|
1558
|
-
def _build_research_context_prompt(
|
|
1559
|
-
self, git_analysis: Dict[str, Any], days: int
|
|
1560
|
-
) -> str:
|
|
1561
|
-
"""Build structured Research agent delegation prompt from git analysis."""
|
|
1562
|
-
|
|
1563
|
-
# Extract key data
|
|
1564
|
-
commits = git_analysis.get("commits", [])
|
|
1565
|
-
branches = git_analysis.get("branches", [])
|
|
1566
|
-
contributors = git_analysis.get("contributors", {})
|
|
1567
|
-
file_changes = git_analysis.get("file_changes", {})
|
|
1568
|
-
|
|
1569
|
-
# Build prompt following Prompt Engineer's template
|
|
1570
|
-
prompt = f"""# Project Context Analysis Mission
|
|
1571
|
-
|
|
1572
|
-
You are Research agent analyzing git history to provide PM with intelligent project context for resuming work.
|
|
1573
|
-
|
|
1574
|
-
## Analysis Scope
|
|
1575
|
-
- **Time Range**: Last {days} days"""
|
|
1576
|
-
|
|
1577
|
-
# Add adaptive mode note if applicable
|
|
1578
|
-
if git_analysis.get("adaptive_mode"):
|
|
1579
|
-
actual_days = git_analysis.get("actual_time_span", "extended period")
|
|
1580
|
-
prompt += f""" (adaptive: {actual_days} days analyzed)
|
|
1581
|
-
- **Note**: {git_analysis.get('reason', 'Analysis window adjusted to ensure meaningful context')}"""
|
|
1582
|
-
|
|
1583
|
-
prompt += f"""
|
|
1584
|
-
- **Commits Analyzed**: {len(commits)} commits
|
|
1585
|
-
- **Branches**: {', '.join(branches[:5]) if branches else 'main'}
|
|
1586
|
-
- **Contributors**: {', '.join(contributors.keys()) if contributors else 'Unknown'}
|
|
1587
|
-
|
|
1588
|
-
## Your Mission
|
|
1589
|
-
|
|
1590
|
-
Analyze git history to answer these questions for PM:
|
|
1591
|
-
|
|
1592
|
-
1. **What was being worked on?** (Active work streams)
|
|
1593
|
-
2. **Why was this work happening?** (Intent and motivation)
|
|
1594
|
-
3. **What's the natural next step?** (Continuation recommendations)
|
|
1595
|
-
4. **What needs attention?** (Risks, stalls, conflicts)
|
|
1596
|
-
|
|
1597
|
-
## Git Data Provided
|
|
1598
|
-
|
|
1599
|
-
### Recent Commits ({min(len(commits), 10)} most recent):
|
|
1600
|
-
"""
|
|
1601
|
-
|
|
1602
|
-
# Add recent commits
|
|
1603
|
-
for commit in commits[:10]:
|
|
1604
|
-
author = commit.get("author", "Unknown")
|
|
1605
|
-
timestamp = commit.get("timestamp", "Unknown date")
|
|
1606
|
-
message = commit.get("message", "No message")
|
|
1607
|
-
files = commit.get("files", [])
|
|
1608
|
-
|
|
1609
|
-
prompt += f"\n- **{timestamp}** by {author}"
|
|
1610
|
-
prompt += f"\n {message}"
|
|
1611
|
-
prompt += f"\n Files changed: {len(files)}\n"
|
|
1612
|
-
|
|
1613
|
-
# Add file change summary
|
|
1614
|
-
if file_changes:
|
|
1615
|
-
# Sort by modifications count
|
|
1616
|
-
sorted_files = sorted(
|
|
1617
|
-
file_changes.items(),
|
|
1618
|
-
key=lambda x: x[1].get("modifications", 0),
|
|
1619
|
-
reverse=True,
|
|
1620
|
-
)
|
|
1621
|
-
prompt += "\n### Most Changed Files:\n"
|
|
1622
|
-
for file_path, file_data in sorted_files[:10]:
|
|
1623
|
-
modifications = file_data.get("modifications", 0)
|
|
1624
|
-
file_contributors = file_data.get("contributors", [])
|
|
1625
|
-
prompt += f"- {file_path}: {modifications} changes ({len(file_contributors)} contributor{'s' if len(file_contributors) != 1 else ''})\n"
|
|
1626
|
-
|
|
1627
|
-
# Add contributor summary
|
|
1628
|
-
if contributors:
|
|
1629
|
-
prompt += "\n### Contributors:\n"
|
|
1630
|
-
sorted_contributors = sorted(
|
|
1631
|
-
contributors.items(),
|
|
1632
|
-
key=lambda x: x[1].get("commits", 0),
|
|
1633
|
-
reverse=True,
|
|
1634
|
-
)
|
|
1635
|
-
for name, info in sorted_contributors[:5]:
|
|
1636
|
-
commit_count = info.get("commits", 0)
|
|
1637
|
-
prompt += f"- {name}: {commit_count} commit{'s' if commit_count != 1 else ''}\n"
|
|
1638
|
-
|
|
1639
|
-
# Add analysis instructions
|
|
1640
|
-
prompt += """
|
|
1641
|
-
|
|
1642
|
-
## Analysis Instructions
|
|
1643
|
-
|
|
1644
|
-
### Phase 1: Work Stream Identification
|
|
1645
|
-
Group related commits into thematic work streams. For each stream:
|
|
1646
|
-
- **Name**: Infer from commit messages (e.g., "Authentication refactor")
|
|
1647
|
-
- **Status**: ongoing/completed/stalled
|
|
1648
|
-
- **Commits**: Count of commits in this stream
|
|
1649
|
-
- **Intent**: WHY this work (from commit bodies/messages)
|
|
1650
|
-
- **Key Files**: Most changed files in this stream
|
|
1651
|
-
|
|
1652
|
-
### Phase 2: Risk Detection
|
|
1653
|
-
Identify:
|
|
1654
|
-
- **Stalled Work**: Work streams with no activity >3 days
|
|
1655
|
-
- **Anti-Patterns**: WIP commits, temp commits, debug commits
|
|
1656
|
-
- **Documentation Lag**: Code changes without doc updates
|
|
1657
|
-
- **Conflicts**: Merge conflicts or divergent branches
|
|
1658
|
-
|
|
1659
|
-
### Phase 3: Recommendations
|
|
1660
|
-
Based on analysis:
|
|
1661
|
-
1. **Primary Focus**: Most active/recent work to continue
|
|
1662
|
-
2. **Quick Wins**: Small tasks that could be finished
|
|
1663
|
-
3. **Blockers**: Issues preventing progress
|
|
1664
|
-
4. **Next Steps**: Logical continuation points
|
|
1665
|
-
|
|
1666
|
-
## Output Format
|
|
1667
|
-
|
|
1668
|
-
Provide a clear markdown summary with:
|
|
1669
|
-
|
|
1670
|
-
1. **Active Work Streams** (What was being worked on)
|
|
1671
|
-
2. **Intent Summary** (Why this work matters)
|
|
1672
|
-
3. **Risks Detected** (What needs attention)
|
|
1673
|
-
4. **Recommended Next Actions** (What to work on)
|
|
1674
|
-
|
|
1675
|
-
Keep it concise (<1000 words) but actionable.
|
|
1676
|
-
|
|
1677
|
-
## Success Criteria
|
|
1678
|
-
- Work streams accurately reflect development themes
|
|
1679
|
-
- Intent captures the "why" not just "what"
|
|
1680
|
-
- Recommendations are specific and actionable
|
|
1681
|
-
- Risks are prioritized by impact
|
|
1682
|
-
"""
|
|
1683
|
-
|
|
1684
|
-
return prompt
|
|
1685
|
-
|
|
1686
|
-
def _display_results(self, result: Dict, verbose: bool):
|
|
1687
|
-
"""Display initialization results."""
|
|
1688
|
-
if result["status"] == OperationResult.SUCCESS:
|
|
1689
|
-
console.print("\n[green]✅ Project Initialization Complete![/green]\n")
|
|
1690
|
-
|
|
1691
|
-
# Display files created
|
|
1692
|
-
if result.get("files_created"):
|
|
1693
|
-
self.display.display_files_list(
|
|
1694
|
-
"Files Created:", result["files_created"]
|
|
1695
|
-
)
|
|
1696
|
-
|
|
1697
|
-
# Display files updated
|
|
1698
|
-
if result.get("files_updated"):
|
|
1699
|
-
self.display.display_files_list(
|
|
1700
|
-
"Files Updated:", result["files_updated"]
|
|
1701
|
-
)
|
|
1702
|
-
|
|
1703
|
-
# Display next steps
|
|
1704
|
-
if result.get("next_steps"):
|
|
1705
|
-
self.display.display_next_steps(result["next_steps"])
|
|
1706
|
-
|
|
1707
|
-
# Display success panel
|
|
1708
|
-
success_content = (
|
|
1709
|
-
"[green]Your project is now optimized for Claude Code and Claude MPM![/green]\n\n"
|
|
1710
|
-
"Key files:\n"
|
|
1711
|
-
"• [cyan]CLAUDE.md[/cyan] - Main documentation for AI agents\n"
|
|
1712
|
-
" - Organized with priority rankings (🔴🟡🟢⚪)\n"
|
|
1713
|
-
" - Instructions ranked by importance for AI understanding\n"
|
|
1714
|
-
" - Holistic documentation review completed\n"
|
|
1715
|
-
"• [cyan].claude-mpm/[/cyan] - Configuration and memories\n"
|
|
1716
|
-
"• [cyan]CODE_STRUCTURE.md[/cyan] - AST-derived architecture documentation (if enabled)\n\n"
|
|
1717
|
-
"[dim]Run 'claude-mpm run' to start using the optimized setup[/dim]"
|
|
1718
|
-
)
|
|
1719
|
-
self.display.display_success_panel("Success", success_content)
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
@click.group(name="mpm-init", invoke_without_command=True)
|
|
1723
|
-
@click.option(
|
|
1724
|
-
"--project-type",
|
|
1725
|
-
type=click.Choice(
|
|
1726
|
-
["web", "api", "cli", "library", "mobile", "desktop", "fullstack"]
|
|
1727
|
-
),
|
|
1728
|
-
help="Type of project to initialize",
|
|
1729
|
-
)
|
|
1730
|
-
@click.option(
|
|
1731
|
-
"--framework",
|
|
1732
|
-
type=str,
|
|
1733
|
-
help="Specific framework (e.g., react, django, fastapi, express)",
|
|
1734
|
-
)
|
|
1735
|
-
@click.option(
|
|
1736
|
-
"--force",
|
|
1737
|
-
is_flag=True,
|
|
1738
|
-
help="Force reinitialization even if project is already configured",
|
|
1739
|
-
)
|
|
1740
|
-
@click.option(
|
|
1741
|
-
"--update",
|
|
1742
|
-
is_flag=True,
|
|
1743
|
-
help="Update existing CLAUDE.md instead of recreating",
|
|
1744
|
-
)
|
|
1745
|
-
@click.option(
|
|
1746
|
-
"--review",
|
|
1747
|
-
is_flag=True,
|
|
1748
|
-
help="Review project state without making changes",
|
|
1749
|
-
)
|
|
1750
|
-
@click.option(
|
|
1751
|
-
"--organize",
|
|
1752
|
-
is_flag=True,
|
|
1753
|
-
help="Automatically organize misplaced files into proper directories",
|
|
1754
|
-
)
|
|
1755
|
-
@click.option(
|
|
1756
|
-
"--auto-safe/--no-auto-safe",
|
|
1757
|
-
default=True,
|
|
1758
|
-
help="Only move files with high confidence (default: safe mode on)",
|
|
1759
|
-
)
|
|
1760
|
-
@click.option(
|
|
1761
|
-
"--preserve-custom/--no-preserve-custom",
|
|
1762
|
-
default=True,
|
|
1763
|
-
help="Preserve custom sections when updating (default: preserve)",
|
|
1764
|
-
)
|
|
1765
|
-
@click.option(
|
|
1766
|
-
"--skip-archive",
|
|
1767
|
-
is_flag=True,
|
|
1768
|
-
help="Skip archiving existing files before updating",
|
|
1769
|
-
)
|
|
1770
|
-
@click.option(
|
|
1771
|
-
"--verbose", is_flag=True, help="Show detailed output during initialization"
|
|
1772
|
-
)
|
|
1773
|
-
@click.option(
|
|
1774
|
-
"--ast-analysis/--no-ast-analysis",
|
|
1775
|
-
default=True,
|
|
1776
|
-
help="Enable/disable AST analysis for enhanced documentation (default: enabled)",
|
|
1777
|
-
)
|
|
1778
|
-
@click.option(
|
|
1779
|
-
"--quick-update",
|
|
1780
|
-
is_flag=True,
|
|
1781
|
-
help="Perform lightweight update based on recent git activity (default: 30 days)",
|
|
1782
|
-
)
|
|
1783
|
-
@click.option(
|
|
1784
|
-
"--catchup",
|
|
1785
|
-
is_flag=True,
|
|
1786
|
-
help="Show recent commit history from all branches for PM context",
|
|
1787
|
-
)
|
|
1788
|
-
@click.option(
|
|
1789
|
-
"--non-interactive",
|
|
1790
|
-
is_flag=True,
|
|
1791
|
-
help="Non-interactive mode - display report only without prompting (use with --quick-update)",
|
|
1792
|
-
)
|
|
1793
|
-
@click.option(
|
|
1794
|
-
"--days",
|
|
1795
|
-
type=int,
|
|
1796
|
-
default=30,
|
|
1797
|
-
help="Number of days for git history analysis in quick update mode (default: 30)",
|
|
1798
|
-
)
|
|
1799
|
-
@click.option(
|
|
1800
|
-
"--export",
|
|
1801
|
-
type=str,
|
|
1802
|
-
default=None,
|
|
1803
|
-
help="Export activity report to file (default: docs/reports/activity-report-{timestamp}.md)",
|
|
1804
|
-
)
|
|
1805
|
-
@click.argument(
|
|
1806
|
-
"project_path",
|
|
1807
|
-
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
|
1808
|
-
required=False,
|
|
1809
|
-
default=".",
|
|
1810
|
-
)
|
|
1811
|
-
@click.pass_context
|
|
1812
|
-
def mpm_init(
|
|
1813
|
-
ctx,
|
|
1814
|
-
project_type,
|
|
1815
|
-
framework,
|
|
1816
|
-
force,
|
|
1817
|
-
update,
|
|
1818
|
-
review,
|
|
1819
|
-
organize,
|
|
1820
|
-
auto_safe,
|
|
1821
|
-
preserve_custom,
|
|
1822
|
-
skip_archive,
|
|
1823
|
-
verbose,
|
|
1824
|
-
ast_analysis,
|
|
1825
|
-
quick_update,
|
|
1826
|
-
catchup,
|
|
1827
|
-
non_interactive,
|
|
1828
|
-
days,
|
|
1829
|
-
export,
|
|
1830
|
-
project_path,
|
|
1831
|
-
):
|
|
1832
|
-
"""
|
|
1833
|
-
Initialize or update a project for optimal use with Claude Code and Claude MPM.
|
|
1834
|
-
|
|
1835
|
-
This command uses the Agentic Coder Optimizer agent to:
|
|
1836
|
-
- Create or update comprehensive CLAUDE.md documentation
|
|
1837
|
-
- Establish single-path workflows (ONE way to do ANYTHING)
|
|
1838
|
-
- Configure development tools and standards
|
|
1839
|
-
- Set up memory systems for project knowledge
|
|
1840
|
-
- Optimize for AI agent understanding
|
|
1841
|
-
- Perform AST analysis for enhanced developer documentation
|
|
1842
|
-
|
|
1843
|
-
Context Management:
|
|
1844
|
-
- resume: Analyze git history to provide context for resuming work
|
|
1845
|
-
- --catchup: Show recent commit history for PM context
|
|
1846
|
-
|
|
1847
|
-
Update Mode:
|
|
1848
|
-
When CLAUDE.md exists, the command offers to update rather than recreate,
|
|
1849
|
-
preserving custom content while refreshing standard sections.
|
|
1850
|
-
|
|
1851
|
-
Examples:
|
|
1852
|
-
claude-mpm mpm-init # Initialize/update current directory
|
|
1853
|
-
claude-mpm mpm-init --catchup # Show recent git history for context
|
|
1854
|
-
claude-mpm mpm-init --review # Review project state without changes
|
|
1855
|
-
claude-mpm mpm-init --update # Force update mode
|
|
1856
|
-
claude-mpm mpm-init --organize # Organize misplaced files
|
|
1857
|
-
claude-mpm mpm-init --project-type web # Initialize as web project
|
|
1858
|
-
claude-mpm mpm-init /path/to/project --force # Force reinitialize project
|
|
1859
|
-
"""
|
|
1860
|
-
# If a subcommand is being invoked, don't run the main command
|
|
1861
|
-
if ctx.invoked_subcommand is not None:
|
|
1862
|
-
return
|
|
1863
|
-
|
|
1864
|
-
try:
|
|
1865
|
-
# Create command instance
|
|
1866
|
-
command = MPMInitCommand(Path(project_path))
|
|
1867
|
-
|
|
1868
|
-
# Run initialization (now synchronous)
|
|
1869
|
-
result = command.initialize_project(
|
|
1870
|
-
project_type=project_type,
|
|
1871
|
-
framework=framework,
|
|
1872
|
-
force=force,
|
|
1873
|
-
verbose=verbose,
|
|
1874
|
-
ast_analysis=ast_analysis,
|
|
1875
|
-
update_mode=update,
|
|
1876
|
-
review_only=review,
|
|
1877
|
-
organize_files=organize,
|
|
1878
|
-
preserve_custom=preserve_custom,
|
|
1879
|
-
skip_archive=skip_archive,
|
|
1880
|
-
quick_update=quick_update,
|
|
1881
|
-
catchup=catchup,
|
|
1882
|
-
non_interactive=non_interactive,
|
|
1883
|
-
days=days,
|
|
1884
|
-
export=export,
|
|
1885
|
-
)
|
|
1886
|
-
|
|
1887
|
-
# Exit with appropriate code
|
|
1888
|
-
if result["status"] == OperationResult.SUCCESS:
|
|
1889
|
-
sys.exit(0)
|
|
1890
|
-
else:
|
|
1891
|
-
sys.exit(1)
|
|
1892
|
-
|
|
1893
|
-
except KeyboardInterrupt:
|
|
1894
|
-
console.print("\n[yellow]Initialization cancelled by user[/yellow]")
|
|
1895
|
-
sys.exit(130)
|
|
1896
|
-
except Exception as e:
|
|
1897
|
-
console.print(f"[red]Initialization failed: {e}[/red]")
|
|
1898
|
-
sys.exit(1)
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
@mpm_init.command(name="context")
|
|
1902
|
-
@click.option(
|
|
1903
|
-
"--session-id",
|
|
1904
|
-
"-i",
|
|
1905
|
-
type=str,
|
|
1906
|
-
help="Unused (for compatibility) - will be removed in future version",
|
|
1907
|
-
)
|
|
1908
|
-
@click.option(
|
|
1909
|
-
"--days",
|
|
1910
|
-
type=int,
|
|
1911
|
-
default=7,
|
|
1912
|
-
help="Number of days of git history to analyze (default: 7)",
|
|
1913
|
-
)
|
|
1914
|
-
@click.argument(
|
|
1915
|
-
"project_path",
|
|
1916
|
-
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
|
1917
|
-
required=False,
|
|
1918
|
-
default=".",
|
|
1919
|
-
)
|
|
1920
|
-
def context_command(session_id, days, project_path):
|
|
1921
|
-
"""
|
|
1922
|
-
Provide intelligent context for resuming work based on git history.
|
|
1923
|
-
|
|
1924
|
-
Analyzes recent git history and generates a Research agent delegation
|
|
1925
|
-
prompt for intelligent project context reconstruction.
|
|
1926
|
-
|
|
1927
|
-
Examples:
|
|
1928
|
-
claude-mpm mpm-init context # Analyze last 7 days
|
|
1929
|
-
claude-mpm mpm-init context --days 14 # Analyze last 14 days
|
|
1930
|
-
claude-mpm mpm-init context --days 30 # Analyze last 30 days
|
|
1931
|
-
|
|
1932
|
-
Note: 'resume' is deprecated, use 'context' instead.
|
|
1933
|
-
"""
|
|
1934
|
-
try:
|
|
1935
|
-
command = MPMInitCommand(Path(project_path))
|
|
1936
|
-
|
|
1937
|
-
result = command.handle_context(session_id=session_id, days=days)
|
|
1938
|
-
|
|
1939
|
-
if (
|
|
1940
|
-
result["status"] == OperationResult.SUCCESS
|
|
1941
|
-
or result["status"] == OperationResult.CONTEXT_READY
|
|
1942
|
-
):
|
|
1943
|
-
sys.exit(0)
|
|
1944
|
-
else:
|
|
1945
|
-
sys.exit(1)
|
|
1946
|
-
|
|
1947
|
-
except KeyboardInterrupt:
|
|
1948
|
-
console.print("\n[yellow]Context analysis cancelled by user[/yellow]")
|
|
1949
|
-
sys.exit(130)
|
|
1950
|
-
except Exception as e:
|
|
1951
|
-
console.print(f"[red]Context analysis failed: {e}[/red]")
|
|
1952
|
-
sys.exit(1)
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
# Add deprecated 'resume' alias for backward compatibility
|
|
1956
|
-
@mpm_init.command(name="resume", hidden=True)
|
|
1957
|
-
@click.option(
|
|
1958
|
-
"--session-id",
|
|
1959
|
-
"-i",
|
|
1960
|
-
type=str,
|
|
1961
|
-
help="Unused (for compatibility) - will be removed in future version",
|
|
1962
|
-
)
|
|
1963
|
-
@click.option(
|
|
1964
|
-
"--days",
|
|
1965
|
-
type=int,
|
|
1966
|
-
default=7,
|
|
1967
|
-
help="Number of days of git history to analyze (default: 7)",
|
|
1968
|
-
)
|
|
1969
|
-
@click.argument(
|
|
1970
|
-
"project_path",
|
|
1971
|
-
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
|
1972
|
-
required=False,
|
|
1973
|
-
default=".",
|
|
1974
|
-
)
|
|
1975
|
-
def resume_session(session_id, days, project_path):
|
|
1976
|
-
"""
|
|
1977
|
-
[DEPRECATED] Use 'context' instead.
|
|
1978
|
-
|
|
1979
|
-
This command is deprecated and will be removed in a future version.
|
|
1980
|
-
Please use 'claude-mpm mpm-init context' instead.
|
|
1981
|
-
"""
|
|
1982
|
-
console.print(
|
|
1983
|
-
"[yellow]⚠️ Warning: 'resume' is deprecated. Use 'context' instead.[/yellow]"
|
|
1984
|
-
)
|
|
1985
|
-
console.print("[dim]Run: claude-mpm mpm-init context[/dim]\n")
|
|
1986
|
-
|
|
1987
|
-
try:
|
|
1988
|
-
command = MPMInitCommand(Path(project_path))
|
|
1989
|
-
result = command.handle_context(session_id=session_id, days=days)
|
|
1990
|
-
|
|
1991
|
-
if (
|
|
1992
|
-
result["status"] == OperationResult.SUCCESS
|
|
1993
|
-
or result["status"] == OperationResult.CONTEXT_READY
|
|
1994
|
-
):
|
|
1995
|
-
sys.exit(0)
|
|
1996
|
-
else:
|
|
1997
|
-
sys.exit(1)
|
|
1998
|
-
|
|
1999
|
-
except KeyboardInterrupt:
|
|
2000
|
-
console.print("\n[yellow]Context analysis cancelled by user[/yellow]")
|
|
2001
|
-
sys.exit(130)
|
|
2002
|
-
except Exception as e:
|
|
2003
|
-
console.print(f"[red]Context analysis failed: {e}[/red]")
|
|
2004
|
-
sys.exit(1)
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
# Export for CLI registration
|
|
2008
|
-
__all__ = ["mpm_init"]
|