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,380 @@
1
+ """Incremental execution with intelligent caching.
2
+
3
+ Phase 10.3.2: Implements file hash tracking and persistent caching to skip
4
+ unchanged files and reuse previous results.
5
+ """
6
+
7
+ import hashlib
8
+ import json
9
+ from collections.abc import Callable
10
+ from contextlib import suppress
11
+ from dataclasses import dataclass, field
12
+ from pathlib import Path
13
+ from typing import Any
14
+
15
+ from crackerjack.services.profiler import ToolProfiler
16
+
17
+
18
+ @dataclass
19
+ class FileHash:
20
+ """File hash metadata."""
21
+
22
+ path: str
23
+ hash: str
24
+ size: int
25
+ modified_time: float
26
+
27
+
28
+ @dataclass
29
+ class CacheEntry:
30
+ """Cached execution result."""
31
+
32
+ tool_name: str
33
+ file_hash: FileHash
34
+ result: Any
35
+ timestamp: float
36
+ success: bool
37
+ error_message: str | None = None
38
+
39
+
40
+ @dataclass
41
+ class ExecutionResult:
42
+ """Result of incremental execution."""
43
+
44
+ tool_name: str
45
+ files_processed: int
46
+ files_cached: int
47
+ files_changed: int
48
+ cache_hit_rate: float
49
+ execution_time: float
50
+ results: dict[str, Any] = field(default_factory=dict)
51
+
52
+ @property
53
+ def cache_effective(self) -> bool:
54
+ """Whether caching was effective (>50% hit rate)."""
55
+ return self.cache_hit_rate >= 50.0
56
+
57
+
58
+ class IncrementalExecutor:
59
+ """Executes tools incrementally with intelligent caching."""
60
+
61
+ def __init__(
62
+ self,
63
+ cache_dir: Path | None = None,
64
+ ttl_seconds: int = 86400, # 24 hours
65
+ profiler: ToolProfiler | None = None,
66
+ ):
67
+ """Initialize incremental executor.
68
+
69
+ Args:
70
+ cache_dir: Directory for cache storage
71
+ ttl_seconds: Time-to-live for cache entries (default: 24 hours)
72
+ profiler: Optional profiler for performance tracking
73
+ """
74
+ self.cache_dir = cache_dir or Path.cwd() / ".crackerjack" / "cache"
75
+ self.cache_dir.mkdir(parents=True, exist_ok=True)
76
+ self.ttl_seconds = ttl_seconds
77
+ self.profiler = profiler
78
+ self._cache: dict[str, CacheEntry] = {}
79
+ self._file_hashes: dict[str, FileHash] = {}
80
+ self._load_cache()
81
+
82
+ def _compute_file_hash(self, file_path: Path) -> FileHash:
83
+ """Compute hash for a file.
84
+
85
+ Args:
86
+ file_path: Path to file
87
+
88
+ Returns:
89
+ FileHash with metadata
90
+ """
91
+ try:
92
+ content = file_path.read_bytes()
93
+ hash_value = hashlib.sha256(content).hexdigest()
94
+ stat = file_path.stat()
95
+
96
+ return FileHash(
97
+ path=str(file_path),
98
+ hash=hash_value,
99
+ size=stat.st_size,
100
+ modified_time=stat.st_mtime,
101
+ )
102
+ except OSError:
103
+ # Return empty hash for files that can't be read
104
+ return FileHash(
105
+ path=str(file_path),
106
+ hash="",
107
+ size=0,
108
+ modified_time=0.0,
109
+ )
110
+
111
+ def _cache_key(self, tool_name: str, file_hash: FileHash) -> str:
112
+ """Generate cache key.
113
+
114
+ Args:
115
+ tool_name: Name of the tool
116
+ file_hash: File hash metadata
117
+
118
+ Returns:
119
+ Cache key string
120
+ """
121
+ return f"{tool_name}:{file_hash.hash}"
122
+
123
+ def _load_cache(self) -> None:
124
+ """Load cache from disk."""
125
+ cache_file = self.cache_dir / "incremental_cache.json"
126
+ if not cache_file.exists():
127
+ return
128
+
129
+ try:
130
+ data = json.loads(cache_file.read_text())
131
+ import time
132
+
133
+ current_time = time.time()
134
+
135
+ for entry_data in data.get("entries", []):
136
+ # Skip expired entries
137
+ if current_time - entry_data["timestamp"] > self.ttl_seconds:
138
+ continue
139
+
140
+ file_hash = FileHash(**entry_data["file_hash"])
141
+ entry = CacheEntry(
142
+ tool_name=entry_data["tool_name"],
143
+ file_hash=file_hash,
144
+ result=entry_data["result"],
145
+ timestamp=entry_data["timestamp"],
146
+ success=entry_data["success"],
147
+ error_message=entry_data.get("error_message"),
148
+ )
149
+
150
+ key = self._cache_key(entry.tool_name, file_hash)
151
+ self._cache[key] = entry
152
+ except (json.JSONDecodeError, KeyError, OSError):
153
+ # Corrupted cache - start fresh
154
+ self._cache = {}
155
+
156
+ def _save_cache(self) -> None:
157
+ """Save cache to disk."""
158
+ cache_file = self.cache_dir / "incremental_cache.json"
159
+
160
+ data = {
161
+ "entries": [
162
+ {
163
+ "tool_name": entry.tool_name,
164
+ "file_hash": {
165
+ "path": entry.file_hash.path,
166
+ "hash": entry.file_hash.hash,
167
+ "size": entry.file_hash.size,
168
+ "modified_time": entry.file_hash.modified_time,
169
+ },
170
+ "result": entry.result,
171
+ "timestamp": entry.timestamp,
172
+ "success": entry.success,
173
+ "error_message": entry.error_message,
174
+ }
175
+ for entry in self._cache.values()
176
+ ]
177
+ }
178
+
179
+ with suppress(OSError):
180
+ cache_file.write_text(json.dumps(data, indent=2))
181
+
182
+ def execute_incremental(
183
+ self,
184
+ tool_name: str,
185
+ files: list[Path],
186
+ tool_func: Callable[[Path], Any],
187
+ force_rerun: bool = False,
188
+ ) -> ExecutionResult:
189
+ """Execute tool incrementally with caching.
190
+
191
+ Args:
192
+ tool_name: Name of the tool
193
+ files: List of files to process
194
+ tool_func: Function to execute on each file
195
+ force_rerun: Skip cache and rerun all files
196
+
197
+ Returns:
198
+ ExecutionResult with statistics
199
+ """
200
+ import time
201
+
202
+ start_time = time.perf_counter()
203
+
204
+ files_cached = 0
205
+ files_changed = 0
206
+ results: dict[str, Any] = {}
207
+
208
+ for file_path in files:
209
+ # Compute current hash
210
+ current_hash = self._compute_file_hash(file_path)
211
+ cache_key = self._cache_key(tool_name, current_hash)
212
+
213
+ # Check cache
214
+ if not force_rerun and cache_key in self._cache:
215
+ cached_entry = self._cache[cache_key]
216
+ results[str(file_path)] = cached_entry.result
217
+ files_cached += 1
218
+
219
+ # Update profiler cache stats
220
+ if self.profiler and tool_name in self.profiler.results:
221
+ self.profiler.results[tool_name].cache_hits += 1
222
+ else:
223
+ # Execute tool
224
+ try:
225
+ result = tool_func(file_path)
226
+ success = True
227
+ error_msg = None
228
+ except Exception as e:
229
+ result = None
230
+ success = False
231
+ error_msg = str(e)
232
+
233
+ results[str(file_path)] = result
234
+ files_changed += 1
235
+
236
+ # Update profiler cache stats
237
+ if self.profiler and tool_name in self.profiler.results:
238
+ self.profiler.results[tool_name].cache_misses += 1
239
+
240
+ # Store in cache
241
+ entry = CacheEntry(
242
+ tool_name=tool_name,
243
+ file_hash=current_hash,
244
+ result=result,
245
+ timestamp=time.time(),
246
+ success=success,
247
+ error_message=error_msg,
248
+ )
249
+ self._cache[cache_key] = entry
250
+
251
+ # Calculate statistics
252
+ total_files = len(files)
253
+ cache_hit_rate = (files_cached / total_files * 100) if total_files > 0 else 0.0
254
+ execution_time = time.perf_counter() - start_time
255
+
256
+ # Save cache
257
+ self._save_cache()
258
+
259
+ return ExecutionResult(
260
+ tool_name=tool_name,
261
+ files_processed=total_files,
262
+ files_cached=files_cached,
263
+ files_changed=files_changed,
264
+ cache_hit_rate=cache_hit_rate,
265
+ execution_time=execution_time,
266
+ results=results,
267
+ )
268
+
269
+ def get_changed_files(
270
+ self,
271
+ tool_name: str,
272
+ files: list[Path],
273
+ ) -> list[Path]:
274
+ """Get list of files that have changed since last execution.
275
+
276
+ Args:
277
+ tool_name: Name of the tool
278
+ files: List of files to check
279
+
280
+ Returns:
281
+ List of changed files
282
+ """
283
+ changed_files: list[Path] = []
284
+
285
+ for file_path in files:
286
+ current_hash = self._compute_file_hash(file_path)
287
+ cache_key = self._cache_key(tool_name, current_hash)
288
+
289
+ # If not in cache or hash differs, it's changed
290
+ if cache_key not in self._cache:
291
+ changed_files.append(file_path)
292
+
293
+ return changed_files
294
+
295
+ def invalidate_file(self, file_path: Path) -> int:
296
+ """Invalidate all cache entries for a file.
297
+
298
+ Args:
299
+ file_path: Path to file
300
+
301
+ Returns:
302
+ Number of entries invalidated
303
+ """
304
+ file_str = str(file_path)
305
+ invalidated = 0
306
+
307
+ # Remove all cache entries for this file
308
+ keys_to_remove = [
309
+ key
310
+ for key, entry in self._cache.items()
311
+ if entry.file_hash.path == file_str
312
+ ]
313
+
314
+ for key in keys_to_remove:
315
+ del self._cache[key]
316
+ invalidated += 1
317
+
318
+ if invalidated > 0:
319
+ self._save_cache()
320
+
321
+ return invalidated
322
+
323
+ def clear_cache(self, tool_name: str | None = None) -> int:
324
+ """Clear cache entries.
325
+
326
+ Args:
327
+ tool_name: Optional tool name to clear (clears all if None)
328
+
329
+ Returns:
330
+ Number of entries cleared
331
+ """
332
+ if tool_name is None:
333
+ # Clear all
334
+ count = len(self._cache)
335
+ self._cache = {}
336
+ else:
337
+ # Clear specific tool
338
+ keys_to_remove = [
339
+ key
340
+ for key, entry in self._cache.items()
341
+ if entry.tool_name == tool_name
342
+ ]
343
+ count = len(keys_to_remove)
344
+ for key in keys_to_remove:
345
+ del self._cache[key]
346
+
347
+ if count > 0:
348
+ self._save_cache()
349
+
350
+ return count
351
+
352
+ def get_cache_stats(self) -> dict[str, Any]:
353
+ """Get cache statistics.
354
+
355
+ Returns:
356
+ Dictionary with cache statistics
357
+ """
358
+ total_entries = len(self._cache)
359
+ tools = {entry.tool_name for entry in self._cache.values()}
360
+ success_count = sum(1 for entry in self._cache.values() if entry.success)
361
+
362
+ return {
363
+ "total_entries": total_entries,
364
+ "unique_tools": len(tools),
365
+ "success_rate": (success_count / total_entries * 100)
366
+ if total_entries > 0
367
+ else 0.0,
368
+ "cache_size_mb": self._estimate_cache_size(),
369
+ }
370
+
371
+ def _estimate_cache_size(self) -> float:
372
+ """Estimate cache size in MB.
373
+
374
+ Returns:
375
+ Estimated size in megabytes
376
+ """
377
+ cache_file = self.cache_dir / "incremental_cache.json"
378
+ if cache_file.exists():
379
+ return cache_file.stat().st_size / 1024 / 1024
380
+ return 0.0
@@ -5,7 +5,8 @@ from pathlib import Path
5
5
 
6
6
  import tomli
7
7
  import yaml
8
- from rich.console import Console
8
+ from acb.console import Console
9
+ from acb.depends import Inject, depends
9
10
 
10
11
  from crackerjack.models.protocols import ConfigMergeServiceProtocol
11
12
 
@@ -16,9 +17,10 @@ from .input_validator import get_input_validator, validate_and_sanitize_path
16
17
 
17
18
 
18
19
  class InitializationService:
20
+ @depends.inject
19
21
  def __init__(
20
22
  self,
21
- console: Console,
23
+ console: Inject[Console],
22
24
  filesystem: FileSystemService,
23
25
  git_service: GitService,
24
26
  pkg_path: Path,
@@ -30,7 +32,7 @@ class InitializationService:
30
32
  self.pkg_path = pkg_path
31
33
 
32
34
  self.config_merge_service = config_merge_service or ConfigMergeService(
33
- console, filesystem, git_service
35
+ filesystem, git_service
34
36
  )
35
37
 
36
38
  def initialize_project(self, project_path: str | Path) -> bool:
@@ -116,8 +118,8 @@ class InitializationService:
116
118
  }
117
119
 
118
120
  def _get_config_files(self) -> dict[str, str]:
121
+ # Skip pre-commit configuration to prevent hook installation
119
122
  return {
120
- ".pre-commit-config.yaml": "smart_merge",
121
123
  "pyproject.toml": "smart_merge",
122
124
  ".gitignore": "smart_merge_gitignore",
123
125
  "CLAUDE.md": "smart_append",
@@ -125,6 +127,92 @@ class InitializationService:
125
127
  "example.mcp.json": "special",
126
128
  }
127
129
 
130
+ def _apply_merge_strategy(
131
+ self,
132
+ merge_strategy: str,
133
+ source_file: Path,
134
+ target_file: Path,
135
+ file_name: str,
136
+ project_name: str,
137
+ force: bool,
138
+ results: dict[str, t.Any],
139
+ ) -> None:
140
+ """Apply the appropriate merge strategy for the config file."""
141
+ if merge_strategy == "smart_merge":
142
+ self._smart_merge_config(
143
+ source_file,
144
+ target_file,
145
+ file_name,
146
+ project_name,
147
+ force,
148
+ results,
149
+ )
150
+ elif merge_strategy == "smart_merge_gitignore":
151
+ self._smart_merge_gitignore(
152
+ target_file,
153
+ project_name,
154
+ force,
155
+ results,
156
+ )
157
+ elif merge_strategy == "smart_append":
158
+ self._smart_append_config(
159
+ source_file,
160
+ target_file,
161
+ file_name,
162
+ project_name,
163
+ force,
164
+ results,
165
+ )
166
+ elif merge_strategy == "replace_if_missing":
167
+ self._handle_replace_if_missing(
168
+ source_file,
169
+ target_file,
170
+ file_name,
171
+ project_name,
172
+ force,
173
+ results,
174
+ )
175
+ else:
176
+ self._handle_default_strategy(
177
+ source_file,
178
+ target_file,
179
+ file_name,
180
+ project_name,
181
+ force,
182
+ results,
183
+ )
184
+
185
+ def _handle_replace_if_missing(
186
+ self,
187
+ source_file: Path,
188
+ target_file: Path,
189
+ file_name: str,
190
+ project_name: str,
191
+ force: bool,
192
+ results: dict[str, t.Any],
193
+ ) -> None:
194
+ """Handle replace_if_missing strategy."""
195
+ if not target_file.exists() or force:
196
+ content = self._read_and_process_content(source_file, True, project_name)
197
+ self._write_file_and_track(target_file, content, file_name, results)
198
+ else:
199
+ self._skip_existing_file(file_name, results)
200
+
201
+ def _handle_default_strategy(
202
+ self,
203
+ source_file: Path,
204
+ target_file: Path,
205
+ file_name: str,
206
+ project_name: str,
207
+ force: bool,
208
+ results: dict[str, t.Any],
209
+ ) -> None:
210
+ """Handle default copy strategy."""
211
+ if not self._should_copy_file(target_file, force, file_name, results):
212
+ return
213
+ content = self._read_and_process_content(source_file, True, project_name)
214
+ self._write_file_and_track(target_file, content, file_name, results)
215
+
128
216
  def _process_config_file(
129
217
  self,
130
218
  file_name: str,
@@ -148,51 +236,15 @@ class InitializationService:
148
236
  return
149
237
 
150
238
  try:
151
- if merge_strategy == "smart_merge":
152
- self._smart_merge_config(
153
- source_file,
154
- target_file,
155
- file_name,
156
- project_name,
157
- force,
158
- results,
159
- )
160
- elif merge_strategy == "smart_merge_gitignore":
161
- self._smart_merge_gitignore(
162
- target_file,
163
- project_name,
164
- force,
165
- results,
166
- )
167
- elif merge_strategy == "smart_append":
168
- self._smart_append_config(
169
- source_file,
170
- target_file,
171
- file_name,
172
- project_name,
173
- force,
174
- results,
175
- )
176
- elif merge_strategy == "replace_if_missing":
177
- if not target_file.exists() or force:
178
- content = self._read_and_process_content(
179
- source_file,
180
- True,
181
- project_name,
182
- )
183
- self._write_file_and_track(target_file, content, file_name, results)
184
- else:
185
- self._skip_existing_file(file_name, results)
186
- else:
187
- if not self._should_copy_file(target_file, force, file_name, results):
188
- return
189
- content = self._read_and_process_content(
190
- source_file,
191
- True,
192
- project_name,
193
- )
194
- self._write_file_and_track(target_file, content, file_name, results)
195
-
239
+ self._apply_merge_strategy(
240
+ merge_strategy,
241
+ source_file,
242
+ target_file,
243
+ file_name,
244
+ project_name,
245
+ force,
246
+ results,
247
+ )
196
248
  except Exception as e:
197
249
  self._handle_file_processing_error(file_name, e, results)
198
250
 
@@ -6,9 +6,9 @@ import typing as t
6
6
  from contextlib import suppress
7
7
  from pathlib import Path
8
8
 
9
- from rich.console import Console
9
+ from acb import console
10
10
 
11
- console = Console()
11
+ # console imported from acb
12
12
 
13
13
 
14
14
  class LogManager: