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,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)