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,557 @@
1
+ """Zuban adapter for type checking with LSP integration."""
2
+
3
+ import asyncio
4
+ import typing as t
5
+ from contextlib import suppress
6
+ from dataclasses import dataclass
7
+ from pathlib import Path
8
+
9
+ from ._base import BaseRustToolAdapter, Issue, ToolResult
10
+
11
+ if t.TYPE_CHECKING:
12
+ from crackerjack.orchestration.execution_strategies import ExecutionContext
13
+ from crackerjack.services.lsp_client import LSPClient
14
+
15
+ # Import the LSP client wrapper
16
+ from ._client import ZubanLSPClient
17
+
18
+
19
+ @dataclass
20
+ class TypeIssue(Issue):
21
+ """Zuban type checking issue."""
22
+
23
+ severity: str = "error" # Override default, type errors are typically errors
24
+ column: int = 1
25
+ error_code: str | None = None
26
+
27
+ def to_dict(self) -> dict[str, t.Any]:
28
+ """Convert issue to dictionary with Zuban-specific fields."""
29
+ base_dict = super().to_dict()
30
+ base_dict.update(
31
+ {
32
+ "column": self.column,
33
+ "error_code": self.error_code,
34
+ }
35
+ )
36
+ return base_dict
37
+
38
+
39
+ class ZubanAdapter(BaseRustToolAdapter):
40
+ """Zuban type checking adapter with LSP integration."""
41
+
42
+ def __init__(
43
+ self,
44
+ context: "ExecutionContext",
45
+ strict_mode: bool = True,
46
+ mypy_compatibility: bool = True,
47
+ use_lsp: bool = True,
48
+ ) -> None:
49
+ """Initialize Zuban adapter.
50
+
51
+ Args:
52
+ context: Execution context
53
+ strict_mode: Enable strict type checking
54
+ mypy_compatibility: Use MyPy-compatible mode
55
+ use_lsp: Enable LSP integration for faster checking
56
+ """
57
+ super().__init__(context)
58
+ self.strict_mode = strict_mode
59
+ self.mypy_compatibility = mypy_compatibility
60
+ self.use_lsp = use_lsp
61
+ self._lsp_client: LSPClient | None = None
62
+ self._lsp_wrapper: ZubanLSPClient | None = None
63
+ self._lsp_available = False
64
+
65
+ def get_tool_name(self) -> str:
66
+ """Get the name of the tool."""
67
+ return "zuban"
68
+
69
+ def check_tool_health(self) -> bool:
70
+ """Check if Zuban is functional before use.
71
+
72
+ Returns:
73
+ True if Zuban can be used safely, False otherwise
74
+ """
75
+ try:
76
+ import subprocess
77
+
78
+ # Test basic version command - this should not crash
79
+ result = subprocess.run(
80
+ ["uv", "run", "zuban", "--version"],
81
+ capture_output=True,
82
+ text=True,
83
+ timeout=10,
84
+ )
85
+
86
+ if result.returncode != 0:
87
+ return False
88
+
89
+ # Test if we can parse TOML without crashing
90
+ # Create a minimal test to check for TOML parsing bug
91
+ result = subprocess.run(
92
+ ["uv", "run", "zuban", "--help"],
93
+ capture_output=True,
94
+ text=True,
95
+ timeout=10,
96
+ )
97
+
98
+ return result.returncode == 0
99
+
100
+ except (subprocess.TimeoutExpired, subprocess.CalledProcessError, Exception):
101
+ return False
102
+
103
+ def supports_json_output(self) -> bool:
104
+ """Zuban does not support JSON output mode."""
105
+ return False
106
+
107
+ def _ensure_lsp_client(self) -> None:
108
+ """Initialize LSP client if not already available."""
109
+ if not self.use_lsp or self._lsp_client is not None:
110
+ return
111
+
112
+ try:
113
+ # Import here to avoid circular imports
114
+ from crackerjack.services.lsp_client import LSPClient
115
+
116
+ self._lsp_client = LSPClient()
117
+ self._lsp_available = self._lsp_client.is_server_running()
118
+
119
+ except ImportError:
120
+ self._lsp_available = False
121
+
122
+ async def get_lsp_diagnostics(self, target_files: list[Path]) -> list[TypeIssue]:
123
+ """Get real-time diagnostics from LSP server.
124
+
125
+ Args:
126
+ target_files: List of files to check
127
+
128
+ Returns:
129
+ List of type issues found by LSP server
130
+ """
131
+ self._ensure_lsp_client()
132
+
133
+ if not self._lsp_available or not self._lsp_client:
134
+ return []
135
+
136
+ try:
137
+ # Convert paths to strings for LSP client
138
+ [str(f.resolve()) for f in target_files]
139
+
140
+ # Get diagnostics from LSP client
141
+ diagnostics, _ = self._lsp_client.check_project_with_feedback(
142
+ project_path=target_files[0].parent if target_files else Path.cwd(),
143
+ show_progress=False,
144
+ )
145
+
146
+ # Convert LSP diagnostics to TypeIssue objects
147
+ issues: list[TypeIssue] = []
148
+ for file_path, file_diagnostics in diagnostics.items():
149
+ for diag in file_diagnostics:
150
+ issues.append(
151
+ TypeIssue(
152
+ file_path=Path(file_path),
153
+ line_number=diag.get("line", 1),
154
+ column=diag.get("column", 1),
155
+ message=diag.get("message", "Type error"),
156
+ severity=diag.get("severity", "error"),
157
+ error_code=diag.get("code"),
158
+ )
159
+ )
160
+
161
+ return issues
162
+
163
+ except Exception:
164
+ # LSP failed, return empty list[t.Any] to trigger fallback
165
+ self._lsp_available = False
166
+ return []
167
+
168
+ async def get_lsp_diagnostics_optimized(
169
+ self, target_files: list[Path]
170
+ ) -> list[TypeIssue]:
171
+ """Get diagnostics using optimized LSP wrapper.
172
+
173
+ Args:
174
+ target_files: List of files to check
175
+
176
+ Returns:
177
+ List of type issues found by LSP server
178
+ """
179
+ if not self.use_lsp:
180
+ return []
181
+
182
+ if not self._lsp_wrapper:
183
+ self._lsp_wrapper = ZubanLSPClient()
184
+
185
+ try:
186
+ async with self._lsp_wrapper as lsp:
187
+ if not await self._initialize_lsp_workspace(lsp, target_files):
188
+ return []
189
+
190
+ issues = await self._process_files_with_lsp(lsp, target_files)
191
+ return issues
192
+
193
+ except Exception:
194
+ # Fallback to original LSP client method
195
+ return await self.get_lsp_diagnostics(target_files)
196
+
197
+ async def _initialize_lsp_workspace(
198
+ self, lsp: t.Any, target_files: list[Path]
199
+ ) -> bool:
200
+ """Initialize LSP workspace and return success status."""
201
+ root_path = target_files[0].parent if target_files else Path.cwd()
202
+ init_result = await lsp.initialize(root_path)
203
+ return init_result and not init_result.get("error")
204
+
205
+ async def _process_files_with_lsp(
206
+ self, lsp: t.Any, target_files: list[Path]
207
+ ) -> list[TypeIssue]:
208
+ """Process files with LSP and collect diagnostics."""
209
+ issues: list[TypeIssue] = []
210
+ for file_path in target_files:
211
+ if file_path.exists():
212
+ file_issues = await self._get_file_diagnostics_from_lsp(lsp, file_path)
213
+ issues.extend(file_issues)
214
+ return issues
215
+
216
+ async def _get_file_diagnostics_from_lsp(
217
+ self, lsp: t.Any, file_path: Path
218
+ ) -> list[TypeIssue]:
219
+ """Get diagnostics for a single file from LSP."""
220
+ await lsp.text_document_did_open(file_path)
221
+ await asyncio.sleep(0.1) # Wait briefly for diagnostics
222
+
223
+ diagnostics = await lsp.get_diagnostics()
224
+ issues = []
225
+
226
+ for diag in diagnostics:
227
+ issue = self._create_type_issue_from_diagnostic(diag, file_path)
228
+ issues.append(issue)
229
+
230
+ await lsp.text_document_did_close(file_path)
231
+ return issues
232
+
233
+ def _create_type_issue_from_diagnostic(
234
+ self, diag: dict[str, t.Any], file_path: Path
235
+ ) -> TypeIssue:
236
+ """Create a TypeIssue from an LSP diagnostic."""
237
+ return TypeIssue(
238
+ file_path=Path(diag.get("uri", str(file_path)).replace("file://", "")),
239
+ line_number=diag.get("range", {}).get("start", {}).get("line", 0) + 1,
240
+ column=diag.get("range", {}).get("start", {}).get("character", 0) + 1,
241
+ message=diag.get("message", "Type error"),
242
+ severity=self._map_lsp_severity(diag.get("severity", 1)),
243
+ error_code=diag.get("code"),
244
+ )
245
+
246
+ def _map_lsp_severity(self, lsp_severity: int) -> str:
247
+ """Map LSP severity codes to string values.
248
+
249
+ Args:
250
+ lsp_severity: LSP severity (1=Error, 2=Warning, 3=Information, 4=Hint)
251
+
252
+ Returns:
253
+ String severity level
254
+ """
255
+ return {1: "error", 2: "warning", 3: "info", 4: "info"}.get(
256
+ lsp_severity, "error"
257
+ )
258
+
259
+ def get_command_args(self, target_files: list[Path]) -> list[str]:
260
+ """Get command arguments for Zuban execution (fallback mode)."""
261
+ args = ["uv", "run", "zuban"]
262
+
263
+ # Mode selection
264
+ if self.mypy_compatibility:
265
+ args.append("mypy") # MyPy-compatible mode
266
+ else:
267
+ args.append("check") # Native Zuban mode
268
+
269
+ # Strictness
270
+ if self.strict_mode:
271
+ args.append("--strict")
272
+
273
+ # Add error codes for better parsing
274
+ args.append("--show-error-codes")
275
+
276
+ # Target files/directories
277
+ if target_files:
278
+ args.extend(str(f) for f in target_files)
279
+ else:
280
+ args.append(".") # Check entire project
281
+
282
+ return args
283
+
284
+ async def check_with_lsp_or_fallback(self, target_files: list[Path]) -> ToolResult:
285
+ """Check files using LSP if available, otherwise fallback to CLI mode.
286
+
287
+ Args:
288
+ target_files: Files to type-check
289
+
290
+ Returns:
291
+ ToolResult with issues found
292
+ """
293
+ # First check if Zuban is functional at all
294
+ if not self.check_tool_health():
295
+ return self._create_error_result(
296
+ "Zuban is not functional due to TOML parsing bug. "
297
+ "Consider using pyright as alternative. "
298
+ "See ZUBAN_TOML_PARSING_BUG_ANALYSIS.md for details."
299
+ )
300
+
301
+ # Try optimized LSP mode first
302
+ if self.use_lsp:
303
+ # Try optimized LSP wrapper first, then fallback to basic LSP client
304
+ lsp_issues = await self.get_lsp_diagnostics_optimized(target_files)
305
+ if not lsp_issues: # If optimized fails, try basic LSP client
306
+ lsp_issues = await self.get_lsp_diagnostics(target_files)
307
+
308
+ if lsp_issues is not None: # LSP succeeded (empty list is valid)
309
+ # Create successful result from LSP
310
+ error_issues = [i for i in lsp_issues if i.severity == "error"]
311
+ success = len(error_issues) == 0
312
+
313
+ result = ToolResult(
314
+ success=success,
315
+ issues=list[Issue](
316
+ lsp_issues
317
+ ), # Convert TypeIssue list to Issue list
318
+ raw_output=f"LSP diagnostics: {len(lsp_issues)} issue(s) found",
319
+ tool_version=self.get_tool_version(),
320
+ )
321
+ # Add execution mode as custom attribute for tracking
322
+ result._execution_mode = "lsp"
323
+ return result
324
+
325
+ # LSP unavailable or failed, fallback to CLI mode
326
+ return await self._run_cli_fallback(target_files)
327
+
328
+ async def _run_cli_fallback(self, target_files: list[Path]) -> ToolResult:
329
+ """Run Zuban in CLI mode as fallback.
330
+
331
+ Args:
332
+ target_files: Files to check
333
+
334
+ Returns:
335
+ ToolResult from CLI execution
336
+ """
337
+ # Use the existing CLI execution logic
338
+ import subprocess
339
+
340
+ try:
341
+ cmd_args = self.get_command_args(target_files)
342
+ result = subprocess.run(
343
+ cmd_args,
344
+ capture_output=True,
345
+ text=True,
346
+ timeout=60,
347
+ cwd=self.context.root_path
348
+ if hasattr(self.context, "root_path")
349
+ else None,
350
+ )
351
+
352
+ # Parse the CLI output using existing methods
353
+ tool_result = self.parse_output(result.stdout + result.stderr)
354
+
355
+ # Mark as CLI mode for tracking
356
+ tool_result._execution_mode = "cli"
357
+
358
+ return tool_result
359
+
360
+ except subprocess.TimeoutExpired:
361
+ return self._create_error_result("Zuban execution timed out")
362
+ except Exception as e:
363
+ return self._create_error_result(f"Zuban execution failed: {e}")
364
+
365
+ def parse_output(self, output: str) -> ToolResult:
366
+ """Parse Zuban output into standardized result."""
367
+ if self._should_use_json_output():
368
+ return self._parse_json_output(output)
369
+ return self._parse_text_output(output)
370
+
371
+ def _parse_json_output(self, output: str) -> ToolResult:
372
+ """Parse JSON output for AI agents."""
373
+ data = self._parse_json_output_safe(output)
374
+ if data is None:
375
+ return self._create_error_result(
376
+ "Invalid JSON output from Zuban", raw_output=output
377
+ )
378
+
379
+ try:
380
+ issues: list[Issue] = []
381
+ for item in data.get("diagnostics", []):
382
+ # Determine severity
383
+ severity = item.get("severity", "error").lower()
384
+ if severity not in ("error", "warning", "info"):
385
+ severity = "error"
386
+
387
+ issues.append(
388
+ TypeIssue(
389
+ file_path=Path(item["file"]),
390
+ line_number=item.get("line", 1),
391
+ column=item.get("column", 1),
392
+ message=item["message"],
393
+ severity=severity,
394
+ error_code=item.get("code"),
395
+ )
396
+ )
397
+
398
+ # Success if no error-level issues
399
+ error_issues = [i for i in issues if i.severity == "error"]
400
+ success = len(error_issues) == 0
401
+
402
+ return ToolResult(
403
+ success=success,
404
+ issues=issues,
405
+ raw_output=output,
406
+ tool_version=self.get_tool_version(),
407
+ )
408
+
409
+ except (KeyError, TypeError, ValueError) as e:
410
+ return self._create_error_result(
411
+ f"Failed to parse Zuban JSON output: {e}", raw_output=output
412
+ )
413
+
414
+ def _parse_text_output(self, output: str) -> ToolResult:
415
+ """Parse text output for human-readable display."""
416
+ issues: list[Issue] = []
417
+
418
+ if not output.strip():
419
+ # No output typically means no type errors found
420
+ return ToolResult(
421
+ success=True,
422
+ issues=[],
423
+ raw_output=output,
424
+ tool_version=self.get_tool_version(),
425
+ )
426
+
427
+ # Parse Zuban/MyPy-style text output
428
+ for line in output.strip().split("\\n"):
429
+ line = line.strip()
430
+ if not line:
431
+ continue
432
+
433
+ issue = self._parse_text_line(line)
434
+ if issue:
435
+ issues.append(issue)
436
+
437
+ # Success if no error-level issues
438
+ error_issues = [i for i in issues if i.severity == "error"]
439
+ success = len(error_issues) == 0
440
+
441
+ return ToolResult(
442
+ success=success,
443
+ issues=issues,
444
+ raw_output=output,
445
+ tool_version=self.get_tool_version(),
446
+ )
447
+
448
+ def _parse_text_line(self, line: str) -> TypeIssue | None:
449
+ """Parse a single line of Zuban text output."""
450
+ try:
451
+ basic_info = self._extract_line_components(line)
452
+ if not basic_info:
453
+ return None
454
+
455
+ file_path, line_number, message_part = basic_info
456
+ column = self._extract_column_number(message_part)
457
+
458
+ message_data = self._parse_message_content(message_part)
459
+ severity = self._normalize_severity(message_data["severity"] or "error")
460
+
461
+ return TypeIssue(
462
+ file_path=file_path,
463
+ line_number=line_number,
464
+ column=column,
465
+ message=message_data["message"] or "Unknown error",
466
+ severity=severity,
467
+ error_code=message_data["error_code"],
468
+ )
469
+
470
+ except (IndexError, ValueError):
471
+ return None
472
+
473
+ def _extract_line_components(self, line: str) -> tuple[Path, int, str] | None:
474
+ """Extract file path, line number, and remaining message from line."""
475
+ if ":" not in line:
476
+ return None
477
+
478
+ parts = line.split(":", 3)
479
+ if len(parts) < 3:
480
+ return None
481
+
482
+ file_path = Path(parts[0].strip())
483
+
484
+ try:
485
+ line_number = int(parts[1].strip())
486
+ except ValueError:
487
+ return None
488
+
489
+ # Handle both 3-part and 4-part formats
490
+ if len(parts) == 4:
491
+ message_part = f"{parts[2]}:{parts[3]}".strip()
492
+ else:
493
+ message_part = parts[2].strip()
494
+
495
+ return file_path, line_number, message_part
496
+
497
+ def _extract_column_number(self, message_part: str) -> int:
498
+ """Extract column number if present in message part."""
499
+ # Try to extract column from the beginning of message_part
500
+ parts = message_part.split(":", 2)
501
+ if len(parts) >= 2:
502
+ with suppress(ValueError):
503
+ return int(parts[0].strip())
504
+ return 1
505
+
506
+ def _parse_message_content(self, message_part: str) -> dict[str, str | None]:
507
+ """Parse message content to extract severity, message, and error code."""
508
+ # Skip column number if present
509
+ parts = message_part.split(":", 2)
510
+ if len(parts) >= 2:
511
+ try:
512
+ int(parts[0].strip()) # Check if first part is column number
513
+ working_message = ":".join(parts[1:]).strip()
514
+ except ValueError:
515
+ working_message = message_part
516
+ else:
517
+ working_message = message_part
518
+
519
+ severity, message = self._extract_severity_and_message(working_message)
520
+ error_code = self._extract_error_code(message)
521
+
522
+ # Remove error code from message if found
523
+ if error_code and "[" in message:
524
+ code_start = message.rfind("[")
525
+ message = message[:code_start].strip()
526
+
527
+ return {"severity": severity, "message": message, "error_code": error_code}
528
+
529
+ def _extract_severity_and_message(self, working_message: str) -> tuple[str, str]:
530
+ """Extract severity indicator and remaining message."""
531
+ severity_indicators = ["error:", "warning:", "note:", "info:"]
532
+
533
+ for indicator in severity_indicators:
534
+ if working_message.lower().startswith(indicator):
535
+ severity = indicator[:-1] # Remove colon
536
+ message = working_message[len(indicator) :].strip()
537
+ return severity, message
538
+
539
+ # Default to error severity
540
+ return "error", working_message
541
+
542
+ def _extract_error_code(self, message: str) -> str | None:
543
+ """Extract error code from message if present."""
544
+ if "[" in message and "]" in message:
545
+ code_start = message.rfind("[")
546
+ code_end = message.rfind("]")
547
+ if code_start < code_end:
548
+ return message[code_start + 1 : code_end]
549
+ return None
550
+
551
+ def _normalize_severity(self, severity: str) -> str:
552
+ """Normalize severity to standard values."""
553
+ if severity in ("note", "info"):
554
+ return "info"
555
+ elif severity not in ("error", "warning"):
556
+ return "error"
557
+ return severity
@@ -0,0 +1,59 @@
1
+ > Crackerjack Docs: [Main](<../../../README.md>) | [Adapters](<../README.md>) | [Refactor](<./README.md>)
2
+
3
+ # Refactor Adapters
4
+
5
+ Modernization and dead-code tooling to simplify code and reduce risk.
6
+
7
+ ## Overview
8
+
9
+ - Suggest idiomatic patterns and cleanups (Refurb)
10
+ - Identify unused dependencies (Creosote)
11
+ - Detect dead code for deletion (Skylos)
12
+
13
+ ## Built-in Implementations
14
+
15
+ | Module | Description | Status |
16
+ | ------ | ----------- | ------ |
17
+ | `refurb.py` | Refactoring suggestions for modern Python idioms | Stable |
18
+ | `creosote.py` | Detects unused dependencies in `pyproject.toml`/`requirements*.txt` | Stable |
19
+ | `skylos.py` | Dead code detection (text/JSON parsing) | Stable |
20
+
21
+ ## Examples
22
+
23
+ Refurb:
24
+
25
+ ```python
26
+ from pathlib import Path
27
+ from crackerjack.adapters.refactor.refurb import RefurbAdapter, RefurbSettings
28
+
29
+
30
+ async def suggest_refactors() -> None:
31
+ adapter = RefurbAdapter(settings=RefurbSettings(explain=True))
32
+ await adapter.init()
33
+ result = await adapter.check(files=[Path("src/")])
34
+ ```
35
+
36
+ Creosote:
37
+
38
+ ```python
39
+ from pathlib import Path
40
+ from crackerjack.adapters.refactor.creosote import CreosoteAdapter, CreosoteSettings
41
+
42
+
43
+ async def find_unused_deps() -> None:
44
+ adapter = CreosoteAdapter(
45
+ settings=CreosoteSettings(config_file=Path("pyproject.toml"))
46
+ )
47
+ await adapter.init()
48
+ result = await adapter.check()
49
+ ```
50
+
51
+ ## Notes
52
+
53
+ - Treat Refurb suggestions as warnings; human review recommended
54
+ - Exclude dev/build tools in Creosote to avoid false positives
55
+
56
+ ## Related
57
+
58
+ - [Complexity](<../complexity/README.md>) — Use complexity reports to target refactors
59
+ - [Format](<../format/README.md>) — Formatting changes often enable simpler refactors
@@ -0,0 +1,12 @@
1
+ """Refactor adapters for code improvement suggestions.
2
+
3
+ Adapters:
4
+ - refurb: Modern Python best practices and idiom suggestions
5
+ - creosote: Unused dependency detection
6
+ - skylos: Dead code detection (unused imports, functions, classes, variables)
7
+ """
8
+
9
+ # ACB will auto-discover these adapters via depends.set() in module files
10
+ # No explicit imports needed here
11
+
12
+ __all__ = []