crackerjack 0.37.9__py3-none-any.whl → 0.45.2__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.
Files changed (425) hide show
  1. crackerjack/README.md +19 -0
  2. crackerjack/__init__.py +30 -1
  3. crackerjack/__main__.py +342 -1263
  4. crackerjack/adapters/README.md +18 -0
  5. crackerjack/adapters/__init__.py +27 -5
  6. crackerjack/adapters/_output_paths.py +167 -0
  7. crackerjack/adapters/_qa_adapter_base.py +309 -0
  8. crackerjack/adapters/_tool_adapter_base.py +706 -0
  9. crackerjack/adapters/ai/README.md +65 -0
  10. crackerjack/adapters/ai/__init__.py +5 -0
  11. crackerjack/adapters/ai/claude.py +853 -0
  12. crackerjack/adapters/complexity/README.md +53 -0
  13. crackerjack/adapters/complexity/__init__.py +10 -0
  14. crackerjack/adapters/complexity/complexipy.py +641 -0
  15. crackerjack/adapters/dependency/__init__.py +22 -0
  16. crackerjack/adapters/dependency/pip_audit.py +418 -0
  17. crackerjack/adapters/format/README.md +72 -0
  18. crackerjack/adapters/format/__init__.py +11 -0
  19. crackerjack/adapters/format/mdformat.py +313 -0
  20. crackerjack/adapters/format/ruff.py +516 -0
  21. crackerjack/adapters/lint/README.md +47 -0
  22. crackerjack/adapters/lint/__init__.py +11 -0
  23. crackerjack/adapters/lint/codespell.py +273 -0
  24. crackerjack/adapters/lsp/README.md +49 -0
  25. crackerjack/adapters/lsp/__init__.py +27 -0
  26. crackerjack/adapters/{rust_tool_manager.py → lsp/_manager.py} +3 -3
  27. crackerjack/adapters/{skylos_adapter.py → lsp/skylos.py} +59 -7
  28. crackerjack/adapters/{zuban_adapter.py → lsp/zuban.py} +3 -6
  29. crackerjack/adapters/refactor/README.md +59 -0
  30. crackerjack/adapters/refactor/__init__.py +12 -0
  31. crackerjack/adapters/refactor/creosote.py +318 -0
  32. crackerjack/adapters/refactor/refurb.py +406 -0
  33. crackerjack/adapters/refactor/skylos.py +494 -0
  34. crackerjack/adapters/sast/README.md +132 -0
  35. crackerjack/adapters/sast/__init__.py +32 -0
  36. crackerjack/adapters/sast/_base.py +201 -0
  37. crackerjack/adapters/sast/bandit.py +423 -0
  38. crackerjack/adapters/sast/pyscn.py +405 -0
  39. crackerjack/adapters/sast/semgrep.py +241 -0
  40. crackerjack/adapters/security/README.md +111 -0
  41. crackerjack/adapters/security/__init__.py +17 -0
  42. crackerjack/adapters/security/gitleaks.py +339 -0
  43. crackerjack/adapters/type/README.md +52 -0
  44. crackerjack/adapters/type/__init__.py +12 -0
  45. crackerjack/adapters/type/pyrefly.py +402 -0
  46. crackerjack/adapters/type/ty.py +402 -0
  47. crackerjack/adapters/type/zuban.py +522 -0
  48. crackerjack/adapters/utility/README.md +51 -0
  49. crackerjack/adapters/utility/__init__.py +10 -0
  50. crackerjack/adapters/utility/checks.py +884 -0
  51. crackerjack/agents/README.md +264 -0
  52. crackerjack/agents/__init__.py +40 -12
  53. crackerjack/agents/base.py +1 -0
  54. crackerjack/agents/claude_code_bridge.py +641 -0
  55. crackerjack/agents/coordinator.py +49 -53
  56. crackerjack/agents/dry_agent.py +187 -3
  57. crackerjack/agents/enhanced_coordinator.py +279 -0
  58. crackerjack/agents/enhanced_proactive_agent.py +185 -0
  59. crackerjack/agents/error_middleware.py +53 -0
  60. crackerjack/agents/formatting_agent.py +6 -8
  61. crackerjack/agents/helpers/__init__.py +9 -0
  62. crackerjack/agents/helpers/performance/__init__.py +22 -0
  63. crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
  64. crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
  65. crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
  66. crackerjack/agents/helpers/refactoring/__init__.py +22 -0
  67. crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
  68. crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
  69. crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
  70. crackerjack/agents/helpers/test_creation/__init__.py +19 -0
  71. crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
  72. crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
  73. crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
  74. crackerjack/agents/performance_agent.py +121 -1152
  75. crackerjack/agents/refactoring_agent.py +156 -655
  76. crackerjack/agents/semantic_agent.py +479 -0
  77. crackerjack/agents/semantic_helpers.py +356 -0
  78. crackerjack/agents/test_creation_agent.py +19 -1605
  79. crackerjack/api.py +5 -7
  80. crackerjack/cli/README.md +394 -0
  81. crackerjack/cli/__init__.py +1 -1
  82. crackerjack/cli/cache_handlers.py +23 -18
  83. crackerjack/cli/cache_handlers_enhanced.py +1 -4
  84. crackerjack/cli/facade.py +70 -8
  85. crackerjack/cli/formatting.py +13 -0
  86. crackerjack/cli/handlers/__init__.py +85 -0
  87. crackerjack/cli/handlers/advanced.py +103 -0
  88. crackerjack/cli/handlers/ai_features.py +62 -0
  89. crackerjack/cli/handlers/analytics.py +479 -0
  90. crackerjack/cli/handlers/changelog.py +271 -0
  91. crackerjack/cli/handlers/config_handlers.py +16 -0
  92. crackerjack/cli/handlers/coverage.py +84 -0
  93. crackerjack/cli/handlers/documentation.py +280 -0
  94. crackerjack/cli/handlers/main_handlers.py +497 -0
  95. crackerjack/cli/handlers/monitoring.py +371 -0
  96. crackerjack/cli/handlers.py +249 -49
  97. crackerjack/cli/interactive.py +8 -5
  98. crackerjack/cli/options.py +203 -110
  99. crackerjack/cli/semantic_handlers.py +292 -0
  100. crackerjack/cli/version.py +19 -0
  101. crackerjack/code_cleaner.py +60 -24
  102. crackerjack/config/README.md +472 -0
  103. crackerjack/config/__init__.py +256 -0
  104. crackerjack/config/global_lock_config.py +191 -54
  105. crackerjack/config/hooks.py +188 -16
  106. crackerjack/config/loader.py +239 -0
  107. crackerjack/config/settings.py +141 -0
  108. crackerjack/config/tool_commands.py +331 -0
  109. crackerjack/core/README.md +393 -0
  110. crackerjack/core/async_workflow_orchestrator.py +79 -53
  111. crackerjack/core/autofix_coordinator.py +22 -9
  112. crackerjack/core/container.py +10 -9
  113. crackerjack/core/enhanced_container.py +9 -9
  114. crackerjack/core/performance.py +1 -1
  115. crackerjack/core/performance_monitor.py +5 -3
  116. crackerjack/core/phase_coordinator.py +1018 -634
  117. crackerjack/core/proactive_workflow.py +3 -3
  118. crackerjack/core/retry.py +275 -0
  119. crackerjack/core/service_watchdog.py +167 -23
  120. crackerjack/core/session_coordinator.py +187 -382
  121. crackerjack/core/timeout_manager.py +161 -44
  122. crackerjack/core/workflow/__init__.py +21 -0
  123. crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
  124. crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
  125. crackerjack/core/workflow/workflow_issue_parser.py +714 -0
  126. crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
  127. crackerjack/core/workflow/workflow_security_gates.py +400 -0
  128. crackerjack/core/workflow_orchestrator.py +1247 -953
  129. crackerjack/data/README.md +11 -0
  130. crackerjack/data/__init__.py +8 -0
  131. crackerjack/data/models.py +79 -0
  132. crackerjack/data/repository.py +210 -0
  133. crackerjack/decorators/README.md +180 -0
  134. crackerjack/decorators/__init__.py +35 -0
  135. crackerjack/decorators/error_handling.py +649 -0
  136. crackerjack/decorators/error_handling_decorators.py +334 -0
  137. crackerjack/decorators/helpers.py +58 -0
  138. crackerjack/decorators/patterns.py +281 -0
  139. crackerjack/decorators/utils.py +58 -0
  140. crackerjack/docs/README.md +11 -0
  141. crackerjack/docs/generated/api/CLI_REFERENCE.md +1 -1
  142. crackerjack/documentation/README.md +11 -0
  143. crackerjack/documentation/ai_templates.py +1 -1
  144. crackerjack/documentation/dual_output_generator.py +11 -9
  145. crackerjack/documentation/reference_generator.py +104 -59
  146. crackerjack/dynamic_config.py +52 -61
  147. crackerjack/errors.py +1 -1
  148. crackerjack/events/README.md +11 -0
  149. crackerjack/events/__init__.py +16 -0
  150. crackerjack/events/telemetry.py +175 -0
  151. crackerjack/events/workflow_bus.py +346 -0
  152. crackerjack/exceptions/README.md +301 -0
  153. crackerjack/exceptions/__init__.py +5 -0
  154. crackerjack/exceptions/config.py +4 -0
  155. crackerjack/exceptions/tool_execution_error.py +245 -0
  156. crackerjack/executors/README.md +591 -0
  157. crackerjack/executors/__init__.py +2 -0
  158. crackerjack/executors/async_hook_executor.py +539 -77
  159. crackerjack/executors/cached_hook_executor.py +3 -3
  160. crackerjack/executors/hook_executor.py +967 -102
  161. crackerjack/executors/hook_lock_manager.py +31 -22
  162. crackerjack/executors/individual_hook_executor.py +66 -32
  163. crackerjack/executors/lsp_aware_hook_executor.py +136 -57
  164. crackerjack/executors/progress_hook_executor.py +282 -0
  165. crackerjack/executors/tool_proxy.py +23 -7
  166. crackerjack/hooks/README.md +485 -0
  167. crackerjack/hooks/lsp_hook.py +8 -9
  168. crackerjack/intelligence/README.md +557 -0
  169. crackerjack/interactive.py +37 -10
  170. crackerjack/managers/README.md +369 -0
  171. crackerjack/managers/async_hook_manager.py +41 -57
  172. crackerjack/managers/hook_manager.py +449 -79
  173. crackerjack/managers/publish_manager.py +81 -36
  174. crackerjack/managers/test_command_builder.py +290 -12
  175. crackerjack/managers/test_executor.py +93 -8
  176. crackerjack/managers/test_manager.py +1082 -75
  177. crackerjack/managers/test_progress.py +118 -26
  178. crackerjack/mcp/README.md +374 -0
  179. crackerjack/mcp/cache.py +25 -2
  180. crackerjack/mcp/client_runner.py +35 -18
  181. crackerjack/mcp/context.py +9 -9
  182. crackerjack/mcp/dashboard.py +24 -8
  183. crackerjack/mcp/enhanced_progress_monitor.py +34 -23
  184. crackerjack/mcp/file_monitor.py +27 -6
  185. crackerjack/mcp/progress_components.py +45 -34
  186. crackerjack/mcp/progress_monitor.py +6 -9
  187. crackerjack/mcp/rate_limiter.py +11 -7
  188. crackerjack/mcp/server.py +2 -0
  189. crackerjack/mcp/server_core.py +187 -55
  190. crackerjack/mcp/service_watchdog.py +12 -9
  191. crackerjack/mcp/task_manager.py +2 -2
  192. crackerjack/mcp/tools/README.md +27 -0
  193. crackerjack/mcp/tools/__init__.py +2 -0
  194. crackerjack/mcp/tools/core_tools.py +75 -52
  195. crackerjack/mcp/tools/execution_tools.py +87 -31
  196. crackerjack/mcp/tools/intelligence_tools.py +2 -2
  197. crackerjack/mcp/tools/proactive_tools.py +1 -1
  198. crackerjack/mcp/tools/semantic_tools.py +584 -0
  199. crackerjack/mcp/tools/utility_tools.py +180 -132
  200. crackerjack/mcp/tools/workflow_executor.py +87 -46
  201. crackerjack/mcp/websocket/README.md +31 -0
  202. crackerjack/mcp/websocket/app.py +11 -1
  203. crackerjack/mcp/websocket/event_bridge.py +188 -0
  204. crackerjack/mcp/websocket/jobs.py +27 -4
  205. crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
  206. crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
  207. crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
  208. crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
  209. crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
  210. crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
  211. crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
  212. crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
  213. crackerjack/mcp/websocket/monitoring/factory.py +109 -0
  214. crackerjack/mcp/websocket/monitoring/filters.py +10 -0
  215. crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
  216. crackerjack/mcp/websocket/monitoring/models.py +90 -0
  217. crackerjack/mcp/websocket/monitoring/utils.py +171 -0
  218. crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
  219. crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
  220. crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
  221. crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
  222. crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
  223. crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
  224. crackerjack/mcp/websocket/monitoring_endpoints.py +16 -2930
  225. crackerjack/mcp/websocket/server.py +1 -3
  226. crackerjack/mcp/websocket/websocket_handler.py +107 -6
  227. crackerjack/models/README.md +308 -0
  228. crackerjack/models/__init__.py +10 -1
  229. crackerjack/models/config.py +639 -22
  230. crackerjack/models/config_adapter.py +6 -6
  231. crackerjack/models/protocols.py +1167 -23
  232. crackerjack/models/pydantic_models.py +320 -0
  233. crackerjack/models/qa_config.py +145 -0
  234. crackerjack/models/qa_results.py +134 -0
  235. crackerjack/models/results.py +35 -0
  236. crackerjack/models/semantic_models.py +258 -0
  237. crackerjack/models/task.py +19 -3
  238. crackerjack/models/test_models.py +60 -0
  239. crackerjack/monitoring/README.md +11 -0
  240. crackerjack/monitoring/ai_agent_watchdog.py +5 -4
  241. crackerjack/monitoring/metrics_collector.py +4 -3
  242. crackerjack/monitoring/regression_prevention.py +4 -3
  243. crackerjack/monitoring/websocket_server.py +4 -241
  244. crackerjack/orchestration/README.md +340 -0
  245. crackerjack/orchestration/__init__.py +43 -0
  246. crackerjack/orchestration/advanced_orchestrator.py +20 -67
  247. crackerjack/orchestration/cache/README.md +312 -0
  248. crackerjack/orchestration/cache/__init__.py +37 -0
  249. crackerjack/orchestration/cache/memory_cache.py +338 -0
  250. crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
  251. crackerjack/orchestration/config.py +297 -0
  252. crackerjack/orchestration/coverage_improvement.py +13 -6
  253. crackerjack/orchestration/execution_strategies.py +6 -6
  254. crackerjack/orchestration/hook_orchestrator.py +1398 -0
  255. crackerjack/orchestration/strategies/README.md +401 -0
  256. crackerjack/orchestration/strategies/__init__.py +39 -0
  257. crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
  258. crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
  259. crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
  260. crackerjack/orchestration/test_progress_streamer.py +1 -1
  261. crackerjack/plugins/README.md +11 -0
  262. crackerjack/plugins/hooks.py +3 -2
  263. crackerjack/plugins/loader.py +3 -3
  264. crackerjack/plugins/managers.py +1 -1
  265. crackerjack/py313.py +191 -0
  266. crackerjack/security/README.md +11 -0
  267. crackerjack/services/README.md +374 -0
  268. crackerjack/services/__init__.py +8 -21
  269. crackerjack/services/ai/README.md +295 -0
  270. crackerjack/services/ai/__init__.py +7 -0
  271. crackerjack/services/ai/advanced_optimizer.py +878 -0
  272. crackerjack/services/{contextual_ai_assistant.py → ai/contextual_ai_assistant.py} +5 -3
  273. crackerjack/services/ai/embeddings.py +444 -0
  274. crackerjack/services/ai/intelligent_commit.py +328 -0
  275. crackerjack/services/ai/predictive_analytics.py +510 -0
  276. crackerjack/services/api_extractor.py +5 -3
  277. crackerjack/services/bounded_status_operations.py +45 -5
  278. crackerjack/services/cache.py +249 -318
  279. crackerjack/services/changelog_automation.py +7 -3
  280. crackerjack/services/command_execution_service.py +305 -0
  281. crackerjack/services/config_integrity.py +83 -39
  282. crackerjack/services/config_merge.py +9 -6
  283. crackerjack/services/config_service.py +198 -0
  284. crackerjack/services/config_template.py +13 -26
  285. crackerjack/services/coverage_badge_service.py +6 -4
  286. crackerjack/services/coverage_ratchet.py +53 -27
  287. crackerjack/services/debug.py +18 -7
  288. crackerjack/services/dependency_analyzer.py +4 -4
  289. crackerjack/services/dependency_monitor.py +13 -13
  290. crackerjack/services/documentation_generator.py +4 -2
  291. crackerjack/services/documentation_service.py +62 -33
  292. crackerjack/services/enhanced_filesystem.py +81 -27
  293. crackerjack/services/enterprise_optimizer.py +1 -1
  294. crackerjack/services/error_pattern_analyzer.py +10 -10
  295. crackerjack/services/file_filter.py +221 -0
  296. crackerjack/services/file_hasher.py +5 -7
  297. crackerjack/services/file_io_service.py +361 -0
  298. crackerjack/services/file_modifier.py +615 -0
  299. crackerjack/services/filesystem.py +80 -109
  300. crackerjack/services/git.py +99 -5
  301. crackerjack/services/health_metrics.py +4 -6
  302. crackerjack/services/heatmap_generator.py +12 -3
  303. crackerjack/services/incremental_executor.py +380 -0
  304. crackerjack/services/initialization.py +101 -49
  305. crackerjack/services/log_manager.py +2 -2
  306. crackerjack/services/logging.py +120 -68
  307. crackerjack/services/lsp_client.py +12 -12
  308. crackerjack/services/memory_optimizer.py +27 -22
  309. crackerjack/services/monitoring/README.md +30 -0
  310. crackerjack/services/monitoring/__init__.py +9 -0
  311. crackerjack/services/monitoring/dependency_monitor.py +678 -0
  312. crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
  313. crackerjack/services/monitoring/health_metrics.py +716 -0
  314. crackerjack/services/monitoring/metrics.py +587 -0
  315. crackerjack/services/{performance_benchmarks.py → monitoring/performance_benchmarks.py} +100 -14
  316. crackerjack/services/{performance_cache.py → monitoring/performance_cache.py} +21 -15
  317. crackerjack/services/{performance_monitor.py → monitoring/performance_monitor.py} +10 -6
  318. crackerjack/services/parallel_executor.py +166 -55
  319. crackerjack/services/patterns/__init__.py +142 -0
  320. crackerjack/services/patterns/agents.py +107 -0
  321. crackerjack/services/patterns/code/__init__.py +15 -0
  322. crackerjack/services/patterns/code/detection.py +118 -0
  323. crackerjack/services/patterns/code/imports.py +107 -0
  324. crackerjack/services/patterns/code/paths.py +159 -0
  325. crackerjack/services/patterns/code/performance.py +119 -0
  326. crackerjack/services/patterns/code/replacement.py +36 -0
  327. crackerjack/services/patterns/core.py +212 -0
  328. crackerjack/services/patterns/documentation/__init__.py +14 -0
  329. crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
  330. crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
  331. crackerjack/services/patterns/documentation/docstrings.py +89 -0
  332. crackerjack/services/patterns/formatting.py +226 -0
  333. crackerjack/services/patterns/operations.py +339 -0
  334. crackerjack/services/patterns/security/__init__.py +23 -0
  335. crackerjack/services/patterns/security/code_injection.py +122 -0
  336. crackerjack/services/patterns/security/credentials.py +190 -0
  337. crackerjack/services/patterns/security/path_traversal.py +221 -0
  338. crackerjack/services/patterns/security/unsafe_operations.py +216 -0
  339. crackerjack/services/patterns/templates.py +62 -0
  340. crackerjack/services/patterns/testing/__init__.py +18 -0
  341. crackerjack/services/patterns/testing/error_patterns.py +107 -0
  342. crackerjack/services/patterns/testing/pytest_output.py +126 -0
  343. crackerjack/services/patterns/tool_output/__init__.py +16 -0
  344. crackerjack/services/patterns/tool_output/bandit.py +72 -0
  345. crackerjack/services/patterns/tool_output/other.py +97 -0
  346. crackerjack/services/patterns/tool_output/pyright.py +67 -0
  347. crackerjack/services/patterns/tool_output/ruff.py +44 -0
  348. crackerjack/services/patterns/url_sanitization.py +114 -0
  349. crackerjack/services/patterns/utilities.py +42 -0
  350. crackerjack/services/patterns/utils.py +339 -0
  351. crackerjack/services/patterns/validation.py +46 -0
  352. crackerjack/services/patterns/versioning.py +62 -0
  353. crackerjack/services/predictive_analytics.py +21 -8
  354. crackerjack/services/profiler.py +280 -0
  355. crackerjack/services/quality/README.md +415 -0
  356. crackerjack/services/quality/__init__.py +11 -0
  357. crackerjack/services/quality/anomaly_detector.py +392 -0
  358. crackerjack/services/quality/pattern_cache.py +333 -0
  359. crackerjack/services/quality/pattern_detector.py +479 -0
  360. crackerjack/services/quality/qa_orchestrator.py +491 -0
  361. crackerjack/services/{quality_baseline.py → quality/quality_baseline.py} +163 -2
  362. crackerjack/services/{quality_baseline_enhanced.py → quality/quality_baseline_enhanced.py} +4 -1
  363. crackerjack/services/{quality_intelligence.py → quality/quality_intelligence.py} +180 -16
  364. crackerjack/services/regex_patterns.py +58 -2987
  365. crackerjack/services/regex_utils.py +55 -29
  366. crackerjack/services/secure_status_formatter.py +42 -15
  367. crackerjack/services/secure_subprocess.py +35 -2
  368. crackerjack/services/security.py +16 -8
  369. crackerjack/services/server_manager.py +40 -51
  370. crackerjack/services/smart_scheduling.py +46 -6
  371. crackerjack/services/status_authentication.py +3 -3
  372. crackerjack/services/thread_safe_status_collector.py +1 -0
  373. crackerjack/services/tool_filter.py +368 -0
  374. crackerjack/services/tool_version_service.py +9 -5
  375. crackerjack/services/unified_config.py +43 -351
  376. crackerjack/services/vector_store.py +689 -0
  377. crackerjack/services/version_analyzer.py +6 -4
  378. crackerjack/services/version_checker.py +14 -8
  379. crackerjack/services/zuban_lsp_service.py +5 -4
  380. crackerjack/slash_commands/README.md +11 -0
  381. crackerjack/slash_commands/init.md +2 -12
  382. crackerjack/slash_commands/run.md +84 -50
  383. crackerjack/tools/README.md +11 -0
  384. crackerjack/tools/__init__.py +30 -0
  385. crackerjack/tools/_git_utils.py +105 -0
  386. crackerjack/tools/check_added_large_files.py +139 -0
  387. crackerjack/tools/check_ast.py +105 -0
  388. crackerjack/tools/check_json.py +103 -0
  389. crackerjack/tools/check_jsonschema.py +297 -0
  390. crackerjack/tools/check_toml.py +103 -0
  391. crackerjack/tools/check_yaml.py +110 -0
  392. crackerjack/tools/codespell_wrapper.py +72 -0
  393. crackerjack/tools/end_of_file_fixer.py +202 -0
  394. crackerjack/tools/format_json.py +128 -0
  395. crackerjack/tools/mdformat_wrapper.py +114 -0
  396. crackerjack/tools/trailing_whitespace.py +198 -0
  397. crackerjack/tools/validate_regex_patterns.py +7 -3
  398. crackerjack/ui/README.md +11 -0
  399. crackerjack/ui/dashboard_renderer.py +28 -0
  400. crackerjack/ui/templates/README.md +11 -0
  401. crackerjack/utils/console_utils.py +13 -0
  402. crackerjack/utils/dependency_guard.py +230 -0
  403. crackerjack/utils/retry_utils.py +275 -0
  404. crackerjack/workflows/README.md +590 -0
  405. crackerjack/workflows/__init__.py +46 -0
  406. crackerjack/workflows/actions.py +811 -0
  407. crackerjack/workflows/auto_fix.py +444 -0
  408. crackerjack/workflows/container_builder.py +499 -0
  409. crackerjack/workflows/definitions.py +443 -0
  410. crackerjack/workflows/engine.py +177 -0
  411. crackerjack/workflows/event_bridge.py +242 -0
  412. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/METADATA +678 -98
  413. crackerjack-0.45.2.dist-info/RECORD +478 -0
  414. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
  415. crackerjack/managers/test_manager_backup.py +0 -1075
  416. crackerjack/mcp/tools/execution_tools_backup.py +0 -1011
  417. crackerjack/mixins/__init__.py +0 -3
  418. crackerjack/mixins/error_handling.py +0 -145
  419. crackerjack/services/config.py +0 -358
  420. crackerjack/ui/server_panels.py +0 -125
  421. crackerjack-0.37.9.dist-info/RECORD +0 -231
  422. /crackerjack/adapters/{rust_tool_adapter.py → lsp/_base.py} +0 -0
  423. /crackerjack/adapters/{lsp_client.py → lsp/_client.py} +0 -0
  424. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/entry_points.txt +0 -0
  425. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,334 @@
1
+ """Reusable decorators for consistent error handling across the codebase."""
2
+
3
+ import functools
4
+ import json
5
+ import subprocess
6
+ from collections.abc import Callable
7
+ from typing import Any
8
+
9
+ from loguru import logger
10
+
11
+
12
+ def handle_file_errors(
13
+ exceptions: tuple[type[Exception], ...] = (
14
+ OSError,
15
+ FileNotFoundError,
16
+ PermissionError,
17
+ ),
18
+ default_return: Any = None,
19
+ log_error: bool = True,
20
+ reraise: bool
21
+ | None = None, # If None, reraise is False when default_return is provided
22
+ ):
23
+ """
24
+ Decorator to handle common file operation errors consistently.
25
+
26
+ Args:
27
+ exceptions: Tuple of exception types to catch
28
+ default_return: Value to return when an exception occurs
29
+ log_error: Whether to log the error
30
+ reraise: Whether to reraise the exception after handling (None means False if default_return is provided)
31
+ """
32
+
33
+ def decorator(func: Callable) -> Callable:
34
+ @functools.wraps(func)
35
+ def wrapper(*args, **kwargs):
36
+ try:
37
+ return func(*args, **kwargs)
38
+ except exceptions as e:
39
+ if log_error:
40
+ logger.error(f"File operation failed in {func.__name__}: {e}")
41
+ # Determine if we should reraise:
42
+ # - if reraise is explicitly set to True/False, respect that
43
+ # - if reraise is None (default):
44
+ # - reraise if no default_return is provided (when default_return is None)
45
+ # - don't reraise if default_return is provided
46
+ should_reraise = (
47
+ reraise if reraise is not None else (default_return is None)
48
+ )
49
+ if should_reraise:
50
+ raise
51
+ return default_return
52
+
53
+ return wrapper
54
+
55
+ return decorator
56
+
57
+
58
+ def handle_json_errors(
59
+ exceptions: tuple[type[Exception], ...] = (
60
+ json.JSONDecodeError,
61
+ TypeError,
62
+ ValueError,
63
+ ),
64
+ default_return: Any = None,
65
+ log_error: bool = True,
66
+ reraise: bool
67
+ | None = None, # If None, reraise is False when default_return is provided
68
+ ):
69
+ """
70
+ Decorator to handle JSON parsing errors consistently.
71
+
72
+ Args:
73
+ exceptions: Tuple of exception types to catch
74
+ default_return: Value to return when an exception occurs
75
+ log_error: Whether to log the error
76
+ reraise: Whether to reraise the exception after handling (None means False if default_return is provided)
77
+ """
78
+
79
+ def decorator(func: Callable) -> Callable:
80
+ @functools.wraps(func)
81
+ def wrapper(*args, **kwargs):
82
+ try:
83
+ result = func(*args, **kwargs)
84
+ return result
85
+ except exceptions as e:
86
+ if log_error:
87
+ logger.error(f"JSON operation failed in {func.__name__}: {e}")
88
+ # Determine if we should reraise:
89
+ # - if reraise is explicitly set to True/False, respect that
90
+ # - if reraise is None (default):
91
+ # - reraise if no default_return is provided (when default_return is None)
92
+ # - don't reraise if default_return is provided
93
+ should_reraise = (
94
+ reraise if reraise is not None else (default_return is None)
95
+ )
96
+ if should_reraise:
97
+ raise
98
+ return default_return
99
+
100
+ return wrapper
101
+
102
+ return decorator
103
+
104
+
105
+ def handle_subprocess_errors(
106
+ exceptions: tuple[type[Exception], ...] = (
107
+ subprocess.CalledProcessError,
108
+ subprocess.TimeoutExpired,
109
+ ),
110
+ default_return: Any = None,
111
+ log_error: bool = True,
112
+ reraise: bool
113
+ | None = None, # If None, reraise is False when default_return is provided
114
+ ):
115
+ """
116
+ Decorator to handle subprocess execution errors consistently.
117
+
118
+ Args:
119
+ exceptions: Tuple of exception types to catch
120
+ default_return: Value to return when an exception occurs
121
+ log_error: Whether to log the error
122
+ reraise: Whether to reraise the exception after handling (None means False if default_return is provided)
123
+ """
124
+
125
+ def decorator(func: Callable) -> Callable:
126
+ @functools.wraps(func)
127
+ def wrapper(*args, **kwargs):
128
+ try:
129
+ result = func(*args, **kwargs)
130
+ return result
131
+ except exceptions as e:
132
+ if log_error:
133
+ logger.error(f"Subprocess operation failed in {func.__name__}: {e}")
134
+ # Determine if we should reraise:
135
+ # - if reraise is explicitly set to True/False, respect that
136
+ # - if reraise is None (default):
137
+ # - reraise if no default_return is provided (when default_return is None)
138
+ # - don't reraise if default_return is provided
139
+ should_reraise = (
140
+ reraise if reraise is not None else (default_return is None)
141
+ )
142
+ if should_reraise:
143
+ raise
144
+ return default_return
145
+
146
+ return wrapper
147
+
148
+ return decorator
149
+
150
+
151
+ def handle_validation_errors(
152
+ exceptions: tuple[type[Exception], ...] = (ValueError, TypeError, AttributeError),
153
+ default_return: Any = None,
154
+ log_error: bool = True,
155
+ reraise: bool
156
+ | None = None, # If None, reraise is False when default_return is provided
157
+ ):
158
+ """
159
+ Decorator to handle data validation errors consistently.
160
+
161
+ Args:
162
+ exceptions: Tuple of exception types to catch
163
+ default_return: Value to return when an exception occurs
164
+ log_error: Whether to log the error
165
+ reraise: Whether to reraise the exception after handling (None means False if default_return is provided)
166
+ """
167
+
168
+ def decorator(func: Callable) -> Callable:
169
+ @functools.wraps(func)
170
+ def wrapper(*args, **kwargs):
171
+ try:
172
+ result = func(*args, **kwargs)
173
+ return result
174
+ except exceptions as e:
175
+ if log_error:
176
+ logger.error(f"Validation failed in {func.__name__}: {e}")
177
+ # Determine if we should reraise:
178
+ # - if reraise is explicitly set to True/False, respect that
179
+ # - if reraise is None (default):
180
+ # - reraise if no default_return is provided (when default_return is None)
181
+ # - don't reraise if default_return is provided
182
+ should_reraise = (
183
+ reraise if reraise is not None else (default_return is None)
184
+ )
185
+ if should_reraise:
186
+ raise
187
+ return default_return
188
+
189
+ return wrapper
190
+
191
+ return decorator
192
+
193
+
194
+ def handle_network_errors(
195
+ exceptions: tuple[type[Exception], ...] = (
196
+ ConnectionError,
197
+ ConnectionRefusedError,
198
+ TimeoutError,
199
+ # Add more common network errors as needed
200
+ ),
201
+ default_return: Any = None,
202
+ log_error: bool = True,
203
+ reraise: bool
204
+ | None = None, # If None, reraise is False when default_return is provided
205
+ ):
206
+ """
207
+ Decorator to handle network-related errors consistently.
208
+
209
+ Args:
210
+ exceptions: Tuple of exception types to catch
211
+ default_return: Value to return when an exception occurs
212
+ log_error: Whether to log the error
213
+ reraise: Whether to reraise the exception after handling (None means False if default_return is provided)
214
+ """
215
+
216
+ def decorator(func: Callable) -> Callable:
217
+ @functools.wraps(func)
218
+ def wrapper(*args, **kwargs):
219
+ try:
220
+ result = func(*args, **kwargs)
221
+ return result
222
+ except exceptions as e:
223
+ if log_error:
224
+ logger.error(f"Network operation failed in {func.__name__}: {e}")
225
+ # Determine if we should reraise:
226
+ # - if reraise is explicitly set to True/False, respect that
227
+ # - if reraise is None (default):
228
+ # - reraise if no default_return is provided (when default_return is None)
229
+ # - don't reraise if default_return is provided
230
+ should_reraise = (
231
+ reraise if reraise is not None else (default_return is None)
232
+ )
233
+ if should_reraise:
234
+ raise
235
+ return default_return
236
+
237
+ return wrapper
238
+
239
+ return decorator
240
+
241
+
242
+ def handle_all_errors(
243
+ log_error: bool = True,
244
+ reraise: bool
245
+ | None = None, # If None, reraise is False when default_return is provided
246
+ default_return: Any = None,
247
+ exclude: tuple[type[BaseException], ...] = (KeyboardInterrupt, SystemExit),
248
+ ):
249
+ """
250
+ Decorator to handle all errors except for specific system exceptions.
251
+
252
+ Args:
253
+ log_error: Whether to log the error
254
+ reraise: Whether to reraise the exception after handling (None means False if default_return is provided)
255
+ default_return: Value to return when an exception occurs
256
+ exclude: Tuple of exception types to exclude from handling
257
+ """
258
+
259
+ def decorator(func: Callable) -> Callable:
260
+ @functools.wraps(func)
261
+ def wrapper(*args, **kwargs):
262
+ try:
263
+ return func(*args, **kwargs)
264
+ except exclude:
265
+ # Don't handle system exceptions like KeyboardInterrupt
266
+ raise
267
+ except Exception as e:
268
+ if log_error:
269
+ logger.error(f"Unexpected error in {func.__name__}: {e}")
270
+ # Determine if we should reraise:
271
+ # - if reraise is explicitly set to True/False, respect that
272
+ # - if reraise is None (default):
273
+ # - reraise if no default_return is provided (when default_return is None)
274
+ # - don't reraise if default_return is provided
275
+ should_reraise = (
276
+ reraise if reraise is not None else (default_return is None)
277
+ )
278
+ if should_reraise:
279
+ raise
280
+ return default_return
281
+
282
+ return wrapper
283
+
284
+ return decorator
285
+
286
+
287
+ def retry_on_error(
288
+ max_attempts: int = 3,
289
+ delay: float = 1.0,
290
+ backoff: float = 2.0,
291
+ exceptions: tuple[type[Exception], ...] = (Exception,),
292
+ log_retry: bool = True,
293
+ ):
294
+ """
295
+ Decorator to retry a function on specific exceptions.
296
+
297
+ Args:
298
+ max_attempts: Maximum number of attempts
299
+ delay: Initial delay between attempts (in seconds)
300
+ backoff: Multiplier for delay after each attempt
301
+ exceptions: Tuple of exception types to retry on
302
+ log_retry: Whether to log retry attempts
303
+ """
304
+
305
+ def decorator(func: Callable) -> Callable:
306
+ @functools.wraps(func)
307
+ def wrapper(*args, **kwargs):
308
+ current_delay = delay
309
+ last_exception = None
310
+
311
+ for attempt in range(max_attempts):
312
+ try:
313
+ return func(*args, **kwargs)
314
+ except exceptions as e:
315
+ last_exception = e
316
+ if log_retry:
317
+ logger.warning(
318
+ f"Attempt {attempt + 1}/{max_attempts} failed in {func.__name__}: {e}. "
319
+ f"Retrying in {current_delay}s..."
320
+ )
321
+ if attempt < max_attempts - 1: # Don't sleep after the last attempt
322
+ import time
323
+
324
+ time.sleep(current_delay)
325
+ current_delay *= backoff
326
+
327
+ logger.error(
328
+ f"All {max_attempts} attempts failed in {func.__name__}: {last_exception}"
329
+ )
330
+ raise last_exception
331
+
332
+ return wrapper
333
+
334
+ return decorator
@@ -0,0 +1,58 @@
1
+ """Shared utilities for error handling decorators."""
2
+
3
+ import asyncio
4
+ import inspect
5
+ import typing as t
6
+ from functools import wraps
7
+
8
+ F = t.TypeVar("F", bound=t.Callable[..., t.Any])
9
+
10
+
11
+ def is_async_function(func: t.Callable[..., t.Any]) -> bool:
12
+ """Check if a function is async."""
13
+ return asyncio.iscoroutinefunction(func)
14
+
15
+
16
+ def preserve_signature[F: t.Callable[..., t.Any]](
17
+ wrapper: F,
18
+ ) -> t.Callable[[t.Callable[..., t.Any]], F]:
19
+ """Preserve function signature in decorators."""
20
+
21
+ def decorator(func: t.Callable[..., t.Any]) -> F:
22
+ wrapped = wraps(func)(wrapper)
23
+ # Preserve signature metadata
24
+ wrapped.__wrapped__ = func # type: ignore[attr-defined]
25
+ return t.cast(F, wrapped)
26
+
27
+ return decorator
28
+
29
+
30
+ def get_function_context(func: t.Callable[..., t.Any]) -> dict[str, t.Any]:
31
+ """Extract context information from a function for error reporting."""
32
+ return {
33
+ "function_name": func.__name__,
34
+ "module": func.__module__,
35
+ "qualname": func.__qualname__,
36
+ "is_async": is_async_function(func),
37
+ }
38
+
39
+
40
+ def format_exception_chain(exc: BaseException) -> list[str]:
41
+ """Format exception chain for logging."""
42
+ chain: list[str] = []
43
+ current: BaseException | None = exc
44
+
45
+ while current is not None:
46
+ chain.append(f"{type(current).__name__}: {current}")
47
+ current = current.__cause__ or current.__context__
48
+
49
+ return chain
50
+
51
+
52
+ def get_callable_params(func: t.Callable[..., t.Any]) -> list[inspect.Parameter]:
53
+ """Get function parameters using inspect."""
54
+ try:
55
+ sig = inspect.signature(func)
56
+ return list(sig.parameters.values())
57
+ except (ValueError, TypeError):
58
+ return []
@@ -0,0 +1,281 @@
1
+ """Error pattern detection and caching decorator."""
2
+
3
+ import typing as t
4
+ from functools import wraps
5
+ from pathlib import Path
6
+
7
+ from ..errors import CrackerjackError
8
+ from ..mcp.cache import ErrorCache, ErrorPattern
9
+ from .helpers import get_function_context, is_async_function
10
+
11
+
12
+ def cache_errors(
13
+ cache_dir: Path | None = None,
14
+ error_type: str | None = None,
15
+ auto_analyze: bool = True,
16
+ ) -> t.Callable[[t.Callable[..., t.Any]], t.Callable[..., t.Any]]:
17
+ """
18
+ Detect and cache error patterns for analysis and auto-fixing.
19
+
20
+ Args:
21
+ cache_dir: Directory for error cache (default: ~/.cache/crackerjack-mcp)
22
+ error_type: Override error type classification (default: auto-detect)
23
+ auto_analyze: Automatically analyze errors for patterns (default: True)
24
+
25
+ Returns:
26
+ Decorated function with error pattern caching
27
+
28
+ Example:
29
+ >>> from pathlib import Path
30
+ >>>
31
+ >>> @cache_errors(error_type="lint", auto_analyze=True)
32
+ >>> async def run_linter(files: list[Path]) -> bool:
33
+ ... # Errors are automatically cached and analyzed
34
+ ... return await linter.run(files)
35
+
36
+ >>> @cache_errors()
37
+ >>> def execute_command(cmd: list[str]) -> bool:
38
+ ... # Error patterns tracked for future auto-fix
39
+ ... return subprocess.run(cmd).returncode == 0
40
+
41
+ Notes:
42
+ - Integrates with Crackerjack's ErrorCache system
43
+ - Tracks error frequency and common fixes
44
+ - Enables intelligent auto-fix suggestions
45
+ - Works with AI agents for pattern recognition
46
+ """
47
+ error_cache = ErrorCache(cache_dir=cache_dir)
48
+
49
+ def decorator(func: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]:
50
+ if is_async_function(func):
51
+ return _create_async_wrapper(func, error_cache, error_type, auto_analyze)
52
+ return _create_sync_wrapper(func, error_cache, error_type, auto_analyze)
53
+
54
+ return decorator
55
+
56
+
57
+ def _create_async_wrapper(
58
+ func: t.Callable[..., t.Any],
59
+ error_cache: ErrorCache,
60
+ error_type: str | None,
61
+ auto_analyze: bool,
62
+ ) -> t.Callable[..., t.Any]:
63
+ """Create async wrapper with error caching."""
64
+
65
+ @wraps(func)
66
+ async def async_wrapper(*args: t.Any, **kwargs: t.Any) -> t.Any:
67
+ try:
68
+ result = await func(*args, **kwargs)
69
+ await _handle_result_analysis(
70
+ result, error_cache, func, error_type, auto_analyze
71
+ )
72
+ return result
73
+ except CrackerjackError as e:
74
+ await _cache_crackerjack_error(error_cache, e, func, error_type)
75
+ raise
76
+ except Exception as e:
77
+ await _handle_generic_exception(
78
+ e, error_cache, func, error_type, auto_analyze
79
+ )
80
+ raise
81
+
82
+ return async_wrapper
83
+
84
+
85
+ def _create_sync_wrapper(
86
+ func: t.Callable[..., t.Any],
87
+ error_cache: ErrorCache,
88
+ error_type: str | None,
89
+ auto_analyze: bool,
90
+ ) -> t.Callable[..., t.Any]:
91
+ """Create sync wrapper with error caching."""
92
+
93
+ @wraps(func)
94
+ def sync_wrapper(*args: t.Any, **kwargs: t.Any) -> t.Any:
95
+ try:
96
+ result = func(*args, **kwargs)
97
+ _handle_result_analysis_sync(
98
+ result, error_cache, func, error_type, auto_analyze
99
+ )
100
+ return result
101
+ except CrackerjackError as e:
102
+ _cache_crackerjack_error_sync(error_cache, e, func, error_type)
103
+ raise
104
+ except Exception as e:
105
+ _handle_generic_exception_sync(
106
+ e, error_cache, func, error_type, auto_analyze
107
+ )
108
+ raise
109
+
110
+ return sync_wrapper
111
+
112
+
113
+ async def _handle_result_analysis(
114
+ result: t.Any,
115
+ cache: ErrorCache,
116
+ func: t.Callable[..., t.Any],
117
+ error_type: str | None,
118
+ auto_analyze: bool,
119
+ ) -> None:
120
+ """Handle result error analysis for async functions."""
121
+ if not auto_analyze or not isinstance(result, dict):
122
+ return
123
+ if "error" in result or "errors" in result:
124
+ await _analyze_result_errors(cache, result, func, error_type)
125
+
126
+
127
+ def _handle_result_analysis_sync(
128
+ result: t.Any,
129
+ cache: ErrorCache,
130
+ func: t.Callable[..., t.Any],
131
+ error_type: str | None,
132
+ auto_analyze: bool,
133
+ ) -> None:
134
+ """Handle result error analysis for sync functions."""
135
+ if not auto_analyze or not isinstance(result, dict):
136
+ return
137
+ if "error" in result or "errors" in result:
138
+ _analyze_result_errors_sync(cache, result, func, error_type)
139
+
140
+
141
+ async def _handle_generic_exception(
142
+ error: Exception,
143
+ cache: ErrorCache,
144
+ func: t.Callable[..., t.Any],
145
+ error_type: str | None,
146
+ auto_analyze: bool,
147
+ ) -> None:
148
+ """Handle generic exception caching for async functions."""
149
+ if auto_analyze:
150
+ await _cache_exception(cache, error, func, error_type)
151
+
152
+
153
+ def _handle_generic_exception_sync(
154
+ error: Exception,
155
+ cache: ErrorCache,
156
+ func: t.Callable[..., t.Any],
157
+ error_type: str | None,
158
+ auto_analyze: bool,
159
+ ) -> None:
160
+ """Handle generic exception caching for sync functions."""
161
+ if auto_analyze:
162
+ _cache_exception_sync(cache, error, func, error_type)
163
+
164
+
165
+ async def _analyze_result_errors(
166
+ cache: ErrorCache,
167
+ result: dict[str, t.Any],
168
+ func: t.Callable[..., t.Any],
169
+ error_type_override: str | None,
170
+ ) -> None:
171
+ """Analyze errors from result dictionary (async)."""
172
+ error_data = result.get("error") or result.get("errors", "")
173
+ if isinstance(error_data, str) and error_data:
174
+ context = get_function_context(func)
175
+ detected_type = error_type_override or context["function_name"]
176
+
177
+ pattern = cache.create_pattern_from_error(error_data, detected_type)
178
+ if pattern:
179
+ await cache.add_pattern(pattern)
180
+
181
+
182
+ def _analyze_result_errors_sync(
183
+ cache: ErrorCache,
184
+ result: dict[str, t.Any],
185
+ func: t.Callable[..., t.Any],
186
+ error_type_override: str | None,
187
+ ) -> None:
188
+ """Analyze errors from result dictionary (sync)."""
189
+ import asyncio
190
+
191
+ error_data = result.get("error") or result.get("errors", "")
192
+ if isinstance(error_data, str) and error_data:
193
+ context = get_function_context(func)
194
+ detected_type = error_type_override or context["function_name"]
195
+
196
+ pattern = cache.create_pattern_from_error(error_data, detected_type)
197
+ if pattern:
198
+ # Run async method in sync context
199
+ asyncio.run(cache.add_pattern(pattern))
200
+
201
+
202
+ async def _cache_crackerjack_error(
203
+ cache: ErrorCache,
204
+ error: CrackerjackError,
205
+ func: t.Callable[..., t.Any],
206
+ error_type_override: str | None,
207
+ ) -> None:
208
+ """Cache a CrackerjackError (async)."""
209
+ get_function_context(func)
210
+ detected_type = error_type_override or error.error_code.name
211
+
212
+ pattern = ErrorPattern(
213
+ pattern_id=f"{detected_type}_{error.error_code.value}_{hash(error.message) % 10000}",
214
+ error_type=detected_type,
215
+ error_code=str(error.error_code.value),
216
+ message_pattern=error.message,
217
+ common_fixes=[error.recovery] if error.recovery else None,
218
+ auto_fixable=False,
219
+ )
220
+
221
+ await cache.add_pattern(pattern)
222
+
223
+
224
+ def _cache_crackerjack_error_sync(
225
+ cache: ErrorCache,
226
+ error: CrackerjackError,
227
+ func: t.Callable[..., t.Any],
228
+ error_type_override: str | None,
229
+ ) -> None:
230
+ """Cache a CrackerjackError (sync)."""
231
+ import asyncio
232
+
233
+ get_function_context(func)
234
+ detected_type = error_type_override or error.error_code.name
235
+
236
+ pattern = ErrorPattern(
237
+ pattern_id=f"{detected_type}_{error.error_code.value}_{hash(error.message) % 10000}",
238
+ error_type=detected_type,
239
+ error_code=str(error.error_code.value),
240
+ message_pattern=error.message,
241
+ common_fixes=[error.recovery] if error.recovery else None,
242
+ auto_fixable=False,
243
+ )
244
+
245
+ asyncio.run(cache.add_pattern(pattern))
246
+
247
+
248
+ async def _cache_exception(
249
+ cache: ErrorCache,
250
+ error: Exception,
251
+ func: t.Callable[..., t.Any],
252
+ error_type_override: str | None,
253
+ ) -> None:
254
+ """Cache a generic exception (async)."""
255
+ get_function_context(func)
256
+ detected_type = error_type_override or type(error).__name__
257
+
258
+ error_message = str(error)
259
+ pattern = cache.create_pattern_from_error(error_message, detected_type)
260
+
261
+ if pattern:
262
+ await cache.add_pattern(pattern)
263
+
264
+
265
+ def _cache_exception_sync(
266
+ cache: ErrorCache,
267
+ error: Exception,
268
+ func: t.Callable[..., t.Any],
269
+ error_type_override: str | None,
270
+ ) -> None:
271
+ """Cache a generic exception (sync)."""
272
+ import asyncio
273
+
274
+ get_function_context(func)
275
+ detected_type = error_type_override or type(error).__name__
276
+
277
+ error_message = str(error)
278
+ pattern = cache.create_pattern_from_error(error_message, detected_type)
279
+
280
+ if pattern:
281
+ asyncio.run(cache.add_pattern(pattern))