claude-mpm 3.4.26__py3-none-any.whl → 3.5.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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/INSTRUCTIONS.md +182 -299
- claude_mpm/agents/agent_loader.py +283 -57
- claude_mpm/agents/agent_loader_integration.py +6 -9
- claude_mpm/agents/base_agent.json +2 -1
- claude_mpm/agents/base_agent_loader.py +1 -1
- claude_mpm/cli/__init__.py +6 -10
- claude_mpm/cli/commands/__init__.py +0 -2
- claude_mpm/cli/commands/agents.py +1 -1
- claude_mpm/cli/commands/memory.py +1 -1
- claude_mpm/cli/commands/run.py +12 -0
- claude_mpm/cli/parser.py +0 -13
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/config/__init__.py +44 -2
- claude_mpm/config/agent_config.py +348 -0
- claude_mpm/config/paths.py +322 -0
- claude_mpm/constants.py +0 -1
- claude_mpm/core/__init__.py +2 -5
- claude_mpm/core/agent_registry.py +63 -17
- claude_mpm/core/claude_runner.py +354 -43
- claude_mpm/core/config.py +7 -1
- claude_mpm/core/config_aliases.py +4 -3
- claude_mpm/core/config_paths.py +151 -0
- claude_mpm/core/factories.py +4 -50
- claude_mpm/core/logger.py +11 -13
- claude_mpm/core/service_registry.py +2 -2
- claude_mpm/dashboard/static/js/components/agent-inference.js +101 -25
- claude_mpm/dashboard/static/js/components/event-processor.js +3 -2
- claude_mpm/hooks/claude_hooks/hook_handler.py +343 -83
- claude_mpm/hooks/memory_integration_hook.py +1 -1
- claude_mpm/init.py +37 -6
- claude_mpm/scripts/socketio_daemon.py +6 -2
- claude_mpm/services/__init__.py +71 -3
- claude_mpm/services/agents/__init__.py +85 -0
- claude_mpm/services/agents/deployment/__init__.py +21 -0
- claude_mpm/services/{agent_deployment.py → agents/deployment/agent_deployment.py} +192 -41
- claude_mpm/services/{agent_lifecycle_manager.py → agents/deployment/agent_lifecycle_manager.py} +11 -10
- claude_mpm/services/agents/loading/__init__.py +11 -0
- claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +9 -8
- claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +2 -2
- claude_mpm/services/{framework_agent_loader.py → agents/loading/framework_agent_loader.py} +116 -40
- claude_mpm/services/agents/management/__init__.py +9 -0
- claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +6 -5
- claude_mpm/services/agents/memory/__init__.py +21 -0
- claude_mpm/services/{agent_memory_manager.py → agents/memory/agent_memory_manager.py} +3 -3
- claude_mpm/services/agents/registry/__init__.py +29 -0
- claude_mpm/services/{agent_registry.py → agents/registry/agent_registry.py} +101 -16
- claude_mpm/services/{deployed_agent_discovery.py → agents/registry/deployed_agent_discovery.py} +12 -2
- claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +6 -5
- claude_mpm/services/async_session_logger.py +584 -0
- claude_mpm/services/claude_session_logger.py +299 -0
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +2 -2
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +17 -17
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +3 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +1 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +1 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +19 -24
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +1 -1
- claude_mpm/services/framework_claude_md_generator.py +4 -2
- claude_mpm/services/memory/__init__.py +17 -0
- claude_mpm/services/{memory_builder.py → memory/builder.py} +3 -3
- claude_mpm/services/memory/cache/__init__.py +14 -0
- claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +1 -1
- claude_mpm/services/memory/cache/simple_cache.py +317 -0
- claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +1 -1
- claude_mpm/services/{memory_router.py → memory/router.py} +1 -1
- claude_mpm/services/optimized_hook_service.py +542 -0
- claude_mpm/services/project_registry.py +14 -8
- claude_mpm/services/response_tracker.py +237 -0
- claude_mpm/services/ticketing_service_original.py +4 -2
- claude_mpm/services/version_control/branch_strategy.py +3 -1
- claude_mpm/utils/paths.py +12 -10
- claude_mpm/utils/session_logging.py +114 -0
- claude_mpm/validation/agent_validator.py +2 -1
- {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/METADATA +26 -20
- {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/RECORD +83 -106
- claude_mpm/cli/commands/ui.py +0 -57
- claude_mpm/core/simple_runner.py +0 -1046
- claude_mpm/hooks/builtin/__init__.py +0 -1
- claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
- claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
- claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
- claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
- claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
- claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
- claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
- claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
- claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
- claude_mpm/orchestration/__init__.py +0 -6
- claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
- claude_mpm/orchestration/archive/factory.py +0 -215
- claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
- claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
- claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
- claude_mpm/orchestration/archive/orchestrator.py +0 -501
- claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
- claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
- claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
- claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
- claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
- claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
- claude_mpm/schemas/workflow_validator.py +0 -411
- claude_mpm/services/parent_directory_manager/__init__.py +0 -577
- claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
- claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
- claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
- claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
- claude_mpm/services/parent_directory_manager/operations.py +0 -186
- claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
- claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
- claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
- claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
- claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
- claude_mpm/ui/__init__.py +0 -1
- claude_mpm/ui/rich_terminal_ui.py +0 -295
- claude_mpm/ui/terminal_ui.py +0 -328
- /claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +0 -0
- /claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +0 -0
- /claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +0 -0
- {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/top_level.txt +0 -0
|
@@ -1,577 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Parent Directory Manager Service - CMPM-104: Parent Directory Template Installation
|
|
4
|
-
================================================================================
|
|
5
|
-
|
|
6
|
-
This service provides comprehensive parent directory template management with
|
|
7
|
-
deployment awareness, building on CMPM-101, CMPM-102, and CMPM-103.
|
|
8
|
-
|
|
9
|
-
Key Features:
|
|
10
|
-
- Parent directory CLAUDE.md management with deployment awareness
|
|
11
|
-
- Template installation workflow with conflict resolution
|
|
12
|
-
- Existing file detection and backup system
|
|
13
|
-
- Version control integration
|
|
14
|
-
- Cross-platform compatibility
|
|
15
|
-
- Integration with all previous CMPM implementations
|
|
16
|
-
|
|
17
|
-
Dependencies:
|
|
18
|
-
- CMPM-101 (Deployment Detection System)
|
|
19
|
-
- CMPM-102 (Versioned Template Management)
|
|
20
|
-
- CMPM-103 (Dependency Management)
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
import os
|
|
24
|
-
from pathlib import Path
|
|
25
|
-
from typing import Dict, List, Optional, Any, Tuple
|
|
26
|
-
|
|
27
|
-
from ...core.base_service import BaseService
|
|
28
|
-
from ...core.logger import setup_logging
|
|
29
|
-
|
|
30
|
-
# Import extracted modules for delegation
|
|
31
|
-
from .backup_manager import BackupManager
|
|
32
|
-
from .template_deployer import TemplateDeployer, DeploymentContext
|
|
33
|
-
from .framework_protector import FrameworkProtector
|
|
34
|
-
from .version_control_helper import VersionControlHelper
|
|
35
|
-
from .deduplication_manager import DeduplicationManager
|
|
36
|
-
from .operations import ParentDirectoryOperations, ParentDirectoryContext
|
|
37
|
-
from .config_manager import ConfigManager, ParentDirectoryConfig
|
|
38
|
-
from .state_manager import StateManager, ParentDirectoryStatus, ParentDirectoryOperation, ParentDirectoryAction
|
|
39
|
-
from .validation_manager import ValidationManager
|
|
40
|
-
from .version_manager import VersionManager
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class ParentDirectoryManager(BaseService):
|
|
44
|
-
"""
|
|
45
|
-
Parent Directory Template Management Service for Claude PM Framework.
|
|
46
|
-
|
|
47
|
-
This service provides:
|
|
48
|
-
- Parent directory CLAUDE.md management with deployment awareness
|
|
49
|
-
- Template installation workflow with conflict resolution
|
|
50
|
-
- Existing file detection and backup system
|
|
51
|
-
- Version control integration
|
|
52
|
-
- Integration with CMPM-101, CMPM-102, and CMPM-103
|
|
53
|
-
|
|
54
|
-
This is now a facade that delegates to specialized modules for:
|
|
55
|
-
- Backup management
|
|
56
|
-
- Template deployment
|
|
57
|
-
- Framework protection
|
|
58
|
-
- Version control
|
|
59
|
-
- Deduplication
|
|
60
|
-
- Directory operations
|
|
61
|
-
- Configuration management
|
|
62
|
-
- State management
|
|
63
|
-
- Validation
|
|
64
|
-
- Version tracking
|
|
65
|
-
"""
|
|
66
|
-
|
|
67
|
-
def __init__(self, config: Optional[Dict[str, Any]] = None, quiet_mode: bool = False):
|
|
68
|
-
"""
|
|
69
|
-
Initialize the Parent Directory Manager.
|
|
70
|
-
|
|
71
|
-
Args:
|
|
72
|
-
config: Optional configuration dictionary
|
|
73
|
-
quiet_mode: If True, suppress INFO level logging
|
|
74
|
-
"""
|
|
75
|
-
super().__init__(name="parent_directory_manager", config=config)
|
|
76
|
-
|
|
77
|
-
# Setup logger based on quiet mode
|
|
78
|
-
level = "WARNING" if quiet_mode or os.getenv('CLAUDE_PM_QUIET_MODE') == 'true' else "INFO"
|
|
79
|
-
self.logger = setup_logging(__name__, level=level)
|
|
80
|
-
|
|
81
|
-
self._quiet_mode = quiet_mode # Store quiet mode setting
|
|
82
|
-
|
|
83
|
-
# Configuration
|
|
84
|
-
self.backup_retention_days = self.get_config("backup_retention_days", 30)
|
|
85
|
-
self.deployment_aware = self.get_config("deployment_aware", True)
|
|
86
|
-
|
|
87
|
-
# Working paths
|
|
88
|
-
self.working_dir = Path.cwd()
|
|
89
|
-
# Temporarily set framework_path - will be properly set after state manager init
|
|
90
|
-
self.framework_path = Path(__file__).resolve().parent.parent.parent.parent
|
|
91
|
-
self.parent_directory_manager_dir = (
|
|
92
|
-
self.working_dir / ".claude-pm" / "parent_directory_manager"
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
# Initialize extracted service modules for delegation
|
|
97
|
-
self._backup_manager = BackupManager(
|
|
98
|
-
base_dir=self.working_dir,
|
|
99
|
-
retention_days=self.backup_retention_days,
|
|
100
|
-
logger=self.logger
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
self._template_deployer = TemplateDeployer(
|
|
104
|
-
framework_path=self.framework_path,
|
|
105
|
-
logger=self.logger
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
self._deduplication_manager = DeduplicationManager(
|
|
109
|
-
logger=self.logger
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
self._directory_ops = ParentDirectoryOperations(
|
|
113
|
-
logger=self.logger
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
self._config_manager = ConfigManager(
|
|
117
|
-
configs_dir=self.parent_directory_manager_dir / "configs",
|
|
118
|
-
logger=self.logger
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
# Initialize version manager early
|
|
122
|
-
self._version_manager = VersionManager(
|
|
123
|
-
framework_path=self.framework_path,
|
|
124
|
-
logger=self.logger
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
self._state_manager = StateManager(
|
|
128
|
-
working_dir=self.working_dir,
|
|
129
|
-
parent_directory_manager_dir=self.parent_directory_manager_dir,
|
|
130
|
-
framework_path=self.framework_path,
|
|
131
|
-
quiet_mode=quiet_mode,
|
|
132
|
-
logger=self.logger
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
# Now properly detect framework path using state manager
|
|
136
|
-
self.framework_path = self._detect_framework_path()
|
|
137
|
-
# Update all managers' framework paths
|
|
138
|
-
self._state_manager.framework_path = self.framework_path
|
|
139
|
-
self._template_deployer.framework_path = self.framework_path
|
|
140
|
-
self._version_manager.framework_path = self.framework_path
|
|
141
|
-
|
|
142
|
-
# Initialize paths
|
|
143
|
-
paths = self._state_manager.initialize_paths(self.parent_directory_manager_dir, self.working_dir)
|
|
144
|
-
self.backups_dir = paths['backups_dir']
|
|
145
|
-
self.configs_dir = paths['configs_dir']
|
|
146
|
-
self.versions_dir = paths['versions_dir']
|
|
147
|
-
self.logs_dir = paths['logs_dir']
|
|
148
|
-
self.managed_directories_file = paths['managed_directories_file']
|
|
149
|
-
self.operation_history_file = paths['operation_history_file']
|
|
150
|
-
|
|
151
|
-
self._validation_manager = ValidationManager(
|
|
152
|
-
logger=self.logger
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
# Integration with other CMPM services removed - use Claude Code Task Tool instead
|
|
156
|
-
self.template_manager = None
|
|
157
|
-
self.dependency_manager = None
|
|
158
|
-
self.deployment_context = None # Loaded during initialization
|
|
159
|
-
|
|
160
|
-
@property
|
|
161
|
-
def quiet(self) -> bool:
|
|
162
|
-
"""Get quiet mode setting."""
|
|
163
|
-
return self._quiet_mode
|
|
164
|
-
|
|
165
|
-
@property
|
|
166
|
-
def version_manager(self):
|
|
167
|
-
"""Get version manager for direct access to version operations."""
|
|
168
|
-
return self._version_manager
|
|
169
|
-
|
|
170
|
-
@property
|
|
171
|
-
def validation_manager(self):
|
|
172
|
-
"""Get validation manager for direct access to validation operations."""
|
|
173
|
-
return self._validation_manager
|
|
174
|
-
|
|
175
|
-
# Delegation methods for public API
|
|
176
|
-
def _log_info_if_not_quiet(self, message: str) -> None:
|
|
177
|
-
self._state_manager.log_info_if_not_quiet(message)
|
|
178
|
-
|
|
179
|
-
def _detect_framework_path(self) -> Path:
|
|
180
|
-
return self._state_manager.detect_framework_path()
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
# Main lifecycle methods
|
|
185
|
-
async def _initialize(self) -> None:
|
|
186
|
-
"""Initialize the Parent Directory Manager service."""
|
|
187
|
-
# Delegate initialization to StateManager
|
|
188
|
-
await self._state_manager.initialize(
|
|
189
|
-
self._state_manager.create_directory_structure,
|
|
190
|
-
self._config_manager,
|
|
191
|
-
self._validation_manager,
|
|
192
|
-
self._version_manager,
|
|
193
|
-
self._deduplicate_claude_md_files,
|
|
194
|
-
self.deployment_aware,
|
|
195
|
-
self.dependency_manager
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
# Update local references
|
|
199
|
-
self.managed_directories = self._config_manager.managed_directories
|
|
200
|
-
self.operation_history = self._state_manager.operation_history
|
|
201
|
-
self.deployment_context = self._state_manager.deployment_context
|
|
202
|
-
self.subsystem_versions = self._version_manager.subsystem_versions
|
|
203
|
-
|
|
204
|
-
async def _cleanup(self) -> None:
|
|
205
|
-
"""Cleanup the Parent Directory Manager service."""
|
|
206
|
-
# Delegate cleanup to StateManager
|
|
207
|
-
await self._state_manager.cleanup(
|
|
208
|
-
self._config_manager,
|
|
209
|
-
self.backups_dir,
|
|
210
|
-
self.backup_retention_days
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
# Public API Methods - all delegating to specialized modules
|
|
214
|
-
|
|
215
|
-
async def register_parent_directory(
|
|
216
|
-
self,
|
|
217
|
-
target_directory: Path,
|
|
218
|
-
context: ParentDirectoryContext,
|
|
219
|
-
template_id: str,
|
|
220
|
-
template_variables: Dict[str, Any] = None,
|
|
221
|
-
**kwargs,
|
|
222
|
-
) -> bool:
|
|
223
|
-
"""
|
|
224
|
-
Register a parent directory for management.
|
|
225
|
-
|
|
226
|
-
Args:
|
|
227
|
-
target_directory: Directory to manage
|
|
228
|
-
context: Context type for the directory
|
|
229
|
-
template_id: Template to use for management
|
|
230
|
-
template_variables: Variables for template rendering
|
|
231
|
-
**kwargs: Additional configuration options
|
|
232
|
-
|
|
233
|
-
Returns:
|
|
234
|
-
True if registration successful, False otherwise
|
|
235
|
-
"""
|
|
236
|
-
result = await self._config_manager.register_parent_directory(
|
|
237
|
-
target_directory, context, template_id, template_variables, **kwargs
|
|
238
|
-
)
|
|
239
|
-
if result:
|
|
240
|
-
self.managed_directories = self._config_manager.managed_directories
|
|
241
|
-
return result
|
|
242
|
-
|
|
243
|
-
async def deploy_framework_template(
|
|
244
|
-
self,
|
|
245
|
-
target_directory: Path,
|
|
246
|
-
force: bool = False,
|
|
247
|
-
) -> ParentDirectoryOperation:
|
|
248
|
-
"""
|
|
249
|
-
Deploy framework template using the new generator with integrated deployment.
|
|
250
|
-
|
|
251
|
-
Args:
|
|
252
|
-
target_directory: Directory to deploy template to
|
|
253
|
-
force: Force deployment even if version is current
|
|
254
|
-
|
|
255
|
-
Returns:
|
|
256
|
-
ParentDirectoryOperation result
|
|
257
|
-
"""
|
|
258
|
-
# Delegate to TemplateDeployer
|
|
259
|
-
success, target_path, error_message, changes_made = await self._template_deployer.deploy_framework_template(
|
|
260
|
-
target_directory=target_directory,
|
|
261
|
-
force=force,
|
|
262
|
-
deduplication_handler=self._deduplicate_claude_md_files,
|
|
263
|
-
backup_manager=self._backup_manager,
|
|
264
|
-
state_manager=self._state_manager,
|
|
265
|
-
quiet=self.quiet
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
# Handle protection guidance if error
|
|
269
|
-
if not success and "Permanent protection" in error_message:
|
|
270
|
-
self._state_manager.handle_protection_error(target_path, error_message, simple=True)
|
|
271
|
-
|
|
272
|
-
# Create operation result
|
|
273
|
-
operation = self._state_manager.create_operation_result(
|
|
274
|
-
action=ParentDirectoryAction.INSTALL,
|
|
275
|
-
target_path=target_path,
|
|
276
|
-
success=success,
|
|
277
|
-
template_id="framework_claude_md",
|
|
278
|
-
backup_manager=self._backup_manager,
|
|
279
|
-
changes_made=changes_made if success else [],
|
|
280
|
-
error_message=error_message if not success else None
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
if success:
|
|
284
|
-
self._state_manager.add_operation(operation)
|
|
285
|
-
|
|
286
|
-
return operation
|
|
287
|
-
|
|
288
|
-
async def install_template_to_parent_directory(
|
|
289
|
-
self,
|
|
290
|
-
target_directory: Path,
|
|
291
|
-
template_id: str,
|
|
292
|
-
template_variables: Dict[str, Any] = None,
|
|
293
|
-
force: bool = False,
|
|
294
|
-
) -> ParentDirectoryOperation:
|
|
295
|
-
"""
|
|
296
|
-
Install a template to a parent directory with version checking.
|
|
297
|
-
|
|
298
|
-
Args:
|
|
299
|
-
target_directory: Directory to install template to
|
|
300
|
-
template_id: Template to install
|
|
301
|
-
template_variables: Variables for template rendering
|
|
302
|
-
force: Force installation even if version is current (overrides version checking)
|
|
303
|
-
|
|
304
|
-
Returns:
|
|
305
|
-
ParentDirectoryOperation result
|
|
306
|
-
"""
|
|
307
|
-
# Handle streaming logging setup
|
|
308
|
-
self.logger, original_logger, deployment_streaming = self._state_manager.setup_deployment_logger(self.logger)
|
|
309
|
-
|
|
310
|
-
try:
|
|
311
|
-
target_file = target_directory / "CLAUDE.md"
|
|
312
|
-
self._current_target_file = target_file
|
|
313
|
-
|
|
314
|
-
# Delegate to TemplateDeployer
|
|
315
|
-
success, target_path, version, error_message, changes_made = await self._template_deployer.install_template(
|
|
316
|
-
target_directory=target_directory,
|
|
317
|
-
template_id=template_id,
|
|
318
|
-
template_variables=template_variables,
|
|
319
|
-
force=force,
|
|
320
|
-
deduplication_handler=self._deduplicate_claude_md_files,
|
|
321
|
-
backup_manager=self._backup_manager,
|
|
322
|
-
state_manager=self._state_manager,
|
|
323
|
-
quiet=self.quiet,
|
|
324
|
-
current_target_file=target_file
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
# Handle protection guidance if error
|
|
328
|
-
if not success and "Permanent protection" in error_message:
|
|
329
|
-
self._state_manager.handle_protection_error(target_path, error_message)
|
|
330
|
-
|
|
331
|
-
# Handle warnings for skipped deployments
|
|
332
|
-
warnings = []
|
|
333
|
-
if success and "Deployment skipped" in str(changes_made):
|
|
334
|
-
warnings = changes_made
|
|
335
|
-
changes_made = []
|
|
336
|
-
|
|
337
|
-
# Create and return operation result
|
|
338
|
-
operation = self._state_manager.create_operation_result(
|
|
339
|
-
action=ParentDirectoryAction.INSTALL,
|
|
340
|
-
target_path=target_path,
|
|
341
|
-
success=success,
|
|
342
|
-
template_id=template_id,
|
|
343
|
-
version=version,
|
|
344
|
-
backup_manager=self._backup_manager,
|
|
345
|
-
changes_made=changes_made if success else [],
|
|
346
|
-
warnings=warnings,
|
|
347
|
-
error_message=error_message if not success else None
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
if success:
|
|
351
|
-
self._state_manager.add_operation(operation)
|
|
352
|
-
|
|
353
|
-
if hasattr(self, '_current_target_file'):
|
|
354
|
-
del self._current_target_file
|
|
355
|
-
|
|
356
|
-
self.logger = self._state_manager.finalize_deployment_logger(self.logger, original_logger, deployment_streaming)
|
|
357
|
-
return operation
|
|
358
|
-
|
|
359
|
-
except Exception as e:
|
|
360
|
-
self.logger.error(f"Failed to install template {template_id} to {target_directory}: {e}")
|
|
361
|
-
|
|
362
|
-
# Clean up temporary attribute
|
|
363
|
-
if hasattr(self, '_current_target_file'):
|
|
364
|
-
del self._current_target_file
|
|
365
|
-
|
|
366
|
-
# Finalize streaming logs if we used streaming logger
|
|
367
|
-
self.logger = self._state_manager.finalize_deployment_logger(self.logger, original_logger, deployment_streaming)
|
|
368
|
-
|
|
369
|
-
return self._state_manager.create_operation_result(
|
|
370
|
-
action=ParentDirectoryAction.INSTALL,
|
|
371
|
-
target_path=target_directory / "CLAUDE.md",
|
|
372
|
-
success=False,
|
|
373
|
-
template_id=template_id,
|
|
374
|
-
error_message=str(e)
|
|
375
|
-
)
|
|
376
|
-
|
|
377
|
-
async def update_parent_directory_template(
|
|
378
|
-
self, target_directory: Path, template_variables: Dict[str, Any] = None, force: bool = False
|
|
379
|
-
) -> ParentDirectoryOperation:
|
|
380
|
-
"""
|
|
381
|
-
Update a template in a parent directory.
|
|
382
|
-
|
|
383
|
-
Args:
|
|
384
|
-
target_directory: Directory containing template to update
|
|
385
|
-
template_variables: New variables for template rendering
|
|
386
|
-
force: Force update even if no changes detected
|
|
387
|
-
|
|
388
|
-
Returns:
|
|
389
|
-
ParentDirectoryOperation result
|
|
390
|
-
"""
|
|
391
|
-
try:
|
|
392
|
-
# Check if directory is managed
|
|
393
|
-
directory_key = str(target_directory)
|
|
394
|
-
if not self._config_manager.is_directory_managed(directory_key):
|
|
395
|
-
raise ValueError(f"Directory not managed: {target_directory}")
|
|
396
|
-
|
|
397
|
-
config = self._config_manager.get_directory_config(directory_key)
|
|
398
|
-
|
|
399
|
-
# Get current status
|
|
400
|
-
status = await self.get_parent_directory_status(target_directory)
|
|
401
|
-
|
|
402
|
-
if not status.exists:
|
|
403
|
-
# File doesn't exist, perform installation
|
|
404
|
-
return await self.install_template_to_parent_directory(
|
|
405
|
-
target_directory, config.template_id, template_variables, force
|
|
406
|
-
)
|
|
407
|
-
|
|
408
|
-
# Update template variables if provided
|
|
409
|
-
if template_variables:
|
|
410
|
-
config.template_variables.update(template_variables)
|
|
411
|
-
|
|
412
|
-
# For updates, delegate to install with force flag to ensure update happens
|
|
413
|
-
result = await self.install_template_to_parent_directory(
|
|
414
|
-
target_directory, config.template_id, config.template_variables, force=True
|
|
415
|
-
)
|
|
416
|
-
|
|
417
|
-
# Change the action to UPDATE in the result
|
|
418
|
-
result.action = ParentDirectoryAction.UPDATE
|
|
419
|
-
|
|
420
|
-
return result
|
|
421
|
-
|
|
422
|
-
except Exception as e:
|
|
423
|
-
self.logger.error(f"Failed to update template in {target_directory}: {e}")
|
|
424
|
-
return self._state_manager.create_operation_result(
|
|
425
|
-
action=ParentDirectoryAction.UPDATE,
|
|
426
|
-
target_path=target_directory / "CLAUDE.md",
|
|
427
|
-
success=False,
|
|
428
|
-
error_message=str(e)
|
|
429
|
-
)
|
|
430
|
-
|
|
431
|
-
async def get_parent_directory_status(self, target_directory: Path) -> ParentDirectoryStatus:
|
|
432
|
-
"""Get status of a parent directory."""
|
|
433
|
-
return await self._state_manager.get_parent_directory_status(
|
|
434
|
-
target_directory, self._config_manager, self.backups_dir
|
|
435
|
-
)
|
|
436
|
-
|
|
437
|
-
async def backup_parent_directory(self, target_directory: Path) -> Optional[Path]:
|
|
438
|
-
"""
|
|
439
|
-
Create a backup of a parent directory's CLAUDE.md file.
|
|
440
|
-
|
|
441
|
-
Args:
|
|
442
|
-
target_directory: Directory containing file to backup
|
|
443
|
-
|
|
444
|
-
Returns:
|
|
445
|
-
Path to backup file or None if failed
|
|
446
|
-
"""
|
|
447
|
-
return await self._backup_manager.backup_parent_directory(target_directory, self.backups_dir)
|
|
448
|
-
|
|
449
|
-
async def restore_parent_directory(
|
|
450
|
-
self, target_directory: Path, backup_timestamp: Optional[str] = None
|
|
451
|
-
) -> ParentDirectoryOperation:
|
|
452
|
-
"""
|
|
453
|
-
Restore a parent directory from backup.
|
|
454
|
-
|
|
455
|
-
Args:
|
|
456
|
-
target_directory: Directory to restore
|
|
457
|
-
backup_timestamp: Specific backup to restore (latest if None)
|
|
458
|
-
|
|
459
|
-
Returns:
|
|
460
|
-
ParentDirectoryOperation result
|
|
461
|
-
"""
|
|
462
|
-
# Delegate to BackupManager
|
|
463
|
-
operation = await self._backup_manager.restore_from_backup(
|
|
464
|
-
target_directory,
|
|
465
|
-
self.backups_dir,
|
|
466
|
-
backup_timestamp
|
|
467
|
-
)
|
|
468
|
-
|
|
469
|
-
# Store operation in history if successful
|
|
470
|
-
if operation.success:
|
|
471
|
-
self._state_manager.add_operation(operation)
|
|
472
|
-
|
|
473
|
-
return operation
|
|
474
|
-
|
|
475
|
-
async def validate_parent_directory(self, target_directory: Path) -> ParentDirectoryOperation:
|
|
476
|
-
"""Validate a parent directory's template."""
|
|
477
|
-
return await self._validation_manager.validate_parent_directory(
|
|
478
|
-
target_directory, self.managed_directories
|
|
479
|
-
)
|
|
480
|
-
|
|
481
|
-
async def list_managed_directories(self) -> List[Dict[str, Any]]:
|
|
482
|
-
"""List all managed directories."""
|
|
483
|
-
return await self._state_manager.list_managed_directories(
|
|
484
|
-
self._config_manager, self.get_parent_directory_status
|
|
485
|
-
)
|
|
486
|
-
|
|
487
|
-
async def get_operation_history(self, limit: int = 50) -> List[Dict[str, Any]]:
|
|
488
|
-
"""Get operation history."""
|
|
489
|
-
return await self._state_manager.get_operation_history(limit)
|
|
490
|
-
|
|
491
|
-
# Subsystem Version Management Methods - delegating to version manager
|
|
492
|
-
# Subsystem Version Management - direct delegation to version manager
|
|
493
|
-
def get_subsystem_versions(self) -> Dict[str, Any]:
|
|
494
|
-
return self._version_manager.get_subsystem_versions()
|
|
495
|
-
|
|
496
|
-
def get_subsystem_version(self, subsystem: str) -> Optional[str]:
|
|
497
|
-
return self._version_manager.get_subsystem_version(subsystem)
|
|
498
|
-
|
|
499
|
-
async def validate_subsystem_compatibility(self, required_versions: Dict[str, str]) -> Dict[str, Any]:
|
|
500
|
-
return await self._validation_manager.validate_subsystem_compatibility(
|
|
501
|
-
required_versions, self._version_manager.get_subsystem_version
|
|
502
|
-
)
|
|
503
|
-
|
|
504
|
-
async def update_subsystem_version(self, subsystem: str, new_version: str) -> bool:
|
|
505
|
-
return await self._version_manager.update_subsystem_version(
|
|
506
|
-
subsystem, new_version,
|
|
507
|
-
lambda file_path: self._backup_manager.create_backup(file_path, self.backups_dir)
|
|
508
|
-
)
|
|
509
|
-
|
|
510
|
-
def get_subsystem_version_report(self) -> Dict[str, Any]:
|
|
511
|
-
return self._version_manager.get_subsystem_version_report()
|
|
512
|
-
|
|
513
|
-
# Directory operations - delegating to directory operations module
|
|
514
|
-
async def detect_parent_directory_context(self, target_directory: Path) -> ParentDirectoryContext:
|
|
515
|
-
return await self._directory_ops.detect_parent_directory_context(target_directory)
|
|
516
|
-
|
|
517
|
-
async def auto_register_parent_directories(
|
|
518
|
-
self, search_paths: List[Path], template_id: str = "parent_directory_claude_md"
|
|
519
|
-
) -> List[Path]:
|
|
520
|
-
"""Automatically register parent directories that should be managed."""
|
|
521
|
-
return await self._directory_ops.auto_register_parent_directories(
|
|
522
|
-
search_paths,
|
|
523
|
-
template_id,
|
|
524
|
-
self.register_parent_directory,
|
|
525
|
-
lambda path, ctx: self._directory_ops.get_default_template_variables(
|
|
526
|
-
path, ctx, self.deployment_context
|
|
527
|
-
)
|
|
528
|
-
)
|
|
529
|
-
|
|
530
|
-
# Deduplication - delegating to deduplication manager
|
|
531
|
-
async def _deduplicate_claude_md_files(self) -> List[Tuple[Path, str]]:
|
|
532
|
-
"""Deduplicate CLAUDE.md files in parent directory hierarchy."""
|
|
533
|
-
return await self._deduplication_manager.deduplicate_claude_md_files(
|
|
534
|
-
self._template_deployer.is_framework_deployment_template,
|
|
535
|
-
self._template_deployer.extract_claude_md_version,
|
|
536
|
-
self._template_deployer.compare_versions,
|
|
537
|
-
lambda file_path: self._backup_manager.create_backup(file_path, self.backups_dir)
|
|
538
|
-
)
|
|
539
|
-
|
|
540
|
-
async def deduplicate_parent_claude_md(self) -> Dict[str, Any]:
|
|
541
|
-
"""Public method to manually trigger CLAUDE.md deduplication in parent hierarchy."""
|
|
542
|
-
return await self._deduplication_manager.deduplicate_parent_claude_md(
|
|
543
|
-
self._template_deployer.is_framework_deployment_template,
|
|
544
|
-
self._template_deployer.extract_claude_md_version,
|
|
545
|
-
self._template_deployer.compare_versions,
|
|
546
|
-
lambda file_path: self._backup_manager.create_backup(file_path, self.backups_dir)
|
|
547
|
-
)
|
|
548
|
-
|
|
549
|
-
# Helper Methods
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
async def _get_framework_template(
|
|
553
|
-
self, template_id: str
|
|
554
|
-
) -> Tuple[Optional[str], Optional[Any]]:
|
|
555
|
-
"""Get template from deployment framework path using the new generator."""
|
|
556
|
-
current_target_file = getattr(self, '_current_target_file', None)
|
|
557
|
-
return await self._template_deployer.get_framework_template(
|
|
558
|
-
template_id,
|
|
559
|
-
current_target_file,
|
|
560
|
-
self._backup_manager,
|
|
561
|
-
self._log_info_if_not_quiet
|
|
562
|
-
)
|
|
563
|
-
|
|
564
|
-
def get_framework_backup_status(self) -> Dict[str, Any]:
|
|
565
|
-
return self._backup_manager.get_framework_backup_status()
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
# Export all public symbols
|
|
569
|
-
__all__ = [
|
|
570
|
-
'ParentDirectoryManager',
|
|
571
|
-
'ParentDirectoryContext',
|
|
572
|
-
'ParentDirectoryStatus',
|
|
573
|
-
'ParentDirectoryOperation',
|
|
574
|
-
'ParentDirectoryAction',
|
|
575
|
-
'ParentDirectoryConfig',
|
|
576
|
-
'DeploymentContext'
|
|
577
|
-
]
|