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,649 @@
1
+ """Enhanced Quality Baseline Service with trending, alerts, and export capabilities."""
2
+
3
+ import json
4
+ import typing as t
5
+ from dataclasses import asdict, dataclass, field
6
+ from datetime import datetime, timedelta
7
+ from enum import Enum
8
+ from pathlib import Path
9
+
10
+ from crackerjack.services.cache import CrackerjackCache
11
+ from crackerjack.services.quality.quality_baseline import (
12
+ QualityBaselineService,
13
+ QualityMetrics,
14
+ )
15
+
16
+
17
+ class TrendDirection(str, Enum):
18
+ """Quality trend direction."""
19
+
20
+ IMPROVING = "improving"
21
+ DECLINING = "declining"
22
+ STABLE = "stable"
23
+ VOLATILE = "volatile"
24
+
25
+
26
+ class AlertSeverity(str, Enum):
27
+ """Alert severity levels."""
28
+
29
+ INFO = "info"
30
+ WARNING = "warning"
31
+ CRITICAL = "critical"
32
+
33
+
34
+ @dataclass
35
+ class QualityTrend:
36
+ """Quality trend analysis over time."""
37
+
38
+ direction: TrendDirection
39
+ change_rate: float # Points per day
40
+ confidence: float # 0.0 to 1.0
41
+ period_days: int
42
+ recent_scores: list[int] = field(default_factory=list)
43
+
44
+ def to_dict(self) -> dict[str, t.Any]:
45
+ return asdict(self)
46
+
47
+
48
+ @dataclass
49
+ class QualityAlert:
50
+ """Quality alert for significant changes."""
51
+
52
+ severity: AlertSeverity
53
+ message: str
54
+ metric_name: str
55
+ current_value: float
56
+ threshold_value: float
57
+ triggered_at: datetime
58
+ git_hash: str | None = None
59
+
60
+ def to_dict(self) -> dict[str, t.Any]:
61
+ data = asdict(self)
62
+ data["triggered_at"] = self.triggered_at.isoformat()
63
+ return data
64
+
65
+
66
+ @dataclass
67
+ class UnifiedMetrics:
68
+ """Unified metrics for real-time monitoring dashboard."""
69
+
70
+ timestamp: datetime
71
+ quality_score: int
72
+ test_coverage: float
73
+ hook_duration: float
74
+ active_jobs: int
75
+ error_count: int
76
+ trend_direction: TrendDirection
77
+ predictions: dict[str, t.Any] = field(default_factory=dict[str, t.Any])
78
+
79
+ def to_dict(self) -> dict[str, t.Any]:
80
+ data = asdict(self)
81
+ data["timestamp"] = self.timestamp.isoformat()
82
+ return data
83
+
84
+
85
+ @dataclass
86
+ class SystemHealthStatus:
87
+ """System health status for monitoring."""
88
+
89
+ overall_status: str # "healthy", "warning", "critical"
90
+ cpu_usage: float
91
+ memory_usage: float
92
+ disk_usage: float
93
+ service_status: dict[str, str] = field(default_factory=dict[str, t.Any])
94
+
95
+ def to_dict(self) -> dict[str, t.Any]:
96
+ return asdict(self)
97
+
98
+
99
+ @dataclass
100
+ class DashboardState:
101
+ """Complete dashboard state for real-time monitoring."""
102
+
103
+ current_metrics: UnifiedMetrics
104
+ historical_data: list[UnifiedMetrics]
105
+ active_alerts: list[QualityAlert]
106
+ system_health: SystemHealthStatus
107
+ recommendations: list[str]
108
+ last_updated: datetime = field(default_factory=datetime.now)
109
+
110
+ def to_dict(self) -> dict[str, t.Any]:
111
+ return {
112
+ "current_metrics": self.current_metrics.to_dict(),
113
+ "historical_data": [metrics.to_dict() for metrics in self.historical_data],
114
+ "active_alerts": [alert.to_dict() for alert in self.active_alerts],
115
+ "system_health": self.system_health.to_dict(),
116
+ "recommendations": self.recommendations,
117
+ "last_updated": self.last_updated.isoformat(),
118
+ }
119
+
120
+
121
+ @dataclass
122
+ class QualityReport:
123
+ """Comprehensive quality report."""
124
+
125
+ current_metrics: QualityMetrics | None
126
+ trend: QualityTrend | None
127
+ alerts: list[QualityAlert]
128
+ historical_data: list[QualityMetrics]
129
+ recommendations: list[str]
130
+ generated_at: datetime = field(default_factory=datetime.now)
131
+
132
+ def to_dict(self) -> dict[str, t.Any]:
133
+ return {
134
+ "current_metrics": self.current_metrics.to_dict()
135
+ if self.current_metrics
136
+ else None,
137
+ "trend": self.trend.to_dict() if self.trend else None,
138
+ "alerts": [alert.to_dict() for alert in self.alerts],
139
+ "historical_data": [metrics.to_dict() for metrics in self.historical_data],
140
+ "recommendations": self.recommendations,
141
+ "generated_at": self.generated_at.isoformat(),
142
+ }
143
+
144
+
145
+ class EnhancedQualityBaselineService(QualityBaselineService):
146
+ """Enhanced quality baseline service with advanced analytics."""
147
+
148
+ def __init__(
149
+ self,
150
+ cache: CrackerjackCache | None = None,
151
+ alert_thresholds: dict[str, float] | None = None,
152
+ ) -> None:
153
+ super().__init__(cache)
154
+ self.alert_thresholds = alert_thresholds or {
155
+ "quality_score_drop": 10.0, # Alert if score drops by 10+ points
156
+ "coverage_drop": 5.0, # Alert if coverage drops by 5%+
157
+ "test_pass_rate_drop": 10.0, # Alert if pass rate drops by 10%+
158
+ "security_issues_increase": 1, # Alert on any security issue increase
159
+ "type_errors_threshold": 10, # Alert if type errors exceed 10
160
+ }
161
+
162
+ def analyze_quality_trend(
163
+ self, days: int = 30, min_data_points: int = 5
164
+ ) -> QualityTrend | None:
165
+ """Analyze quality trend over specified period."""
166
+ baselines = self.get_recent_baselines(
167
+ limit=days * 2
168
+ ) # Get more data for analysis
169
+
170
+ if len(baselines) < min_data_points:
171
+ return None
172
+
173
+ # Filter to specified period
174
+ cutoff_date = datetime.now() - timedelta(days=days)
175
+ recent_baselines = [b for b in baselines if b.timestamp >= cutoff_date]
176
+
177
+ if len(recent_baselines) < min_data_points:
178
+ return None
179
+
180
+ # Calculate trend
181
+ scores = [b.quality_score for b in recent_baselines]
182
+ timestamps = [
183
+ (b.timestamp - cutoff_date).total_seconds() / 86400
184
+ for b in recent_baselines
185
+ ]
186
+
187
+ # Simple linear regression for trend
188
+ n = len(scores)
189
+ sum_x = sum(timestamps)
190
+ sum_y = sum(scores)
191
+ sum_xy = sum(x * y for x, y in zip(timestamps, scores))
192
+ sum_x2 = sum(x * x for x in timestamps)
193
+
194
+ if n * sum_x2 - sum_x * sum_x == 0:
195
+ slope: float = 0.0
196
+ else:
197
+ slope = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x * sum_x)
198
+
199
+ # Determine direction and confidence
200
+ abs_slope = abs(slope)
201
+
202
+ if abs_slope < 0.1:
203
+ direction = TrendDirection.STABLE
204
+ elif slope > 0:
205
+ direction = TrendDirection.IMPROVING
206
+ else:
207
+ direction = TrendDirection.DECLINING
208
+
209
+ # Calculate volatility (standard deviation of scores)
210
+ mean_score = sum(scores) / len(scores)
211
+ variance = sum((score - mean_score) ** 2 for score in scores) / len(scores)
212
+ volatility = variance**0.5
213
+
214
+ if volatility > 15: # High volatility threshold
215
+ direction = TrendDirection.VOLATILE
216
+
217
+ # Confidence based on data consistency and amount
218
+ confidence = min(1.0, (len(scores) / 10) * (1 / (volatility + 1)))
219
+
220
+ return QualityTrend(
221
+ direction=direction,
222
+ change_rate=slope,
223
+ confidence=confidence,
224
+ period_days=days,
225
+ recent_scores=scores[-10:], # Last 10 scores
226
+ )
227
+
228
+ def check_quality_alerts(
229
+ self, current_metrics: dict[str, t.Any], baseline_git_hash: str | None = None
230
+ ) -> list[QualityAlert]:
231
+ """Check for quality alerts based on thresholds."""
232
+ alerts: list[QualityAlert] = []
233
+ baseline = self.get_baseline(baseline_git_hash)
234
+
235
+ if not baseline:
236
+ return alerts
237
+
238
+ # Filter metrics to only include parameters that calculate_quality_score accepts
239
+ score_metrics = {
240
+ k: v
241
+ for k, v in current_metrics.items()
242
+ if k
243
+ in (
244
+ "coverage_percent",
245
+ "test_pass_rate",
246
+ "hook_failures",
247
+ "complexity_violations",
248
+ "security_issues",
249
+ "type_errors",
250
+ "linting_issues",
251
+ )
252
+ }
253
+ current_score = self.calculate_quality_score(**score_metrics)
254
+ git_hash = self.get_current_git_hash()
255
+
256
+ # Quality score drop alert
257
+ score_drop = baseline.quality_score - current_score
258
+ if score_drop >= self.alert_thresholds["quality_score_drop"]:
259
+ alerts.append(
260
+ QualityAlert(
261
+ severity=AlertSeverity.CRITICAL
262
+ if score_drop >= 20
263
+ else AlertSeverity.WARNING,
264
+ message=f"Quality score dropped by {score_drop:.1f} points (from {baseline.quality_score} to {current_score})",
265
+ metric_name="quality_score",
266
+ current_value=current_score,
267
+ threshold_value=baseline.quality_score
268
+ - self.alert_thresholds["quality_score_drop"],
269
+ triggered_at=datetime.now(),
270
+ git_hash=git_hash,
271
+ )
272
+ )
273
+
274
+ # Coverage drop alert
275
+ coverage_drop = baseline.coverage_percent - current_metrics.get(
276
+ "coverage_percent", 0
277
+ )
278
+ if coverage_drop >= self.alert_thresholds["coverage_drop"]:
279
+ alerts.append(
280
+ QualityAlert(
281
+ severity=AlertSeverity.WARNING,
282
+ message=f"Test coverage dropped by {coverage_drop:.1f}% (from {baseline.coverage_percent:.1f}% to {current_metrics.get('coverage_percent', 0):.1f}%)",
283
+ metric_name="coverage_percent",
284
+ current_value=current_metrics.get("coverage_percent", 0),
285
+ threshold_value=baseline.coverage_percent
286
+ - self.alert_thresholds["coverage_drop"],
287
+ triggered_at=datetime.now(),
288
+ git_hash=git_hash,
289
+ )
290
+ )
291
+
292
+ # Security issues increase alert
293
+ security_increase = (
294
+ current_metrics.get("security_issues", 0) - baseline.security_issues
295
+ )
296
+ if security_increase >= self.alert_thresholds["security_issues_increase"]:
297
+ alerts.append(
298
+ QualityAlert(
299
+ severity=AlertSeverity.CRITICAL,
300
+ message=f"Security issues increased by {security_increase} (from {baseline.security_issues} to {current_metrics.get('security_issues', 0)})",
301
+ metric_name="security_issues",
302
+ current_value=current_metrics.get("security_issues", 0),
303
+ threshold_value=baseline.security_issues
304
+ + self.alert_thresholds["security_issues_increase"]
305
+ - 1,
306
+ triggered_at=datetime.now(),
307
+ git_hash=git_hash,
308
+ )
309
+ )
310
+
311
+ # Type errors threshold alert
312
+ type_errors = current_metrics.get("type_errors", 0)
313
+ if type_errors >= self.alert_thresholds["type_errors_threshold"]:
314
+ alerts.append(
315
+ QualityAlert(
316
+ severity=AlertSeverity.WARNING,
317
+ message=f"Type errors ({type_errors}) exceed threshold ({self.alert_thresholds['type_errors_threshold']})",
318
+ metric_name="type_errors",
319
+ current_value=type_errors,
320
+ threshold_value=self.alert_thresholds["type_errors_threshold"],
321
+ triggered_at=datetime.now(),
322
+ git_hash=git_hash,
323
+ )
324
+ )
325
+
326
+ return alerts
327
+
328
+ def generate_recommendations(
329
+ self,
330
+ current_metrics: dict[str, t.Any],
331
+ trend: QualityTrend | None,
332
+ alerts: list[QualityAlert],
333
+ ) -> list[str]:
334
+ """Generate actionable recommendations."""
335
+ recommendations: list[str] = []
336
+
337
+ # Generate different types of recommendations
338
+ self._add_coverage_recommendations(current_metrics, recommendations)
339
+ self._add_error_recommendations(current_metrics, recommendations)
340
+ self._add_trend_recommendations(trend, recommendations)
341
+ self._add_alert_recommendations(alerts, recommendations)
342
+ self._add_general_recommendations(current_metrics, recommendations)
343
+
344
+ return recommendations
345
+
346
+ def _add_coverage_recommendations(
347
+ self, metrics: dict[str, t.Any], recommendations: list[str]
348
+ ) -> None:
349
+ """Add coverage-based recommendations."""
350
+ coverage = metrics.get("coverage_percent", 0)
351
+ if coverage < 80:
352
+ recommendations.append(
353
+ f"📊 Increase test coverage from {coverage:.1f}% to 80%+ by adding tests for uncovered code paths"
354
+ )
355
+ elif coverage < 95:
356
+ recommendations.append(
357
+ f"🎯 Consider targeting 95%+ coverage (currently {coverage:.1f}%) for better code quality"
358
+ )
359
+
360
+ def _add_error_recommendations(
361
+ self, metrics: dict[str, t.Any], recommendations: list[str]
362
+ ) -> None:
363
+ """Add error-based recommendations."""
364
+ type_errors = metrics.get("type_errors", 0)
365
+ if type_errors > 0:
366
+ recommendations.append(
367
+ f"🔧 Fix {type_errors} type errors to improve code reliability"
368
+ )
369
+
370
+ security_issues = metrics.get("security_issues", 0)
371
+ if security_issues > 0:
372
+ recommendations.append(
373
+ f"🔒 Address {security_issues} security issues immediately"
374
+ )
375
+
376
+ def _add_trend_recommendations(
377
+ self, trend: QualityTrend | None, recommendations: list[str]
378
+ ) -> None:
379
+ """Add trend-based recommendations."""
380
+ if not trend:
381
+ return
382
+
383
+ trend_messages = {
384
+ TrendDirection.DECLINING: "📉 Quality trend is declining - consider code review process improvements",
385
+ TrendDirection.VOLATILE: "⚠️ Quality is volatile - implement more consistent testing practices",
386
+ TrendDirection.IMPROVING: "📈 Great job! Quality is improving - maintain current practices",
387
+ }
388
+
389
+ message = trend_messages.get(trend.direction)
390
+ if message:
391
+ recommendations.append(message)
392
+
393
+ def _add_alert_recommendations(
394
+ self, alerts: list[QualityAlert], recommendations: list[str]
395
+ ) -> None:
396
+ """Add alert-based recommendations."""
397
+ critical_alerts = [a for a in alerts if a.severity == AlertSeverity.CRITICAL]
398
+ if critical_alerts:
399
+ recommendations.append(
400
+ f"🚨 Address {len(critical_alerts)} critical quality issues before proceeding"
401
+ )
402
+
403
+ def _add_general_recommendations(
404
+ self, metrics: dict[str, t.Any], recommendations: list[str]
405
+ ) -> None:
406
+ """Add general recommendations."""
407
+ hook_failures = metrics.get("hook_failures", 0)
408
+ if hook_failures > 0:
409
+ recommendations.append(
410
+ f"⚙️ Fix {hook_failures} pre-commit hook failures to streamline development"
411
+ )
412
+
413
+ def generate_comprehensive_report(
414
+ self, current_metrics: dict[str, t.Any] | None = None, days: int = 30
415
+ ) -> QualityReport:
416
+ """Generate comprehensive quality report."""
417
+ # Get current metrics or create from latest baseline
418
+ current_baseline = None
419
+ if current_metrics:
420
+ git_hash = self.get_current_git_hash()
421
+ if git_hash:
422
+ # Filter metrics to only include parameters that calculate_quality_score accepts
423
+ score_metrics = {
424
+ k: v
425
+ for k, v in current_metrics.items()
426
+ if k
427
+ in (
428
+ "coverage_percent",
429
+ "test_pass_rate",
430
+ "hook_failures",
431
+ "complexity_violations",
432
+ "security_issues",
433
+ "type_errors",
434
+ "linting_issues",
435
+ )
436
+ }
437
+ quality_score = self.calculate_quality_score(**score_metrics)
438
+ current_baseline = QualityMetrics(
439
+ git_hash=git_hash,
440
+ timestamp=datetime.now(),
441
+ coverage_percent=current_metrics.get("coverage_percent", 0.0),
442
+ test_count=current_metrics.get("test_count", 0),
443
+ test_pass_rate=current_metrics.get("test_pass_rate", 0.0),
444
+ hook_failures=current_metrics.get("hook_failures", 0),
445
+ complexity_violations=current_metrics.get(
446
+ "complexity_violations", 0
447
+ ),
448
+ security_issues=current_metrics.get("security_issues", 0),
449
+ type_errors=current_metrics.get("type_errors", 0),
450
+ linting_issues=current_metrics.get("linting_issues", 0),
451
+ quality_score=quality_score,
452
+ )
453
+ else:
454
+ current_baseline = self.get_baseline()
455
+
456
+ # Analyze trend
457
+ trend = self.analyze_quality_trend(days=days)
458
+
459
+ # Check alerts
460
+ alerts = []
461
+ if current_metrics:
462
+ alerts = self.check_quality_alerts(current_metrics)
463
+
464
+ # Get historical data
465
+ historical_data = self.get_recent_baselines(limit=days)
466
+
467
+ # Generate recommendations
468
+ metrics_dict = current_metrics or (
469
+ {
470
+ "coverage_percent": current_baseline.coverage_percent,
471
+ "test_count": current_baseline.test_count,
472
+ "test_pass_rate": current_baseline.test_pass_rate,
473
+ "hook_failures": current_baseline.hook_failures,
474
+ "complexity_violations": current_baseline.complexity_violations,
475
+ "security_issues": current_baseline.security_issues,
476
+ "type_errors": current_baseline.type_errors,
477
+ "linting_issues": current_baseline.linting_issues,
478
+ }
479
+ if current_baseline
480
+ else {}
481
+ )
482
+
483
+ recommendations = self.generate_recommendations(metrics_dict, trend, alerts)
484
+
485
+ return QualityReport(
486
+ current_metrics=current_baseline,
487
+ trend=trend,
488
+ alerts=alerts,
489
+ historical_data=historical_data,
490
+ recommendations=recommendations,
491
+ )
492
+
493
+ def export_report(
494
+ self, report: QualityReport, output_path: Path, format: str = "json"
495
+ ) -> None:
496
+ """Export quality report to file."""
497
+ if format.lower() == "json":
498
+ with output_path.open("w") as f:
499
+ json.dump(report.to_dict(), f, indent=2, default=str)
500
+ else:
501
+ raise ValueError(f"Unsupported export format: {format}")
502
+
503
+ def set_alert_threshold(self, metric: str, threshold: float) -> None:
504
+ """Update alert threshold for specific metric."""
505
+ self.alert_thresholds[metric] = threshold
506
+
507
+ def get_alert_thresholds(self) -> dict[str, float]:
508
+ """Get current alert thresholds."""
509
+ return self.alert_thresholds.copy()
510
+
511
+ def create_unified_metrics(
512
+ self, current_metrics: dict[str, t.Any], active_job_count: int = 0
513
+ ) -> UnifiedMetrics:
514
+ """Create UnifiedMetrics from current quality data."""
515
+ # Calculate quality score
516
+ score_metrics = {
517
+ k: v
518
+ for k, v in current_metrics.items()
519
+ if k
520
+ in (
521
+ "coverage_percent",
522
+ "test_pass_rate",
523
+ "hook_failures",
524
+ "complexity_violations",
525
+ "security_issues",
526
+ "type_errors",
527
+ "linting_issues",
528
+ )
529
+ }
530
+ quality_score = self.calculate_quality_score(**score_metrics)
531
+
532
+ # Get trend direction
533
+ trend = self.analyze_quality_trend(days=7)
534
+ trend_direction = trend.direction if trend else TrendDirection.STABLE
535
+
536
+ # Calculate error count
537
+ error_count = (
538
+ current_metrics.get("hook_failures", 0)
539
+ + current_metrics.get("security_issues", 0)
540
+ + current_metrics.get("type_errors", 0)
541
+ + current_metrics.get("linting_issues", 0)
542
+ )
543
+
544
+ # Create predictions based on trend
545
+ predictions = {}
546
+ if trend and trend.confidence > 0.5:
547
+ days_ahead = 7
548
+ predicted_score = quality_score + (trend.change_rate * days_ahead)
549
+ predictions["quality_score_7_days"] = max(0.0, min(100.0, predicted_score))
550
+
551
+ return UnifiedMetrics(
552
+ timestamp=datetime.now(),
553
+ quality_score=quality_score,
554
+ test_coverage=current_metrics.get("coverage_percent", 0.0),
555
+ hook_duration=current_metrics.get("hook_duration", 0.0),
556
+ active_jobs=active_job_count,
557
+ error_count=error_count,
558
+ trend_direction=trend_direction,
559
+ predictions=predictions,
560
+ )
561
+
562
+ def get_system_health(self) -> SystemHealthStatus:
563
+ """Get current system health status."""
564
+ import psutil
565
+
566
+ try:
567
+ cpu_percent = psutil.cpu_percent(interval=1)
568
+ memory = psutil.virtual_memory()
569
+ disk = psutil.disk_usage("/")
570
+
571
+ # Determine overall status
572
+ if cpu_percent > 90 or memory.percent > 90 or disk.percent > 95:
573
+ overall_status = "critical"
574
+ elif cpu_percent > 70 or memory.percent > 80 or disk.percent > 85:
575
+ overall_status = "warning"
576
+ else:
577
+ overall_status = "healthy"
578
+
579
+ service_status = {
580
+ "quality_baseline": "healthy",
581
+ "git": "healthy" if self.get_current_git_hash() else "warning",
582
+ "cache": "healthy" if self.cache else "warning",
583
+ }
584
+
585
+ return SystemHealthStatus(
586
+ overall_status=overall_status,
587
+ cpu_usage=cpu_percent,
588
+ memory_usage=memory.percent,
589
+ disk_usage=disk.percent,
590
+ service_status=service_status,
591
+ )
592
+ except ImportError:
593
+ # psutil not available, return basic status
594
+ return SystemHealthStatus(
595
+ overall_status="healthy",
596
+ cpu_usage=0.0,
597
+ memory_usage=0.0,
598
+ disk_usage=0.0,
599
+ service_status={"quality_baseline": "healthy"},
600
+ )
601
+
602
+ def create_dashboard_state(
603
+ self,
604
+ current_metrics: dict[str, t.Any],
605
+ active_job_count: int = 0,
606
+ historical_days: int = 30,
607
+ ) -> DashboardState:
608
+ """Create complete dashboard state for monitoring."""
609
+ # Create current unified metrics
610
+ unified_metrics = self.create_unified_metrics(current_metrics, active_job_count)
611
+
612
+ # Get historical data and convert to UnifiedMetrics
613
+ historical_baselines = self.get_recent_baselines(limit=historical_days)
614
+ historical_unified = [
615
+ UnifiedMetrics(
616
+ timestamp=baseline.timestamp,
617
+ quality_score=baseline.quality_score,
618
+ test_coverage=baseline.coverage_percent,
619
+ hook_duration=0.0, # Not tracked in baseline
620
+ active_jobs=0, # Historical data
621
+ error_count=(
622
+ baseline.hook_failures
623
+ + baseline.security_issues
624
+ + baseline.type_errors
625
+ + baseline.linting_issues
626
+ ),
627
+ trend_direction=TrendDirection.STABLE, # Calculate per point if needed
628
+ predictions={},
629
+ )
630
+ for baseline in historical_baselines[-10:] # Last 10 data points
631
+ ]
632
+
633
+ # Get active alerts
634
+ alerts = self.check_quality_alerts(current_metrics)
635
+
636
+ # Get system health
637
+ system_health = self.get_system_health()
638
+
639
+ # Generate recommendations
640
+ trend = self.analyze_quality_trend(days=7)
641
+ recommendations = self.generate_recommendations(current_metrics, trend, alerts)
642
+
643
+ return DashboardState(
644
+ current_metrics=unified_metrics,
645
+ historical_data=historical_unified,
646
+ active_alerts=alerts,
647
+ system_health=system_health,
648
+ recommendations=recommendations,
649
+ )