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,1158 @@
1
+ """Phase execution orchestration for workflow pipeline.
2
+
3
+ Executes individual workflow phases (config, quality, tests, hooks, publishing, commit).
4
+ Handles LSP configuration and integration with Zuban type checking server.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import subprocess
11
+ import sys
12
+ import typing as t
13
+ from contextlib import suppress
14
+ from pathlib import Path
15
+
16
+ from acb.console import Console
17
+ from acb.depends import Inject, depends
18
+
19
+ from crackerjack.agents.base import AgentContext
20
+ from crackerjack.events import WorkflowEvent, WorkflowEventBus
21
+ from crackerjack.models.protocols import (
22
+ DebugServiceProtocol,
23
+ LoggerProtocol,
24
+ OptionsProtocol,
25
+ QualityIntelligenceProtocol,
26
+ )
27
+ from crackerjack.services.monitoring.performance_monitor import phase_monitor
28
+
29
+
30
+ class WorkflowPhaseExecutor:
31
+ """Executes individual workflow phases and manages LSP configuration.
32
+
33
+ This class handles:
34
+ - Phase execution (config, quality, testing, hooks, publishing, commit)
35
+ - LSP server lifecycle (initialization, configuration, cleanup)
36
+ - AI-assisted fixing workflows
37
+ - Phase monitoring and status tracking
38
+ """
39
+
40
+ @depends.inject
41
+ def __init__(
42
+ self,
43
+ console: Inject[Console],
44
+ logger: Inject[LoggerProtocol],
45
+ pkg_path: Path,
46
+ debugger: Inject[DebugServiceProtocol],
47
+ quality_intelligence: Inject[QualityIntelligenceProtocol] | None = None,
48
+ ) -> None:
49
+ """Initialize phase executor.
50
+
51
+ Args:
52
+ console: Console for user output
53
+ logger: Structured logger
54
+ pkg_path: Project root path
55
+ debugger: Debug service for workflow tracking
56
+ quality_intelligence: Optional quality intelligence service
57
+ """
58
+ self.console = console
59
+ self.logger = logger
60
+ self.pkg_path = pkg_path
61
+ self.debugger = debugger
62
+ self._quality_intelligence = quality_intelligence
63
+ self._mcp_state_manager: t.Any = None
64
+ self._last_security_audit: t.Any = None
65
+ self._code_cleaning_complete = False
66
+
67
+ # These will be injected by orchestrator
68
+ self.session: t.Any = None
69
+ self.phases: t.Any = None
70
+ self._event_bus: WorkflowEventBus | None = None
71
+
72
+ def configure(
73
+ self, session: t.Any, phases: t.Any, event_bus: WorkflowEventBus | None = None
74
+ ) -> None:
75
+ """Configure executor with required dependencies.
76
+
77
+ Args:
78
+ session: Session coordinator
79
+ phases: Phase coordinator
80
+ event_bus: Optional event bus for workflow events
81
+ """
82
+ self.session = session
83
+ self.phases = phases
84
+ self._event_bus = event_bus
85
+
86
+ # =============================================================================
87
+ # LSP CONFIGURATION METHODS (8 methods)
88
+ # =============================================================================
89
+
90
+ def _configure_session_cleanup(self, options: OptionsProtocol) -> None:
91
+ """Configure session cleanup behavior."""
92
+ if hasattr(options, "cleanup"):
93
+ self.session.set_cleanup_config(options.cleanup)
94
+
95
+ def _initialize_zuban_lsp(self, options: OptionsProtocol) -> None:
96
+ """Initialize Zuban LSP server if not disabled."""
97
+ if self._should_skip_zuban_lsp(options):
98
+ return
99
+
100
+ if self._is_zuban_lsp_already_running():
101
+ return
102
+
103
+ self._start_zuban_lsp_server(options)
104
+
105
+ def _should_skip_zuban_lsp(self, options: OptionsProtocol) -> bool:
106
+ """Check if Zuban LSP server should be skipped."""
107
+ if getattr(options, "no_zuban_lsp", False):
108
+ self.logger.debug("Zuban LSP server disabled by --no-zuban-lsp flag")
109
+ return True
110
+
111
+ config = getattr(options, "zuban_lsp", None)
112
+ if config and not config.enabled:
113
+ self.logger.debug("Zuban LSP server disabled in configuration")
114
+ return True
115
+
116
+ if config and not config.auto_start:
117
+ self.logger.debug("Zuban LSP server auto-start disabled in configuration")
118
+ return True
119
+
120
+ return False
121
+
122
+ def _is_zuban_lsp_already_running(self) -> bool:
123
+ """Check if LSP server is already running to avoid duplicates."""
124
+ from crackerjack.services.server_manager import find_zuban_lsp_processes
125
+
126
+ existing_processes = find_zuban_lsp_processes()
127
+ if existing_processes:
128
+ self.logger.debug(
129
+ f"Zuban LSP server already running (PID: {existing_processes[0]['pid']})"
130
+ )
131
+ return True
132
+ return False
133
+
134
+ def _start_zuban_lsp_server(self, options: OptionsProtocol) -> None:
135
+ """Start the Zuban LSP server in background."""
136
+ try:
137
+ config = getattr(options, "zuban_lsp", None)
138
+ zuban_lsp_port, zuban_lsp_mode = self._get_zuban_lsp_config(options, config)
139
+
140
+ cmd = [
141
+ sys.executable,
142
+ "-m",
143
+ "crackerjack",
144
+ "--start-zuban-lsp",
145
+ "--zuban-lsp-port",
146
+ str(zuban_lsp_port),
147
+ "--zuban-lsp-mode",
148
+ zuban_lsp_mode,
149
+ ]
150
+
151
+ subprocess.Popen(
152
+ cmd,
153
+ stdout=subprocess.DEVNULL,
154
+ stderr=subprocess.DEVNULL,
155
+ start_new_session=True,
156
+ )
157
+
158
+ self.logger.info(
159
+ f"Auto-started Zuban LSP server on port {zuban_lsp_port} ({zuban_lsp_mode} mode)"
160
+ )
161
+
162
+ except Exception as e:
163
+ self.logger.warning(f"Failed to auto-start Zuban LSP server: {e}")
164
+
165
+ def _get_zuban_lsp_config(
166
+ self, options: OptionsProtocol, config: t.Any
167
+ ) -> tuple[int, str]:
168
+ """Get Zuban LSP configuration values."""
169
+ if config:
170
+ return config.port, config.mode
171
+ return (
172
+ getattr(options, "zuban_lsp_port", 8677),
173
+ getattr(options, "zuban_lsp_mode", "stdio"),
174
+ )
175
+
176
+ def _configure_hook_manager_lsp(self, options: OptionsProtocol) -> None:
177
+ """Configure hook manager with LSP optimization settings."""
178
+ # Check if LSP hooks are enabled
179
+ enable_lsp_hooks = getattr(options, "enable_lsp_hooks", False)
180
+
181
+ # Configure the hook manager
182
+ hook_manager = self.phases.hook_manager
183
+ if hasattr(hook_manager, "configure_lsp_optimization"):
184
+ hook_manager.configure_lsp_optimization(enable_lsp_hooks)
185
+
186
+ if enable_lsp_hooks and not getattr(options, "no_zuban_lsp", False):
187
+ self.console.print(
188
+ "🔍 LSP-optimized hook execution enabled for faster type checking",
189
+ style="blue",
190
+ )
191
+
192
+ def _register_lsp_cleanup_handler(self, options: OptionsProtocol) -> None:
193
+ """Register cleanup handler to stop LSP server when workflow completes."""
194
+ # Get configuration to check if we should handle LSP cleanup
195
+ config = getattr(options, "zuban_lsp", None)
196
+ if config and not config.enabled:
197
+ return
198
+
199
+ if getattr(options, "no_zuban_lsp", False):
200
+ return
201
+
202
+ def cleanup_lsp_server() -> None:
203
+ """Cleanup function to gracefully stop LSP server if it was auto-started."""
204
+ try:
205
+ from crackerjack.services.server_manager import (
206
+ find_zuban_lsp_processes,
207
+ stop_process,
208
+ )
209
+
210
+ lsp_processes = find_zuban_lsp_processes()
211
+ if lsp_processes:
212
+ for proc in lsp_processes:
213
+ self.logger.debug(
214
+ f"Stopping auto-started Zuban LSP server (PID: {proc['pid']})"
215
+ )
216
+ stop_process(proc["pid"])
217
+
218
+ except Exception as e:
219
+ self.logger.debug(f"Error during LSP cleanup: {e}")
220
+
221
+ # Register the cleanup handler with the session
222
+ self.session.register_cleanup(cleanup_lsp_server)
223
+
224
+ # =============================================================================
225
+ # PHASE EXECUTION METHODS (~51 methods)
226
+ # =============================================================================
227
+
228
+ async def _execute_workflow_phases(
229
+ self, options: OptionsProtocol, workflow_id: str
230
+ ) -> bool:
231
+ """Execute all workflow phases in order.
232
+
233
+ Args:
234
+ options: Workflow options
235
+ workflow_id: Unique workflow identifier
236
+
237
+ Returns:
238
+ True if all phases succeeded, False otherwise
239
+ """
240
+ # Execute configuration phase
241
+ config_success, success = await self._execute_config_phase(options, workflow_id)
242
+
243
+ # Execute quality phase
244
+ (
245
+ quality_success,
246
+ quality_phase_status,
247
+ ) = await self._execute_quality_phase_with_events(options, workflow_id)
248
+ success = success and quality_phase_status
249
+
250
+ # If quality phase failed and we're in publishing mode, stop here
251
+ if not quality_success and self._is_publishing_workflow(options):
252
+ return False
253
+
254
+ # Execute publishing workflow if requested
255
+ (
256
+ publish_requested,
257
+ publishing_success,
258
+ ) = await self._execute_publishing_if_requested(options, workflow_id)
259
+ if not publishing_success:
260
+ success = False
261
+
262
+ # Execute commit workflow independently if requested
263
+ commit_requested, commit_success = await self._execute_commit_if_requested(
264
+ options, workflow_id
265
+ )
266
+ if not commit_success:
267
+ success = False
268
+
269
+ # Only fail the overall workflow if publishing was explicitly requested and failed
270
+ if self._should_fail_on_publish_failure(publishing_success, options):
271
+ self.console.print(
272
+ "[red]❌ Publishing failed - overall workflow marked as failed[/red]"
273
+ )
274
+ return False
275
+
276
+ return success
277
+
278
+ async def _execute_config_phase(
279
+ self, options: OptionsProtocol, workflow_id: str
280
+ ) -> tuple[bool, bool]:
281
+ """Execute the configuration phase and return success status and overall status."""
282
+ await self._publish_event(
283
+ WorkflowEvent.CONFIG_PHASE_STARTED,
284
+ {"workflow_id": workflow_id},
285
+ )
286
+
287
+ with phase_monitor(workflow_id, "configuration"):
288
+ config_success = self.phases.run_configuration_phase(options)
289
+ success = config_success
290
+
291
+ await self._publish_event(
292
+ WorkflowEvent.CONFIG_PHASE_COMPLETED,
293
+ {"workflow_id": workflow_id, "success": config_success},
294
+ )
295
+
296
+ return config_success, success
297
+
298
+ async def _execute_quality_phase_with_events(
299
+ self, options: OptionsProtocol, workflow_id: str
300
+ ) -> tuple[bool, bool]:
301
+ """Execute the quality phase with events and return success and combined status."""
302
+ await self._publish_event(
303
+ WorkflowEvent.QUALITY_PHASE_STARTED,
304
+ {"workflow_id": workflow_id},
305
+ )
306
+ quality_success = await self._execute_quality_phase(options, workflow_id)
307
+ success = quality_success
308
+
309
+ await self._publish_event(
310
+ WorkflowEvent.QUALITY_PHASE_COMPLETED,
311
+ {"workflow_id": workflow_id, "success": quality_success},
312
+ )
313
+
314
+ return quality_success, success
315
+
316
+ async def _execute_quality_phase(
317
+ self, options: OptionsProtocol, workflow_id: str
318
+ ) -> bool:
319
+ """Execute the quality phase based on options."""
320
+ # Use quality intelligence to make informed decisions about quality phase
321
+ if self._quality_intelligence:
322
+ quality_decision = await self._make_quality_intelligence_decision(options)
323
+ self.console.print(
324
+ f"[dim]🧠 Quality Intelligence: {quality_decision}[/dim]"
325
+ )
326
+
327
+ if hasattr(options, "fast") and options.fast:
328
+ return await self._run_fast_hooks_phase_monitored(options, workflow_id)
329
+ if hasattr(options, "fast_iteration") and options.fast_iteration:
330
+ return await self._run_fast_hooks_phase_monitored(options, workflow_id)
331
+ if hasattr(options, "comp") and options.comp:
332
+ return await self._run_comprehensive_hooks_phase_monitored(
333
+ options, workflow_id
334
+ )
335
+ if getattr(options, "test", False):
336
+ return await self._execute_test_workflow(options, workflow_id)
337
+ return await self._execute_standard_hooks_workflow_monitored(
338
+ options, workflow_id
339
+ )
340
+
341
+ async def _execute_test_workflow(
342
+ self, options: OptionsProtocol, workflow_id: str
343
+ ) -> bool:
344
+ """Execute test workflow with optional AI fixing."""
345
+ iteration = self._start_iteration_tracking(options)
346
+
347
+ if not await self._execute_initial_phases(options, workflow_id, iteration):
348
+ return False
349
+
350
+ (
351
+ testing_passed,
352
+ comprehensive_passed,
353
+ ) = await self._run_main_quality_phases_async(options, workflow_id)
354
+
355
+ return await self._handle_ai_workflow_completion(
356
+ options, iteration, testing_passed, comprehensive_passed, workflow_id
357
+ )
358
+
359
+ async def _execute_initial_phases(
360
+ self, options: OptionsProtocol, workflow_id: str, iteration: int
361
+ ) -> bool:
362
+ """Execute initial fast hooks phase."""
363
+ with phase_monitor(workflow_id, "fast_hooks") as monitor:
364
+ if not await self._run_initial_fast_hooks_async(
365
+ options, iteration, monitor
366
+ ):
367
+ return False
368
+
369
+ return self._execute_optional_cleaning_phase(options)
370
+
371
+ def _execute_optional_cleaning_phase(self, options: OptionsProtocol) -> bool:
372
+ """Execute code cleaning phase if requested."""
373
+ if not getattr(options, "clean", False):
374
+ return True
375
+
376
+ if not self._run_code_cleaning_phase(options):
377
+ return False
378
+
379
+ if not self._run_post_cleaning_fast_hooks(options):
380
+ return False
381
+
382
+ self._mark_code_cleaning_complete()
383
+ return True
384
+
385
+ async def _execute_publishing_if_requested(
386
+ self, options: OptionsProtocol, workflow_id: str
387
+ ) -> tuple[bool, bool]:
388
+ """Execute publishing phase if requested."""
389
+ publish_requested = bool(
390
+ getattr(options, "publish", False) or getattr(options, "all", False)
391
+ )
392
+
393
+ if publish_requested:
394
+ await self._publish_event(
395
+ WorkflowEvent.PUBLISH_PHASE_STARTED,
396
+ {"workflow_id": workflow_id},
397
+ )
398
+
399
+ publishing_success = await self._execute_publishing_workflow(
400
+ options, workflow_id
401
+ )
402
+
403
+ if publish_requested:
404
+ await self._publish_event(
405
+ WorkflowEvent.PUBLISH_PHASE_COMPLETED,
406
+ {
407
+ "workflow_id": workflow_id,
408
+ "success": publishing_success,
409
+ },
410
+ )
411
+
412
+ return publish_requested, publishing_success
413
+
414
+ async def _execute_commit_if_requested(
415
+ self, options: OptionsProtocol, workflow_id: str
416
+ ) -> tuple[bool, bool]:
417
+ """Execute commit phase if requested."""
418
+ commit_requested = bool(getattr(options, "commit", False))
419
+
420
+ if commit_requested:
421
+ await self._publish_event(
422
+ WorkflowEvent.COMMIT_PHASE_STARTED,
423
+ {"workflow_id": workflow_id},
424
+ )
425
+
426
+ commit_success = await self._execute_commit_workflow(options, workflow_id)
427
+
428
+ if commit_requested:
429
+ await self._publish_event(
430
+ WorkflowEvent.COMMIT_PHASE_COMPLETED,
431
+ {
432
+ "workflow_id": workflow_id,
433
+ "success": commit_success,
434
+ },
435
+ )
436
+
437
+ return commit_requested, commit_success
438
+
439
+ async def _execute_publishing_workflow(
440
+ self, options: OptionsProtocol, workflow_id: str
441
+ ) -> bool:
442
+ """Execute publishing workflow."""
443
+ if not options.publish and not options.all:
444
+ return True
445
+
446
+ with phase_monitor(workflow_id, "publishing"):
447
+ if not self.phases.run_publishing_phase(options):
448
+ self.session.fail_task("workflow", "Publishing failed")
449
+ return False
450
+ return True
451
+
452
+ async def _execute_commit_workflow(
453
+ self, options: OptionsProtocol, workflow_id: str
454
+ ) -> bool:
455
+ """Execute commit workflow."""
456
+ if not options.commit:
457
+ return True
458
+
459
+ with phase_monitor(workflow_id, "commit"):
460
+ if not self.phases.run_commit_phase(options):
461
+ return False
462
+ return True
463
+
464
+ def _is_publishing_workflow(self, options: OptionsProtocol) -> bool:
465
+ """Check if this is a publishing workflow."""
466
+ return bool(
467
+ getattr(options, "publish", False) or getattr(options, "all", False)
468
+ )
469
+
470
+ def _should_fail_on_publish_failure(
471
+ self, publishing_success: bool, options: OptionsProtocol
472
+ ) -> bool:
473
+ """Check if the overall workflow should fail due to publishing failure."""
474
+ return not publishing_success and (
475
+ getattr(options, "publish", False) or getattr(options, "all", False)
476
+ )
477
+
478
+ # Phase execution helpers
479
+
480
+ def _start_iteration_tracking(self, options: OptionsProtocol) -> int:
481
+ """Start tracking iteration for AI workflows."""
482
+ iteration = 1
483
+ if options.ai_agent and self._should_debug():
484
+ self.debugger.log_iteration_start(iteration)
485
+ return iteration
486
+
487
+ async def _run_main_quality_phases_async(
488
+ self, options: OptionsProtocol, workflow_id: str
489
+ ) -> tuple[bool, bool]:
490
+ """Run testing and comprehensive hooks phases in parallel."""
491
+ testing_task = asyncio.create_task(
492
+ self._run_testing_phase_async(options, workflow_id)
493
+ )
494
+ comprehensive_task = asyncio.create_task(
495
+ self._run_comprehensive_hooks_phase_monitored(options, workflow_id)
496
+ )
497
+
498
+ results = await asyncio.gather(
499
+ testing_task, comprehensive_task, return_exceptions=True
500
+ )
501
+
502
+ testing_result, comprehensive_result = results
503
+
504
+ if isinstance(testing_result, Exception):
505
+ self.logger.error(f"Testing phase failed with exception: {testing_result}")
506
+ testing_passed = False
507
+ else:
508
+ testing_passed = bool(testing_result)
509
+
510
+ if isinstance(comprehensive_result, Exception):
511
+ self.logger.error(
512
+ f"Comprehensive hooks failed with exception: {comprehensive_result}"
513
+ )
514
+ comprehensive_passed = False
515
+ else:
516
+ comprehensive_passed = bool(comprehensive_result)
517
+
518
+ return testing_passed, comprehensive_passed
519
+
520
+ async def _handle_ai_workflow_completion(
521
+ self,
522
+ options: OptionsProtocol,
523
+ iteration: int,
524
+ testing_passed: bool,
525
+ comprehensive_passed: bool,
526
+ workflow_id: str = "unknown",
527
+ ) -> bool:
528
+ """Handle workflow completion with optional AI fixing."""
529
+ if options.ai_agent:
530
+ return await self._handle_ai_agent_workflow(
531
+ options, iteration, testing_passed, comprehensive_passed, workflow_id
532
+ )
533
+
534
+ return await self._handle_standard_workflow(
535
+ options, iteration, testing_passed, comprehensive_passed
536
+ )
537
+
538
+ async def _handle_ai_agent_workflow(
539
+ self,
540
+ options: OptionsProtocol,
541
+ iteration: int,
542
+ testing_passed: bool,
543
+ comprehensive_passed: bool,
544
+ workflow_id: str = "unknown",
545
+ ) -> bool:
546
+ """Handle workflow with AI agent enabled."""
547
+ # Import security gates methods from workflow_security_gates
548
+ from .workflow_security_gates import WorkflowSecurityGates
549
+
550
+ security_gates = WorkflowSecurityGates(
551
+ console=self.console,
552
+ logger=self.logger,
553
+ session=self.session,
554
+ debugger=self.debugger,
555
+ )
556
+ security_gates.configure(self.phases, self._execute_ai_fixing_workflow)
557
+
558
+ if not await security_gates.process_security_gates(options):
559
+ return False
560
+
561
+ needs_ai_fixing = self._determine_ai_fixing_needed(
562
+ testing_passed, comprehensive_passed, bool(options.publish or options.all)
563
+ )
564
+
565
+ if needs_ai_fixing:
566
+ return await self._execute_ai_fixing_workflow(options, iteration)
567
+
568
+ return self._finalize_ai_workflow_success(
569
+ options, iteration, testing_passed, comprehensive_passed
570
+ )
571
+
572
+ async def _execute_ai_fixing_workflow(
573
+ self, options: OptionsProtocol, iteration: int
574
+ ) -> bool:
575
+ """Execute AI fixing workflow."""
576
+ # Import AI coordinator methods from workflow_ai_coordinator
577
+ from .workflow_ai_coordinator import WorkflowAICoordinator
578
+
579
+ ai_coordinator = WorkflowAICoordinator(
580
+ console=self.console,
581
+ logger=self.logger,
582
+ pkg_path=self.pkg_path,
583
+ debugger=self.debugger,
584
+ )
585
+ ai_coordinator.configure(self.session, self.phases, self._mcp_state_manager)
586
+
587
+ success = await ai_coordinator.run_ai_agent_fixing_phase(options)
588
+ if self._should_debug():
589
+ self.debugger.log_iteration_end(iteration, success)
590
+ return success
591
+
592
+ def _finalize_ai_workflow_success(
593
+ self,
594
+ options: OptionsProtocol,
595
+ iteration: int,
596
+ testing_passed: bool,
597
+ comprehensive_passed: bool,
598
+ ) -> bool:
599
+ """Finalize AI workflow when no fixing is needed."""
600
+ publishing_requested = bool(options.publish or options.all)
601
+
602
+ final_success = self._determine_workflow_success(
603
+ testing_passed, comprehensive_passed, publishing_requested
604
+ )
605
+
606
+ self._show_partial_success_warning_if_needed(
607
+ publishing_requested, final_success, testing_passed, comprehensive_passed
608
+ )
609
+
610
+ if self._should_debug():
611
+ self.debugger.log_iteration_end(iteration, final_success)
612
+
613
+ return final_success
614
+
615
+ def _show_partial_success_warning_if_needed(
616
+ self,
617
+ publishing_requested: bool,
618
+ final_success: bool,
619
+ testing_passed: bool,
620
+ comprehensive_passed: bool,
621
+ ) -> None:
622
+ """Show warning if workflow succeeded with partial quality."""
623
+ should_show_warning = (
624
+ publishing_requested
625
+ and final_success
626
+ and not (testing_passed and comprehensive_passed)
627
+ )
628
+
629
+ if should_show_warning:
630
+ self._show_security_audit_warning()
631
+
632
+ async def _handle_standard_workflow(
633
+ self,
634
+ options: OptionsProtocol,
635
+ iteration: int,
636
+ testing_passed: bool,
637
+ comprehensive_passed: bool,
638
+ ) -> bool:
639
+ """Handle standard workflow without AI agent."""
640
+ # Import security gates methods
641
+ from .workflow_security_gates import WorkflowSecurityGates
642
+
643
+ security_gates = WorkflowSecurityGates(
644
+ console=self.console,
645
+ logger=self.logger,
646
+ session=self.session,
647
+ debugger=self.debugger,
648
+ )
649
+ security_gates.configure(self.phases, None)
650
+
651
+ (
652
+ publishing_requested,
653
+ security_blocks,
654
+ ) = await security_gates.check_security_gates_for_publishing(options)
655
+
656
+ if publishing_requested and security_blocks:
657
+ return await security_gates.handle_security_gate_failure(options)
658
+
659
+ success = self._determine_workflow_success(
660
+ testing_passed,
661
+ comprehensive_passed,
662
+ publishing_requested,
663
+ )
664
+
665
+ if (
666
+ publishing_requested
667
+ and success
668
+ and not (testing_passed and comprehensive_passed)
669
+ ):
670
+ self._show_security_audit_warning()
671
+ elif publishing_requested and not success:
672
+ self.console.print(
673
+ "[red]❌ Quality checks failed - cannot proceed to publishing[/red]"
674
+ )
675
+
676
+ if not success and getattr(options, "verbose", False):
677
+ self._show_verbose_failure_details(testing_passed, comprehensive_passed)
678
+
679
+ if options.ai_agent and self._should_debug():
680
+ self.debugger.log_iteration_end(iteration, success)
681
+ return success
682
+
683
+ def _determine_workflow_success(
684
+ self,
685
+ testing_passed: bool,
686
+ comprehensive_passed: bool,
687
+ publishing_requested: bool,
688
+ ) -> bool:
689
+ """Determine overall workflow success."""
690
+ if publishing_requested:
691
+ return testing_passed and comprehensive_passed
692
+
693
+ return testing_passed and comprehensive_passed
694
+
695
+ def _show_verbose_failure_details(
696
+ self, testing_passed: bool, comprehensive_passed: bool
697
+ ) -> None:
698
+ """Show detailed failure information in verbose mode."""
699
+ self.console.print(
700
+ f"[yellow]⚠️ Quality phase results - testing_passed: {testing_passed}, comprehensive_passed: {comprehensive_passed}[/yellow]"
701
+ )
702
+ if not testing_passed:
703
+ self.console.print("[yellow] → Tests reported failure[/yellow]")
704
+ if not comprehensive_passed:
705
+ self.console.print(
706
+ "[yellow] → Comprehensive hooks reported failure[/yellow]"
707
+ )
708
+
709
+ def _determine_ai_fixing_needed(
710
+ self,
711
+ testing_passed: bool,
712
+ comprehensive_passed: bool,
713
+ publishing_requested: bool,
714
+ ) -> bool:
715
+ """Determine if AI fixing is needed."""
716
+ if publishing_requested:
717
+ return not testing_passed or not comprehensive_passed
718
+
719
+ return not testing_passed or not comprehensive_passed
720
+
721
+ def _show_security_audit_warning(self) -> None:
722
+ """Show security audit warning."""
723
+ audit_report = getattr(self, "_last_security_audit", None)
724
+
725
+ if audit_report:
726
+ self.console.print(
727
+ "[yellow]⚠️ SECURITY AUDIT: Proceeding with partial quality success[/yellow]"
728
+ )
729
+
730
+ for warning in audit_report.security_warnings:
731
+ if "CRITICAL" in warning:
732
+ self.console.print(f"[red]{warning}[/red]")
733
+ elif "HIGH" in warning:
734
+ self.console.print(f"[yellow]{warning}[/yellow]")
735
+ else:
736
+ self.console.print(f"[blue]{warning}[/blue]")
737
+
738
+ if audit_report.recommendations:
739
+ self.console.print("[bold]Security Recommendations: [/bold]")
740
+ for rec in audit_report.recommendations[:3]:
741
+ self.console.print(f"[dim]{rec}[/dim]")
742
+ else:
743
+ self.console.print(
744
+ "[yellow]⚠️ SECURITY AUDIT: Proceeding with partial quality success[/yellow]"
745
+ )
746
+ self.console.print(
747
+ "[yellow]✅ Security-critical checks (bandit, pyright, gitleaks) have passed[/yellow]"
748
+ )
749
+ self.console.print(
750
+ "[yellow]⚠️ Some non-critical quality checks failed - consider reviewing before production deployment[/yellow]"
751
+ )
752
+
753
+ # Individual phase execution methods
754
+
755
+ def _run_fast_hooks_phase(self, options: OptionsProtocol) -> bool:
756
+ """Execute fast hooks phase."""
757
+ self._update_mcp_status("fast", "running")
758
+
759
+ if not self.phases.run_fast_hooks_only(options):
760
+ self.session.fail_task("workflow", "Fast hooks failed")
761
+ self._update_mcp_status("fast", "failed")
762
+ return False
763
+
764
+ self._update_mcp_status("fast", "completed")
765
+ return True
766
+
767
+ def _run_testing_phase(self, options: OptionsProtocol) -> bool:
768
+ """Execute testing phase."""
769
+ self._update_mcp_status("tests", "running")
770
+
771
+ success = self.phases.run_testing_phase(options)
772
+ if not success:
773
+ self.session.fail_task("workflow", "Testing failed")
774
+ self._handle_test_failures()
775
+ self._update_mcp_status("tests", "failed")
776
+
777
+ else:
778
+ self._update_mcp_status("tests", "completed")
779
+
780
+ return success
781
+
782
+ def _run_comprehensive_hooks_phase(self, options: OptionsProtocol) -> bool:
783
+ """Execute comprehensive hooks phase."""
784
+ self._update_mcp_status("comprehensive", "running")
785
+
786
+ success = self.phases.run_comprehensive_hooks_only(options)
787
+ if not success:
788
+ self.session.fail_task("comprehensive_hooks", "Comprehensive hooks failed")
789
+ self._update_mcp_status("comprehensive", "failed")
790
+
791
+ else:
792
+ self._update_mcp_status("comprehensive", "completed")
793
+
794
+ return success
795
+
796
+ def _run_code_cleaning_phase(self, options: OptionsProtocol) -> bool:
797
+ """Execute code cleaning phase."""
798
+ self.console.print("\n[bold blue]🧹 Running Code Cleaning Phase...[/bold blue]")
799
+
800
+ success = self.phases.run_cleaning_phase(options)
801
+ if success:
802
+ self.console.print("[green]✅ Code cleaning completed successfully[/green]")
803
+ else:
804
+ self.console.print("[red]❌ Code cleaning failed[/red]")
805
+ self.session.fail_task("workflow", "Code cleaning phase failed")
806
+
807
+ return success
808
+
809
+ def _run_post_cleaning_fast_hooks(self, options: OptionsProtocol) -> bool:
810
+ """Run fast hooks after code cleaning as sanity check."""
811
+ self.console.print(
812
+ "\n[bold cyan]🔍 Running Post-Cleaning Fast Hooks Sanity Check...[/bold cyan]"
813
+ )
814
+ # Allow a single re-run after cleaning by resetting the session guard
815
+ with suppress(Exception):
816
+ # Access PhaseCoordinator instance to reset its duplicate guard
817
+ setattr(self.phases, "_fast_hooks_started", False)
818
+ success = self._run_fast_hooks_phase(options)
819
+ if success:
820
+ self.console.print("[green]✅ Post-cleaning sanity check passed[/green]")
821
+ else:
822
+ self.console.print("[red]❌ Post-cleaning sanity check failed[/red]")
823
+ self.session.fail_task("workflow", "Post-cleaning fast hooks failed")
824
+
825
+ return success
826
+
827
+ # Async phase execution with monitoring
828
+
829
+ async def _run_initial_fast_hooks_async(
830
+ self, options: OptionsProtocol, iteration: int, monitor: t.Any
831
+ ) -> bool:
832
+ """Run initial fast hooks asynchronously."""
833
+ monitor.record_sequential_op()
834
+ fast_hooks_passed = self._run_fast_hooks_phase(options)
835
+ if not fast_hooks_passed:
836
+ if options.ai_agent and self._should_debug():
837
+ self.debugger.log_iteration_end(iteration, False)
838
+ return False
839
+ return True
840
+
841
+ async def _run_fast_hooks_phase_monitored(
842
+ self, options: OptionsProtocol, workflow_id: str
843
+ ) -> bool:
844
+ """Run fast hooks phase with monitoring."""
845
+ iteration = self._start_iteration_tracking(options)
846
+
847
+ with phase_monitor(workflow_id, "fast_hooks") as monitor:
848
+ monitor.record_sequential_op()
849
+ # Run blocking sync method in thread to avoid blocking event loop
850
+ fast_hooks_success = await asyncio.to_thread(
851
+ self._run_fast_hooks_phase, options
852
+ )
853
+
854
+ # Delegate to AI workflow completion handler if AI agent enabled
855
+ if options.ai_agent:
856
+ return await self._handle_ai_workflow_completion(
857
+ options, iteration, fast_hooks_success, True, workflow_id
858
+ )
859
+
860
+ return fast_hooks_success
861
+
862
+ async def _run_comprehensive_hooks_phase_monitored(
863
+ self, options: OptionsProtocol, workflow_id: str
864
+ ) -> bool:
865
+ """Run comprehensive hooks phase with monitoring."""
866
+ iteration = self._start_iteration_tracking(options)
867
+
868
+ with phase_monitor(workflow_id, "comprehensive_hooks") as monitor:
869
+ monitor.record_sequential_op()
870
+ # Run blocking sync method in thread to avoid blocking event loop
871
+ comprehensive_success = await asyncio.to_thread(
872
+ self._run_comprehensive_hooks_phase, options
873
+ )
874
+
875
+ # Delegate to AI workflow completion handler if AI agent enabled
876
+ if options.ai_agent:
877
+ return await self._handle_ai_workflow_completion(
878
+ options, iteration, True, comprehensive_success, workflow_id
879
+ )
880
+
881
+ return comprehensive_success
882
+
883
+ async def _run_testing_phase_async(
884
+ self, options: OptionsProtocol, workflow_id: str
885
+ ) -> bool:
886
+ """Run testing phase asynchronously with optional coverage improvement."""
887
+ with phase_monitor(workflow_id, "testing") as monitor:
888
+ monitor.record_sequential_op()
889
+ test_result = self._run_testing_phase(options)
890
+
891
+ # Execute coverage improvement if boost_coverage is enabled and tests passed
892
+ if test_result and getattr(options, "boost_coverage", False):
893
+ await self._execute_coverage_improvement(options)
894
+
895
+ return test_result
896
+
897
+ async def _execute_coverage_improvement(self, options: OptionsProtocol) -> None:
898
+ """Execute coverage improvement when boost_coverage is enabled."""
899
+ try:
900
+ from crackerjack.orchestration.coverage_improvement import (
901
+ create_coverage_improvement_orchestrator,
902
+ )
903
+
904
+ coverage_orchestrator = await create_coverage_improvement_orchestrator(
905
+ self.pkg_path
906
+ )
907
+
908
+ should_improve = await coverage_orchestrator.should_improve_coverage()
909
+ if not should_improve:
910
+ self.console.print(
911
+ "[dim]📈 Coverage at 100% - no improvement needed[/dim]"
912
+ )
913
+ return
914
+
915
+ # Create agent context for coverage improvement
916
+ agent_context = AgentContext(
917
+ project_path=self.pkg_path,
918
+ )
919
+
920
+ result = await coverage_orchestrator.execute_coverage_improvement(
921
+ agent_context
922
+ )
923
+
924
+ if result["status"] == "completed":
925
+ # Coverage orchestrator already printed success message
926
+ pass
927
+ elif result["status"] == "skipped":
928
+ self.console.print(
929
+ f"[dim]📈 Coverage improvement skipped: {result.get('reason', 'Unknown')}[/dim]"
930
+ )
931
+ else:
932
+ # Coverage orchestrator already printed failure message
933
+ pass
934
+
935
+ except Exception as e:
936
+ # Coverage orchestrator handles error display, only log for internal tracking
937
+ self.logger.warning(f"Coverage improvement error: {e}")
938
+
939
+ async def _execute_standard_hooks_workflow_monitored(
940
+ self, options: OptionsProtocol, workflow_id: str
941
+ ) -> bool:
942
+ """Execute standard hooks workflow with monitoring."""
943
+ iteration = self._start_iteration_tracking(options)
944
+
945
+ with phase_monitor(workflow_id, "hooks") as monitor:
946
+ self._update_hooks_status_running()
947
+
948
+ # Run blocking sync method in thread to avoid blocking event loop
949
+ fast_hooks_success = await asyncio.to_thread(
950
+ self._execute_monitored_fast_hooks_phase, options, monitor
951
+ )
952
+ if not fast_hooks_success:
953
+ self._handle_hooks_completion(False)
954
+ # If AI agent is enabled and hooks failed, delegate to AI workflow completion
955
+ if options.ai_agent:
956
+ return await self._handle_ai_workflow_completion(
957
+ options, iteration, fast_hooks_success, False, workflow_id
958
+ )
959
+ return False
960
+
961
+ # Run blocking sync method in thread to avoid blocking event loop
962
+ cleaning_success = await asyncio.to_thread(
963
+ self._execute_monitored_cleaning_phase, options
964
+ )
965
+ if not cleaning_success:
966
+ self._handle_hooks_completion(False)
967
+ return False
968
+
969
+ # Run blocking sync method in thread to avoid blocking event loop
970
+ comprehensive_success = await asyncio.to_thread(
971
+ self._execute_monitored_comprehensive_phase, options, monitor
972
+ )
973
+
974
+ hooks_success = fast_hooks_success and comprehensive_success
975
+ self._handle_hooks_completion(hooks_success)
976
+
977
+ # Delegate to AI workflow completion handler to check if AI fixing is needed
978
+ return await self._handle_ai_workflow_completion(
979
+ options,
980
+ iteration,
981
+ fast_hooks_success,
982
+ comprehensive_success,
983
+ workflow_id,
984
+ )
985
+
986
+ def _execute_monitored_fast_hooks_phase(
987
+ self, options: OptionsProtocol, monitor: t.Any
988
+ ) -> bool:
989
+ """Execute fast hooks with monitoring."""
990
+ fast_hooks_success = self._run_fast_hooks_phase(options)
991
+ if fast_hooks_success:
992
+ monitor.record_sequential_op()
993
+ return fast_hooks_success
994
+
995
+ def _execute_monitored_cleaning_phase(self, options: OptionsProtocol) -> bool:
996
+ """Execute cleaning phase with monitoring."""
997
+ if not getattr(options, "clean", False):
998
+ return True
999
+
1000
+ if not self._run_code_cleaning_phase(options):
1001
+ return False
1002
+
1003
+ if not self._run_post_cleaning_fast_hooks(options):
1004
+ return False
1005
+
1006
+ self._mark_code_cleaning_complete()
1007
+ return True
1008
+
1009
+ def _execute_monitored_comprehensive_phase(
1010
+ self, options: OptionsProtocol, monitor: t.Any
1011
+ ) -> bool:
1012
+ """Execute comprehensive hooks with monitoring."""
1013
+ comprehensive_success = self._run_comprehensive_hooks_phase(options)
1014
+ if comprehensive_success:
1015
+ monitor.record_sequential_op()
1016
+ return comprehensive_success
1017
+
1018
+ # Quality intelligence methods
1019
+
1020
+ async def _make_quality_intelligence_decision(
1021
+ self, options: OptionsProtocol
1022
+ ) -> str:
1023
+ """Use quality intelligence to make informed decisions about workflow execution."""
1024
+ try:
1025
+ if not self._quality_intelligence:
1026
+ return "Quality intelligence not available"
1027
+
1028
+ anomalies = await self._quality_intelligence.detect_anomalies_async()
1029
+ patterns = await self._quality_intelligence.identify_patterns_async()
1030
+
1031
+ recommendations = self._build_quality_recommendations(anomalies, patterns)
1032
+ return "; ".join(recommendations)
1033
+
1034
+ except Exception as e:
1035
+ return f"Quality intelligence analysis failed: {str(e)[:50]}..."
1036
+
1037
+ def _build_quality_recommendations(
1038
+ self, anomalies: t.Any, patterns: t.Any
1039
+ ) -> list[str]:
1040
+ """Build quality recommendations based on anomalies and patterns."""
1041
+ recommendations = []
1042
+
1043
+ if anomalies:
1044
+ recommendations.extend(self._analyze_anomalies(anomalies))
1045
+
1046
+ if patterns:
1047
+ recommendations.extend(self._analyze_patterns(patterns))
1048
+
1049
+ if not recommendations:
1050
+ recommendations.append("baseline quality analysis active")
1051
+
1052
+ return recommendations
1053
+
1054
+ def _analyze_anomalies(self, anomalies: t.Any) -> list[str]:
1055
+ """Analyze anomalies and return recommendations."""
1056
+ high_severity_anomalies = [
1057
+ a for a in anomalies if a.severity.name in ("CRITICAL", "HIGH")
1058
+ ]
1059
+
1060
+ if high_severity_anomalies:
1061
+ return ["comprehensive analysis recommended due to quality anomalies"]
1062
+ return ["standard quality checks sufficient"]
1063
+
1064
+ def _analyze_patterns(self, patterns: t.Any) -> list[str]:
1065
+ """Analyze patterns and return recommendations."""
1066
+ improving_patterns = [
1067
+ p for p in patterns if p.trend_direction.name == "IMPROVING"
1068
+ ]
1069
+
1070
+ if improving_patterns:
1071
+ return ["quality trending upward"]
1072
+ return ["quality monitoring active"]
1073
+
1074
+ # Helper methods
1075
+
1076
+ def _update_mcp_status(self, stage: str, status: str) -> None:
1077
+ """Update MCP state manager status."""
1078
+ if hasattr(self, "_mcp_state_manager") and self._mcp_state_manager:
1079
+ self._mcp_state_manager.update_stage_status(stage, status)
1080
+
1081
+ def _update_hooks_status_running(self) -> None:
1082
+ """Update hooks status to running."""
1083
+ if self._has_mcp_state_manager():
1084
+ self._mcp_state_manager.update_stage_status("fast", "running")
1085
+ self._mcp_state_manager.update_stage_status("comprehensive", "running")
1086
+
1087
+ def _handle_hooks_completion(self, hooks_success: bool) -> None:
1088
+ """Handle hooks completion status."""
1089
+ if not hooks_success:
1090
+ self.session.fail_task("workflow", "Hooks failed")
1091
+ self._update_hooks_status_failed()
1092
+ else:
1093
+ self._update_hooks_status_completed()
1094
+
1095
+ def _has_mcp_state_manager(self) -> bool:
1096
+ """Check if MCP state manager is available."""
1097
+ return hasattr(self, "_mcp_state_manager") and self._mcp_state_manager
1098
+
1099
+ def _update_hooks_status_failed(self) -> None:
1100
+ """Update hooks status to failed."""
1101
+ if self._has_mcp_state_manager():
1102
+ self._mcp_state_manager.update_stage_status("fast", "failed")
1103
+ self._mcp_state_manager.update_stage_status("comprehensive", "failed")
1104
+
1105
+ def _update_hooks_status_completed(self) -> None:
1106
+ """Update hooks status to completed."""
1107
+ if self._has_mcp_state_manager():
1108
+ self._mcp_state_manager.update_stage_status("fast", "completed")
1109
+ self._mcp_state_manager.update_stage_status("comprehensive", "completed")
1110
+
1111
+ def _has_code_cleaning_run(self) -> bool:
1112
+ """Check if code cleaning has been run."""
1113
+ return getattr(self, "_code_cleaning_complete", False)
1114
+
1115
+ def _mark_code_cleaning_complete(self) -> None:
1116
+ """Mark code cleaning as complete."""
1117
+ self._code_cleaning_complete = True
1118
+
1119
+ def _handle_test_failures(self) -> None:
1120
+ """Handle test failures by logging to MCP state."""
1121
+ if not (hasattr(self, "_mcp_state_manager") and self._mcp_state_manager):
1122
+ return
1123
+
1124
+ test_manager = self.phases.test_manager
1125
+ if not hasattr(test_manager, "get_test_failures"):
1126
+ return
1127
+
1128
+ failures = test_manager.get_test_failures()
1129
+
1130
+ if self._should_debug():
1131
+ self.debugger.log_test_failures(len(failures))
1132
+
1133
+ from crackerjack.mcp.state import Issue, Priority
1134
+
1135
+ for i, failure in enumerate(failures[:10]):
1136
+ issue = Issue(
1137
+ id=f"test_failure_{i}",
1138
+ type="test_failure",
1139
+ message=failure.strip(),
1140
+ file_path="tests/",
1141
+ priority=Priority.HIGH,
1142
+ stage="tests",
1143
+ auto_fixable=False,
1144
+ )
1145
+ self._mcp_state_manager.add_issue(issue)
1146
+
1147
+ def _should_debug(self) -> bool:
1148
+ """Check if debug mode is enabled."""
1149
+ import os
1150
+
1151
+ return os.environ.get("AI_AGENT_DEBUG", "0") == "1"
1152
+
1153
+ async def _publish_event(
1154
+ self, event: WorkflowEvent, data: dict[str, t.Any]
1155
+ ) -> None:
1156
+ """Publish workflow event if event bus is available."""
1157
+ if self._event_bus:
1158
+ await self._event_bus.publish_async(event, data)