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,346 @@
1
+ """Workflow event bus built on top of ACB event primitives.
2
+
3
+ Provides a lightweight in-process event bus that uses ``acb.events`` data
4
+ structures so the rest of the codebase can adopt the forthcoming ACB EventBus
5
+ without waiting on external messaging infrastructure. Subscribers register
6
+ handlers for workflow event types and publishers emit events that are dispatched
7
+ asynchronously.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import asyncio
13
+ import logging
14
+ import threading
15
+ import typing as t
16
+ from dataclasses import dataclass, field
17
+ from enum import Enum
18
+
19
+ from acb.events import (
20
+ Event,
21
+ EventHandlerResult,
22
+ FunctionalEventHandler,
23
+ create_event,
24
+ )
25
+ from acb.events._base import EventSubscription
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+ HandlerCallable = t.Callable[
30
+ [Event], t.Awaitable[EventHandlerResult] | EventHandlerResult
31
+ ]
32
+
33
+
34
+ class WorkflowEvent(str, Enum):
35
+ """Standard workflow events emitted inside Crackerjack."""
36
+
37
+ WORKFLOW_STARTED = "workflow.started"
38
+ WORKFLOW_SESSION_INITIALIZING = "workflow.session.initializing"
39
+ WORKFLOW_SESSION_READY = "workflow.session.ready"
40
+ CONFIG_PHASE_STARTED = "workflow.config.started"
41
+ CONFIG_PHASE_COMPLETED = "workflow.config.completed"
42
+ WORKFLOW_COMPLETED = "workflow.completed"
43
+ WORKFLOW_FAILED = "workflow.failed"
44
+ WORKFLOW_INTERRUPTED = "workflow.interrupted"
45
+
46
+ QUALITY_PHASE_STARTED = "workflow.quality.started"
47
+ QUALITY_PHASE_COMPLETED = "workflow.quality.completed"
48
+
49
+ PUBLISH_PHASE_STARTED = "workflow.publish.started"
50
+ PUBLISH_PHASE_COMPLETED = "workflow.publish.completed"
51
+
52
+ COMMIT_PHASE_STARTED = "workflow.commit.started"
53
+ COMMIT_PHASE_COMPLETED = "workflow.commit.completed"
54
+
55
+ HOOK_STRATEGY_STARTED = "hooks.strategy.started"
56
+ HOOK_STRATEGY_COMPLETED = "hooks.strategy.completed"
57
+ HOOK_STRATEGY_FAILED = "hooks.strategy.failed"
58
+
59
+ HOOK_EXECUTION_STARTED = "hooks.execution.started"
60
+ HOOK_EXECUTION_COMPLETED = "hooks.execution.completed"
61
+ HOOK_EXECUTION_FAILED = "hooks.execution.failed"
62
+
63
+ def __str__(self) -> str: # pragma: no cover - trivial
64
+ return str(self.value)
65
+
66
+
67
+ @dataclass
68
+ class WorkflowEventDispatchResult:
69
+ """Result returned from publishing an event."""
70
+
71
+ event: Event
72
+ results: list[EventHandlerResult] = field(default_factory=list)
73
+
74
+
75
+ @dataclass
76
+ class _SubscriptionEntry:
77
+ """Internal representation of a subscription with concurrency control."""
78
+
79
+ subscription: EventSubscription
80
+ description: str | None = None
81
+ semaphore: asyncio.Semaphore = field(default_factory=lambda: asyncio.Semaphore(1))
82
+ max_retries: int = 0
83
+ retry_backoff: float = 0.5
84
+
85
+ def __post_init__(self) -> None:
86
+ max_concurrent = self.subscription.max_concurrent or 1
87
+ self.semaphore = asyncio.Semaphore(max_concurrent)
88
+
89
+
90
+ class WorkflowEventBus:
91
+ """In-process event bus compatible with ACB event handlers."""
92
+
93
+ def __init__(self) -> None:
94
+ self._subscriptions: dict[str | None, dict[str, _SubscriptionEntry]] = {}
95
+ self._lock = threading.RLock()
96
+ self._default_handlers_registered = False
97
+
98
+ def subscribe(
99
+ self,
100
+ event_type: WorkflowEvent | str | None,
101
+ handler: HandlerCallable,
102
+ *,
103
+ predicate: t.Callable[[Event], bool] | None = None,
104
+ max_concurrent: int | None = None,
105
+ description: str | None = None,
106
+ max_retries: int = 0,
107
+ retry_backoff: float = 0.5,
108
+ ) -> str:
109
+ """Register a handler for an event type.
110
+
111
+ Args:
112
+ event_type: WorkflowEvent enum value, string, or ``None`` for wildcard.
113
+ handler: Callable invoked when the event is published.
114
+ predicate: Optional additional filter predicate.
115
+ max_concurrent: Maximum concurrent invocations for this handler.
116
+ description: Optional human readable identifier.
117
+ max_retries: Number of retry attempts when a handler raises.
118
+ retry_backoff: Initial backoff delay (seconds) between retries; doubles each attempt.
119
+
120
+ Returns:
121
+ Subscription ID string.
122
+ """
123
+ event_type_value = (
124
+ event_type.value if isinstance(event_type, WorkflowEvent) else event_type
125
+ )
126
+
127
+ event_handler = FunctionalEventHandler(
128
+ handler,
129
+ event_type=event_type_value,
130
+ predicate=predicate,
131
+ )
132
+ subscription = EventSubscription(
133
+ handler=event_handler,
134
+ event_type=event_type_value,
135
+ predicate=predicate,
136
+ max_concurrent=max_concurrent or 1,
137
+ )
138
+ entry = _SubscriptionEntry(
139
+ subscription=subscription,
140
+ description=description,
141
+ max_retries=max_retries,
142
+ retry_backoff=retry_backoff,
143
+ )
144
+
145
+ key = event_type_value
146
+
147
+ with self._lock:
148
+ bucket = self._subscriptions.setdefault(key, {})
149
+ bucket[str(subscription.subscription_id)] = entry
150
+
151
+ logger.debug(
152
+ "Registered workflow event subscription",
153
+ extra={
154
+ "event_type": event_type_value or "*",
155
+ "subscription_id": str(subscription.subscription_id),
156
+ "description": description,
157
+ "max_concurrent": max_concurrent or 1,
158
+ "max_retries": max_retries,
159
+ "retry_backoff": retry_backoff,
160
+ },
161
+ )
162
+
163
+ return str(subscription.subscription_id)
164
+
165
+ def unsubscribe(self, subscription_id: str) -> bool:
166
+ """Remove a subscription by ID."""
167
+ with self._lock:
168
+ for bucket in self._subscriptions.values():
169
+ if subscription_id in bucket:
170
+ del bucket[subscription_id]
171
+ logger.debug(
172
+ "Removed workflow event subscription",
173
+ extra={"subscription_id": subscription_id},
174
+ )
175
+ return True
176
+ return False
177
+
178
+ def list_subscriptions(self) -> list[dict[str, t.Any]]:
179
+ """Return summary information for registered subscriptions."""
180
+ data: list[dict[str, t.Any]] = []
181
+ with self._lock:
182
+ for event_type, bucket in self._subscriptions.items():
183
+ for subscription_id, entry in bucket.items():
184
+ data.append(
185
+ {
186
+ "subscription_id": subscription_id,
187
+ "event_type": event_type or "*",
188
+ "description": entry.description,
189
+ "max_concurrent": entry.subscription.max_concurrent,
190
+ }
191
+ )
192
+ return data
193
+
194
+ async def publish(
195
+ self,
196
+ event_type: WorkflowEvent | str,
197
+ payload: dict[str, t.Any] | None = None,
198
+ *,
199
+ source: str = "crackerjack.workflow",
200
+ **metadata: t.Any,
201
+ ) -> WorkflowEventDispatchResult:
202
+ """Publish an event to subscribed handlers."""
203
+ event_type_value = (
204
+ event_type.value if isinstance(event_type, WorkflowEvent) else event_type
205
+ )
206
+ payload = payload or {}
207
+ event = create_event(event_type_value, source, payload, **metadata)
208
+
209
+ entries = self._collect_subscriptions(event)
210
+ if not entries:
211
+ logger.debug(
212
+ "Workflow event published with no subscribers",
213
+ extra={"event_type": event_type_value},
214
+ )
215
+ return WorkflowEventDispatchResult(event=event, results=[])
216
+
217
+ tasks = [self._invoke_subscription(entry, event) for entry in entries]
218
+ raw_results = await asyncio.gather(*tasks, return_exceptions=True)
219
+
220
+ results: list[EventHandlerResult] = []
221
+ for entry, result in zip(entries, raw_results, strict=False):
222
+ if isinstance(result, EventHandlerResult):
223
+ results.append(result)
224
+ continue
225
+
226
+ if isinstance(result, Exception):
227
+ logger.exception(
228
+ "Workflow event handler raised an exception",
229
+ extra={
230
+ "event_type": event_type_value,
231
+ "subscription_id": entry.subscription.subscription_id,
232
+ "description": entry.description,
233
+ },
234
+ exc_info=result,
235
+ )
236
+ results.append(
237
+ EventHandlerResult(
238
+ success=False,
239
+ error_message=str(result),
240
+ metadata={
241
+ "subscription_id": str(entry.subscription.subscription_id)
242
+ },
243
+ )
244
+ )
245
+ continue
246
+
247
+ # Allow handlers to return truthy values instead of EventHandlerResult
248
+ success = True if result is None else bool(result)
249
+ results.append(
250
+ EventHandlerResult(
251
+ success=success,
252
+ metadata={
253
+ "subscription_id": str(entry.subscription.subscription_id)
254
+ },
255
+ )
256
+ )
257
+
258
+ return WorkflowEventDispatchResult(event=event, results=results)
259
+
260
+ def register_logging_handler(self) -> None:
261
+ """Install a default debug logging handler (idempotent)."""
262
+ if self._default_handlers_registered:
263
+ return
264
+
265
+ async def _log_event(event: Event) -> EventHandlerResult:
266
+ logger.debug(
267
+ "Workflow event dispatched",
268
+ extra={
269
+ "event_type": event.metadata.event_type,
270
+ "source": event.metadata.source,
271
+ "payload": event.payload,
272
+ },
273
+ )
274
+ return EventHandlerResult(success=True)
275
+
276
+ self.subscribe(
277
+ event_type=None,
278
+ handler=_log_event,
279
+ description="workflow.logging",
280
+ )
281
+ self._default_handlers_registered = True
282
+
283
+ def _collect_subscriptions(self, event: Event) -> list[_SubscriptionEntry]:
284
+ with self._lock:
285
+ specific = list(
286
+ self._subscriptions.get(event.metadata.event_type, {}).values()
287
+ )
288
+ wildcard = list(self._subscriptions.get(None, {}).values())
289
+ return specific + wildcard
290
+
291
+ async def _invoke_subscription(
292
+ self,
293
+ entry: _SubscriptionEntry,
294
+ event: Event,
295
+ ) -> EventHandlerResult:
296
+ handler = entry.subscription.handler
297
+ if not handler.can_handle(event):
298
+ return EventHandlerResult(
299
+ success=True,
300
+ metadata={
301
+ "subscription_id": str(entry.subscription.subscription_id),
302
+ "skipped": True,
303
+ },
304
+ )
305
+
306
+ async with entry.semaphore:
307
+ attempt = 0
308
+ delay = max(entry.retry_backoff, 0.0)
309
+ while True:
310
+ try:
311
+ return await handler.handle(event)
312
+ except Exception as exc:
313
+ attempt += 1
314
+ if attempt > entry.max_retries:
315
+ logger.exception(
316
+ "Workflow event handler failed after retries",
317
+ extra={
318
+ "subscription_id": str(
319
+ entry.subscription.subscription_id
320
+ ),
321
+ "description": entry.description,
322
+ "event_type": event.metadata.event_type,
323
+ "attempts": attempt,
324
+ },
325
+ exc_info=exc,
326
+ )
327
+ raise
328
+
329
+ logger.warning(
330
+ "Workflow event handler raised; retrying",
331
+ extra={
332
+ "subscription_id": str(entry.subscription.subscription_id),
333
+ "description": entry.description,
334
+ "event_type": event.metadata.event_type,
335
+ "attempt": attempt,
336
+ "max_retries": entry.max_retries,
337
+ "retry_delay": delay,
338
+ },
339
+ exc_info=exc,
340
+ )
341
+ if delay > 0:
342
+ await asyncio.sleep(delay)
343
+ delay *= 2
344
+
345
+
346
+ __all__ = ["WorkflowEventBus", "WorkflowEvent", "WorkflowEventDispatchResult"]
@@ -0,0 +1,301 @@
1
+ > Crackerjack Docs: [Main](<../../README.md>) | [Crackerjack Package](<../README.md>) | [Exceptions](<./README.md>)
2
+
3
+ # Exceptions
4
+
5
+ Custom exception types with rich formatting and context-aware error reporting. Provides enhanced UX for tool execution failures and configuration issues.
6
+
7
+ ## Exception Hierarchy
8
+
9
+ ```
10
+ BaseException
11
+ └── Exception
12
+ ├── ToolExecutionError # Rich tool execution failures
13
+ └── ConfigIntegrityError # Configuration validation issues
14
+ ```
15
+
16
+ ## Custom Exception Types
17
+
18
+ ### ToolExecutionError
19
+
20
+ Enhanced error with rich formatting for failed tool executions. Provides detailed context including exit codes, stdout/stderr, duration, and actionable suggestions.
21
+
22
+ **Features:**
23
+
24
+ - Rich console formatting with syntax highlighting
25
+ - Automatic output truncation for readability
26
+ - Actionable error messages with suggestions
27
+ - Context tracking (command, cwd, duration)
28
+ - Integration with Crackerjack's console system
29
+
30
+ **Constructor:**
31
+
32
+ ```python
33
+ ToolExecutionError(
34
+ tool: str, # Tool name that failed
35
+ exit_code: int, # Process exit code
36
+ stdout: str = "", # Standard output
37
+ stderr: str = "", # Standard error
38
+ command: list[str] | None = None, # Full command executed
39
+ cwd: Path | None = None, # Working directory
40
+ duration: float | None = None, # Execution duration (seconds)
41
+ )
42
+ ```
43
+
44
+ **Usage Example:**
45
+
46
+ ```python
47
+ from crackerjack.exceptions import ToolExecutionError
48
+ from pathlib import Path
49
+
50
+ try:
51
+ result = subprocess.run(
52
+ ["ruff", "check", "."], capture_output=True, text=True, cwd=project_dir
53
+ )
54
+ if result.returncode != 0:
55
+ raise ToolExecutionError(
56
+ tool="ruff",
57
+ exit_code=result.returncode,
58
+ stdout=result.stdout,
59
+ stderr=result.stderr,
60
+ command=["ruff", "check", "."],
61
+ cwd=project_dir,
62
+ duration=2.5,
63
+ )
64
+ except ToolExecutionError as e:
65
+ # Rich formatted output
66
+ console.print(e.format_rich())
67
+
68
+ # Or get actionable message
69
+ print(e.get_actionable_message())
70
+ ```
71
+
72
+ **Rich Formatting:**
73
+
74
+ ```python
75
+ from acb.console import Console
76
+
77
+ console = Console()
78
+
79
+ # Create error
80
+ error = ToolExecutionError(
81
+ tool="pytest",
82
+ exit_code=1,
83
+ stderr="test_example.py::test_feature FAILED",
84
+ duration=3.2,
85
+ )
86
+
87
+ # Display with rich formatting
88
+ panel = error.format_rich(console)
89
+ console.print(panel)
90
+ ```
91
+
92
+ **Output:**
93
+
94
+ ```
95
+ ╭─ ❌ Tool Execution Failed: pytest ─────────────╮
96
+ │ Tool: pytest │
97
+ │ Exit Code: 1 │
98
+ │ Duration: 3.20s │
99
+ │ │
100
+ │ Error Output: │
101
+ │ test_example.py::test_feature FAILED │
102
+ ╰────────────────────────────────────────────────╯
103
+ ```
104
+
105
+ **Actionable Messages:**
106
+
107
+ The `get_actionable_message()` method provides smart error pattern detection:
108
+
109
+ ```python
110
+ error = ToolExecutionError(
111
+ tool="ruff", exit_code=1, stderr="ModuleNotFoundError: No module named 'requests'"
112
+ )
113
+
114
+ print(error.get_actionable_message())
115
+ # Output:
116
+ # Tool 'ruff' failed with exit code 1
117
+ # → Check Python dependencies are installed (try: uv sync)
118
+ ```
119
+
120
+ **Common Patterns Detected:**
121
+
122
+ - Permission denied → Check file permissions
123
+ - Command not found → Ensure tool is installed
124
+ - Timeout errors → Increase timeout setting
125
+ - Syntax errors → Check code syntax
126
+ - Import errors → Run dependency sync
127
+ - Type errors → Fix type annotations
128
+ - Out of memory → Reduce batch size
129
+
130
+ ### ConfigIntegrityError
131
+
132
+ Simple exception for configuration validation and integrity issues.
133
+
134
+ **Usage Example:**
135
+
136
+ ```python
137
+ from crackerjack.exceptions import ConfigIntegrityError
138
+
139
+
140
+ def validate_config(config: dict) -> None:
141
+ if "required_field" not in config:
142
+ raise ConfigIntegrityError(
143
+ "Missing required field 'required_field' in configuration"
144
+ )
145
+
146
+ if config.get("version") != "1.0":
147
+ raise ConfigIntegrityError(
148
+ f"Unsupported config version: {config.get('version')}"
149
+ )
150
+ ```
151
+
152
+ ## Error Handling Patterns
153
+
154
+ ### Pattern 1: Tool Execution with Context
155
+
156
+ ```python
157
+ from crackerjack.exceptions import ToolExecutionError
158
+ import subprocess
159
+ import time
160
+
161
+
162
+ def run_tool(tool: str, args: list[str], cwd: Path) -> bool:
163
+ """Run tool with comprehensive error reporting."""
164
+ start = time.time()
165
+
166
+ try:
167
+ result = subprocess.run(
168
+ [tool] + args, capture_output=True, text=True, cwd=cwd, timeout=300
169
+ )
170
+
171
+ if result.returncode != 0:
172
+ raise ToolExecutionError(
173
+ tool=tool,
174
+ exit_code=result.returncode,
175
+ stdout=result.stdout,
176
+ stderr=result.stderr,
177
+ command=[tool] + args,
178
+ cwd=cwd,
179
+ duration=time.time() - start,
180
+ )
181
+
182
+ return True
183
+
184
+ except subprocess.TimeoutExpired as e:
185
+ raise ToolExecutionError(
186
+ tool=tool,
187
+ exit_code=-1,
188
+ stderr=f"Tool execution timed out after {e.timeout}s",
189
+ command=[tool] + args,
190
+ cwd=cwd,
191
+ duration=e.timeout,
192
+ ) from e
193
+ ```
194
+
195
+ ### Pattern 2: Graceful Error Display
196
+
197
+ ```python
198
+ from crackerjack.exceptions import ToolExecutionError
199
+ from acb.console import Console
200
+ from acb.depends import depends
201
+
202
+
203
+ @depends.inject
204
+ def execute_with_nice_errors(func: callable, console: Console = depends()) -> bool:
205
+ """Execute function with rich error formatting."""
206
+ try:
207
+ return func()
208
+ except ToolExecutionError as e:
209
+ console.print(e.format_rich())
210
+ console.print(f"\n[yellow]{e.get_actionable_message()}[/yellow]")
211
+ return False
212
+ ```
213
+
214
+ ### Pattern 3: Config Validation
215
+
216
+ ```python
217
+ from crackerjack.exceptions import ConfigIntegrityError
218
+ from pathlib import Path
219
+ import yaml
220
+
221
+
222
+ def load_and_validate_config(path: Path) -> dict:
223
+ """Load config with integrity validation."""
224
+ if not path.exists():
225
+ raise ConfigIntegrityError(f"Configuration file not found: {path}")
226
+
227
+ with open(path) as f:
228
+ config = yaml.safe_load(f)
229
+
230
+ required = ["version", "project_name", "settings"]
231
+ missing = [k for k in required if k not in config]
232
+
233
+ if missing:
234
+ raise ConfigIntegrityError(
235
+ f"Missing required config fields: {', '.join(missing)}"
236
+ )
237
+
238
+ return config
239
+ ```
240
+
241
+ ## Best Practices
242
+
243
+ ### Use ToolExecutionError for All Tool Failures
244
+
245
+ Provides consistent, rich error reporting across the codebase:
246
+
247
+ ```python
248
+ # ✅ Good - Rich error context
249
+ if exit_code != 0:
250
+ raise ToolExecutionError(
251
+ tool="mypy", exit_code=exit_code, stderr=stderr, duration=duration
252
+ )
253
+
254
+ # ❌ Bad - Generic exception
255
+ if exit_code != 0:
256
+ raise RuntimeError(f"mypy failed: {stderr}")
257
+ ```
258
+
259
+ ### Include All Available Context
260
+
261
+ More context enables better error messages:
262
+
263
+ ```python
264
+ # ✅ Good - Full context
265
+ raise ToolExecutionError(
266
+ tool="pytest",
267
+ exit_code=1,
268
+ stdout=result.stdout,
269
+ stderr=result.stderr,
270
+ command=full_command,
271
+ cwd=project_dir,
272
+ duration=elapsed,
273
+ )
274
+
275
+ # ⚠️ Minimal - Missing helpful context
276
+ raise ToolExecutionError(tool="pytest", exit_code=1)
277
+ ```
278
+
279
+ ### Use format_rich() for User-Facing Errors
280
+
281
+ Provides best UX with Rich console integration:
282
+
283
+ ```python
284
+ try:
285
+ run_checks()
286
+ except ToolExecutionError as e:
287
+ console.print(e.format_rich()) # Beautiful formatting
288
+ console.print(f"\n{e.get_actionable_message()}") # Smart suggestions
289
+ ```
290
+
291
+ ## Implementation Files
292
+
293
+ - **`tool_execution_error.py`** - ToolExecutionError with rich formatting
294
+ - **`config.py`** - ConfigIntegrityError for configuration validation
295
+
296
+ ## Related
297
+
298
+ - [Decorators](<../decorators/README.md>) - Error handling decorators
299
+ - [Errors](../errors/README.md) - Core error types and CrackerjackError base
300
+ - [MCP](<../mcp/README.md>) - Error caching and pattern analysis
301
+ - [Console Integration](https://github.com/Textualize/rich) - Rich console formatting
@@ -0,0 +1,5 @@
1
+ """Custom exceptions for crackerjack."""
2
+
3
+ from .tool_execution_error import ToolExecutionError
4
+
5
+ __all__ = ["ToolExecutionError"]
@@ -0,0 +1,4 @@
1
+ class ConfigIntegrityError(Exception):
2
+ """Custom exception for configuration integrity issues."""
3
+
4
+ pass