crackerjack 0.29.0__py3-none-any.whl → 0.31.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of crackerjack might be problematic. Click here for more details.
- crackerjack/CLAUDE.md +1005 -0
- crackerjack/RULES.md +380 -0
- crackerjack/__init__.py +42 -13
- crackerjack/__main__.py +225 -253
- crackerjack/agents/__init__.py +41 -0
- crackerjack/agents/architect_agent.py +281 -0
- crackerjack/agents/base.py +169 -0
- crackerjack/agents/coordinator.py +512 -0
- crackerjack/agents/documentation_agent.py +498 -0
- crackerjack/agents/dry_agent.py +388 -0
- crackerjack/agents/formatting_agent.py +245 -0
- crackerjack/agents/import_optimization_agent.py +281 -0
- crackerjack/agents/performance_agent.py +669 -0
- crackerjack/agents/proactive_agent.py +104 -0
- crackerjack/agents/refactoring_agent.py +788 -0
- crackerjack/agents/security_agent.py +529 -0
- crackerjack/agents/test_creation_agent.py +652 -0
- crackerjack/agents/test_specialist_agent.py +486 -0
- crackerjack/agents/tracker.py +212 -0
- crackerjack/api.py +560 -0
- crackerjack/cli/__init__.py +24 -0
- crackerjack/cli/facade.py +104 -0
- crackerjack/cli/handlers.py +267 -0
- crackerjack/cli/interactive.py +471 -0
- crackerjack/cli/options.py +401 -0
- crackerjack/cli/utils.py +18 -0
- crackerjack/code_cleaner.py +670 -0
- crackerjack/config/__init__.py +19 -0
- crackerjack/config/hooks.py +218 -0
- crackerjack/core/__init__.py +0 -0
- crackerjack/core/async_workflow_orchestrator.py +406 -0
- crackerjack/core/autofix_coordinator.py +200 -0
- crackerjack/core/container.py +104 -0
- crackerjack/core/enhanced_container.py +542 -0
- crackerjack/core/performance.py +243 -0
- crackerjack/core/phase_coordinator.py +561 -0
- crackerjack/core/proactive_workflow.py +316 -0
- crackerjack/core/session_coordinator.py +289 -0
- crackerjack/core/workflow_orchestrator.py +640 -0
- crackerjack/dynamic_config.py +577 -0
- crackerjack/errors.py +263 -41
- crackerjack/executors/__init__.py +11 -0
- crackerjack/executors/async_hook_executor.py +431 -0
- crackerjack/executors/cached_hook_executor.py +242 -0
- crackerjack/executors/hook_executor.py +345 -0
- crackerjack/executors/individual_hook_executor.py +669 -0
- crackerjack/intelligence/__init__.py +44 -0
- crackerjack/intelligence/adaptive_learning.py +751 -0
- crackerjack/intelligence/agent_orchestrator.py +551 -0
- crackerjack/intelligence/agent_registry.py +414 -0
- crackerjack/intelligence/agent_selector.py +502 -0
- crackerjack/intelligence/integration.py +290 -0
- crackerjack/interactive.py +576 -315
- crackerjack/managers/__init__.py +11 -0
- crackerjack/managers/async_hook_manager.py +135 -0
- crackerjack/managers/hook_manager.py +137 -0
- crackerjack/managers/publish_manager.py +411 -0
- crackerjack/managers/test_command_builder.py +151 -0
- crackerjack/managers/test_executor.py +435 -0
- crackerjack/managers/test_manager.py +258 -0
- crackerjack/managers/test_manager_backup.py +1124 -0
- crackerjack/managers/test_progress.py +144 -0
- crackerjack/mcp/__init__.py +0 -0
- crackerjack/mcp/cache.py +336 -0
- crackerjack/mcp/client_runner.py +104 -0
- crackerjack/mcp/context.py +615 -0
- crackerjack/mcp/dashboard.py +636 -0
- crackerjack/mcp/enhanced_progress_monitor.py +479 -0
- crackerjack/mcp/file_monitor.py +336 -0
- crackerjack/mcp/progress_components.py +569 -0
- crackerjack/mcp/progress_monitor.py +949 -0
- crackerjack/mcp/rate_limiter.py +332 -0
- crackerjack/mcp/server.py +22 -0
- crackerjack/mcp/server_core.py +244 -0
- crackerjack/mcp/service_watchdog.py +501 -0
- crackerjack/mcp/state.py +395 -0
- crackerjack/mcp/task_manager.py +257 -0
- crackerjack/mcp/tools/__init__.py +17 -0
- crackerjack/mcp/tools/core_tools.py +249 -0
- crackerjack/mcp/tools/error_analyzer.py +308 -0
- crackerjack/mcp/tools/execution_tools.py +370 -0
- crackerjack/mcp/tools/execution_tools_backup.py +1097 -0
- crackerjack/mcp/tools/intelligence_tool_registry.py +80 -0
- crackerjack/mcp/tools/intelligence_tools.py +314 -0
- crackerjack/mcp/tools/monitoring_tools.py +502 -0
- crackerjack/mcp/tools/proactive_tools.py +384 -0
- crackerjack/mcp/tools/progress_tools.py +141 -0
- crackerjack/mcp/tools/utility_tools.py +341 -0
- crackerjack/mcp/tools/workflow_executor.py +360 -0
- crackerjack/mcp/websocket/__init__.py +14 -0
- crackerjack/mcp/websocket/app.py +39 -0
- crackerjack/mcp/websocket/endpoints.py +559 -0
- crackerjack/mcp/websocket/jobs.py +253 -0
- crackerjack/mcp/websocket/server.py +116 -0
- crackerjack/mcp/websocket/websocket_handler.py +78 -0
- crackerjack/mcp/websocket_server.py +10 -0
- crackerjack/models/__init__.py +31 -0
- crackerjack/models/config.py +93 -0
- crackerjack/models/config_adapter.py +230 -0
- crackerjack/models/protocols.py +118 -0
- crackerjack/models/task.py +154 -0
- crackerjack/monitoring/ai_agent_watchdog.py +450 -0
- crackerjack/monitoring/regression_prevention.py +638 -0
- crackerjack/orchestration/__init__.py +0 -0
- crackerjack/orchestration/advanced_orchestrator.py +970 -0
- crackerjack/orchestration/execution_strategies.py +341 -0
- crackerjack/orchestration/test_progress_streamer.py +636 -0
- crackerjack/plugins/__init__.py +15 -0
- crackerjack/plugins/base.py +200 -0
- crackerjack/plugins/hooks.py +246 -0
- crackerjack/plugins/loader.py +335 -0
- crackerjack/plugins/managers.py +259 -0
- crackerjack/py313.py +8 -3
- crackerjack/services/__init__.py +22 -0
- crackerjack/services/cache.py +314 -0
- crackerjack/services/config.py +347 -0
- crackerjack/services/config_integrity.py +99 -0
- crackerjack/services/contextual_ai_assistant.py +516 -0
- crackerjack/services/coverage_ratchet.py +347 -0
- crackerjack/services/debug.py +736 -0
- crackerjack/services/dependency_monitor.py +617 -0
- crackerjack/services/enhanced_filesystem.py +439 -0
- crackerjack/services/file_hasher.py +151 -0
- crackerjack/services/filesystem.py +395 -0
- crackerjack/services/git.py +165 -0
- crackerjack/services/health_metrics.py +611 -0
- crackerjack/services/initialization.py +847 -0
- crackerjack/services/log_manager.py +286 -0
- crackerjack/services/logging.py +174 -0
- crackerjack/services/metrics.py +578 -0
- crackerjack/services/pattern_cache.py +362 -0
- crackerjack/services/pattern_detector.py +515 -0
- crackerjack/services/performance_benchmarks.py +653 -0
- crackerjack/services/security.py +163 -0
- crackerjack/services/server_manager.py +234 -0
- crackerjack/services/smart_scheduling.py +144 -0
- crackerjack/services/tool_version_service.py +61 -0
- crackerjack/services/unified_config.py +437 -0
- crackerjack/services/version_checker.py +248 -0
- crackerjack/slash_commands/__init__.py +14 -0
- crackerjack/slash_commands/init.md +122 -0
- crackerjack/slash_commands/run.md +163 -0
- crackerjack/slash_commands/status.md +127 -0
- crackerjack-0.31.4.dist-info/METADATA +742 -0
- crackerjack-0.31.4.dist-info/RECORD +148 -0
- crackerjack-0.31.4.dist-info/entry_points.txt +2 -0
- crackerjack/.gitignore +0 -34
- crackerjack/.libcst.codemod.yaml +0 -18
- crackerjack/.pdm.toml +0 -1
- crackerjack/.pre-commit-config-ai.yaml +0 -149
- crackerjack/.pre-commit-config-fast.yaml +0 -69
- crackerjack/.pre-commit-config.yaml +0 -114
- crackerjack/crackerjack.py +0 -4140
- crackerjack/pyproject.toml +0 -285
- crackerjack-0.29.0.dist-info/METADATA +0 -1289
- crackerjack-0.29.0.dist-info/RECORD +0 -17
- {crackerjack-0.29.0.dist-info → crackerjack-0.31.4.dist-info}/WHEEL +0 -0
- {crackerjack-0.29.0.dist-info → crackerjack-0.31.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import typing as t
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
|
|
8
|
+
from crackerjack.config.hooks import HookStrategy
|
|
9
|
+
from crackerjack.models.protocols import OptionsProtocol
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ExecutionStrategy(str, Enum):
|
|
13
|
+
BATCH = "batch"
|
|
14
|
+
INDIVIDUAL = "individual"
|
|
15
|
+
ADAPTIVE = "adaptive"
|
|
16
|
+
SELECTIVE = "selective"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ProgressLevel(str, Enum):
|
|
20
|
+
BASIC = "basic"
|
|
21
|
+
DETAILED = "detailed"
|
|
22
|
+
GRANULAR = "granular"
|
|
23
|
+
STREAMING = "streaming"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class StreamingMode(str, Enum):
|
|
27
|
+
WEBSOCKET = "websocket"
|
|
28
|
+
FILE = "file"
|
|
29
|
+
HYBRID = "hybrid"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AICoordinationMode(str, Enum):
|
|
33
|
+
SINGLE_AGENT = "single - agent"
|
|
34
|
+
MULTI_AGENT = "multi - agent"
|
|
35
|
+
COORDINATOR = "coordinator"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AIIntelligence(str, Enum):
|
|
39
|
+
BASIC = "basic"
|
|
40
|
+
ADAPTIVE = "adaptive"
|
|
41
|
+
LEARNING = "learning"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class OrchestrationConfig:
|
|
46
|
+
execution_strategy: ExecutionStrategy = ExecutionStrategy.BATCH
|
|
47
|
+
progress_level: ProgressLevel = ProgressLevel.DETAILED
|
|
48
|
+
streaming_mode: StreamingMode = StreamingMode.WEBSOCKET
|
|
49
|
+
ai_coordination_mode: AICoordinationMode = AICoordinationMode.SINGLE_AGENT
|
|
50
|
+
ai_intelligence: AIIntelligence = AIIntelligence.BASIC
|
|
51
|
+
|
|
52
|
+
correlation_tracking: bool = True
|
|
53
|
+
failure_analysis: bool = True
|
|
54
|
+
intelligent_retry: bool = True
|
|
55
|
+
|
|
56
|
+
max_parallel_hooks: int = 3
|
|
57
|
+
max_parallel_tests: int = 4
|
|
58
|
+
timeout_multiplier: float = 1.0
|
|
59
|
+
|
|
60
|
+
debug_level: str = "standard"
|
|
61
|
+
log_individual_outputs: bool = False
|
|
62
|
+
preserve_temp_files: bool = False
|
|
63
|
+
|
|
64
|
+
def to_dict(self) -> dict[str, t.Any]:
|
|
65
|
+
return {
|
|
66
|
+
"execution_strategy": self.execution_strategy.value,
|
|
67
|
+
"progress_level": self.progress_level.value,
|
|
68
|
+
"streaming_mode": self.streaming_mode.value,
|
|
69
|
+
"ai_coordination_mode": self.ai_coordination_mode.value,
|
|
70
|
+
"ai_intelligence": self.ai_intelligence.value,
|
|
71
|
+
"correlation_tracking": self.correlation_tracking,
|
|
72
|
+
"failure_analysis": self.failure_analysis,
|
|
73
|
+
"intelligent_retry": self.intelligent_retry,
|
|
74
|
+
"max_parallel_hooks": self.max_parallel_hooks,
|
|
75
|
+
"max_parallel_tests": self.max_parallel_tests,
|
|
76
|
+
"timeout_multiplier": self.timeout_multiplier,
|
|
77
|
+
"debug_level": self.debug_level,
|
|
78
|
+
"log_individual_outputs": self.log_individual_outputs,
|
|
79
|
+
"preserve_temp_files": self.preserve_temp_files,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class ExecutionContext:
|
|
84
|
+
def __init__(
|
|
85
|
+
self,
|
|
86
|
+
pkg_path: Path,
|
|
87
|
+
options: OptionsProtocol,
|
|
88
|
+
previous_failures: list[str] | None = None,
|
|
89
|
+
changed_files: list[Path] | None = None,
|
|
90
|
+
iteration_count: int = 1,
|
|
91
|
+
) -> None:
|
|
92
|
+
self.pkg_path = pkg_path
|
|
93
|
+
self.options = options
|
|
94
|
+
self.previous_failures = previous_failures or []
|
|
95
|
+
self.changed_files = changed_files or []
|
|
96
|
+
self.iteration_count = iteration_count
|
|
97
|
+
|
|
98
|
+
self.total_python_files = len(list(pkg_path.rglob(" * .py")))
|
|
99
|
+
self.total_test_files = len(list(pkg_path.glob("tests / test_ * .py")))
|
|
100
|
+
self.has_complex_setup = self._detect_complex_setup()
|
|
101
|
+
self.estimated_hook_duration = self._estimate_hook_duration()
|
|
102
|
+
|
|
103
|
+
def _detect_complex_setup(self) -> bool:
|
|
104
|
+
complex_indicators = [
|
|
105
|
+
(self.pkg_path / "pyproject.toml").exists(),
|
|
106
|
+
(self.pkg_path / "setup.py").exists(),
|
|
107
|
+
(self.pkg_path / "requirements.txt").exists(),
|
|
108
|
+
len(list(self.pkg_path.rglob(" * .py"))) > 50,
|
|
109
|
+
len(list(self.pkg_path.glob("tests / test_ * .py"))) > 20,
|
|
110
|
+
]
|
|
111
|
+
return sum(complex_indicators) >= 3
|
|
112
|
+
|
|
113
|
+
def _estimate_hook_duration(self) -> float:
|
|
114
|
+
base_time = 30.0
|
|
115
|
+
file_factor = self.total_python_files * 0.5
|
|
116
|
+
test_factor = self.total_test_files * 2.0
|
|
117
|
+
|
|
118
|
+
return base_time + file_factor + test_factor
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class StrategySelector:
|
|
122
|
+
def __init__(self, console: Console) -> None:
|
|
123
|
+
self.console = console
|
|
124
|
+
|
|
125
|
+
def select_strategy(
|
|
126
|
+
self,
|
|
127
|
+
config: OrchestrationConfig,
|
|
128
|
+
context: ExecutionContext,
|
|
129
|
+
) -> ExecutionStrategy:
|
|
130
|
+
if config.execution_strategy != ExecutionStrategy.ADAPTIVE:
|
|
131
|
+
return config.execution_strategy
|
|
132
|
+
|
|
133
|
+
return self._select_adaptive_strategy(context)
|
|
134
|
+
|
|
135
|
+
def _select_adaptive_strategy(self, context: ExecutionContext) -> ExecutionStrategy:
|
|
136
|
+
if context.iteration_count == 1:
|
|
137
|
+
return ExecutionStrategy.BATCH
|
|
138
|
+
|
|
139
|
+
if len(context.previous_failures) > 5:
|
|
140
|
+
self.console.print(
|
|
141
|
+
"[yellow]🧠 Switching to individual execution due to multiple failures[/yellow]",
|
|
142
|
+
)
|
|
143
|
+
return ExecutionStrategy.INDIVIDUAL
|
|
144
|
+
|
|
145
|
+
if context.changed_files and len(context.changed_files) < 5:
|
|
146
|
+
self.console.print(
|
|
147
|
+
"[cyan]🎯 Using selective execution for targeted file changes[/cyan]",
|
|
148
|
+
)
|
|
149
|
+
return ExecutionStrategy.SELECTIVE
|
|
150
|
+
|
|
151
|
+
if context.has_complex_setup and context.iteration_count > 2:
|
|
152
|
+
return ExecutionStrategy.INDIVIDUAL
|
|
153
|
+
|
|
154
|
+
return ExecutionStrategy.BATCH
|
|
155
|
+
|
|
156
|
+
def select_hook_subset(
|
|
157
|
+
self,
|
|
158
|
+
strategy: HookStrategy,
|
|
159
|
+
execution_strategy: ExecutionStrategy,
|
|
160
|
+
context: ExecutionContext,
|
|
161
|
+
) -> HookStrategy:
|
|
162
|
+
if execution_strategy == ExecutionStrategy.SELECTIVE:
|
|
163
|
+
return self._create_selective_strategy(strategy, context)
|
|
164
|
+
|
|
165
|
+
return strategy
|
|
166
|
+
|
|
167
|
+
def _create_selective_strategy(
|
|
168
|
+
self,
|
|
169
|
+
strategy: HookStrategy,
|
|
170
|
+
context: ExecutionContext,
|
|
171
|
+
) -> HookStrategy:
|
|
172
|
+
priority_hooks = set(context.previous_failures)
|
|
173
|
+
|
|
174
|
+
if context.changed_files:
|
|
175
|
+
for file_path in context.changed_files:
|
|
176
|
+
if file_path.suffix == ".py":
|
|
177
|
+
priority_hooks.update(["pyright", "ruff - check", "ruff - format"])
|
|
178
|
+
if "test" in str(file_path):
|
|
179
|
+
priority_hooks.update(["pytest", "coverage"])
|
|
180
|
+
if str(file_path).endswith(("setup.py", "pyproject.toml")):
|
|
181
|
+
priority_hooks.update(["bandit", "creosote", "detect - secrets"])
|
|
182
|
+
|
|
183
|
+
selected_hooks = [
|
|
184
|
+
hook for hook in strategy.hooks if hook.name in priority_hooks
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
if not selected_hooks:
|
|
188
|
+
selected_hooks = strategy.hooks[:3]
|
|
189
|
+
|
|
190
|
+
self.console.print(
|
|
191
|
+
f"[cyan]🎯 Selected {len(selected_hooks)} hooks for targeted execution: "
|
|
192
|
+
f"{', '.join(h.name for h in selected_hooks)}[/cyan]",
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return HookStrategy(
|
|
196
|
+
name=f"{strategy.name}_selective",
|
|
197
|
+
hooks=selected_hooks,
|
|
198
|
+
timeout=strategy.timeout,
|
|
199
|
+
retry_policy=strategy.retry_policy,
|
|
200
|
+
parallel=strategy.parallel,
|
|
201
|
+
max_workers=min(strategy.max_workers, len(selected_hooks)),
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class OrchestrationPlanner:
|
|
206
|
+
def __init__(self, console: Console) -> None:
|
|
207
|
+
self.console = console
|
|
208
|
+
self.strategy_selector = StrategySelector(console)
|
|
209
|
+
|
|
210
|
+
def create_execution_plan(
|
|
211
|
+
self,
|
|
212
|
+
config: OrchestrationConfig,
|
|
213
|
+
context: ExecutionContext,
|
|
214
|
+
hook_strategies: list[HookStrategy],
|
|
215
|
+
) -> "ExecutionPlan":
|
|
216
|
+
execution_strategy = self.strategy_selector.select_strategy(config, context)
|
|
217
|
+
|
|
218
|
+
hook_plans = []
|
|
219
|
+
for strategy in hook_strategies:
|
|
220
|
+
selected_strategy = self.strategy_selector.select_hook_subset(
|
|
221
|
+
strategy,
|
|
222
|
+
execution_strategy,
|
|
223
|
+
context,
|
|
224
|
+
)
|
|
225
|
+
hook_plans.append(
|
|
226
|
+
{
|
|
227
|
+
"strategy": selected_strategy,
|
|
228
|
+
"execution_mode": execution_strategy,
|
|
229
|
+
"estimated_duration": self._estimate_strategy_duration(
|
|
230
|
+
selected_strategy,
|
|
231
|
+
),
|
|
232
|
+
},
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
test_plan = self._create_test_plan(config, context, execution_strategy)
|
|
236
|
+
|
|
237
|
+
ai_plan = self._create_ai_plan(config, context)
|
|
238
|
+
|
|
239
|
+
return ExecutionPlan(
|
|
240
|
+
config=config,
|
|
241
|
+
execution_strategy=execution_strategy,
|
|
242
|
+
hook_plans=hook_plans,
|
|
243
|
+
test_plan=test_plan,
|
|
244
|
+
ai_plan=ai_plan,
|
|
245
|
+
estimated_total_duration=sum(
|
|
246
|
+
plan["estimated_duration"] for plan in hook_plans
|
|
247
|
+
)
|
|
248
|
+
+ test_plan["estimated_duration"],
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
def _estimate_strategy_duration(self, strategy: HookStrategy) -> float:
|
|
252
|
+
base_time_per_hook = 10.0
|
|
253
|
+
return len(strategy.hooks) * base_time_per_hook
|
|
254
|
+
|
|
255
|
+
def _create_test_plan(
|
|
256
|
+
self,
|
|
257
|
+
config: OrchestrationConfig,
|
|
258
|
+
context: ExecutionContext,
|
|
259
|
+
execution_strategy: ExecutionStrategy,
|
|
260
|
+
) -> dict[str, t.Any]:
|
|
261
|
+
if execution_strategy == ExecutionStrategy.INDIVIDUAL:
|
|
262
|
+
test_mode = "individual_with_progress"
|
|
263
|
+
elif execution_strategy == ExecutionStrategy.SELECTIVE:
|
|
264
|
+
test_mode = "selective"
|
|
265
|
+
else:
|
|
266
|
+
test_mode = "full_suite"
|
|
267
|
+
|
|
268
|
+
return {
|
|
269
|
+
"mode": test_mode,
|
|
270
|
+
"parallel_workers": min(
|
|
271
|
+
config.max_parallel_tests,
|
|
272
|
+
context.total_test_files,
|
|
273
|
+
),
|
|
274
|
+
"estimated_duration": context.total_test_files * 2.0,
|
|
275
|
+
"progress_tracking": config.progress_level
|
|
276
|
+
in (ProgressLevel.DETAILED, ProgressLevel.GRANULAR),
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
def _create_ai_plan(
|
|
280
|
+
self,
|
|
281
|
+
config: OrchestrationConfig,
|
|
282
|
+
context: ExecutionContext,
|
|
283
|
+
) -> dict[str, t.Any]:
|
|
284
|
+
return {
|
|
285
|
+
"mode": config.ai_coordination_mode,
|
|
286
|
+
"intelligence_level": config.ai_intelligence,
|
|
287
|
+
"batch_processing": True,
|
|
288
|
+
"correlation_tracking": config.correlation_tracking,
|
|
289
|
+
"failure_analysis": config.failure_analysis,
|
|
290
|
+
"adaptive_retry": config.intelligent_retry,
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@dataclass
|
|
295
|
+
class ExecutionPlan:
|
|
296
|
+
config: OrchestrationConfig
|
|
297
|
+
execution_strategy: ExecutionStrategy
|
|
298
|
+
hook_plans: list[dict[str, t.Any]]
|
|
299
|
+
test_plan: dict[str, t.Any]
|
|
300
|
+
ai_plan: dict[str, t.Any]
|
|
301
|
+
estimated_total_duration: float
|
|
302
|
+
|
|
303
|
+
def print_plan_summary(self, console: Console) -> None:
|
|
304
|
+
console.print("\n" + "=" * 80)
|
|
305
|
+
console.print(
|
|
306
|
+
"[bold bright_blue]🎯 ORCHESTRATED EXECUTION PLAN[/bold bright_blue]",
|
|
307
|
+
)
|
|
308
|
+
console.print("=" * 80)
|
|
309
|
+
|
|
310
|
+
console.print(f"[bold]Strategy: [/bold] {self.execution_strategy.value}")
|
|
311
|
+
console.print(
|
|
312
|
+
f"[bold]AI Mode: [/bold] {self.config.ai_coordination_mode.value}",
|
|
313
|
+
)
|
|
314
|
+
console.print(
|
|
315
|
+
f"[bold]Progress Level: [/bold] {self.config.progress_level.value}",
|
|
316
|
+
)
|
|
317
|
+
console.print(
|
|
318
|
+
f"[bold]Estimated Duration: [/bold] {self.estimated_total_duration: .1f}s",
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
console.print("\n[bold cyan]Hook Execution: [/bold cyan]")
|
|
322
|
+
for i, plan in enumerate(self.hook_plans, 1):
|
|
323
|
+
strategy = plan["strategy"]
|
|
324
|
+
console.print(
|
|
325
|
+
f" {i}. {strategy.name} - {len(strategy.hooks)} hooks "
|
|
326
|
+
f"({plan['estimated_duration']: .1f}s)",
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
console.print("\n[bold green]Test Execution: [/bold green]")
|
|
330
|
+
console.print(f" Mode: {self.test_plan['mode']}")
|
|
331
|
+
console.print(f" Workers: {self.test_plan['parallel_workers']}")
|
|
332
|
+
console.print(f" Duration: {self.test_plan['estimated_duration']: .1f}s")
|
|
333
|
+
|
|
334
|
+
console.print("\n[bold magenta]AI Coordination: [/bold magenta]")
|
|
335
|
+
console.print(f" Mode: {self.ai_plan['mode'].value}")
|
|
336
|
+
console.print(f" Intelligence: {self.ai_plan['intelligence_level'].value}")
|
|
337
|
+
console.print(
|
|
338
|
+
f" Batch Processing: {'✅' if self.ai_plan['batch_processing'] else '❌'}",
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
console.print("=" * 80)
|