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,479 @@
1
+ import ast
2
+ import logging
3
+ import typing as t
4
+ from collections.abc import Awaitable, Callable
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+
8
+ from crackerjack.agents.base import Issue, IssueType, Priority
9
+
10
+ from .pattern_cache import CachedPattern, PatternCache
11
+
12
+ DetectorMethod = Callable[[Path, str, ast.AST], Awaitable[list["AntiPattern"]]]
13
+
14
+
15
+ class AntiPatternConfig(t.TypedDict):
16
+ detector: DetectorMethod
17
+ description: str
18
+ prevention: str
19
+
20
+
21
+ @dataclass
22
+ class AntiPattern:
23
+ pattern_type: str
24
+ severity: Priority
25
+ file_path: str
26
+ line_number: int | None
27
+ description: str
28
+ suggestion: str
29
+ prevention_strategy: str
30
+
31
+
32
+ class PatternDetector:
33
+ def __init__(self, project_path: Path, pattern_cache: PatternCache) -> None:
34
+ self.project_path = project_path
35
+ self.pattern_cache = pattern_cache
36
+ self.logger = logging.getLogger(__name__)
37
+
38
+ self._anti_patterns: dict[str, AntiPatternConfig] = {
39
+ "complexity_hotspot": {
40
+ "detector": self._detect_complexity_hotspots,
41
+ "description": "Functions approaching complexity limits",
42
+ "prevention": "Extract methods, use helper functions",
43
+ },
44
+ "code_duplication": {
45
+ "detector": self._detect_code_duplication,
46
+ "description": "Repeated code patterns across files",
47
+ "prevention": "Extract common functionality to utilities",
48
+ },
49
+ "performance_issues": {
50
+ "detector": self._detect_performance_issues,
51
+ "description": "Inefficient code patterns",
52
+ "prevention": "Use optimized algorithms and data structures",
53
+ },
54
+ "security_risks": {
55
+ "detector": self._detect_security_risks,
56
+ "description": "Potentially unsafe code patterns",
57
+ "prevention": "Apply secure coding practices",
58
+ },
59
+ "import_complexity": {
60
+ "detector": self._detect_import_complexity,
61
+ "description": "Complex or problematic import patterns",
62
+ "prevention": "Organize imports, avoid circular dependencies",
63
+ },
64
+ }
65
+
66
+ async def analyze_codebase(self) -> list[AntiPattern]:
67
+ self.logger.info("Starting proactive anti-pattern analysis")
68
+
69
+ anti_patterns = []
70
+ python_files = list[t.Any](self.project_path.glob("**/*.py"))
71
+
72
+ for file_path in python_files:
73
+ if self._should_skip_file(file_path):
74
+ continue
75
+
76
+ file_anti_patterns = await self._analyze_file(file_path)
77
+ anti_patterns.extend(file_anti_patterns)
78
+
79
+ self.logger.info(f"Detected {len(anti_patterns)} potential anti-patterns")
80
+ return anti_patterns
81
+
82
+ async def _analyze_file(self, file_path: Path) -> list[AntiPattern]:
83
+ anti_patterns = []
84
+
85
+ try:
86
+ content = file_path.read_text(encoding="utf-8")
87
+
88
+ try:
89
+ tree = ast.parse(content, filename=str(file_path))
90
+ except SyntaxError as e:
91
+ self.logger.warning(f"Syntax error in {file_path}: {e}")
92
+ return []
93
+
94
+ for pattern_name, pattern_info in self._anti_patterns.items():
95
+ detector_method = pattern_info["detector"]
96
+ try:
97
+ detected = await detector_method(file_path, content, tree)
98
+ anti_patterns.extend(detected)
99
+ except Exception as e:
100
+ self.logger.warning(
101
+ f"Error in {pattern_name} detector for {file_path}: {e}"
102
+ )
103
+
104
+ except Exception as e:
105
+ self.logger.warning(f"Failed to analyze {file_path}: {e}")
106
+
107
+ return anti_patterns
108
+
109
+ async def _detect_complexity_hotspots(
110
+ self, file_path: Path, content: str, tree: ast.AST
111
+ ) -> list[AntiPattern]:
112
+ anti_patterns = []
113
+
114
+ class ComplexityVisitor(ast.NodeVisitor):
115
+ def __init__(self) -> None:
116
+ self.functions: list[tuple[str, int, int]] = []
117
+
118
+ def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
119
+ complexity = 1
120
+
121
+ for child in ast.walk(node):
122
+ if isinstance(child, ast.If | ast.For | ast.While | ast.With):
123
+ complexity += 1
124
+ elif isinstance(child, ast.Try):
125
+ complexity += 1
126
+ elif isinstance(child, ast.ExceptHandler):
127
+ complexity += 1
128
+ elif isinstance(child, ast.BoolOp):
129
+ complexity += len(child.values) - 1
130
+
131
+ self.functions.append((node.name, node.lineno, complexity))
132
+ self.generic_visit(node)
133
+
134
+ visitor = ComplexityVisitor()
135
+ visitor.visit(tree)
136
+
137
+ for func_name, line_no, complexity in visitor.functions:
138
+ if complexity >= 10:
139
+ anti_patterns.append(
140
+ AntiPattern(
141
+ pattern_type="complexity_hotspot",
142
+ severity=Priority.HIGH if complexity >= 12 else Priority.MEDIUM,
143
+ file_path=str(file_path),
144
+ line_number=line_no,
145
+ description=f"Function '{func_name}' has complexity {complexity} (approaching limit of 15)",
146
+ suggestion=f"Break down '{func_name}' into smaller helper methods",
147
+ prevention_strategy="extract_method",
148
+ )
149
+ )
150
+
151
+ return anti_patterns
152
+
153
+ async def _detect_code_duplication(
154
+ self, file_path: Path, content: str, tree: ast.AST
155
+ ) -> list[AntiPattern]:
156
+ anti_patterns = []
157
+
158
+ lines = content.split("\n")
159
+ line_groups: dict[str, list[int]] = {}
160
+
161
+ for i, line in enumerate(lines, 1):
162
+ stripped = line.strip()
163
+ if len(stripped) > 20 and not stripped.startswith("#"):
164
+ if stripped in line_groups:
165
+ line_groups[stripped].append(i)
166
+ else:
167
+ line_groups[stripped] = [i]
168
+
169
+ for line_content, line_numbers in line_groups.items():
170
+ if len(line_numbers) >= 3:
171
+ anti_patterns.append(
172
+ AntiPattern(
173
+ pattern_type="code_duplication",
174
+ severity=Priority.MEDIUM,
175
+ file_path=str(file_path),
176
+ line_number=line_numbers[0],
177
+ description=f"Line appears {len(line_numbers)} times: '{line_content[:50]}...'",
178
+ suggestion="Extract common functionality to a utility function",
179
+ prevention_strategy="extract_utility",
180
+ )
181
+ )
182
+
183
+ return anti_patterns
184
+
185
+ async def _detect_performance_issues(
186
+ self, file_path: Path, content: str, tree: ast.AST
187
+ ) -> list[AntiPattern]:
188
+ anti_patterns = []
189
+
190
+ class PerformanceVisitor(ast.NodeVisitor):
191
+ def __init__(self) -> None:
192
+ self.issues: list[tuple[int, str, str]] = []
193
+
194
+ def visit_For(self, node: ast.For) -> None:
195
+ for child in ast.walk(node.body[0] if node.body else node):
196
+ if isinstance(child, ast.For | ast.While) and child != node:
197
+ self.issues.append(
198
+ (
199
+ node.lineno,
200
+ "Nested loop detected-potential O(n²) complexity",
201
+ "Consider using dictionary lookups or set[t.Any] operations",
202
+ )
203
+ )
204
+ break
205
+
206
+ for stmt in node.body:
207
+ if (
208
+ isinstance(stmt, ast.AugAssign)
209
+ and isinstance(stmt.op, ast.Add)
210
+ and isinstance(stmt.target, ast.Name)
211
+ ):
212
+ self.issues.append(
213
+ (
214
+ stmt.lineno,
215
+ "List concatenation in loop-inefficient",
216
+ "Use list[t.Any].append() and join at the end",
217
+ )
218
+ )
219
+
220
+ self.generic_visit(node)
221
+
222
+ visitor = PerformanceVisitor()
223
+ visitor.visit(tree)
224
+
225
+ for line_no, description, suggestion in visitor.issues:
226
+ anti_patterns.append(
227
+ AntiPattern(
228
+ pattern_type="performance_issues",
229
+ severity=Priority.MEDIUM,
230
+ file_path=str(file_path),
231
+ line_number=line_no,
232
+ description=description,
233
+ suggestion=suggestion,
234
+ prevention_strategy="optimize_algorithm",
235
+ )
236
+ )
237
+
238
+ return anti_patterns
239
+
240
+ async def _detect_security_risks(
241
+ self, file_path: Path, content: str, tree: ast.AST
242
+ ) -> list[AntiPattern]:
243
+ anti_patterns = []
244
+
245
+ hardcoded_path_patterns = self._check_hardcoded_paths(file_path, content)
246
+ anti_patterns.extend(hardcoded_path_patterns)
247
+
248
+ subprocess_patterns = self._check_subprocess_security(file_path, tree)
249
+ anti_patterns.extend(subprocess_patterns)
250
+
251
+ return anti_patterns
252
+
253
+ def _check_hardcoded_paths(
254
+ self, file_path: Path, content: str
255
+ ) -> list[AntiPattern]:
256
+ anti_patterns = []
257
+
258
+ if "/tmp/" in content or "C: \\" in content: # nosec B108
259
+ lines = content.split("\n")
260
+ for i, line in enumerate(lines, 1):
261
+ if "/tmp/" in line or "C: \\" in line: # nosec B108
262
+ anti_patterns.append(
263
+ AntiPattern(
264
+ pattern_type="security_risks",
265
+ severity=Priority.HIGH,
266
+ file_path=str(file_path),
267
+ line_number=i,
268
+ description="Hardcoded path detected-potential security risk",
269
+ suggestion="Use tempfile module for temporary files",
270
+ prevention_strategy="use_secure_temp_files",
271
+ )
272
+ )
273
+ break
274
+
275
+ return anti_patterns
276
+
277
+ def _check_subprocess_security(
278
+ self, file_path: Path, tree: ast.AST
279
+ ) -> list[AntiPattern]:
280
+ anti_patterns = []
281
+
282
+ class SecurityVisitor(ast.NodeVisitor):
283
+ def __init__(self) -> None:
284
+ self.issues: list[tuple[int, str, str]] = []
285
+
286
+ def visit_Call(self, node: ast.Call) -> None:
287
+ if (
288
+ isinstance(node.func, ast.Attribute)
289
+ and isinstance(node.func.value, ast.Name)
290
+ and node.func.value.id == "subprocess"
291
+ ):
292
+ for keyword in node.keywords:
293
+ if (
294
+ keyword.arg == "shell"
295
+ and isinstance(keyword.value, ast.Constant)
296
+ and keyword.value.value is True
297
+ ):
298
+ self.issues.append(
299
+ (
300
+ node.lineno,
301
+ "subprocess with shell=True-security risk",
302
+ "Avoid shell=True or validate inputs carefully",
303
+ )
304
+ )
305
+
306
+ self.generic_visit(node)
307
+
308
+ visitor = SecurityVisitor()
309
+ visitor.visit(tree)
310
+
311
+ for line_no, description, suggestion in visitor.issues:
312
+ anti_patterns.append(
313
+ AntiPattern(
314
+ pattern_type="security_risks",
315
+ severity=Priority.HIGH,
316
+ file_path=str(file_path),
317
+ line_number=line_no,
318
+ description=description,
319
+ suggestion=suggestion,
320
+ prevention_strategy="secure_subprocess",
321
+ )
322
+ )
323
+
324
+ return anti_patterns
325
+
326
+ async def _detect_import_complexity(
327
+ self, file_path: Path, content: str, tree: ast.AST
328
+ ) -> list[AntiPattern]:
329
+ anti_patterns = []
330
+
331
+ class ImportVisitor(ast.NodeVisitor):
332
+ def __init__(self) -> None:
333
+ self.imports: list[tuple[int, str]] = []
334
+ self.import_count = 0
335
+
336
+ def visit_Import(self, node: ast.Import) -> None:
337
+ self.import_count += len(node.names)
338
+ for alias in node.names:
339
+ if alias.name.count(".") > 2:
340
+ self.imports.append((node.lineno, f"Deep import: {alias.name}"))
341
+ self.generic_visit(node)
342
+
343
+ def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
344
+ if node.module:
345
+ self.import_count += len(node.names) if node.names else 1
346
+ if node.names and len(node.names) > 10:
347
+ self.imports.append(
348
+ (node.lineno, f"Many imports from {node.module}")
349
+ )
350
+ self.generic_visit(node)
351
+
352
+ visitor = ImportVisitor()
353
+ visitor.visit(tree)
354
+
355
+ if visitor.import_count > 50:
356
+ anti_patterns.append(
357
+ AntiPattern(
358
+ pattern_type="import_complexity",
359
+ severity=Priority.MEDIUM,
360
+ file_path=str(file_path),
361
+ line_number=1,
362
+ description=f"File has {visitor.import_count} imports-may indicate tight coupling",
363
+ suggestion="Consider breaking file into smaller modules",
364
+ prevention_strategy="modular_design",
365
+ )
366
+ )
367
+
368
+ for line_no, description in visitor.imports:
369
+ anti_patterns.append(
370
+ AntiPattern(
371
+ pattern_type="import_complexity",
372
+ severity=Priority.LOW,
373
+ file_path=str(file_path),
374
+ line_number=line_no,
375
+ description=description,
376
+ suggestion="Simplify import structure",
377
+ prevention_strategy="clean_imports",
378
+ )
379
+ )
380
+
381
+ return anti_patterns
382
+
383
+ def _should_skip_file(self, file_path: Path) -> bool:
384
+ skip_patterns = [
385
+ "__pycache__",
386
+ ".git",
387
+ ".venv",
388
+ "venv",
389
+ ".tox",
390
+ "build",
391
+ "dist",
392
+ ".pytest_cache",
393
+ "node_modules",
394
+ ]
395
+
396
+ path_str = str(file_path)
397
+ return any(pattern in path_str for pattern in skip_patterns)
398
+
399
+ async def suggest_proactive_refactoring(
400
+ self, anti_patterns: list[AntiPattern]
401
+ ) -> list[Issue]:
402
+ issues = []
403
+
404
+ for anti_pattern in anti_patterns:
405
+ issue_type_map = {
406
+ "complexity_hotspot": IssueType.COMPLEXITY,
407
+ "code_duplication": IssueType.DRY_VIOLATION,
408
+ "performance_issues": IssueType.PERFORMANCE,
409
+ "security_risks": IssueType.SECURITY,
410
+ "import_complexity": IssueType.IMPORT_ERROR,
411
+ }
412
+
413
+ issue_type = issue_type_map.get(
414
+ anti_pattern.pattern_type, IssueType.FORMATTING
415
+ )
416
+
417
+ issue = Issue(
418
+ id=f"proactive_{anti_pattern.pattern_type}_{hash(anti_pattern.file_path + str(anti_pattern.line_number))}",
419
+ type=issue_type,
420
+ severity=anti_pattern.severity,
421
+ message=f"Proactive: {anti_pattern.description}",
422
+ file_path=anti_pattern.file_path,
423
+ line_number=anti_pattern.line_number,
424
+ details=[
425
+ anti_pattern.suggestion,
426
+ f"Prevention strategy: {anti_pattern.prevention_strategy}",
427
+ ],
428
+ stage="proactive_analysis",
429
+ )
430
+
431
+ issues.append(issue)
432
+
433
+ return issues
434
+
435
+ async def get_cached_solutions(
436
+ self, anti_patterns: list[AntiPattern]
437
+ ) -> dict[str, CachedPattern]:
438
+ solutions = {}
439
+
440
+ for anti_pattern in anti_patterns:
441
+ solution_key = self._generate_solution_key(anti_pattern)
442
+ cached_pattern = self._find_cached_pattern_for_anti_pattern(anti_pattern)
443
+
444
+ if cached_pattern:
445
+ solutions[solution_key] = cached_pattern
446
+
447
+ return solutions
448
+
449
+ def _generate_solution_key(self, anti_pattern: AntiPattern) -> str:
450
+ return f"{anti_pattern.pattern_type}_{anti_pattern.file_path}_{anti_pattern.line_number}"
451
+
452
+ def _find_cached_pattern_for_anti_pattern(
453
+ self, anti_pattern: AntiPattern
454
+ ) -> CachedPattern | None:
455
+ issue_type = self._map_anti_pattern_to_issue_type(anti_pattern.pattern_type)
456
+ if not issue_type:
457
+ return None
458
+
459
+ temp_issue = self._create_temp_issue_for_lookup(anti_pattern, issue_type)
460
+ return self.pattern_cache.get_best_pattern_for_issue(temp_issue)
461
+
462
+ def _map_anti_pattern_to_issue_type(self, pattern_type: str) -> IssueType | None:
463
+ return {
464
+ "complexity_hotspot": IssueType.COMPLEXITY,
465
+ "code_duplication": IssueType.DRY_VIOLATION,
466
+ "performance_issues": IssueType.PERFORMANCE,
467
+ "security_risks": IssueType.SECURITY,
468
+ }.get(pattern_type)
469
+
470
+ def _create_temp_issue_for_lookup(
471
+ self, anti_pattern: AntiPattern, issue_type: IssueType
472
+ ) -> Issue:
473
+ return Issue(
474
+ id="temp",
475
+ type=issue_type,
476
+ severity=anti_pattern.severity,
477
+ message=anti_pattern.description,
478
+ file_path=anti_pattern.file_path,
479
+ )