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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. crackerjack/README.md +19 -0
  2. crackerjack/__init__.py +30 -1
  3. crackerjack/__main__.py +342 -1263
  4. crackerjack/adapters/README.md +18 -0
  5. crackerjack/adapters/__init__.py +27 -5
  6. crackerjack/adapters/_output_paths.py +167 -0
  7. crackerjack/adapters/_qa_adapter_base.py +309 -0
  8. crackerjack/adapters/_tool_adapter_base.py +706 -0
  9. crackerjack/adapters/ai/README.md +65 -0
  10. crackerjack/adapters/ai/__init__.py +5 -0
  11. crackerjack/adapters/ai/claude.py +853 -0
  12. crackerjack/adapters/complexity/README.md +53 -0
  13. crackerjack/adapters/complexity/__init__.py +10 -0
  14. crackerjack/adapters/complexity/complexipy.py +641 -0
  15. crackerjack/adapters/dependency/__init__.py +22 -0
  16. crackerjack/adapters/dependency/pip_audit.py +418 -0
  17. crackerjack/adapters/format/README.md +72 -0
  18. crackerjack/adapters/format/__init__.py +11 -0
  19. crackerjack/adapters/format/mdformat.py +313 -0
  20. crackerjack/adapters/format/ruff.py +516 -0
  21. crackerjack/adapters/lint/README.md +47 -0
  22. crackerjack/adapters/lint/__init__.py +11 -0
  23. crackerjack/adapters/lint/codespell.py +273 -0
  24. crackerjack/adapters/lsp/README.md +49 -0
  25. crackerjack/adapters/lsp/__init__.py +27 -0
  26. crackerjack/adapters/{rust_tool_manager.py → lsp/_manager.py} +3 -3
  27. crackerjack/adapters/{skylos_adapter.py → lsp/skylos.py} +59 -7
  28. crackerjack/adapters/{zuban_adapter.py → lsp/zuban.py} +3 -6
  29. crackerjack/adapters/refactor/README.md +59 -0
  30. crackerjack/adapters/refactor/__init__.py +12 -0
  31. crackerjack/adapters/refactor/creosote.py +318 -0
  32. crackerjack/adapters/refactor/refurb.py +406 -0
  33. crackerjack/adapters/refactor/skylos.py +494 -0
  34. crackerjack/adapters/sast/README.md +132 -0
  35. crackerjack/adapters/sast/__init__.py +32 -0
  36. crackerjack/adapters/sast/_base.py +201 -0
  37. crackerjack/adapters/sast/bandit.py +423 -0
  38. crackerjack/adapters/sast/pyscn.py +405 -0
  39. crackerjack/adapters/sast/semgrep.py +241 -0
  40. crackerjack/adapters/security/README.md +111 -0
  41. crackerjack/adapters/security/__init__.py +17 -0
  42. crackerjack/adapters/security/gitleaks.py +339 -0
  43. crackerjack/adapters/type/README.md +52 -0
  44. crackerjack/adapters/type/__init__.py +12 -0
  45. crackerjack/adapters/type/pyrefly.py +402 -0
  46. crackerjack/adapters/type/ty.py +402 -0
  47. crackerjack/adapters/type/zuban.py +522 -0
  48. crackerjack/adapters/utility/README.md +51 -0
  49. crackerjack/adapters/utility/__init__.py +10 -0
  50. crackerjack/adapters/utility/checks.py +884 -0
  51. crackerjack/agents/README.md +264 -0
  52. crackerjack/agents/__init__.py +40 -12
  53. crackerjack/agents/base.py +1 -0
  54. crackerjack/agents/claude_code_bridge.py +641 -0
  55. crackerjack/agents/coordinator.py +49 -53
  56. crackerjack/agents/dry_agent.py +187 -3
  57. crackerjack/agents/enhanced_coordinator.py +279 -0
  58. crackerjack/agents/enhanced_proactive_agent.py +185 -0
  59. crackerjack/agents/error_middleware.py +53 -0
  60. crackerjack/agents/formatting_agent.py +6 -8
  61. crackerjack/agents/helpers/__init__.py +9 -0
  62. crackerjack/agents/helpers/performance/__init__.py +22 -0
  63. crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
  64. crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
  65. crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
  66. crackerjack/agents/helpers/refactoring/__init__.py +22 -0
  67. crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
  68. crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
  69. crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
  70. crackerjack/agents/helpers/test_creation/__init__.py +19 -0
  71. crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
  72. crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
  73. crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
  74. crackerjack/agents/performance_agent.py +121 -1152
  75. crackerjack/agents/refactoring_agent.py +156 -655
  76. crackerjack/agents/semantic_agent.py +479 -0
  77. crackerjack/agents/semantic_helpers.py +356 -0
  78. crackerjack/agents/test_creation_agent.py +19 -1605
  79. crackerjack/api.py +5 -7
  80. crackerjack/cli/README.md +394 -0
  81. crackerjack/cli/__init__.py +1 -1
  82. crackerjack/cli/cache_handlers.py +23 -18
  83. crackerjack/cli/cache_handlers_enhanced.py +1 -4
  84. crackerjack/cli/facade.py +70 -8
  85. crackerjack/cli/formatting.py +13 -0
  86. crackerjack/cli/handlers/__init__.py +85 -0
  87. crackerjack/cli/handlers/advanced.py +103 -0
  88. crackerjack/cli/handlers/ai_features.py +62 -0
  89. crackerjack/cli/handlers/analytics.py +479 -0
  90. crackerjack/cli/handlers/changelog.py +271 -0
  91. crackerjack/cli/handlers/config_handlers.py +16 -0
  92. crackerjack/cli/handlers/coverage.py +84 -0
  93. crackerjack/cli/handlers/documentation.py +280 -0
  94. crackerjack/cli/handlers/main_handlers.py +497 -0
  95. crackerjack/cli/handlers/monitoring.py +371 -0
  96. crackerjack/cli/handlers.py +249 -49
  97. crackerjack/cli/interactive.py +8 -5
  98. crackerjack/cli/options.py +203 -110
  99. crackerjack/cli/semantic_handlers.py +292 -0
  100. crackerjack/cli/version.py +19 -0
  101. crackerjack/code_cleaner.py +60 -24
  102. crackerjack/config/README.md +472 -0
  103. crackerjack/config/__init__.py +256 -0
  104. crackerjack/config/global_lock_config.py +191 -54
  105. crackerjack/config/hooks.py +188 -16
  106. crackerjack/config/loader.py +239 -0
  107. crackerjack/config/settings.py +141 -0
  108. crackerjack/config/tool_commands.py +331 -0
  109. crackerjack/core/README.md +393 -0
  110. crackerjack/core/async_workflow_orchestrator.py +79 -53
  111. crackerjack/core/autofix_coordinator.py +22 -9
  112. crackerjack/core/container.py +10 -9
  113. crackerjack/core/enhanced_container.py +9 -9
  114. crackerjack/core/performance.py +1 -1
  115. crackerjack/core/performance_monitor.py +5 -3
  116. crackerjack/core/phase_coordinator.py +1018 -634
  117. crackerjack/core/proactive_workflow.py +3 -3
  118. crackerjack/core/retry.py +275 -0
  119. crackerjack/core/service_watchdog.py +167 -23
  120. crackerjack/core/session_coordinator.py +187 -382
  121. crackerjack/core/timeout_manager.py +161 -44
  122. crackerjack/core/workflow/__init__.py +21 -0
  123. crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
  124. crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
  125. crackerjack/core/workflow/workflow_issue_parser.py +714 -0
  126. crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
  127. crackerjack/core/workflow/workflow_security_gates.py +400 -0
  128. crackerjack/core/workflow_orchestrator.py +1247 -953
  129. crackerjack/data/README.md +11 -0
  130. crackerjack/data/__init__.py +8 -0
  131. crackerjack/data/models.py +79 -0
  132. crackerjack/data/repository.py +210 -0
  133. crackerjack/decorators/README.md +180 -0
  134. crackerjack/decorators/__init__.py +35 -0
  135. crackerjack/decorators/error_handling.py +649 -0
  136. crackerjack/decorators/error_handling_decorators.py +334 -0
  137. crackerjack/decorators/helpers.py +58 -0
  138. crackerjack/decorators/patterns.py +281 -0
  139. crackerjack/decorators/utils.py +58 -0
  140. crackerjack/docs/README.md +11 -0
  141. crackerjack/docs/generated/api/CLI_REFERENCE.md +1 -1
  142. crackerjack/documentation/README.md +11 -0
  143. crackerjack/documentation/ai_templates.py +1 -1
  144. crackerjack/documentation/dual_output_generator.py +11 -9
  145. crackerjack/documentation/reference_generator.py +104 -59
  146. crackerjack/dynamic_config.py +52 -61
  147. crackerjack/errors.py +1 -1
  148. crackerjack/events/README.md +11 -0
  149. crackerjack/events/__init__.py +16 -0
  150. crackerjack/events/telemetry.py +175 -0
  151. crackerjack/events/workflow_bus.py +346 -0
  152. crackerjack/exceptions/README.md +301 -0
  153. crackerjack/exceptions/__init__.py +5 -0
  154. crackerjack/exceptions/config.py +4 -0
  155. crackerjack/exceptions/tool_execution_error.py +245 -0
  156. crackerjack/executors/README.md +591 -0
  157. crackerjack/executors/__init__.py +2 -0
  158. crackerjack/executors/async_hook_executor.py +539 -77
  159. crackerjack/executors/cached_hook_executor.py +3 -3
  160. crackerjack/executors/hook_executor.py +967 -102
  161. crackerjack/executors/hook_lock_manager.py +31 -22
  162. crackerjack/executors/individual_hook_executor.py +66 -32
  163. crackerjack/executors/lsp_aware_hook_executor.py +136 -57
  164. crackerjack/executors/progress_hook_executor.py +282 -0
  165. crackerjack/executors/tool_proxy.py +23 -7
  166. crackerjack/hooks/README.md +485 -0
  167. crackerjack/hooks/lsp_hook.py +8 -9
  168. crackerjack/intelligence/README.md +557 -0
  169. crackerjack/interactive.py +37 -10
  170. crackerjack/managers/README.md +369 -0
  171. crackerjack/managers/async_hook_manager.py +41 -57
  172. crackerjack/managers/hook_manager.py +449 -79
  173. crackerjack/managers/publish_manager.py +81 -36
  174. crackerjack/managers/test_command_builder.py +290 -12
  175. crackerjack/managers/test_executor.py +93 -8
  176. crackerjack/managers/test_manager.py +1082 -75
  177. crackerjack/managers/test_progress.py +118 -26
  178. crackerjack/mcp/README.md +374 -0
  179. crackerjack/mcp/cache.py +25 -2
  180. crackerjack/mcp/client_runner.py +35 -18
  181. crackerjack/mcp/context.py +9 -9
  182. crackerjack/mcp/dashboard.py +24 -8
  183. crackerjack/mcp/enhanced_progress_monitor.py +34 -23
  184. crackerjack/mcp/file_monitor.py +27 -6
  185. crackerjack/mcp/progress_components.py +45 -34
  186. crackerjack/mcp/progress_monitor.py +6 -9
  187. crackerjack/mcp/rate_limiter.py +11 -7
  188. crackerjack/mcp/server.py +2 -0
  189. crackerjack/mcp/server_core.py +187 -55
  190. crackerjack/mcp/service_watchdog.py +12 -9
  191. crackerjack/mcp/task_manager.py +2 -2
  192. crackerjack/mcp/tools/README.md +27 -0
  193. crackerjack/mcp/tools/__init__.py +2 -0
  194. crackerjack/mcp/tools/core_tools.py +75 -52
  195. crackerjack/mcp/tools/execution_tools.py +87 -31
  196. crackerjack/mcp/tools/intelligence_tools.py +2 -2
  197. crackerjack/mcp/tools/proactive_tools.py +1 -1
  198. crackerjack/mcp/tools/semantic_tools.py +584 -0
  199. crackerjack/mcp/tools/utility_tools.py +180 -132
  200. crackerjack/mcp/tools/workflow_executor.py +87 -46
  201. crackerjack/mcp/websocket/README.md +31 -0
  202. crackerjack/mcp/websocket/app.py +11 -1
  203. crackerjack/mcp/websocket/event_bridge.py +188 -0
  204. crackerjack/mcp/websocket/jobs.py +27 -4
  205. crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
  206. crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
  207. crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
  208. crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
  209. crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
  210. crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
  211. crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
  212. crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
  213. crackerjack/mcp/websocket/monitoring/factory.py +109 -0
  214. crackerjack/mcp/websocket/monitoring/filters.py +10 -0
  215. crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
  216. crackerjack/mcp/websocket/monitoring/models.py +90 -0
  217. crackerjack/mcp/websocket/monitoring/utils.py +171 -0
  218. crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
  219. crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
  220. crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
  221. crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
  222. crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
  223. crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
  224. crackerjack/mcp/websocket/monitoring_endpoints.py +16 -2930
  225. crackerjack/mcp/websocket/server.py +1 -3
  226. crackerjack/mcp/websocket/websocket_handler.py +107 -6
  227. crackerjack/models/README.md +308 -0
  228. crackerjack/models/__init__.py +10 -1
  229. crackerjack/models/config.py +639 -22
  230. crackerjack/models/config_adapter.py +6 -6
  231. crackerjack/models/protocols.py +1167 -23
  232. crackerjack/models/pydantic_models.py +320 -0
  233. crackerjack/models/qa_config.py +145 -0
  234. crackerjack/models/qa_results.py +134 -0
  235. crackerjack/models/results.py +35 -0
  236. crackerjack/models/semantic_models.py +258 -0
  237. crackerjack/models/task.py +19 -3
  238. crackerjack/models/test_models.py +60 -0
  239. crackerjack/monitoring/README.md +11 -0
  240. crackerjack/monitoring/ai_agent_watchdog.py +5 -4
  241. crackerjack/monitoring/metrics_collector.py +4 -3
  242. crackerjack/monitoring/regression_prevention.py +4 -3
  243. crackerjack/monitoring/websocket_server.py +4 -241
  244. crackerjack/orchestration/README.md +340 -0
  245. crackerjack/orchestration/__init__.py +43 -0
  246. crackerjack/orchestration/advanced_orchestrator.py +20 -67
  247. crackerjack/orchestration/cache/README.md +312 -0
  248. crackerjack/orchestration/cache/__init__.py +37 -0
  249. crackerjack/orchestration/cache/memory_cache.py +338 -0
  250. crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
  251. crackerjack/orchestration/config.py +297 -0
  252. crackerjack/orchestration/coverage_improvement.py +13 -6
  253. crackerjack/orchestration/execution_strategies.py +6 -6
  254. crackerjack/orchestration/hook_orchestrator.py +1398 -0
  255. crackerjack/orchestration/strategies/README.md +401 -0
  256. crackerjack/orchestration/strategies/__init__.py +39 -0
  257. crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
  258. crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
  259. crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
  260. crackerjack/orchestration/test_progress_streamer.py +1 -1
  261. crackerjack/plugins/README.md +11 -0
  262. crackerjack/plugins/hooks.py +3 -2
  263. crackerjack/plugins/loader.py +3 -3
  264. crackerjack/plugins/managers.py +1 -1
  265. crackerjack/py313.py +191 -0
  266. crackerjack/security/README.md +11 -0
  267. crackerjack/services/README.md +374 -0
  268. crackerjack/services/__init__.py +8 -21
  269. crackerjack/services/ai/README.md +295 -0
  270. crackerjack/services/ai/__init__.py +7 -0
  271. crackerjack/services/ai/advanced_optimizer.py +878 -0
  272. crackerjack/services/{contextual_ai_assistant.py → ai/contextual_ai_assistant.py} +5 -3
  273. crackerjack/services/ai/embeddings.py +444 -0
  274. crackerjack/services/ai/intelligent_commit.py +328 -0
  275. crackerjack/services/ai/predictive_analytics.py +510 -0
  276. crackerjack/services/api_extractor.py +5 -3
  277. crackerjack/services/bounded_status_operations.py +45 -5
  278. crackerjack/services/cache.py +249 -318
  279. crackerjack/services/changelog_automation.py +7 -3
  280. crackerjack/services/command_execution_service.py +305 -0
  281. crackerjack/services/config_integrity.py +83 -39
  282. crackerjack/services/config_merge.py +9 -6
  283. crackerjack/services/config_service.py +198 -0
  284. crackerjack/services/config_template.py +13 -26
  285. crackerjack/services/coverage_badge_service.py +6 -4
  286. crackerjack/services/coverage_ratchet.py +53 -27
  287. crackerjack/services/debug.py +18 -7
  288. crackerjack/services/dependency_analyzer.py +4 -4
  289. crackerjack/services/dependency_monitor.py +13 -13
  290. crackerjack/services/documentation_generator.py +4 -2
  291. crackerjack/services/documentation_service.py +62 -33
  292. crackerjack/services/enhanced_filesystem.py +81 -27
  293. crackerjack/services/enterprise_optimizer.py +1 -1
  294. crackerjack/services/error_pattern_analyzer.py +10 -10
  295. crackerjack/services/file_filter.py +221 -0
  296. crackerjack/services/file_hasher.py +5 -7
  297. crackerjack/services/file_io_service.py +361 -0
  298. crackerjack/services/file_modifier.py +615 -0
  299. crackerjack/services/filesystem.py +80 -109
  300. crackerjack/services/git.py +99 -5
  301. crackerjack/services/health_metrics.py +4 -6
  302. crackerjack/services/heatmap_generator.py +12 -3
  303. crackerjack/services/incremental_executor.py +380 -0
  304. crackerjack/services/initialization.py +101 -49
  305. crackerjack/services/log_manager.py +2 -2
  306. crackerjack/services/logging.py +120 -68
  307. crackerjack/services/lsp_client.py +12 -12
  308. crackerjack/services/memory_optimizer.py +27 -22
  309. crackerjack/services/monitoring/README.md +30 -0
  310. crackerjack/services/monitoring/__init__.py +9 -0
  311. crackerjack/services/monitoring/dependency_monitor.py +678 -0
  312. crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
  313. crackerjack/services/monitoring/health_metrics.py +716 -0
  314. crackerjack/services/monitoring/metrics.py +587 -0
  315. crackerjack/services/{performance_benchmarks.py → monitoring/performance_benchmarks.py} +100 -14
  316. crackerjack/services/{performance_cache.py → monitoring/performance_cache.py} +21 -15
  317. crackerjack/services/{performance_monitor.py → monitoring/performance_monitor.py} +10 -6
  318. crackerjack/services/parallel_executor.py +166 -55
  319. crackerjack/services/patterns/__init__.py +142 -0
  320. crackerjack/services/patterns/agents.py +107 -0
  321. crackerjack/services/patterns/code/__init__.py +15 -0
  322. crackerjack/services/patterns/code/detection.py +118 -0
  323. crackerjack/services/patterns/code/imports.py +107 -0
  324. crackerjack/services/patterns/code/paths.py +159 -0
  325. crackerjack/services/patterns/code/performance.py +119 -0
  326. crackerjack/services/patterns/code/replacement.py +36 -0
  327. crackerjack/services/patterns/core.py +212 -0
  328. crackerjack/services/patterns/documentation/__init__.py +14 -0
  329. crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
  330. crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
  331. crackerjack/services/patterns/documentation/docstrings.py +89 -0
  332. crackerjack/services/patterns/formatting.py +226 -0
  333. crackerjack/services/patterns/operations.py +339 -0
  334. crackerjack/services/patterns/security/__init__.py +23 -0
  335. crackerjack/services/patterns/security/code_injection.py +122 -0
  336. crackerjack/services/patterns/security/credentials.py +190 -0
  337. crackerjack/services/patterns/security/path_traversal.py +221 -0
  338. crackerjack/services/patterns/security/unsafe_operations.py +216 -0
  339. crackerjack/services/patterns/templates.py +62 -0
  340. crackerjack/services/patterns/testing/__init__.py +18 -0
  341. crackerjack/services/patterns/testing/error_patterns.py +107 -0
  342. crackerjack/services/patterns/testing/pytest_output.py +126 -0
  343. crackerjack/services/patterns/tool_output/__init__.py +16 -0
  344. crackerjack/services/patterns/tool_output/bandit.py +72 -0
  345. crackerjack/services/patterns/tool_output/other.py +97 -0
  346. crackerjack/services/patterns/tool_output/pyright.py +67 -0
  347. crackerjack/services/patterns/tool_output/ruff.py +44 -0
  348. crackerjack/services/patterns/url_sanitization.py +114 -0
  349. crackerjack/services/patterns/utilities.py +42 -0
  350. crackerjack/services/patterns/utils.py +339 -0
  351. crackerjack/services/patterns/validation.py +46 -0
  352. crackerjack/services/patterns/versioning.py +62 -0
  353. crackerjack/services/predictive_analytics.py +21 -8
  354. crackerjack/services/profiler.py +280 -0
  355. crackerjack/services/quality/README.md +415 -0
  356. crackerjack/services/quality/__init__.py +11 -0
  357. crackerjack/services/quality/anomaly_detector.py +392 -0
  358. crackerjack/services/quality/pattern_cache.py +333 -0
  359. crackerjack/services/quality/pattern_detector.py +479 -0
  360. crackerjack/services/quality/qa_orchestrator.py +491 -0
  361. crackerjack/services/{quality_baseline.py → quality/quality_baseline.py} +163 -2
  362. crackerjack/services/{quality_baseline_enhanced.py → quality/quality_baseline_enhanced.py} +4 -1
  363. crackerjack/services/{quality_intelligence.py → quality/quality_intelligence.py} +180 -16
  364. crackerjack/services/regex_patterns.py +58 -2987
  365. crackerjack/services/regex_utils.py +55 -29
  366. crackerjack/services/secure_status_formatter.py +42 -15
  367. crackerjack/services/secure_subprocess.py +35 -2
  368. crackerjack/services/security.py +16 -8
  369. crackerjack/services/server_manager.py +40 -51
  370. crackerjack/services/smart_scheduling.py +46 -6
  371. crackerjack/services/status_authentication.py +3 -3
  372. crackerjack/services/thread_safe_status_collector.py +1 -0
  373. crackerjack/services/tool_filter.py +368 -0
  374. crackerjack/services/tool_version_service.py +9 -5
  375. crackerjack/services/unified_config.py +43 -351
  376. crackerjack/services/vector_store.py +689 -0
  377. crackerjack/services/version_analyzer.py +6 -4
  378. crackerjack/services/version_checker.py +14 -8
  379. crackerjack/services/zuban_lsp_service.py +5 -4
  380. crackerjack/slash_commands/README.md +11 -0
  381. crackerjack/slash_commands/init.md +2 -12
  382. crackerjack/slash_commands/run.md +84 -50
  383. crackerjack/tools/README.md +11 -0
  384. crackerjack/tools/__init__.py +30 -0
  385. crackerjack/tools/_git_utils.py +105 -0
  386. crackerjack/tools/check_added_large_files.py +139 -0
  387. crackerjack/tools/check_ast.py +105 -0
  388. crackerjack/tools/check_json.py +103 -0
  389. crackerjack/tools/check_jsonschema.py +297 -0
  390. crackerjack/tools/check_toml.py +103 -0
  391. crackerjack/tools/check_yaml.py +110 -0
  392. crackerjack/tools/codespell_wrapper.py +72 -0
  393. crackerjack/tools/end_of_file_fixer.py +202 -0
  394. crackerjack/tools/format_json.py +128 -0
  395. crackerjack/tools/mdformat_wrapper.py +114 -0
  396. crackerjack/tools/trailing_whitespace.py +198 -0
  397. crackerjack/tools/validate_regex_patterns.py +7 -3
  398. crackerjack/ui/README.md +11 -0
  399. crackerjack/ui/dashboard_renderer.py +28 -0
  400. crackerjack/ui/templates/README.md +11 -0
  401. crackerjack/utils/console_utils.py +13 -0
  402. crackerjack/utils/dependency_guard.py +230 -0
  403. crackerjack/utils/retry_utils.py +275 -0
  404. crackerjack/workflows/README.md +590 -0
  405. crackerjack/workflows/__init__.py +46 -0
  406. crackerjack/workflows/actions.py +811 -0
  407. crackerjack/workflows/auto_fix.py +444 -0
  408. crackerjack/workflows/container_builder.py +499 -0
  409. crackerjack/workflows/definitions.py +443 -0
  410. crackerjack/workflows/engine.py +177 -0
  411. crackerjack/workflows/event_bridge.py +242 -0
  412. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/METADATA +678 -98
  413. crackerjack-0.45.2.dist-info/RECORD +478 -0
  414. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
  415. crackerjack/managers/test_manager_backup.py +0 -1075
  416. crackerjack/mcp/tools/execution_tools_backup.py +0 -1011
  417. crackerjack/mixins/__init__.py +0 -3
  418. crackerjack/mixins/error_handling.py +0 -145
  419. crackerjack/services/config.py +0 -358
  420. crackerjack/ui/server_panels.py +0 -125
  421. crackerjack-0.37.9.dist-info/RECORD +0 -231
  422. /crackerjack/adapters/{rust_tool_adapter.py → lsp/_base.py} +0 -0
  423. /crackerjack/adapters/{lsp_client.py → lsp/_client.py} +0 -0
  424. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/entry_points.txt +0 -0
  425. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,434 +1,239 @@
1
- import json
2
- import logging
1
+ from __future__ import annotations
2
+
3
3
  import time
4
4
  import typing as t
5
- from contextlib import suppress
5
+ import uuid
6
6
  from pathlib import Path
7
7
 
8
- from rich.console import Console
8
+ from acb.console import Console
9
+ from acb.depends import depends
9
10
 
10
- from crackerjack.models.protocols import OptionsProtocol
11
11
  from crackerjack.models.task import SessionTracker
12
12
 
13
+ if t.TYPE_CHECKING:
14
+ from crackerjack.core.workflow_orchestrator import WorkflowPipeline
15
+ from crackerjack.models.protocols import OptionsProtocol
16
+
13
17
 
14
18
  class SessionCoordinator:
19
+ """Lightweight session tracking and cleanup coordinator."""
20
+
15
21
  def __init__(
16
22
  self,
17
- console: Console,
18
- pkg_path: Path,
23
+ console: Console | None = None,
24
+ pkg_path: Path | None = None,
19
25
  web_job_id: str | None = None,
20
26
  ) -> None:
21
- self.console = console
22
- self.pkg_path = pkg_path
23
- self.session_tracker: SessionTracker | None = None
24
- self._cleanup_handlers: list[t.Callable[[], None]] = []
25
- self._thread_pool = None
26
- self._lock_files: set[Path] = set()
27
-
28
- import uuid
29
-
30
- self.session_id = web_job_id or str(uuid.uuid4())
27
+ self.console = console or depends.get_sync(Console)
28
+ self.pkg_path = pkg_path or Path.cwd()
31
29
  self.web_job_id = web_job_id
30
+ self.session_id = web_job_id or uuid.uuid4().hex[:8]
32
31
  self.start_time = time.time()
33
- self.tasks: dict[str, t.Any] = {}
32
+ self.cleanup_config: t.Any = None
33
+ self.cleanup_handlers: list[t.Callable[[], None]] = []
34
+ self.lock_files: set[Path] = set()
34
35
  self.current_task: str | None = None
35
- self.success: bool = False
36
36
 
37
- self._setup_logging()
37
+ self.session_tracker: SessionTracker | None = None
38
+ self.tasks: dict[str, t.Any] = {}
39
+
40
+ def initialize_session_tracking(self, options: OptionsProtocol) -> None:
41
+ """Initialize session metadata and baseline tracking."""
42
+ self.session_tracker = SessionTracker(
43
+ session_id=self.session_id, start_time=self.start_time
44
+ )
38
45
 
39
- if self.web_job_id:
40
- self._setup_websocket_progress_file()
46
+ self.session_tracker.metadata.update(
47
+ {
48
+ "options": getattr(options, "__dict__", {}),
49
+ "pkg_path": str(self.pkg_path),
50
+ "initialized_at": time.time(),
51
+ },
52
+ )
53
+ self.tasks = self.session_tracker.tasks
54
+ self.start_session("workflow")
41
55
 
42
56
  def start_session(self, task_name: str) -> None:
57
+ """Record the start of a high-level session task."""
43
58
  self.current_task = task_name
59
+ # Lazily initialize session tracker if not already set
60
+ if self.session_tracker is None:
61
+ self.session_tracker = SessionTracker(
62
+ session_id=self.session_id, start_time=self.start_time
63
+ )
64
+ self.tasks = self.session_tracker.tasks
65
+ self.session_tracker.metadata.update({"pkg_path": str(self.pkg_path)})
66
+ self.session_tracker.metadata["current_session"] = task_name
44
67
 
45
- def end_session(self, success: bool = True) -> None:
46
- self.success = success
68
+ def end_session(self, success: bool) -> None:
69
+ """Mark session completion."""
70
+ # Record wall-clock end time for tests and summaries
47
71
  self.end_time = time.time()
72
+ if self.session_tracker:
73
+ self.session_tracker.metadata["completed_at"] = self.end_time
74
+ self.session_tracker.metadata["success"] = success
75
+ self.current_task = None
48
76
 
49
- # Capture quality metrics at session end
50
- self._capture_quality_metrics()
51
-
52
- if success:
53
- self.complete_task("session", "Session completed successfully")
54
- else:
55
- self.fail_task("session", "Session completed with errors")
56
-
57
- def initialize_session_tracking(self, options: OptionsProtocol) -> None:
58
- if hasattr(options, "track_progress") and options.track_progress:
59
- import uuid
60
-
77
+ def track_task(
78
+ self,
79
+ task_id: str,
80
+ task_name: str,
81
+ details: str | None = None,
82
+ ) -> str:
83
+ """Track a task within the session."""
84
+ if self.session_tracker is None:
61
85
  self.session_tracker = SessionTracker(
62
- console=self.console,
63
- session_id=str(uuid.uuid4()),
64
- start_time=time.time(),
86
+ session_id=self.session_id, start_time=self.start_time
65
87
  )
88
+ self.tasks = self.session_tracker.tasks
89
+ self.session_tracker.metadata.update({"pkg_path": str(self.pkg_path)})
90
+ self.session_tracker.start_task(task_id, task_name, details)
91
+ return task_id
66
92
 
67
- def track_task(self, task_id: str, task_name: str) -> str:
68
- import time
69
-
70
- task_obj = type(
71
- "Task",
72
- (),
73
- {
74
- "task_id": task_id,
75
- "description": task_name,
76
- "start_time": time.time(),
77
- "status": "in_progress",
78
- "details": None,
79
- "end_time": None,
80
- "progress": 0,
81
- },
82
- )()
83
-
84
- self.tasks[task_id] = task_obj
85
-
93
+ def complete_task(
94
+ self,
95
+ task_id: str,
96
+ details: str | None = None,
97
+ files_changed: list[str] | None = None,
98
+ ) -> None:
99
+ """Mark task as completed."""
86
100
  if self.session_tracker:
87
- self.session_tracker.start_task(task_id, task_name)
88
-
89
- return task_id
101
+ self.session_tracker.complete_task(task_id, details, files_changed)
90
102
 
91
103
  def update_task(
92
104
  self,
93
105
  task_id: str,
94
106
  status: str,
107
+ *,
95
108
  details: str | None = None,
96
- progress: int | None = None,
109
+ files_changed: list[str] | None = None,
110
+ error_message: str | None = None,
97
111
  ) -> None:
98
- if task_id in self.tasks:
99
- task = self.tasks[task_id]
100
- task.status = status
101
- if details:
102
- task.details = details
103
- if progress is not None:
104
- task.progress = progress
105
-
106
- if status in ("completed", "failed"):
107
- task.end_time = time.time()
108
-
109
- def complete_task(self, task_id: str, details: str | None = None) -> None:
110
- if self.session_tracker:
111
- self.session_tracker.complete_task(task_id, details=details)
112
-
113
- def fail_task(self, task_id: str, error: str) -> None:
114
- if self.session_tracker:
115
- self.session_tracker.fail_task(task_id, error)
116
-
117
- def get_session_summary(self) -> dict[str, int] | None:
118
- if self.session_tracker:
119
- return self.session_tracker.get_summary()
120
- return None
121
-
122
- def get_summary(self) -> dict[str, t.Any]:
123
- duration = getattr(self, "end_time", time.time()) - self.start_time
124
- tasks_count = len(self.tasks)
112
+ """Update a task's status in the current session.
125
113
 
126
- if self.session_tracker:
127
- return self.session_tracker.get_summary()
128
-
129
- return {
130
- "session_id": self.session_id,
131
- "duration": duration,
132
- "tasks_count": tasks_count,
133
- "success": self.success,
134
- "tasks": [
135
- {
136
- "task_id": task.task_id,
137
- "description": task.description,
138
- "status": task.status,
139
- "details": task.details,
140
- "start_time": task.start_time,
141
- "end_time": task.end_time,
142
- "progress": task.progress,
143
- }
144
- for task in self.tasks.values()
145
- ],
146
- }
147
-
148
- def finalize_session(self, start_time: float, success: bool) -> None:
149
- total_time = time.time() - start_time
150
- if success:
151
- self.complete_task(
152
- "workflow",
153
- f"Completed successfully in {total_time: .1f}s",
154
- )
155
- else:
156
- self.complete_task(
157
- "workflow",
158
- f"Completed with issues in {total_time: .1f}s",
159
- )
160
-
161
- def register_cleanup(self, cleanup_handler: t.Callable[[], None]) -> None:
162
- self._cleanup_handlers.append(cleanup_handler)
163
-
164
- def track_lock_file(self, lock_file_path: Path) -> None:
165
- self._lock_files.add(lock_file_path)
166
-
167
- def cleanup_resources(self) -> None:
168
- for cleanup_handler in self._cleanup_handlers:
169
- with suppress(Exception):
170
- cleanup_handler()
171
-
172
- self._cleanup_temporary_files()
173
-
174
- def _cleanup_temporary_files(self) -> None:
175
- if not hasattr(self, "_cleanup_config") or self._cleanup_config is None:
176
- self._cleanup_debug_logs()
177
- self._cleanup_coverage_files()
178
- self._cleanup_pycache_directories()
179
- elif self._cleanup_config.auto_cleanup:
180
- self._cleanup_debug_logs(keep_recent=self._cleanup_config.keep_debug_logs)
181
- self._cleanup_coverage_files(
182
- keep_recent=self._cleanup_config.keep_coverage_files,
183
- )
184
- self._cleanup_pycache_directories()
185
-
186
- def set_cleanup_config(self, cleanup_config: t.Any) -> None:
187
- self._cleanup_config = cleanup_config
188
-
189
- def _cleanup_debug_logs(self, keep_recent: int = 5) -> None:
190
- with suppress(Exception):
191
- from crackerjack.services.log_manager import get_log_manager
192
-
193
- log_manager = get_log_manager()
194
-
195
- log_manager.rotate_logs(
196
- log_manager.debug_dir,
197
- "debug-*.log",
198
- max_files=keep_recent,
199
- max_age_days=7,
200
- )
201
-
202
- legacy_pattern = "crackerjack-debug-*.log"
203
- legacy_files = sorted(
204
- self.pkg_path.glob(legacy_pattern),
205
- key=lambda p: p.stat().st_mtime,
206
- )
207
-
208
- for old_file in legacy_files[:-keep_recent]:
209
- with suppress(FileNotFoundError, PermissionError):
210
- old_file.unlink()
211
-
212
- def _cleanup_coverage_files(self, keep_recent: int = 10) -> None:
213
- with suppress(Exception):
214
- cache_dir = Path.home() / ".cache" / "crackerjack" / "coverage"
215
- if cache_dir.exists():
216
- pattern = ".coverage *"
217
- coverage_files = sorted(
218
- cache_dir.glob(pattern),
219
- key=lambda p: p.stat().st_mtime,
220
- )
221
-
222
- for old_file in coverage_files[:-keep_recent]:
223
- with suppress(FileNotFoundError, PermissionError):
224
- old_file.unlink()
225
-
226
- pattern = ".coverage.*"
227
- coverage_files = sorted(
228
- self.pkg_path.glob(pattern),
229
- key=lambda p: p.stat().st_mtime,
114
+ Supports 'completed', 'failed', and 'in_progress' states. Unknown statuses
115
+ are set directly on the TaskStatusData if present.
116
+ """
117
+ if self.session_tracker is None:
118
+ # Initialize tracker lazily to ensure tasks dict exists
119
+ self.session_tracker = SessionTracker(
120
+ session_id=self.session_id, start_time=self.start_time
230
121
  )
122
+ self.tasks = self.session_tracker.tasks
123
+ self.session_tracker.metadata.update({"pkg_path": str(self.pkg_path)})
231
124
 
232
- for old_file in coverage_files:
233
- with suppress(FileNotFoundError, PermissionError):
234
- old_file.unlink()
235
-
236
- def _cleanup_pycache_directories(self) -> None:
237
- with suppress(Exception):
238
- import shutil
239
-
240
- for pycache_dir in self.pkg_path.rglob("__pycache__"):
241
- if pycache_dir.is_dir():
242
- with suppress(FileNotFoundError, PermissionError):
243
- shutil.rmtree(pycache_dir)
244
-
245
- def _setup_logging(self) -> None:
246
- logger = logging.getLogger("crackerjack")
247
- if not logger.handlers:
248
- handler = logging.StreamHandler()
249
- handler.setLevel(logging.WARNING)
250
- logger.addHandler(handler)
251
- logger.setLevel(logging.WARNING)
252
-
253
- def _setup_websocket_progress_file(self) -> None:
254
- import tempfile
255
-
256
- self.progress_dir = Path(tempfile.gettempdir()) / "crackerjack-mcp-progress"
257
- self.progress_file = self.progress_dir / f"job-{self.web_job_id}.json"
258
-
259
- if self.progress_file.exists():
260
- self._update_websocket_progress("running", "Crackerjack process started")
261
-
262
- def _update_websocket_progress(self, status: str, message: str) -> None:
263
- if not hasattr(self, "progress_file") or not self.progress_file:
125
+ normalized = status.lower()
126
+ if normalized == "completed":
127
+ self.session_tracker.complete_task(task_id, details, files_changed)
264
128
  return
265
-
266
- try:
267
- progress_data = {}
268
- if self.progress_file.exists():
269
- progress_data = json.loads(self.progress_file.read_text())
270
-
271
- progress_data.update(
272
- {
273
- "status": status,
274
- "message": message,
275
- "updated_at": time.time(),
276
- "current_stage": message,
277
- },
278
- )
279
-
280
- self.progress_file.write_text(json.dumps(progress_data, indent=2))
281
-
282
- except Exception as e:
283
- self.console.print(
284
- f"[dim yellow]Warning: Could not update progress file: {e}[/ dim yellow]",
129
+ if normalized == "failed":
130
+ self.session_tracker.fail_task(
131
+ task_id, error_message or "Task failed", details
285
132
  )
133
+ return
134
+ if normalized == "in_progress":
135
+ # Ensure task exists; if not, create it as in-progress
136
+ if task_id not in self.session_tracker.tasks:
137
+ self.session_tracker.start_task(task_id, task_id, details)
138
+ else:
139
+ task = self.session_tracker.tasks[task_id]
140
+ task.status = "in_progress"
141
+ if details:
142
+ task.details = details
143
+ return
286
144
 
287
- def update_stage(self, stage: str, status: str) -> None:
288
- if self.web_job_id:
289
- self._update_websocket_progress(status, f"{stage}: {status}")
290
-
291
- def _capture_quality_metrics(self) -> None:
292
- """Capture quality metrics at the end of the session."""
293
- try:
294
- quality_service = self._initialize_quality_service()
295
- metrics = self._extract_session_metrics()
296
-
297
- if metrics:
298
- self._record_quality_baseline(quality_service, metrics)
299
- report = quality_service.generate_comprehensive_report(metrics)
300
- self._display_quality_report(report)
301
- except Exception as e:
302
- self._handle_quality_tracking_error(e)
303
-
304
- def _initialize_quality_service(self) -> t.Any:
305
- """Initialize the quality baseline service."""
306
- from crackerjack.services.quality_baseline_enhanced import (
307
- EnhancedQualityBaselineService,
308
- )
309
-
310
- return EnhancedQualityBaselineService()
145
+ # Fallback: set arbitrary status value if task exists
146
+ if task_id in self.session_tracker.tasks:
147
+ task = self.session_tracker.tasks[task_id]
148
+ task.status = normalized or task.status
149
+ if details:
150
+ task.details = details
311
151
 
312
- def _record_quality_baseline(
313
- self, quality_service: t.Any, metrics: dict[str, t.Any]
152
+ def fail_task(
153
+ self,
154
+ task_id: str,
155
+ error_message: str,
156
+ details: str | None = None,
314
157
  ) -> None:
315
- """Record quality baseline with metrics."""
316
- quality_service.record_baseline(
317
- coverage_percent=metrics.get("coverage_percent", 0.0),
318
- test_count=metrics.get("test_count", 0),
319
- test_pass_rate=metrics.get("test_pass_rate", 100.0),
320
- hook_failures=metrics.get("hook_failures", 0),
321
- complexity_violations=metrics.get("complexity_violations", 0),
322
- security_issues=metrics.get("security_issues", 0),
323
- type_errors=metrics.get("type_errors", 0),
324
- linting_issues=metrics.get("linting_issues", 0),
325
- )
326
-
327
- def _handle_quality_tracking_error(self, error: Exception) -> None:
328
- """Handle quality tracking errors without failing the session."""
329
- self.console.print(
330
- f"[dim yellow]Warning: Quality tracking failed: {error}[/dim yellow]"
331
- )
332
-
333
- def _extract_session_metrics(self) -> dict[str, t.Any] | None:
334
- """Extract quality metrics from the current session."""
335
- with suppress(Exception):
336
- metrics: dict[str, t.Any] = {}
337
- self._extract_test_metrics(metrics)
338
- self._extract_hook_metrics(metrics)
339
- self._set_default_metrics(metrics)
340
- return metrics or None
341
- return None
342
-
343
- def _extract_test_metrics(self, metrics: dict[str, t.Any]) -> None:
344
- """Extract test-related metrics from tasks."""
345
- if "testing" not in self.tasks:
346
- return
347
-
348
- test_task = self.tasks["testing"]
158
+ """Mark task as failed."""
159
+ if self.session_tracker:
160
+ self.session_tracker.fail_task(task_id, error_message, details)
349
161
 
350
- if hasattr(test_task, "coverage_percent"):
351
- metrics["coverage_percent"] = getattr(test_task, "coverage_percent", 0.0)
352
- if hasattr(test_task, "test_count"):
353
- metrics["test_count"] = getattr(test_task, "test_count", 0)
354
- if hasattr(test_task, "test_pass_rate"):
355
- metrics["test_pass_rate"] = getattr(test_task, "test_pass_rate", 0.0)
162
+ def finalize_session(self, start_time: float, success: bool) -> None:
163
+ """Finalize session bookkeeping."""
164
+ duration = time.time() - start_time
165
+ if self.session_tracker:
166
+ self.session_tracker.metadata["duration"] = duration
167
+ self.session_tracker.metadata["success"] = success
168
+ if success and self.current_task:
169
+ self.session_tracker.complete_task(self.current_task)
170
+ elif not success and self.current_task:
171
+ self.session_tracker.fail_task(self.current_task, "Session failed")
172
+ self.current_task = None
356
173
 
357
- def _extract_hook_metrics(self, metrics: dict[str, t.Any]) -> None:
358
- """Extract hook failure metrics from tasks."""
359
- hook_failures = 0
360
- for task_name, task in self.tasks.items():
361
- if "hooks" in task_name and hasattr(task, "status"):
362
- if getattr(task, "status") == "failed":
363
- hook_failures += 1
364
- metrics["hook_failures"] = hook_failures
174
+ def cleanup_resources(self) -> None:
175
+ """Execute registered cleanup handlers and release tracked resources."""
176
+ for handler in self.cleanup_handlers.copy():
177
+ try:
178
+ handler()
179
+ except Exception as exc: # pragma: no cover - defensive
180
+ self.console.print(
181
+ f"[red]Cleanup handler error:[/ red] {type(exc).__name__}: {exc}",
182
+ )
365
183
 
366
- def _set_default_metrics(self, metrics: dict[str, t.Any]) -> None:
367
- """Set default values for metrics we don't have direct access to."""
368
- defaults = {
369
- "coverage_percent": 0.0,
370
- "test_count": 0,
371
- "test_pass_rate": 100.0 if self.success else 0.0,
372
- "complexity_violations": 0,
373
- "security_issues": 0,
374
- "type_errors": 0,
375
- "linting_issues": 0,
184
+ for lock_path in list(self.lock_files):
185
+ try:
186
+ if lock_path.exists():
187
+ lock_path.unlink()
188
+ except OSError:
189
+ pass
190
+ finally:
191
+ self.lock_files.discard(lock_path)
192
+
193
+ def register_cleanup(self, handler: t.Callable[[], None]) -> None:
194
+ """Register cleanup handler to execute when session completes."""
195
+ self.cleanup_handlers.append(handler)
196
+
197
+ def track_lock_file(self, path: Path) -> None:
198
+ """Track lock file for cleanup."""
199
+ self.lock_files.add(path)
200
+
201
+ def set_cleanup_config(self, config: t.Any) -> None:
202
+ """Store cleanup configuration from options."""
203
+ self.cleanup_config = config
204
+
205
+ def get_session_summary(self) -> dict[str, t.Any]:
206
+ """Return high-level session summary."""
207
+ if self.session_tracker:
208
+ summary = self.session_tracker.get_summary()
209
+ # Backward compatible alias
210
+ if "tasks_count" not in summary:
211
+ summary["tasks_count"] = summary.get("total_tasks", 0)
212
+ return summary
213
+ return {
214
+ "session_id": self.session_id,
215
+ "metadata": {"pkg_path": str(self.pkg_path)},
216
+ "tasks": {},
217
+ "tasks_count": 0,
376
218
  }
377
- for key, default_value in defaults.items():
378
- metrics.setdefault(key, default_value)
379
219
 
380
- def _display_quality_report(self, report: t.Any) -> None:
381
- """Display a summary of the quality report."""
382
- with suppress(Exception):
383
- if not report.current_metrics:
384
- return
385
-
386
- self._display_quality_score(report)
387
- self._display_quality_trend(report)
388
- self._display_critical_alerts(report)
389
- self._display_top_recommendations(report)
390
-
391
- def _display_quality_score(self, report: t.Any) -> None:
392
- """Display the quality score."""
393
- score = report.current_metrics.quality_score
394
- self.console.print(f"\n[cyan]📊 Quality Score: {score}/100[/cyan]")
395
-
396
- def _display_quality_trend(self, report: t.Any) -> None:
397
- """Display quality trend information."""
398
- if not report.trend:
399
- return
400
-
401
- trend_emoji = self._get_trend_emoji(report.trend.direction.value)
402
- self.console.print(
403
- f"[dim]{trend_emoji} Trend: {report.trend.direction.value} "
404
- f"({report.trend.confidence:.1%} confidence)[/dim]"
405
- )
406
-
407
- def _get_trend_emoji(self, direction: str) -> str:
408
- """Get emoji for trend direction."""
409
- trend_emojis = {
410
- "improving": "📈",
411
- "declining": "📉",
412
- "stable": "📊",
413
- "volatile": "⚠️",
414
- }
415
- return trend_emojis.get(direction, "📊")
220
+ def get_summary(self) -> dict[str, t.Any]:
221
+ """Alias for get_session_summary."""
222
+ return self.get_session_summary()
416
223
 
417
- def _display_critical_alerts(self, report: t.Any) -> None:
418
- """Display critical quality alerts."""
419
- critical_alerts = [a for a in report.alerts if a.severity.value == "critical"]
420
- if critical_alerts:
421
- self.console.print(
422
- f"[red]🚨 {len(critical_alerts)} critical quality issues[/red]"
423
- )
424
224
 
425
- def _display_top_recommendations(self, report: t.Any) -> None:
426
- """Display top quality recommendations."""
427
- if not report.recommendations:
428
- return
225
+ class SessionController:
226
+ """Coordinates session setup for the workflow pipeline."""
429
227
 
430
- self.console.print("\n[yellow]💡 Top Recommendations:[/yellow]")
431
- for rec in report.recommendations[:2]: # Show top 2
432
- self.console.print(f" {rec}")
228
+ def __init__(self, pipeline: WorkflowPipeline) -> None:
229
+ self._pipeline = pipeline
433
230
 
434
- # Silently fail for display issues using suppress above
231
+ def initialize(self, options: OptionsProtocol) -> None:
232
+ """Initialize session state and ancillary services."""
233
+ pipeline = self._pipeline
234
+ pipeline.session.initialize_session_tracking(options)
235
+ pipeline._configure_session_cleanup(options)
236
+ pipeline._initialize_zuban_lsp(options)
237
+ pipeline._configure_hook_manager_lsp(options)
238
+ pipeline._register_lsp_cleanup_handler(options)
239
+ pipeline._log_workflow_startup_info(options)