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.

Files changed (158) hide show
  1. crackerjack/CLAUDE.md +1005 -0
  2. crackerjack/RULES.md +380 -0
  3. crackerjack/__init__.py +42 -13
  4. crackerjack/__main__.py +225 -253
  5. crackerjack/agents/__init__.py +41 -0
  6. crackerjack/agents/architect_agent.py +281 -0
  7. crackerjack/agents/base.py +169 -0
  8. crackerjack/agents/coordinator.py +512 -0
  9. crackerjack/agents/documentation_agent.py +498 -0
  10. crackerjack/agents/dry_agent.py +388 -0
  11. crackerjack/agents/formatting_agent.py +245 -0
  12. crackerjack/agents/import_optimization_agent.py +281 -0
  13. crackerjack/agents/performance_agent.py +669 -0
  14. crackerjack/agents/proactive_agent.py +104 -0
  15. crackerjack/agents/refactoring_agent.py +788 -0
  16. crackerjack/agents/security_agent.py +529 -0
  17. crackerjack/agents/test_creation_agent.py +652 -0
  18. crackerjack/agents/test_specialist_agent.py +486 -0
  19. crackerjack/agents/tracker.py +212 -0
  20. crackerjack/api.py +560 -0
  21. crackerjack/cli/__init__.py +24 -0
  22. crackerjack/cli/facade.py +104 -0
  23. crackerjack/cli/handlers.py +267 -0
  24. crackerjack/cli/interactive.py +471 -0
  25. crackerjack/cli/options.py +401 -0
  26. crackerjack/cli/utils.py +18 -0
  27. crackerjack/code_cleaner.py +670 -0
  28. crackerjack/config/__init__.py +19 -0
  29. crackerjack/config/hooks.py +218 -0
  30. crackerjack/core/__init__.py +0 -0
  31. crackerjack/core/async_workflow_orchestrator.py +406 -0
  32. crackerjack/core/autofix_coordinator.py +200 -0
  33. crackerjack/core/container.py +104 -0
  34. crackerjack/core/enhanced_container.py +542 -0
  35. crackerjack/core/performance.py +243 -0
  36. crackerjack/core/phase_coordinator.py +561 -0
  37. crackerjack/core/proactive_workflow.py +316 -0
  38. crackerjack/core/session_coordinator.py +289 -0
  39. crackerjack/core/workflow_orchestrator.py +640 -0
  40. crackerjack/dynamic_config.py +577 -0
  41. crackerjack/errors.py +263 -41
  42. crackerjack/executors/__init__.py +11 -0
  43. crackerjack/executors/async_hook_executor.py +431 -0
  44. crackerjack/executors/cached_hook_executor.py +242 -0
  45. crackerjack/executors/hook_executor.py +345 -0
  46. crackerjack/executors/individual_hook_executor.py +669 -0
  47. crackerjack/intelligence/__init__.py +44 -0
  48. crackerjack/intelligence/adaptive_learning.py +751 -0
  49. crackerjack/intelligence/agent_orchestrator.py +551 -0
  50. crackerjack/intelligence/agent_registry.py +414 -0
  51. crackerjack/intelligence/agent_selector.py +502 -0
  52. crackerjack/intelligence/integration.py +290 -0
  53. crackerjack/interactive.py +576 -315
  54. crackerjack/managers/__init__.py +11 -0
  55. crackerjack/managers/async_hook_manager.py +135 -0
  56. crackerjack/managers/hook_manager.py +137 -0
  57. crackerjack/managers/publish_manager.py +411 -0
  58. crackerjack/managers/test_command_builder.py +151 -0
  59. crackerjack/managers/test_executor.py +435 -0
  60. crackerjack/managers/test_manager.py +258 -0
  61. crackerjack/managers/test_manager_backup.py +1124 -0
  62. crackerjack/managers/test_progress.py +144 -0
  63. crackerjack/mcp/__init__.py +0 -0
  64. crackerjack/mcp/cache.py +336 -0
  65. crackerjack/mcp/client_runner.py +104 -0
  66. crackerjack/mcp/context.py +615 -0
  67. crackerjack/mcp/dashboard.py +636 -0
  68. crackerjack/mcp/enhanced_progress_monitor.py +479 -0
  69. crackerjack/mcp/file_monitor.py +336 -0
  70. crackerjack/mcp/progress_components.py +569 -0
  71. crackerjack/mcp/progress_monitor.py +949 -0
  72. crackerjack/mcp/rate_limiter.py +332 -0
  73. crackerjack/mcp/server.py +22 -0
  74. crackerjack/mcp/server_core.py +244 -0
  75. crackerjack/mcp/service_watchdog.py +501 -0
  76. crackerjack/mcp/state.py +395 -0
  77. crackerjack/mcp/task_manager.py +257 -0
  78. crackerjack/mcp/tools/__init__.py +17 -0
  79. crackerjack/mcp/tools/core_tools.py +249 -0
  80. crackerjack/mcp/tools/error_analyzer.py +308 -0
  81. crackerjack/mcp/tools/execution_tools.py +370 -0
  82. crackerjack/mcp/tools/execution_tools_backup.py +1097 -0
  83. crackerjack/mcp/tools/intelligence_tool_registry.py +80 -0
  84. crackerjack/mcp/tools/intelligence_tools.py +314 -0
  85. crackerjack/mcp/tools/monitoring_tools.py +502 -0
  86. crackerjack/mcp/tools/proactive_tools.py +384 -0
  87. crackerjack/mcp/tools/progress_tools.py +141 -0
  88. crackerjack/mcp/tools/utility_tools.py +341 -0
  89. crackerjack/mcp/tools/workflow_executor.py +360 -0
  90. crackerjack/mcp/websocket/__init__.py +14 -0
  91. crackerjack/mcp/websocket/app.py +39 -0
  92. crackerjack/mcp/websocket/endpoints.py +559 -0
  93. crackerjack/mcp/websocket/jobs.py +253 -0
  94. crackerjack/mcp/websocket/server.py +116 -0
  95. crackerjack/mcp/websocket/websocket_handler.py +78 -0
  96. crackerjack/mcp/websocket_server.py +10 -0
  97. crackerjack/models/__init__.py +31 -0
  98. crackerjack/models/config.py +93 -0
  99. crackerjack/models/config_adapter.py +230 -0
  100. crackerjack/models/protocols.py +118 -0
  101. crackerjack/models/task.py +154 -0
  102. crackerjack/monitoring/ai_agent_watchdog.py +450 -0
  103. crackerjack/monitoring/regression_prevention.py +638 -0
  104. crackerjack/orchestration/__init__.py +0 -0
  105. crackerjack/orchestration/advanced_orchestrator.py +970 -0
  106. crackerjack/orchestration/execution_strategies.py +341 -0
  107. crackerjack/orchestration/test_progress_streamer.py +636 -0
  108. crackerjack/plugins/__init__.py +15 -0
  109. crackerjack/plugins/base.py +200 -0
  110. crackerjack/plugins/hooks.py +246 -0
  111. crackerjack/plugins/loader.py +335 -0
  112. crackerjack/plugins/managers.py +259 -0
  113. crackerjack/py313.py +8 -3
  114. crackerjack/services/__init__.py +22 -0
  115. crackerjack/services/cache.py +314 -0
  116. crackerjack/services/config.py +347 -0
  117. crackerjack/services/config_integrity.py +99 -0
  118. crackerjack/services/contextual_ai_assistant.py +516 -0
  119. crackerjack/services/coverage_ratchet.py +347 -0
  120. crackerjack/services/debug.py +736 -0
  121. crackerjack/services/dependency_monitor.py +617 -0
  122. crackerjack/services/enhanced_filesystem.py +439 -0
  123. crackerjack/services/file_hasher.py +151 -0
  124. crackerjack/services/filesystem.py +395 -0
  125. crackerjack/services/git.py +165 -0
  126. crackerjack/services/health_metrics.py +611 -0
  127. crackerjack/services/initialization.py +847 -0
  128. crackerjack/services/log_manager.py +286 -0
  129. crackerjack/services/logging.py +174 -0
  130. crackerjack/services/metrics.py +578 -0
  131. crackerjack/services/pattern_cache.py +362 -0
  132. crackerjack/services/pattern_detector.py +515 -0
  133. crackerjack/services/performance_benchmarks.py +653 -0
  134. crackerjack/services/security.py +163 -0
  135. crackerjack/services/server_manager.py +234 -0
  136. crackerjack/services/smart_scheduling.py +144 -0
  137. crackerjack/services/tool_version_service.py +61 -0
  138. crackerjack/services/unified_config.py +437 -0
  139. crackerjack/services/version_checker.py +248 -0
  140. crackerjack/slash_commands/__init__.py +14 -0
  141. crackerjack/slash_commands/init.md +122 -0
  142. crackerjack/slash_commands/run.md +163 -0
  143. crackerjack/slash_commands/status.md +127 -0
  144. crackerjack-0.31.4.dist-info/METADATA +742 -0
  145. crackerjack-0.31.4.dist-info/RECORD +148 -0
  146. crackerjack-0.31.4.dist-info/entry_points.txt +2 -0
  147. crackerjack/.gitignore +0 -34
  148. crackerjack/.libcst.codemod.yaml +0 -18
  149. crackerjack/.pdm.toml +0 -1
  150. crackerjack/.pre-commit-config-ai.yaml +0 -149
  151. crackerjack/.pre-commit-config-fast.yaml +0 -69
  152. crackerjack/.pre-commit-config.yaml +0 -114
  153. crackerjack/crackerjack.py +0 -4140
  154. crackerjack/pyproject.toml +0 -285
  155. crackerjack-0.29.0.dist-info/METADATA +0 -1289
  156. crackerjack-0.29.0.dist-info/RECORD +0 -17
  157. {crackerjack-0.29.0.dist-info โ†’ crackerjack-0.31.4.dist-info}/WHEEL +0 -0
  158. {crackerjack-0.29.0.dist-info โ†’ crackerjack-0.31.4.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,258 @@
1
+ """Refactored test manager with focused responsibilities.
2
+
3
+ This is the new modular test manager that delegates to specialized components:
4
+ - TestExecutor: Handles test execution and progress tracking
5
+ - TestCommandBuilder: Builds pytest commands with appropriate options
6
+ - TestProgress: Tracks and displays test progress
7
+ - CoverageRatchetService: Manages coverage requirements
8
+
9
+ REFACTORING NOTE: Original test_manager.py was 1133 lines with 60+ methods.
10
+ This refactored version is ~200 lines and delegates to focused modules.
11
+ """
12
+
13
+ import subprocess
14
+ import time
15
+ import typing as t
16
+ from pathlib import Path
17
+
18
+ from rich.console import Console
19
+
20
+ from crackerjack.models.protocols import OptionsProtocol
21
+ from crackerjack.services.coverage_ratchet import CoverageRatchetService
22
+
23
+ from .test_command_builder import TestCommandBuilder
24
+ from .test_executor import TestExecutor
25
+
26
+
27
+ class TestManager:
28
+ """Refactored test manager with modular architecture."""
29
+
30
+ def __init__(self, console: Console, pkg_path: Path) -> None:
31
+ self.console = console
32
+ self.pkg_path = pkg_path
33
+
34
+ # Initialize specialized components
35
+ self.executor = TestExecutor(console, pkg_path)
36
+ self.command_builder = TestCommandBuilder(pkg_path)
37
+ self.coverage_ratchet = CoverageRatchetService(pkg_path, console)
38
+
39
+ # State
40
+ self._last_test_failures: list[str] = []
41
+ self._progress_callback: t.Callable[[dict[str, t.Any]], None] | None = None
42
+ self.coverage_ratchet_enabled = True
43
+
44
+ def set_progress_callback(
45
+ self,
46
+ callback: t.Callable[[dict[str, t.Any]], None] | None,
47
+ ) -> None:
48
+ """Set callback for AI mode structured progress updates."""
49
+ self._progress_callback = callback
50
+
51
+ def set_coverage_ratchet_enabled(self, enabled: bool) -> None:
52
+ """Enable or disable the coverage ratchet system."""
53
+ self.coverage_ratchet_enabled = enabled
54
+ if enabled:
55
+ self.console.print(
56
+ "[cyan]๐Ÿ“Š[/cyan] Coverage ratchet enabled - targeting 100% coverage"
57
+ )
58
+ else:
59
+ self.console.print("[yellow]โš ๏ธ[/yellow] Coverage ratchet disabled")
60
+
61
+ def run_tests(self, options: OptionsProtocol) -> bool:
62
+ """Run tests with comprehensive progress tracking and coverage analysis."""
63
+ start_time = time.time()
64
+
65
+ try:
66
+ result = self._execute_test_workflow(options)
67
+ duration = time.time() - start_time
68
+
69
+ if result:
70
+ return self._handle_test_success(result.stdout, duration)
71
+ else:
72
+ return self._handle_test_failure(
73
+ result.stderr if result else "", duration
74
+ )
75
+
76
+ except Exception as e:
77
+ return self._handle_test_error(start_time, e)
78
+
79
+ def run_specific_tests(self, test_pattern: str) -> bool:
80
+ """Run tests matching a specific pattern."""
81
+ self.console.print(f"[cyan]๐Ÿงช[/cyan] Running tests matching: {test_pattern}")
82
+
83
+ cmd = self.command_builder.build_specific_test_command(test_pattern)
84
+ result = self.executor.execute_with_progress(cmd)
85
+
86
+ success = result.returncode == 0
87
+ if success:
88
+ self.console.print("[green]โœ…[/green] Specific tests passed")
89
+ else:
90
+ self.console.print("[red]โŒ[/red] Some specific tests failed")
91
+
92
+ return success
93
+
94
+ def validate_test_environment(self) -> bool:
95
+ """Validate test environment and configuration."""
96
+ if not self.has_tests():
97
+ self.console.print("[yellow]โš ๏ธ[/yellow] No tests found")
98
+ return False
99
+
100
+ # Test basic pytest collection
101
+ cmd = self.command_builder.build_validation_command()
102
+ result = subprocess.run(cmd, cwd=self.pkg_path, capture_output=True, text=True)
103
+
104
+ if result.returncode != 0:
105
+ self.console.print("[red]โŒ[/red] Test environment validation failed")
106
+ self.console.print(result.stderr)
107
+ return False
108
+
109
+ self.console.print("[green]โœ…[/green] Test environment validated")
110
+ return True
111
+
112
+ def get_coverage_ratchet_status(self) -> dict[str, t.Any]:
113
+ """Get comprehensive coverage ratchet status."""
114
+ return self.coverage_ratchet.get_status_report()
115
+
116
+ def get_test_stats(self) -> dict[str, t.Any]:
117
+ """Get comprehensive test execution statistics."""
118
+ return {
119
+ "has_tests": self.has_tests(),
120
+ "coverage_ratchet_enabled": self.coverage_ratchet_enabled,
121
+ "last_failures_count": len(self._last_test_failures),
122
+ }
123
+
124
+ def get_test_failures(self) -> list[str]:
125
+ """Get list of recent test failures."""
126
+ return self._last_test_failures.copy()
127
+
128
+ def get_test_command(self, options: OptionsProtocol) -> list[str]:
129
+ """Get the test command that would be executed."""
130
+ return self.command_builder.build_command(options)
131
+
132
+ def get_coverage_report(self) -> str | None:
133
+ """Get coverage report if available."""
134
+ try:
135
+ return self.coverage_ratchet.get_coverage_report()
136
+ except Exception:
137
+ return None
138
+
139
+ def has_tests(self) -> bool:
140
+ """Check if project has tests."""
141
+ test_directories = ["tests", "test"]
142
+ test_files = ["test_*.py", "*_test.py"]
143
+
144
+ for test_dir in test_directories:
145
+ test_path = self.pkg_path / test_dir
146
+ if test_path.exists() and test_path.is_dir():
147
+ for test_file_pattern in test_files:
148
+ if list(test_path.glob(f"**/{test_file_pattern}")):
149
+ return True
150
+
151
+ # Check for test files in root directory
152
+ for test_file_pattern in test_files:
153
+ if list(self.pkg_path.glob(test_file_pattern)):
154
+ return True
155
+
156
+ return False
157
+
158
+ # Private implementation methods
159
+
160
+ def _execute_test_workflow(
161
+ self, options: OptionsProtocol
162
+ ) -> subprocess.CompletedProcess[str]:
163
+ """Execute the complete test workflow."""
164
+ self._print_test_start_message(options)
165
+
166
+ cmd = self.command_builder.build_command(options)
167
+
168
+ if self._progress_callback:
169
+ return self.executor.execute_with_ai_progress(
170
+ cmd, self._progress_callback, self._get_timeout(options)
171
+ )
172
+ return self.executor.execute_with_progress(cmd, self._get_timeout(options))
173
+
174
+ def _print_test_start_message(self, options: OptionsProtocol) -> None:
175
+ """Print test execution start message."""
176
+ workers = self.command_builder.get_optimal_workers(options)
177
+ timeout = self.command_builder.get_test_timeout(options)
178
+
179
+ self.console.print(
180
+ f"[cyan]๐Ÿงช[/cyan] Running tests (workers: {workers}, timeout: {timeout}s)"
181
+ )
182
+
183
+ def _handle_test_success(self, output: str, duration: float) -> bool:
184
+ """Handle successful test execution."""
185
+ self.console.print(f"[green]โœ…[/green] Tests passed in {duration:.1f}s")
186
+
187
+ if self.coverage_ratchet_enabled:
188
+ return self._process_coverage_ratchet()
189
+
190
+ return True
191
+
192
+ def _handle_test_failure(self, output: str, duration: float) -> bool:
193
+ """Handle failed test execution."""
194
+ self.console.print(f"[red]โŒ[/red] Tests failed in {duration:.1f}s")
195
+
196
+ self._last_test_failures = self._extract_failure_lines(output)
197
+ return False
198
+
199
+ def _handle_test_error(self, start_time: float, error: Exception) -> bool:
200
+ """Handle test execution errors."""
201
+ duration = time.time() - start_time
202
+ self.console.print(
203
+ f"[red]๐Ÿ’ฅ[/red] Test execution error after {duration:.1f}s: {error}"
204
+ )
205
+ return False
206
+
207
+ def _process_coverage_ratchet(self) -> bool:
208
+ """Process coverage ratchet checks."""
209
+ if not self.coverage_ratchet_enabled:
210
+ return True
211
+
212
+ ratchet_result = self.coverage_ratchet.check_and_update_coverage()
213
+ return self._handle_ratchet_result(ratchet_result)
214
+
215
+ def _handle_ratchet_result(self, ratchet_result: dict[str, t.Any]) -> bool:
216
+ """Handle coverage ratchet results."""
217
+ if ratchet_result.get("success", False):
218
+ if ratchet_result.get("improved", False):
219
+ self._handle_coverage_improvement(ratchet_result)
220
+ return True
221
+ else:
222
+ self.console.print(
223
+ f"[red]๐Ÿ“‰[/red] Coverage regression: "
224
+ f"{ratchet_result.get('current_coverage', 0):.2f}% < "
225
+ f"{ratchet_result.get('previous_coverage', 0):.2f}%"
226
+ )
227
+ return False
228
+
229
+ def _handle_coverage_improvement(self, ratchet_result: dict[str, t.Any]) -> None:
230
+ """Handle coverage improvements."""
231
+ improvement = ratchet_result.get("improvement", 0)
232
+ current = ratchet_result.get("current_coverage", 0)
233
+
234
+ self.console.print(
235
+ f"[green]๐Ÿ“ˆ[/green] Coverage improved by {improvement:.2f}% "
236
+ f"to {current:.2f}%"
237
+ )
238
+
239
+ def _extract_failure_lines(self, output: str) -> list[str]:
240
+ """Extract failure information from test output."""
241
+ failures = []
242
+ lines = output.split("\n")
243
+
244
+ for line in lines:
245
+ if any(
246
+ keyword in line for keyword in ("FAILED", "ERROR", "AssertionError")
247
+ ):
248
+ failures.append(line.strip())
249
+
250
+ return failures[:10] # Limit to first 10 failures
251
+
252
+ def _get_timeout(self, options: OptionsProtocol) -> int:
253
+ """Get timeout for test execution."""
254
+ return self.command_builder.get_test_timeout(options)
255
+
256
+
257
+ # For backward compatibility, also export the old class name
258
+ TestManagementImpl = TestManager