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
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import socket
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from ..models.protocols import OptionsProtocol
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class GlobalLockConfig:
|
|
11
|
+
"""Configuration for global hook locking system."""
|
|
12
|
+
|
|
13
|
+
enabled: bool = True
|
|
14
|
+
timeout_seconds: float = 600.0 # 10 minutes default
|
|
15
|
+
stale_lock_hours: float = 2.0 # Clean locks older than 2 hours
|
|
16
|
+
lock_directory: Path = field(
|
|
17
|
+
default_factory=lambda: Path.home() / ".crackerjack" / "locks"
|
|
18
|
+
)
|
|
19
|
+
session_heartbeat_interval: float = 30.0 # Heartbeat every 30s
|
|
20
|
+
max_retry_attempts: int = 3
|
|
21
|
+
retry_delay_seconds: float = 5.0
|
|
22
|
+
enable_lock_monitoring: bool = True
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def from_options(cls, options: "OptionsProtocol") -> "GlobalLockConfig":
|
|
26
|
+
"""Create GlobalLockConfig from CLI options.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
options: Options object containing CLI arguments
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Configured GlobalLockConfig instance
|
|
33
|
+
"""
|
|
34
|
+
# Import here to avoid circular import
|
|
35
|
+
|
|
36
|
+
# Create config with custom values from options
|
|
37
|
+
enabled = not options.disable_global_locks
|
|
38
|
+
timeout_seconds = float(options.global_lock_timeout)
|
|
39
|
+
# Get default lock directory from field definition
|
|
40
|
+
default_lock_dir = Path.home() / ".crackerjack" / "locks"
|
|
41
|
+
lock_directory = (
|
|
42
|
+
Path(options.global_lock_dir)
|
|
43
|
+
if options.global_lock_dir
|
|
44
|
+
else default_lock_dir
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Create instance with all parameters so __post_init__ is called
|
|
48
|
+
config = cls(
|
|
49
|
+
enabled=enabled,
|
|
50
|
+
timeout_seconds=timeout_seconds,
|
|
51
|
+
lock_directory=lock_directory,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
return config
|
|
55
|
+
|
|
56
|
+
def __post_init__(self) -> None:
|
|
57
|
+
"""Ensure lock directory exists and has proper permissions."""
|
|
58
|
+
self.lock_directory.mkdir(parents=True, exist_ok=True)
|
|
59
|
+
# Set restrictive permissions (owner read/write only)
|
|
60
|
+
self.lock_directory.chmod(0o700)
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def hostname(self) -> str:
|
|
64
|
+
"""Get the current hostname for lock identification."""
|
|
65
|
+
return socket.gethostname()
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def session_id(self) -> str:
|
|
69
|
+
"""Get a unique session identifier."""
|
|
70
|
+
return f"{self.hostname}_{os.getpid()}"
|
|
71
|
+
|
|
72
|
+
def get_lock_path(self, hook_name: str) -> Path:
|
|
73
|
+
"""Get the lock file path for a specific hook.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
hook_name: Name of the hook
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Path to the lock file
|
|
80
|
+
"""
|
|
81
|
+
return self.lock_directory / f"{hook_name}.lock"
|
|
82
|
+
|
|
83
|
+
def get_heartbeat_path(self, hook_name: str) -> Path:
|
|
84
|
+
"""Get the heartbeat file path for a specific hook.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
hook_name: Name of the hook
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Path to the heartbeat file
|
|
91
|
+
"""
|
|
92
|
+
return self.lock_directory / f"{hook_name}.heartbeat"
|
|
93
|
+
|
|
94
|
+
def is_valid_lock_file(self, lock_path: Path) -> bool:
|
|
95
|
+
"""Check if a lock file is valid (not stale).
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
lock_path: Path to the lock file
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
True if the lock file is valid and not stale
|
|
102
|
+
"""
|
|
103
|
+
if not lock_path.exists():
|
|
104
|
+
return False
|
|
105
|
+
|
|
106
|
+
# Check if the lock file is older than stale_lock_hours
|
|
107
|
+
import time
|
|
108
|
+
|
|
109
|
+
file_age_hours = (time.time() - lock_path.stat().st_mtime) / 3600
|
|
110
|
+
return file_age_hours < self.stale_lock_hours
|
crackerjack/config/hooks.py
CHANGED
|
@@ -26,7 +26,21 @@ class HookDefinition:
|
|
|
26
26
|
config_path: Path | None = None
|
|
27
27
|
|
|
28
28
|
def get_command(self) -> list[str]:
|
|
29
|
-
|
|
29
|
+
# Use direct pre-commit execution (pre-commit manages its own environments)
|
|
30
|
+
import shutil
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
# Find pre-commit executable - prefer project venv, fallback to system
|
|
34
|
+
pre_commit_path = None
|
|
35
|
+
current_dir = Path.cwd()
|
|
36
|
+
project_pre_commit = current_dir / ".venv" / "bin" / "pre-commit"
|
|
37
|
+
if project_pre_commit.exists():
|
|
38
|
+
pre_commit_path = str(project_pre_commit)
|
|
39
|
+
else:
|
|
40
|
+
pre_commit_path = shutil.which("pre-commit") or "pre-commit"
|
|
41
|
+
|
|
42
|
+
# Build command for direct pre-commit execution
|
|
43
|
+
cmd = [pre_commit_path, "run"]
|
|
30
44
|
if self.config_path:
|
|
31
45
|
cmd.extend(["-c", str(self.config_path)])
|
|
32
46
|
if self.manual_stage:
|
|
@@ -46,55 +60,64 @@ class HookStrategy:
|
|
|
46
60
|
|
|
47
61
|
|
|
48
62
|
FAST_HOOKS = [
|
|
63
|
+
HookDefinition(
|
|
64
|
+
name="validate-regex-patterns",
|
|
65
|
+
command=[], # Dynamically built by get_command()
|
|
66
|
+
is_formatting=True, # Treat as formatting for autofix purposes
|
|
67
|
+
timeout=30,
|
|
68
|
+
retry_on_failure=True, # Enable retries for autofix
|
|
69
|
+
),
|
|
49
70
|
HookDefinition(
|
|
50
71
|
name="trailing-whitespace",
|
|
51
|
-
command=[
|
|
72
|
+
command=[], # Dynamically built by get_command()
|
|
52
73
|
is_formatting=True,
|
|
53
74
|
retry_on_failure=True,
|
|
54
75
|
),
|
|
55
76
|
HookDefinition(
|
|
56
77
|
name="end-of-file-fixer",
|
|
57
|
-
command=[
|
|
78
|
+
command=[], # Dynamically built by get_command()
|
|
58
79
|
is_formatting=True,
|
|
59
80
|
retry_on_failure=True,
|
|
60
81
|
),
|
|
61
82
|
HookDefinition(
|
|
62
83
|
name="check-yaml",
|
|
63
|
-
command=[
|
|
84
|
+
command=[], # Dynamically built by get_command()
|
|
64
85
|
),
|
|
65
86
|
HookDefinition(
|
|
66
87
|
name="check-toml",
|
|
67
|
-
command=[
|
|
88
|
+
command=[], # Dynamically built by get_command()
|
|
68
89
|
),
|
|
69
90
|
HookDefinition(
|
|
70
91
|
name="check-added-large-files",
|
|
71
|
-
command=[
|
|
92
|
+
command=[], # Dynamically built by get_command()
|
|
72
93
|
),
|
|
73
94
|
HookDefinition(
|
|
74
95
|
name="uv-lock",
|
|
75
|
-
command=[
|
|
96
|
+
command=[], # Dynamically built by get_command()
|
|
76
97
|
),
|
|
77
98
|
HookDefinition(
|
|
78
99
|
name="gitleaks",
|
|
79
|
-
command=[
|
|
100
|
+
command=[], # Dynamically built by get_command()
|
|
80
101
|
),
|
|
81
102
|
HookDefinition(
|
|
82
103
|
name="codespell",
|
|
83
|
-
command=[
|
|
104
|
+
command=[], # Dynamically built by get_command()
|
|
84
105
|
),
|
|
85
106
|
HookDefinition(
|
|
86
107
|
name="ruff-check",
|
|
87
|
-
command=[
|
|
108
|
+
command=[], # Dynamically built by get_command()
|
|
109
|
+
is_formatting=True, # Treat as formatting for autofix purposes
|
|
110
|
+
retry_on_failure=True, # Enable retries for autofix
|
|
88
111
|
),
|
|
89
112
|
HookDefinition(
|
|
90
113
|
name="ruff-format",
|
|
91
|
-
command=[
|
|
114
|
+
command=[], # Dynamically built by get_command()
|
|
92
115
|
is_formatting=True,
|
|
93
116
|
retry_on_failure=True,
|
|
94
117
|
),
|
|
95
118
|
HookDefinition(
|
|
96
119
|
name="mdformat",
|
|
97
|
-
command=[
|
|
120
|
+
command=[], # Dynamically built by get_command()
|
|
98
121
|
is_formatting=True,
|
|
99
122
|
retry_on_failure=True,
|
|
100
123
|
),
|
|
@@ -103,85 +126,43 @@ FAST_HOOKS = [
|
|
|
103
126
|
COMPREHENSIVE_HOOKS = [
|
|
104
127
|
HookDefinition(
|
|
105
128
|
name="pyright",
|
|
106
|
-
command=[
|
|
107
|
-
"pre-commit",
|
|
108
|
-
"run",
|
|
109
|
-
"--hook-stage",
|
|
110
|
-
"manual",
|
|
111
|
-
"pyright",
|
|
112
|
-
"--all-files",
|
|
113
|
-
],
|
|
129
|
+
command=[], # Dynamically built by get_command()
|
|
114
130
|
timeout=120,
|
|
115
131
|
stage=HookStage.COMPREHENSIVE,
|
|
116
132
|
manual_stage=True,
|
|
117
133
|
),
|
|
118
134
|
HookDefinition(
|
|
119
135
|
name="bandit",
|
|
120
|
-
command=[
|
|
121
|
-
"pre-commit",
|
|
122
|
-
"run",
|
|
123
|
-
"--hook-stage",
|
|
124
|
-
"manual",
|
|
125
|
-
"bandit",
|
|
126
|
-
"--all-files",
|
|
127
|
-
],
|
|
136
|
+
command=[], # Dynamically built by get_command()
|
|
128
137
|
timeout=120,
|
|
129
138
|
stage=HookStage.COMPREHENSIVE,
|
|
130
139
|
manual_stage=True,
|
|
131
140
|
),
|
|
132
141
|
HookDefinition(
|
|
133
142
|
name="vulture",
|
|
134
|
-
command=[
|
|
135
|
-
"pre-commit",
|
|
136
|
-
"run",
|
|
137
|
-
"--hook-stage",
|
|
138
|
-
"manual",
|
|
139
|
-
"vulture",
|
|
140
|
-
"--all-files",
|
|
141
|
-
],
|
|
143
|
+
command=[], # Dynamically built by get_command()
|
|
142
144
|
timeout=120,
|
|
143
145
|
stage=HookStage.COMPREHENSIVE,
|
|
144
146
|
manual_stage=True,
|
|
145
147
|
),
|
|
146
148
|
HookDefinition(
|
|
147
149
|
name="refurb",
|
|
148
|
-
command=[
|
|
149
|
-
"pre-commit",
|
|
150
|
-
"run",
|
|
151
|
-
"--hook-stage",
|
|
152
|
-
"manual",
|
|
153
|
-
"refurb",
|
|
154
|
-
"--all-files",
|
|
155
|
-
],
|
|
150
|
+
command=[], # Dynamically built by get_command()
|
|
156
151
|
timeout=120,
|
|
157
152
|
stage=HookStage.COMPREHENSIVE,
|
|
158
153
|
manual_stage=True,
|
|
159
154
|
),
|
|
160
155
|
HookDefinition(
|
|
161
156
|
name="creosote",
|
|
162
|
-
command=[
|
|
163
|
-
"pre-commit",
|
|
164
|
-
"run",
|
|
165
|
-
"--hook-stage",
|
|
166
|
-
"manual",
|
|
167
|
-
"creosote",
|
|
168
|
-
"--all-files",
|
|
169
|
-
],
|
|
157
|
+
command=[], # Dynamically built by get_command()
|
|
170
158
|
timeout=120,
|
|
171
159
|
stage=HookStage.COMPREHENSIVE,
|
|
172
160
|
manual_stage=True,
|
|
173
161
|
),
|
|
174
162
|
HookDefinition(
|
|
175
163
|
name="complexipy",
|
|
176
|
-
command=[
|
|
177
|
-
|
|
178
|
-
"run",
|
|
179
|
-
"--hook-stage",
|
|
180
|
-
"manual",
|
|
181
|
-
"complexipy",
|
|
182
|
-
"--all-files",
|
|
183
|
-
],
|
|
184
|
-
timeout=120,
|
|
164
|
+
command=[], # Dynamically built by get_command()
|
|
165
|
+
timeout=60,
|
|
185
166
|
stage=HookStage.COMPREHENSIVE,
|
|
186
167
|
manual_stage=True,
|
|
187
168
|
),
|
|
@@ -213,6 +194,4 @@ class HookConfigLoader:
|
|
|
213
194
|
msg = f"Unknown hook strategy: {name}"
|
|
214
195
|
raise ValueError(msg)
|
|
215
196
|
|
|
216
|
-
|
|
217
|
-
def get_all_strategies() -> dict[str, HookStrategy]:
|
|
218
|
-
return {"fast": FAST_STRATEGY, "comprehensive": COMPREHENSIVE_STRATEGY}
|
|
197
|
+
# Removed unused method: get_all_strategies
|