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,338 @@
1
+ """In-memory LRU cache adapter for testing and development.
2
+
3
+ Provides a simple in-memory cache with LRU eviction for testing orchestration
4
+ without persisting to disk. Useful for unit tests and development workflows.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import hashlib
10
+ import json
11
+ import logging
12
+ import typing as t
13
+ from collections import OrderedDict
14
+ from contextlib import suppress
15
+ from pathlib import Path
16
+ from uuid import UUID
17
+
18
+ from pydantic import BaseModel, Field
19
+
20
+ from crackerjack.models.task import HookResult
21
+
22
+ if t.TYPE_CHECKING:
23
+ from crackerjack.config.hooks import HookDefinition
24
+
25
+ # ACB Module Registration (REQUIRED)
26
+ MODULE_ID = UUID("01937d86-ace0-7000-8000-000000000005") # Static UUID7
27
+ MODULE_STATUS = "stable"
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class MemoryCacheSettings(BaseModel):
33
+ """Settings for in-memory cache adapter."""
34
+
35
+ max_entries: int = Field(default=100, ge=10, le=1000)
36
+ default_ttl: int = Field(default=3600, ge=60, le=86400)
37
+
38
+
39
+ class MemoryCacheAdapter:
40
+ """In-memory LRU cache adapter for testing.
41
+
42
+ Features:
43
+ - LRU eviction when max_entries reached
44
+ - TTL-based expiration
45
+ - No disk persistence (ephemeral)
46
+ - Thread-safe operations
47
+
48
+ Use Cases:
49
+ - Unit testing orchestration without disk I/O
50
+ - Development workflows requiring fast cache
51
+ - CI/CD pipelines with ephemeral environments
52
+
53
+ Example:
54
+ ```python
55
+ cache = MemoryCacheAdapter(settings=MemoryCacheSettings(max_entries=50))
56
+ await cache.init()
57
+
58
+ # Cache operations work identically to ToolProxyCacheAdapter
59
+ result = await cache.get(key)
60
+ if not result:
61
+ result = await execute_hook(hook)
62
+ await cache.set(key, result)
63
+ ```
64
+ """
65
+
66
+ def __init__(
67
+ self,
68
+ settings: MemoryCacheSettings | None = None,
69
+ ) -> None:
70
+ """Initialize in-memory cache adapter.
71
+
72
+ Args:
73
+ settings: Optional cache settings
74
+ """
75
+ self.settings = settings or MemoryCacheSettings()
76
+ self._cache: OrderedDict[str, tuple[HookResult, float]] = OrderedDict()
77
+ self._initialized = False
78
+
79
+ logger.debug(
80
+ "MemoryCacheAdapter initializing",
81
+ extra={
82
+ "max_entries": self.settings.max_entries,
83
+ "default_ttl": self.settings.default_ttl,
84
+ },
85
+ )
86
+
87
+ async def init(self) -> None:
88
+ """Initialize cache adapter (no-op for memory cache)."""
89
+ if self._initialized:
90
+ logger.debug("Memory cache already initialized")
91
+ return
92
+
93
+ self._initialized = True
94
+
95
+ logger.info(
96
+ "MemoryCacheAdapter initialized",
97
+ extra={
98
+ "max_entries": self.settings.max_entries,
99
+ "default_ttl": self.settings.default_ttl,
100
+ },
101
+ )
102
+
103
+ async def get(self, key: str) -> HookResult | None:
104
+ """Retrieve cached hook result.
105
+
106
+ Args:
107
+ key: Cache key
108
+
109
+ Returns:
110
+ Cached HookResult if found and not expired, None otherwise
111
+ """
112
+ if not self._initialized:
113
+ logger.warning("Memory cache not initialized, returning None")
114
+ return None
115
+
116
+ try:
117
+ import time
118
+
119
+ if key in self._cache:
120
+ result, expiry = self._cache[key]
121
+
122
+ # Check expiration
123
+ if time.time() < expiry:
124
+ # Move to end (LRU update)
125
+ self._cache.move_to_end(key)
126
+
127
+ logger.debug(
128
+ "Cache hit",
129
+ extra={
130
+ "key": key,
131
+ "hook_name": result.name,
132
+ "status": result.status,
133
+ },
134
+ )
135
+ return result
136
+ else:
137
+ # Expired - remove from cache
138
+ del self._cache[key]
139
+ logger.debug("Cache entry expired", extra={"key": key})
140
+
141
+ logger.debug("Cache miss", extra={"key": key})
142
+ return None
143
+
144
+ except Exception as e:
145
+ logger.error(
146
+ "Failed to retrieve from cache",
147
+ extra={
148
+ "key": key,
149
+ "error": str(e),
150
+ },
151
+ )
152
+ return None
153
+
154
+ async def set(
155
+ self,
156
+ key: str,
157
+ result: HookResult,
158
+ ttl: int | None = None,
159
+ ) -> None:
160
+ """Cache hook result with TTL and LRU eviction.
161
+
162
+ Args:
163
+ key: Cache key
164
+ result: HookResult to cache
165
+ ttl: Optional time-to-live in seconds
166
+ """
167
+ if not self._initialized:
168
+ logger.warning("Memory cache not initialized, skipping cache write")
169
+ return
170
+
171
+ try:
172
+ import time
173
+
174
+ ttl_sec = ttl or self.settings.default_ttl
175
+ expiry = time.time() + ttl_sec
176
+
177
+ # LRU eviction if at capacity
178
+ if len(self._cache) >= self.settings.max_entries and key not in self._cache:
179
+ # Remove oldest entry (first item in OrderedDict)
180
+ evicted_key, _ = self._cache.popitem(last=False)
181
+ logger.debug(
182
+ "LRU eviction",
183
+ extra={
184
+ "evicted_key": evicted_key,
185
+ "cache_size": len(self._cache),
186
+ },
187
+ )
188
+
189
+ self._cache[key] = (result, expiry)
190
+ # Move to end (most recently used)
191
+ self._cache.move_to_end(key)
192
+
193
+ logger.debug(
194
+ "Cache write",
195
+ extra={
196
+ "key": key,
197
+ "hook_name": result.name,
198
+ "status": result.status,
199
+ "ttl": ttl_sec,
200
+ "cache_size": len(self._cache),
201
+ },
202
+ )
203
+
204
+ except Exception as e:
205
+ logger.error(
206
+ "Failed to write to cache",
207
+ extra={
208
+ "key": key,
209
+ "error": str(e),
210
+ },
211
+ )
212
+
213
+ def compute_key(
214
+ self,
215
+ hook: HookDefinition,
216
+ files: list[Path],
217
+ ) -> str:
218
+ """Compute content-based cache key.
219
+
220
+ Uses same algorithm as ToolProxyCacheAdapter for consistency.
221
+
222
+ Args:
223
+ hook: Hook definition
224
+ files: List of files to be checked by hook
225
+
226
+ Returns:
227
+ Cache key string
228
+ """
229
+ try:
230
+ # Hash hook configuration (Phase 8+ direct invocation API)
231
+ config_data = {
232
+ "name": hook.name,
233
+ "command": hook.command, # Direct tool invocation command
234
+ "timeout": hook.timeout,
235
+ "stage": hook.stage.value
236
+ if hasattr(hook.stage, "value")
237
+ else str(hook.stage),
238
+ "security_level": hook.security_level.value
239
+ if hasattr(hook.security_level, "value")
240
+ else str(hook.security_level),
241
+ }
242
+ config_json = json.dumps(config_data, sort_keys=True)
243
+ config_hash = hashlib.sha256(config_json.encode()).hexdigest()[:16]
244
+
245
+ # Hash file contents
246
+ content_hasher = hashlib.sha256()
247
+ for file_path in sorted(files):
248
+ try:
249
+ if file_path.exists() and file_path.is_file():
250
+ content_hasher.update(file_path.read_bytes())
251
+ except Exception as e:
252
+ logger.warning(
253
+ f"Failed to hash file {file_path}: {e}",
254
+ extra={"file": str(file_path), "error": str(e)},
255
+ )
256
+ continue
257
+
258
+ content_hash = content_hasher.hexdigest()[:16]
259
+
260
+ cache_key = f"{hook.name}:{config_hash}:{content_hash}"
261
+
262
+ logger.debug(
263
+ "Cache key computed",
264
+ extra={
265
+ "hook_name": hook.name,
266
+ "file_count": len(files),
267
+ "config_hash": config_hash,
268
+ "content_hash": content_hash,
269
+ },
270
+ )
271
+
272
+ return cache_key
273
+
274
+ except Exception as e:
275
+ logger.error(
276
+ "Failed to compute cache key",
277
+ extra={
278
+ "hook_name": hook.name,
279
+ "error": str(e),
280
+ },
281
+ )
282
+ return f"{hook.name}:error"
283
+
284
+ async def clear(self) -> None:
285
+ """Clear all cached results."""
286
+ try:
287
+ self._cache.clear()
288
+ logger.info("Memory cache cleared")
289
+ except Exception as e:
290
+ logger.error("Failed to clear cache", extra={"error": str(e)})
291
+
292
+ async def get_stats(self) -> dict[str, t.Any]:
293
+ """Get cache statistics.
294
+
295
+ Returns:
296
+ Dictionary with cache statistics
297
+ """
298
+ import time
299
+
300
+ try:
301
+ total_entries = len(self._cache)
302
+ expired_entries = sum(
303
+ 1 for _, expiry in self._cache.values() if time.time() >= expiry
304
+ )
305
+ active_entries = total_entries - expired_entries
306
+
307
+ stats = {
308
+ "total_entries": total_entries,
309
+ "active_entries": active_entries,
310
+ "expired_entries": expired_entries,
311
+ "max_entries": self.settings.max_entries,
312
+ "default_ttl": self.settings.default_ttl,
313
+ }
314
+
315
+ logger.debug("Memory cache statistics", extra=stats)
316
+
317
+ return stats
318
+
319
+ except Exception as e:
320
+ logger.error("Failed to get cache statistics", extra={"error": str(e)})
321
+ return {}
322
+
323
+ @property
324
+ def module_id(self) -> UUID:
325
+ """Reference to module-level MODULE_ID."""
326
+ return MODULE_ID
327
+
328
+ @property
329
+ def adapter_name(self) -> str:
330
+ """Human-readable adapter name."""
331
+ return "MemoryCacheAdapter"
332
+
333
+
334
+ # ACB Registration (REQUIRED at module level)
335
+ with suppress(Exception):
336
+ from acb.depends import depends
337
+
338
+ depends.set(MemoryCacheAdapter)
@@ -0,0 +1,340 @@
1
+ """Tool proxy cache adapter for hook result caching.
2
+
3
+ Bridges to existing tool_proxy cache infrastructure for consistent caching
4
+ across the crackerjack ecosystem. Implements content-based cache keys using
5
+ hash of hook configuration and file contents.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import json
12
+ import logging
13
+ import typing as t
14
+ from contextlib import suppress
15
+ from pathlib import Path
16
+ from uuid import UUID
17
+
18
+ from pydantic import BaseModel, Field
19
+
20
+ from crackerjack.models.task import HookResult
21
+
22
+ if t.TYPE_CHECKING:
23
+ from crackerjack.config.hooks import HookDefinition
24
+
25
+ # ACB Module Registration (REQUIRED)
26
+ MODULE_ID = UUID("01937d86-ace0-7000-8000-000000000004") # Static UUID7
27
+ MODULE_STATUS = "stable"
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class ToolProxyCacheSettings(BaseModel):
33
+ """Settings for tool proxy cache adapter."""
34
+
35
+ default_ttl: int = Field(default=3600, ge=60, le=86400) # 1 minute to 24 hours
36
+ max_cache_size_mb: int = Field(default=100, ge=10, le=1000)
37
+ enable_compression: bool = True
38
+
39
+
40
+ class ToolProxyCacheAdapter:
41
+ """Cache adapter bridging to tool_proxy infrastructure.
42
+
43
+ Features:
44
+ - Content-based cache keys (config + file hashes)
45
+ - Configurable TTL per hook result
46
+ - Integration with existing tool_proxy cache
47
+ - Automatic cache invalidation on content changes
48
+
49
+ Cache Key Format:
50
+ {hook_name}:{config_hash}:{content_hash}
51
+
52
+ Example:
53
+ ```python
54
+ cache = ToolProxyCacheAdapter()
55
+ await cache.init()
56
+
57
+ # Check cache
58
+ cached_result = await cache.get(cache_key)
59
+ if cached_result:
60
+ return cached_result
61
+
62
+ # Execute hook and cache result
63
+ result = await execute_hook(hook)
64
+ await cache.set(cache_key, result, ttl=3600)
65
+ ```
66
+ """
67
+
68
+ def __init__(
69
+ self,
70
+ settings: ToolProxyCacheSettings | None = None,
71
+ cache_dir: Path | None = None,
72
+ ) -> None:
73
+ """Initialize tool proxy cache adapter.
74
+
75
+ Args:
76
+ settings: Optional cache settings
77
+ cache_dir: Optional cache directory (defaults to .crackerjack/cache)
78
+ """
79
+ self.settings = settings or ToolProxyCacheSettings()
80
+ self._cache_dir = cache_dir or Path.cwd() / ".crackerjack" / "cache"
81
+ self._cache: dict[
82
+ str, tuple[HookResult, float]
83
+ ] = {} # key -> (result, expiry_timestamp)
84
+ self._initialized = False
85
+
86
+ logger.debug(
87
+ "ToolProxyCacheAdapter initializing",
88
+ extra={
89
+ "cache_dir": str(self._cache_dir),
90
+ "default_ttl": self.settings.default_ttl,
91
+ "enable_compression": self.settings.enable_compression,
92
+ },
93
+ )
94
+
95
+ async def init(self) -> None:
96
+ """Initialize cache adapter and ensure cache directory exists."""
97
+ if self._initialized:
98
+ logger.debug("Cache adapter already initialized")
99
+ return
100
+
101
+ try:
102
+ self._cache_dir.mkdir(parents=True, exist_ok=True)
103
+ self._initialized = True
104
+
105
+ logger.info(
106
+ "ToolProxyCacheAdapter initialized",
107
+ extra={
108
+ "cache_dir": str(self._cache_dir),
109
+ "default_ttl": self.settings.default_ttl,
110
+ },
111
+ )
112
+ except Exception as e:
113
+ logger.error(
114
+ "Failed to initialize cache adapter",
115
+ extra={
116
+ "error": str(e),
117
+ "cache_dir": str(self._cache_dir),
118
+ },
119
+ )
120
+ raise
121
+
122
+ async def get(self, key: str) -> HookResult | None:
123
+ """Retrieve cached hook result.
124
+
125
+ Args:
126
+ key: Cache key (computed via compute_key())
127
+
128
+ Returns:
129
+ Cached HookResult if found and not expired, None otherwise
130
+ """
131
+ if not self._initialized:
132
+ logger.warning("Cache adapter not initialized, returning None")
133
+ return None
134
+
135
+ try:
136
+ import time
137
+
138
+ if key in self._cache:
139
+ result, expiry = self._cache[key]
140
+
141
+ # Check expiration
142
+ if time.time() < expiry:
143
+ logger.debug(
144
+ "Cache hit",
145
+ extra={
146
+ "key": key,
147
+ "hook_name": result.name,
148
+ "status": result.status,
149
+ },
150
+ )
151
+ return result
152
+ else:
153
+ # Expired - remove from cache
154
+ del self._cache[key]
155
+ logger.debug("Cache entry expired", extra={"key": key})
156
+
157
+ logger.debug("Cache miss", extra={"key": key})
158
+ return None
159
+
160
+ except Exception as e:
161
+ logger.error(
162
+ "Failed to retrieve from cache",
163
+ extra={
164
+ "key": key,
165
+ "error": str(e),
166
+ },
167
+ )
168
+ return None
169
+
170
+ async def set(
171
+ self,
172
+ key: str,
173
+ result: HookResult,
174
+ ttl: int | None = None,
175
+ ) -> None:
176
+ """Cache hook result with TTL.
177
+
178
+ Args:
179
+ key: Cache key (computed via compute_key())
180
+ result: HookResult to cache
181
+ ttl: Optional time-to-live in seconds (defaults to settings.default_ttl)
182
+ """
183
+ if not self._initialized:
184
+ logger.warning("Cache adapter not initialized, skipping cache write")
185
+ return
186
+
187
+ try:
188
+ import time
189
+
190
+ ttl_sec = ttl or self.settings.default_ttl
191
+ expiry = time.time() + ttl_sec
192
+
193
+ self._cache[key] = (result, expiry)
194
+
195
+ logger.debug(
196
+ "Cache write",
197
+ extra={
198
+ "key": key,
199
+ "hook_name": result.name,
200
+ "status": result.status,
201
+ "ttl": ttl_sec,
202
+ },
203
+ )
204
+
205
+ except Exception as e:
206
+ logger.error(
207
+ "Failed to write to cache",
208
+ extra={
209
+ "key": key,
210
+ "error": str(e),
211
+ },
212
+ )
213
+
214
+ def compute_key(
215
+ self,
216
+ hook: HookDefinition,
217
+ files: list[Path],
218
+ ) -> str:
219
+ """Compute content-based cache key.
220
+
221
+ Cache key format: {hook_name}:{config_hash}:{content_hash}
222
+
223
+ Args:
224
+ hook: Hook definition
225
+ files: List of files to be checked by hook
226
+
227
+ Returns:
228
+ Cache key string
229
+ """
230
+ try:
231
+ # Hash hook configuration (Phase 8+ direct invocation API)
232
+ config_data = {
233
+ "name": hook.name,
234
+ "command": hook.command, # Direct tool invocation command
235
+ "timeout": hook.timeout,
236
+ "stage": hook.stage.value
237
+ if hasattr(hook.stage, "value")
238
+ else str(hook.stage),
239
+ "security_level": hook.security_level.value
240
+ if hasattr(hook.security_level, "value")
241
+ else str(hook.security_level),
242
+ }
243
+ config_json = json.dumps(config_data, sort_keys=True)
244
+ config_hash = hashlib.sha256(config_json.encode()).hexdigest()[:16]
245
+
246
+ # Hash file contents (for cache invalidation on content changes)
247
+ content_hasher = hashlib.sha256()
248
+ for file_path in sorted(files):
249
+ try:
250
+ if file_path.exists() and file_path.is_file():
251
+ content_hasher.update(file_path.read_bytes())
252
+ except Exception as e:
253
+ logger.warning(
254
+ f"Failed to hash file {file_path}: {e}",
255
+ extra={"file": str(file_path), "error": str(e)},
256
+ )
257
+ continue
258
+
259
+ content_hash = content_hasher.hexdigest()[:16]
260
+
261
+ cache_key = f"{hook.name}:{config_hash}:{content_hash}"
262
+
263
+ logger.debug(
264
+ "Cache key computed",
265
+ extra={
266
+ "hook_name": hook.name,
267
+ "file_count": len(files),
268
+ "config_hash": config_hash,
269
+ "content_hash": content_hash,
270
+ },
271
+ )
272
+
273
+ return cache_key
274
+
275
+ except Exception as e:
276
+ logger.error(
277
+ "Failed to compute cache key",
278
+ extra={
279
+ "hook_name": hook.name,
280
+ "error": str(e),
281
+ },
282
+ )
283
+ # Fallback to simple key
284
+ return f"{hook.name}:error"
285
+
286
+ async def clear(self) -> None:
287
+ """Clear all cached results."""
288
+ try:
289
+ self._cache.clear()
290
+ logger.info("Cache cleared")
291
+ except Exception as e:
292
+ logger.error("Failed to clear cache", extra={"error": str(e)})
293
+
294
+ async def get_stats(self) -> dict[str, t.Any]:
295
+ """Get cache statistics.
296
+
297
+ Returns:
298
+ Dictionary with cache statistics
299
+ """
300
+ import time
301
+
302
+ try:
303
+ total_entries = len(self._cache)
304
+ expired_entries = sum(
305
+ 1 for _, expiry in self._cache.values() if time.time() >= expiry
306
+ )
307
+ active_entries = total_entries - expired_entries
308
+
309
+ stats = {
310
+ "total_entries": total_entries,
311
+ "active_entries": active_entries,
312
+ "expired_entries": expired_entries,
313
+ "cache_dir": str(self._cache_dir),
314
+ "default_ttl": self.settings.default_ttl,
315
+ }
316
+
317
+ logger.debug("Cache statistics", extra=stats)
318
+
319
+ return stats
320
+
321
+ except Exception as e:
322
+ logger.error("Failed to get cache statistics", extra={"error": str(e)})
323
+ return {}
324
+
325
+ @property
326
+ def module_id(self) -> UUID:
327
+ """Reference to module-level MODULE_ID."""
328
+ return MODULE_ID
329
+
330
+ @property
331
+ def adapter_name(self) -> str:
332
+ """Human-readable adapter name."""
333
+ return "ToolProxyCacheAdapter"
334
+
335
+
336
+ # ACB Registration (REQUIRED at module level)
337
+ with suppress(Exception):
338
+ from acb.depends import depends
339
+
340
+ depends.set(ToolProxyCacheAdapter)