claude-mpm 3.4.27__py3-none-any.whl → 3.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +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 +5 -7
- 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.27.dist-info → claude_mpm-3.5.1.dist-info}/METADATA +28 -20
- {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.1.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.27.dist-info → claude_mpm-3.5.1.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.1.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.1.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.1.dist-info}/top_level.txt +0 -0
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Validation Manager - Handles validation and compatibility checks
|
|
4
|
-
================================================================================
|
|
5
|
-
|
|
6
|
-
This module manages validation of parent directories, subsystem compatibility,
|
|
7
|
-
and version comparisons.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
import os
|
|
11
|
-
from pathlib import Path
|
|
12
|
-
from typing import Dict, Any, Optional, List, Tuple
|
|
13
|
-
from datetime import datetime
|
|
14
|
-
import logging
|
|
15
|
-
|
|
16
|
-
from .state_manager import ParentDirectoryOperation, ParentDirectoryAction
|
|
17
|
-
from ...utils.path_operations import path_ops
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class ValidationManager:
|
|
21
|
-
"""Manages validation and compatibility checks."""
|
|
22
|
-
|
|
23
|
-
def __init__(self, logger: Optional[logging.Logger] = None):
|
|
24
|
-
"""
|
|
25
|
-
Initialize the Validation Manager.
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
logger: Logger instance to use
|
|
29
|
-
"""
|
|
30
|
-
self.logger = logger or logging.getLogger(__name__)
|
|
31
|
-
|
|
32
|
-
async def validate_parent_directory(
|
|
33
|
-
self,
|
|
34
|
-
target_directory: Path,
|
|
35
|
-
managed_directories: Dict[str, Any],
|
|
36
|
-
template_manager: Optional[Any] = None
|
|
37
|
-
) -> ParentDirectoryOperation:
|
|
38
|
-
"""
|
|
39
|
-
Validate a parent directory's template.
|
|
40
|
-
|
|
41
|
-
Args:
|
|
42
|
-
target_directory: Directory to validate
|
|
43
|
-
managed_directories: Dictionary of managed directories
|
|
44
|
-
template_manager: Template manager instance (optional)
|
|
45
|
-
|
|
46
|
-
Returns:
|
|
47
|
-
ParentDirectoryOperation result
|
|
48
|
-
"""
|
|
49
|
-
try:
|
|
50
|
-
# Check for INSTRUCTIONS.md first, then CLAUDE.md
|
|
51
|
-
target_file = target_directory / "INSTRUCTIONS.md"
|
|
52
|
-
if not path_ops.validate_exists(target_file):
|
|
53
|
-
target_file = target_directory / "CLAUDE.md"
|
|
54
|
-
|
|
55
|
-
if not path_ops.validate_exists(target_file):
|
|
56
|
-
return ParentDirectoryOperation(
|
|
57
|
-
action=ParentDirectoryAction.VALIDATE,
|
|
58
|
-
target_path=target_file,
|
|
59
|
-
success=False,
|
|
60
|
-
error_message="INSTRUCTIONS.md/CLAUDE.md file not found",
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
# Check if managed
|
|
64
|
-
directory_key = str(target_directory)
|
|
65
|
-
if directory_key not in managed_directories:
|
|
66
|
-
return ParentDirectoryOperation(
|
|
67
|
-
action=ParentDirectoryAction.VALIDATE,
|
|
68
|
-
target_path=target_file,
|
|
69
|
-
success=True,
|
|
70
|
-
warnings=["Directory not managed by Parent Directory Manager"],
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
config = managed_directories[directory_key]
|
|
74
|
-
|
|
75
|
-
# Validate template if template manager available
|
|
76
|
-
validation_errors = []
|
|
77
|
-
validation_warnings = []
|
|
78
|
-
|
|
79
|
-
# template_manager removed - use Claude Code Task Tool instead
|
|
80
|
-
rendered_content = None
|
|
81
|
-
|
|
82
|
-
if rendered_content:
|
|
83
|
-
# Compare with actual content
|
|
84
|
-
actual_content = path_ops.safe_read(target_file)
|
|
85
|
-
if not actual_content:
|
|
86
|
-
return ParentDirectoryOperation(
|
|
87
|
-
action=ParentDirectoryAction.VALIDATE,
|
|
88
|
-
target_path=target_file,
|
|
89
|
-
success=False,
|
|
90
|
-
error_message="Failed to read file content",
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
if actual_content != rendered_content:
|
|
94
|
-
validation_warnings.append("Content differs from expected template output")
|
|
95
|
-
else:
|
|
96
|
-
validation_errors.append("Failed to render template for validation")
|
|
97
|
-
|
|
98
|
-
# Check file permissions
|
|
99
|
-
if not os.access(target_file, os.R_OK):
|
|
100
|
-
validation_errors.append("File is not readable")
|
|
101
|
-
|
|
102
|
-
if not os.access(target_file, os.W_OK):
|
|
103
|
-
validation_warnings.append("File is not writable")
|
|
104
|
-
|
|
105
|
-
# Create operation result
|
|
106
|
-
operation = ParentDirectoryOperation(
|
|
107
|
-
action=ParentDirectoryAction.VALIDATE,
|
|
108
|
-
target_path=target_file,
|
|
109
|
-
success=len(validation_errors) == 0,
|
|
110
|
-
template_id=config.template_id,
|
|
111
|
-
error_message="; ".join(validation_errors) if validation_errors else None,
|
|
112
|
-
warnings=validation_warnings,
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
return operation
|
|
116
|
-
|
|
117
|
-
except Exception as e:
|
|
118
|
-
self.logger.error(f"Failed to validate parent directory {target_directory}: {e}")
|
|
119
|
-
return ParentDirectoryOperation(
|
|
120
|
-
action=ParentDirectoryAction.VALIDATE,
|
|
121
|
-
# Try to determine which file would be used
|
|
122
|
-
target_file = target_directory / "INSTRUCTIONS.md"
|
|
123
|
-
if not path_ops.validate_exists(target_file):
|
|
124
|
-
target_file = target_directory / "CLAUDE.md"
|
|
125
|
-
return ParentDirectoryOperation(
|
|
126
|
-
action=ParentDirectoryAction.VALIDATE,
|
|
127
|
-
target_path=target_file,
|
|
128
|
-
success=False,
|
|
129
|
-
success=False,
|
|
130
|
-
error_message=str(e),
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
async def validate_subsystem_compatibility(
|
|
134
|
-
self,
|
|
135
|
-
required_versions: Dict[str, str],
|
|
136
|
-
get_subsystem_version_func
|
|
137
|
-
) -> Dict[str, Any]:
|
|
138
|
-
"""
|
|
139
|
-
Validate subsystem version compatibility against requirements.
|
|
140
|
-
|
|
141
|
-
Args:
|
|
142
|
-
required_versions: Dictionary of subsystem -> required version
|
|
143
|
-
get_subsystem_version_func: Function to get current subsystem version
|
|
144
|
-
|
|
145
|
-
Returns:
|
|
146
|
-
Validation results with compatibility status
|
|
147
|
-
"""
|
|
148
|
-
try:
|
|
149
|
-
results = {
|
|
150
|
-
"compatible": True,
|
|
151
|
-
"validation_timestamp": datetime.now().isoformat(),
|
|
152
|
-
"subsystem_checks": {}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
for subsystem, required_version in required_versions.items():
|
|
156
|
-
current_version = get_subsystem_version_func(subsystem)
|
|
157
|
-
|
|
158
|
-
check_result = {
|
|
159
|
-
"subsystem": subsystem,
|
|
160
|
-
"required_version": required_version,
|
|
161
|
-
"current_version": current_version,
|
|
162
|
-
"compatible": False,
|
|
163
|
-
"status": "unknown"
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if current_version is None or current_version in ["unknown", "not_found"]:
|
|
167
|
-
check_result["status"] = "missing"
|
|
168
|
-
results["compatible"] = False
|
|
169
|
-
elif current_version == required_version:
|
|
170
|
-
check_result["compatible"] = True
|
|
171
|
-
check_result["status"] = "exact_match"
|
|
172
|
-
else:
|
|
173
|
-
# Try version comparison for compatibility
|
|
174
|
-
try:
|
|
175
|
-
comparison = self.compare_subsystem_versions(current_version, required_version)
|
|
176
|
-
if comparison >= 0:
|
|
177
|
-
check_result["compatible"] = True
|
|
178
|
-
check_result["status"] = "compatible" if comparison > 0 else "exact_match"
|
|
179
|
-
else:
|
|
180
|
-
check_result["status"] = "outdated"
|
|
181
|
-
results["compatible"] = False
|
|
182
|
-
except Exception as comp_error:
|
|
183
|
-
check_result["status"] = "comparison_failed"
|
|
184
|
-
check_result["error"] = str(comp_error)
|
|
185
|
-
results["compatible"] = False
|
|
186
|
-
|
|
187
|
-
results["subsystem_checks"][subsystem] = check_result
|
|
188
|
-
|
|
189
|
-
return results
|
|
190
|
-
|
|
191
|
-
except Exception as e:
|
|
192
|
-
self.logger.error(f"Failed to validate subsystem compatibility: {e}")
|
|
193
|
-
return {
|
|
194
|
-
"compatible": False,
|
|
195
|
-
"error": str(e),
|
|
196
|
-
"validation_timestamp": datetime.now().isoformat()
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
def compare_subsystem_versions(self, version1: str, version2: str) -> int:
|
|
200
|
-
"""
|
|
201
|
-
Compare two subsystem version strings.
|
|
202
|
-
Supports serial number format (001, 002, etc.).
|
|
203
|
-
|
|
204
|
-
Args:
|
|
205
|
-
version1: First version string
|
|
206
|
-
version2: Second version string
|
|
207
|
-
|
|
208
|
-
Returns:
|
|
209
|
-
-1 if version1 < version2
|
|
210
|
-
0 if version1 == version2
|
|
211
|
-
1 if version1 > version2
|
|
212
|
-
"""
|
|
213
|
-
try:
|
|
214
|
-
# Handle serial number format (001, 002, etc.)
|
|
215
|
-
if version1.isdigit() and version2.isdigit():
|
|
216
|
-
v1_num = int(version1)
|
|
217
|
-
v2_num = int(version2)
|
|
218
|
-
if v1_num < v2_num:
|
|
219
|
-
return -1
|
|
220
|
-
elif v1_num > v2_num:
|
|
221
|
-
return 1
|
|
222
|
-
else:
|
|
223
|
-
return 0
|
|
224
|
-
|
|
225
|
-
# Handle semantic versioning (x.y.z)
|
|
226
|
-
if "." in version1 and "." in version2:
|
|
227
|
-
v1_parts = [int(x) for x in version1.split(".")]
|
|
228
|
-
v2_parts = [int(x) for x in version2.split(".")]
|
|
229
|
-
|
|
230
|
-
# Pad shorter version with zeros
|
|
231
|
-
max_len = max(len(v1_parts), len(v2_parts))
|
|
232
|
-
v1_parts.extend([0] * (max_len - len(v1_parts)))
|
|
233
|
-
v2_parts.extend([0] * (max_len - len(v2_parts)))
|
|
234
|
-
|
|
235
|
-
for i in range(max_len):
|
|
236
|
-
if v1_parts[i] < v2_parts[i]:
|
|
237
|
-
return -1
|
|
238
|
-
elif v1_parts[i] > v2_parts[i]:
|
|
239
|
-
return 1
|
|
240
|
-
|
|
241
|
-
return 0
|
|
242
|
-
|
|
243
|
-
# String comparison fallback
|
|
244
|
-
if version1 < version2:
|
|
245
|
-
return -1
|
|
246
|
-
elif version1 > version2:
|
|
247
|
-
return 1
|
|
248
|
-
else:
|
|
249
|
-
return 0
|
|
250
|
-
|
|
251
|
-
except Exception as e:
|
|
252
|
-
self.logger.error(f"Failed to compare subsystem versions {version1} vs {version2}: {e}")
|
|
253
|
-
# If comparison fails, assume versions are different
|
|
254
|
-
return -1 if version1 != version2 else 0
|
|
255
|
-
|
|
256
|
-
def validate_framework_template_integrity(self, framework_path: Path) -> bool:
|
|
257
|
-
"""
|
|
258
|
-
Validate that the framework template exists and has expected content.
|
|
259
|
-
|
|
260
|
-
Args:
|
|
261
|
-
framework_path: Path to framework
|
|
262
|
-
|
|
263
|
-
Returns:
|
|
264
|
-
True if framework template is valid, False otherwise
|
|
265
|
-
"""
|
|
266
|
-
try:
|
|
267
|
-
# Try INSTRUCTIONS.md first, then fall back to CLAUDE.md
|
|
268
|
-
framework_template_path = framework_path / "agents" / "INSTRUCTIONS.md"
|
|
269
|
-
if not path_ops.validate_exists(framework_template_path):
|
|
270
|
-
framework_template_path = framework_path / "agents" / "CLAUDE.md"
|
|
271
|
-
|
|
272
|
-
if not path_ops.validate_exists(framework_template_path):
|
|
273
|
-
self.logger.error(f"Framework template does not exist: {framework_template_path}")
|
|
274
|
-
return False
|
|
275
|
-
|
|
276
|
-
if not path_ops.validate_is_file(framework_template_path):
|
|
277
|
-
self.logger.error(f"Framework template path is not a file: {framework_template_path}")
|
|
278
|
-
return False
|
|
279
|
-
|
|
280
|
-
# Read and validate content
|
|
281
|
-
content = path_ops.safe_read(framework_template_path)
|
|
282
|
-
if not content:
|
|
283
|
-
self.logger.error(f"Failed to read framework template at {framework_template_path}")
|
|
284
|
-
return False
|
|
285
|
-
|
|
286
|
-
if len(content.strip()) == 0:
|
|
287
|
-
self.logger.error(f"Framework template is empty: {framework_template_path}")
|
|
288
|
-
return False
|
|
289
|
-
|
|
290
|
-
# Check for critical content markers
|
|
291
|
-
critical_markers = [
|
|
292
|
-
"AI ASSISTANT ROLE DESIGNATION",
|
|
293
|
-
"CLAUDE_MD_VERSION:",
|
|
294
|
-
"Framework Context"
|
|
295
|
-
]
|
|
296
|
-
|
|
297
|
-
missing_critical = [marker for marker in critical_markers if marker not in content]
|
|
298
|
-
|
|
299
|
-
if missing_critical:
|
|
300
|
-
self.logger.error(f"Framework template missing critical content: {missing_critical}")
|
|
301
|
-
return False
|
|
302
|
-
|
|
303
|
-
self.logger.debug(f"Framework template integrity verified: {framework_template_path}")
|
|
304
|
-
return True
|
|
305
|
-
|
|
306
|
-
except Exception as e:
|
|
307
|
-
self.logger.error(f"Failed to validate framework template integrity: {e}")
|
|
308
|
-
return False
|
|
309
|
-
|
|
310
|
-
async def validate_deployment_context(
|
|
311
|
-
self,
|
|
312
|
-
deployment_aware: bool,
|
|
313
|
-
dependency_manager: Optional[Any] = None
|
|
314
|
-
) -> Optional[Dict[str, Any]]:
|
|
315
|
-
"""
|
|
316
|
-
Validate deployment context using CMPM-101.
|
|
317
|
-
|
|
318
|
-
Args:
|
|
319
|
-
deployment_aware: Whether to check deployment context
|
|
320
|
-
dependency_manager: Dependency manager instance
|
|
321
|
-
|
|
322
|
-
Returns:
|
|
323
|
-
Deployment context or None
|
|
324
|
-
"""
|
|
325
|
-
try:
|
|
326
|
-
if not deployment_aware:
|
|
327
|
-
return None
|
|
328
|
-
|
|
329
|
-
# Use dependency manager to get deployment context
|
|
330
|
-
# dependency_manager removed - use Claude Code Task Tool instead
|
|
331
|
-
deployment_config = None
|
|
332
|
-
if deployment_config:
|
|
333
|
-
self.logger.info(
|
|
334
|
-
f"Deployment context validated: {deployment_config.get('strategy', 'unknown')}"
|
|
335
|
-
)
|
|
336
|
-
return deployment_config
|
|
337
|
-
else:
|
|
338
|
-
self.logger.warning("No deployment context available - dependency manager removed")
|
|
339
|
-
return None
|
|
340
|
-
|
|
341
|
-
except Exception as e:
|
|
342
|
-
self.logger.error(f"Failed to validate deployment context: {e}")
|
|
343
|
-
return None
|
|
344
|
-
|
|
345
|
-
def should_skip_deployment(
|
|
346
|
-
self,
|
|
347
|
-
target_file: Path,
|
|
348
|
-
template_content: str,
|
|
349
|
-
force: bool,
|
|
350
|
-
template_deployer
|
|
351
|
-
) -> Tuple[bool, Optional[str], bool]:
|
|
352
|
-
"""
|
|
353
|
-
Check if deployment should be skipped based on file type and version comparison.
|
|
354
|
-
|
|
355
|
-
Args:
|
|
356
|
-
target_file: Target file path
|
|
357
|
-
template_content: Template content to deploy
|
|
358
|
-
force: Force deployment flag
|
|
359
|
-
template_deployer: Template deployer instance
|
|
360
|
-
|
|
361
|
-
Returns:
|
|
362
|
-
Tuple of (should_skip, reason, is_permanent_protection)
|
|
363
|
-
"""
|
|
364
|
-
should_skip, reason = template_deployer.should_skip_deployment(
|
|
365
|
-
target_file, template_content, force
|
|
366
|
-
)
|
|
367
|
-
|
|
368
|
-
# Check for permanent protection
|
|
369
|
-
is_permanent_protection = False
|
|
370
|
-
if path_ops.validate_exists(target_file) and should_skip:
|
|
371
|
-
existing_content = path_ops.safe_read(target_file)
|
|
372
|
-
if not existing_content:
|
|
373
|
-
return False, "Failed to read existing file content"
|
|
374
|
-
if not template_deployer.is_framework_deployment_template(existing_content):
|
|
375
|
-
is_permanent_protection = True
|
|
376
|
-
reason = "Existing file is not a framework deployment template"
|
|
377
|
-
|
|
378
|
-
return should_skip, reason, is_permanent_protection
|