crackerjack 0.31.10__py3-none-any.whl → 0.31.13__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 +50 -9
  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.13.dist-info}/METADATA +197 -12
  150. crackerjack-0.31.13.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.13.dist-info}/WHEEL +0 -0
  154. {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/entry_points.txt +0 -0
  155. {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,282 @@
1
+ """Refactoring analysis helper classes and utilities."""
2
+
3
+ import ast
4
+ import typing as t
5
+
6
+
7
+ class ComplexityCalculator(ast.NodeVisitor):
8
+ """Calculator for cognitive complexity analysis."""
9
+
10
+ def __init__(self) -> None:
11
+ self.complexity = 0
12
+ self.nesting_level = 0
13
+ self.binary_sequences = 0
14
+
15
+ def visit_If(self, node: ast.If) -> None:
16
+ self._process_conditional_node(node)
17
+
18
+ def visit_For(self, node: ast.For) -> None:
19
+ self._process_loop_node(node)
20
+
21
+ def visit_While(self, node: ast.While) -> None:
22
+ self._process_loop_node(node)
23
+
24
+ def visit_Try(self, node: ast.Try) -> None:
25
+ self._process_try_node(node)
26
+
27
+ def visit_With(self, node: ast.With) -> None:
28
+ self._process_context_node(node)
29
+
30
+ def visit_BoolOp(self, node: ast.BoolOp) -> None:
31
+ self._process_boolean_operation(node)
32
+
33
+ def visit_ListComp(self, node: ast.ListComp) -> None:
34
+ self._process_comprehension(node)
35
+
36
+ def visit_DictComp(self, node: ast.DictComp) -> None:
37
+ self._process_comprehension(node)
38
+
39
+ def visit_SetComp(self, node: ast.SetComp) -> None:
40
+ self._process_comprehension(node)
41
+
42
+ def visit_GeneratorExp(self, node: ast.GeneratorExp) -> None:
43
+ self._process_comprehension(node)
44
+
45
+ def _process_conditional_node(self, node: ast.If) -> None:
46
+ """Process if/elif nodes with condition complexity."""
47
+ # Base complexity + nesting penalty
48
+ self.complexity += 1 + self.nesting_level
49
+
50
+ # Penalty for complex conditions
51
+ if self._has_complex_condition(node.test):
52
+ self.complexity += 1
53
+
54
+ self._visit_with_nesting(node)
55
+
56
+ def _process_loop_node(self, node: ast.For | ast.While) -> None:
57
+ """Process for/while loop nodes."""
58
+ self.complexity += 1 + self.nesting_level
59
+ self._visit_with_nesting(node)
60
+
61
+ def _process_try_node(self, node: ast.Try) -> None:
62
+ """Process try/except nodes with handler penalty."""
63
+ # Base complexity for try + number of except handlers
64
+ self.complexity += 1 + self.nesting_level + len(node.handlers)
65
+ self._visit_with_nesting(node)
66
+
67
+ def _process_context_node(self, node: ast.With) -> None:
68
+ """Process with/context manager nodes."""
69
+ self.complexity += 1 + self.nesting_level
70
+ self._visit_with_nesting(node)
71
+
72
+ def _process_boolean_operation(self, node: ast.BoolOp) -> None:
73
+ """Process boolean operations with chain penalty."""
74
+ penalty = len(node.values) - 1
75
+ if penalty > 2: # Long chains are more complex
76
+ penalty += 1
77
+ self.complexity += penalty
78
+ self.generic_visit(node)
79
+
80
+ def _process_comprehension(
81
+ self, node: ast.ListComp | ast.DictComp | ast.SetComp | ast.GeneratorExp
82
+ ) -> None:
83
+ """Process comprehensions with condition penalty."""
84
+ self.complexity += 1
85
+ # Check each generator for ifs conditions
86
+ for generator in node.generators:
87
+ if hasattr(generator, "ifs") and generator.ifs:
88
+ self.complexity += len(generator.ifs)
89
+ self.generic_visit(node)
90
+
91
+ def _visit_with_nesting(self, node: ast.AST) -> None:
92
+ """Visit a node with proper nesting level tracking."""
93
+ self.nesting_level += 1
94
+ self.generic_visit(node)
95
+ self.nesting_level -= 1
96
+
97
+ def _has_complex_condition(self, node: ast.expr) -> bool:
98
+ """Check if condition involves complex expressions."""
99
+ return (isinstance(node, ast.BoolOp) and len(node.values) > 2) or isinstance(
100
+ node, ast.Compare | ast.Call
101
+ )
102
+
103
+
104
+ class UsageDataCollector:
105
+ """Collector for usage data analysis."""
106
+
107
+ def __init__(self):
108
+ self.defined_names: set[str] = set()
109
+ self.used_names: set[str] = set()
110
+ self.import_lines: list[tuple[int, str, str]] = []
111
+ self.unused_functions: list[dict[str, t.Any]] = []
112
+ self.unused_classes: list[dict[str, t.Any]] = []
113
+ self.unused_variables: list[dict[str, t.Any]] = []
114
+
115
+ def get_results(self, analyzer: "EnhancedUsageAnalyzer") -> dict[str, t.Any]:
116
+ """Get collected usage data results."""
117
+ return {
118
+ "defined_names": self.defined_names,
119
+ "used_names": self.used_names,
120
+ "import_lines": self.import_lines,
121
+ "unused_functions": self.unused_functions,
122
+ "unused_classes": self.unused_classes,
123
+ "unused_variables": self.unused_variables,
124
+ "function_calls": analyzer.function_calls,
125
+ }
126
+
127
+
128
+ class EnhancedUsageAnalyzer(ast.NodeVisitor):
129
+ """Analyzer for enhanced usage data collection."""
130
+
131
+ def __init__(self, collector: UsageDataCollector):
132
+ self.scope_stack = [set()] # Track variable scopes
133
+ self.class_methods = {} # Track class method usage
134
+ self.function_calls = set() # Track function calls
135
+ self.collector = collector
136
+
137
+ def visit_Import(self, node: ast.Import) -> None:
138
+ self._process_import_node(node)
139
+
140
+ def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
141
+ self._process_import_from_node(node)
142
+
143
+ def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
144
+ self._process_function_definition(node)
145
+
146
+ def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
147
+ self._process_async_function_definition(node)
148
+
149
+ def visit_ClassDef(self, node: ast.ClassDef) -> None:
150
+ self._process_class_definition(node)
151
+
152
+ def visit_Assign(self, node: ast.Assign) -> None:
153
+ self._process_assignment(node)
154
+
155
+ def visit_AnnAssign(self, node: ast.AnnAssign) -> None:
156
+ self._process_annotated_assignment(node)
157
+
158
+ def visit_Name(self, node: ast.Name) -> None:
159
+ self._process_name_usage(node)
160
+
161
+ def visit_Call(self, node: ast.Call) -> None:
162
+ self._process_function_call(node)
163
+
164
+ def visit_Attribute(self, node: ast.Attribute) -> None:
165
+ self._process_attribute_access(node)
166
+
167
+ def _process_import_node(self, node: ast.Import) -> None:
168
+ """Process import statements."""
169
+ for alias in node.names:
170
+ name = alias.asname or alias.name
171
+ self.collector.defined_names.add(name)
172
+ self.collector.import_lines.append((node.lineno, name, "import"))
173
+
174
+ def _process_import_from_node(self, node: ast.ImportFrom) -> None:
175
+ """Process from-import statements."""
176
+ for alias in node.names:
177
+ name = alias.asname or alias.name
178
+ self.collector.defined_names.add(name)
179
+ self.collector.import_lines.append((node.lineno, name, "from_import"))
180
+
181
+ def _process_function_definition(self, node: ast.FunctionDef) -> None:
182
+ """Process function definitions."""
183
+ self.collector.defined_names.add(node.name)
184
+ if self._should_track_function(node.name):
185
+ function_info = self._create_function_info(node)
186
+ self.collector.unused_functions.append(function_info)
187
+ self._visit_with_scope(node)
188
+
189
+ def _process_async_function_definition(self, node: ast.AsyncFunctionDef) -> None:
190
+ """Process async function definitions."""
191
+ self.collector.defined_names.add(node.name)
192
+ if not node.name.startswith("_"):
193
+ function_info = self._create_function_info(node)
194
+ self.collector.unused_functions.append(function_info)
195
+ self._visit_with_scope(node)
196
+
197
+ def _process_class_definition(self, node: ast.ClassDef) -> None:
198
+ """Process class definitions."""
199
+ self.collector.defined_names.add(node.name)
200
+ self.collector.unused_classes.append(
201
+ {
202
+ "name": node.name,
203
+ "line": node.lineno,
204
+ "methods": [],
205
+ }
206
+ )
207
+ self._visit_with_scope(node)
208
+
209
+ def _process_assignment(self, node: ast.Assign) -> None:
210
+ """Process variable assignments."""
211
+ for target in node.targets:
212
+ if isinstance(target, ast.Name):
213
+ self.collector.defined_names.add(target.id)
214
+ if self._is_in_function_or_class_scope():
215
+ var_info = self._create_variable_info(target, node)
216
+ self.collector.unused_variables.append(var_info)
217
+ self.generic_visit(node)
218
+
219
+ def _process_annotated_assignment(self, node: ast.AnnAssign) -> None:
220
+ """Process annotated assignments."""
221
+ if isinstance(node.target, ast.Name):
222
+ self.collector.defined_names.add(node.target.id)
223
+ self.generic_visit(node)
224
+
225
+ def _process_name_usage(self, node: ast.Name) -> None:
226
+ """Process name usage (variable references)."""
227
+ if isinstance(node.ctx, ast.Load):
228
+ self.collector.used_names.add(node.id)
229
+ if self.scope_stack:
230
+ self.scope_stack[-1].add(node.id)
231
+
232
+ def _process_function_call(self, node: ast.Call) -> None:
233
+ """Process function/method calls."""
234
+ if isinstance(node.func, ast.Name):
235
+ self.function_calls.add(node.func.id)
236
+ self.collector.used_names.add(node.func.id)
237
+ elif isinstance(node.func, ast.Attribute):
238
+ if isinstance(node.func.value, ast.Name):
239
+ self.collector.used_names.add(node.func.value.id)
240
+ self.function_calls.add(node.func.attr)
241
+ self.generic_visit(node)
242
+
243
+ def _process_attribute_access(self, node: ast.Attribute) -> None:
244
+ """Process attribute access."""
245
+ if isinstance(node.value, ast.Name):
246
+ self.collector.used_names.add(node.value.id)
247
+ self.generic_visit(node)
248
+
249
+ def _should_track_function(self, name: str) -> bool:
250
+ """Determine if function should be tracked for unused analysis."""
251
+ return not name.startswith("_") and name != "__init__"
252
+
253
+ def _create_function_info(
254
+ self, node: ast.FunctionDef | ast.AsyncFunctionDef
255
+ ) -> dict[str, t.Any]:
256
+ """Create function information dictionary."""
257
+ return {
258
+ "name": node.name,
259
+ "line": node.lineno,
260
+ "is_method": len(self.scope_stack) > 1,
261
+ "args": [arg.arg for arg in node.args.args],
262
+ }
263
+
264
+ def _create_variable_info(
265
+ self, target: ast.Name, node: ast.Assign
266
+ ) -> dict[str, t.Any]:
267
+ """Create variable information dictionary."""
268
+ return {
269
+ "name": target.id,
270
+ "line": node.lineno,
271
+ "scope_level": len(self.scope_stack),
272
+ }
273
+
274
+ def _is_in_function_or_class_scope(self) -> bool:
275
+ """Check if currently in function or class scope."""
276
+ return len(self.scope_stack) > 1
277
+
278
+ def _visit_with_scope(self, node: ast.AST) -> None:
279
+ """Visit node with proper scope tracking."""
280
+ self.scope_stack.append(set())
281
+ self.generic_visit(node)
282
+ self.scope_stack.pop()