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,894 @@
1
+ import time
2
+ import typing as t
3
+ from pathlib import Path
4
+
5
+ from acb.console import Console
6
+ from rich.console import Group
7
+ from rich.panel import Panel
8
+ from rich.table import Table
9
+
10
+ from crackerjack.agents import (
11
+ AgentContext,
12
+ AgentCoordinator,
13
+ Issue,
14
+ IssueType,
15
+ Priority,
16
+ )
17
+ from crackerjack.config.hooks import HookConfigLoader, HookStrategy
18
+ from crackerjack.core.session_coordinator import SessionCoordinator
19
+ from crackerjack.executors.hook_executor import HookExecutor
20
+ from crackerjack.executors.individual_hook_executor import (
21
+ HookProgress,
22
+ IndividualHookExecutor,
23
+ )
24
+ from crackerjack.managers.test_manager import TestManagementImpl
25
+ from crackerjack.models.protocols import OptionsProtocol
26
+ from crackerjack.models.task import HookResult
27
+ from crackerjack.services.monitoring.metrics import get_metrics_collector
28
+
29
+ from .execution_strategies import (
30
+ AICoordinationMode,
31
+ ExecutionContext,
32
+ ExecutionPlan,
33
+ ExecutionStrategy,
34
+ OrchestrationConfig,
35
+ OrchestrationPlanner,
36
+ )
37
+ from .test_progress_streamer import TestProgressStreamer, TestSuiteProgress
38
+
39
+
40
+ class CorrelationTracker:
41
+ def __init__(self) -> None:
42
+ self.iteration_data: list[dict[str, t.Any]] = []
43
+ self.failure_patterns: dict[str, list[str]] = {}
44
+ self.fix_success_rates: dict[str, float] = {}
45
+
46
+ def record_iteration(
47
+ self,
48
+ iteration: int,
49
+ hook_results: list[HookResult],
50
+ test_results: dict[str, t.Any],
51
+ ai_fixes: list[str],
52
+ ) -> None:
53
+ failed_hooks = [r.name for r in hook_results if r.status == "failed"]
54
+
55
+ iteration_data = {
56
+ "iteration": iteration,
57
+ "timestamp": time.time(),
58
+ "failed_hooks": failed_hooks,
59
+ "test_failures": test_results.get("failed_tests", []),
60
+ "ai_fixes_applied": ai_fixes,
61
+ "total_errors": sum(
62
+ len(getattr(r, "error_details", [])) for r in hook_results
63
+ ),
64
+ }
65
+
66
+ self.iteration_data.append(iteration_data)
67
+ self._analyze_failure_patterns()
68
+
69
+ def _analyze_failure_patterns(self) -> None:
70
+ if len(self.iteration_data) < 2:
71
+ return
72
+
73
+ for i in range(1, len(self.iteration_data)):
74
+ current = self.iteration_data[i]
75
+ previous = self.iteration_data[i - 1]
76
+
77
+ recurring_failures = set[t.Any](current["failed_hooks"]) & set[t.Any](
78
+ previous["failed_hooks"],
79
+ )
80
+
81
+ for hook in recurring_failures:
82
+ if hook not in self.failure_patterns:
83
+ self.failure_patterns[hook] = []
84
+ self.failure_patterns[hook].append(f"iteration_{current['iteration']}")
85
+
86
+ def get_problematic_hooks(self) -> list[str]:
87
+ return [
88
+ hook
89
+ for hook, failures in self.failure_patterns.items()
90
+ if len(failures) >= 2
91
+ ]
92
+
93
+ def get_correlation_data(self) -> dict[str, t.Any]:
94
+ return {
95
+ "iteration_count": len(self.iteration_data),
96
+ "failure_patterns": self.failure_patterns,
97
+ "problematic_hooks": self.get_problematic_hooks(),
98
+ "recent_trends": self.iteration_data[-3:]
99
+ if len(self.iteration_data) >= 3
100
+ else self.iteration_data,
101
+ }
102
+
103
+
104
+ class ProgressStreamer:
105
+ """Base class for streaming progress updates during orchestration."""
106
+
107
+ def __init__(
108
+ self,
109
+ config: OrchestrationConfig | None = None,
110
+ session: SessionCoordinator | None = None,
111
+ ) -> None:
112
+ self.config = config
113
+ self.session = session
114
+
115
+ def update_stage(self, stage: str, substage: str = "") -> None:
116
+ """Update current stage."""
117
+ pass
118
+
119
+ def update_hook_progress(self, progress: HookProgress) -> None:
120
+ """Update hook progress."""
121
+ pass
122
+
123
+ def _stream_update(self, data: dict[str, t.Any]) -> None:
124
+ """Stream update data."""
125
+ pass
126
+
127
+
128
+ class MinimalProgressStreamer(ProgressStreamer):
129
+ def __init__(
130
+ self,
131
+ config: OrchestrationConfig | None = None,
132
+ session: SessionCoordinator | None = None,
133
+ ) -> None:
134
+ # Minimal implementation doesn't use config or session
135
+ pass
136
+
137
+ def update_stage(self, stage: str, substage: str = "") -> None:
138
+ pass
139
+
140
+ def update_hook_progress(self, progress: HookProgress) -> None:
141
+ pass
142
+
143
+ def _stream_update(self, data: dict[str, t.Any]) -> None:
144
+ pass
145
+
146
+
147
+ class AdvancedWorkflowOrchestrator:
148
+ def __init__(
149
+ self,
150
+ console: Console,
151
+ pkg_path: Path,
152
+ session: SessionCoordinator,
153
+ config: OrchestrationConfig | None = None,
154
+ ) -> None:
155
+ self.console = console
156
+ self.pkg_path = pkg_path
157
+ self.session = session
158
+ self.config = config or OrchestrationConfig()
159
+
160
+ self.hook_config_loader = HookConfigLoader()
161
+ self.batch_executor = HookExecutor(console, pkg_path, quiet=True)
162
+ self.individual_executor = IndividualHookExecutor(console, pkg_path)
163
+ self.test_manager = TestManagementImpl(console, pkg_path)
164
+ self.test_streamer = TestProgressStreamer(console, pkg_path)
165
+ self.planner = OrchestrationPlanner(console)
166
+
167
+ self.correlation_tracker = CorrelationTracker()
168
+ try:
169
+ self.progress_streamer = ProgressStreamer(self.config, session)
170
+ except Exception as e:
171
+ console.print(
172
+ f"[yellow]Warning: ProgressStreamer initialization failed: {e}[/ yellow]",
173
+ )
174
+ self.progress_streamer = MinimalProgressStreamer()
175
+ self.metrics = get_metrics_collector()
176
+
177
+ self._detect_and_configure_mcp_mode()
178
+
179
+ self.agent_coordinator: AgentCoordinator | None = None
180
+
181
+ def _detect_and_configure_mcp_mode(self) -> None:
182
+ is_mcp_mode = (
183
+ hasattr(self.console.file, "getvalue")
184
+ or not self.console.is_terminal
185
+ or hasattr(self.session, "job_id")
186
+ )
187
+
188
+ if is_mcp_mode:
189
+ self.individual_executor.set_mcp_mode(True)
190
+ self.console.print(
191
+ "[dim]🔧 MCP mode detected-using minimal output mode[/ dim]",
192
+ )
193
+ if self.config.ai_coordination_mode in (
194
+ AICoordinationMode.MULTI_AGENT,
195
+ AICoordinationMode.COORDINATOR,
196
+ ):
197
+ self._initialize_multi_agent_system()
198
+
199
+ self.individual_executor.set_progress_callback(
200
+ self.progress_streamer.update_hook_progress,
201
+ )
202
+ self.test_streamer.set_progress_callback(self._update_test_suite_progress)
203
+
204
+ def _configure_verbose_mode(self, options: OptionsProtocol) -> None:
205
+ verbose_mode = getattr(options, "verbose", False)
206
+
207
+ if not hasattr(self.console.file, "getvalue"):
208
+ quiet_mode = not verbose_mode
209
+ self.individual_executor.set_mcp_mode(quiet_mode)
210
+
211
+ if verbose_mode:
212
+ self.console.print(
213
+ "[dim]🔧 Verbose mode enabled-showing detailed hook output[/ dim]",
214
+ )
215
+
216
+ def _initialize_multi_agent_system(self) -> None:
217
+ self.console.print(
218
+ "[bold cyan]🤖 Initializing Multi-Agent AI System[/ bold cyan]",
219
+ )
220
+
221
+ agent_context = AgentContext(
222
+ project_path=self.pkg_path,
223
+ session_id=getattr(self.session, "job_id", None),
224
+ )
225
+
226
+ self.agent_coordinator = AgentCoordinator(agent_context)
227
+ self.agent_coordinator.initialize_agents()
228
+
229
+ capabilities = self.agent_coordinator.get_agent_capabilities()
230
+ self.console.print(
231
+ f"[green]✅ Initialized {len(capabilities)} specialized agents: [/ green]",
232
+ )
233
+ for agent_name, info in capabilities.items():
234
+ types_str = ", ".join(info["supported_types"])
235
+ self.console.print(f" • {agent_name}: {types_str}")
236
+
237
+ self.console.print(
238
+ f"[cyan]AI Coordination Mode: {self.config.ai_coordination_mode.value}[/ cyan]",
239
+ )
240
+
241
+ def _display_iteration_stats(
242
+ self,
243
+ iteration: int,
244
+ max_iterations: int,
245
+ iteration_times: dict[str, float],
246
+ hooks_time: float,
247
+ tests_time: float,
248
+ ai_time: float,
249
+ context: t.Any,
250
+ ) -> None:
251
+ timing_table = Table(show_header=True, header_style="bold cyan")
252
+ timing_table.add_column("Phase", style="cyan")
253
+ timing_table.add_column("This Iteration", justify="right", style="yellow")
254
+ timing_table.add_column("Cumulative", justify="right", style="green")
255
+
256
+ timing_table.add_row(
257
+ "🔧 Hooks",
258
+ f"{iteration_times.get('hooks', 0): .1f}s",
259
+ f"{hooks_time: .1f}s",
260
+ )
261
+ timing_table.add_row(
262
+ "🧪 Tests",
263
+ f"{iteration_times.get('tests', 0): .1f}s",
264
+ f"{tests_time: .1f}s",
265
+ )
266
+ timing_table.add_row(
267
+ "🤖 AI Analysis",
268
+ f"{iteration_times.get('ai', 0): .1f}s",
269
+ f"{ai_time: .1f}s",
270
+ )
271
+
272
+ total_iteration_time = sum(iteration_times.values())
273
+ total_cumulative_time = hooks_time + tests_time + ai_time
274
+ timing_table.add_row(
275
+ "📊 Total",
276
+ f"{total_iteration_time: .1f}s",
277
+ f"{total_cumulative_time: .1f}s",
278
+ style="bold",
279
+ )
280
+
281
+ status_table = Table(show_header=True, header_style="bold magenta")
282
+ status_table.add_column("Metric", style="magenta")
283
+ status_table.add_column("Value", justify="right", style="white")
284
+
285
+ status_table.add_row("🔄 Iteration", f"{iteration}/{max_iterations}")
286
+ status_table.add_row(
287
+ "📈 Progress",
288
+ f"{(iteration / max_iterations) * 100: .1f}%",
289
+ )
290
+
291
+ if hasattr(context, "hook_failures"):
292
+ status_table.add_row("❌ Hook Failures", str(len(context.hook_failures)))
293
+ if hasattr(context, "test_failures"):
294
+ status_table.add_row("🧪 Test Failures", str(len(context.test_failures)))
295
+
296
+ panel_content = Group(
297
+ "[bold white]Timing Breakdown[/ bold white]",
298
+ timing_table,
299
+ "",
300
+ "[bold white]Status Summary[/ bold white]",
301
+ status_table,
302
+ )
303
+
304
+ iteration_panel = Panel(
305
+ panel_content,
306
+ title=f"[bold bright_blue]📊 Iteration {iteration} Statistics[/ bold bright_blue]",
307
+ border_style="bright_blue",
308
+ padding=(1, 2),
309
+ )
310
+
311
+ self.console.print()
312
+ self.console.print(iteration_panel)
313
+ self.console.print()
314
+
315
+ async def execute_orchestrated_workflow(
316
+ self,
317
+ options: OptionsProtocol,
318
+ max_iterations: int = 10,
319
+ ) -> bool:
320
+ self._configure_verbose_mode(options)
321
+
322
+ workflow_start_time = time.time()
323
+ job_id = (
324
+ getattr(self.session, "job_id", None) or f"orchestration_{int(time.time())}"
325
+ )
326
+
327
+ self.console.print(
328
+ "\n[bold bright_blue]🚀 STARTING ORCHESTRATED WORKFLOW[/ bold bright_blue]",
329
+ )
330
+
331
+ context = ExecutionContext(self.pkg_path, options)
332
+
333
+ hook_strategies = [
334
+ self.hook_config_loader.load_strategy("fast"),
335
+ self.hook_config_loader.load_strategy("comprehensive"),
336
+ ]
337
+
338
+ execution_plan = self.planner.create_execution_plan(
339
+ self.config,
340
+ context,
341
+ hook_strategies,
342
+ )
343
+
344
+ execution_plan.print_plan_summary(self.console)
345
+
346
+ success = False
347
+ strategy_switches = 0
348
+ hooks_time: float = 0.0
349
+ tests_time: float = 0.0
350
+ ai_time: float = 0.0
351
+
352
+ for iteration in range(1, max_iterations + 1):
353
+ self.console.print(
354
+ f"\n[bold bright_yellow]🔄 ITERATION {iteration} / {max_iterations}[/ bold bright_yellow]",
355
+ )
356
+
357
+ context.iteration_count = iteration
358
+
359
+ time.time()
360
+ iteration_success, iteration_times = await self._execute_single_iteration(
361
+ execution_plan,
362
+ context,
363
+ iteration,
364
+ )
365
+
366
+ hooks_time += iteration_times.get("hooks", 0)
367
+ tests_time += iteration_times.get("tests", 0)
368
+ ai_time += iteration_times.get("ai", 0)
369
+
370
+ self._display_iteration_stats(
371
+ iteration,
372
+ max_iterations,
373
+ iteration_times,
374
+ hooks_time,
375
+ tests_time,
376
+ ai_time,
377
+ context,
378
+ )
379
+
380
+ if iteration_success:
381
+ self.console.print(
382
+ f"\n[bold green]🎉 WORKFLOW COMPLETED SUCCESSFULLY IN {iteration} ITERATIONS ![/ bold green]",
383
+ )
384
+ success = True
385
+ break
386
+
387
+ if iteration < max_iterations:
388
+ old_strategy = execution_plan.execution_strategy
389
+ execution_plan = self._adapt_execution_plan(execution_plan, context)
390
+ if execution_plan.execution_strategy != old_strategy:
391
+ strategy_switches += 1
392
+
393
+ if not success:
394
+ self.console.print(
395
+ f"\n[bold red]❌ WORKFLOW INCOMPLETE AFTER {max_iterations} ITERATIONS[/ bold red]",
396
+ )
397
+
398
+ self._print_final_analysis()
399
+
400
+ total_time = int((time.time() - workflow_start_time) * 1000)
401
+ correlation_data = self.correlation_tracker.get_correlation_data()
402
+
403
+ self.metrics.record_orchestration_execution(
404
+ job_id=job_id,
405
+ execution_strategy=execution_plan.execution_strategy.value,
406
+ progress_level=self.config.progress_level.value,
407
+ ai_mode=self.config.ai_coordination_mode.value,
408
+ iteration_count=context.iteration_count,
409
+ strategy_switches=strategy_switches,
410
+ correlation_insights=correlation_data,
411
+ total_execution_time_ms=total_time,
412
+ hooks_execution_time_ms=round(hooks_time * 1000),
413
+ tests_execution_time_ms=round(tests_time * 1000),
414
+ ai_analysis_time_ms=round(ai_time * 1000),
415
+ )
416
+
417
+ return success
418
+
419
+ async def _execute_single_iteration(
420
+ self,
421
+ plan: ExecutionPlan,
422
+ context: ExecutionContext,
423
+ iteration: int,
424
+ ) -> tuple[bool, dict[str, float]]:
425
+ self.progress_streamer.update_stage("iteration_start", f"iteration_{iteration}")
426
+
427
+ phase_times: dict[str, float] = {"hooks": 0.0, "tests": 0.0, "ai": 0.0}
428
+
429
+ hooks_start = time.time()
430
+ hook_results = await self._execute_hooks_phase(plan, context)
431
+ phase_times["hooks"] = time.time() - hooks_start
432
+
433
+ tests_start = time.time()
434
+ test_results = await self._execute_tests_phase(plan, context)
435
+ phase_times["tests"] = time.time() - tests_start
436
+
437
+ ai_fixes = []
438
+ if not (
439
+ all(r.status == "passed" for r in hook_results)
440
+ and test_results.get("success", False)
441
+ ):
442
+ ai_start = time.time()
443
+ ai_fixes = await self._execute_ai_phase(plan, hook_results, test_results)
444
+ phase_times["ai"] = time.time() - ai_start
445
+
446
+ job_id = (
447
+ getattr(self.session, "job_id", None) or f"orchestration_{int(time.time())}"
448
+ )
449
+ self.metrics.record_strategy_decision(
450
+ job_id=job_id,
451
+ iteration=iteration,
452
+ previous_strategy=getattr(context, "previous_strategy", None),
453
+ selected_strategy=plan.execution_strategy.value,
454
+ decision_reason=f"Iteration {iteration} execution strategy",
455
+ context_data={
456
+ "failed_hooks": len([r for r in hook_results if r.status == "failed"]),
457
+ "failed_tests": len(test_results.get("failed_tests", [])),
458
+ "ai_fixes_applied": len(ai_fixes),
459
+ },
460
+ effectiveness_score=None,
461
+ )
462
+
463
+ self.correlation_tracker.record_iteration(
464
+ iteration,
465
+ hook_results,
466
+ test_results,
467
+ ai_fixes,
468
+ )
469
+
470
+ all_hooks_passed = all(r.status == "passed" for r in hook_results)
471
+ all_tests_passed = test_results.get("success", False)
472
+
473
+ return all_hooks_passed and all_tests_passed, phase_times
474
+
475
+ async def _execute_hooks_phase(
476
+ self,
477
+ plan: ExecutionPlan,
478
+ context: ExecutionContext,
479
+ ) -> list[HookResult]:
480
+ self.progress_streamer.update_stage("hooks", "starting")
481
+
482
+ all_results = []
483
+
484
+ for hook_plan in plan.hook_plans:
485
+ strategy = hook_plan["strategy"]
486
+ execution_mode = hook_plan["execution_mode"]
487
+
488
+ if strategy.name == "fast":
489
+ fast_results = await self._execute_fast_hooks_with_autofix(
490
+ strategy,
491
+ execution_mode,
492
+ context,
493
+ )
494
+ all_results.extend(fast_results)
495
+ else:
496
+ self.progress_streamer.update_stage(
497
+ "hooks",
498
+ f"executing_{strategy.name}",
499
+ )
500
+
501
+ if execution_mode == ExecutionStrategy.INDIVIDUAL:
502
+ result = await self.individual_executor.execute_strategy_individual(
503
+ strategy,
504
+ )
505
+ all_results.extend(result.hook_results)
506
+ else:
507
+ results = self.batch_executor.execute_strategy(strategy)
508
+ all_results.extend(results.results)
509
+
510
+ self.progress_streamer.update_stage("hooks", "completed")
511
+ return all_results
512
+
513
+ async def _execute_fast_hooks_with_autofix(
514
+ self,
515
+ strategy: HookStrategy,
516
+ execution_mode: ExecutionStrategy,
517
+ context: ExecutionContext,
518
+ ) -> list[HookResult]:
519
+ self.progress_streamer.update_stage("hooks", "fast_hooks_with_autofix")
520
+
521
+ max_autofix_cycles = 2
522
+ autofix_cycle = 0
523
+
524
+ while autofix_cycle < max_autofix_cycles:
525
+ self.console.print(
526
+ f"[cyan]🚀 Fast hooks execution (autofix cycle {autofix_cycle + 1}/{max_autofix_cycles})[/ cyan]",
527
+ )
528
+
529
+ first_attempt = await self._execute_fast_hooks_attempt(
530
+ strategy,
531
+ execution_mode,
532
+ )
533
+
534
+ if all(r.status == "passed" for r in first_attempt):
535
+ self.console.print(
536
+ "[green]✅ Fast hooks passed on first attempt[/ green]",
537
+ )
538
+ return first_attempt
539
+
540
+ self.console.print(
541
+ "[yellow]⚠️ Fast hooks failed on first attempt, retrying...[/ yellow]",
542
+ )
543
+ second_attempt = await self._execute_fast_hooks_attempt(
544
+ strategy,
545
+ execution_mode,
546
+ )
547
+
548
+ if all(r.status == "passed" for r in second_attempt):
549
+ self.console.print(
550
+ "[green]✅ Fast hooks passed on second attempt[/ green]",
551
+ )
552
+ return second_attempt
553
+
554
+ autofix_cycle += 1
555
+ if autofix_cycle < max_autofix_cycles:
556
+ self.console.print(
557
+ "[red]❌ Fast hooks failed twice, triggering autofix cycle...[/ red]",
558
+ )
559
+ await self._trigger_autofix_for_fast_hooks(second_attempt)
560
+ else:
561
+ self.console.print(
562
+ "[red]❌ Fast hooks failed after maximum autofix cycles[/ red]",
563
+ )
564
+ return second_attempt
565
+
566
+ return []
567
+
568
+ async def _execute_fast_hooks_attempt(
569
+ self,
570
+ strategy: HookStrategy,
571
+ execution_mode: ExecutionStrategy,
572
+ ) -> list[HookResult]:
573
+ if execution_mode == ExecutionStrategy.INDIVIDUAL:
574
+ result = await self.individual_executor.execute_strategy_individual(
575
+ strategy,
576
+ )
577
+ return result.hook_results
578
+ results = self.batch_executor.execute_strategy(strategy)
579
+ return results.results
580
+
581
+ async def _trigger_autofix_for_fast_hooks(
582
+ self,
583
+ failed_results: list[HookResult],
584
+ ) -> None:
585
+ self.console.print(
586
+ "[magenta]🤖 Starting AI autofix cycle for fast hooks...[/ magenta]",
587
+ )
588
+
589
+ mock_test_results = {
590
+ "success": True,
591
+ "failed_tests": [],
592
+ "individual_tests": [],
593
+ }
594
+
595
+ from .execution_strategies import ExecutionPlan, ExecutionStrategy
596
+
597
+ mock_plan = ExecutionPlan(
598
+ config=self.config,
599
+ execution_strategy=ExecutionStrategy.BATCH,
600
+ hook_plans=[],
601
+ test_plan={"mode": "full_suite", "estimated_duration": 0},
602
+ ai_plan={
603
+ "mode": self.config.ai_coordination_mode,
604
+ "intelligence_level": self.config.ai_intelligence,
605
+ "batch_processing": True,
606
+ "correlation_tracking": self.config.correlation_tracking,
607
+ "failure_analysis": self.config.failure_analysis,
608
+ "adaptive_retry": self.config.intelligent_retry,
609
+ },
610
+ estimated_total_duration=0,
611
+ )
612
+
613
+ ai_fixes = await self._execute_ai_phase(
614
+ mock_plan,
615
+ failed_results,
616
+ mock_test_results,
617
+ )
618
+
619
+ if ai_fixes:
620
+ self.console.print(
621
+ f"[green]✅ Applied {len(ai_fixes)} AI fixes for fast hooks[/ green]",
622
+ )
623
+ else:
624
+ self.console.print("[yellow]⚠️ No AI fixes could be applied[/ yellow]")
625
+
626
+ async def _execute_tests_phase(
627
+ self,
628
+ plan: ExecutionPlan,
629
+ context: ExecutionContext,
630
+ ) -> dict[str, t.Any]:
631
+ self.progress_streamer.update_stage("tests", "starting")
632
+
633
+ test_mode = plan.test_plan.get("mode", "full_suite")
634
+
635
+ if test_mode in ("individual_with_progress", "selective"):
636
+ test_results = await self.test_streamer.run_tests_with_streaming(
637
+ context.options,
638
+ test_mode,
639
+ )
640
+
641
+ job_id = (
642
+ getattr(self.session, "job_id", None)
643
+ or f"orchestration_{int(time.time())}"
644
+ )
645
+ individual_tests = test_results.get("individual_tests", [])
646
+
647
+ for test in individual_tests:
648
+ self.metrics.record_individual_test(
649
+ job_id=job_id,
650
+ test_id=test.test_id,
651
+ test_file=test.test_file,
652
+ test_class=test.test_class,
653
+ test_method=test.test_method,
654
+ status=test.status,
655
+ execution_time_ms=int((test.duration or 0) * 1000),
656
+ error_message=test.error_message,
657
+ error_traceback=test.failure_traceback,
658
+ )
659
+ else:
660
+ test_success = self.test_manager.run_tests(context.options)
661
+ test_results = {
662
+ "success": test_success,
663
+ "failed_tests": [],
664
+ "suite_progress": None,
665
+ "individual_tests": [],
666
+ }
667
+
668
+ self.progress_streamer.update_stage("tests", "completed")
669
+ return test_results
670
+
671
+ def _update_test_suite_progress(self, suite_progress: TestSuiteProgress) -> None:
672
+ current_test = suite_progress.current_test or "running tests"
673
+ self.progress_streamer.update_stage(
674
+ "tests",
675
+ f"{suite_progress.completed_tests} / {suite_progress.total_tests}-{current_test}",
676
+ )
677
+
678
+ async def _execute_ai_phase(
679
+ self,
680
+ plan: ExecutionPlan,
681
+ hook_results: list[HookResult],
682
+ test_results: dict[str, t.Any],
683
+ ) -> list[str]:
684
+ self.progress_streamer.update_stage("ai_analysis", "analyzing_failures")
685
+
686
+ failed_hooks = [r for r in hook_results if r.status == "failed"]
687
+ failed_tests = test_results.get("failed_tests", [])
688
+
689
+ individual_tests = test_results.get("individual_tests", [])
690
+ failed_individual_tests = [t for t in individual_tests if t.status == "failed"]
691
+
692
+ correlation_data = self.correlation_tracker.get_correlation_data()
693
+
694
+ self.console.print("\n[bold magenta]🤖 AI ANALYSIS PHASE[/ bold magenta]")
695
+ self.console.print(f"AI Mode: {self.config.ai_coordination_mode.value}")
696
+ self.console.print(f"Failed hooks: {len(failed_hooks)}")
697
+ self.console.print(f"Failed tests: {len(failed_tests)}")
698
+
699
+ if failed_individual_tests:
700
+ self.console.print(
701
+ f"Individual test failures: {len(failed_individual_tests)}",
702
+ )
703
+ for test in failed_individual_tests[:3]:
704
+ self.console.print(f" ❌ {test.test_id}")
705
+
706
+ if correlation_data["problematic_hooks"]:
707
+ self.console.print(
708
+ f"Problematic hooks (recurring): {', '.join(correlation_data['problematic_hooks'])}",
709
+ )
710
+
711
+ if self.agent_coordinator and self.config.ai_coordination_mode in (
712
+ AICoordinationMode.MULTI_AGENT,
713
+ AICoordinationMode.COORDINATOR,
714
+ ):
715
+ ai_fixes = await self._execute_multi_agent_analysis(
716
+ failed_hooks,
717
+ failed_tests,
718
+ failed_individual_tests,
719
+ correlation_data,
720
+ )
721
+ else:
722
+ ai_fixes = await self._execute_single_agent_analysis(
723
+ failed_hooks,
724
+ failed_tests,
725
+ failed_individual_tests,
726
+ correlation_data,
727
+ )
728
+
729
+ self.progress_streamer.update_stage("ai_analysis", "completed")
730
+ return ai_fixes
731
+
732
+ async def _execute_multi_agent_analysis(
733
+ self,
734
+ failed_hooks: list[HookResult],
735
+ failed_tests: list[str],
736
+ failed_individual_tests: list[t.Any],
737
+ correlation_data: dict[str, t.Any],
738
+ ) -> list[str]:
739
+ self.console.print("[bold cyan]🤖 Multi-Agent Analysis Started[/ bold cyan]")
740
+
741
+ issues = []
742
+
743
+ for hook_result in failed_hooks:
744
+ issue_type = self._map_hook_to_issue_type(hook_result.name)
745
+ issue = Issue(
746
+ id=f"hook_{hook_result.name}_{hash(str(hook_result.issues_found))}",
747
+ type=issue_type,
748
+ severity=Priority.HIGH
749
+ if hook_result.name in correlation_data.get("problematic_hooks", [])
750
+ else Priority.MEDIUM,
751
+ message=(
752
+ hook_result.issues_found[0]
753
+ if hook_result.issues_found
754
+ else f"{hook_result.name} failed"
755
+ ),
756
+ stage="hooks",
757
+ details=getattr(hook_result, "error_details", []),
758
+ )
759
+ issues.append(issue)
760
+
761
+ for test_failure in failed_individual_tests:
762
+ issue = Issue(
763
+ id=f"test_{test_failure.test_id}",
764
+ type=IssueType.TEST_FAILURE,
765
+ severity=Priority.HIGH,
766
+ message=test_failure.error_message
767
+ or f"Test failed: {test_failure.test_id}",
768
+ file_path=getattr(test_failure, "test_file", None),
769
+ stage="tests",
770
+ details=[test_failure.failure_traceback]
771
+ if hasattr(test_failure, "failure_traceback")
772
+ else [],
773
+ )
774
+ issues.append(issue)
775
+
776
+ if not issues:
777
+ return ["No issues identified for multi-agent analysis"]
778
+
779
+ self.console.print(
780
+ f"[cyan]Processing {len(issues)} issues with specialized agents...[/ cyan]",
781
+ )
782
+
783
+ assert self.agent_coordinator is not None
784
+
785
+ result = await self.agent_coordinator.handle_issues_proactively(issues)
786
+
787
+ ai_fixes = []
788
+ if result.fixes_applied:
789
+ ai_fixes.extend(result.fixes_applied)
790
+ else:
791
+ ai_fixes.append(
792
+ f"Multi-agent analysis completed with {result.confidence: .2f} confidence",
793
+ )
794
+
795
+ if result.remaining_issues:
796
+ ai_fixes.append(f"Remaining issues: {len(result.remaining_issues)}")
797
+
798
+ if result.recommendations:
799
+ ai_fixes.extend(
800
+ [f"Recommendation: {rec}" for rec in result.recommendations[:3]],
801
+ )
802
+
803
+ self.console.print(
804
+ f"[green]✅ Multi-agent analysis completed: {len(result.fixes_applied)} fixes applied[/ green]",
805
+ )
806
+ return ai_fixes
807
+
808
+ async def _execute_single_agent_analysis(
809
+ self,
810
+ failed_hooks: list[HookResult],
811
+ failed_tests: list[str],
812
+ failed_individual_tests: list[t.Any],
813
+ correlation_data: dict[str, t.Any],
814
+ ) -> list[str]:
815
+ return [
816
+ f"[Single Agent] Analyzed {len(failed_hooks)} hook failures",
817
+ f"[Single Agent] Analyzed {len(failed_tests)} test failures",
818
+ f"[Single Agent] Analyzed {len(failed_individual_tests)} individual test failures",
819
+ "[Single Agent] Applied batch fixes based on correlation analysis",
820
+ ]
821
+
822
+ def _map_hook_to_issue_type(self, hook_name: str) -> IssueType:
823
+ hook_type_mapping = {
824
+ "ruff-format": IssueType.FORMATTING,
825
+ "ruff-check": IssueType.FORMATTING,
826
+ "pyright": IssueType.TYPE_ERROR,
827
+ "bandit": IssueType.SECURITY,
828
+ "vulture": IssueType.DEAD_CODE,
829
+ "refurb": IssueType.COMPLEXITY,
830
+ "creosote": IssueType.DEPENDENCY,
831
+ "gitleaks": IssueType.SECURITY,
832
+ "trailing-whitespace": IssueType.FORMATTING,
833
+ "end-of-file-fixer": IssueType.FORMATTING,
834
+ }
835
+
836
+ return hook_type_mapping.get(hook_name) or IssueType.FORMATTING
837
+
838
+ def _adapt_execution_plan(
839
+ self,
840
+ current_plan: ExecutionPlan,
841
+ context: ExecutionContext,
842
+ ) -> ExecutionPlan:
843
+ problematic_hooks = self.correlation_tracker.get_problematic_hooks()
844
+
845
+ if problematic_hooks:
846
+ self.console.print(
847
+ f"[yellow]🧠 Adapting strategy due to recurring failures in: {', '.join(problematic_hooks)}[/ yellow]",
848
+ )
849
+
850
+ if current_plan.execution_strategy == ExecutionStrategy.BATCH:
851
+ self.config.execution_strategy = ExecutionStrategy.INDIVIDUAL
852
+ self.console.print(
853
+ "[cyan]📋 Switching to individual execution for better debugging[/ cyan]",
854
+ )
855
+
856
+ hook_strategies = [
857
+ self.hook_config_loader.load_strategy("fast"),
858
+ self.hook_config_loader.load_strategy("comprehensive"),
859
+ ]
860
+
861
+ return self.planner.create_execution_plan(self.config, context, hook_strategies)
862
+
863
+ def _print_final_analysis(self) -> None:
864
+ correlation_data = self.correlation_tracker.get_correlation_data()
865
+
866
+ if correlation_data["iteration_count"] == 0:
867
+ return
868
+
869
+ self.console.print("\n" + "=" * 80)
870
+ self.console.print(
871
+ "[bold bright_magenta]🔍 CORRELATION ANALYSIS[/ bold bright_magenta]",
872
+ )
873
+ self.console.print("=" * 80)
874
+
875
+ self.console.print(f"Total iterations: {correlation_data['iteration_count']}")
876
+
877
+ if correlation_data["problematic_hooks"]:
878
+ self.console.print(
879
+ "\n[bold red]Problematic hooks (recurring failures): [/ bold red]",
880
+ )
881
+ for hook in correlation_data["problematic_hooks"]:
882
+ failures = correlation_data["failure_patterns"][hook]
883
+ self.console.print(f" ❌ {hook}-failed in {len(failures)} iterations")
884
+
885
+ if correlation_data["recent_trends"]:
886
+ self.console.print("\n[bold yellow]Recent trends: [/ bold yellow]")
887
+ for trend in correlation_data["recent_trends"][-2:]:
888
+ failed_count = len(trend["failed_hooks"])
889
+ self.console.print(
890
+ f" Iteration {trend['iteration']}: {failed_count} failed hooks, "
891
+ f"{trend['total_errors']} total errors",
892
+ )
893
+
894
+ self.console.print("=" * 80)