crackerjack 0.18.2__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 (533) hide show
  1. crackerjack/README.md +19 -0
  2. crackerjack/__init__.py +96 -2
  3. crackerjack/__main__.py +637 -138
  4. crackerjack/adapters/README.md +18 -0
  5. crackerjack/adapters/__init__.py +39 -0
  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/lsp/_base.py +194 -0
  27. crackerjack/adapters/lsp/_client.py +358 -0
  28. crackerjack/adapters/lsp/_manager.py +193 -0
  29. crackerjack/adapters/lsp/skylos.py +283 -0
  30. crackerjack/adapters/lsp/zuban.py +557 -0
  31. crackerjack/adapters/refactor/README.md +59 -0
  32. crackerjack/adapters/refactor/__init__.py +12 -0
  33. crackerjack/adapters/refactor/creosote.py +318 -0
  34. crackerjack/adapters/refactor/refurb.py +406 -0
  35. crackerjack/adapters/refactor/skylos.py +494 -0
  36. crackerjack/adapters/sast/README.md +132 -0
  37. crackerjack/adapters/sast/__init__.py +32 -0
  38. crackerjack/adapters/sast/_base.py +201 -0
  39. crackerjack/adapters/sast/bandit.py +423 -0
  40. crackerjack/adapters/sast/pyscn.py +405 -0
  41. crackerjack/adapters/sast/semgrep.py +241 -0
  42. crackerjack/adapters/security/README.md +111 -0
  43. crackerjack/adapters/security/__init__.py +17 -0
  44. crackerjack/adapters/security/gitleaks.py +339 -0
  45. crackerjack/adapters/type/README.md +52 -0
  46. crackerjack/adapters/type/__init__.py +12 -0
  47. crackerjack/adapters/type/pyrefly.py +402 -0
  48. crackerjack/adapters/type/ty.py +402 -0
  49. crackerjack/adapters/type/zuban.py +522 -0
  50. crackerjack/adapters/utility/README.md +51 -0
  51. crackerjack/adapters/utility/__init__.py +10 -0
  52. crackerjack/adapters/utility/checks.py +884 -0
  53. crackerjack/agents/README.md +264 -0
  54. crackerjack/agents/__init__.py +66 -0
  55. crackerjack/agents/architect_agent.py +238 -0
  56. crackerjack/agents/base.py +167 -0
  57. crackerjack/agents/claude_code_bridge.py +641 -0
  58. crackerjack/agents/coordinator.py +600 -0
  59. crackerjack/agents/documentation_agent.py +520 -0
  60. crackerjack/agents/dry_agent.py +585 -0
  61. crackerjack/agents/enhanced_coordinator.py +279 -0
  62. crackerjack/agents/enhanced_proactive_agent.py +185 -0
  63. crackerjack/agents/error_middleware.py +53 -0
  64. crackerjack/agents/formatting_agent.py +230 -0
  65. crackerjack/agents/helpers/__init__.py +9 -0
  66. crackerjack/agents/helpers/performance/__init__.py +22 -0
  67. crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
  68. crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
  69. crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
  70. crackerjack/agents/helpers/refactoring/__init__.py +22 -0
  71. crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
  72. crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
  73. crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
  74. crackerjack/agents/helpers/test_creation/__init__.py +19 -0
  75. crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
  76. crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
  77. crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
  78. crackerjack/agents/import_optimization_agent.py +1181 -0
  79. crackerjack/agents/performance_agent.py +325 -0
  80. crackerjack/agents/performance_helpers.py +205 -0
  81. crackerjack/agents/proactive_agent.py +55 -0
  82. crackerjack/agents/refactoring_agent.py +511 -0
  83. crackerjack/agents/refactoring_helpers.py +247 -0
  84. crackerjack/agents/security_agent.py +793 -0
  85. crackerjack/agents/semantic_agent.py +479 -0
  86. crackerjack/agents/semantic_helpers.py +356 -0
  87. crackerjack/agents/test_creation_agent.py +570 -0
  88. crackerjack/agents/test_specialist_agent.py +526 -0
  89. crackerjack/agents/tracker.py +110 -0
  90. crackerjack/api.py +647 -0
  91. crackerjack/cli/README.md +394 -0
  92. crackerjack/cli/__init__.py +24 -0
  93. crackerjack/cli/cache_handlers.py +209 -0
  94. crackerjack/cli/cache_handlers_enhanced.py +680 -0
  95. crackerjack/cli/facade.py +162 -0
  96. crackerjack/cli/formatting.py +13 -0
  97. crackerjack/cli/handlers/__init__.py +85 -0
  98. crackerjack/cli/handlers/advanced.py +103 -0
  99. crackerjack/cli/handlers/ai_features.py +62 -0
  100. crackerjack/cli/handlers/analytics.py +479 -0
  101. crackerjack/cli/handlers/changelog.py +271 -0
  102. crackerjack/cli/handlers/config_handlers.py +16 -0
  103. crackerjack/cli/handlers/coverage.py +84 -0
  104. crackerjack/cli/handlers/documentation.py +280 -0
  105. crackerjack/cli/handlers/main_handlers.py +497 -0
  106. crackerjack/cli/handlers/monitoring.py +371 -0
  107. crackerjack/cli/handlers.py +700 -0
  108. crackerjack/cli/interactive.py +488 -0
  109. crackerjack/cli/options.py +1216 -0
  110. crackerjack/cli/semantic_handlers.py +292 -0
  111. crackerjack/cli/utils.py +19 -0
  112. crackerjack/cli/version.py +19 -0
  113. crackerjack/code_cleaner.py +1307 -0
  114. crackerjack/config/README.md +472 -0
  115. crackerjack/config/__init__.py +275 -0
  116. crackerjack/config/global_lock_config.py +207 -0
  117. crackerjack/config/hooks.py +390 -0
  118. crackerjack/config/loader.py +239 -0
  119. crackerjack/config/settings.py +141 -0
  120. crackerjack/config/tool_commands.py +331 -0
  121. crackerjack/core/README.md +393 -0
  122. crackerjack/core/__init__.py +0 -0
  123. crackerjack/core/async_workflow_orchestrator.py +738 -0
  124. crackerjack/core/autofix_coordinator.py +282 -0
  125. crackerjack/core/container.py +105 -0
  126. crackerjack/core/enhanced_container.py +583 -0
  127. crackerjack/core/file_lifecycle.py +472 -0
  128. crackerjack/core/performance.py +244 -0
  129. crackerjack/core/performance_monitor.py +357 -0
  130. crackerjack/core/phase_coordinator.py +1227 -0
  131. crackerjack/core/proactive_workflow.py +267 -0
  132. crackerjack/core/resource_manager.py +425 -0
  133. crackerjack/core/retry.py +275 -0
  134. crackerjack/core/service_watchdog.py +601 -0
  135. crackerjack/core/session_coordinator.py +239 -0
  136. crackerjack/core/timeout_manager.py +563 -0
  137. crackerjack/core/websocket_lifecycle.py +410 -0
  138. crackerjack/core/workflow/__init__.py +21 -0
  139. crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
  140. crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
  141. crackerjack/core/workflow/workflow_issue_parser.py +714 -0
  142. crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
  143. crackerjack/core/workflow/workflow_security_gates.py +400 -0
  144. crackerjack/core/workflow_orchestrator.py +2243 -0
  145. crackerjack/data/README.md +11 -0
  146. crackerjack/data/__init__.py +8 -0
  147. crackerjack/data/models.py +79 -0
  148. crackerjack/data/repository.py +210 -0
  149. crackerjack/decorators/README.md +180 -0
  150. crackerjack/decorators/__init__.py +35 -0
  151. crackerjack/decorators/error_handling.py +649 -0
  152. crackerjack/decorators/error_handling_decorators.py +334 -0
  153. crackerjack/decorators/helpers.py +58 -0
  154. crackerjack/decorators/patterns.py +281 -0
  155. crackerjack/decorators/utils.py +58 -0
  156. crackerjack/docs/INDEX.md +11 -0
  157. crackerjack/docs/README.md +11 -0
  158. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  159. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  160. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  161. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  162. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  163. crackerjack/documentation/README.md +11 -0
  164. crackerjack/documentation/__init__.py +31 -0
  165. crackerjack/documentation/ai_templates.py +756 -0
  166. crackerjack/documentation/dual_output_generator.py +767 -0
  167. crackerjack/documentation/mkdocs_integration.py +518 -0
  168. crackerjack/documentation/reference_generator.py +1065 -0
  169. crackerjack/dynamic_config.py +678 -0
  170. crackerjack/errors.py +378 -0
  171. crackerjack/events/README.md +11 -0
  172. crackerjack/events/__init__.py +16 -0
  173. crackerjack/events/telemetry.py +175 -0
  174. crackerjack/events/workflow_bus.py +346 -0
  175. crackerjack/exceptions/README.md +301 -0
  176. crackerjack/exceptions/__init__.py +5 -0
  177. crackerjack/exceptions/config.py +4 -0
  178. crackerjack/exceptions/tool_execution_error.py +245 -0
  179. crackerjack/executors/README.md +591 -0
  180. crackerjack/executors/__init__.py +13 -0
  181. crackerjack/executors/async_hook_executor.py +938 -0
  182. crackerjack/executors/cached_hook_executor.py +316 -0
  183. crackerjack/executors/hook_executor.py +1295 -0
  184. crackerjack/executors/hook_lock_manager.py +708 -0
  185. crackerjack/executors/individual_hook_executor.py +739 -0
  186. crackerjack/executors/lsp_aware_hook_executor.py +349 -0
  187. crackerjack/executors/progress_hook_executor.py +282 -0
  188. crackerjack/executors/tool_proxy.py +433 -0
  189. crackerjack/hooks/README.md +485 -0
  190. crackerjack/hooks/lsp_hook.py +93 -0
  191. crackerjack/intelligence/README.md +557 -0
  192. crackerjack/intelligence/__init__.py +37 -0
  193. crackerjack/intelligence/adaptive_learning.py +693 -0
  194. crackerjack/intelligence/agent_orchestrator.py +485 -0
  195. crackerjack/intelligence/agent_registry.py +377 -0
  196. crackerjack/intelligence/agent_selector.py +439 -0
  197. crackerjack/intelligence/integration.py +250 -0
  198. crackerjack/interactive.py +719 -0
  199. crackerjack/managers/README.md +369 -0
  200. crackerjack/managers/__init__.py +11 -0
  201. crackerjack/managers/async_hook_manager.py +135 -0
  202. crackerjack/managers/hook_manager.py +585 -0
  203. crackerjack/managers/publish_manager.py +631 -0
  204. crackerjack/managers/test_command_builder.py +391 -0
  205. crackerjack/managers/test_executor.py +474 -0
  206. crackerjack/managers/test_manager.py +1357 -0
  207. crackerjack/managers/test_progress.py +187 -0
  208. crackerjack/mcp/README.md +374 -0
  209. crackerjack/mcp/__init__.py +0 -0
  210. crackerjack/mcp/cache.py +352 -0
  211. crackerjack/mcp/client_runner.py +121 -0
  212. crackerjack/mcp/context.py +802 -0
  213. crackerjack/mcp/dashboard.py +657 -0
  214. crackerjack/mcp/enhanced_progress_monitor.py +493 -0
  215. crackerjack/mcp/file_monitor.py +394 -0
  216. crackerjack/mcp/progress_components.py +607 -0
  217. crackerjack/mcp/progress_monitor.py +1016 -0
  218. crackerjack/mcp/rate_limiter.py +336 -0
  219. crackerjack/mcp/server.py +24 -0
  220. crackerjack/mcp/server_core.py +526 -0
  221. crackerjack/mcp/service_watchdog.py +505 -0
  222. crackerjack/mcp/state.py +407 -0
  223. crackerjack/mcp/task_manager.py +259 -0
  224. crackerjack/mcp/tools/README.md +27 -0
  225. crackerjack/mcp/tools/__init__.py +19 -0
  226. crackerjack/mcp/tools/core_tools.py +469 -0
  227. crackerjack/mcp/tools/error_analyzer.py +283 -0
  228. crackerjack/mcp/tools/execution_tools.py +384 -0
  229. crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
  230. crackerjack/mcp/tools/intelligence_tools.py +264 -0
  231. crackerjack/mcp/tools/monitoring_tools.py +628 -0
  232. crackerjack/mcp/tools/proactive_tools.py +367 -0
  233. crackerjack/mcp/tools/progress_tools.py +222 -0
  234. crackerjack/mcp/tools/semantic_tools.py +584 -0
  235. crackerjack/mcp/tools/utility_tools.py +358 -0
  236. crackerjack/mcp/tools/workflow_executor.py +699 -0
  237. crackerjack/mcp/websocket/README.md +31 -0
  238. crackerjack/mcp/websocket/__init__.py +14 -0
  239. crackerjack/mcp/websocket/app.py +54 -0
  240. crackerjack/mcp/websocket/endpoints.py +492 -0
  241. crackerjack/mcp/websocket/event_bridge.py +188 -0
  242. crackerjack/mcp/websocket/jobs.py +406 -0
  243. crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
  244. crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
  245. crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
  246. crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
  247. crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
  248. crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
  249. crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
  250. crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
  251. crackerjack/mcp/websocket/monitoring/factory.py +109 -0
  252. crackerjack/mcp/websocket/monitoring/filters.py +10 -0
  253. crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
  254. crackerjack/mcp/websocket/monitoring/models.py +90 -0
  255. crackerjack/mcp/websocket/monitoring/utils.py +171 -0
  256. crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
  257. crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
  258. crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
  259. crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
  260. crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
  261. crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
  262. crackerjack/mcp/websocket/monitoring_endpoints.py +21 -0
  263. crackerjack/mcp/websocket/server.py +174 -0
  264. crackerjack/mcp/websocket/websocket_handler.py +276 -0
  265. crackerjack/mcp/websocket_server.py +10 -0
  266. crackerjack/models/README.md +308 -0
  267. crackerjack/models/__init__.py +40 -0
  268. crackerjack/models/config.py +730 -0
  269. crackerjack/models/config_adapter.py +265 -0
  270. crackerjack/models/protocols.py +1535 -0
  271. crackerjack/models/pydantic_models.py +320 -0
  272. crackerjack/models/qa_config.py +145 -0
  273. crackerjack/models/qa_results.py +134 -0
  274. crackerjack/models/resource_protocols.py +299 -0
  275. crackerjack/models/results.py +35 -0
  276. crackerjack/models/semantic_models.py +258 -0
  277. crackerjack/models/task.py +173 -0
  278. crackerjack/models/test_models.py +60 -0
  279. crackerjack/monitoring/README.md +11 -0
  280. crackerjack/monitoring/__init__.py +0 -0
  281. crackerjack/monitoring/ai_agent_watchdog.py +405 -0
  282. crackerjack/monitoring/metrics_collector.py +427 -0
  283. crackerjack/monitoring/regression_prevention.py +580 -0
  284. crackerjack/monitoring/websocket_server.py +406 -0
  285. crackerjack/orchestration/README.md +340 -0
  286. crackerjack/orchestration/__init__.py +43 -0
  287. crackerjack/orchestration/advanced_orchestrator.py +894 -0
  288. crackerjack/orchestration/cache/README.md +312 -0
  289. crackerjack/orchestration/cache/__init__.py +37 -0
  290. crackerjack/orchestration/cache/memory_cache.py +338 -0
  291. crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
  292. crackerjack/orchestration/config.py +297 -0
  293. crackerjack/orchestration/coverage_improvement.py +180 -0
  294. crackerjack/orchestration/execution_strategies.py +361 -0
  295. crackerjack/orchestration/hook_orchestrator.py +1398 -0
  296. crackerjack/orchestration/strategies/README.md +401 -0
  297. crackerjack/orchestration/strategies/__init__.py +39 -0
  298. crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
  299. crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
  300. crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
  301. crackerjack/orchestration/test_progress_streamer.py +647 -0
  302. crackerjack/plugins/README.md +11 -0
  303. crackerjack/plugins/__init__.py +15 -0
  304. crackerjack/plugins/base.py +200 -0
  305. crackerjack/plugins/hooks.py +254 -0
  306. crackerjack/plugins/loader.py +335 -0
  307. crackerjack/plugins/managers.py +264 -0
  308. crackerjack/py313.py +191 -0
  309. crackerjack/security/README.md +11 -0
  310. crackerjack/security/__init__.py +0 -0
  311. crackerjack/security/audit.py +197 -0
  312. crackerjack/services/README.md +374 -0
  313. crackerjack/services/__init__.py +9 -0
  314. crackerjack/services/ai/README.md +295 -0
  315. crackerjack/services/ai/__init__.py +7 -0
  316. crackerjack/services/ai/advanced_optimizer.py +878 -0
  317. crackerjack/services/ai/contextual_ai_assistant.py +542 -0
  318. crackerjack/services/ai/embeddings.py +444 -0
  319. crackerjack/services/ai/intelligent_commit.py +328 -0
  320. crackerjack/services/ai/predictive_analytics.py +510 -0
  321. crackerjack/services/anomaly_detector.py +392 -0
  322. crackerjack/services/api_extractor.py +617 -0
  323. crackerjack/services/backup_service.py +467 -0
  324. crackerjack/services/bounded_status_operations.py +530 -0
  325. crackerjack/services/cache.py +369 -0
  326. crackerjack/services/changelog_automation.py +399 -0
  327. crackerjack/services/command_execution_service.py +305 -0
  328. crackerjack/services/config_integrity.py +132 -0
  329. crackerjack/services/config_merge.py +546 -0
  330. crackerjack/services/config_service.py +198 -0
  331. crackerjack/services/config_template.py +493 -0
  332. crackerjack/services/coverage_badge_service.py +173 -0
  333. crackerjack/services/coverage_ratchet.py +381 -0
  334. crackerjack/services/debug.py +733 -0
  335. crackerjack/services/dependency_analyzer.py +460 -0
  336. crackerjack/services/dependency_monitor.py +622 -0
  337. crackerjack/services/documentation_generator.py +493 -0
  338. crackerjack/services/documentation_service.py +704 -0
  339. crackerjack/services/enhanced_filesystem.py +497 -0
  340. crackerjack/services/enterprise_optimizer.py +865 -0
  341. crackerjack/services/error_pattern_analyzer.py +676 -0
  342. crackerjack/services/file_filter.py +221 -0
  343. crackerjack/services/file_hasher.py +149 -0
  344. crackerjack/services/file_io_service.py +361 -0
  345. crackerjack/services/file_modifier.py +615 -0
  346. crackerjack/services/filesystem.py +381 -0
  347. crackerjack/services/git.py +422 -0
  348. crackerjack/services/health_metrics.py +615 -0
  349. crackerjack/services/heatmap_generator.py +744 -0
  350. crackerjack/services/incremental_executor.py +380 -0
  351. crackerjack/services/initialization.py +823 -0
  352. crackerjack/services/input_validator.py +668 -0
  353. crackerjack/services/intelligent_commit.py +327 -0
  354. crackerjack/services/log_manager.py +289 -0
  355. crackerjack/services/logging.py +228 -0
  356. crackerjack/services/lsp_client.py +628 -0
  357. crackerjack/services/memory_optimizer.py +414 -0
  358. crackerjack/services/metrics.py +587 -0
  359. crackerjack/services/monitoring/README.md +30 -0
  360. crackerjack/services/monitoring/__init__.py +9 -0
  361. crackerjack/services/monitoring/dependency_monitor.py +678 -0
  362. crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
  363. crackerjack/services/monitoring/health_metrics.py +716 -0
  364. crackerjack/services/monitoring/metrics.py +587 -0
  365. crackerjack/services/monitoring/performance_benchmarks.py +410 -0
  366. crackerjack/services/monitoring/performance_cache.py +388 -0
  367. crackerjack/services/monitoring/performance_monitor.py +569 -0
  368. crackerjack/services/parallel_executor.py +527 -0
  369. crackerjack/services/pattern_cache.py +333 -0
  370. crackerjack/services/pattern_detector.py +478 -0
  371. crackerjack/services/patterns/__init__.py +142 -0
  372. crackerjack/services/patterns/agents.py +107 -0
  373. crackerjack/services/patterns/code/__init__.py +15 -0
  374. crackerjack/services/patterns/code/detection.py +118 -0
  375. crackerjack/services/patterns/code/imports.py +107 -0
  376. crackerjack/services/patterns/code/paths.py +159 -0
  377. crackerjack/services/patterns/code/performance.py +119 -0
  378. crackerjack/services/patterns/code/replacement.py +36 -0
  379. crackerjack/services/patterns/core.py +212 -0
  380. crackerjack/services/patterns/documentation/__init__.py +14 -0
  381. crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
  382. crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
  383. crackerjack/services/patterns/documentation/docstrings.py +89 -0
  384. crackerjack/services/patterns/formatting.py +226 -0
  385. crackerjack/services/patterns/operations.py +339 -0
  386. crackerjack/services/patterns/security/__init__.py +23 -0
  387. crackerjack/services/patterns/security/code_injection.py +122 -0
  388. crackerjack/services/patterns/security/credentials.py +190 -0
  389. crackerjack/services/patterns/security/path_traversal.py +221 -0
  390. crackerjack/services/patterns/security/unsafe_operations.py +216 -0
  391. crackerjack/services/patterns/templates.py +62 -0
  392. crackerjack/services/patterns/testing/__init__.py +18 -0
  393. crackerjack/services/patterns/testing/error_patterns.py +107 -0
  394. crackerjack/services/patterns/testing/pytest_output.py +126 -0
  395. crackerjack/services/patterns/tool_output/__init__.py +16 -0
  396. crackerjack/services/patterns/tool_output/bandit.py +72 -0
  397. crackerjack/services/patterns/tool_output/other.py +97 -0
  398. crackerjack/services/patterns/tool_output/pyright.py +67 -0
  399. crackerjack/services/patterns/tool_output/ruff.py +44 -0
  400. crackerjack/services/patterns/url_sanitization.py +114 -0
  401. crackerjack/services/patterns/utilities.py +42 -0
  402. crackerjack/services/patterns/utils.py +339 -0
  403. crackerjack/services/patterns/validation.py +46 -0
  404. crackerjack/services/patterns/versioning.py +62 -0
  405. crackerjack/services/predictive_analytics.py +523 -0
  406. crackerjack/services/profiler.py +280 -0
  407. crackerjack/services/quality/README.md +415 -0
  408. crackerjack/services/quality/__init__.py +11 -0
  409. crackerjack/services/quality/anomaly_detector.py +392 -0
  410. crackerjack/services/quality/pattern_cache.py +333 -0
  411. crackerjack/services/quality/pattern_detector.py +479 -0
  412. crackerjack/services/quality/qa_orchestrator.py +491 -0
  413. crackerjack/services/quality/quality_baseline.py +395 -0
  414. crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
  415. crackerjack/services/quality/quality_intelligence.py +949 -0
  416. crackerjack/services/regex_patterns.py +58 -0
  417. crackerjack/services/regex_utils.py +483 -0
  418. crackerjack/services/secure_path_utils.py +524 -0
  419. crackerjack/services/secure_status_formatter.py +450 -0
  420. crackerjack/services/secure_subprocess.py +635 -0
  421. crackerjack/services/security.py +239 -0
  422. crackerjack/services/security_logger.py +495 -0
  423. crackerjack/services/server_manager.py +411 -0
  424. crackerjack/services/smart_scheduling.py +167 -0
  425. crackerjack/services/status_authentication.py +460 -0
  426. crackerjack/services/status_security_manager.py +315 -0
  427. crackerjack/services/terminal_utils.py +0 -0
  428. crackerjack/services/thread_safe_status_collector.py +441 -0
  429. crackerjack/services/tool_filter.py +368 -0
  430. crackerjack/services/tool_version_service.py +43 -0
  431. crackerjack/services/unified_config.py +115 -0
  432. crackerjack/services/validation_rate_limiter.py +220 -0
  433. crackerjack/services/vector_store.py +689 -0
  434. crackerjack/services/version_analyzer.py +461 -0
  435. crackerjack/services/version_checker.py +223 -0
  436. crackerjack/services/websocket_resource_limiter.py +438 -0
  437. crackerjack/services/zuban_lsp_service.py +391 -0
  438. crackerjack/slash_commands/README.md +11 -0
  439. crackerjack/slash_commands/__init__.py +59 -0
  440. crackerjack/slash_commands/init.md +112 -0
  441. crackerjack/slash_commands/run.md +197 -0
  442. crackerjack/slash_commands/status.md +127 -0
  443. crackerjack/tools/README.md +11 -0
  444. crackerjack/tools/__init__.py +30 -0
  445. crackerjack/tools/_git_utils.py +105 -0
  446. crackerjack/tools/check_added_large_files.py +139 -0
  447. crackerjack/tools/check_ast.py +105 -0
  448. crackerjack/tools/check_json.py +103 -0
  449. crackerjack/tools/check_jsonschema.py +297 -0
  450. crackerjack/tools/check_toml.py +103 -0
  451. crackerjack/tools/check_yaml.py +110 -0
  452. crackerjack/tools/codespell_wrapper.py +72 -0
  453. crackerjack/tools/end_of_file_fixer.py +202 -0
  454. crackerjack/tools/format_json.py +128 -0
  455. crackerjack/tools/mdformat_wrapper.py +114 -0
  456. crackerjack/tools/trailing_whitespace.py +198 -0
  457. crackerjack/tools/validate_input_validator_patterns.py +236 -0
  458. crackerjack/tools/validate_regex_patterns.py +188 -0
  459. crackerjack/ui/README.md +11 -0
  460. crackerjack/ui/__init__.py +1 -0
  461. crackerjack/ui/dashboard_renderer.py +28 -0
  462. crackerjack/ui/templates/README.md +11 -0
  463. crackerjack/utils/console_utils.py +13 -0
  464. crackerjack/utils/dependency_guard.py +230 -0
  465. crackerjack/utils/retry_utils.py +275 -0
  466. crackerjack/workflows/README.md +590 -0
  467. crackerjack/workflows/__init__.py +46 -0
  468. crackerjack/workflows/actions.py +811 -0
  469. crackerjack/workflows/auto_fix.py +444 -0
  470. crackerjack/workflows/container_builder.py +499 -0
  471. crackerjack/workflows/definitions.py +443 -0
  472. crackerjack/workflows/engine.py +177 -0
  473. crackerjack/workflows/event_bridge.py +242 -0
  474. crackerjack-0.45.2.dist-info/METADATA +1678 -0
  475. crackerjack-0.45.2.dist-info/RECORD +478 -0
  476. {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
  477. crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
  478. crackerjack/.gitignore +0 -14
  479. crackerjack/.libcst.codemod.yaml +0 -18
  480. crackerjack/.pdm.toml +0 -1
  481. crackerjack/.pre-commit-config.yaml +0 -91
  482. crackerjack/.pytest_cache/.gitignore +0 -2
  483. crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
  484. crackerjack/.pytest_cache/README.md +0 -8
  485. crackerjack/.pytest_cache/v/cache/nodeids +0 -1
  486. crackerjack/.pytest_cache/v/cache/stepwise +0 -1
  487. crackerjack/.ruff_cache/.gitignore +0 -1
  488. crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
  489. crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
  490. crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
  491. crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
  492. crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
  493. crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
  494. crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  495. crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
  496. crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
  497. crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
  498. crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
  499. crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
  500. crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
  501. crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
  502. crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
  503. crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
  504. crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
  505. crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
  506. crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
  507. crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
  508. crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
  509. crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
  510. crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
  511. crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
  512. crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
  513. crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
  514. crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
  515. crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
  516. crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
  517. crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
  518. crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
  519. crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
  520. crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
  521. crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
  522. crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
  523. crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
  524. crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
  525. crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
  526. crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
  527. crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
  528. crackerjack/crackerjack.py +0 -855
  529. crackerjack/pyproject.toml +0 -214
  530. crackerjack-0.18.2.dist-info/METADATA +0 -420
  531. crackerjack-0.18.2.dist-info/RECORD +0 -59
  532. crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
  533. {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,390 @@
1
+ from dataclasses import dataclass, field
2
+ from enum import Enum
3
+ from pathlib import Path
4
+
5
+ from crackerjack.config.tool_commands import get_tool_command
6
+
7
+
8
+ class HookStage(Enum):
9
+ FAST = "fast"
10
+ COMPREHENSIVE = "comprehensive"
11
+
12
+
13
+ class RetryPolicy(Enum):
14
+ NONE = "none"
15
+ FORMATTING_ONLY = "formatting_only"
16
+ ALL_HOOKS = "all_hooks"
17
+
18
+
19
+ class SecurityLevel(Enum):
20
+ CRITICAL = "critical"
21
+ HIGH = "high"
22
+ MEDIUM = "medium"
23
+ LOW = "low"
24
+
25
+
26
+ @dataclass
27
+ class HookDefinition:
28
+ name: str
29
+ command: list[str]
30
+ timeout: int = 60
31
+ stage: HookStage = HookStage.FAST
32
+ description: str | None = None
33
+ retry_on_failure: bool = False
34
+ is_formatting: bool = False
35
+ manual_stage: bool = False
36
+ config_path: Path | None = None
37
+ security_level: SecurityLevel = SecurityLevel.MEDIUM
38
+ use_precommit_legacy: bool = True # Phase 8.2: Backward compatibility flag
39
+ accepts_file_paths: bool = False # Phase 10.4.4: Can tool process individual files?
40
+ _direct_cmd_cache: list[str] | None = field(default=None, init=False, repr=False)
41
+
42
+ def get_command(self) -> list[str]:
43
+ """Get the command to execute this hook.
44
+
45
+ Returns the appropriate command based on use_precommit_legacy flag:
46
+ - If use_precommit_legacy=True: Returns pre-commit wrapper command (legacy mode)
47
+ - If use_precommit_legacy=False: Returns direct tool command (Phase 8+ mode)
48
+
49
+ Returns:
50
+ List of command arguments for subprocess execution
51
+ """
52
+ # Phase 8.2: Direct invocation mode (new behavior)
53
+ if not self.use_precommit_legacy:
54
+ if self._direct_cmd_cache is None:
55
+ try:
56
+ self._direct_cmd_cache = get_tool_command(
57
+ self.name, pkg_path=Path.cwd()
58
+ )
59
+ except KeyError:
60
+ # Fallback to pre-commit if tool not in registry
61
+ # This ensures graceful degradation during migration
62
+ self._direct_cmd_cache = None
63
+ if self._direct_cmd_cache is not None:
64
+ return self._direct_cmd_cache
65
+
66
+ # Legacy mode: Use pre-commit wrapper (Phase 1-7 behavior)
67
+ import shutil
68
+
69
+ pre_commit_path = None
70
+ current_dir = Path.cwd()
71
+ project_pre_commit = current_dir / ".venv" / "bin" / "pre-commit"
72
+ if project_pre_commit.exists():
73
+ pre_commit_path = str(project_pre_commit)
74
+ else:
75
+ pre_commit_path = shutil.which("pre-commit") or "pre-commit"
76
+
77
+ cmd = [pre_commit_path, "run"]
78
+ if self.config_path:
79
+ cmd.extend(["-c", str(self.config_path)])
80
+ if self.manual_stage:
81
+ cmd.extend(["--hook-stage", "manual"])
82
+ cmd.extend([self.name, "--all-files"])
83
+ return cmd
84
+
85
+ def build_command(self, files: list[Path] | None = None) -> list[str]:
86
+ """Build command with optional file paths for targeted execution.
87
+
88
+ Phase 10.4.4: Enables incremental execution on specific files when supported.
89
+
90
+ Args:
91
+ files: Optional list of file paths to process. If None, processes all files.
92
+
93
+ Returns:
94
+ Command list with file paths appended if tool accepts them.
95
+
96
+ Example:
97
+ >>> hook = HookDefinition(
98
+ ... name="ruff-check",
99
+ ... command=["ruff", "check"],
100
+ ... accepts_file_paths=True,
101
+ ... )
102
+ >>> hook.build_command([Path("foo.py"), Path("bar.py")])
103
+ ["ruff", "check", "foo.py", "bar.py"]
104
+ """
105
+ base_cmd = self.get_command().copy()
106
+
107
+ # Append file paths if tool accepts them and files are provided
108
+ if files and self.accepts_file_paths:
109
+ base_cmd.extend([str(f) for f in files])
110
+
111
+ return base_cmd
112
+
113
+
114
+ @dataclass
115
+ class HookStrategy:
116
+ name: str
117
+ hooks: list[HookDefinition]
118
+ timeout: int = 300
119
+ retry_policy: RetryPolicy = RetryPolicy.NONE
120
+ parallel: bool = False
121
+ max_workers: int = 3
122
+
123
+
124
+ FAST_HOOKS = [
125
+ HookDefinition(
126
+ name="validate-regex-patterns",
127
+ command=[],
128
+ is_formatting=True,
129
+ timeout=120, # Increased from 60 to handle larger codebases and prevent timeout issues
130
+ retry_on_failure=True,
131
+ security_level=SecurityLevel.HIGH,
132
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
133
+ ),
134
+ HookDefinition(
135
+ name="trailing-whitespace",
136
+ command=[],
137
+ is_formatting=True,
138
+ timeout=120, # Increased from 60 to handle larger codebases and prevent timeout issues
139
+ retry_on_failure=True,
140
+ security_level=SecurityLevel.LOW,
141
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
142
+ accepts_file_paths=True, # Phase 10.4.4: File-level fixer
143
+ ),
144
+ HookDefinition(
145
+ name="end-of-file-fixer",
146
+ command=[],
147
+ is_formatting=True,
148
+ timeout=120, # Increased from 60 to handle larger codebases and prevent timeout issues
149
+ retry_on_failure=True,
150
+ security_level=SecurityLevel.LOW,
151
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
152
+ accepts_file_paths=True, # Phase 10.4.4: File-level fixer
153
+ ),
154
+ HookDefinition(
155
+ name="check-yaml",
156
+ command=[],
157
+ timeout=60, # Increased from 20 to reduce timeout issues with larger YAML files
158
+ security_level=SecurityLevel.MEDIUM,
159
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
160
+ accepts_file_paths=True, # Phase 10.4.4: File-level validator
161
+ ),
162
+ HookDefinition(
163
+ name="check-toml",
164
+ command=[],
165
+ timeout=150, # Increased from 79 to reduce timeout issues with larger TOML files
166
+ security_level=SecurityLevel.MEDIUM,
167
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
168
+ accepts_file_paths=True, # Phase 10.4.4: File-level validator
169
+ ),
170
+ HookDefinition(
171
+ name="check-json",
172
+ command=[],
173
+ timeout=90, # Increased from 30 to reduce timeout issues with larger JSON files
174
+ security_level=SecurityLevel.MEDIUM,
175
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
176
+ accepts_file_paths=True, # Phase 10.4.4: File-level validator
177
+ ),
178
+ HookDefinition(
179
+ name="check-ast",
180
+ command=[],
181
+ timeout=90, # Increased from 30 to reduce timeout issues with larger Python files
182
+ security_level=SecurityLevel.HIGH,
183
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
184
+ accepts_file_paths=True, # Phase 10.4.4: File-level validator
185
+ ),
186
+ HookDefinition(
187
+ name="format-json",
188
+ command=[],
189
+ is_formatting=True,
190
+ timeout=120, # Increased from 45 to reduce timeout issues with larger JSON files
191
+ retry_on_failure=True,
192
+ security_level=SecurityLevel.LOW,
193
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
194
+ accepts_file_paths=True, # Phase 10.4.4: File-level formatter
195
+ ),
196
+ HookDefinition(
197
+ name="check-added-large-files",
198
+ command=[],
199
+ timeout=90, # Increased from 30 to reduce timeout issues with repositories with many files
200
+ security_level=SecurityLevel.HIGH,
201
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
202
+ ),
203
+ HookDefinition(
204
+ name="uv-lock",
205
+ command=[],
206
+ timeout=60, # Increased from 20 to reduce timeout issues with complex dependency trees
207
+ security_level=SecurityLevel.HIGH,
208
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
209
+ ),
210
+ HookDefinition(
211
+ name="codespell",
212
+ command=[],
213
+ timeout=150, # Increased from 45 to reduce timeout issues with large codebases
214
+ security_level=SecurityLevel.LOW,
215
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
216
+ accepts_file_paths=True, # Phase 10.4.4: File-level spell checker
217
+ ),
218
+ HookDefinition(
219
+ name="ruff-check",
220
+ command=[],
221
+ is_formatting=True,
222
+ timeout=240, # Increased from 120 to reduce timeout issues with large codebases
223
+ retry_on_failure=True,
224
+ security_level=SecurityLevel.MEDIUM,
225
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
226
+ accepts_file_paths=True, # Phase 10.4.4: File-level Python linter
227
+ ),
228
+ HookDefinition(
229
+ name="ruff-format",
230
+ command=[],
231
+ is_formatting=True,
232
+ timeout=240, # Increased from 120 to reduce timeout issues with large codebases
233
+ retry_on_failure=True,
234
+ security_level=SecurityLevel.LOW,
235
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
236
+ accepts_file_paths=True, # Phase 10.4.4: File-level Python formatter
237
+ ),
238
+ HookDefinition(
239
+ name="mdformat",
240
+ command=[],
241
+ is_formatting=True,
242
+ timeout=300, # Increased from 120 to reduce timeout issues with larger markdown files
243
+ retry_on_failure=True,
244
+ security_level=SecurityLevel.LOW,
245
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
246
+ accepts_file_paths=True, # Phase 10.4.4: File-level markdown formatter
247
+ ),
248
+ ]
249
+
250
+ COMPREHENSIVE_HOOKS = [
251
+ HookDefinition(
252
+ name="zuban",
253
+ command=[],
254
+ timeout=240, # Increased from 80 to reduce timeout issues with larger codebases during type checking
255
+ stage=HookStage.COMPREHENSIVE,
256
+ manual_stage=True,
257
+ security_level=SecurityLevel.HIGH, # Changed from CRITICAL to HIGH to allow other hooks to run
258
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
259
+ accepts_file_paths=True, # Phase 10.5: Allow incremental execution on changed files to avoid virtual environments
260
+ ),
261
+ HookDefinition(
262
+ name="semgrep",
263
+ command=[],
264
+ timeout=480, # Increased from 240 to reduce timeout issues with comprehensive security scans
265
+ stage=HookStage.COMPREHENSIVE,
266
+ manual_stage=True,
267
+ security_level=SecurityLevel.CRITICAL,
268
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
269
+ accepts_file_paths=True, # Phase 10.4.4: File-level SAST scanner
270
+ ),
271
+ HookDefinition(
272
+ name="pyscn",
273
+ command=[],
274
+ timeout=300, # CFG analysis, clone detection, complexity metrics
275
+ stage=HookStage.COMPREHENSIVE,
276
+ manual_stage=True,
277
+ security_level=SecurityLevel.HIGH, # Security + quality analysis
278
+ use_precommit_legacy=False, # Direct invocation
279
+ accepts_file_paths=True, # Can scan specific Python files
280
+ ),
281
+ # NOTE: Bandit replaced with Semgrep (using uvx for Python 3.13 isolation)
282
+ # HookDefinition(
283
+ # name="bandit",
284
+ # command=[],
285
+ # timeout=180, # 3 minutes for SAST scanning
286
+ # stage=HookStage.COMPREHENSIVE,
287
+ # manual_stage=True,
288
+ # security_level=SecurityLevel.CRITICAL,
289
+ # use_precommit_legacy=False, # Phase 8.4: Direct invocation
290
+ # accepts_file_paths=True, # Phase 10.4.4: File-level SAST scanner
291
+ # ),
292
+ HookDefinition(
293
+ name="gitleaks",
294
+ command=[],
295
+ timeout=180, # Increased from 45 to reduce timeout issues with comprehensive security scans
296
+ stage=HookStage.COMPREHENSIVE,
297
+ manual_stage=True,
298
+ security_level=SecurityLevel.CRITICAL,
299
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
300
+ ),
301
+ HookDefinition(
302
+ name="pip-audit",
303
+ command=[],
304
+ timeout=180, # Network calls to vulnerability databases
305
+ stage=HookStage.COMPREHENSIVE,
306
+ manual_stage=True,
307
+ security_level=SecurityLevel.CRITICAL, # CVE vulnerabilities are critical
308
+ use_precommit_legacy=False, # Direct invocation
309
+ accepts_file_paths=False, # Scans entire environment/requirements
310
+ ),
311
+ HookDefinition(
312
+ name="skylos",
313
+ command=[],
314
+ timeout=180, # Increased from 60 to reduce timeout issues with comprehensive dead code scanning
315
+ stage=HookStage.COMPREHENSIVE,
316
+ manual_stage=True,
317
+ security_level=SecurityLevel.MEDIUM,
318
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
319
+ accepts_file_paths=True, # Phase 10.5: Incremental execution on changed files
320
+ ),
321
+ HookDefinition(
322
+ name="refurb",
323
+ command=[],
324
+ timeout=480, # Increased from 240 to reduce timeout issues with comprehensive refactoring analysis
325
+ stage=HookStage.COMPREHENSIVE,
326
+ manual_stage=True,
327
+ security_level=SecurityLevel.MEDIUM,
328
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
329
+ accepts_file_paths=True, # Phase 10.5: Incremental execution on changed files (240s -> ~10s)
330
+ ),
331
+ HookDefinition(
332
+ name="creosote",
333
+ command=[],
334
+ timeout=360, # Increased from 180 to reduce timeout issues with comprehensive dependency analysis
335
+ stage=HookStage.COMPREHENSIVE,
336
+ manual_stage=True,
337
+ security_level=SecurityLevel.HIGH,
338
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
339
+ ),
340
+ HookDefinition(
341
+ name="complexipy",
342
+ command=[],
343
+ timeout=300, # Increased from 120 to reduce timeout issues with comprehensive complexity analysis
344
+ stage=HookStage.COMPREHENSIVE,
345
+ manual_stage=True,
346
+ security_level=SecurityLevel.MEDIUM,
347
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
348
+ accepts_file_paths=True, # Phase 10.5: Incremental execution on changed files
349
+ ),
350
+ HookDefinition(
351
+ name="check-jsonschema",
352
+ command=[],
353
+ timeout=180, # Increased from 60 to reduce timeout issues with complex schema validation
354
+ stage=HookStage.COMPREHENSIVE,
355
+ manual_stage=True,
356
+ security_level=SecurityLevel.HIGH,
357
+ use_precommit_legacy=False, # Phase 8.4: Direct invocation
358
+ accepts_file_paths=True, # Phase 10.4.4: File-level schema validator
359
+ ),
360
+ ]
361
+
362
+
363
+ FAST_STRATEGY = HookStrategy(
364
+ name="fast",
365
+ hooks=FAST_HOOKS,
366
+ timeout=300, # Increased from 60 to accommodate all increased hook timeouts
367
+ retry_policy=RetryPolicy.FORMATTING_ONLY,
368
+ parallel=True, # Phase 6: Enable parallel execution for 2-3x speedup
369
+ max_workers=4, # Optimal concurrency for fast hooks
370
+ )
371
+
372
+ COMPREHENSIVE_STRATEGY = HookStrategy(
373
+ name="comprehensive",
374
+ hooks=COMPREHENSIVE_HOOKS,
375
+ timeout=1800, # Increased from 300 to accommodate all increased hook timeouts
376
+ retry_policy=RetryPolicy.NONE,
377
+ parallel=True, # Phase 6: Enable parallel execution for 2x speedup
378
+ max_workers=4, # Optimal concurrency for comprehensive hooks
379
+ )
380
+
381
+
382
+ class HookConfigLoader:
383
+ @staticmethod
384
+ def load_strategy(name: str, _: Path | None = None) -> HookStrategy:
385
+ if name == "fast":
386
+ return FAST_STRATEGY
387
+ if name == "comprehensive":
388
+ return COMPREHENSIVE_STRATEGY
389
+ msg = f"Unknown hook strategy: {name}"
390
+ raise ValueError(msg)
@@ -0,0 +1,239 @@
1
+ """Settings loader for ACB configuration with YAML support.
2
+
3
+ This module provides utilities for loading ACB Settings from YAML files
4
+ with support for configuration layering and environment-specific overrides.
5
+
6
+ Configuration Priority (highest to lowest):
7
+ 1. settings/local.yaml (local overrides, gitignored)
8
+ 2. settings/crackerjack.yaml (main configuration)
9
+ 3. Default values from Settings class
10
+
11
+ Example:
12
+ >>> from crackerjack.config import CrackerjackSettings
13
+ >>> settings = CrackerjackSettings.load()
14
+ >>> settings.verbose
15
+ False
16
+
17
+ >>> # Async loading with full ACB initialization
18
+ >>> settings = await CrackerjackSettings.load_async()
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import logging
24
+ import typing as t
25
+ from pathlib import Path
26
+ from typing import TypeVar
27
+
28
+ import yaml
29
+ from acb.config import Settings
30
+
31
+ logger = logging.getLogger(__name__)
32
+
33
+ T = TypeVar("T", bound=Settings)
34
+
35
+
36
+ def _load_single_config_file(config_file: Path) -> dict[str, t.Any]:
37
+ """Load a single config file and return its data."""
38
+ if not config_file.exists():
39
+ logger.debug(f"Configuration file not found: {config_file}")
40
+ return {}
41
+
42
+ try:
43
+ with config_file.open() as f:
44
+ loaded_data: t.Any = yaml.safe_load(f)
45
+ if isinstance(loaded_data, dict):
46
+ logger.debug(f"Loaded configuration from {config_file}")
47
+ return loaded_data
48
+ else:
49
+ logger.warning(
50
+ f"Invalid YAML format in {config_file}: expected dict, got {type(loaded_data).__name__}"
51
+ )
52
+ return {}
53
+ except yaml.YAMLError as e:
54
+ logger.error(f"Failed to parse YAML from {config_file}: {e}")
55
+ return {}
56
+ except OSError as e:
57
+ logger.error(f"Failed to read {config_file}: {e}")
58
+ return {}
59
+
60
+
61
+ def _merge_config_data(config_files: list[Path]) -> dict[str, t.Any]:
62
+ """Merge data from all config files."""
63
+ merged_data = {}
64
+ for config_file in config_files:
65
+ file_data = _load_single_config_file(config_file)
66
+ merged_data.update(file_data)
67
+ return merged_data
68
+
69
+
70
+ def load_settings[T: Settings](
71
+ settings_class: type[T],
72
+ settings_dir: Path | None = None,
73
+ ) -> T:
74
+ """Load settings from YAML files with layered configuration.
75
+
76
+ This function loads configuration from multiple YAML files and merges them
77
+ with priority-based overriding. Unknown YAML fields are silently ignored.
78
+
79
+ Args:
80
+ settings_class: The Settings class to instantiate
81
+ settings_dir: Directory containing YAML files (default: ./settings)
82
+
83
+ Returns:
84
+ Initialized Settings instance with merged configuration
85
+
86
+ Configuration Priority (highest to lowest):
87
+ 1. settings/local.yaml (local overrides, gitignored)
88
+ 2. settings/crackerjack.yaml (main configuration)
89
+ 3. Default values from Settings class
90
+
91
+ Example:
92
+ >>> class MySettings(Settings):
93
+ ... debug: bool = False
94
+ ... max_workers: int = 4
95
+ >>> settings = load_settings(MySettings)
96
+ >>> settings.debug
97
+ False
98
+ """
99
+ if settings_dir is None:
100
+ settings_dir = Path.cwd() / "settings"
101
+
102
+ # Configuration files in priority order (lowest to highest)
103
+ config_files = [
104
+ settings_dir / "crackerjack.yaml",
105
+ settings_dir / "local.yaml",
106
+ ]
107
+
108
+ # Load and merge data from all config files
109
+ merged_data = _merge_config_data(config_files)
110
+
111
+ # Filter to only fields defined in the Settings class
112
+ # This prevents validation errors from unknown YAML keys
113
+ relevant_data = {
114
+ k: v for k, v in merged_data.items() if k in settings_class.model_fields
115
+ }
116
+
117
+ # Log filtered fields if any were excluded
118
+ excluded_fields = set(merged_data.keys()) - set(relevant_data.keys())
119
+ if excluded_fields:
120
+ logger.debug(
121
+ f"Ignored unknown configuration fields: {', '.join(sorted(excluded_fields))}"
122
+ )
123
+
124
+ logger.info(
125
+ f"Loaded {len(relevant_data)} configuration values for {settings_class.__name__}"
126
+ )
127
+
128
+ # Synchronous initialization (safe for module-level code)
129
+ return settings_class(**relevant_data)
130
+
131
+
132
+ async def load_settings_async[T: Settings](
133
+ settings_class: type[T],
134
+ settings_dir: Path | None = None,
135
+ ) -> T:
136
+ """Load settings asynchronously with full ACB initialization.
137
+
138
+ This function provides the same configuration loading as load_settings()
139
+ but uses ACB's async initialization which includes secret loading and
140
+ other async setup operations.
141
+
142
+ Args:
143
+ settings_class: The Settings class to instantiate
144
+ settings_dir: Directory containing YAML files (default: ./settings)
145
+
146
+ Returns:
147
+ Initialized Settings instance with async initialization complete
148
+
149
+ Note:
150
+ Use this for application runtime when async context is available.
151
+ For module-level initialization, use synchronous load_settings().
152
+
153
+ Example:
154
+ >>> settings = await load_settings_async(CrackerjackSettings)
155
+ >>> settings.verbose
156
+ False
157
+ """
158
+ if settings_dir is None:
159
+ settings_dir = Path.cwd() / "settings"
160
+
161
+ # Configuration files in priority order (lowest to highest)
162
+ config_files = [
163
+ settings_dir / "crackerjack.yaml",
164
+ settings_dir / "local.yaml",
165
+ ]
166
+
167
+ # Load and merge YAML data from all files
168
+ merged_data = await _load_yaml_data(config_files)
169
+
170
+ # Process the loaded data
171
+ relevant_data = _filter_relevant_data(merged_data, settings_class)
172
+ _log_filtered_fields(merged_data, relevant_data)
173
+ _log_load_info(settings_class, relevant_data)
174
+
175
+ # Async initialization (loads secrets, performs async setup)
176
+ return await settings_class.create_async(**relevant_data)
177
+
178
+
179
+ async def _load_yaml_data(config_files: list[Path]) -> dict[str, t.Any]:
180
+ """Load and merge YAML data from configuration files."""
181
+ merged_data: dict[str, t.Any] = {}
182
+ for config_file in config_files:
183
+ file_data = await _load_single_yaml_file(config_file)
184
+ if file_data is not None:
185
+ merged_data.update(file_data)
186
+ elif not config_file.exists():
187
+ logger.debug(f"Configuration file not found: {config_file}")
188
+ return merged_data
189
+
190
+
191
+ async def _load_single_yaml_file(config_file: Path) -> dict[str, t.Any] | None:
192
+ """Load a single YAML file and return its content."""
193
+ if not config_file.exists():
194
+ return None
195
+
196
+ try:
197
+ with config_file.open() as f:
198
+ loaded_data: t.Any = yaml.safe_load(f)
199
+ if isinstance(loaded_data, dict):
200
+ logger.debug(f"Loaded configuration from {config_file}")
201
+ return loaded_data
202
+ else:
203
+ logger.warning(
204
+ f"Invalid YAML format in {config_file}: expected dict, got {type(loaded_data).__name__}"
205
+ )
206
+ return {}
207
+ except yaml.YAMLError as e:
208
+ logger.error(f"Failed to parse YAML from {config_file}: {e}")
209
+ return None
210
+ except OSError as e:
211
+ logger.error(f"Failed to read {config_file}: {e}")
212
+ return None
213
+
214
+
215
+ def _filter_relevant_data[T: Settings](
216
+ merged_data: dict[str, t.Any], settings_class: type[T]
217
+ ) -> dict[str, t.Any]:
218
+ """Filter the loaded data to only fields defined in the Settings class."""
219
+ return {k: v for k, v in merged_data.items() if k in settings_class.model_fields}
220
+
221
+
222
+ def _log_filtered_fields(
223
+ merged_data: dict[str, t.Any], relevant_data: dict[str, t.Any]
224
+ ) -> None:
225
+ """Log any fields that were excluded due to not being in the settings class."""
226
+ excluded_fields = set(merged_data.keys()) - set(relevant_data.keys())
227
+ if excluded_fields:
228
+ logger.debug(
229
+ f"Ignored unknown configuration fields: {', '.join(sorted(excluded_fields))}"
230
+ )
231
+
232
+
233
+ def _log_load_info[T: Settings](
234
+ settings_class: type[T], relevant_data: dict[str, t.Any]
235
+ ) -> None:
236
+ """Log information about the loaded configuration."""
237
+ logger.info(
238
+ f"Loaded {len(relevant_data)} configuration values for {settings_class.__name__} (async)"
239
+ )