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
@@ -4,9 +4,10 @@ import re
4
4
  from datetime import datetime
5
5
  from pathlib import Path
6
6
 
7
- from rich.console import Console
7
+ from acb.console import Console
8
+ from acb.depends import Inject, depends
8
9
 
9
- from .git import GitService
10
+ from crackerjack.models.protocols import GitServiceProtocol
10
11
 
11
12
 
12
13
  class ChangelogEntry:
@@ -33,7 +34,10 @@ class ChangelogEntry:
33
34
  class ChangelogGenerator:
34
35
  """Generate and update changelogs based on git commits."""
35
36
 
36
- def __init__(self, console: Console, git_service: GitService) -> None:
37
+ @depends.inject
38
+ def __init__(
39
+ self, console: Inject[Console], git_service: Inject[GitServiceProtocol]
40
+ ) -> None:
37
41
  self.console = console
38
42
  self.git = git_service
39
43
 
@@ -0,0 +1,305 @@
1
+ """Unified command execution service with consistent error handling and timeouts."""
2
+
3
+ import asyncio
4
+ import subprocess
5
+ from pathlib import Path
6
+
7
+ from loguru import logger
8
+
9
+
10
+ class CommandExecutionService:
11
+ """Unified command execution with consistent error handling, timeouts, and caching."""
12
+
13
+ def __init__(self, default_timeout: int = 30):
14
+ """
15
+ Initialize the command execution service.
16
+
17
+ Args:
18
+ default_timeout: Default timeout in seconds for commands
19
+ """
20
+ self.default_timeout = default_timeout
21
+
22
+ async def run_command(
23
+ self,
24
+ cmd: str | list[str],
25
+ cwd: str | Path | None = None,
26
+ env: dict[str, str] | None = None,
27
+ timeout: int | None = None,
28
+ capture_output: bool = True,
29
+ check: bool = True,
30
+ ) -> subprocess.CompletedProcess:
31
+ """
32
+ Run a command with timeout and error handling.
33
+
34
+ Args:
35
+ cmd: Command to run as a string or list of strings
36
+ cwd: Working directory to run the command in
37
+ env: Environment variables to use
38
+ timeout: Timeout in seconds (uses default if not specified)
39
+ capture_output: Whether to capture stdout/stderr
40
+ check: If True, raises exception on non-zero exit code
41
+
42
+ Returns:
43
+ CompletedProcess instance with results
44
+
45
+ Raises:
46
+ subprocess.TimeoutExpired: If command times out
47
+ subprocess.CalledProcessError: If command fails and check=True
48
+ """
49
+ timeout = timeout or self.default_timeout
50
+ str_cmd = " ".join(cmd) if isinstance(cmd, list) else cmd
51
+ logger.debug(f"Executing command: {str_cmd}")
52
+
53
+ try:
54
+ self._get_executable(cmd)
55
+ process = await self._create_subprocess(cmd, capture_output, cwd, env)
56
+ return await self._execute_process(
57
+ process, cmd, str_cmd, timeout, check, capture_output
58
+ )
59
+ except FileNotFoundError:
60
+ logger.error(f"Command not found: {self._get_executable(cmd)}")
61
+ raise
62
+ except Exception as e:
63
+ logger.error(f"Command execution failed: {str_cmd}, Error: {e}")
64
+ raise
65
+
66
+ def _get_executable(self, cmd: str | list[str]) -> str:
67
+ """Extract executable name from command."""
68
+ if isinstance(cmd, list):
69
+ return cmd[0] if cmd else ""
70
+ else:
71
+ parts = cmd.split()
72
+ return parts[0] if parts else ""
73
+
74
+ async def _create_subprocess(
75
+ self,
76
+ cmd: str | list[str],
77
+ capture_output: bool,
78
+ cwd: str | Path | None,
79
+ env: dict[str, str] | None,
80
+ ) -> asyncio.subprocess.Process:
81
+ """Create subprocess with proper configuration."""
82
+ return await asyncio.create_subprocess_exec(
83
+ *(cmd if isinstance(cmd, list) else cmd.split()),
84
+ stdout=asyncio.subprocess.PIPE if capture_output else None,
85
+ stderr=asyncio.subprocess.PIPE if capture_output else None,
86
+ cwd=cwd,
87
+ env=env,
88
+ )
89
+
90
+ async def _execute_process(
91
+ self,
92
+ process: asyncio.subprocess.Process,
93
+ cmd: str | list[str],
94
+ str_cmd: str,
95
+ timeout: int,
96
+ check: bool,
97
+ capture_output: bool,
98
+ ) -> subprocess.CompletedProcess:
99
+ """Execute the process and handle the result."""
100
+ try:
101
+ stdout, stderr = await asyncio.wait_for(
102
+ process.communicate(), timeout=timeout
103
+ )
104
+
105
+ return_code = process.returncode if process.returncode is not None else 0
106
+ completed_process = subprocess.CompletedProcess(
107
+ cmd,
108
+ return_code,
109
+ stdout.decode() if stdout else None,
110
+ stderr.decode() if stderr else None,
111
+ )
112
+
113
+ if check and process.returncode != 0:
114
+ logger.error(
115
+ f"Command failed with exit code {process.returncode}: {str_cmd}"
116
+ )
117
+ raise subprocess.CalledProcessError(
118
+ return_code,
119
+ cmd,
120
+ output=completed_process.stdout,
121
+ stderr=completed_process.stderr,
122
+ )
123
+
124
+ logger.debug(f"Command completed successfully: {str_cmd}")
125
+ return completed_process
126
+
127
+ except TimeoutError:
128
+ # Handle timeout
129
+ process.kill()
130
+ await process.wait() # Ensure process is cleaned up
131
+ logger.error(f"Command timed out after {timeout}s: {str_cmd}")
132
+ raise subprocess.TimeoutExpired(cmd, timeout)
133
+
134
+ def run_command_sync(
135
+ self,
136
+ cmd: str | list[str],
137
+ cwd: str | Path | None = None,
138
+ env: dict[str, str] | None = None,
139
+ timeout: int | None = None,
140
+ capture_output: bool = True,
141
+ check: bool = True,
142
+ ) -> subprocess.CompletedProcess:
143
+ """
144
+ Synchronous version of run_command.
145
+
146
+ Args:
147
+ cmd: Command to run as a string or list of strings
148
+ cwd: Working directory to run the command in
149
+ env: Environment variables to use
150
+ timeout: Timeout in seconds (uses default if not specified)
151
+ capture_output: Whether to capture stdout/stderr
152
+ check: If True, raises exception on non-zero exit code
153
+
154
+ Returns:
155
+ CompletedProcess instance with results
156
+ """
157
+ timeout = timeout or self.default_timeout
158
+ str_cmd = " ".join(cmd) if isinstance(cmd, list) else cmd
159
+
160
+ try:
161
+ logger.debug(f"Executing sync command: {str_cmd}")
162
+
163
+ result = subprocess.run(
164
+ cmd,
165
+ cwd=cwd,
166
+ env=env,
167
+ timeout=timeout,
168
+ capture_output=capture_output,
169
+ text=True, # Return strings instead of bytes
170
+ check=check,
171
+ )
172
+
173
+ logger.debug(f"Sync command completed: {str_cmd}")
174
+ return result
175
+
176
+ except subprocess.TimeoutExpired:
177
+ logger.error(f"Sync command timed out after {timeout}s: {str_cmd}")
178
+ raise
179
+ except Exception as e:
180
+ logger.error(f"Sync command execution failed: {str_cmd}, Error: {e}")
181
+ raise
182
+
183
+ async def run_multiple_commands(
184
+ self,
185
+ commands: list[str | list[str]],
186
+ cwd: str | Path | None = None,
187
+ env: dict[str, str] | None = None,
188
+ timeout: int | None = None,
189
+ parallel: bool = False,
190
+ ) -> list[subprocess.CompletedProcess]:
191
+ """
192
+ Run multiple commands sequentially or in parallel.
193
+
194
+ Args:
195
+ commands: List of commands to run
196
+ cwd: Working directory to run the commands in
197
+ env: Environment variables to use
198
+ timeout: Timeout in seconds for each command
199
+ parallel: If True, run commands in parallel; otherwise sequentially
200
+
201
+ Returns:
202
+ List of CompletedProcess instances with results
203
+ """
204
+ results = []
205
+
206
+ if parallel:
207
+ # Run commands in parallel
208
+ tasks = [
209
+ self.run_command(cmd, cwd=cwd, env=env, timeout=timeout)
210
+ for cmd in commands
211
+ ]
212
+ results = await asyncio.gather(*tasks)
213
+ else:
214
+ # Run commands sequentially
215
+ for cmd in commands:
216
+ result = await self.run_command(cmd, cwd=cwd, env=env, timeout=timeout)
217
+ results.append(result)
218
+
219
+ return results
220
+
221
+ async def command_exists(self, command: str) -> bool:
222
+ """
223
+ Check if a command exists in the system.
224
+
225
+ Args:
226
+ command: Command to check
227
+
228
+ Returns:
229
+ True if command exists, False otherwise
230
+ """
231
+ try:
232
+ # Try running 'which' on Unix-like systems or 'where' on Windows
233
+ import platform
234
+
235
+ if platform.system() == "Windows":
236
+ check_cmd = ["where", command]
237
+ else:
238
+ check_cmd = ["which", command]
239
+
240
+ result = await self.run_command(
241
+ check_cmd,
242
+ capture_output=True,
243
+ check=False, # Don't raise on non-zero exit (which returns 1 if not found)
244
+ )
245
+
246
+ return result.returncode == 0
247
+ except (subprocess.CalledProcessError, FileNotFoundError):
248
+ # If the check command itself fails, command likely doesn't exist
249
+ return False
250
+
251
+ async def run_command_with_retries(
252
+ self,
253
+ cmd: str | list[str],
254
+ max_retries: int = 3,
255
+ cwd: str | Path | None = None,
256
+ env: dict[str, str] | None = None,
257
+ timeout: int | None = None,
258
+ capture_output: bool = True,
259
+ check: bool = True,
260
+ backoff_factor: float = 1.0,
261
+ ) -> subprocess.CompletedProcess:
262
+ """
263
+ Run a command with retry logic.
264
+
265
+ Args:
266
+ cmd: Command to run
267
+ max_retries: Maximum number of retry attempts
268
+ cwd: Working directory
269
+ env: Environment variables
270
+ timeout: Timeout for each attempt
271
+ capture_output: Whether to capture output
272
+ check: Whether to check return code
273
+ backoff_factor: Factor by which to multiply wait time between retries
274
+
275
+ Returns:
276
+ CompletedProcess instance with results
277
+ """
278
+ for attempt in range(
279
+ max_retries + 1
280
+ ): # +1 because first attempt doesn't count as retry
281
+ try:
282
+ return await self.run_command(
283
+ cmd,
284
+ cwd=cwd,
285
+ env=env,
286
+ timeout=timeout,
287
+ capture_output=capture_output,
288
+ check=check,
289
+ )
290
+ except (subprocess.TimeoutExpired, subprocess.CalledProcessError) as e:
291
+ if attempt == max_retries:
292
+ # Last attempt, re-raise the exception
293
+ logger.error(f"Command failed after {max_retries} retries: {cmd}")
294
+ raise
295
+ else:
296
+ # Wait before retrying with exponential backoff
297
+ wait_time = backoff_factor * (2**attempt)
298
+ logger.warning(
299
+ f"Command failed on attempt {attempt + 1}, "
300
+ f"retrying in {wait_time}s: {cmd}. Error: {e}"
301
+ )
302
+ await asyncio.sleep(wait_time)
303
+
304
+ # This line should never be reached due to the loop logic
305
+ raise RuntimeError("Unexpected error in run_command_with_retries")
@@ -1,15 +1,58 @@
1
+ import tomllib
2
+ import typing as t
1
3
  from pathlib import Path
2
4
 
3
- from rich.console import Console
5
+ from acb.console import Console
6
+ from acb.depends import Inject, depends
4
7
 
8
+ from crackerjack.exceptions.config import ConfigIntegrityError
9
+ from crackerjack.models.protocols import ConfigIntegrityServiceProtocol, ServiceProtocol
5
10
 
6
- class ConfigIntegrityService:
7
- def __init__(self, console: Console, project_path: Path) -> None:
11
+
12
+ class ConfigIntegrityService(ConfigIntegrityServiceProtocol, ServiceProtocol):
13
+ @depends.inject
14
+ def __init__(self, console: Inject[Console], project_path: Path) -> None:
8
15
  self.console = console
9
16
  self.project_path = project_path
10
17
  self.cache_dir = Path.home() / ".cache" / "crackerjack"
11
18
  self.cache_dir.mkdir(parents=True, exist_ok=True)
12
19
 
20
+ def initialize(self) -> None:
21
+ pass
22
+
23
+ def cleanup(self) -> None:
24
+ pass
25
+
26
+ def health_check(self) -> bool:
27
+ return True
28
+
29
+ def shutdown(self) -> None:
30
+ pass
31
+
32
+ def metrics(self) -> dict[str, t.Any]:
33
+ return {}
34
+
35
+ def is_healthy(self) -> bool:
36
+ return True
37
+
38
+ def register_resource(self, resource: t.Any) -> None:
39
+ pass
40
+
41
+ def cleanup_resource(self, resource: t.Any) -> None:
42
+ pass
43
+
44
+ def record_error(self, error: Exception) -> None:
45
+ pass
46
+
47
+ def increment_requests(self) -> None:
48
+ pass
49
+
50
+ def get_custom_metric(self, name: str) -> t.Any:
51
+ return None
52
+
53
+ def set_custom_metric(self, name: str, value: t.Any) -> None:
54
+ pass
55
+
13
56
  def check_config_integrity(self) -> bool:
14
57
  config_files = [
15
58
  ".pre-commit-config.yaml",
@@ -20,13 +63,21 @@ class ConfigIntegrityService:
20
63
 
21
64
  for file_name in config_files:
22
65
  file_path = self.project_path / file_name
23
- if file_path.exists() and self._check_file_drift(file_path):
24
- drift_detected = True
66
+ if file_path.exists():
67
+ try:
68
+ if self._check_file_drift(file_path):
69
+ drift_detected = True
70
+ except ConfigIntegrityError as e:
71
+ self.console.print(
72
+ f"[red]❌ Error checking {file_path.name}: {e}[/ red]"
73
+ )
74
+ drift_detected = True
25
75
 
26
- if not self._has_required_config_sections():
27
- self.console.print(
28
- "[yellow]⚠️ Configuration missing required sections[/ yellow]",
29
- )
76
+ try:
77
+ if not self._has_required_config_sections():
78
+ drift_detected = True
79
+ except ConfigIntegrityError as e:
80
+ self.console.print(f"[red]❌ Configuration integrity error: {e}[/ red]")
30
81
  drift_detected = True
31
82
 
32
83
  return drift_detected
@@ -39,50 +90,43 @@ class ConfigIntegrityService:
39
90
  current_hash = hash(current_content)
40
91
 
41
92
  if cache_file.exists():
42
- from contextlib import suppress
43
-
44
- with suppress(OSError, ValueError):
45
- cached_hash = int(cache_file.read_text().strip())
46
- if current_hash != cached_hash:
47
- self.console.print(
48
- f"[yellow]⚠️ {file_path.name} has been modified manually[/ yellow]",
49
- )
50
- return True
93
+ cached_hash = int(cache_file.read_text().strip())
94
+ if current_hash != cached_hash:
95
+ self.console.print(
96
+ f"[yellow]⚠️ {file_path.name} has been modified manually[/ yellow]",
97
+ )
98
+ return True
51
99
 
52
100
  cache_file.write_text(str(current_hash))
53
101
  return False
54
102
 
55
103
  except OSError as e:
56
- self.console.print(f"[red]❌ Error checking {file_path.name}: {e}[/ red]")
57
- return False
104
+ raise ConfigIntegrityError(
105
+ f"Failed to check file drift for {file_path.name}: {e}"
106
+ ) from e
58
107
 
59
108
  def _has_required_config_sections(self) -> bool:
60
109
  pyproject = self.project_path / "pyproject.toml"
61
110
  if not pyproject.exists():
62
- return False
111
+ raise ConfigIntegrityError("pyproject.toml not found.")
63
112
 
64
113
  try:
65
- import tomllib
66
-
67
114
  with pyproject.open("rb") as f:
68
115
  config = tomllib.load(f)
116
+ except Exception as e:
117
+ raise ConfigIntegrityError(f"Error parsing pyproject.toml: {e}") from e
69
118
 
70
- required = ["tool.ruff", "tool.pyright", "tool.pytest.ini_options"]
71
-
72
- for section in required:
73
- keys = section.split(".")
74
- current = config
119
+ required = ["tool.ruff", "tool.pyright", "tool.pytest.ini_options"]
75
120
 
76
- for key in keys:
77
- if key not in current:
78
- self.console.print(
79
- f"[yellow]⚠️ Missing required config section: {section}[/ yellow]",
80
- )
81
- return False
82
- current = current[key]
121
+ for section in required:
122
+ keys = section.split(".")
123
+ current = config
83
124
 
84
- return True
125
+ for key in keys:
126
+ if key not in current:
127
+ raise ConfigIntegrityError(
128
+ f"Missing required config section: {section} in pyproject.toml"
129
+ )
130
+ current = current[key]
85
131
 
86
- except Exception as e:
87
- self.console.print(f"[red]❌ Error parsing pyproject.toml: {e}[/ red]")
88
- return False
132
+ return True
@@ -6,27 +6,30 @@ from pathlib import Path
6
6
  import tomli
7
7
  import tomli_w
8
8
  import yaml
9
- from rich.console import Console
9
+ from acb.console import Console
10
+ from acb.depends import Inject, depends
11
+ from acb.logger import Logger
10
12
 
11
13
  from crackerjack.models.protocols import (
12
14
  ConfigMergeServiceProtocol,
13
15
  FileSystemInterface,
14
16
  GitInterface,
15
17
  )
16
- from crackerjack.services.logging import get_logger
17
18
 
18
19
 
19
20
  class ConfigMergeService(ConfigMergeServiceProtocol):
21
+ @depends.inject
20
22
  def __init__(
21
23
  self,
22
- console: Console,
23
- filesystem: FileSystemInterface,
24
- git_service: GitInterface,
24
+ console: Inject[Console],
25
+ filesystem: Inject[FileSystemInterface],
26
+ git_service: Inject[GitInterface],
27
+ logger: Inject[Logger],
25
28
  ) -> None:
26
29
  self.console = console
27
30
  self.filesystem = filesystem
28
31
  self.git_service = git_service
29
- self.logger = get_logger("crackerjack.config_merge")
32
+ self.logger = logger
30
33
 
31
34
  def smart_merge_pyproject(
32
35
  self,