crackerjack 0.32.0__py3-none-any.whl → 0.33.1__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 (200) hide show
  1. crackerjack/__main__.py +1350 -34
  2. crackerjack/adapters/__init__.py +17 -0
  3. crackerjack/adapters/lsp_client.py +358 -0
  4. crackerjack/adapters/rust_tool_adapter.py +194 -0
  5. crackerjack/adapters/rust_tool_manager.py +193 -0
  6. crackerjack/adapters/skylos_adapter.py +231 -0
  7. crackerjack/adapters/zuban_adapter.py +560 -0
  8. crackerjack/agents/base.py +7 -3
  9. crackerjack/agents/coordinator.py +271 -33
  10. crackerjack/agents/documentation_agent.py +9 -15
  11. crackerjack/agents/dry_agent.py +3 -15
  12. crackerjack/agents/formatting_agent.py +1 -1
  13. crackerjack/agents/import_optimization_agent.py +36 -180
  14. crackerjack/agents/performance_agent.py +17 -98
  15. crackerjack/agents/performance_helpers.py +7 -31
  16. crackerjack/agents/proactive_agent.py +1 -3
  17. crackerjack/agents/refactoring_agent.py +16 -85
  18. crackerjack/agents/refactoring_helpers.py +7 -42
  19. crackerjack/agents/security_agent.py +9 -48
  20. crackerjack/agents/test_creation_agent.py +356 -513
  21. crackerjack/agents/test_specialist_agent.py +0 -4
  22. crackerjack/api.py +6 -25
  23. crackerjack/cli/cache_handlers.py +204 -0
  24. crackerjack/cli/cache_handlers_enhanced.py +683 -0
  25. crackerjack/cli/facade.py +100 -0
  26. crackerjack/cli/handlers.py +224 -9
  27. crackerjack/cli/interactive.py +6 -4
  28. crackerjack/cli/options.py +642 -55
  29. crackerjack/cli/utils.py +2 -1
  30. crackerjack/code_cleaner.py +58 -117
  31. crackerjack/config/global_lock_config.py +8 -48
  32. crackerjack/config/hooks.py +53 -62
  33. crackerjack/core/async_workflow_orchestrator.py +24 -34
  34. crackerjack/core/autofix_coordinator.py +3 -17
  35. crackerjack/core/enhanced_container.py +64 -6
  36. crackerjack/core/file_lifecycle.py +12 -89
  37. crackerjack/core/performance.py +2 -2
  38. crackerjack/core/performance_monitor.py +15 -55
  39. crackerjack/core/phase_coordinator.py +257 -218
  40. crackerjack/core/resource_manager.py +14 -90
  41. crackerjack/core/service_watchdog.py +62 -95
  42. crackerjack/core/session_coordinator.py +149 -0
  43. crackerjack/core/timeout_manager.py +14 -72
  44. crackerjack/core/websocket_lifecycle.py +13 -78
  45. crackerjack/core/workflow_orchestrator.py +558 -240
  46. crackerjack/docs/INDEX.md +11 -0
  47. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  48. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  49. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  50. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  51. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  52. crackerjack/documentation/__init__.py +31 -0
  53. crackerjack/documentation/ai_templates.py +756 -0
  54. crackerjack/documentation/dual_output_generator.py +765 -0
  55. crackerjack/documentation/mkdocs_integration.py +518 -0
  56. crackerjack/documentation/reference_generator.py +977 -0
  57. crackerjack/dynamic_config.py +55 -50
  58. crackerjack/executors/async_hook_executor.py +10 -15
  59. crackerjack/executors/cached_hook_executor.py +117 -43
  60. crackerjack/executors/hook_executor.py +8 -34
  61. crackerjack/executors/hook_lock_manager.py +26 -183
  62. crackerjack/executors/individual_hook_executor.py +13 -11
  63. crackerjack/executors/lsp_aware_hook_executor.py +270 -0
  64. crackerjack/executors/tool_proxy.py +417 -0
  65. crackerjack/hooks/lsp_hook.py +79 -0
  66. crackerjack/intelligence/adaptive_learning.py +25 -10
  67. crackerjack/intelligence/agent_orchestrator.py +2 -5
  68. crackerjack/intelligence/agent_registry.py +34 -24
  69. crackerjack/intelligence/agent_selector.py +5 -7
  70. crackerjack/interactive.py +17 -6
  71. crackerjack/managers/async_hook_manager.py +0 -1
  72. crackerjack/managers/hook_manager.py +79 -1
  73. crackerjack/managers/publish_manager.py +66 -13
  74. crackerjack/managers/test_command_builder.py +5 -17
  75. crackerjack/managers/test_executor.py +1 -3
  76. crackerjack/managers/test_manager.py +109 -7
  77. crackerjack/managers/test_manager_backup.py +10 -9
  78. crackerjack/mcp/cache.py +2 -2
  79. crackerjack/mcp/client_runner.py +1 -1
  80. crackerjack/mcp/context.py +191 -68
  81. crackerjack/mcp/dashboard.py +7 -5
  82. crackerjack/mcp/enhanced_progress_monitor.py +31 -28
  83. crackerjack/mcp/file_monitor.py +30 -23
  84. crackerjack/mcp/progress_components.py +31 -21
  85. crackerjack/mcp/progress_monitor.py +50 -53
  86. crackerjack/mcp/rate_limiter.py +6 -6
  87. crackerjack/mcp/server_core.py +161 -32
  88. crackerjack/mcp/service_watchdog.py +2 -1
  89. crackerjack/mcp/state.py +4 -7
  90. crackerjack/mcp/task_manager.py +11 -9
  91. crackerjack/mcp/tools/core_tools.py +174 -33
  92. crackerjack/mcp/tools/error_analyzer.py +3 -2
  93. crackerjack/mcp/tools/execution_tools.py +15 -12
  94. crackerjack/mcp/tools/execution_tools_backup.py +42 -30
  95. crackerjack/mcp/tools/intelligence_tool_registry.py +7 -5
  96. crackerjack/mcp/tools/intelligence_tools.py +5 -2
  97. crackerjack/mcp/tools/monitoring_tools.py +33 -70
  98. crackerjack/mcp/tools/proactive_tools.py +24 -11
  99. crackerjack/mcp/tools/progress_tools.py +5 -8
  100. crackerjack/mcp/tools/utility_tools.py +20 -14
  101. crackerjack/mcp/tools/workflow_executor.py +62 -40
  102. crackerjack/mcp/websocket/app.py +8 -0
  103. crackerjack/mcp/websocket/endpoints.py +352 -357
  104. crackerjack/mcp/websocket/jobs.py +40 -57
  105. crackerjack/mcp/websocket/monitoring_endpoints.py +2935 -0
  106. crackerjack/mcp/websocket/server.py +7 -25
  107. crackerjack/mcp/websocket/websocket_handler.py +6 -17
  108. crackerjack/mixins/__init__.py +3 -0
  109. crackerjack/mixins/error_handling.py +145 -0
  110. crackerjack/models/config.py +21 -1
  111. crackerjack/models/config_adapter.py +49 -1
  112. crackerjack/models/protocols.py +176 -107
  113. crackerjack/models/resource_protocols.py +55 -210
  114. crackerjack/models/task.py +3 -0
  115. crackerjack/monitoring/ai_agent_watchdog.py +13 -13
  116. crackerjack/monitoring/metrics_collector.py +426 -0
  117. crackerjack/monitoring/regression_prevention.py +8 -8
  118. crackerjack/monitoring/websocket_server.py +643 -0
  119. crackerjack/orchestration/advanced_orchestrator.py +11 -6
  120. crackerjack/orchestration/coverage_improvement.py +3 -3
  121. crackerjack/orchestration/execution_strategies.py +26 -6
  122. crackerjack/orchestration/test_progress_streamer.py +8 -5
  123. crackerjack/plugins/base.py +2 -2
  124. crackerjack/plugins/hooks.py +7 -0
  125. crackerjack/plugins/managers.py +11 -8
  126. crackerjack/security/__init__.py +0 -1
  127. crackerjack/security/audit.py +90 -105
  128. crackerjack/services/anomaly_detector.py +392 -0
  129. crackerjack/services/api_extractor.py +615 -0
  130. crackerjack/services/backup_service.py +2 -2
  131. crackerjack/services/bounded_status_operations.py +15 -152
  132. crackerjack/services/cache.py +127 -1
  133. crackerjack/services/changelog_automation.py +395 -0
  134. crackerjack/services/config.py +18 -11
  135. crackerjack/services/config_merge.py +30 -85
  136. crackerjack/services/config_template.py +506 -0
  137. crackerjack/services/contextual_ai_assistant.py +48 -22
  138. crackerjack/services/coverage_badge_service.py +171 -0
  139. crackerjack/services/coverage_ratchet.py +41 -17
  140. crackerjack/services/debug.py +3 -3
  141. crackerjack/services/dependency_analyzer.py +460 -0
  142. crackerjack/services/dependency_monitor.py +14 -11
  143. crackerjack/services/documentation_generator.py +491 -0
  144. crackerjack/services/documentation_service.py +675 -0
  145. crackerjack/services/enhanced_filesystem.py +6 -5
  146. crackerjack/services/enterprise_optimizer.py +865 -0
  147. crackerjack/services/error_pattern_analyzer.py +676 -0
  148. crackerjack/services/file_hasher.py +1 -1
  149. crackerjack/services/git.py +41 -45
  150. crackerjack/services/health_metrics.py +10 -8
  151. crackerjack/services/heatmap_generator.py +735 -0
  152. crackerjack/services/initialization.py +30 -33
  153. crackerjack/services/input_validator.py +5 -97
  154. crackerjack/services/intelligent_commit.py +327 -0
  155. crackerjack/services/log_manager.py +15 -12
  156. crackerjack/services/logging.py +4 -3
  157. crackerjack/services/lsp_client.py +628 -0
  158. crackerjack/services/memory_optimizer.py +409 -0
  159. crackerjack/services/metrics.py +42 -33
  160. crackerjack/services/parallel_executor.py +416 -0
  161. crackerjack/services/pattern_cache.py +1 -1
  162. crackerjack/services/pattern_detector.py +6 -6
  163. crackerjack/services/performance_benchmarks.py +250 -576
  164. crackerjack/services/performance_cache.py +382 -0
  165. crackerjack/services/performance_monitor.py +565 -0
  166. crackerjack/services/predictive_analytics.py +510 -0
  167. crackerjack/services/quality_baseline.py +234 -0
  168. crackerjack/services/quality_baseline_enhanced.py +646 -0
  169. crackerjack/services/quality_intelligence.py +785 -0
  170. crackerjack/services/regex_patterns.py +605 -524
  171. crackerjack/services/regex_utils.py +43 -123
  172. crackerjack/services/secure_path_utils.py +5 -164
  173. crackerjack/services/secure_status_formatter.py +30 -141
  174. crackerjack/services/secure_subprocess.py +11 -92
  175. crackerjack/services/security.py +61 -30
  176. crackerjack/services/security_logger.py +18 -22
  177. crackerjack/services/server_manager.py +124 -16
  178. crackerjack/services/status_authentication.py +16 -159
  179. crackerjack/services/status_security_manager.py +4 -131
  180. crackerjack/services/terminal_utils.py +0 -0
  181. crackerjack/services/thread_safe_status_collector.py +19 -125
  182. crackerjack/services/unified_config.py +21 -13
  183. crackerjack/services/validation_rate_limiter.py +5 -54
  184. crackerjack/services/version_analyzer.py +459 -0
  185. crackerjack/services/version_checker.py +1 -1
  186. crackerjack/services/websocket_resource_limiter.py +10 -144
  187. crackerjack/services/zuban_lsp_service.py +390 -0
  188. crackerjack/slash_commands/__init__.py +2 -7
  189. crackerjack/slash_commands/run.md +2 -2
  190. crackerjack/tools/validate_input_validator_patterns.py +14 -40
  191. crackerjack/tools/validate_regex_patterns.py +19 -48
  192. {crackerjack-0.32.0.dist-info → crackerjack-0.33.1.dist-info}/METADATA +197 -26
  193. crackerjack-0.33.1.dist-info/RECORD +229 -0
  194. crackerjack/CLAUDE.md +0 -207
  195. crackerjack/RULES.md +0 -380
  196. crackerjack/py313.py +0 -234
  197. crackerjack-0.32.0.dist-info/RECORD +0 -180
  198. {crackerjack-0.32.0.dist-info → crackerjack-0.33.1.dist-info}/WHEEL +0 -0
  199. {crackerjack-0.32.0.dist-info → crackerjack-0.33.1.dist-info}/entry_points.txt +0 -0
  200. {crackerjack-0.32.0.dist-info → crackerjack-0.33.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,234 @@
1
+ import subprocess
2
+ import typing as t
3
+ from dataclasses import asdict, dataclass
4
+ from datetime import datetime
5
+
6
+ from crackerjack.services.cache import CrackerjackCache
7
+
8
+
9
+ @dataclass
10
+ class QualityMetrics:
11
+ """Quality metrics for a specific commit/session."""
12
+
13
+ git_hash: str
14
+ timestamp: datetime
15
+ coverage_percent: float
16
+ test_count: int
17
+ test_pass_rate: float
18
+ hook_failures: int
19
+ complexity_violations: int
20
+ security_issues: int
21
+ type_errors: int
22
+ linting_issues: int
23
+ quality_score: int # Overall score 0-100
24
+
25
+ def to_dict(self) -> dict[str, t.Any]:
26
+ data = asdict(self)
27
+ data["timestamp"] = self.timestamp.isoformat()
28
+ return data
29
+
30
+ @classmethod
31
+ def from_dict(cls, data: dict[str, t.Any]) -> "QualityMetrics":
32
+ data = data.copy()
33
+ if isinstance(data["timestamp"], str):
34
+ data["timestamp"] = datetime.fromisoformat(data["timestamp"])
35
+ return cls(**data)
36
+
37
+
38
+ class QualityBaselineService:
39
+ """Service for tracking and persisting quality baselines across sessions."""
40
+
41
+ def __init__(self, cache: CrackerjackCache | None = None) -> None:
42
+ self.cache = cache or CrackerjackCache()
43
+
44
+ def get_current_git_hash(self) -> str | None:
45
+ """Get current git commit hash."""
46
+ try:
47
+ result = subprocess.run(
48
+ ["git", "rev-parse", "HEAD"],
49
+ capture_output=True,
50
+ text=True,
51
+ check=True,
52
+ )
53
+ return result.stdout.strip()
54
+ except (subprocess.CalledProcessError, FileNotFoundError):
55
+ return None
56
+
57
+ def calculate_quality_score(
58
+ self,
59
+ coverage_percent: float,
60
+ test_pass_rate: float,
61
+ hook_failures: int,
62
+ complexity_violations: int,
63
+ security_issues: int,
64
+ type_errors: int,
65
+ linting_issues: int,
66
+ ) -> int:
67
+ """Calculate overall quality score (0-100)."""
68
+ # Base score from coverage and tests
69
+ base_score = (coverage_percent * 0.4) + (test_pass_rate * 0.3)
70
+
71
+ # Penalty for issues (each issue type has different weight)
72
+ penalties = (
73
+ hook_failures * 2.0 # Hook failures are serious
74
+ + complexity_violations * 1.5 # Complexity is important
75
+ + security_issues * 3.0 # Security is critical
76
+ + type_errors * 2.0 # Type errors are serious
77
+ + linting_issues * 0.5 # Linting is less critical
78
+ )
79
+
80
+ # Apply penalties with diminishing returns
81
+ penalty_score = max(0, 30 - (penalties * 0.8))
82
+
83
+ return max(0, min(100, int(base_score + penalty_score)))
84
+
85
+ def record_baseline(
86
+ self,
87
+ coverage_percent: float,
88
+ test_count: int,
89
+ test_pass_rate: float,
90
+ hook_failures: int = 0,
91
+ complexity_violations: int = 0,
92
+ security_issues: int = 0,
93
+ type_errors: int = 0,
94
+ linting_issues: int = 0,
95
+ ) -> QualityMetrics | None:
96
+ """Record quality baseline for current commit."""
97
+ git_hash = self.get_current_git_hash()
98
+ if not git_hash:
99
+ return None
100
+
101
+ quality_score = self.calculate_quality_score(
102
+ coverage_percent=coverage_percent,
103
+ test_pass_rate=test_pass_rate,
104
+ hook_failures=hook_failures,
105
+ complexity_violations=complexity_violations,
106
+ security_issues=security_issues,
107
+ type_errors=type_errors,
108
+ linting_issues=linting_issues,
109
+ )
110
+
111
+ metrics = QualityMetrics(
112
+ git_hash=git_hash,
113
+ timestamp=datetime.now(),
114
+ coverage_percent=coverage_percent,
115
+ test_count=test_count,
116
+ test_pass_rate=test_pass_rate,
117
+ hook_failures=hook_failures,
118
+ complexity_violations=complexity_violations,
119
+ security_issues=security_issues,
120
+ type_errors=type_errors,
121
+ linting_issues=linting_issues,
122
+ quality_score=quality_score,
123
+ )
124
+
125
+ # Store in cache for persistence across sessions
126
+ self.cache.set_quality_baseline(git_hash, metrics.to_dict())
127
+ return metrics
128
+
129
+ def get_baseline(self, git_hash: str | None = None) -> QualityMetrics | None:
130
+ """Get quality baseline for specific commit (or current commit)."""
131
+ if not git_hash:
132
+ git_hash = self.get_current_git_hash()
133
+
134
+ if not git_hash:
135
+ return None
136
+
137
+ baseline_data = self.cache.get_quality_baseline(git_hash)
138
+ if baseline_data:
139
+ return QualityMetrics.from_dict(baseline_data)
140
+
141
+ return None
142
+
143
+ def compare_with_baseline(
144
+ self,
145
+ current_metrics: dict[str, t.Any],
146
+ baseline_git_hash: str | None = None,
147
+ ) -> dict[str, t.Any]:
148
+ """Compare current metrics with baseline."""
149
+ baseline = self.get_baseline(baseline_git_hash)
150
+ if not baseline:
151
+ return {
152
+ "comparison_available": False,
153
+ "message": "No baseline found for comparison",
154
+ }
155
+
156
+ current_score = self.calculate_quality_score(**current_metrics)
157
+
158
+ return {
159
+ "comparison_available": True,
160
+ "baseline_score": baseline.quality_score,
161
+ "current_score": current_score,
162
+ "score_change": current_score - baseline.quality_score,
163
+ "baseline_timestamp": baseline.timestamp.isoformat(),
164
+ "improvements": self._identify_improvements(baseline, current_metrics),
165
+ "regressions": self._identify_regressions(baseline, current_metrics),
166
+ }
167
+
168
+ def _identify_improvements(
169
+ self, baseline: QualityMetrics, current: dict[str, t.Any]
170
+ ) -> list[str]:
171
+ """Identify areas that improved since baseline."""
172
+ improvements = []
173
+
174
+ if current["coverage_percent"] > baseline.coverage_percent:
175
+ improvements.append(
176
+ f"Coverage increased by {current['coverage_percent'] - baseline.coverage_percent:.1f}%"
177
+ )
178
+
179
+ if current["test_pass_rate"] > baseline.test_pass_rate:
180
+ improvements.append(
181
+ f"Test pass rate improved by {current['test_pass_rate'] - baseline.test_pass_rate:.1f}%"
182
+ )
183
+
184
+ if current.get("hook_failures", 0) < baseline.hook_failures:
185
+ improvements.append(
186
+ f"Hook failures reduced by {baseline.hook_failures - current.get('hook_failures', 0)}"
187
+ )
188
+
189
+ return improvements
190
+
191
+ def _identify_regressions(
192
+ self, baseline: QualityMetrics, current: dict[str, t.Any]
193
+ ) -> list[str]:
194
+ """Identify areas that regressed since baseline."""
195
+ regressions = []
196
+
197
+ if current["coverage_percent"] < baseline.coverage_percent:
198
+ regressions.append(
199
+ f"Coverage decreased by {baseline.coverage_percent - current['coverage_percent']:.1f}%"
200
+ )
201
+
202
+ if current["test_pass_rate"] < baseline.test_pass_rate:
203
+ regressions.append(
204
+ f"Test pass rate decreased by {baseline.test_pass_rate - current['test_pass_rate']:.1f}%"
205
+ )
206
+
207
+ if current.get("security_issues", 0) > baseline.security_issues:
208
+ regressions.append(
209
+ f"Security issues increased by {current.get('security_issues', 0) - baseline.security_issues}"
210
+ )
211
+
212
+ return regressions
213
+
214
+ def get_recent_baselines(self, limit: int = 10) -> list[QualityMetrics]:
215
+ """Get recent baselines (requires git log parsing since cache is keyed by hash)."""
216
+ try:
217
+ result = subprocess.run(
218
+ ["git", "log", "--oneline", "-n", str(limit), "--format=%H"],
219
+ capture_output=True,
220
+ text=True,
221
+ check=True,
222
+ )
223
+ git_hashes = result.stdout.strip().split("\n")
224
+
225
+ baselines = []
226
+ for git_hash in git_hashes:
227
+ baseline = self.get_baseline(git_hash.strip())
228
+ if baseline:
229
+ baselines.append(baseline)
230
+
231
+ return sorted(baselines, key=lambda b: b.timestamp, reverse=True)
232
+
233
+ except (subprocess.CalledProcessError, FileNotFoundError):
234
+ return []