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,139 @@
1
+ """Check for large files added to git repository.
2
+
3
+ This tool is a native Python implementation replacing pre-commit's
4
+ check-added-large-files hook. It warns about files exceeding a size threshold.
5
+
6
+ Usage:
7
+ python -m crackerjack.tools.check_added_large_files [files...]
8
+
9
+ Exit Codes:
10
+ 0: No large files found
11
+ 1: One or more large files detected
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import argparse
17
+ import sys
18
+ from pathlib import Path
19
+
20
+ from crackerjack.tools._git_utils import get_git_tracked_files
21
+
22
+
23
+ def get_file_size(file_path: Path) -> int:
24
+ """Get file size in bytes.
25
+
26
+ Args:
27
+ file_path: Path to file
28
+
29
+ Returns:
30
+ File size in bytes, or 0 if file doesn't exist
31
+ """
32
+ try:
33
+ return file_path.stat().st_size
34
+ except (FileNotFoundError, OSError):
35
+ return 0
36
+
37
+
38
+ def format_size(size_bytes: int | float) -> str:
39
+ """Format file size in human-readable format.
40
+
41
+ Args:
42
+ size_bytes: Size in bytes
43
+
44
+ Returns:
45
+ Human-readable size string (e.g., "1.5 MB")
46
+ """
47
+ size: float = float(size_bytes)
48
+ for unit in ("B", "KB", "MB", "GB"):
49
+ if size < 1024.0:
50
+ return f"{size:.1f} {unit}"
51
+ size /= 1024.0
52
+ return f"{size:.1f} TB"
53
+
54
+
55
+ def main(argv: list[str] | None = None) -> int:
56
+ """Main entry point for check-added-large-files tool.
57
+
58
+ Args:
59
+ argv: Command-line arguments (defaults to sys.argv[1:])
60
+
61
+ Returns:
62
+ Exit code: 0 if no large files, 1 if large files found
63
+ """
64
+ parser = argparse.ArgumentParser(
65
+ description="Check for large files in git repository"
66
+ )
67
+ parser.add_argument(
68
+ "files",
69
+ nargs="*",
70
+ type=Path,
71
+ help="Files to check (default: all git-tracked files)",
72
+ )
73
+ parser.add_argument(
74
+ "--maxkb",
75
+ type=int,
76
+ default=1000,
77
+ help="Maximum file size in KB (default: 1000)",
78
+ )
79
+ parser.add_argument(
80
+ "--enforce-all",
81
+ action="store_true",
82
+ help="Check all files, not just newly added ones",
83
+ )
84
+
85
+ # When called from tests, avoid picking up pytest argv
86
+ if argv is None:
87
+ argv = []
88
+ args = parser.parse_args(argv)
89
+
90
+ # Convert KB to bytes
91
+ max_size_bytes = args.maxkb * 1024
92
+
93
+ # Determine which files to check
94
+ if not args.files:
95
+ # Get all git-tracked files, respecting gitignore
96
+ files = get_git_tracked_files()
97
+ if not files:
98
+ # Fallback to all files in current directory if not in git repo
99
+ files = list(Path.cwd().rglob("*"))
100
+ files = [f for f in files if f.is_file()]
101
+ else:
102
+ files = args.files
103
+
104
+ # Filter to existing files only
105
+ files = [f for f in files if f.is_file()]
106
+
107
+ if not files:
108
+ print("No files to check") # noqa: T201
109
+ return 0
110
+
111
+ # Process files
112
+ large_files = []
113
+ for file_path in files:
114
+ size = get_file_size(file_path)
115
+ if size > max_size_bytes:
116
+ large_files.append((file_path, size))
117
+
118
+ # Report results
119
+ if large_files:
120
+ print("Large files detected:", file=sys.stderr) # noqa: T201
121
+ for file_path, size in large_files:
122
+ print(
123
+ f" {file_path}: {format_size(size)} "
124
+ f"(exceeds {format_size(max_size_bytes)})",
125
+ file=sys.stderr,
126
+ ) # noqa: T201
127
+ print(
128
+ f"\n{len(large_files)} large file(s) found. "
129
+ f"Consider using Git LFS for large files.",
130
+ file=sys.stderr,
131
+ ) # noqa: T201
132
+ return 1
133
+
134
+ print("All files are under size limit") # noqa: T201
135
+ return 0
136
+
137
+
138
+ if __name__ == "__main__":
139
+ sys.exit(main())
@@ -0,0 +1,105 @@
1
+ """Validate Python file AST syntax.
2
+
3
+ This tool is a native Python implementation replacing pre-commit's
4
+ check-ast hook. It scans Python files and validates their AST syntax.
5
+
6
+ Usage:
7
+ python -m crackerjack.tools.check_ast [files...]
8
+
9
+ Exit Codes:
10
+ 0: All Python files have valid ASTs
11
+ 1: One or more Python files have syntax errors (invalid ASTs)
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import argparse
17
+ import ast
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ from ._git_utils import get_files_by_extension
22
+
23
+
24
+ def validate_ast_file(file_path: Path) -> tuple[bool, str | None]:
25
+ """Validate a Python file's AST syntax.
26
+
27
+ Args:
28
+ file_path: Path to Python file to validate
29
+
30
+ Returns:
31
+ Tuple of (is_valid, error_message)
32
+ - is_valid: True if file has valid Python AST syntax
33
+ - error_message: Error description if is_valid is False, None otherwise
34
+ """
35
+ try:
36
+ with file_path.open(encoding="utf-8") as f:
37
+ content = f.read()
38
+
39
+ # Parse the content into an AST
40
+ ast.parse(content)
41
+ return True, None
42
+ except SyntaxError as e:
43
+ return False, f"Syntax error at line {e.lineno}: {e.msg}"
44
+ except Exception as e:
45
+ return False, f"Error reading file: {e}"
46
+
47
+
48
+ def main(argv: list[str] | None = None) -> int:
49
+ """Main entry point for check-ast tool.
50
+
51
+ Args:
52
+ argv: Command-line arguments (defaults to sys.argv[1:])
53
+
54
+ Returns:
55
+ Exit code: 0 if all Python files have valid ASTs, 1 if any errors found
56
+ """
57
+ parser = argparse.ArgumentParser(description="Validate Python file AST syntax")
58
+ parser.add_argument(
59
+ "files",
60
+ nargs="*",
61
+ type=Path,
62
+ help="Python files to check (default: all .py files)",
63
+ )
64
+
65
+ args = parser.parse_args(argv)
66
+
67
+ # Default to all git-tracked Python files if none specified
68
+ if not args.files:
69
+ # Get all tracked Python files (respects .gitignore via git ls-files)
70
+ files = get_files_by_extension([".py"])
71
+ if not files:
72
+ # Fallback to rglob if not in git repo
73
+ files = list(Path.cwd().rglob("*.py"))
74
+ else:
75
+ files = args.files
76
+
77
+ # Filter to existing files only
78
+ files = [f for f in files if f.is_file()]
79
+
80
+ if not files:
81
+ print("No Python files to check") # noqa: T201
82
+ return 0
83
+
84
+ # Process files
85
+ error_count = 0
86
+ for file_path in files:
87
+ is_valid, error_msg = validate_ast_file(file_path)
88
+
89
+ if not is_valid:
90
+ print(f"✗ {file_path}: {error_msg}", file=sys.stderr) # noqa: T201
91
+ error_count += 1
92
+ else:
93
+ print(f"✓ {file_path}: Valid AST") # noqa: T201
94
+
95
+ # Return appropriate exit code
96
+ if error_count > 0:
97
+ print(f"\n{error_count} Python file(s) with AST errors", file=sys.stderr) # noqa: T201
98
+ return 1
99
+
100
+ print(f"\nAll {len(files)} Python file(s) have valid ASTs") # noqa: T201
101
+ return 0
102
+
103
+
104
+ if __name__ == "__main__":
105
+ sys.exit(main())
@@ -0,0 +1,103 @@
1
+ """Validate JSON file syntax.
2
+
3
+ This tool is a native Python implementation replacing pre-commit's
4
+ check-json hook. It scans JSON files and validates their syntax.
5
+
6
+ Usage:
7
+ python -m crackerjack.tools.check_json [files...]
8
+
9
+ Exit Codes:
10
+ 0: All JSON files are valid
11
+ 1: One or more JSON files have syntax errors
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import argparse
17
+ import json
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ from ._git_utils import get_files_by_extension
22
+
23
+
24
+ def validate_json_file(file_path: Path) -> tuple[bool, str | None]:
25
+ """Validate a JSON file's syntax.
26
+
27
+ Args:
28
+ file_path: Path to JSON file to validate
29
+
30
+ Returns:
31
+ Tuple of (is_valid, error_message)
32
+ - is_valid: True if file has valid JSON syntax
33
+ - error_message: Error description if is_valid is False, None otherwise
34
+ """
35
+ try:
36
+ with file_path.open(encoding="utf-8") as f:
37
+ # Load JSON and validate structure
38
+ json.load(f)
39
+ return True, None
40
+ except json.JSONDecodeError as e:
41
+ return False, str(e)
42
+ except Exception as e:
43
+ return False, f"Error reading file: {e}"
44
+
45
+
46
+ def main(argv: list[str] | None = None) -> int:
47
+ """Main entry point for check-json tool.
48
+
49
+ Args:
50
+ argv: Command-line arguments (defaults to sys.argv[1:])
51
+
52
+ Returns:
53
+ Exit code: 0 if all JSON valid, 1 if any errors found
54
+ """
55
+ parser = argparse.ArgumentParser(description="Validate JSON file syntax")
56
+ parser.add_argument(
57
+ "files",
58
+ nargs="*",
59
+ type=Path,
60
+ help="JSON files to check (default: all .json files)",
61
+ )
62
+
63
+ args = parser.parse_args(argv)
64
+
65
+ # Default to all git-tracked JSON files if none specified
66
+ if not args.files:
67
+ # Get all tracked JSON files (respects .gitignore via git ls-files)
68
+ files = get_files_by_extension([".json"])
69
+ if not files:
70
+ # Fallback to rglob if not in git repo
71
+ files = list(Path.cwd().rglob("*.json"))
72
+ else:
73
+ files = args.files
74
+
75
+ # Filter to existing files only
76
+ files = [f for f in files if f.is_file()]
77
+
78
+ if not files:
79
+ print("No JSON files to check") # noqa: T201
80
+ return 0
81
+
82
+ # Process files
83
+ error_count = 0
84
+ for file_path in files:
85
+ is_valid, error_msg = validate_json_file(file_path)
86
+
87
+ if not is_valid:
88
+ print(f"✗ {file_path}: {error_msg}", file=sys.stderr) # noqa: T201
89
+ error_count += 1
90
+ else:
91
+ print(f"✓ {file_path}: Valid JSON") # noqa: T201
92
+
93
+ # Return appropriate exit code
94
+ if error_count > 0:
95
+ print(f"\n{error_count} JSON file(s) with errors", file=sys.stderr) # noqa: T201
96
+ return 1
97
+
98
+ print(f"\nAll {len(files)} JSON file(s) are valid") # noqa: T201
99
+ return 0
100
+
101
+
102
+ if __name__ == "__main__":
103
+ sys.exit(main())
@@ -0,0 +1,297 @@
1
+ """Validate JSON files against JSON Schema definitions.
2
+
3
+ This tool is a native Python implementation for validating JSON files
4
+ against their corresponding JSON Schema definitions. It automatically
5
+ finds .json files and attempts to validate them against similarly named
6
+ .schema.json or .json files that follow the JSON Schema standard.
7
+
8
+ Usage:
9
+ python -m crackerjack.tools.check_jsonschema [files...]
10
+
11
+ Exit Codes:
12
+ 0: All JSON files are valid against their schemas
13
+ 1: One or more JSON files fail schema validation
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import argparse
19
+ import json
20
+ import sys
21
+ import typing as t
22
+ from pathlib import Path
23
+
24
+ from ._git_utils import get_files_by_extension
25
+
26
+ if t.TYPE_CHECKING:
27
+ pass
28
+
29
+
30
+ def _check_filename_pattern_schema(json_file: Path) -> Path | None:
31
+ """Check for {name}.schema.json pattern."""
32
+ schema_path = json_file.with_name(f"{json_file.stem}.schema.json")
33
+ if schema_path.is_file():
34
+ return schema_path
35
+ return None
36
+
37
+
38
+ def _resolve_local_schema_path(json_file: Path, schema_ref: str) -> Path | None:
39
+ """Resolve a local schema file path.
40
+
41
+ Args:
42
+ json_file: The JSON file containing the schema reference
43
+ schema_ref: The schema reference string
44
+
45
+ Returns:
46
+ Path to schema file if found, None otherwise
47
+ """
48
+ if schema_ref.endswith((".json", ".schema.json")):
49
+ schema_path = json_file.parent / schema_ref
50
+ if schema_path.is_file():
51
+ return schema_path
52
+ return None
53
+
54
+
55
+ def _check_internal_schema_ref(json_file: Path) -> Path | None:
56
+ """Try to find a schema reference inside the JSON file."""
57
+ try:
58
+ with json_file.open(encoding="utf-8") as f:
59
+ data = json.load(f)
60
+
61
+ if isinstance(data, dict):
62
+ schema_ref = data.get("$schema")
63
+ if schema_ref and isinstance(schema_ref, str):
64
+ return _resolve_local_schema_path(json_file, schema_ref)
65
+ except (OSError, json.JSONDecodeError):
66
+ pass
67
+ return None
68
+
69
+
70
+ def _check_same_dir_schema(json_file: Path) -> Path | None:
71
+ """Try schema.json in the same directory."""
72
+ schema_path = json_file.with_name("schema.json")
73
+ if schema_path.is_file():
74
+ return schema_path
75
+ return None
76
+
77
+
78
+ def _check_parent_dir_schemas(json_file: Path) -> Path | None:
79
+ """Try finding schema.json in parent directories (up to 3 levels)."""
80
+ current_dir = json_file.parent
81
+ for _ in range(3):
82
+ schema_path = current_dir / "schema.json"
83
+ if schema_path.is_file():
84
+ return schema_path
85
+ if current_dir.parent == current_dir: # reached root
86
+ break
87
+ current_dir = current_dir.parent
88
+ return None
89
+
90
+
91
+ def find_schema_for_json(json_file: Path) -> Path | None:
92
+ """Find the corresponding schema file for a JSON file.
93
+
94
+ Looks for schema files in common patterns:
95
+ - {name}.schema.json
96
+ - {name}.json (if it contains $schema reference)
97
+ - schema.json in the same directory
98
+ - schema.json in parent directories
99
+
100
+ Args:
101
+ json_file: Path to the JSON file to validate
102
+
103
+ Returns:
104
+ Path to schema file, or None if not found
105
+ """
106
+ # Try {name}.schema.json pattern
107
+ result = _check_filename_pattern_schema(json_file)
108
+ if result:
109
+ return result
110
+
111
+ # Try to find a schema reference inside the JSON file
112
+ result = _check_internal_schema_ref(json_file)
113
+ if result:
114
+ return result
115
+
116
+ # Try schema.json in the same directory
117
+ result = _check_same_dir_schema(json_file)
118
+ if result:
119
+ return result
120
+
121
+ # Try finding schema.json in parent directories (up to 3 levels)
122
+ return _check_parent_dir_schemas(json_file)
123
+
124
+
125
+ def load_schema(schema_path: Path) -> dict[str, t.Any] | None:
126
+ """Load a JSON schema from file.
127
+
128
+ Args:
129
+ schema_path: Path to the schema file
130
+
131
+ Returns:
132
+ Schema as dictionary, or None if loading fails
133
+ """
134
+ try:
135
+ with schema_path.open(encoding="utf-8") as f:
136
+ schema = json.load(f)
137
+
138
+ # Basic validation that this looks like a schema
139
+ if not isinstance(schema, dict):
140
+ return None
141
+
142
+ return schema
143
+ except (OSError, json.JSONDecodeError) as e:
144
+ print(f"Could not load schema {schema_path}: {e}", file=sys.stderr) # noqa: T201
145
+ return None
146
+
147
+
148
+ def validate_json_against_schema(
149
+ json_file: Path, schema_path: Path
150
+ ) -> tuple[bool, str | None]:
151
+ """Validate a JSON file against a schema.
152
+
153
+ Args:
154
+ json_file: Path to the JSON file to validate
155
+ schema_path: Path to the schema file
156
+
157
+ Returns:
158
+ Tuple of (is_valid, error_message)
159
+ - is_valid: True if file validates against schema
160
+ - error_message: Error description if is_valid is False, None otherwise
161
+ """
162
+ try:
163
+ # Load schema
164
+ schema = load_schema(schema_path)
165
+ if not schema:
166
+ return False, f"Could not load schema: {schema_path}"
167
+
168
+ # Load JSON data
169
+ with json_file.open(encoding="utf-8") as f:
170
+ data = json.load(f)
171
+
172
+ # Import jsonschema only when needed to avoid dependency issues
173
+ import jsonschema
174
+
175
+ # Validate the data against the schema
176
+ validator_class = jsonschema.Draft7Validator
177
+ if hasattr(validator_class, "check_schema"):
178
+ # Validate the schema itself first
179
+ validator_class.check_schema(schema)
180
+
181
+ validator = validator_class(schema)
182
+ errors = list(validator.iter_errors(data))
183
+
184
+ if errors:
185
+ error_messages = [
186
+ f" {error.message}" for error in errors[:5]
187
+ ] # Limit to first 5 errors
188
+ if len(errors) > 5:
189
+ error_messages.append(f" ... and {len(errors) - 5} more errors")
190
+ return False, "Schema validation failed:\n" + "\n".join(error_messages)
191
+
192
+ return True, None
193
+
194
+ except ImportError:
195
+ return (
196
+ False,
197
+ "jsonschema library not available. Install with: pip install jsonschema",
198
+ )
199
+ except jsonschema.SchemaError as e:
200
+ return False, f"Invalid schema: {e}"
201
+ except json.JSONDecodeError as e:
202
+ return False, f"Invalid JSON in file: {e}"
203
+ except Exception as e:
204
+ return False, f"Validation error: {e}"
205
+
206
+
207
+ def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
208
+ """Parse command-line arguments."""
209
+ parser = argparse.ArgumentParser(
210
+ description="Validate JSON files against JSON Schema definitions"
211
+ )
212
+ parser.add_argument(
213
+ "files",
214
+ nargs="*",
215
+ type=Path,
216
+ help="JSON files to validate against schemas (default: all .json files)",
217
+ )
218
+ parser.add_argument(
219
+ "--strict",
220
+ action="store_true",
221
+ help="Fail if no schema is found for a JSON file",
222
+ )
223
+
224
+ return parser.parse_args(argv)
225
+
226
+
227
+ def _get_json_files(args: argparse.Namespace) -> list[Path]:
228
+ """Get list of JSON files to validate."""
229
+ if not args.files:
230
+ # Get all tracked JSON files (respects .gitignore via git ls-files)
231
+ files = get_files_by_extension([".json"])
232
+ if not files:
233
+ # Fallback to rglob if not in git repo
234
+ files = list(Path.cwd().rglob("*.json"))
235
+ else:
236
+ files = args.files
237
+
238
+ # Filter to existing files only
239
+ return [f for f in files if f.is_file()]
240
+
241
+
242
+ def _process_file(file_path: Path, schema_path: Path | None, strict: bool) -> int:
243
+ """Process a single file and return error count increment."""
244
+ if not schema_path:
245
+ if strict:
246
+ print(f"✗ {file_path}: No schema found", file=sys.stderr) # noqa: T201
247
+ return 1
248
+ else:
249
+ print(f"→ {file_path}: No schema found, skipping validation") # noqa: T201
250
+ return 0
251
+
252
+ is_valid, error_msg = validate_json_against_schema(file_path, schema_path)
253
+
254
+ if not is_valid:
255
+ print(f"✗ {file_path}: {error_msg}", file=sys.stderr) # noqa: T201
256
+ return 1
257
+ else:
258
+ print(f"✓ {file_path}: Valid against {schema_path.name}") # noqa: T201
259
+ return 0
260
+
261
+
262
+ def main(argv: list[str] | None = None) -> int:
263
+ """Main entry point for check-jsonschema tool.
264
+
265
+ Args:
266
+ argv: Command-line arguments (defaults to sys.argv[1:])
267
+
268
+ Returns:
269
+ Exit code: 0 if all JSON files validate against schemas, 1 if any errors found
270
+ """
271
+ args = _parse_args(argv)
272
+
273
+ files = _get_json_files(args)
274
+
275
+ if not files:
276
+ print("No JSON files to validate") # noqa: T201
277
+ return 0
278
+
279
+ # Process files
280
+ error_count = 0
281
+ for file_path in files:
282
+ schema_path = find_schema_for_json(file_path)
283
+ error_count += _process_file(file_path, schema_path, args.strict)
284
+
285
+ # Return appropriate exit code
286
+ if error_count > 0:
287
+ print(f"\n{error_count} JSON file(s) failed schema validation", file=sys.stderr) # noqa: T201
288
+ return 1
289
+
290
+ print(
291
+ f"\nAll {len([f for f in files if find_schema_for_json(f)])} JSON file(s) passed schema validation"
292
+ ) # noqa: T201
293
+ return 0
294
+
295
+
296
+ if __name__ == "__main__":
297
+ sys.exit(main())