crackerjack 0.31.10__py3-none-any.whl → 0.31.12__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 +288 -705
- crackerjack/__main__.py +22 -8
- crackerjack/agents/__init__.py +0 -3
- crackerjack/agents/architect_agent.py +0 -43
- crackerjack/agents/base.py +1 -9
- crackerjack/agents/coordinator.py +2 -148
- crackerjack/agents/documentation_agent.py +109 -81
- crackerjack/agents/dry_agent.py +122 -97
- crackerjack/agents/formatting_agent.py +3 -16
- crackerjack/agents/import_optimization_agent.py +1174 -130
- crackerjack/agents/performance_agent.py +956 -188
- crackerjack/agents/performance_helpers.py +229 -0
- crackerjack/agents/proactive_agent.py +1 -48
- crackerjack/agents/refactoring_agent.py +516 -246
- crackerjack/agents/refactoring_helpers.py +282 -0
- crackerjack/agents/security_agent.py +393 -90
- crackerjack/agents/test_creation_agent.py +1776 -120
- crackerjack/agents/test_specialist_agent.py +59 -15
- crackerjack/agents/tracker.py +0 -102
- crackerjack/api.py +145 -37
- crackerjack/cli/handlers.py +48 -30
- crackerjack/cli/interactive.py +11 -11
- crackerjack/cli/options.py +66 -4
- crackerjack/code_cleaner.py +808 -148
- crackerjack/config/global_lock_config.py +110 -0
- crackerjack/config/hooks.py +43 -64
- crackerjack/core/async_workflow_orchestrator.py +247 -97
- crackerjack/core/autofix_coordinator.py +192 -109
- crackerjack/core/enhanced_container.py +46 -63
- crackerjack/core/file_lifecycle.py +549 -0
- crackerjack/core/performance.py +9 -8
- crackerjack/core/performance_monitor.py +395 -0
- crackerjack/core/phase_coordinator.py +281 -94
- crackerjack/core/proactive_workflow.py +9 -58
- crackerjack/core/resource_manager.py +501 -0
- crackerjack/core/service_watchdog.py +490 -0
- crackerjack/core/session_coordinator.py +4 -8
- crackerjack/core/timeout_manager.py +504 -0
- crackerjack/core/websocket_lifecycle.py +475 -0
- crackerjack/core/workflow_orchestrator.py +343 -209
- crackerjack/dynamic_config.py +47 -6
- crackerjack/errors.py +3 -4
- crackerjack/executors/async_hook_executor.py +63 -13
- crackerjack/executors/cached_hook_executor.py +14 -14
- crackerjack/executors/hook_executor.py +100 -37
- crackerjack/executors/hook_lock_manager.py +856 -0
- crackerjack/executors/individual_hook_executor.py +120 -86
- crackerjack/intelligence/__init__.py +0 -7
- crackerjack/intelligence/adaptive_learning.py +13 -86
- crackerjack/intelligence/agent_orchestrator.py +15 -78
- crackerjack/intelligence/agent_registry.py +12 -59
- crackerjack/intelligence/agent_selector.py +31 -92
- crackerjack/intelligence/integration.py +1 -41
- crackerjack/interactive.py +9 -9
- crackerjack/managers/async_hook_manager.py +25 -8
- crackerjack/managers/hook_manager.py +9 -9
- crackerjack/managers/publish_manager.py +57 -59
- crackerjack/managers/test_command_builder.py +6 -36
- crackerjack/managers/test_executor.py +9 -61
- crackerjack/managers/test_manager.py +17 -63
- crackerjack/managers/test_manager_backup.py +77 -127
- crackerjack/managers/test_progress.py +4 -23
- crackerjack/mcp/cache.py +5 -12
- crackerjack/mcp/client_runner.py +10 -10
- crackerjack/mcp/context.py +64 -6
- crackerjack/mcp/dashboard.py +14 -11
- crackerjack/mcp/enhanced_progress_monitor.py +55 -55
- crackerjack/mcp/file_monitor.py +72 -42
- crackerjack/mcp/progress_components.py +103 -84
- crackerjack/mcp/progress_monitor.py +122 -49
- crackerjack/mcp/rate_limiter.py +12 -12
- crackerjack/mcp/server_core.py +16 -22
- crackerjack/mcp/service_watchdog.py +26 -26
- crackerjack/mcp/state.py +15 -0
- crackerjack/mcp/tools/core_tools.py +95 -39
- crackerjack/mcp/tools/error_analyzer.py +6 -32
- crackerjack/mcp/tools/execution_tools.py +1 -56
- crackerjack/mcp/tools/execution_tools_backup.py +35 -131
- crackerjack/mcp/tools/intelligence_tool_registry.py +0 -36
- crackerjack/mcp/tools/intelligence_tools.py +2 -55
- crackerjack/mcp/tools/monitoring_tools.py +308 -145
- crackerjack/mcp/tools/proactive_tools.py +12 -42
- crackerjack/mcp/tools/progress_tools.py +23 -15
- crackerjack/mcp/tools/utility_tools.py +3 -40
- crackerjack/mcp/tools/workflow_executor.py +40 -60
- crackerjack/mcp/websocket/app.py +0 -3
- crackerjack/mcp/websocket/endpoints.py +206 -268
- crackerjack/mcp/websocket/jobs.py +213 -66
- crackerjack/mcp/websocket/server.py +84 -6
- crackerjack/mcp/websocket/websocket_handler.py +137 -29
- crackerjack/models/config_adapter.py +3 -16
- crackerjack/models/protocols.py +162 -3
- crackerjack/models/resource_protocols.py +454 -0
- crackerjack/models/task.py +3 -3
- crackerjack/monitoring/__init__.py +0 -0
- crackerjack/monitoring/ai_agent_watchdog.py +25 -71
- crackerjack/monitoring/regression_prevention.py +28 -87
- crackerjack/orchestration/advanced_orchestrator.py +44 -78
- crackerjack/orchestration/coverage_improvement.py +10 -60
- crackerjack/orchestration/execution_strategies.py +16 -16
- crackerjack/orchestration/test_progress_streamer.py +61 -53
- crackerjack/plugins/base.py +1 -1
- crackerjack/plugins/managers.py +22 -20
- crackerjack/py313.py +65 -21
- crackerjack/services/backup_service.py +467 -0
- crackerjack/services/bounded_status_operations.py +627 -0
- crackerjack/services/cache.py +7 -9
- crackerjack/services/config.py +35 -52
- crackerjack/services/config_integrity.py +5 -16
- crackerjack/services/config_merge.py +542 -0
- crackerjack/services/contextual_ai_assistant.py +17 -19
- crackerjack/services/coverage_ratchet.py +44 -73
- crackerjack/services/debug.py +25 -39
- crackerjack/services/dependency_monitor.py +52 -50
- crackerjack/services/enhanced_filesystem.py +14 -11
- crackerjack/services/file_hasher.py +1 -1
- crackerjack/services/filesystem.py +1 -12
- crackerjack/services/git.py +71 -47
- crackerjack/services/health_metrics.py +31 -27
- crackerjack/services/initialization.py +276 -428
- crackerjack/services/input_validator.py +760 -0
- crackerjack/services/log_manager.py +16 -16
- crackerjack/services/logging.py +7 -6
- crackerjack/services/metrics.py +43 -43
- crackerjack/services/pattern_cache.py +2 -31
- crackerjack/services/pattern_detector.py +26 -63
- crackerjack/services/performance_benchmarks.py +20 -45
- crackerjack/services/regex_patterns.py +2887 -0
- crackerjack/services/regex_utils.py +537 -0
- crackerjack/services/secure_path_utils.py +683 -0
- crackerjack/services/secure_status_formatter.py +534 -0
- crackerjack/services/secure_subprocess.py +605 -0
- crackerjack/services/security.py +47 -10
- crackerjack/services/security_logger.py +492 -0
- crackerjack/services/server_manager.py +109 -50
- crackerjack/services/smart_scheduling.py +8 -25
- crackerjack/services/status_authentication.py +603 -0
- crackerjack/services/status_security_manager.py +442 -0
- crackerjack/services/thread_safe_status_collector.py +546 -0
- crackerjack/services/tool_version_service.py +1 -23
- crackerjack/services/unified_config.py +36 -58
- crackerjack/services/validation_rate_limiter.py +269 -0
- crackerjack/services/version_checker.py +9 -40
- crackerjack/services/websocket_resource_limiter.py +572 -0
- crackerjack/slash_commands/__init__.py +52 -2
- crackerjack/tools/__init__.py +0 -0
- crackerjack/tools/validate_input_validator_patterns.py +262 -0
- crackerjack/tools/validate_regex_patterns.py +198 -0
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/METADATA +197 -12
- crackerjack-0.31.12.dist-info/RECORD +178 -0
- crackerjack/cli/facade.py +0 -104
- crackerjack-0.31.10.dist-info/RECORD +0 -149
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/WHEEL +0 -0
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/licenses/LICENSE +0 -0
crackerjack/cli/handlers.py
CHANGED
|
@@ -9,6 +9,10 @@ from .options import Options
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def setup_ai_agent_env(ai_agent: bool, verbose: bool = False) -> None:
|
|
12
|
+
# Set debug environment variable if verbose is enabled
|
|
13
|
+
if verbose:
|
|
14
|
+
os.environ["CRACKERJACK_DEBUG"] = "1"
|
|
15
|
+
|
|
12
16
|
if ai_agent:
|
|
13
17
|
os.environ["AI_AGENT"] = "1"
|
|
14
18
|
os.environ["AI_AGENT_DEBUG"] = "1"
|
|
@@ -19,7 +23,7 @@ def setup_ai_agent_env(ai_agent: bool, verbose: bool = False) -> None:
|
|
|
19
23
|
if verbose:
|
|
20
24
|
console = Console()
|
|
21
25
|
console.print(
|
|
22
|
-
"[bold cyan]🐛 AI Agent Debug Mode Configuration: [/bold cyan]",
|
|
26
|
+
"[bold cyan]🐛 AI Agent Debug Mode Configuration: [/ bold cyan]",
|
|
23
27
|
)
|
|
24
28
|
console.print(f" • AI Agent: {'✅ Enabled' if ai_agent else '❌ Disabled'}")
|
|
25
29
|
console.print(
|
|
@@ -34,7 +38,6 @@ def setup_ai_agent_env(ai_agent: bool, verbose: bool = False) -> None:
|
|
|
34
38
|
def handle_mcp_server(websocket_port: int | None = None) -> None:
|
|
35
39
|
from crackerjack.mcp.server import main as start_mcp_main
|
|
36
40
|
|
|
37
|
-
# Always pass current working directory as project path
|
|
38
41
|
project_path = str(Path.cwd())
|
|
39
42
|
|
|
40
43
|
if websocket_port:
|
|
@@ -47,45 +50,45 @@ def handle_monitor_mode(dev_mode: bool = False) -> None:
|
|
|
47
50
|
from crackerjack.mcp.progress_monitor import run_progress_monitor
|
|
48
51
|
|
|
49
52
|
console = Console()
|
|
50
|
-
console.print("[bold cyan]🌟 Starting Multi-Project Progress Monitor[/bold cyan]")
|
|
53
|
+
console.print("[bold cyan]🌟 Starting Multi-Project Progress Monitor[/ bold cyan]")
|
|
51
54
|
console.print(
|
|
52
|
-
"[bold yellow]🐕 With integrated Service Watchdog and WebSocket polling[/bold yellow]",
|
|
55
|
+
"[bold yellow]🐕 With integrated Service Watchdog and WebSocket polling[/ bold yellow]",
|
|
53
56
|
)
|
|
54
57
|
|
|
55
58
|
try:
|
|
56
59
|
asyncio.run(run_progress_monitor(dev_mode=dev_mode))
|
|
57
60
|
except KeyboardInterrupt:
|
|
58
|
-
console.print("\n[yellow]🛑 Monitor stopped[/yellow]")
|
|
61
|
+
console.print("\n[yellow]🛑 Monitor stopped[/ yellow]")
|
|
59
62
|
|
|
60
63
|
|
|
61
64
|
def handle_enhanced_monitor_mode(dev_mode: bool = False) -> None:
|
|
62
65
|
from crackerjack.mcp.enhanced_progress_monitor import run_enhanced_progress_monitor
|
|
63
66
|
|
|
64
67
|
console = Console()
|
|
65
|
-
console.print("[bold magenta]✨ Starting Enhanced Progress Monitor[/bold magenta]")
|
|
68
|
+
console.print("[bold magenta]✨ Starting Enhanced Progress Monitor[/ bold magenta]")
|
|
66
69
|
console.print(
|
|
67
|
-
"[bold cyan]📊 With advanced MetricCard widgets and modern web UI patterns[/bold cyan]",
|
|
70
|
+
"[bold cyan]📊 With advanced MetricCard widgets and modern web UI patterns[/ bold cyan]",
|
|
68
71
|
)
|
|
69
72
|
|
|
70
73
|
try:
|
|
71
74
|
asyncio.run(run_enhanced_progress_monitor(dev_mode=dev_mode))
|
|
72
75
|
except KeyboardInterrupt:
|
|
73
|
-
console.print("\n[yellow]🛑 Enhanced Monitor stopped[/yellow]")
|
|
76
|
+
console.print("\n[yellow]🛑 Enhanced Monitor stopped[/ yellow]")
|
|
74
77
|
|
|
75
78
|
|
|
76
79
|
def handle_dashboard_mode(dev_mode: bool = False) -> None:
|
|
77
80
|
from crackerjack.mcp.dashboard import run_dashboard
|
|
78
81
|
|
|
79
82
|
console = Console()
|
|
80
|
-
console.print("[bold green]🎯 Starting Comprehensive Dashboard[/bold green]")
|
|
83
|
+
console.print("[bold green]🎯 Starting Comprehensive Dashboard[/ bold green]")
|
|
81
84
|
console.print(
|
|
82
|
-
"[bold cyan]📈 With system metrics, job tracking, and performance monitoring[/bold cyan]",
|
|
85
|
+
"[bold cyan]📈 With system metrics, job tracking, and performance monitoring[/ bold cyan]",
|
|
83
86
|
)
|
|
84
87
|
|
|
85
88
|
try:
|
|
86
89
|
run_dashboard()
|
|
87
90
|
except KeyboardInterrupt:
|
|
88
|
-
console.print("\n[yellow]🛑 Dashboard stopped[/yellow]")
|
|
91
|
+
console.print("\n[yellow]🛑 Dashboard stopped[/ yellow]")
|
|
89
92
|
|
|
90
93
|
|
|
91
94
|
def handle_watchdog_mode() -> None:
|
|
@@ -95,7 +98,7 @@ def handle_watchdog_mode() -> None:
|
|
|
95
98
|
try:
|
|
96
99
|
asyncio.run(start_watchdog())
|
|
97
100
|
except KeyboardInterrupt:
|
|
98
|
-
console.print("\n[yellow]🛑 Watchdog stopped[/yellow]")
|
|
101
|
+
console.print("\n[yellow]🛑 Watchdog stopped[/ yellow]")
|
|
99
102
|
|
|
100
103
|
|
|
101
104
|
def handle_start_websocket_server(port: int = 8675) -> None:
|
|
@@ -120,14 +123,14 @@ def handle_stop_mcp_server() -> None:
|
|
|
120
123
|
from crackerjack.services.server_manager import list_server_status, stop_all_servers
|
|
121
124
|
|
|
122
125
|
console = Console()
|
|
123
|
-
console.print("[bold red]🛑 Stopping MCP Servers[/bold red]")
|
|
126
|
+
console.print("[bold red]🛑 Stopping MCP Servers[/ bold red]")
|
|
124
127
|
|
|
125
128
|
list_server_status(console)
|
|
126
129
|
|
|
127
130
|
if stop_all_servers(console):
|
|
128
|
-
console.print("\n[bold green]✅ All servers stopped successfully[/bold green]")
|
|
131
|
+
console.print("\n[bold green]✅ All servers stopped successfully[/ bold green]")
|
|
129
132
|
else:
|
|
130
|
-
console.print("\n[bold red]❌ Some servers failed to stop[/bold red]")
|
|
133
|
+
console.print("\n[bold red]❌ Some servers failed to stop[/ bold red]")
|
|
131
134
|
raise SystemExit(1)
|
|
132
135
|
|
|
133
136
|
|
|
@@ -136,9 +139,9 @@ def handle_restart_mcp_server(websocket_port: int | None = None) -> None:
|
|
|
136
139
|
|
|
137
140
|
console = Console()
|
|
138
141
|
if restart_mcp_server(websocket_port, console):
|
|
139
|
-
console.print("\n[bold green]✅ MCP server restart completed[/bold green]")
|
|
142
|
+
console.print("\n[bold green]✅ MCP server restart completed[/ bold green]")
|
|
140
143
|
else:
|
|
141
|
-
console.print("\n[bold red]❌ MCP server restart failed[/bold red]")
|
|
144
|
+
console.print("\n[bold red]❌ MCP server restart failed[/ bold red]")
|
|
142
145
|
raise SystemExit(1)
|
|
143
146
|
|
|
144
147
|
|
|
@@ -161,6 +164,11 @@ def handle_standard_mode(
|
|
|
161
164
|
|
|
162
165
|
console = Console()
|
|
163
166
|
|
|
167
|
+
# Configure global lock manager from CLI options
|
|
168
|
+
from crackerjack.executors.hook_lock_manager import hook_lock_manager
|
|
169
|
+
|
|
170
|
+
hook_lock_manager.configure_from_options(options)
|
|
171
|
+
|
|
164
172
|
if orchestrated:
|
|
165
173
|
handle_orchestrated_mode(options, job_id)
|
|
166
174
|
else:
|
|
@@ -175,15 +183,20 @@ def handle_standard_mode(
|
|
|
175
183
|
orchestrator = AsyncWorkflowOrchestrator(
|
|
176
184
|
console=console,
|
|
177
185
|
pkg_path=pkg_path,
|
|
186
|
+
dry_run=getattr(options, "dry_run", False),
|
|
178
187
|
web_job_id=job_id,
|
|
188
|
+
verbose=options.verbose,
|
|
189
|
+
debug=getattr(options, "debug", False),
|
|
179
190
|
)
|
|
180
191
|
success = asyncio.run(orchestrator.run_complete_workflow_async(options))
|
|
181
192
|
else:
|
|
182
193
|
orchestrator = WorkflowOrchestrator(
|
|
183
194
|
console=console,
|
|
184
195
|
pkg_path=pkg_path,
|
|
196
|
+
dry_run=getattr(options, "dry_run", False),
|
|
185
197
|
web_job_id=job_id,
|
|
186
198
|
verbose=options.verbose,
|
|
199
|
+
debug=getattr(options, "debug", False),
|
|
187
200
|
)
|
|
188
201
|
success = asyncio.run(orchestrator.run_complete_workflow(options))
|
|
189
202
|
|
|
@@ -195,7 +208,12 @@ def handle_orchestrated_mode(options: Options, job_id: str | None = None) -> Non
|
|
|
195
208
|
from rich.console import Console
|
|
196
209
|
|
|
197
210
|
console = Console()
|
|
198
|
-
console.print("[bold bright_blue]🚀 ORCHESTRATED MODE ENABLED[/bold bright_blue]")
|
|
211
|
+
console.print("[bold bright_blue]🚀 ORCHESTRATED MODE ENABLED[/ bold bright_blue]")
|
|
212
|
+
|
|
213
|
+
# Configure global lock manager from CLI options
|
|
214
|
+
from crackerjack.executors.hook_lock_manager import hook_lock_manager
|
|
215
|
+
|
|
216
|
+
hook_lock_manager.configure_from_options(options)
|
|
199
217
|
|
|
200
218
|
try:
|
|
201
219
|
from crackerjack.core.session_coordinator import SessionCoordinator
|
|
@@ -209,8 +227,8 @@ def handle_orchestrated_mode(options: Options, job_id: str | None = None) -> Non
|
|
|
209
227
|
ProgressLevel,
|
|
210
228
|
)
|
|
211
229
|
except ImportError as e:
|
|
212
|
-
console.print(f"[red]Orchestrated mode not available: {e}[/red]")
|
|
213
|
-
console.print("[yellow]Falling back to standard mode[/yellow]")
|
|
230
|
+
console.print(f"[red]Orchestrated mode not available: {e}[/ red]")
|
|
231
|
+
console.print("[yellow]Falling back to standard mode[/ yellow]")
|
|
214
232
|
handle_standard_mode(options, False, job_id)
|
|
215
233
|
return
|
|
216
234
|
|
|
@@ -218,7 +236,7 @@ def handle_orchestrated_mode(options: Options, job_id: str | None = None) -> Non
|
|
|
218
236
|
strategy = ExecutionStrategy(options.orchestration_strategy)
|
|
219
237
|
except ValueError:
|
|
220
238
|
console.print(
|
|
221
|
-
f"[red]Invalid orchestration strategy: {options.orchestration_strategy}[/red]",
|
|
239
|
+
f"[red]Invalid orchestration strategy: {options.orchestration_strategy}[/ red]",
|
|
222
240
|
)
|
|
223
241
|
strategy = ExecutionStrategy.ADAPTIVE
|
|
224
242
|
|
|
@@ -226,14 +244,14 @@ def handle_orchestrated_mode(options: Options, job_id: str | None = None) -> Non
|
|
|
226
244
|
progress = ProgressLevel(options.orchestration_progress)
|
|
227
245
|
except ValueError:
|
|
228
246
|
console.print(
|
|
229
|
-
f"[red]Invalid progress level: {options.orchestration_progress}[/red]",
|
|
247
|
+
f"[red]Invalid progress level: {options.orchestration_progress}[/ red]",
|
|
230
248
|
)
|
|
231
249
|
progress = ProgressLevel.GRANULAR
|
|
232
250
|
|
|
233
251
|
try:
|
|
234
252
|
ai_mode = AICoordinationMode(options.orchestration_ai_mode)
|
|
235
253
|
except ValueError:
|
|
236
|
-
console.print(f"[red]Invalid AI mode: {options.orchestration_ai_mode}[/red]")
|
|
254
|
+
console.print(f"[red]Invalid AI mode: {options.orchestration_ai_mode}[/ red]")
|
|
237
255
|
ai_mode = AICoordinationMode.SINGLE_AGENT
|
|
238
256
|
|
|
239
257
|
config = OrchestrationConfig(
|
|
@@ -242,9 +260,9 @@ def handle_orchestrated_mode(options: Options, job_id: str | None = None) -> Non
|
|
|
242
260
|
ai_coordination_mode=ai_mode,
|
|
243
261
|
)
|
|
244
262
|
|
|
245
|
-
console.print(f"[cyan]Execution Strategy: [/cyan] {strategy.value}")
|
|
246
|
-
console.print(f"[cyan]Progress Level: [/cyan] {progress.value}")
|
|
247
|
-
console.print(f"[cyan]AI Coordination: [/cyan] {ai_mode.value}")
|
|
263
|
+
console.print(f"[cyan]Execution Strategy: [/ cyan] {strategy.value}")
|
|
264
|
+
console.print(f"[cyan]Progress Level: [/ cyan] {progress.value}")
|
|
265
|
+
console.print(f"[cyan]AI Coordination: [/ cyan] {ai_mode.value}")
|
|
248
266
|
|
|
249
267
|
pkg_path = Path.cwd()
|
|
250
268
|
session = SessionCoordinator(console, pkg_path, web_job_id=job_id)
|
|
@@ -254,14 +272,14 @@ def handle_orchestrated_mode(options: Options, job_id: str | None = None) -> Non
|
|
|
254
272
|
success = asyncio.run(orchestrator.execute_orchestrated_workflow(options))
|
|
255
273
|
if success:
|
|
256
274
|
console.print(
|
|
257
|
-
"\n[bold green]🎉 ORCHESTRATED WORKFLOW COMPLETED SUCCESSFULLY![/bold green]",
|
|
275
|
+
"\n[bold green]🎉 ORCHESTRATED WORKFLOW COMPLETED SUCCESSFULLY ![/ bold green]",
|
|
258
276
|
)
|
|
259
277
|
else:
|
|
260
|
-
console.print("\n[bold red]❌ ORCHESTRATED WORKFLOW FAILED[/bold red]")
|
|
278
|
+
console.print("\n[bold red]❌ ORCHESTRATED WORKFLOW FAILED[/ bold red]")
|
|
261
279
|
sys.exit(1)
|
|
262
280
|
except KeyboardInterrupt:
|
|
263
|
-
console.print("\n[yellow]🛑 Orchestrated workflow interrupted[/yellow]")
|
|
281
|
+
console.print("\n[yellow]🛑 Orchestrated workflow interrupted[/ yellow]")
|
|
264
282
|
sys.exit(130)
|
|
265
283
|
except Exception as e:
|
|
266
|
-
console.print(f"\n[red]💥 Orchestrated workflow error: {e}[/red]")
|
|
284
|
+
console.print(f"\n[red]💥 Orchestrated workflow error: {e}[/ red]")
|
|
267
285
|
sys.exit(1)
|
crackerjack/cli/interactive.py
CHANGED
|
@@ -115,7 +115,7 @@ class InteractiveWorkflowManager:
|
|
|
115
115
|
deps = ["cleaning"] if options.clean else []
|
|
116
116
|
self.add_task(
|
|
117
117
|
"hooks",
|
|
118
|
-
"Run pre
|
|
118
|
+
"Run pre-commit hooks (fast + comprehensive)",
|
|
119
119
|
"run_hooks_phase",
|
|
120
120
|
dependencies=deps,
|
|
121
121
|
)
|
|
@@ -284,7 +284,7 @@ class InteractiveWorkflowManager:
|
|
|
284
284
|
self.setup_workflow(options)
|
|
285
285
|
if not self.tasks:
|
|
286
286
|
self.console.print(
|
|
287
|
-
"[yellow]⚠️ No tasks to execute based on options[/yellow]",
|
|
287
|
+
"[yellow]⚠️ No tasks to execute based on options[/ yellow]",
|
|
288
288
|
)
|
|
289
289
|
return True
|
|
290
290
|
|
|
@@ -292,7 +292,7 @@ class InteractiveWorkflowManager:
|
|
|
292
292
|
self.console.print(self.layout)
|
|
293
293
|
|
|
294
294
|
if not Confirm.ask("\n🚀 Start workflow?", default=True):
|
|
295
|
-
self.console.print("[yellow]⏹️ Workflow cancelled[/yellow]")
|
|
295
|
+
self.console.print("[yellow]⏹️ Workflow cancelled[/ yellow]")
|
|
296
296
|
return False
|
|
297
297
|
|
|
298
298
|
return True
|
|
@@ -328,7 +328,7 @@ class InteractiveWorkflowManager:
|
|
|
328
328
|
)
|
|
329
329
|
|
|
330
330
|
if not retry:
|
|
331
|
-
self.console.print("[red]⏹️ Workflow stopped due to task failure[/red]")
|
|
331
|
+
self.console.print("[red]⏹️ Workflow stopped due to task failure[/ red]")
|
|
332
332
|
return False
|
|
333
333
|
|
|
334
334
|
failed_task.skip()
|
|
@@ -373,7 +373,7 @@ class InteractiveWorkflowManager:
|
|
|
373
373
|
}
|
|
374
374
|
status_text = task.status.name
|
|
375
375
|
style = status_styles.get(task.status, "white")
|
|
376
|
-
duration_text = f"{task.duration: .1f}s" if task.duration else "
|
|
376
|
+
duration_text = f"{task.duration: .1f}s" if task.duration else "-"
|
|
377
377
|
details = task.error.message if task.error else task.description
|
|
378
378
|
table.add_row(
|
|
379
379
|
task.name,
|
|
@@ -385,11 +385,11 @@ class InteractiveWorkflowManager:
|
|
|
385
385
|
self.console.print(table)
|
|
386
386
|
if failed_count == 0:
|
|
387
387
|
self.console.print(
|
|
388
|
-
f"\n[bold green]🎉 Workflow completed ! {success_count} / {len(self.tasks)} tasks successful[/bold green]",
|
|
388
|
+
f"\n[bold green]🎉 Workflow completed ! {success_count} / {len(self.tasks)} tasks successful[/ bold green]",
|
|
389
389
|
)
|
|
390
390
|
else:
|
|
391
391
|
self.console.print(
|
|
392
|
-
f"\n[bold yellow]⚠️ Workflow completed with issues: {failed_count} failed, {skipped_count} skipped[/bold yellow]",
|
|
392
|
+
f"\n[bold yellow]⚠️ Workflow completed with issues: {failed_count} failed, {skipped_count} skipped[/ bold yellow]",
|
|
393
393
|
)
|
|
394
394
|
|
|
395
395
|
|
|
@@ -414,7 +414,7 @@ class InteractiveCLI:
|
|
|
414
414
|
if not success:
|
|
415
415
|
raise SystemExit(1)
|
|
416
416
|
except KeyboardInterrupt:
|
|
417
|
-
self.console.print("\n[yellow]⏹️ Interactive session cancelled[/yellow]")
|
|
417
|
+
self.console.print("\n[yellow]⏹️ Interactive session cancelled[/ yellow]")
|
|
418
418
|
raise SystemExit(130)
|
|
419
419
|
except Exception as e:
|
|
420
420
|
error = CrackerjackError(
|
|
@@ -426,10 +426,10 @@ class InteractiveCLI:
|
|
|
426
426
|
|
|
427
427
|
def _show_welcome(self) -> None:
|
|
428
428
|
welcome_panel = Panel(
|
|
429
|
-
f"[bold cyan]Welcome to Crackerjack Interactive Mode ! [/bold cyan]\n\n"
|
|
429
|
+
f"[bold cyan]Welcome to Crackerjack Interactive Mode ! [/ bold cyan]\n\n"
|
|
430
430
|
f"Version: {self.pkg_version}\n"
|
|
431
431
|
f"This interactive interface will guide you through the crackerjack workflow\n"
|
|
432
|
-
f"with real
|
|
432
|
+
f"with real-time feedback and customizable options.",
|
|
433
433
|
title="🚀 Crackerjack Interactive",
|
|
434
434
|
border_style="cyan",
|
|
435
435
|
)
|
|
@@ -437,7 +437,7 @@ class InteractiveCLI:
|
|
|
437
437
|
self.console.print()
|
|
438
438
|
|
|
439
439
|
def _get_user_preferences(self, options: OptionsProtocol) -> OptionsProtocol:
|
|
440
|
-
self.console.print("[bold]🔧 Workflow Configuration[/bold]")
|
|
440
|
+
self.console.print("[bold]🔧 Workflow Configuration[/ bold]")
|
|
441
441
|
self.console.print("Configure your crackerjack workflow: \n")
|
|
442
442
|
updated_options = type(options)(**vars(options))
|
|
443
443
|
updated_options.clean = Confirm.ask(
|
crackerjack/cli/options.py
CHANGED
|
@@ -23,6 +23,7 @@ class Options(BaseModel):
|
|
|
23
23
|
publish: BumpOption | None = None
|
|
24
24
|
bump: BumpOption | None = None
|
|
25
25
|
verbose: bool = False
|
|
26
|
+
debug: bool = False
|
|
26
27
|
clean: bool = False
|
|
27
28
|
test: bool = False
|
|
28
29
|
benchmark: bool = False
|
|
@@ -62,12 +63,28 @@ class Options(BaseModel):
|
|
|
62
63
|
websocket_port: int | None = None
|
|
63
64
|
dev: bool = False
|
|
64
65
|
dashboard: bool = False
|
|
65
|
-
max_iterations: int =
|
|
66
|
+
max_iterations: int = 5
|
|
66
67
|
enterprise_batch: str | None = None
|
|
67
68
|
monitor_dashboard: str | None = None
|
|
68
69
|
coverage_status: bool = False
|
|
69
70
|
coverage_goal: float | None = None
|
|
70
71
|
no_coverage_ratchet: bool = False
|
|
72
|
+
skip_config_merge: bool = False
|
|
73
|
+
disable_global_locks: bool = False
|
|
74
|
+
global_lock_timeout: int = 600
|
|
75
|
+
global_lock_cleanup: bool = True
|
|
76
|
+
global_lock_dir: str | None = None
|
|
77
|
+
quick: bool = False
|
|
78
|
+
thorough: bool = False
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def effective_max_iterations(self) -> int:
|
|
82
|
+
"""Get the effective max iterations based on quick/thorough flags."""
|
|
83
|
+
if self.quick:
|
|
84
|
+
return 3 # Quick mode: 3 iterations for CI/CD
|
|
85
|
+
if self.thorough:
|
|
86
|
+
return 8 # Thorough mode: 8 iterations for complex refactoring
|
|
87
|
+
return self.max_iterations # Default: 5 iterations
|
|
71
88
|
|
|
72
89
|
@classmethod
|
|
73
90
|
@field_validator("publish", "bump", mode="before")
|
|
@@ -112,6 +129,7 @@ CLI_OPTIONS = {
|
|
|
112
129
|
help="Update pre-commit hooks configuration.",
|
|
113
130
|
),
|
|
114
131
|
"verbose": typer.Option(False, "-v", "--verbose", help="Enable verbose output."),
|
|
132
|
+
"debug": typer.Option(False, "--debug", help="Enable debug output."),
|
|
115
133
|
"publish": typer.Option(
|
|
116
134
|
None,
|
|
117
135
|
"-p",
|
|
@@ -130,7 +148,7 @@ CLI_OPTIONS = {
|
|
|
130
148
|
False,
|
|
131
149
|
"-x",
|
|
132
150
|
"--clean",
|
|
133
|
-
help="Remove docstrings, line comments, and unnecessary whitespace from source code (doesn't affect test files).",
|
|
151
|
+
help="Remove docstrings, line comments, and unnecessary whitespace from source code with automatic backup protection (doesn't affect test files).",
|
|
134
152
|
),
|
|
135
153
|
"test": typer.Option(False, "-t", "--test", help="Run tests."),
|
|
136
154
|
"benchmark": typer.Option(
|
|
@@ -275,9 +293,9 @@ CLI_OPTIONS = {
|
|
|
275
293
|
help="Start the comprehensive dashboard with system metrics, job tracking, and performance monitoring.",
|
|
276
294
|
),
|
|
277
295
|
"max_iterations": typer.Option(
|
|
278
|
-
|
|
296
|
+
5,
|
|
279
297
|
"--max-iterations",
|
|
280
|
-
help="Maximum number of iterations for AI agent auto-fixing workflows (default:
|
|
298
|
+
help="Maximum number of iterations for AI agent auto-fixing workflows (default: 5).",
|
|
281
299
|
),
|
|
282
300
|
"ai_debug": typer.Option(
|
|
283
301
|
False,
|
|
@@ -330,6 +348,36 @@ CLI_OPTIONS = {
|
|
|
330
348
|
"--boost-coverage/--no-boost-coverage",
|
|
331
349
|
help="Automatically improve test coverage after successful workflow execution (default: True).",
|
|
332
350
|
),
|
|
351
|
+
"disable_global_locks": typer.Option(
|
|
352
|
+
False,
|
|
353
|
+
"--disable-global-locks",
|
|
354
|
+
help="Disable global locking (allow concurrent hook execution across sessions).",
|
|
355
|
+
),
|
|
356
|
+
"global_lock_timeout": typer.Option(
|
|
357
|
+
600,
|
|
358
|
+
"--global-lock-timeout",
|
|
359
|
+
help="Global lock timeout in seconds (default: 600).",
|
|
360
|
+
),
|
|
361
|
+
"global_lock_cleanup": typer.Option(
|
|
362
|
+
True,
|
|
363
|
+
"--cleanup-stale-locks/--no-cleanup-stale-locks",
|
|
364
|
+
help="Clean up stale global lock files before execution (default: True).",
|
|
365
|
+
),
|
|
366
|
+
"global_lock_dir": typer.Option(
|
|
367
|
+
None,
|
|
368
|
+
"--global-lock-dir",
|
|
369
|
+
help="Custom directory for global lock files (default: ~/.crackerjack/locks).",
|
|
370
|
+
),
|
|
371
|
+
"quick": typer.Option(
|
|
372
|
+
False,
|
|
373
|
+
"--quick",
|
|
374
|
+
help="Quick mode: Run with maximum 3 iterations (ideal for CI/CD).",
|
|
375
|
+
),
|
|
376
|
+
"thorough": typer.Option(
|
|
377
|
+
False,
|
|
378
|
+
"--thorough",
|
|
379
|
+
help="Thorough mode: Run with maximum 8 iterations (for complex refactoring).",
|
|
380
|
+
),
|
|
333
381
|
}
|
|
334
382
|
|
|
335
383
|
|
|
@@ -339,6 +387,7 @@ def create_options(
|
|
|
339
387
|
no_config_updates: bool,
|
|
340
388
|
update_precommit: bool,
|
|
341
389
|
verbose: bool,
|
|
390
|
+
debug: bool,
|
|
342
391
|
publish: BumpOption | None,
|
|
343
392
|
all: BumpOption | None,
|
|
344
393
|
bump: BumpOption | None,
|
|
@@ -369,6 +418,12 @@ def create_options(
|
|
|
369
418
|
coverage_goal: float | None,
|
|
370
419
|
no_coverage_ratchet: bool,
|
|
371
420
|
boost_coverage: bool,
|
|
421
|
+
disable_global_locks: bool,
|
|
422
|
+
global_lock_timeout: int,
|
|
423
|
+
global_lock_cleanup: bool,
|
|
424
|
+
global_lock_dir: str | None,
|
|
425
|
+
quick: bool,
|
|
426
|
+
thorough: bool,
|
|
372
427
|
) -> Options:
|
|
373
428
|
return Options(
|
|
374
429
|
commit=commit,
|
|
@@ -376,6 +431,7 @@ def create_options(
|
|
|
376
431
|
no_config_updates=no_config_updates,
|
|
377
432
|
update_precommit=update_precommit,
|
|
378
433
|
verbose=verbose,
|
|
434
|
+
debug=debug,
|
|
379
435
|
publish=publish,
|
|
380
436
|
bump=bump,
|
|
381
437
|
clean=clean,
|
|
@@ -406,4 +462,10 @@ def create_options(
|
|
|
406
462
|
coverage_goal=coverage_goal,
|
|
407
463
|
no_coverage_ratchet=no_coverage_ratchet,
|
|
408
464
|
boost_coverage=boost_coverage,
|
|
465
|
+
disable_global_locks=disable_global_locks,
|
|
466
|
+
global_lock_timeout=global_lock_timeout,
|
|
467
|
+
global_lock_cleanup=global_lock_cleanup,
|
|
468
|
+
global_lock_dir=global_lock_dir,
|
|
469
|
+
quick=quick,
|
|
470
|
+
thorough=thorough,
|
|
409
471
|
)
|