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
@@ -0,0 +1,114 @@
1
+ """Git-aware wrapper for mdformat.
2
+
3
+ This wrapper ensures mdformat only checks git-tracked markdown files,
4
+ automatically respecting .gitignore patterns without needing manual skip
5
+ configuration.
6
+
7
+ Usage:
8
+ python -m crackerjack.tools.mdformat_wrapper [mdformat args...]
9
+
10
+ Exit Codes:
11
+ Same as mdformat (0 = no issues, 1 = issues found, etc.)
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import subprocess
17
+ import sys
18
+ from pathlib import Path
19
+
20
+ from ._git_utils import get_git_tracked_files
21
+
22
+
23
+ def main(argv: list[str] | None = None) -> int:
24
+ """Run mdformat on git-tracked markdown files only.
25
+
26
+ This wrapper automatically discovers git-tracked .md and .markdown files
27
+ and passes them to mdformat, ensuring .gitignore patterns are respected.
28
+
29
+ Behavior:
30
+ - First run: Formats files and returns exit code 1 (fail to signal changes)
31
+ - Second run: Files already formatted, returns exit code 0 (pass)
32
+
33
+ Args:
34
+ argv: Optional arguments to pass to mdformat
35
+
36
+ Returns:
37
+ Exit code: 0 if no changes needed, 1 if files were formatted
38
+ """
39
+ # Get all git-tracked markdown files (automatically respects .gitignore)
40
+ md_files = get_git_tracked_files("*.md")
41
+ markdown_files = get_git_tracked_files("*.markdown")
42
+ files = md_files + markdown_files
43
+
44
+ if not files:
45
+ print("No git-tracked markdown files found", file=sys.stderr) # noqa: T201
46
+ return 0 # No files is not an error for formatters
47
+
48
+ # Build mdformat command with git-tracked files
49
+ cmd = ["mdformat"]
50
+
51
+ # Add any additional arguments passed to wrapper
52
+ if argv:
53
+ cmd.extend(argv)
54
+
55
+ # Add file paths at the end
56
+ cmd.extend([str(f) for f in files])
57
+
58
+ # Execute mdformat
59
+ try:
60
+ # First, check if files need formatting (dry-run)
61
+ check_cmd = cmd + ["--check"]
62
+ check_result = subprocess.run(
63
+ check_cmd,
64
+ cwd=Path.cwd(),
65
+ check=False,
66
+ capture_output=True,
67
+ text=True,
68
+ )
69
+
70
+ # If check passed (exit code 0), files are already formatted
71
+ if check_result.returncode == 0:
72
+ print(f"All {len(files)} markdown files already formatted correctly")
73
+ return 0
74
+
75
+ # Files need formatting - run mdformat to fix them
76
+ format_result = subprocess.run(
77
+ cmd,
78
+ cwd=Path.cwd(),
79
+ check=False,
80
+ capture_output=True,
81
+ text=True,
82
+ )
83
+
84
+ # Forward output to stdout/stderr
85
+ if format_result.stdout:
86
+ print(format_result.stdout, end="")
87
+ if format_result.stderr:
88
+ print(format_result.stderr, end="", file=sys.stderr)
89
+
90
+ # Return exit code 1 to indicate files were formatted (changes made)
91
+ # This causes the hook to fail on first run, pass on second run
92
+ files_formatted = (
93
+ check_result.returncode
94
+ ) # Non-zero means files needed formatting
95
+ if files_formatted:
96
+ print(
97
+ f"Formatted {len(files)} markdown files - run crackerjack again to verify"
98
+ )
99
+ return 1 # Fail to signal changes were made
100
+
101
+ return 0
102
+ except FileNotFoundError:
103
+ print(
104
+ "Error: mdformat not found. Install with: uv pip install mdformat mdformat-ruff",
105
+ file=sys.stderr,
106
+ ) # noqa: T201
107
+ return 127 # Command not found
108
+ except Exception as e:
109
+ print(f"Error running mdformat: {e}", file=sys.stderr) # noqa: T201
110
+ return 1
111
+
112
+
113
+ if __name__ == "__main__":
114
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,198 @@
1
+ """Remove trailing whitespace from files.
2
+
3
+ This tool is a native Python implementation replacing pre-commit's
4
+ trailing-whitespace hook. It scans files for lines with trailing whitespace
5
+ and automatically removes it.
6
+
7
+ Usage:
8
+ python -m crackerjack.tools.trailing_whitespace [files...]
9
+
10
+ Exit Codes:
11
+ 0: No trailing whitespace found (or successfully fixed)
12
+ 1: Trailing whitespace found and fixed (files modified)
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import argparse
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ from ._git_utils import get_files_by_extension
22
+
23
+
24
+ def has_trailing_whitespace(line: str) -> bool:
25
+ """Check if a line has trailing whitespace.
26
+
27
+ Args:
28
+ line: Line to check (should include newline if present)
29
+
30
+ Returns:
31
+ True if line has trailing whitespace before newline
32
+ """
33
+ # Remove trailing newline for checking
34
+ line_stripped = line.rstrip("\n\r")
35
+ # Check if there's whitespace at the end
36
+ return line_stripped != line_stripped.rstrip()
37
+
38
+
39
+ def fix_trailing_whitespace(file_path: Path) -> bool:
40
+ """Remove trailing whitespace from a file.
41
+
42
+ Args:
43
+ file_path: Path to file to process
44
+
45
+ Returns:
46
+ True if file was modified, False if no changes needed
47
+ """
48
+ try:
49
+ # Read file content
50
+ content = file_path.read_text(encoding="utf-8")
51
+ lines = content.splitlines(keepends=True)
52
+
53
+ # Process lines
54
+ modified = False
55
+ new_lines = []
56
+ for line in lines:
57
+ if has_trailing_whitespace(line):
58
+ # Remove trailing whitespace but preserve newline
59
+ stripped = line.rstrip()
60
+ if line.endswith("\n"):
61
+ stripped += "\n"
62
+ elif line.endswith("\r\n"):
63
+ stripped += "\r\n"
64
+ new_lines.append(stripped)
65
+ modified = True
66
+ else:
67
+ new_lines.append(line)
68
+
69
+ # Write back if modified
70
+ if modified:
71
+ file_path.write_text("".join(new_lines), encoding="utf-8")
72
+ print(f"Fixed trailing whitespace: {file_path}") # noqa: T201
73
+
74
+ return modified
75
+
76
+ except UnicodeDecodeError:
77
+ # Skip binary files
78
+ return False
79
+ except Exception as e:
80
+ print(f"Error processing {file_path}: {e}", file=sys.stderr) # noqa: T201
81
+ return False
82
+
83
+
84
+ def _collect_files_to_check(args: argparse.Namespace) -> list[Path]:
85
+ """Collect files to check for trailing whitespace.
86
+
87
+ Args:
88
+ args: Parsed command-line arguments
89
+
90
+ Returns:
91
+ List of file paths to process
92
+ """
93
+ # Default to all git-tracked files if none specified
94
+ if not args.files:
95
+ # Get all tracked text files (respects .gitignore via git ls-files)
96
+ files = get_files_by_extension(
97
+ [".py", ".md", ".txt", ".yaml", ".yml", ".toml", ".json"]
98
+ )
99
+ if not files:
100
+ # Fallback to Python files if not in git repo
101
+ files = list(Path.cwd().rglob("*.py"))
102
+ else:
103
+ files = args.files
104
+
105
+ # Filter to existing files only
106
+ return [f for f in files if f.is_file()]
107
+
108
+
109
+ def _process_files_in_check_mode(files: list[Path]) -> int:
110
+ """Process files in check-only mode.
111
+
112
+ Args:
113
+ files: List of file paths to check
114
+
115
+ Returns:
116
+ Count of files with trailing whitespace
117
+ """
118
+ modified_count = 0
119
+ for file_path in files:
120
+ content = file_path.read_text(encoding="utf-8")
121
+ lines = content.splitlines(keepends=True)
122
+ if any(has_trailing_whitespace(line) for line in lines):
123
+ print(f"Trailing whitespace found: {file_path}") # noqa: T201
124
+ modified_count += 1
125
+ return modified_count
126
+
127
+
128
+ def _process_files_in_fix_mode(files: list[Path]) -> int:
129
+ """Process files in fix mode.
130
+
131
+ Args:
132
+ files: List of file paths to fix
133
+
134
+ Returns:
135
+ Count of files modified
136
+ """
137
+ modified_count = 0
138
+ for file_path in files:
139
+ if fix_trailing_whitespace(file_path):
140
+ modified_count += 1
141
+ return modified_count
142
+
143
+
144
+ def main(argv: list[str] | None = None) -> int:
145
+ """Main entry point for trailing-whitespace tool.
146
+
147
+ Args:
148
+ argv: Command-line arguments (defaults to sys.argv[1:])
149
+
150
+ Returns:
151
+ Exit code: 0 if no files modified, 1 if files were modified
152
+ """
153
+ parser = argparse.ArgumentParser(
154
+ description="Remove trailing whitespace from files"
155
+ )
156
+ parser.add_argument(
157
+ "files",
158
+ nargs="*",
159
+ type=Path,
160
+ help="Files to check (default: all Python files in current directory)",
161
+ )
162
+ parser.add_argument(
163
+ "--check",
164
+ action="store_true",
165
+ help="Check only, don't modify files",
166
+ )
167
+
168
+ args = parser.parse_args(argv)
169
+
170
+ files = _collect_files_to_check(args)
171
+
172
+ if not files:
173
+ print("No files to check") # noqa: T201
174
+ return 0
175
+
176
+ # Process files based on mode
177
+ if args.check:
178
+ modified_count = _process_files_in_check_mode(files)
179
+ else:
180
+ modified_count = _process_files_in_fix_mode(files)
181
+
182
+ # Return appropriate exit code
183
+ if modified_count > 0:
184
+ if args.check:
185
+ print(f"\n{modified_count} file(s) with trailing whitespace") # noqa: T201
186
+ else:
187
+ print(f"\nFixed {modified_count} file(s)") # noqa: T201
188
+ # Align with pre-commit semantics so HookExecutor treats this as pass
189
+ # when a formatter modifies files but exits with code 1.
190
+ print("files were modified by this hook") # noqa: T201
191
+ return 1
192
+
193
+ print("No trailing whitespace found") # noqa: T201
194
+ return 0
195
+
196
+
197
+ if __name__ == "__main__":
198
+ sys.exit(main())
@@ -145,6 +145,10 @@ def validate_file(file_path: Path) -> list[tuple[int, str]]:
145
145
 
146
146
 
147
147
  def main(file_paths: list[str]) -> int:
148
+ if not file_paths:
149
+ print("✅ No Python files to validate")
150
+ return 0
151
+
148
152
  exit_code = 0
149
153
 
150
154
  for file_path_str in file_paths:
@@ -167,15 +171,15 @@ def main(file_paths: list[str]) -> int:
167
171
  if exit_code == 0:
168
172
  print("✅ All regex patterns validated successfully!")
169
173
  else:
170
- print("\n" + "=" * 74)
174
+ print("\n" + "=" * 70)
171
175
  print("REGEX VALIDATION FAILED")
172
- print("=" * 74)
176
+ print("=" * 70)
173
177
  print("To fix these issues: ")
174
178
  print("1. Use patterns from crackerjack.services.regex_patterns")
175
179
  print("2. Add new patterns to SAFE_PATTERNS with comprehensive tests")
176
180
  print("3. Use '# REGEX OK: reason' comment for legitimate exceptions")
177
181
  print("4. Fix \\g<1> replacement syntax (no spaces)")
178
- print("=" * 74)
182
+ print("=" * 70)
179
183
 
180
184
  return exit_code
181
185
 
@@ -0,0 +1,11 @@
1
+ > Crackerjack Docs: [Main](<../../README.md>) | [Crackerjack Package](<../README.md>) | [UI](<./README.md>)
2
+
3
+ # UI
4
+
5
+ User interface components and templates.
6
+
7
+ ## Related
8
+
9
+ - [Crackerjack Package](<../README.md>) - Parent package
10
+ - [UI Templates](<./templates/README.md>) - Template files for UI components
11
+ - [MCP](<../mcp/README.md>) - MCP progress monitor UI
@@ -0,0 +1,28 @@
1
+ """Utilities for rendering the monitoring dashboard UI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from functools import lru_cache
6
+ from pathlib import Path
7
+
8
+ _TEMPLATE_DIR = Path(__file__).with_suffix("").parent / "templates"
9
+
10
+
11
+ def _load_asset(filename: str) -> str:
12
+ path = _TEMPLATE_DIR / filename
13
+ if not path.exists():
14
+ msg = f"Dashboard asset not found: {filename}"
15
+ raise FileNotFoundError(msg)
16
+ return path.read_text(encoding="utf-8")
17
+
18
+
19
+ @lru_cache(maxsize=1)
20
+ def render_monitoring_dashboard() -> str:
21
+ """Render the monitoring dashboard HTML using cached assets."""
22
+ html_template = _load_asset("monitoring_dashboard.html")
23
+ css_styles = _load_asset("monitoring_dashboard.css")
24
+ javascript_code = _load_asset("monitoring_dashboard.js")
25
+ return html_template.format(
26
+ css_styles=css_styles,
27
+ javascript_code=javascript_code,
28
+ )
@@ -0,0 +1,11 @@
1
+ > Crackerjack Docs: [Main](<../../../README.md>) | [Crackerjack Package](<../../README.md>) | [UI](<../README.md>) | [Templates](<./README.md>)
2
+
3
+ # UI Templates
4
+
5
+ Templates used by UI components.
6
+
7
+ ## Related
8
+
9
+ - [UI](<../README.md>) - Parent UI package
10
+ - [Crackerjack Package](<../../README.md>) - Root package
11
+ - [Data](<../../data/README.md>) - Static data and assets
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from crackerjack.config import get_console_width
4
+
5
+
6
+ def separator(char: str = "-", width: int | None = None) -> str:
7
+ """Return a horizontal separator string.
8
+
9
+ - char: the character to repeat (default '-')
10
+ - width: explicit width; if None, uses configured console width
11
+ """
12
+ w = width if isinstance(width, int) and width > 0 else get_console_width()
13
+ return char * w
@@ -0,0 +1,230 @@
1
+ """
2
+ Dependency Guard module to ensure proper dependency injection.
3
+
4
+ This module provides utilities to ensure that dependencies are properly
5
+ registered in the ACB dependency injection system and to handle cases
6
+ where dependencies might be registered as empty tuples or other invalid
7
+ values.
8
+ """
9
+
10
+ import sys
11
+ import typing
12
+ from typing import Any
13
+
14
+ from acb.depends import depends
15
+ from acb.logger import Logger
16
+
17
+
18
+ def _should_log_debug() -> bool:
19
+ """Check if debug mode is active via CLI flags.
20
+
21
+ Uses sys.argv directly for early detection before flag parsing.
22
+ This is thread-safe as sys.argv is read-only during execution.
23
+ """
24
+ return any(
25
+ arg in ("--debug", "-d", "--ai-debug") or arg.startswith("--debug=")
26
+ for arg in sys.argv[1:]
27
+ )
28
+
29
+
30
+ def _log_dependency_issue(message: str, level: str = "WARNING") -> None:
31
+ """Log dependency issues only in debug mode.
32
+
33
+ Args:
34
+ message: The log message to emit
35
+ level: Log level (INFO, WARNING, ERROR)
36
+ """
37
+ if not _should_log_debug():
38
+ return
39
+ # Use stderr for diagnostic messages (stdout reserved for user output)
40
+ print(f"[CRACKERJACK:{level}] {message}", file=sys.stderr)
41
+
42
+
43
+ def ensure_logger_dependency() -> None:
44
+ """
45
+ Ensure that Logger and LoggerProtocol are properly registered in the DI container.
46
+ This prevents issues where empty tuples might get registered instead of logger instances.
47
+ """
48
+ # Check if Logger is registered and has a valid instance
49
+ try:
50
+ logger_instance = depends.get_sync(Logger)
51
+ # If we get an empty tuple, string, or other invalid value, replace it
52
+ if isinstance(logger_instance, tuple) and len(logger_instance) == 0:
53
+ _log_dependency_issue(
54
+ "Logger dependency was registered as empty tuple, replacing with fresh instance"
55
+ )
56
+ # Create a new logger instance to replace the invalid one
57
+ from acb.logger import Logger as ACBLogger
58
+
59
+ fresh_logger = ACBLogger()
60
+ depends.set(Logger, fresh_logger)
61
+ elif isinstance(logger_instance, str):
62
+ _log_dependency_issue(
63
+ f"Logger dependency was registered as string ({logger_instance!r}), replacing with fresh instance"
64
+ )
65
+ # Create a new logger instance to replace the invalid one
66
+ from acb.logger import Logger as ACBLogger
67
+
68
+ fresh_logger = ACBLogger()
69
+ depends.set(Logger, fresh_logger)
70
+ except Exception:
71
+ # If there's no logger registered at all, create one
72
+ from acb.logger import Logger as ACBLogger
73
+
74
+ fresh_logger = ACBLogger()
75
+ depends.set(Logger, fresh_logger)
76
+
77
+ # Do the same check for LoggerProtocol if it exists
78
+ # Import once to avoid typing issues
79
+ try:
80
+ from crackerjack.models.protocols import LoggerProtocol as _LoggerProtocol
81
+
82
+ logger_proto_instance = depends.get_sync(_LoggerProtocol)
83
+ if isinstance(logger_proto_instance, tuple) and len(logger_proto_instance) == 0:
84
+ _log_dependency_issue(
85
+ "LoggerProtocol dependency was registered as empty tuple, replacing with fresh instance"
86
+ )
87
+ from acb.logger import Logger as ACBLogger
88
+
89
+ fresh_logger = ACBLogger()
90
+ depends.set(_LoggerProtocol, fresh_logger)
91
+ elif isinstance(logger_proto_instance, str):
92
+ _log_dependency_issue(
93
+ f"LoggerProtocol dependency was registered as string ({logger_proto_instance!r}), replacing with fresh instance"
94
+ )
95
+ from acb.logger import Logger as ACBLogger
96
+
97
+ fresh_logger = ACBLogger()
98
+ depends.set(_LoggerProtocol, fresh_logger)
99
+ except ImportError:
100
+ # LoggerProtocol doesn't exist, that's fine
101
+ pass
102
+ except Exception:
103
+ # If there's no LoggerProtocol registered, create one
104
+ try:
105
+ from acb.logger import Logger as ACBLogger
106
+
107
+ fresh_logger = ACBLogger()
108
+ _log_dependency_issue(
109
+ "Registering LoggerProtocol with fresh logger instance", level="INFO"
110
+ )
111
+ # Register the fresh_logger instance with the LoggerProtocol
112
+ depends.set(_LoggerProtocol, fresh_logger)
113
+ except NameError:
114
+ # _LoggerProtocol is not defined if the import failed
115
+ pass
116
+ except Exception:
117
+ pass # Any other error, just continue
118
+
119
+
120
+ def validate_dependency_registration(
121
+ dep_type: type[Any], fallback_factory: typing.Callable | None = None
122
+ ) -> bool:
123
+ """
124
+ Validate that a dependency is properly registered and not an empty tuple or string.
125
+
126
+ Args:
127
+ dep_type: The type of dependency to validate
128
+ fallback_factory: Optional factory function to create a fallback instance if needed
129
+
130
+ Returns:
131
+ True if the dependency is properly registered, False otherwise
132
+ """
133
+ try:
134
+ instance = depends.get_sync(dep_type)
135
+ # Check if it's an empty tuple (the problematic case)
136
+ if isinstance(instance, tuple) and len(instance) == 0:
137
+ _log_dependency_issue(
138
+ f"Dependency {dep_type} was registered as empty tuple"
139
+ )
140
+ # Replace with a fallback if provided
141
+ if fallback_factory:
142
+ fallback_instance = fallback_factory()
143
+ depends.set(dep_type, fallback_instance)
144
+ _log_dependency_issue(
145
+ f"Replaced empty tuple for {dep_type} with new instance",
146
+ level="INFO",
147
+ )
148
+ return True
149
+ return False
150
+ # Check if it's a string (another problematic case)
151
+ elif isinstance(instance, str):
152
+ _log_dependency_issue(
153
+ f"Dependency {dep_type} was registered as string: {instance!r}"
154
+ )
155
+ # Replace with a fallback if provided
156
+ if fallback_factory:
157
+ fallback_instance = fallback_factory()
158
+ depends.set(dep_type, fallback_instance)
159
+ _log_dependency_issue(
160
+ f"Replaced string for {dep_type} with new instance", level="INFO"
161
+ )
162
+ return True
163
+ return False
164
+ return True
165
+ except Exception:
166
+ # If dependency doesn't exist at all, return False
167
+ return False
168
+
169
+
170
+ def safe_get_logger() -> Logger:
171
+ """
172
+ Safely get a logger instance, ensuring it's not an empty tuple or string.
173
+
174
+ Returns:
175
+ A valid logger instance
176
+ """
177
+ try:
178
+ logger_instance = depends.get_sync(Logger)
179
+ if isinstance(logger_instance, tuple) and len(logger_instance) == 0:
180
+ _log_dependency_issue(
181
+ "Logger dependency was an empty tuple in safe_get_logger, replacing with fresh instance"
182
+ )
183
+ # Create and register a fresh logger
184
+ from acb.logger import Logger as ACBLogger
185
+
186
+ fresh_logger = ACBLogger()
187
+ depends.set(Logger, fresh_logger)
188
+ return fresh_logger
189
+ elif isinstance(logger_instance, str):
190
+ _log_dependency_issue(
191
+ f"Logger dependency was a string ({logger_instance!r}) in safe_get_logger, replacing with fresh instance"
192
+ )
193
+ # Create and register a fresh logger
194
+ from acb.logger import Logger as ACBLogger
195
+
196
+ fresh_logger = ACBLogger()
197
+ depends.set(Logger, fresh_logger)
198
+ return fresh_logger
199
+ return logger_instance
200
+ except Exception:
201
+ # If no logger is registered, create one
202
+ from acb.logger import Logger as ACBLogger
203
+
204
+ _log_dependency_issue(
205
+ "No logger registered, creating and registering a fresh logger instance",
206
+ level="INFO",
207
+ )
208
+ fresh_logger = ACBLogger()
209
+ depends.set(Logger, fresh_logger)
210
+ return fresh_logger
211
+
212
+
213
+ def check_all_dependencies_for_empty_tuples():
214
+ """
215
+ Debug function to check all registered dependencies for empty tuples.
216
+ This can help identify which dependencies have been incorrectly registered.
217
+ """
218
+ # This would require access to the internal state of the ACB DI system
219
+ # which might not be available, so we'll just print a notice
220
+ _log_dependency_issue(
221
+ "Dependency check: To check all dependencies for empty tuples, you would need access to ACB's internal container state.",
222
+ level="INFO",
223
+ )
224
+ _log_dependency_issue(
225
+ "This is currently not possible without modifying ACB itself.", level="INFO"
226
+ )
227
+ _log_dependency_issue(
228
+ "The best approach is to use the individual validation functions for known problematic dependencies.",
229
+ level="INFO",
230
+ )