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,744 @@
1
+ """Heat map visualization generator for error patterns and code quality metrics."""
2
+
3
+ import json
4
+ import logging
5
+ import typing as t
6
+ from collections import defaultdict
7
+ from dataclasses import dataclass, field
8
+ from datetime import datetime, timedelta
9
+ from pathlib import Path
10
+
11
+ from .dependency_analyzer import DependencyGraph
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ @dataclass
17
+ class HeatMapCell:
18
+ """Individual cell in a heat map."""
19
+
20
+ x: int
21
+ y: int
22
+ value: float
23
+ label: str
24
+ metadata: dict[str, t.Any] = field(default_factory=dict[str, t.Any])
25
+ color_intensity: float = 0.0 # 0.0 to 1.0
26
+
27
+
28
+ @dataclass
29
+ class HeatMapData:
30
+ """Complete heat map data structure."""
31
+
32
+ title: str
33
+ cells: list[HeatMapCell]
34
+ x_labels: list[str]
35
+ y_labels: list[str]
36
+ color_scale: dict[str, t.Any]
37
+ metadata: dict[str, t.Any] = field(default_factory=dict[str, t.Any])
38
+ generated_at: datetime = field(default_factory=datetime.now)
39
+
40
+ def to_dict(self) -> dict[str, t.Any]:
41
+ """Convert to dictionary for JSON serialization."""
42
+ return {
43
+ "title": self.title,
44
+ "cells": [
45
+ {
46
+ "x": cell.x,
47
+ "y": cell.y,
48
+ "value": cell.value,
49
+ "label": cell.label,
50
+ "color_intensity": cell.color_intensity,
51
+ "metadata": cell.metadata,
52
+ }
53
+ for cell in self.cells
54
+ ],
55
+ "x_labels": self.x_labels,
56
+ "y_labels": self.y_labels,
57
+ "color_scale": self.color_scale,
58
+ "metadata": self.metadata,
59
+ "generated_at": self.generated_at.isoformat(),
60
+ }
61
+
62
+
63
+ class HeatMapGenerator:
64
+ """Generates heat map visualizations for various code quality metrics."""
65
+
66
+ def __init__(self) -> None:
67
+ """Initialize heat map generator."""
68
+ self.error_data: dict[str, list[dict[str, t.Any]]] = defaultdict(list)
69
+ self.metric_data: dict[str, dict[str, t.Any]] = {}
70
+
71
+ # Color schemes
72
+ self.color_schemes = {
73
+ "error_intensity": {
74
+ "low": "#90EE90", # Light green
75
+ "medium": "#FFD700", # Gold
76
+ "high": "#FF6347", # Tomato
77
+ "critical": "#DC143C", # Crimson
78
+ },
79
+ "quality_score": {
80
+ "excellent": "#228B22", # Forest green
81
+ "good": "#32CD32", # Lime green
82
+ "average": "#FFD700", # Gold
83
+ "poor": "#FF6347", # Tomato
84
+ "critical": "#DC143C", # Crimson
85
+ },
86
+ "complexity": {
87
+ "simple": "#E6F3FF", # Very light blue
88
+ "moderate": "#B3D9FF", # Light blue
89
+ "complex": "#80BFFF", # Medium blue
90
+ "very_complex": "#4D9FFF", # Dark blue
91
+ "extremely_complex": "#1A5CFF", # Very dark blue
92
+ },
93
+ }
94
+
95
+ def add_error_data(
96
+ self,
97
+ file_path: str,
98
+ line_number: int,
99
+ error_type: str,
100
+ severity: str,
101
+ timestamp: datetime | None = None,
102
+ metadata: dict[str, t.Any] | None = None,
103
+ ) -> None:
104
+ """Add error data for heat map generation."""
105
+ if timestamp is None:
106
+ timestamp = datetime.now()
107
+
108
+ error_record = {
109
+ "file_path": file_path,
110
+ "line_number": line_number,
111
+ "error_type": error_type,
112
+ "severity": severity,
113
+ "timestamp": timestamp,
114
+ "metadata": metadata or {},
115
+ }
116
+
117
+ self.error_data[file_path].append(error_record)
118
+
119
+ def add_metric_data(
120
+ self,
121
+ identifier: str,
122
+ metrics: dict[str, float],
123
+ metadata: dict[str, t.Any] | None = None,
124
+ ) -> None:
125
+ """Add metric data for heat map generation."""
126
+ self.metric_data[identifier] = {
127
+ "metrics": metrics,
128
+ "metadata": metadata or {},
129
+ "timestamp": datetime.now(),
130
+ }
131
+
132
+ def generate_error_frequency_heatmap(
133
+ self,
134
+ time_window: timedelta = timedelta(days=7),
135
+ granularity: str = "hourly", # hourly, daily, weekly
136
+ ) -> HeatMapData:
137
+ """Generate heat map showing error frequency patterns over time."""
138
+ now = datetime.now()
139
+ start_time = now - time_window
140
+
141
+ bucket_config = self._get_time_bucket_config(time_window, granularity)
142
+ file_paths = list[t.Any](self.error_data.keys())
143
+ time_buckets = self._create_time_buckets(start_time, bucket_config)
144
+ error_matrix = self._build_error_matrix(
145
+ start_time, now, time_buckets, bucket_config
146
+ )
147
+ cells = self._create_frequency_cells(file_paths, time_buckets, error_matrix)
148
+ labels = self._create_frequency_labels(
149
+ file_paths, time_buckets, bucket_config["format"]
150
+ )
151
+
152
+ return HeatMapData(
153
+ title=f"Error Frequency Heat Map ({granularity.title()})",
154
+ cells=cells,
155
+ x_labels=labels[0],
156
+ y_labels=labels[1],
157
+ color_scale=self.color_schemes["error_intensity"],
158
+ metadata={
159
+ "granularity": granularity,
160
+ "time_window_days": time_window.days,
161
+ "max_errors": self._calculate_max_errors(error_matrix),
162
+ "total_files": len(file_paths),
163
+ },
164
+ )
165
+
166
+ def _get_time_bucket_config(
167
+ self, time_window: timedelta, granularity: str
168
+ ) -> dict[str, t.Any]:
169
+ """Get time bucket configuration based on granularity."""
170
+ if granularity == "hourly":
171
+ return {
172
+ "count": int(time_window.total_seconds() / 3600),
173
+ "size": timedelta(hours=1),
174
+ "format": "%H:%M",
175
+ }
176
+ elif granularity == "daily":
177
+ return {
178
+ "count": time_window.days,
179
+ "size": timedelta(days=1),
180
+ "format": "%m/%d",
181
+ }
182
+ # weekly
183
+ return {
184
+ "count": max(1, time_window.days // 7),
185
+ "size": timedelta(weeks=1),
186
+ "format": "Week %W",
187
+ }
188
+
189
+ def _create_time_buckets(
190
+ self, start_time: datetime, bucket_config: dict[str, t.Any]
191
+ ) -> list[datetime]:
192
+ """Create time buckets for the heatmap."""
193
+ time_buckets = []
194
+ current_time = start_time
195
+ for _ in range(bucket_config["count"]):
196
+ time_buckets.append(current_time)
197
+ current_time += bucket_config["size"]
198
+ return time_buckets
199
+
200
+ def _build_error_matrix(
201
+ self,
202
+ start_time: datetime,
203
+ end_time: datetime,
204
+ time_buckets: list[datetime],
205
+ bucket_config: dict[str, t.Any],
206
+ ) -> dict[str, t.Any]:
207
+ """Build error count matrix for files and time buckets."""
208
+ from collections import defaultdict
209
+
210
+ error_matrix: dict[str, t.Any] = defaultdict(
211
+ lambda: defaultdict(int) # type: ignore[call-overload]
212
+ )
213
+
214
+ for file_path, errors in self.error_data.items():
215
+ for error in errors:
216
+ error_time = error["timestamp"]
217
+ if start_time <= error_time <= end_time:
218
+ bucket_index = self._find_time_bucket_index(
219
+ error_time, start_time, time_buckets, bucket_config["size"]
220
+ )
221
+ error_matrix[file_path][bucket_index] += 1
222
+
223
+ return error_matrix
224
+
225
+ def _find_time_bucket_index(
226
+ self,
227
+ error_time: datetime,
228
+ start_time: datetime,
229
+ time_buckets: list[datetime],
230
+ bucket_size: timedelta,
231
+ ) -> int:
232
+ """Find the appropriate time bucket index for an error."""
233
+ return min(
234
+ len(time_buckets) - 1,
235
+ int(
236
+ (error_time - start_time).total_seconds() / bucket_size.total_seconds()
237
+ ),
238
+ )
239
+
240
+ def _create_frequency_cells(
241
+ self,
242
+ file_paths: list[str],
243
+ time_buckets: list[datetime],
244
+ error_matrix: dict[str, t.Any],
245
+ ) -> list[HeatMapCell]:
246
+ """Create heat map cells from error frequency data."""
247
+ cells = []
248
+ max_errors = self._calculate_max_errors(error_matrix)
249
+
250
+ for y, file_path in enumerate(file_paths):
251
+ for x in range(len(time_buckets)):
252
+ error_count = error_matrix[file_path][x]
253
+ intensity = error_count / max_errors
254
+
255
+ cell = HeatMapCell(
256
+ x=x,
257
+ y=y,
258
+ value=error_count,
259
+ label=f"{Path(file_path).name}: {error_count} errors",
260
+ color_intensity=intensity,
261
+ metadata={
262
+ "file_path": file_path,
263
+ "time_bucket": time_buckets[x].isoformat(),
264
+ "error_count": error_count,
265
+ },
266
+ )
267
+ cells.append(cell)
268
+
269
+ return cells
270
+
271
+ def _create_frequency_labels(
272
+ self, file_paths: list[str], time_buckets: list[datetime], x_label_format: str
273
+ ) -> tuple[list[str], list[str]]:
274
+ """Create x and y labels for frequency heatmap."""
275
+ x_labels = [bucket.strftime(x_label_format) for bucket in time_buckets]
276
+ y_labels = [Path(fp).name for fp in file_paths]
277
+ return x_labels, y_labels
278
+
279
+ def _calculate_max_errors(self, error_matrix: dict[str, t.Any]) -> int:
280
+ """Calculate maximum error count for normalization."""
281
+ return (
282
+ max(
283
+ max(bucket_counts.values()) if bucket_counts else 0
284
+ for bucket_counts in error_matrix.values()
285
+ )
286
+ or 1
287
+ )
288
+
289
+ def generate_code_complexity_heatmap(self, project_root: str | Path) -> HeatMapData:
290
+ """Generate heat map showing code complexity across files and functions."""
291
+ from .dependency_analyzer import analyze_project_dependencies
292
+
293
+ project_root = Path(project_root)
294
+ dependency_graph = analyze_project_dependencies(project_root)
295
+
296
+ file_complexity = self._extract_file_complexity_data(
297
+ dependency_graph, project_root
298
+ )
299
+ cells = self._create_complexity_cells(file_complexity)
300
+ x_labels, y_labels = self._create_complexity_labels(file_complexity, cells)
301
+ max_complexity = self._calculate_max_complexity(file_complexity)
302
+
303
+ return HeatMapData(
304
+ title="Code Complexity Heat Map",
305
+ cells=cells,
306
+ x_labels=x_labels,
307
+ y_labels=y_labels,
308
+ color_scale=self.color_schemes["complexity"],
309
+ metadata={
310
+ "max_complexity": max_complexity,
311
+ "total_files": len(file_complexity),
312
+ "complexity_threshold": 15,
313
+ },
314
+ )
315
+
316
+ def _extract_file_complexity_data(
317
+ self, dependency_graph: DependencyGraph, project_root: Path
318
+ ) -> dict[str, t.Any]:
319
+ """Extract complexity data grouped by file."""
320
+ file_complexity = defaultdict(list)
321
+
322
+ for node in dependency_graph.nodes.values():
323
+ if node.type in ("function", "method", "class"):
324
+ relative_path = str(Path(node.file_path).relative_to(project_root))
325
+ file_complexity[relative_path].append(
326
+ {
327
+ "name": node.name,
328
+ "complexity": node.complexity,
329
+ "type": node.type,
330
+ "line": node.line_number,
331
+ }
332
+ )
333
+ return file_complexity
334
+
335
+ def _create_complexity_cells(
336
+ self, file_complexity: dict[str, t.Any]
337
+ ) -> list[HeatMapCell]:
338
+ """Create heat map cells from complexity data."""
339
+ cells = []
340
+ files = list[t.Any](file_complexity.keys())
341
+
342
+ for y, file_path in enumerate(files):
343
+ from operator import itemgetter
344
+
345
+ functions = sorted(file_complexity[file_path], key=itemgetter("line"))
346
+
347
+ for x, func_data in enumerate(functions[:50]): # Limit to 50 functions
348
+ cell = self._create_complexity_cell(x, y, func_data, file_path)
349
+ cells.append(cell)
350
+
351
+ return cells
352
+
353
+ def _create_complexity_cell(
354
+ self, x: int, y: int, func_data: dict[str, t.Any], file_path: str
355
+ ) -> HeatMapCell:
356
+ """Create a single complexity heat map cell."""
357
+ complexity = func_data["complexity"]
358
+ intensity = min(1.0, complexity / 15) # Normalize to complexity threshold
359
+ complexity_level = self._get_complexity_level(complexity)
360
+
361
+ return HeatMapCell(
362
+ x=x,
363
+ y=y,
364
+ value=complexity,
365
+ label=f"{func_data['name']}: {complexity}",
366
+ color_intensity=intensity,
367
+ metadata={
368
+ "file_path": file_path,
369
+ "function_name": func_data["name"],
370
+ "function_type": func_data["type"],
371
+ "line_number": func_data["line"],
372
+ "complexity": complexity,
373
+ "complexity_level": complexity_level,
374
+ },
375
+ )
376
+
377
+ def _get_complexity_level(self, complexity: int) -> str:
378
+ """Determine complexity category based on value."""
379
+ if complexity <= 5:
380
+ return "simple"
381
+ elif complexity <= 10:
382
+ return "moderate"
383
+ elif complexity <= 15:
384
+ return "complex"
385
+ elif complexity <= 20:
386
+ return "very_complex"
387
+ return "extremely_complex"
388
+
389
+ def _create_complexity_labels(
390
+ self, file_complexity: dict[str, t.Any], cells: list[HeatMapCell]
391
+ ) -> tuple[list[str], list[str]]:
392
+ """Create x and y labels for complexity heat map."""
393
+ files = list[t.Any](file_complexity.keys())
394
+ y_labels = [Path(fp).name for fp in files]
395
+
396
+ max_x = max(cell.x for cell in cells) if cells else 0
397
+ x_labels = [f"Func {x + 1}" for x in range(max_x + 1)]
398
+
399
+ return x_labels, y_labels
400
+
401
+ def _calculate_max_complexity(self, file_complexity: dict[str, t.Any]) -> int:
402
+ """Calculate maximum complexity value across all functions."""
403
+ return (
404
+ max(
405
+ max(item["complexity"] for item in items)
406
+ for items in file_complexity.values()
407
+ if items
408
+ )
409
+ or 1
410
+ )
411
+
412
+ def generate_quality_metrics_heatmap(self) -> HeatMapData:
413
+ """Generate heat map showing various quality metrics."""
414
+ if not self.metric_data:
415
+ return self._get_default_quality_heatmap()
416
+
417
+ metric_types = self._get_quality_metric_types()
418
+ identifiers = list[t.Any](self.metric_data.keys())
419
+ max_values = self._calculate_metric_max_values(metric_types)
420
+ cells = self._create_quality_metric_cells(identifiers, metric_types, max_values)
421
+
422
+ return HeatMapData(
423
+ title="Quality Metrics Heat Map",
424
+ cells=cells,
425
+ x_labels=metric_types,
426
+ y_labels=identifiers,
427
+ color_scale=self.color_schemes["quality_score"],
428
+ metadata={
429
+ "metric_count": len(metric_types),
430
+ "entity_count": len(identifiers),
431
+ },
432
+ )
433
+
434
+ def _get_default_quality_heatmap(self) -> HeatMapData:
435
+ """Return default quality heatmap for empty data."""
436
+ return HeatMapData(
437
+ title="Quality Metrics Heat Map",
438
+ cells=[],
439
+ x_labels=[],
440
+ y_labels=[],
441
+ color_scale=self.color_schemes["quality_score"],
442
+ )
443
+
444
+ def _get_quality_metric_types(self) -> list[str]:
445
+ """Define metric types to visualize."""
446
+ return [
447
+ "test_coverage",
448
+ "complexity_score",
449
+ "duplication_ratio",
450
+ "documentation_ratio",
451
+ "security_score",
452
+ "performance_score",
453
+ ]
454
+
455
+ def _calculate_metric_max_values(self, metric_types: list[str]) -> dict[str, float]:
456
+ """Calculate max values for normalization."""
457
+ max_values: dict[str, float] = {}
458
+ for metric_type in metric_types:
459
+ values = [
460
+ data["metrics"][metric_type]
461
+ for data in self.metric_data.values()
462
+ if metric_type in data["metrics"]
463
+ ]
464
+ max_values[metric_type] = max(values) if values else 1
465
+ return max_values
466
+
467
+ def _create_quality_metric_cells(
468
+ self,
469
+ identifiers: list[str],
470
+ metric_types: list[str],
471
+ max_values: dict[str, float],
472
+ ) -> list[HeatMapCell]:
473
+ """Create cells for quality metrics heatmap."""
474
+ cells = []
475
+ for y, identifier in enumerate(identifiers):
476
+ data = self.metric_data[identifier]
477
+ metrics = data["metrics"]
478
+
479
+ for x, metric_type in enumerate(metric_types):
480
+ value = metrics.get(metric_type, 0)
481
+ intensity = value / max_values[metric_type]
482
+ quality_score = self._calculate_quality_score(metric_type, intensity)
483
+ quality_level = self._determine_quality_level(quality_score)
484
+
485
+ cell = HeatMapCell(
486
+ x=x,
487
+ y=y,
488
+ value=value,
489
+ label=f"{identifier}: {metric_type} = {value:.2f}",
490
+ color_intensity=quality_score,
491
+ metadata={
492
+ "identifier": identifier,
493
+ "metric_type": metric_type,
494
+ "raw_value": value,
495
+ "quality_score": quality_score,
496
+ "quality_level": quality_level,
497
+ },
498
+ )
499
+ cells.append(cell)
500
+ return cells
501
+
502
+ def _calculate_quality_score(self, metric_type: str, intensity: float) -> float:
503
+ """Calculate quality score for a metric (higher is better for most metrics)."""
504
+ if metric_type in ("complexity_score", "duplication_ratio"):
505
+ # Lower is better for these metrics
506
+ return 1.0 - min(1.0, intensity)
507
+ # Higher is better
508
+ return intensity
509
+
510
+ def _determine_quality_level(self, quality_score: float) -> str:
511
+ """Determine quality level from quality score."""
512
+ if quality_score >= 0.9:
513
+ return "excellent"
514
+ elif quality_score >= 0.7:
515
+ return "good"
516
+ elif quality_score >= 0.5:
517
+ return "average"
518
+ elif quality_score >= 0.3:
519
+ return "poor"
520
+ return "critical"
521
+
522
+ def generate_test_failure_heatmap(
523
+ self, time_window: timedelta = timedelta(days=14)
524
+ ) -> HeatMapData:
525
+ """Generate heat map showing test failure patterns."""
526
+ test_errors = self._filter_test_errors(time_window)
527
+ test_matrix = self._group_test_errors_by_matrix(test_errors)
528
+ test_files = list[t.Any](test_matrix.keys())
529
+ error_types = self._collect_error_types(test_matrix)
530
+ max_failures = self._calculate_max_test_failures(test_matrix)
531
+ cells = self._create_test_failure_cells(
532
+ test_matrix, test_files, error_types, max_failures
533
+ )
534
+ metadata = self._build_test_failure_metadata(
535
+ time_window, max_failures, test_files, error_types
536
+ )
537
+
538
+ return HeatMapData(
539
+ title="Test Failure Heat Map",
540
+ cells=cells,
541
+ x_labels=error_types,
542
+ y_labels=test_files,
543
+ color_scale=self.color_schemes["error_intensity"],
544
+ metadata=metadata,
545
+ )
546
+
547
+ def _filter_test_errors(self, time_window: timedelta) -> list[dict[str, t.Any]]:
548
+ """Filter for test-related errors within the time window."""
549
+ test_errors: list[dict[str, t.Any]] = []
550
+ now = datetime.now()
551
+ start_time = now - time_window
552
+
553
+ for file_path, errors in self.error_data.items():
554
+ for error in errors:
555
+ if error["timestamp"] >= start_time and (
556
+ "test" in error["error_type"].lower() or "test" in file_path.lower()
557
+ ):
558
+ test_errors.append(error | {"file_path": file_path})
559
+ return test_errors
560
+
561
+ def _group_test_errors_by_matrix(
562
+ self, test_errors: list[dict[str, t.Any]]
563
+ ) -> defaultdict[str, defaultdict[str, int]]:
564
+ """Group test errors by file and error type."""
565
+ from collections import defaultdict as dd
566
+
567
+ def make_inner_defaultdict() -> defaultdict[str, int]:
568
+ return dd(int)
569
+
570
+ test_matrix: defaultdict[str, defaultdict[str, int]] = defaultdict(
571
+ make_inner_defaultdict
572
+ )
573
+
574
+ for error in test_errors:
575
+ file_name = Path(error["file_path"]).name
576
+ error_type = error["error_type"]
577
+ test_matrix[file_name][error_type] += 1
578
+
579
+ return test_matrix
580
+
581
+ def _collect_error_types(
582
+ self, test_matrix: defaultdict[str, defaultdict[str, int]]
583
+ ) -> list[str]:
584
+ """Collect all unique error types from the test matrix."""
585
+ all_error_types: set[str] = set()
586
+ for error_types in test_matrix.values():
587
+ all_error_types.update(error_types.keys())
588
+ return list[t.Any](all_error_types)
589
+
590
+ def _calculate_max_test_failures(
591
+ self, test_matrix: defaultdict[str, defaultdict[str, int]]
592
+ ) -> int:
593
+ """Calculate maximum failures for normalization."""
594
+ return (
595
+ max(
596
+ max(error_counts.values()) if error_counts else 0
597
+ for error_counts in test_matrix.values()
598
+ )
599
+ or 1
600
+ )
601
+
602
+ def _create_test_failure_cells(
603
+ self,
604
+ test_matrix: defaultdict[str, defaultdict[str, int]],
605
+ test_files: list[str],
606
+ error_types: list[str],
607
+ max_failures: int,
608
+ ) -> list[HeatMapCell]:
609
+ """Create cells for the test failure heatmap."""
610
+ cells = []
611
+ for y, test_file in enumerate(test_files):
612
+ for x, error_type in enumerate(error_types):
613
+ failure_count = test_matrix[test_file][error_type]
614
+ intensity = failure_count / max_failures
615
+
616
+ cell = HeatMapCell(
617
+ x=x,
618
+ y=y,
619
+ value=failure_count,
620
+ label=f"{test_file}: {error_type} ({failure_count} failures)",
621
+ color_intensity=intensity,
622
+ metadata={
623
+ "test_file": test_file,
624
+ "error_type": error_type,
625
+ "failure_count": failure_count,
626
+ },
627
+ )
628
+ cells.append(cell)
629
+ return cells
630
+
631
+ def _build_test_failure_metadata(
632
+ self,
633
+ time_window: timedelta,
634
+ max_failures: int,
635
+ test_files: list[str],
636
+ error_types: list[str],
637
+ ) -> dict[str, t.Any]:
638
+ """Build metadata dictionary for test failure heatmap."""
639
+ return {
640
+ "time_window_days": time_window.days,
641
+ "max_failures": max_failures,
642
+ "total_test_files": len(test_files),
643
+ "total_error_types": len(error_types),
644
+ }
645
+
646
+ def export_heatmap_data(
647
+ self, heatmap: HeatMapData, output_path: str | Path, format_type: str = "json"
648
+ ) -> None:
649
+ """Export heat map data to file."""
650
+ if format_type.lower() == "json":
651
+ with open(output_path, "w", encoding="utf-8") as f:
652
+ json.dump(heatmap.to_dict(), f, indent=2)
653
+ elif format_type.lower() == "csv":
654
+ import csv
655
+
656
+ with open(output_path, "w", newline="", encoding="utf-8") as f:
657
+ writer = csv.writer(f)
658
+
659
+ # Write header
660
+ writer.writerow(["x", "y", "value", "label", "intensity"])
661
+
662
+ # Write data
663
+ for cell in heatmap.cells:
664
+ writer.writerow(
665
+ [
666
+ cell.x,
667
+ cell.y,
668
+ cell.value,
669
+ cell.label,
670
+ cell.color_intensity,
671
+ ]
672
+ )
673
+ else:
674
+ msg = f"Unsupported format: {format_type}"
675
+ raise ValueError(msg)
676
+
677
+ def generate_html_visualization(self, heatmap: HeatMapData) -> str:
678
+ """Generate HTML visualization for the heat map."""
679
+ html_template = """
680
+ <!DOCTYPE html>
681
+ <html>
682
+ <head>
683
+ <title>{title}</title>
684
+ <style>
685
+ body {{ font-family: Arial, sans-serif; margin: 20px; }}
686
+ .heatmap {{ display: grid; gap: 1px; background: #ddd; }}
687
+ .cell {{
688
+ padding: 5px;
689
+ text-align: center;
690
+ font-size: 10px;
691
+ min-width: 80px;
692
+ min-height: 20px;
693
+ }}
694
+ .legend {{ margin-top: 20px; }}
695
+ .legend-item {{ display: inline-block; margin: 0 10px; }}
696
+ </style>
697
+ </head>
698
+ <body>
699
+ <h1>{title}</h1>
700
+ <div class="heatmap" style="grid-template-columns: repeat({cols}, 1fr);">
701
+ {cells_html}
702
+ </div>
703
+ <div class="legend">
704
+ {legend_html}
705
+ </div>
706
+ <p>Generated at: {generated_at}</p>
707
+ </body>
708
+ </html>
709
+ """
710
+
711
+ # Generate cells HTML
712
+ cells_html = ""
713
+ for cell in heatmap.cells:
714
+ # Calculate color based on intensity
715
+ intensity = int(255 * (1 - cell.color_intensity))
716
+ color = f"rgb({255}, {intensity}, {intensity})"
717
+
718
+ cells_html += f"""
719
+ <div class="cell" style="background-color: {color};"
720
+ title="{cell.label}">
721
+ {cell.value:.1f}
722
+ </div>
723
+ """
724
+
725
+ # Generate legend HTML
726
+ legend_html = ""
727
+ for level, color in heatmap.color_scale.items():
728
+ legend_html += f"""
729
+ <div class="legend-item">
730
+ <span style="background-color: {color}; padding: 2px 8px;">
731
+ {level.title()}
732
+ </span>
733
+ </div>
734
+ """
735
+
736
+ max_x = max(cell.x for cell in heatmap.cells) if heatmap.cells else 1
737
+
738
+ return html_template.format(
739
+ title=heatmap.title,
740
+ cols=max_x + 1,
741
+ cells_html=cells_html,
742
+ legend_html=legend_html,
743
+ generated_at=heatmap.generated_at.isoformat(),
744
+ )