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.

Files changed (155) hide show
  1. crackerjack/CLAUDE.md +288 -705
  2. crackerjack/__main__.py +22 -8
  3. crackerjack/agents/__init__.py +0 -3
  4. crackerjack/agents/architect_agent.py +0 -43
  5. crackerjack/agents/base.py +1 -9
  6. crackerjack/agents/coordinator.py +2 -148
  7. crackerjack/agents/documentation_agent.py +109 -81
  8. crackerjack/agents/dry_agent.py +122 -97
  9. crackerjack/agents/formatting_agent.py +3 -16
  10. crackerjack/agents/import_optimization_agent.py +1174 -130
  11. crackerjack/agents/performance_agent.py +956 -188
  12. crackerjack/agents/performance_helpers.py +229 -0
  13. crackerjack/agents/proactive_agent.py +1 -48
  14. crackerjack/agents/refactoring_agent.py +516 -246
  15. crackerjack/agents/refactoring_helpers.py +282 -0
  16. crackerjack/agents/security_agent.py +393 -90
  17. crackerjack/agents/test_creation_agent.py +1776 -120
  18. crackerjack/agents/test_specialist_agent.py +59 -15
  19. crackerjack/agents/tracker.py +0 -102
  20. crackerjack/api.py +145 -37
  21. crackerjack/cli/handlers.py +48 -30
  22. crackerjack/cli/interactive.py +11 -11
  23. crackerjack/cli/options.py +66 -4
  24. crackerjack/code_cleaner.py +808 -148
  25. crackerjack/config/global_lock_config.py +110 -0
  26. crackerjack/config/hooks.py +43 -64
  27. crackerjack/core/async_workflow_orchestrator.py +247 -97
  28. crackerjack/core/autofix_coordinator.py +192 -109
  29. crackerjack/core/enhanced_container.py +46 -63
  30. crackerjack/core/file_lifecycle.py +549 -0
  31. crackerjack/core/performance.py +9 -8
  32. crackerjack/core/performance_monitor.py +395 -0
  33. crackerjack/core/phase_coordinator.py +281 -94
  34. crackerjack/core/proactive_workflow.py +9 -58
  35. crackerjack/core/resource_manager.py +501 -0
  36. crackerjack/core/service_watchdog.py +490 -0
  37. crackerjack/core/session_coordinator.py +4 -8
  38. crackerjack/core/timeout_manager.py +504 -0
  39. crackerjack/core/websocket_lifecycle.py +475 -0
  40. crackerjack/core/workflow_orchestrator.py +343 -209
  41. crackerjack/dynamic_config.py +47 -6
  42. crackerjack/errors.py +3 -4
  43. crackerjack/executors/async_hook_executor.py +63 -13
  44. crackerjack/executors/cached_hook_executor.py +14 -14
  45. crackerjack/executors/hook_executor.py +100 -37
  46. crackerjack/executors/hook_lock_manager.py +856 -0
  47. crackerjack/executors/individual_hook_executor.py +120 -86
  48. crackerjack/intelligence/__init__.py +0 -7
  49. crackerjack/intelligence/adaptive_learning.py +13 -86
  50. crackerjack/intelligence/agent_orchestrator.py +15 -78
  51. crackerjack/intelligence/agent_registry.py +12 -59
  52. crackerjack/intelligence/agent_selector.py +31 -92
  53. crackerjack/intelligence/integration.py +1 -41
  54. crackerjack/interactive.py +9 -9
  55. crackerjack/managers/async_hook_manager.py +25 -8
  56. crackerjack/managers/hook_manager.py +9 -9
  57. crackerjack/managers/publish_manager.py +57 -59
  58. crackerjack/managers/test_command_builder.py +6 -36
  59. crackerjack/managers/test_executor.py +9 -61
  60. crackerjack/managers/test_manager.py +17 -63
  61. crackerjack/managers/test_manager_backup.py +77 -127
  62. crackerjack/managers/test_progress.py +4 -23
  63. crackerjack/mcp/cache.py +5 -12
  64. crackerjack/mcp/client_runner.py +10 -10
  65. crackerjack/mcp/context.py +64 -6
  66. crackerjack/mcp/dashboard.py +14 -11
  67. crackerjack/mcp/enhanced_progress_monitor.py +55 -55
  68. crackerjack/mcp/file_monitor.py +72 -42
  69. crackerjack/mcp/progress_components.py +103 -84
  70. crackerjack/mcp/progress_monitor.py +122 -49
  71. crackerjack/mcp/rate_limiter.py +12 -12
  72. crackerjack/mcp/server_core.py +16 -22
  73. crackerjack/mcp/service_watchdog.py +26 -26
  74. crackerjack/mcp/state.py +15 -0
  75. crackerjack/mcp/tools/core_tools.py +95 -39
  76. crackerjack/mcp/tools/error_analyzer.py +6 -32
  77. crackerjack/mcp/tools/execution_tools.py +1 -56
  78. crackerjack/mcp/tools/execution_tools_backup.py +35 -131
  79. crackerjack/mcp/tools/intelligence_tool_registry.py +0 -36
  80. crackerjack/mcp/tools/intelligence_tools.py +2 -55
  81. crackerjack/mcp/tools/monitoring_tools.py +308 -145
  82. crackerjack/mcp/tools/proactive_tools.py +12 -42
  83. crackerjack/mcp/tools/progress_tools.py +23 -15
  84. crackerjack/mcp/tools/utility_tools.py +3 -40
  85. crackerjack/mcp/tools/workflow_executor.py +40 -60
  86. crackerjack/mcp/websocket/app.py +0 -3
  87. crackerjack/mcp/websocket/endpoints.py +206 -268
  88. crackerjack/mcp/websocket/jobs.py +213 -66
  89. crackerjack/mcp/websocket/server.py +84 -6
  90. crackerjack/mcp/websocket/websocket_handler.py +137 -29
  91. crackerjack/models/config_adapter.py +3 -16
  92. crackerjack/models/protocols.py +162 -3
  93. crackerjack/models/resource_protocols.py +454 -0
  94. crackerjack/models/task.py +3 -3
  95. crackerjack/monitoring/__init__.py +0 -0
  96. crackerjack/monitoring/ai_agent_watchdog.py +25 -71
  97. crackerjack/monitoring/regression_prevention.py +28 -87
  98. crackerjack/orchestration/advanced_orchestrator.py +44 -78
  99. crackerjack/orchestration/coverage_improvement.py +10 -60
  100. crackerjack/orchestration/execution_strategies.py +16 -16
  101. crackerjack/orchestration/test_progress_streamer.py +61 -53
  102. crackerjack/plugins/base.py +1 -1
  103. crackerjack/plugins/managers.py +22 -20
  104. crackerjack/py313.py +65 -21
  105. crackerjack/services/backup_service.py +467 -0
  106. crackerjack/services/bounded_status_operations.py +627 -0
  107. crackerjack/services/cache.py +7 -9
  108. crackerjack/services/config.py +35 -52
  109. crackerjack/services/config_integrity.py +5 -16
  110. crackerjack/services/config_merge.py +542 -0
  111. crackerjack/services/contextual_ai_assistant.py +17 -19
  112. crackerjack/services/coverage_ratchet.py +44 -73
  113. crackerjack/services/debug.py +25 -39
  114. crackerjack/services/dependency_monitor.py +52 -50
  115. crackerjack/services/enhanced_filesystem.py +14 -11
  116. crackerjack/services/file_hasher.py +1 -1
  117. crackerjack/services/filesystem.py +1 -12
  118. crackerjack/services/git.py +71 -47
  119. crackerjack/services/health_metrics.py +31 -27
  120. crackerjack/services/initialization.py +276 -428
  121. crackerjack/services/input_validator.py +760 -0
  122. crackerjack/services/log_manager.py +16 -16
  123. crackerjack/services/logging.py +7 -6
  124. crackerjack/services/metrics.py +43 -43
  125. crackerjack/services/pattern_cache.py +2 -31
  126. crackerjack/services/pattern_detector.py +26 -63
  127. crackerjack/services/performance_benchmarks.py +20 -45
  128. crackerjack/services/regex_patterns.py +2887 -0
  129. crackerjack/services/regex_utils.py +537 -0
  130. crackerjack/services/secure_path_utils.py +683 -0
  131. crackerjack/services/secure_status_formatter.py +534 -0
  132. crackerjack/services/secure_subprocess.py +605 -0
  133. crackerjack/services/security.py +47 -10
  134. crackerjack/services/security_logger.py +492 -0
  135. crackerjack/services/server_manager.py +109 -50
  136. crackerjack/services/smart_scheduling.py +8 -25
  137. crackerjack/services/status_authentication.py +603 -0
  138. crackerjack/services/status_security_manager.py +442 -0
  139. crackerjack/services/thread_safe_status_collector.py +546 -0
  140. crackerjack/services/tool_version_service.py +1 -23
  141. crackerjack/services/unified_config.py +36 -58
  142. crackerjack/services/validation_rate_limiter.py +269 -0
  143. crackerjack/services/version_checker.py +9 -40
  144. crackerjack/services/websocket_resource_limiter.py +572 -0
  145. crackerjack/slash_commands/__init__.py +52 -2
  146. crackerjack/tools/__init__.py +0 -0
  147. crackerjack/tools/validate_input_validator_patterns.py +262 -0
  148. crackerjack/tools/validate_regex_patterns.py +198 -0
  149. {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/METADATA +197 -12
  150. crackerjack-0.31.12.dist-info/RECORD +178 -0
  151. crackerjack/cli/facade.py +0 -104
  152. crackerjack-0.31.10.dist-info/RECORD +0 -149
  153. {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/WHEEL +0 -0
  154. {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/entry_points.txt +0 -0
  155. {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
@@ -26,7 +26,21 @@ class HookDefinition:
26
26
  config_path: Path | None = None
27
27
 
28
28
  def get_command(self) -> list[str]:
29
- cmd = ["pre-commit", "run"]
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=["pre-commit", "run", "trailing-whitespace", "--all-files"],
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=["pre-commit", "run", "end-of-file-fixer", "--all-files"],
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=["pre-commit", "run", "check-yaml", "--all-files"],
84
+ command=[], # Dynamically built by get_command()
64
85
  ),
65
86
  HookDefinition(
66
87
  name="check-toml",
67
- command=["pre-commit", "run", "check-toml", "--all-files"],
88
+ command=[], # Dynamically built by get_command()
68
89
  ),
69
90
  HookDefinition(
70
91
  name="check-added-large-files",
71
- command=["pre-commit", "run", "check-added-large-files", "--all-files"],
92
+ command=[], # Dynamically built by get_command()
72
93
  ),
73
94
  HookDefinition(
74
95
  name="uv-lock",
75
- command=["pre-commit", "run", "uv-lock", "--all-files"],
96
+ command=[], # Dynamically built by get_command()
76
97
  ),
77
98
  HookDefinition(
78
99
  name="gitleaks",
79
- command=["pre-commit", "run", "gitleaks", "--all-files"],
100
+ command=[], # Dynamically built by get_command()
80
101
  ),
81
102
  HookDefinition(
82
103
  name="codespell",
83
- command=["pre-commit", "run", "codespell", "--all-files"],
104
+ command=[], # Dynamically built by get_command()
84
105
  ),
85
106
  HookDefinition(
86
107
  name="ruff-check",
87
- command=["pre-commit", "run", "ruff-check", "--all-files"],
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=["pre-commit", "run", "ruff-format", "--all-files"],
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=["pre-commit", "run", "mdformat", "--all-files"],
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
- "pre-commit",
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
- @staticmethod
217
- def get_all_strategies() -> dict[str, HookStrategy]:
218
- return {"fast": FAST_STRATEGY, "comprehensive": COMPREHENSIVE_STRATEGY}
197
+ # Removed unused method: get_all_strategies