crackerjack 0.37.9__py3-none-any.whl → 0.45.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. crackerjack/README.md +19 -0
  2. crackerjack/__init__.py +30 -1
  3. crackerjack/__main__.py +342 -1263
  4. crackerjack/adapters/README.md +18 -0
  5. crackerjack/adapters/__init__.py +27 -5
  6. crackerjack/adapters/_output_paths.py +167 -0
  7. crackerjack/adapters/_qa_adapter_base.py +309 -0
  8. crackerjack/adapters/_tool_adapter_base.py +706 -0
  9. crackerjack/adapters/ai/README.md +65 -0
  10. crackerjack/adapters/ai/__init__.py +5 -0
  11. crackerjack/adapters/ai/claude.py +853 -0
  12. crackerjack/adapters/complexity/README.md +53 -0
  13. crackerjack/adapters/complexity/__init__.py +10 -0
  14. crackerjack/adapters/complexity/complexipy.py +641 -0
  15. crackerjack/adapters/dependency/__init__.py +22 -0
  16. crackerjack/adapters/dependency/pip_audit.py +418 -0
  17. crackerjack/adapters/format/README.md +72 -0
  18. crackerjack/adapters/format/__init__.py +11 -0
  19. crackerjack/adapters/format/mdformat.py +313 -0
  20. crackerjack/adapters/format/ruff.py +516 -0
  21. crackerjack/adapters/lint/README.md +47 -0
  22. crackerjack/adapters/lint/__init__.py +11 -0
  23. crackerjack/adapters/lint/codespell.py +273 -0
  24. crackerjack/adapters/lsp/README.md +49 -0
  25. crackerjack/adapters/lsp/__init__.py +27 -0
  26. crackerjack/adapters/{rust_tool_manager.py → lsp/_manager.py} +3 -3
  27. crackerjack/adapters/{skylos_adapter.py → lsp/skylos.py} +59 -7
  28. crackerjack/adapters/{zuban_adapter.py → lsp/zuban.py} +3 -6
  29. crackerjack/adapters/refactor/README.md +59 -0
  30. crackerjack/adapters/refactor/__init__.py +12 -0
  31. crackerjack/adapters/refactor/creosote.py +318 -0
  32. crackerjack/adapters/refactor/refurb.py +406 -0
  33. crackerjack/adapters/refactor/skylos.py +494 -0
  34. crackerjack/adapters/sast/README.md +132 -0
  35. crackerjack/adapters/sast/__init__.py +32 -0
  36. crackerjack/adapters/sast/_base.py +201 -0
  37. crackerjack/adapters/sast/bandit.py +423 -0
  38. crackerjack/adapters/sast/pyscn.py +405 -0
  39. crackerjack/adapters/sast/semgrep.py +241 -0
  40. crackerjack/adapters/security/README.md +111 -0
  41. crackerjack/adapters/security/__init__.py +17 -0
  42. crackerjack/adapters/security/gitleaks.py +339 -0
  43. crackerjack/adapters/type/README.md +52 -0
  44. crackerjack/adapters/type/__init__.py +12 -0
  45. crackerjack/adapters/type/pyrefly.py +402 -0
  46. crackerjack/adapters/type/ty.py +402 -0
  47. crackerjack/adapters/type/zuban.py +522 -0
  48. crackerjack/adapters/utility/README.md +51 -0
  49. crackerjack/adapters/utility/__init__.py +10 -0
  50. crackerjack/adapters/utility/checks.py +884 -0
  51. crackerjack/agents/README.md +264 -0
  52. crackerjack/agents/__init__.py +40 -12
  53. crackerjack/agents/base.py +1 -0
  54. crackerjack/agents/claude_code_bridge.py +641 -0
  55. crackerjack/agents/coordinator.py +49 -53
  56. crackerjack/agents/dry_agent.py +187 -3
  57. crackerjack/agents/enhanced_coordinator.py +279 -0
  58. crackerjack/agents/enhanced_proactive_agent.py +185 -0
  59. crackerjack/agents/error_middleware.py +53 -0
  60. crackerjack/agents/formatting_agent.py +6 -8
  61. crackerjack/agents/helpers/__init__.py +9 -0
  62. crackerjack/agents/helpers/performance/__init__.py +22 -0
  63. crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
  64. crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
  65. crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
  66. crackerjack/agents/helpers/refactoring/__init__.py +22 -0
  67. crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
  68. crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
  69. crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
  70. crackerjack/agents/helpers/test_creation/__init__.py +19 -0
  71. crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
  72. crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
  73. crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
  74. crackerjack/agents/performance_agent.py +121 -1152
  75. crackerjack/agents/refactoring_agent.py +156 -655
  76. crackerjack/agents/semantic_agent.py +479 -0
  77. crackerjack/agents/semantic_helpers.py +356 -0
  78. crackerjack/agents/test_creation_agent.py +19 -1605
  79. crackerjack/api.py +5 -7
  80. crackerjack/cli/README.md +394 -0
  81. crackerjack/cli/__init__.py +1 -1
  82. crackerjack/cli/cache_handlers.py +23 -18
  83. crackerjack/cli/cache_handlers_enhanced.py +1 -4
  84. crackerjack/cli/facade.py +70 -8
  85. crackerjack/cli/formatting.py +13 -0
  86. crackerjack/cli/handlers/__init__.py +85 -0
  87. crackerjack/cli/handlers/advanced.py +103 -0
  88. crackerjack/cli/handlers/ai_features.py +62 -0
  89. crackerjack/cli/handlers/analytics.py +479 -0
  90. crackerjack/cli/handlers/changelog.py +271 -0
  91. crackerjack/cli/handlers/config_handlers.py +16 -0
  92. crackerjack/cli/handlers/coverage.py +84 -0
  93. crackerjack/cli/handlers/documentation.py +280 -0
  94. crackerjack/cli/handlers/main_handlers.py +497 -0
  95. crackerjack/cli/handlers/monitoring.py +371 -0
  96. crackerjack/cli/handlers.py +249 -49
  97. crackerjack/cli/interactive.py +8 -5
  98. crackerjack/cli/options.py +203 -110
  99. crackerjack/cli/semantic_handlers.py +292 -0
  100. crackerjack/cli/version.py +19 -0
  101. crackerjack/code_cleaner.py +60 -24
  102. crackerjack/config/README.md +472 -0
  103. crackerjack/config/__init__.py +256 -0
  104. crackerjack/config/global_lock_config.py +191 -54
  105. crackerjack/config/hooks.py +188 -16
  106. crackerjack/config/loader.py +239 -0
  107. crackerjack/config/settings.py +141 -0
  108. crackerjack/config/tool_commands.py +331 -0
  109. crackerjack/core/README.md +393 -0
  110. crackerjack/core/async_workflow_orchestrator.py +79 -53
  111. crackerjack/core/autofix_coordinator.py +22 -9
  112. crackerjack/core/container.py +10 -9
  113. crackerjack/core/enhanced_container.py +9 -9
  114. crackerjack/core/performance.py +1 -1
  115. crackerjack/core/performance_monitor.py +5 -3
  116. crackerjack/core/phase_coordinator.py +1018 -634
  117. crackerjack/core/proactive_workflow.py +3 -3
  118. crackerjack/core/retry.py +275 -0
  119. crackerjack/core/service_watchdog.py +167 -23
  120. crackerjack/core/session_coordinator.py +187 -382
  121. crackerjack/core/timeout_manager.py +161 -44
  122. crackerjack/core/workflow/__init__.py +21 -0
  123. crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
  124. crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
  125. crackerjack/core/workflow/workflow_issue_parser.py +714 -0
  126. crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
  127. crackerjack/core/workflow/workflow_security_gates.py +400 -0
  128. crackerjack/core/workflow_orchestrator.py +1247 -953
  129. crackerjack/data/README.md +11 -0
  130. crackerjack/data/__init__.py +8 -0
  131. crackerjack/data/models.py +79 -0
  132. crackerjack/data/repository.py +210 -0
  133. crackerjack/decorators/README.md +180 -0
  134. crackerjack/decorators/__init__.py +35 -0
  135. crackerjack/decorators/error_handling.py +649 -0
  136. crackerjack/decorators/error_handling_decorators.py +334 -0
  137. crackerjack/decorators/helpers.py +58 -0
  138. crackerjack/decorators/patterns.py +281 -0
  139. crackerjack/decorators/utils.py +58 -0
  140. crackerjack/docs/README.md +11 -0
  141. crackerjack/docs/generated/api/CLI_REFERENCE.md +1 -1
  142. crackerjack/documentation/README.md +11 -0
  143. crackerjack/documentation/ai_templates.py +1 -1
  144. crackerjack/documentation/dual_output_generator.py +11 -9
  145. crackerjack/documentation/reference_generator.py +104 -59
  146. crackerjack/dynamic_config.py +52 -61
  147. crackerjack/errors.py +1 -1
  148. crackerjack/events/README.md +11 -0
  149. crackerjack/events/__init__.py +16 -0
  150. crackerjack/events/telemetry.py +175 -0
  151. crackerjack/events/workflow_bus.py +346 -0
  152. crackerjack/exceptions/README.md +301 -0
  153. crackerjack/exceptions/__init__.py +5 -0
  154. crackerjack/exceptions/config.py +4 -0
  155. crackerjack/exceptions/tool_execution_error.py +245 -0
  156. crackerjack/executors/README.md +591 -0
  157. crackerjack/executors/__init__.py +2 -0
  158. crackerjack/executors/async_hook_executor.py +539 -77
  159. crackerjack/executors/cached_hook_executor.py +3 -3
  160. crackerjack/executors/hook_executor.py +967 -102
  161. crackerjack/executors/hook_lock_manager.py +31 -22
  162. crackerjack/executors/individual_hook_executor.py +66 -32
  163. crackerjack/executors/lsp_aware_hook_executor.py +136 -57
  164. crackerjack/executors/progress_hook_executor.py +282 -0
  165. crackerjack/executors/tool_proxy.py +23 -7
  166. crackerjack/hooks/README.md +485 -0
  167. crackerjack/hooks/lsp_hook.py +8 -9
  168. crackerjack/intelligence/README.md +557 -0
  169. crackerjack/interactive.py +37 -10
  170. crackerjack/managers/README.md +369 -0
  171. crackerjack/managers/async_hook_manager.py +41 -57
  172. crackerjack/managers/hook_manager.py +449 -79
  173. crackerjack/managers/publish_manager.py +81 -36
  174. crackerjack/managers/test_command_builder.py +290 -12
  175. crackerjack/managers/test_executor.py +93 -8
  176. crackerjack/managers/test_manager.py +1082 -75
  177. crackerjack/managers/test_progress.py +118 -26
  178. crackerjack/mcp/README.md +374 -0
  179. crackerjack/mcp/cache.py +25 -2
  180. crackerjack/mcp/client_runner.py +35 -18
  181. crackerjack/mcp/context.py +9 -9
  182. crackerjack/mcp/dashboard.py +24 -8
  183. crackerjack/mcp/enhanced_progress_monitor.py +34 -23
  184. crackerjack/mcp/file_monitor.py +27 -6
  185. crackerjack/mcp/progress_components.py +45 -34
  186. crackerjack/mcp/progress_monitor.py +6 -9
  187. crackerjack/mcp/rate_limiter.py +11 -7
  188. crackerjack/mcp/server.py +2 -0
  189. crackerjack/mcp/server_core.py +187 -55
  190. crackerjack/mcp/service_watchdog.py +12 -9
  191. crackerjack/mcp/task_manager.py +2 -2
  192. crackerjack/mcp/tools/README.md +27 -0
  193. crackerjack/mcp/tools/__init__.py +2 -0
  194. crackerjack/mcp/tools/core_tools.py +75 -52
  195. crackerjack/mcp/tools/execution_tools.py +87 -31
  196. crackerjack/mcp/tools/intelligence_tools.py +2 -2
  197. crackerjack/mcp/tools/proactive_tools.py +1 -1
  198. crackerjack/mcp/tools/semantic_tools.py +584 -0
  199. crackerjack/mcp/tools/utility_tools.py +180 -132
  200. crackerjack/mcp/tools/workflow_executor.py +87 -46
  201. crackerjack/mcp/websocket/README.md +31 -0
  202. crackerjack/mcp/websocket/app.py +11 -1
  203. crackerjack/mcp/websocket/event_bridge.py +188 -0
  204. crackerjack/mcp/websocket/jobs.py +27 -4
  205. crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
  206. crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
  207. crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
  208. crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
  209. crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
  210. crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
  211. crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
  212. crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
  213. crackerjack/mcp/websocket/monitoring/factory.py +109 -0
  214. crackerjack/mcp/websocket/monitoring/filters.py +10 -0
  215. crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
  216. crackerjack/mcp/websocket/monitoring/models.py +90 -0
  217. crackerjack/mcp/websocket/monitoring/utils.py +171 -0
  218. crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
  219. crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
  220. crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
  221. crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
  222. crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
  223. crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
  224. crackerjack/mcp/websocket/monitoring_endpoints.py +16 -2930
  225. crackerjack/mcp/websocket/server.py +1 -3
  226. crackerjack/mcp/websocket/websocket_handler.py +107 -6
  227. crackerjack/models/README.md +308 -0
  228. crackerjack/models/__init__.py +10 -1
  229. crackerjack/models/config.py +639 -22
  230. crackerjack/models/config_adapter.py +6 -6
  231. crackerjack/models/protocols.py +1167 -23
  232. crackerjack/models/pydantic_models.py +320 -0
  233. crackerjack/models/qa_config.py +145 -0
  234. crackerjack/models/qa_results.py +134 -0
  235. crackerjack/models/results.py +35 -0
  236. crackerjack/models/semantic_models.py +258 -0
  237. crackerjack/models/task.py +19 -3
  238. crackerjack/models/test_models.py +60 -0
  239. crackerjack/monitoring/README.md +11 -0
  240. crackerjack/monitoring/ai_agent_watchdog.py +5 -4
  241. crackerjack/monitoring/metrics_collector.py +4 -3
  242. crackerjack/monitoring/regression_prevention.py +4 -3
  243. crackerjack/monitoring/websocket_server.py +4 -241
  244. crackerjack/orchestration/README.md +340 -0
  245. crackerjack/orchestration/__init__.py +43 -0
  246. crackerjack/orchestration/advanced_orchestrator.py +20 -67
  247. crackerjack/orchestration/cache/README.md +312 -0
  248. crackerjack/orchestration/cache/__init__.py +37 -0
  249. crackerjack/orchestration/cache/memory_cache.py +338 -0
  250. crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
  251. crackerjack/orchestration/config.py +297 -0
  252. crackerjack/orchestration/coverage_improvement.py +13 -6
  253. crackerjack/orchestration/execution_strategies.py +6 -6
  254. crackerjack/orchestration/hook_orchestrator.py +1398 -0
  255. crackerjack/orchestration/strategies/README.md +401 -0
  256. crackerjack/orchestration/strategies/__init__.py +39 -0
  257. crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
  258. crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
  259. crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
  260. crackerjack/orchestration/test_progress_streamer.py +1 -1
  261. crackerjack/plugins/README.md +11 -0
  262. crackerjack/plugins/hooks.py +3 -2
  263. crackerjack/plugins/loader.py +3 -3
  264. crackerjack/plugins/managers.py +1 -1
  265. crackerjack/py313.py +191 -0
  266. crackerjack/security/README.md +11 -0
  267. crackerjack/services/README.md +374 -0
  268. crackerjack/services/__init__.py +8 -21
  269. crackerjack/services/ai/README.md +295 -0
  270. crackerjack/services/ai/__init__.py +7 -0
  271. crackerjack/services/ai/advanced_optimizer.py +878 -0
  272. crackerjack/services/{contextual_ai_assistant.py → ai/contextual_ai_assistant.py} +5 -3
  273. crackerjack/services/ai/embeddings.py +444 -0
  274. crackerjack/services/ai/intelligent_commit.py +328 -0
  275. crackerjack/services/ai/predictive_analytics.py +510 -0
  276. crackerjack/services/api_extractor.py +5 -3
  277. crackerjack/services/bounded_status_operations.py +45 -5
  278. crackerjack/services/cache.py +249 -318
  279. crackerjack/services/changelog_automation.py +7 -3
  280. crackerjack/services/command_execution_service.py +305 -0
  281. crackerjack/services/config_integrity.py +83 -39
  282. crackerjack/services/config_merge.py +9 -6
  283. crackerjack/services/config_service.py +198 -0
  284. crackerjack/services/config_template.py +13 -26
  285. crackerjack/services/coverage_badge_service.py +6 -4
  286. crackerjack/services/coverage_ratchet.py +53 -27
  287. crackerjack/services/debug.py +18 -7
  288. crackerjack/services/dependency_analyzer.py +4 -4
  289. crackerjack/services/dependency_monitor.py +13 -13
  290. crackerjack/services/documentation_generator.py +4 -2
  291. crackerjack/services/documentation_service.py +62 -33
  292. crackerjack/services/enhanced_filesystem.py +81 -27
  293. crackerjack/services/enterprise_optimizer.py +1 -1
  294. crackerjack/services/error_pattern_analyzer.py +10 -10
  295. crackerjack/services/file_filter.py +221 -0
  296. crackerjack/services/file_hasher.py +5 -7
  297. crackerjack/services/file_io_service.py +361 -0
  298. crackerjack/services/file_modifier.py +615 -0
  299. crackerjack/services/filesystem.py +80 -109
  300. crackerjack/services/git.py +99 -5
  301. crackerjack/services/health_metrics.py +4 -6
  302. crackerjack/services/heatmap_generator.py +12 -3
  303. crackerjack/services/incremental_executor.py +380 -0
  304. crackerjack/services/initialization.py +101 -49
  305. crackerjack/services/log_manager.py +2 -2
  306. crackerjack/services/logging.py +120 -68
  307. crackerjack/services/lsp_client.py +12 -12
  308. crackerjack/services/memory_optimizer.py +27 -22
  309. crackerjack/services/monitoring/README.md +30 -0
  310. crackerjack/services/monitoring/__init__.py +9 -0
  311. crackerjack/services/monitoring/dependency_monitor.py +678 -0
  312. crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
  313. crackerjack/services/monitoring/health_metrics.py +716 -0
  314. crackerjack/services/monitoring/metrics.py +587 -0
  315. crackerjack/services/{performance_benchmarks.py → monitoring/performance_benchmarks.py} +100 -14
  316. crackerjack/services/{performance_cache.py → monitoring/performance_cache.py} +21 -15
  317. crackerjack/services/{performance_monitor.py → monitoring/performance_monitor.py} +10 -6
  318. crackerjack/services/parallel_executor.py +166 -55
  319. crackerjack/services/patterns/__init__.py +142 -0
  320. crackerjack/services/patterns/agents.py +107 -0
  321. crackerjack/services/patterns/code/__init__.py +15 -0
  322. crackerjack/services/patterns/code/detection.py +118 -0
  323. crackerjack/services/patterns/code/imports.py +107 -0
  324. crackerjack/services/patterns/code/paths.py +159 -0
  325. crackerjack/services/patterns/code/performance.py +119 -0
  326. crackerjack/services/patterns/code/replacement.py +36 -0
  327. crackerjack/services/patterns/core.py +212 -0
  328. crackerjack/services/patterns/documentation/__init__.py +14 -0
  329. crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
  330. crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
  331. crackerjack/services/patterns/documentation/docstrings.py +89 -0
  332. crackerjack/services/patterns/formatting.py +226 -0
  333. crackerjack/services/patterns/operations.py +339 -0
  334. crackerjack/services/patterns/security/__init__.py +23 -0
  335. crackerjack/services/patterns/security/code_injection.py +122 -0
  336. crackerjack/services/patterns/security/credentials.py +190 -0
  337. crackerjack/services/patterns/security/path_traversal.py +221 -0
  338. crackerjack/services/patterns/security/unsafe_operations.py +216 -0
  339. crackerjack/services/patterns/templates.py +62 -0
  340. crackerjack/services/patterns/testing/__init__.py +18 -0
  341. crackerjack/services/patterns/testing/error_patterns.py +107 -0
  342. crackerjack/services/patterns/testing/pytest_output.py +126 -0
  343. crackerjack/services/patterns/tool_output/__init__.py +16 -0
  344. crackerjack/services/patterns/tool_output/bandit.py +72 -0
  345. crackerjack/services/patterns/tool_output/other.py +97 -0
  346. crackerjack/services/patterns/tool_output/pyright.py +67 -0
  347. crackerjack/services/patterns/tool_output/ruff.py +44 -0
  348. crackerjack/services/patterns/url_sanitization.py +114 -0
  349. crackerjack/services/patterns/utilities.py +42 -0
  350. crackerjack/services/patterns/utils.py +339 -0
  351. crackerjack/services/patterns/validation.py +46 -0
  352. crackerjack/services/patterns/versioning.py +62 -0
  353. crackerjack/services/predictive_analytics.py +21 -8
  354. crackerjack/services/profiler.py +280 -0
  355. crackerjack/services/quality/README.md +415 -0
  356. crackerjack/services/quality/__init__.py +11 -0
  357. crackerjack/services/quality/anomaly_detector.py +392 -0
  358. crackerjack/services/quality/pattern_cache.py +333 -0
  359. crackerjack/services/quality/pattern_detector.py +479 -0
  360. crackerjack/services/quality/qa_orchestrator.py +491 -0
  361. crackerjack/services/{quality_baseline.py → quality/quality_baseline.py} +163 -2
  362. crackerjack/services/{quality_baseline_enhanced.py → quality/quality_baseline_enhanced.py} +4 -1
  363. crackerjack/services/{quality_intelligence.py → quality/quality_intelligence.py} +180 -16
  364. crackerjack/services/regex_patterns.py +58 -2987
  365. crackerjack/services/regex_utils.py +55 -29
  366. crackerjack/services/secure_status_formatter.py +42 -15
  367. crackerjack/services/secure_subprocess.py +35 -2
  368. crackerjack/services/security.py +16 -8
  369. crackerjack/services/server_manager.py +40 -51
  370. crackerjack/services/smart_scheduling.py +46 -6
  371. crackerjack/services/status_authentication.py +3 -3
  372. crackerjack/services/thread_safe_status_collector.py +1 -0
  373. crackerjack/services/tool_filter.py +368 -0
  374. crackerjack/services/tool_version_service.py +9 -5
  375. crackerjack/services/unified_config.py +43 -351
  376. crackerjack/services/vector_store.py +689 -0
  377. crackerjack/services/version_analyzer.py +6 -4
  378. crackerjack/services/version_checker.py +14 -8
  379. crackerjack/services/zuban_lsp_service.py +5 -4
  380. crackerjack/slash_commands/README.md +11 -0
  381. crackerjack/slash_commands/init.md +2 -12
  382. crackerjack/slash_commands/run.md +84 -50
  383. crackerjack/tools/README.md +11 -0
  384. crackerjack/tools/__init__.py +30 -0
  385. crackerjack/tools/_git_utils.py +105 -0
  386. crackerjack/tools/check_added_large_files.py +139 -0
  387. crackerjack/tools/check_ast.py +105 -0
  388. crackerjack/tools/check_json.py +103 -0
  389. crackerjack/tools/check_jsonschema.py +297 -0
  390. crackerjack/tools/check_toml.py +103 -0
  391. crackerjack/tools/check_yaml.py +110 -0
  392. crackerjack/tools/codespell_wrapper.py +72 -0
  393. crackerjack/tools/end_of_file_fixer.py +202 -0
  394. crackerjack/tools/format_json.py +128 -0
  395. crackerjack/tools/mdformat_wrapper.py +114 -0
  396. crackerjack/tools/trailing_whitespace.py +198 -0
  397. crackerjack/tools/validate_regex_patterns.py +7 -3
  398. crackerjack/ui/README.md +11 -0
  399. crackerjack/ui/dashboard_renderer.py +28 -0
  400. crackerjack/ui/templates/README.md +11 -0
  401. crackerjack/utils/console_utils.py +13 -0
  402. crackerjack/utils/dependency_guard.py +230 -0
  403. crackerjack/utils/retry_utils.py +275 -0
  404. crackerjack/workflows/README.md +590 -0
  405. crackerjack/workflows/__init__.py +46 -0
  406. crackerjack/workflows/actions.py +811 -0
  407. crackerjack/workflows/auto_fix.py +444 -0
  408. crackerjack/workflows/container_builder.py +499 -0
  409. crackerjack/workflows/definitions.py +443 -0
  410. crackerjack/workflows/engine.py +177 -0
  411. crackerjack/workflows/event_bridge.py +242 -0
  412. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/METADATA +678 -98
  413. crackerjack-0.45.2.dist-info/RECORD +478 -0
  414. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
  415. crackerjack/managers/test_manager_backup.py +0 -1075
  416. crackerjack/mcp/tools/execution_tools_backup.py +0 -1011
  417. crackerjack/mixins/__init__.py +0 -3
  418. crackerjack/mixins/error_handling.py +0 -145
  419. crackerjack/services/config.py +0 -358
  420. crackerjack/ui/server_panels.py +0 -125
  421. crackerjack-0.37.9.dist-info/RECORD +0 -231
  422. /crackerjack/adapters/{rust_tool_adapter.py → lsp/_base.py} +0 -0
  423. /crackerjack/adapters/{lsp_client.py → lsp/_client.py} +0 -0
  424. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/entry_points.txt +0 -0
  425. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,587 @@
1
+ import json
2
+ import sqlite3
3
+ import threading
4
+ import typing as t
5
+ from contextlib import contextmanager
6
+ from datetime import date, datetime
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+
11
+ class MetricsCollector:
12
+ def __init__(self, db_path: Path | None = None) -> None:
13
+ if db_path is None:
14
+ db_dir = Path.home() / ".cache" / "crackerjack"
15
+ db_dir.mkdir(parents=True, exist_ok=True)
16
+ db_path = db_dir / "metrics.db"
17
+
18
+ self.db_path = db_path
19
+ self._lock = threading.Lock()
20
+ self._init_database()
21
+
22
+ def _init_database(self) -> None:
23
+ with self._get_connection() as conn:
24
+ conn.executescript("""
25
+ -- Jobs table
26
+ CREATE TABLE IF NOT EXISTS jobs (
27
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
28
+ job_id TEXT UNIQUE NOT NULL,
29
+ start_time TIMESTAMP NOT NULL,
30
+ end_time TIMESTAMP,
31
+ status TEXT NOT NULL, -- 'running', 'success', 'failed', 'cancelled'
32
+ iterations INTEGER DEFAULT 0,
33
+ ai_agent BOOLEAN DEFAULT 0,
34
+ error_message TEXT,
35
+ metadata TEXT -- JSON field for additional data
36
+ );
37
+
38
+ -- Errors table
39
+ CREATE TABLE IF NOT EXISTS errors (
40
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
41
+ job_id TEXT,
42
+ timestamp TIMESTAMP NOT NULL,
43
+ error_type TEXT NOT NULL, -- 'hook', 'test', 'lint', 'type_check', etc.
44
+ error_category TEXT, -- 'ruff', 'pyright', 'pytest', etc.
45
+ error_message TEXT,
46
+ file_path TEXT,
47
+ line_number INTEGER,
48
+ FOREIGN KEY (job_id) REFERENCES jobs(job_id)
49
+ );
50
+
51
+ -- Hook executions table
52
+ CREATE TABLE IF NOT EXISTS hook_executions (
53
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
54
+ job_id TEXT,
55
+ timestamp TIMESTAMP NOT NULL,
56
+ hook_name TEXT NOT NULL,
57
+ hook_type TEXT, -- 'fast', 'comprehensive'
58
+ execution_time_ms INTEGER,
59
+ status TEXT, -- 'success', 'failed', 'skipped'
60
+ FOREIGN KEY (job_id) REFERENCES jobs(job_id)
61
+ );
62
+
63
+ -- Test executions table
64
+ CREATE TABLE IF NOT EXISTS test_executions (
65
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
66
+ job_id TEXT,
67
+ timestamp TIMESTAMP NOT NULL,
68
+ total_tests INTEGER,
69
+ passed INTEGER,
70
+ failed INTEGER,
71
+ skipped INTEGER,
72
+ execution_time_ms INTEGER,
73
+ coverage_percent REAL,
74
+ FOREIGN KEY (job_id) REFERENCES jobs(job_id)
75
+ );
76
+
77
+ -- Orchestration executions table (NEW)
78
+ CREATE TABLE IF NOT EXISTS orchestration_executions (
79
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
80
+ job_id TEXT,
81
+ timestamp TIMESTAMP NOT NULL,
82
+ execution_strategy TEXT NOT NULL, -- 'batch', 'individual', 'adaptive', 'selective'
83
+ progress_level TEXT NOT NULL, -- 'basic', 'detailed', 'granular', 'streaming'
84
+ ai_mode TEXT NOT NULL, -- 'single-agent', 'multi-agent', 'coordinator'
85
+ iteration_count INTEGER DEFAULT 1,
86
+ strategy_switches INTEGER DEFAULT 0, -- How many times strategy changed
87
+ correlation_insights TEXT, -- JSON of correlation analysis results
88
+ total_execution_time_ms INTEGER,
89
+ hooks_execution_time_ms INTEGER,
90
+ tests_execution_time_ms INTEGER,
91
+ ai_analysis_time_ms INTEGER,
92
+ FOREIGN KEY (job_id) REFERENCES jobs(job_id)
93
+ );
94
+
95
+ -- Strategy decisions table (NEW)
96
+ CREATE TABLE IF NOT EXISTS strategy_decisions (
97
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
98
+ job_id TEXT,
99
+ iteration INTEGER,
100
+ timestamp TIMESTAMP NOT NULL,
101
+ previous_strategy TEXT,
102
+ selected_strategy TEXT NOT NULL,
103
+ decision_reason TEXT, -- Why this strategy was chosen
104
+ context_data TEXT, -- JSON of execution context
105
+ effectiveness_score REAL, -- How well the strategy worked (0 - 1)
106
+ FOREIGN KEY (job_id) REFERENCES jobs(job_id)
107
+ );
108
+
109
+ -- Individual test executions table (NEW - more granular than test_executions)
110
+ CREATE TABLE IF NOT EXISTS individual_test_executions (
111
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
112
+ job_id TEXT,
113
+ timestamp TIMESTAMP NOT NULL,
114
+ test_id TEXT NOT NULL, -- Full test identifier
115
+ test_file TEXT NOT NULL,
116
+ test_class TEXT,
117
+ test_method TEXT,
118
+ status TEXT NOT NULL, -- 'passed', 'failed', 'skipped', 'error'
119
+ execution_time_ms INTEGER,
120
+ error_message TEXT,
121
+ error_traceback TEXT,
122
+ FOREIGN KEY (job_id) REFERENCES jobs(job_id)
123
+ );
124
+
125
+ -- Daily summary table (for quick stats)
126
+ CREATE TABLE IF NOT EXISTS daily_summary (
127
+ date DATE PRIMARY KEY,
128
+ total_jobs INTEGER DEFAULT 0,
129
+ successful_jobs INTEGER DEFAULT 0,
130
+ failed_jobs INTEGER DEFAULT 0,
131
+ total_errors INTEGER DEFAULT 0,
132
+ hook_errors INTEGER DEFAULT 0,
133
+ test_errors INTEGER DEFAULT 0,
134
+ lint_errors INTEGER DEFAULT 0,
135
+ type_errors INTEGER DEFAULT 0,
136
+ avg_job_duration_ms INTEGER,
137
+ total_ai_fixes INTEGER DEFAULT 0,
138
+ orchestrated_jobs INTEGER DEFAULT 0, -- NEW
139
+ avg_orchestration_iterations REAL DEFAULT 0, -- NEW
140
+ most_effective_strategy TEXT -- NEW
141
+ );
142
+
143
+ --Create indexes for performance
144
+ CREATE INDEX IF NOT EXISTS idx_jobs_start_time ON jobs(start_time);
145
+ CREATE INDEX IF NOT EXISTS idx_errors_job_id ON errors(job_id);
146
+ CREATE INDEX IF NOT EXISTS idx_errors_type ON errors(error_type);
147
+ CREATE INDEX IF NOT EXISTS idx_hooks_job_id ON hook_executions(job_id);
148
+ CREATE INDEX IF NOT EXISTS idx_tests_job_id ON test_executions(job_id);
149
+ CREATE INDEX IF NOT EXISTS idx_orchestration_job_id ON orchestration_executions(job_id);
150
+ CREATE INDEX IF NOT EXISTS idx_strategy_decisions_job_id ON strategy_decisions(job_id);
151
+ CREATE INDEX IF NOT EXISTS idx_individual_tests_job_id ON individual_test_executions(job_id);
152
+ CREATE INDEX IF NOT EXISTS idx_strategy_decisions_strategy ON strategy_decisions(selected_strategy);
153
+ """)
154
+
155
+ @contextmanager
156
+ def _get_connection(self) -> t.Iterator[sqlite3.Connection]:
157
+ conn = sqlite3.connect(str(self.db_path))
158
+ conn.row_factory = sqlite3.Row
159
+ try:
160
+ yield conn
161
+ conn.commit()
162
+ except Exception:
163
+ conn.rollback()
164
+ raise
165
+ finally:
166
+ conn.close()
167
+
168
+ def start_job(
169
+ self,
170
+ job_id: str,
171
+ ai_agent: bool = False,
172
+ metadata: dict[str, Any] | None = None,
173
+ ) -> None:
174
+ with self._lock, self._get_connection() as conn:
175
+ conn.execute(
176
+ """
177
+ INSERT INTO jobs (job_id, start_time, status, ai_agent, metadata)
178
+ VALUES (?, ?, 'running', ?, ?)
179
+ """,
180
+ (job_id, datetime.now(), ai_agent, json.dumps(metadata or {})),
181
+ )
182
+
183
+ def end_job(
184
+ self,
185
+ job_id: str,
186
+ status: str,
187
+ iterations: int = 0,
188
+ error_message: str | None = None,
189
+ ) -> None:
190
+ with self._lock, self._get_connection() as conn:
191
+ conn.execute(
192
+ """
193
+ UPDATE jobs
194
+ SET end_time=?, status=?, iterations=?, error_message=?
195
+ WHERE job_id=?
196
+ """,
197
+ (datetime.now(), status, iterations, error_message, job_id),
198
+ )
199
+
200
+ self._update_daily_summary(conn, datetime.now().date())
201
+
202
+ def record_error(
203
+ self,
204
+ job_id: str,
205
+ error_type: str,
206
+ error_category: str,
207
+ error_message: str,
208
+ file_path: str | None = None,
209
+ line_number: int | None = None,
210
+ ) -> None:
211
+ with self._lock, self._get_connection() as conn:
212
+ conn.execute(
213
+ """
214
+ INSERT INTO errors (job_id, timestamp, error_type, error_category,
215
+ error_message, file_path, line_number)
216
+ VALUES (?, ?, ?, ?, ?, ?, ?)
217
+ """,
218
+ (
219
+ job_id,
220
+ datetime.now(),
221
+ error_type,
222
+ error_category,
223
+ error_message,
224
+ file_path,
225
+ line_number,
226
+ ),
227
+ )
228
+
229
+ def record_hook_execution(
230
+ self,
231
+ job_id: str,
232
+ hook_name: str,
233
+ hook_type: str,
234
+ execution_time_ms: int,
235
+ status: str,
236
+ ) -> None:
237
+ with self._lock, self._get_connection() as conn:
238
+ conn.execute(
239
+ """
240
+ INSERT INTO hook_executions (job_id, timestamp, hook_name,
241
+ hook_type, execution_time_ms, status)
242
+ VALUES (?, ?, ?, ?, ?, ?)
243
+ """,
244
+ (
245
+ job_id,
246
+ datetime.now(),
247
+ hook_name,
248
+ hook_type,
249
+ execution_time_ms,
250
+ status,
251
+ ),
252
+ )
253
+
254
+ def record_test_execution(
255
+ self,
256
+ job_id: str,
257
+ total_tests: int,
258
+ passed: int,
259
+ failed: int,
260
+ skipped: int,
261
+ execution_time_ms: int,
262
+ coverage_percent: float | None = None,
263
+ ) -> None:
264
+ with self._lock, self._get_connection() as conn:
265
+ conn.execute(
266
+ """
267
+ INSERT INTO test_executions (job_id, timestamp, total_tests,
268
+ passed, failed, skipped,
269
+ execution_time_ms, coverage_percent)
270
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
271
+ """,
272
+ (
273
+ job_id,
274
+ datetime.now(),
275
+ total_tests,
276
+ passed,
277
+ failed,
278
+ skipped,
279
+ execution_time_ms,
280
+ coverage_percent,
281
+ ),
282
+ )
283
+
284
+ def record_orchestration_execution(
285
+ self,
286
+ job_id: str,
287
+ execution_strategy: str,
288
+ progress_level: str,
289
+ ai_mode: str,
290
+ iteration_count: int,
291
+ strategy_switches: int,
292
+ correlation_insights: dict[str, Any],
293
+ total_execution_time_ms: int,
294
+ hooks_execution_time_ms: int,
295
+ tests_execution_time_ms: int,
296
+ ai_analysis_time_ms: int,
297
+ ) -> None:
298
+ with self._lock, self._get_connection() as conn:
299
+ conn.execute(
300
+ """
301
+ INSERT INTO orchestration_executions
302
+ (job_id, timestamp, execution_strategy, progress_level, ai_mode,
303
+ iteration_count, strategy_switches, correlation_insights,
304
+ total_execution_time_ms, hooks_execution_time_ms,
305
+ tests_execution_time_ms, ai_analysis_time_ms)
306
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
307
+ """,
308
+ (
309
+ job_id,
310
+ datetime.now(),
311
+ execution_strategy,
312
+ progress_level,
313
+ ai_mode,
314
+ iteration_count,
315
+ strategy_switches,
316
+ json.dumps(correlation_insights),
317
+ total_execution_time_ms,
318
+ hooks_execution_time_ms,
319
+ tests_execution_time_ms,
320
+ ai_analysis_time_ms,
321
+ ),
322
+ )
323
+
324
+ def record_strategy_decision(
325
+ self,
326
+ job_id: str,
327
+ iteration: int,
328
+ previous_strategy: str | None,
329
+ selected_strategy: str,
330
+ decision_reason: str,
331
+ context_data: dict[str, Any],
332
+ effectiveness_score: float | None = None,
333
+ ) -> None:
334
+ with self._lock, self._get_connection() as conn:
335
+ conn.execute(
336
+ """
337
+ INSERT INTO strategy_decisions
338
+ (job_id, iteration, timestamp, previous_strategy, selected_strategy,
339
+ decision_reason, context_data, effectiveness_score)
340
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
341
+ """,
342
+ (
343
+ job_id,
344
+ iteration,
345
+ datetime.now(),
346
+ previous_strategy,
347
+ selected_strategy,
348
+ decision_reason,
349
+ json.dumps(context_data),
350
+ effectiveness_score,
351
+ ),
352
+ )
353
+
354
+ def record_individual_test(
355
+ self,
356
+ job_id: str,
357
+ test_id: str,
358
+ test_file: str,
359
+ test_class: str | None,
360
+ test_method: str | None,
361
+ status: str,
362
+ execution_time_ms: int | None,
363
+ error_message: str | None = None,
364
+ error_traceback: str | None = None,
365
+ ) -> None:
366
+ with self._lock, self._get_connection() as conn:
367
+ conn.execute(
368
+ """
369
+ INSERT INTO individual_test_executions
370
+ (job_id, timestamp, test_id, test_file, test_class, test_method,
371
+ status, execution_time_ms, error_message, error_traceback)
372
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
373
+ """,
374
+ (
375
+ job_id,
376
+ datetime.now(),
377
+ test_id,
378
+ test_file,
379
+ test_class,
380
+ test_method,
381
+ status,
382
+ execution_time_ms,
383
+ error_message,
384
+ error_traceback,
385
+ ),
386
+ )
387
+
388
+ def get_orchestration_stats(self) -> dict[str, Any]:
389
+ with self._get_connection() as conn:
390
+ strategy_stats = conn.execute("""
391
+ SELECT
392
+ selected_strategy,
393
+ COUNT(*) as usage_count,
394
+ AVG(effectiveness_score) as avg_effectiveness,
395
+ AVG(
396
+ SELECT iteration_count
397
+ FROM orchestration_executions o
398
+ WHERE o.job_id=sd.job_id
399
+ ) as avg_iterations_needed
400
+ FROM strategy_decisions sd
401
+ WHERE effectiveness_score IS NOT NULL
402
+ GROUP BY selected_strategy
403
+ ORDER BY avg_effectiveness DESC, usage_count DESC
404
+ """).fetchall()
405
+
406
+ correlation_patterns = conn.execute("""
407
+ SELECT
408
+ json_extract(correlation_insights, '$.problematic_hooks') as problematic_hooks,
409
+ COUNT(*) as frequency
410
+ FROM orchestration_executions
411
+ WHERE correlation_insights != 'null'
412
+ AND correlation_insights != '{}'
413
+ GROUP BY problematic_hooks
414
+ ORDER BY frequency DESC
415
+ LIMIT 10
416
+ """).fetchall()
417
+
418
+ performance_stats = conn.execute("""
419
+ SELECT
420
+ execution_strategy,
421
+ COUNT(*) as executions,
422
+ AVG(total_execution_time_ms) as avg_total_time,
423
+ AVG(hooks_execution_time_ms) as avg_hooks_time,
424
+ AVG(tests_execution_time_ms) as avg_tests_time,
425
+ AVG(ai_analysis_time_ms) as avg_ai_time,
426
+ AVG(iteration_count) as avg_iterations
427
+ FROM orchestration_executions
428
+ GROUP BY execution_strategy
429
+ """).fetchall()
430
+
431
+ test_failure_patterns = conn.execute("""
432
+ SELECT
433
+ test_file,
434
+ test_class,
435
+ test_method,
436
+ COUNT(*) as failure_count,
437
+ AVG(execution_time_ms) as avg_execution_time
438
+ FROM individual_test_executions
439
+ WHERE status='failed'
440
+ GROUP BY test_file, test_class, test_method
441
+ ORDER BY failure_count DESC
442
+ LIMIT 15
443
+ """).fetchall()
444
+
445
+ return {
446
+ "strategy_effectiveness": [
447
+ dict[str, t.Any](row) for row in strategy_stats
448
+ ],
449
+ "correlation_patterns": [
450
+ dict[str, t.Any](row) for row in correlation_patterns
451
+ ],
452
+ "performance_by_strategy": [
453
+ dict[str, t.Any](row) for row in performance_stats
454
+ ],
455
+ "test_failure_patterns": [
456
+ dict[str, t.Any](row) for row in test_failure_patterns
457
+ ],
458
+ }
459
+
460
+ def _update_daily_summary(
461
+ self,
462
+ conn: sqlite3.Connection,
463
+ date: date,
464
+ ) -> None:
465
+ job_stats = conn.execute(
466
+ """
467
+ SELECT
468
+ COUNT(*) as total_jobs,
469
+ SUM(CASE WHEN status='success' THEN 1 ELSE 0 END) as successful_jobs,
470
+ SUM(CASE WHEN status='failed' THEN 1 ELSE 0 END) as failed_jobs,
471
+ AVG(CASE
472
+ WHEN end_time IS NOT NULL
473
+ THEN (julianday(end_time)-julianday(start_time)) * 86400000
474
+ ELSE NULL
475
+ END) as avg_duration_ms,
476
+ SUM(CASE WHEN ai_agent=1 AND status='success' THEN 1 ELSE 0 END) as ai_fixes
477
+ FROM jobs
478
+ WHERE DATE(start_time) = ?
479
+ """,
480
+ (date,),
481
+ ).fetchone()
482
+
483
+ error_stats = conn.execute(
484
+ """
485
+ SELECT
486
+ COUNT(*) as total_errors,
487
+ SUM(CASE WHEN error_type='hook' THEN 1 ELSE 0 END) as hook_errors,
488
+ SUM(CASE WHEN error_type='test' THEN 1 ELSE 0 END) as test_errors,
489
+ SUM(CASE WHEN error_type='lint' THEN 1 ELSE 0 END) as lint_errors,
490
+ SUM(CASE WHEN error_type='type_check' THEN 1 ELSE 0 END) as type_errors
491
+ FROM errors
492
+ WHERE DATE(timestamp) = ?
493
+ """,
494
+ (date,),
495
+ ).fetchone()
496
+
497
+ orchestration_stats = conn.execute(
498
+ """
499
+ SELECT
500
+ COUNT(*) as orchestrated_jobs,
501
+ AVG(iteration_count) as avg_iterations,
502
+ (SELECT selected_strategy
503
+ FROM strategy_decisions sd2
504
+ WHERE DATE(sd2.timestamp) = ?
505
+ GROUP BY selected_strategy
506
+ ORDER BY COUNT(*) DESC
507
+ LIMIT 1) as most_effective_strategy
508
+ FROM orchestration_executions
509
+ WHERE DATE(timestamp) = ?
510
+ """,
511
+ (date, date),
512
+ ).fetchone()
513
+
514
+ conn.execute(
515
+ """
516
+ INSERT OR REPLACE INTO daily_summary
517
+ (date, total_jobs, successful_jobs, failed_jobs, total_errors,
518
+ hook_errors, test_errors, lint_errors, type_errors,
519
+ avg_job_duration_ms, total_ai_fixes, orchestrated_jobs,
520
+ avg_orchestration_iterations, most_effective_strategy)
521
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
522
+ """,
523
+ (
524
+ date,
525
+ job_stats["total_jobs"] or 0,
526
+ job_stats["successful_jobs"] or 0,
527
+ job_stats["failed_jobs"] or 0,
528
+ error_stats["total_errors"] or 0,
529
+ error_stats["hook_errors"] or 0,
530
+ error_stats["test_errors"] or 0,
531
+ error_stats["lint_errors"] or 0,
532
+ error_stats["type_errors"] or 0,
533
+ int(job_stats["avg_duration_ms"] or 0),
534
+ job_stats["ai_fixes"] or 0,
535
+ orchestration_stats["orchestrated_jobs"] or 0,
536
+ float(orchestration_stats["avg_iterations"] or 0),
537
+ orchestration_stats["most_effective_strategy"],
538
+ ),
539
+ )
540
+
541
+ def get_all_time_stats(self) -> dict[str, Any]:
542
+ with self._get_connection() as conn:
543
+ job_stats = conn.execute("""
544
+ SELECT
545
+ COUNT(*) as total_jobs,
546
+ SUM(CASE WHEN status='success' THEN 1 ELSE 0 END) as successful_jobs,
547
+ SUM(CASE WHEN status='failed' THEN 1 ELSE 0 END) as failed_jobs,
548
+ SUM(CASE WHEN ai_agent=1 THEN 1 ELSE 0 END) as ai_agent_jobs,
549
+ AVG(iterations) as avg_iterations
550
+ FROM jobs
551
+ """).fetchone()
552
+
553
+ error_stats = conn.execute("""
554
+ SELECT error_type, COUNT( * ) as count
555
+ FROM errors
556
+ GROUP BY error_type
557
+ """).fetchall()
558
+
559
+ common_errors = conn.execute("""
560
+ SELECT error_category, error_message, COUNT( * ) as count
561
+ FROM errors
562
+ GROUP BY error_category, error_message
563
+ ORDER BY count DESC
564
+ LIMIT 10
565
+ """).fetchall()
566
+
567
+ return {
568
+ "total_jobs": job_stats["total_jobs"] or 0,
569
+ "successful_jobs": job_stats["successful_jobs"] or 0,
570
+ "failed_jobs": job_stats["failed_jobs"] or 0,
571
+ "ai_agent_jobs": job_stats["ai_agent_jobs"] or 0,
572
+ "avg_iterations": float(job_stats["avg_iterations"] or 0),
573
+ "error_breakdown": {
574
+ row["error_type"]: row["count"] for row in error_stats
575
+ },
576
+ "common_errors": [dict[str, t.Any](row) for row in common_errors],
577
+ }
578
+
579
+
580
+ _metrics_collector: MetricsCollector | None = None
581
+
582
+
583
+ def get_metrics_collector() -> MetricsCollector:
584
+ global _metrics_collector
585
+ if _metrics_collector is None:
586
+ _metrics_collector = MetricsCollector()
587
+ return _metrics_collector