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,58 @@
1
+ """Shared utilities for error handling decorators."""
2
+
3
+ import asyncio
4
+ import inspect
5
+ import typing as t
6
+ from functools import wraps
7
+
8
+ F = t.TypeVar("F", bound=t.Callable[..., t.Any])
9
+
10
+
11
+ def is_async_function(func: t.Callable[..., t.Any]) -> bool:
12
+ """Check if a function is async."""
13
+ return asyncio.iscoroutinefunction(func)
14
+
15
+
16
+ def preserve_signature[F: t.Callable[..., t.Any]](
17
+ wrapper: F,
18
+ ) -> t.Callable[[t.Callable[..., t.Any]], F]:
19
+ """Preserve function signature in decorators."""
20
+
21
+ def decorator(func: t.Callable[..., t.Any]) -> F:
22
+ wrapped = wraps(func)(wrapper)
23
+ # Preserve signature metadata
24
+ wrapped.__wrapped__ = func # type: ignore[attr-defined]
25
+ return t.cast(F, wrapped)
26
+
27
+ return decorator
28
+
29
+
30
+ def get_function_context(func: t.Callable[..., t.Any]) -> dict[str, t.Any]:
31
+ """Extract context information from a function for error reporting."""
32
+ return {
33
+ "function_name": func.__name__,
34
+ "module": func.__module__,
35
+ "qualname": func.__qualname__,
36
+ "is_async": is_async_function(func),
37
+ }
38
+
39
+
40
+ def format_exception_chain(exc: BaseException) -> list[str]:
41
+ """Format exception chain for logging."""
42
+ chain: list[str] = []
43
+ current: BaseException | None = exc
44
+
45
+ while current is not None:
46
+ chain.append(f"{type(current).__name__}: {current}")
47
+ current = current.__cause__ or current.__context__
48
+
49
+ return chain
50
+
51
+
52
+ def get_callable_params(func: t.Callable[..., t.Any]) -> list[inspect.Parameter]:
53
+ """Get function parameters using inspect."""
54
+ try:
55
+ sig = inspect.signature(func)
56
+ return list(sig.parameters.values())
57
+ except (ValueError, TypeError):
58
+ return []
@@ -0,0 +1,11 @@
1
+ > Crackerjack Docs: [Main](<../../README.md>) | [Crackerjack Package](<../README.md>) | [Docs](<./README.md>)
2
+
3
+ # Package Docs
4
+
5
+ Internal/generated documentation assets related to the package.
6
+
7
+ ## Related
8
+
9
+ - [Crackerjack Package](<../README.md>) - Parent package
10
+ - [Documentation](<../documentation/README.md>) - Documentation helpers and build utilities
11
+ - [Data](<../data/README.md>) - Static data and assets
@@ -83,7 +83,7 @@ This document describes all command-line options and usage patterns.
83
83
  - `--dev` (bool):
84
84
  - `--dashboard` (bool):
85
85
  - `--max_iterations` (int):
86
- - `--enterprise_batch` (str | None):
86
+ - `--advanced_batch` (str | None):
87
87
  - `--monitor_dashboard` (str | None):
88
88
  - `--coverage_status` (bool):
89
89
  - `--coverage_goal` (float | None):
@@ -0,0 +1,11 @@
1
+ > Crackerjack Docs: [Main](<../../README.md>) | [Crackerjack Package](<../README.md>) | [Documentation](<./README.md>)
2
+
3
+ # Documentation Helpers
4
+
5
+ Documentation helpers and build-time utilities used by the package.
6
+
7
+ ## Related
8
+
9
+ - [Crackerjack Package](<../README.md>) - Parent package
10
+ - [Docs](<../docs/README.md>) - Generated documentation assets
11
+ - [Agents](<../agents/README.md>) - AI agents including DocumentationAgent
@@ -523,7 +523,7 @@ class AITemplateEngine:
523
523
  command_pattern = SAFE_PATTERNS[
524
524
  "extract_bash_command_blocks"
525
525
  ]._get_compiled_pattern()
526
- return command_pattern.sub(enhance_command_block, content) # type: ignore[no-any-return]
526
+ return command_pattern.sub(enhance_command_block, content)
527
527
 
528
528
  def _optimize_for_step_by_step(self, content: str, context: TemplateContext) -> str:
529
529
  """Optimize content for step-by-step processing.
@@ -8,7 +8,8 @@ from datetime import datetime
8
8
  from pathlib import Path
9
9
 
10
10
  import yaml
11
- from rich.console import Console
11
+ from acb import console as acb_console
12
+ from acb.console import Console
12
13
 
13
14
  from crackerjack.agents.coordinator import AgentCoordinator
14
15
  from crackerjack.services.cache import CrackerjackCache
@@ -60,7 +61,7 @@ class DualOutputGenerator:
60
61
  cache: CrackerjackCache | None = None,
61
62
  ):
62
63
  self.project_path = project_path or Path.cwd()
63
- self.console = console or Console()
64
+ self.console = console or acb_console
64
65
  self.cache = cache or CrackerjackCache()
65
66
 
66
67
  # Documentation paths
@@ -122,7 +123,7 @@ class DualOutputGenerator:
122
123
  async def _generate_ai_reference(self) -> str:
123
124
  """Generate AI-REFERENCE.md with command decision trees and lookup tables."""
124
125
 
125
- self.console.print("🤖 Generating AI reference documentation...")
126
+ self.console.print("🤖 Generating AI reference documentation")
126
127
 
127
128
  # Get current command structure
128
129
  from crackerjack.cli.options import CLI_OPTIONS
@@ -193,7 +194,7 @@ Generated by crackerjack documentation system v{self._get_version()}
193
194
  async def _generate_agent_capabilities(self) -> dict[str, t.Any]:
194
195
  """Generate AGENT-CAPABILITIES.json with structured agent data."""
195
196
 
196
- self.console.print("🎯 Generating agent capabilities data...")
197
+ self.console.print("🎯 Generating agent capabilities data")
197
198
 
198
199
  # Initialize agent coordinator to get current agents
199
200
  from crackerjack.agents.base import AgentContext
@@ -247,7 +248,7 @@ Generated by crackerjack documentation system v{self._get_version()}
247
248
  async def _generate_error_patterns(self) -> dict[str, t.Any]:
248
249
  """Generate ERROR-PATTERNS.yaml with automated error resolution patterns."""
249
250
 
250
- self.console.print("🔍 Generating error patterns documentation...")
251
+ self.console.print("🔍 Generating error patterns documentation")
251
252
 
252
253
  # Analyze existing error patterns and common fixes
253
254
  patterns = {
@@ -279,7 +280,7 @@ Generated by crackerjack documentation system v{self._get_version()}
279
280
  async def _generate_readme_enhancements(self) -> str:
280
281
  """Generate enhanced README.md sections with improved human readability."""
281
282
 
282
- self.console.print("📖 Generating README enhancements...")
283
+ self.console.print("📖 Generating README enhancements")
283
284
 
284
285
  # Read current README if it exists
285
286
  if self.readme_path.exists():
@@ -692,7 +693,8 @@ graph TD
692
693
  return True
693
694
 
694
695
  # Check if source files are newer than generated docs
695
- source_paths = list[t.Any](Path("crackerjack").rglob("*.py"))
696
+ # Use project_path to find source files instead of hardcoded "crackerjack"
697
+ source_paths = list[t.Any](self.project_path.rglob("*.py"))
696
698
  if not source_paths:
697
699
  return True
698
700
 
@@ -703,7 +705,7 @@ graph TD
703
705
  if p.exists()
704
706
  )
705
707
 
706
- return latest_source > oldest_doc # type: ignore[no-any-return]
708
+ return latest_source > oldest_doc
707
709
 
708
710
  async def _write_documentation_files(self, result: DocumentationResult) -> None:
709
711
  """Write generated documentation to files."""
@@ -758,7 +760,7 @@ graph TD
758
760
  def _get_version(self) -> str:
759
761
  """Get crackerjack version."""
760
762
  try:
761
- from crackerjack.cli.utils import get_package_version
763
+ from crackerjack.cli.version import get_package_version
762
764
 
763
765
  return get_package_version()
764
766
  except Exception:
@@ -485,44 +485,74 @@ class ReferenceGenerator:
485
485
  Returns:
486
486
  Enhanced commands with workflow info
487
487
  """
488
- # Define common workflow patterns
489
- workflow_patterns = {
488
+ workflow_patterns = self._get_workflow_patterns()
489
+
490
+ for command in commands.values():
491
+ self._assign_command_workflows(command, workflow_patterns)
492
+ self._add_ai_context_to_command(command)
493
+
494
+ return commands
495
+
496
+ def _get_workflow_patterns(self) -> dict[str, list[str]]:
497
+ """Get workflow patterns for command categorization.
498
+
499
+ Returns:
500
+ Dictionary mapping workflow names to pattern lists
501
+ """
502
+ return {
490
503
  "development": ["test", "format", "lint", "type-check"],
491
504
  "release": ["version", "build", "publish", "tag"],
492
505
  "maintenance": ["clean", "update", "optimize", "backup"],
493
506
  "monitoring": ["status", "health", "metrics", "logs"],
494
507
  }
495
508
 
496
- for command in commands.values():
497
- # Assign workflows based on command name patterns
498
- for workflow, patterns in workflow_patterns.items():
499
- if any(pattern in command.name for pattern in patterns):
500
- command.common_workflows.append(workflow)
501
-
502
- # Add AI context based on command purpose
503
- if "test" in command.name:
504
- command.ai_context.update(
505
- {
506
- "purpose": "quality_assurance",
507
- "automation_level": "high",
508
- "ai_agent_compatible": True,
509
- }
510
- )
511
- command.success_patterns.append("All tests passed")
512
- command.failure_patterns.append("Test failures detected")
513
-
514
- elif "format" in command.name or "lint" in command.name:
515
- command.ai_context.update(
516
- {
517
- "purpose": "code_quality",
518
- "automation_level": "high",
519
- "ai_agent_compatible": True,
520
- }
521
- )
522
- command.success_patterns.append("No formatting issues")
523
- command.failure_patterns.append("Style violations found")
509
+ def _assign_command_workflows(
510
+ self, command: CommandInfo, workflow_patterns: dict[str, list[str]]
511
+ ) -> None:
512
+ """Assign workflows to a command based on name patterns.
524
513
 
525
- return commands
514
+ Args:
515
+ command: Command to assign workflows to
516
+ workflow_patterns: Workflow patterns to match against
517
+ """
518
+ for workflow, patterns in workflow_patterns.items():
519
+ if any(pattern in command.name for pattern in patterns):
520
+ command.common_workflows.append(workflow)
521
+
522
+ def _add_ai_context_to_command(self, command: CommandInfo) -> None:
523
+ """Add AI context to a command based on its purpose.
524
+
525
+ Args:
526
+ command: Command to enhance with AI context
527
+ """
528
+ if "test" in command.name:
529
+ self._add_test_ai_context(command)
530
+ elif "format" in command.name or "lint" in command.name:
531
+ self._add_quality_ai_context(command)
532
+
533
+ def _add_test_ai_context(self, command: CommandInfo) -> None:
534
+ """Add AI context for test-related commands."""
535
+ command.ai_context.update(
536
+ {
537
+ "purpose": "quality_assurance",
538
+ "automation_level": "high",
539
+ "ai_agent_compatible": True,
540
+ }
541
+ )
542
+ command.success_patterns.append("All tests passed")
543
+ command.failure_patterns.append("Test failures detected")
544
+
545
+ def _add_quality_ai_context(self, command: CommandInfo) -> None:
546
+ """Add AI context for code quality commands."""
547
+ command.ai_context.update(
548
+ {
549
+ "purpose": "code_quality",
550
+ "automation_level": "high",
551
+ "ai_agent_compatible": True,
552
+ }
553
+ )
554
+ command.success_patterns.append("No formatting issues")
555
+ command.failure_patterns.append("Style violations found")
526
556
 
527
557
  def _categorize_commands(
528
558
  self, commands: dict[str, CommandInfo]
@@ -536,8 +566,18 @@ class ReferenceGenerator:
536
566
  Dictionary of category to command names
537
567
  """
538
568
  categories: dict[str, list[str]] = {}
569
+ category_patterns = self._get_category_patterns()
570
+
571
+ for command in commands.values():
572
+ category = self._determine_command_category(command, category_patterns)
573
+ command.category = category
574
+ self._add_command_to_category(categories, category, command.name)
575
+
576
+ return categories
539
577
 
540
- category_patterns = {
578
+ def _get_category_patterns(self) -> dict[str, list[str]]:
579
+ """Get category patterns for command classification."""
580
+ return {
541
581
  "development": ["test", "format", "lint", "check", "run"],
542
582
  "server": ["server", "start", "stop", "restart", "monitor"],
543
583
  "release": ["version", "bump", "publish", "build", "tag"],
@@ -545,27 +585,22 @@ class ReferenceGenerator:
545
585
  "utilities": ["clean", "help", "info", "status"],
546
586
  }
547
587
 
548
- for command in commands.values():
549
- assigned = False
550
-
551
- # Assign based on patterns
552
- for category, patterns in category_patterns.items():
553
- if any(pattern in command.name for pattern in patterns):
554
- command.category = category
555
- if category not in categories:
556
- categories[category] = []
557
- categories[category].append(command.name)
558
- assigned = True
559
- break
560
-
561
- # Default category
562
- if not assigned:
563
- command.category = "general"
564
- if "general" not in categories:
565
- categories["general"] = []
566
- categories["general"].append(command.name)
567
-
568
- return categories
588
+ def _determine_command_category(
589
+ self, command: CommandInfo, category_patterns: dict[str, list[str]]
590
+ ) -> str:
591
+ """Determine the category for a command based on patterns."""
592
+ for category, patterns in category_patterns.items():
593
+ if any(pattern in command.name for pattern in patterns):
594
+ return category
595
+ return "general"
596
+
597
+ def _add_command_to_category(
598
+ self, categories: dict[str, list[str]], category: str, command_name: str
599
+ ) -> None:
600
+ """Add command to the specified category."""
601
+ if category not in categories:
602
+ categories[category] = []
603
+ categories[category].append(command_name)
569
604
 
570
605
  def _generate_workflows(
571
606
  self, commands: dict[str, CommandInfo]
@@ -663,7 +698,9 @@ class ReferenceGenerator:
663
698
  """Render command categories for markdown."""
664
699
  category_lines = []
665
700
  for category, command_names in reference.categories.items():
666
- category_section = self._render_markdown_category(category, reference.commands, command_names)
701
+ category_section = self._render_markdown_category(
702
+ category, reference.commands, command_names
703
+ )
667
704
  category_lines.extend(category_section)
668
705
  return category_lines
669
706
 
@@ -733,7 +770,9 @@ class ReferenceGenerator:
733
770
 
734
771
  # Add related commands section
735
772
  if command.related_commands:
736
- related_lines = self._render_command_related_markdown(command.related_commands)
773
+ related_lines = self._render_command_related_markdown(
774
+ command.related_commands
775
+ )
737
776
  lines.extend(related_lines)
738
777
 
739
778
  return lines
@@ -813,9 +852,11 @@ class ReferenceGenerator:
813
852
  def _render_html(self, reference: CommandReference) -> str:
814
853
  """Render reference as HTML."""
815
854
  html_parts = [
816
- self._render_html_header(reference.generated_at.strftime("%Y-%m-%d %H:%M:%S")),
855
+ self._render_html_header(
856
+ reference.generated_at.strftime("%Y-%m-%d %H:%M:%S")
857
+ ),
817
858
  self._render_html_commands(reference),
818
- "</body></html>"
859
+ "</body></html>",
819
860
  ]
820
861
  return "".join(html_parts)
821
862
 
@@ -842,7 +883,9 @@ class ReferenceGenerator:
842
883
  """Render HTML commands by category."""
843
884
  html_parts = []
844
885
  for category, command_names in reference.categories.items():
845
- category_html = self._render_html_category(category, reference.commands, command_names)
886
+ category_html = self._render_html_category(
887
+ category, reference.commands, command_names
888
+ )
846
889
  html_parts.append(category_html)
847
890
  return "".join(html_parts)
848
891
 
@@ -918,7 +961,9 @@ class ReferenceGenerator:
918
961
  "aliases": command.aliases,
919
962
  }
920
963
 
921
- def _serialize_parameters(self, parameters: list[ParameterInfo]) -> list[dict[str, t.Any]]:
964
+ def _serialize_parameters(
965
+ self, parameters: list[ParameterInfo]
966
+ ) -> list[dict[str, t.Any]]:
922
967
  """Serialize parameters for JSON output."""
923
968
  return [self._serialize_parameter(param) for param in parameters]
924
969
 
@@ -148,7 +148,7 @@ HOOKS_REGISTRY: dict[str, list[HookMetadata]] = {
148
148
  "id": "uv-lock",
149
149
  "name": None,
150
150
  "repo": "https://github.com/astral-sh/uv-pre-commit",
151
- "rev": "0.8.15",
151
+ "rev": "0.9.0",
152
152
  "tier": 1,
153
153
  "time_estimate": 0.5,
154
154
  "stages": None,
@@ -174,7 +174,7 @@ HOOKS_REGISTRY: dict[str, list[HookMetadata]] = {
174
174
  "stages": None,
175
175
  "args": None,
176
176
  "files": None,
177
- "exclude": r"uv\.lock|pyproject\.toml|tests/.*|docs/.*|.*\.md",
177
+ "exclude": r"uv\.lock|pyproject\.toml|tests/.*|docs/.*|\.claude/.*|.*\.md",
178
178
  "additional_dependencies": None,
179
179
  "types_or": None,
180
180
  "language": None,
@@ -192,7 +192,7 @@ HOOKS_REGISTRY: dict[str, list[HookMetadata]] = {
192
192
  "stages": ["pre-push", "manual"],
193
193
  "args": ["-c", "pyproject.toml", "-r", "-ll"],
194
194
  "files": "^crackerjack/.*\\.py$",
195
- "exclude": None,
195
+ "exclude": r"^tests/",
196
196
  "additional_dependencies": None,
197
197
  "types_or": None,
198
198
  "language": None,
@@ -224,7 +224,7 @@ HOOKS_REGISTRY: dict[str, list[HookMetadata]] = {
224
224
  "id": "ruff-check",
225
225
  "name": None,
226
226
  "repo": "https://github.com/astral-sh/ruff-pre-commit",
227
- "rev": "v0.12.12",
227
+ "rev": "v0.14.0",
228
228
  "tier": 2,
229
229
  "time_estimate": 1.5,
230
230
  "stages": None,
@@ -242,7 +242,7 @@ HOOKS_REGISTRY: dict[str, list[HookMetadata]] = {
242
242
  "id": "ruff-format",
243
243
  "name": None,
244
244
  "repo": "https://github.com/astral-sh/ruff-pre-commit",
245
- "rev": "v0.12.12",
245
+ "rev": "v0.14.0",
246
246
  "tier": 2,
247
247
  "time_estimate": 1.0,
248
248
  "stages": None,
@@ -284,9 +284,9 @@ HOOKS_REGISTRY: dict[str, list[HookMetadata]] = {
284
284
  "tier": 3,
285
285
  "time_estimate": 0.1,
286
286
  "stages": ["pre-push", "manual"],
287
- "args": ["crackerjack"],
287
+ "args": ["crackerjack", "--exclude", "tests"],
288
288
  "files": None,
289
- "exclude": None,
289
+ "exclude": r"^tests/",
290
290
  "additional_dependencies": None,
291
291
  "types_or": None,
292
292
  "language": "system",
@@ -334,13 +334,13 @@ HOOKS_REGISTRY: dict[str, list[HookMetadata]] = {
334
334
  "id": "refurb",
335
335
  "name": None,
336
336
  "repo": "https://github.com/dosisod/refurb",
337
- "rev": "v2.1.0",
337
+ "rev": "v2.2.0",
338
338
  "tier": 3,
339
339
  "time_estimate": 3.0,
340
340
  "stages": ["pre-push", "manual"],
341
- "args": ["--ignore", "FURB184", "--ignore", "FURB120"],
341
+ "args": [],
342
342
  "files": "^crackerjack/.*\\.py$",
343
- "exclude": r"^tests/.*\.py$",
343
+ "exclude": r"^tests/",
344
344
  "additional_dependencies": None,
345
345
  "types_or": None,
346
346
  "language": None,
@@ -358,7 +358,7 @@ HOOKS_REGISTRY: dict[str, list[HookMetadata]] = {
358
358
  "stages": ["pre-push", "manual"],
359
359
  "args": ["--config-file", "mypy.ini", "./crackerjack"],
360
360
  "files": None,
361
- "exclude": None,
361
+ "exclude": r"^tests/",
362
362
  "additional_dependencies": None,
363
363
  "types_or": None,
364
364
  "language": "system",
@@ -366,24 +366,6 @@ HOOKS_REGISTRY: dict[str, list[HookMetadata]] = {
366
366
  "experimental": False,
367
367
  "pass_filenames": False,
368
368
  },
369
- {
370
- "id": "pyright",
371
- "name": "pyright-type-checking",
372
- "repo": "local",
373
- "rev": "",
374
- "tier": 3,
375
- "time_estimate": 0.25,
376
- "stages": ["pre-push", "manual"],
377
- "args": [],
378
- "files": "^crackerjack/.*\\.py$",
379
- "exclude": r"^crackerjack/(mcp|plugins)/.*\.py$|crackerjack/code_cleaner\.py$",
380
- "additional_dependencies": None,
381
- "types_or": None,
382
- "language": "system",
383
- "entry": "uv run pyright",
384
- "experimental": False,
385
- "pass_filenames": None,
386
- },
387
369
  ],
388
370
  "experimental": [],
389
371
  }
@@ -465,19 +447,15 @@ class DynamicConfigGenerator:
465
447
  )
466
448
 
467
449
  def _sanitize_package_directory(self, package_directory: str) -> str:
468
- """Convert hyphens to underscores in package directory names."""
469
450
  return package_directory.replace("-", "_")
470
451
 
471
452
  def _detect_package_directory(self) -> str:
472
- """Detect the package directory name for the current project."""
473
453
  from pathlib import Path
474
454
 
475
- # Check if we're in the crackerjack project itself
476
455
  current_dir = Path.cwd()
477
456
  if (current_dir / "crackerjack").exists() and (
478
457
  current_dir / "pyproject.toml"
479
458
  ).exists():
480
- # Check if this is actually the crackerjack project
481
459
  with suppress(Exception):
482
460
  import tomllib
483
461
 
@@ -486,7 +464,6 @@ class DynamicConfigGenerator:
486
464
  if data.get("project", {}).get("name") == "crackerjack":
487
465
  return "crackerjack"
488
466
 
489
- # Try to read package name from pyproject.toml
490
467
  pyproject_path = current_dir / "pyproject.toml"
491
468
  if pyproject_path.exists():
492
469
  with suppress(Exception):
@@ -497,15 +474,13 @@ class DynamicConfigGenerator:
497
474
 
498
475
  if "project" in data and "name" in data["project"]:
499
476
  package_name = str(data["project"]["name"])
500
- # Check if package directory exists
477
+
501
478
  if (current_dir / package_name).exists():
502
479
  return package_name
503
480
 
504
- # Fallback to project directory name
505
481
  if (current_dir / current_dir.name).exists():
506
482
  return current_dir.name
507
483
 
508
- # Default fallback to current directory name
509
484
  return current_dir.name
510
485
 
511
486
  def _should_include_hook(
@@ -534,45 +509,55 @@ class DynamicConfigGenerator:
534
509
  for category_hooks in HOOKS_REGISTRY.values():
535
510
  for hook in category_hooks:
536
511
  if self._should_include_hook(hook, config, enabled_experimental):
537
- # Create a copy and update package-specific configurations
538
512
  updated_hook = self._update_hook_for_package(hook.copy())
539
513
  filtered_hooks.append(updated_hook)
540
514
 
541
515
  return filtered_hooks
542
516
 
543
517
  def _update_hook_for_package(self, hook: HookMetadata) -> HookMetadata:
544
- """Update hook configuration to use the detected package directory."""
545
- # Update skylos hook
546
- if hook["id"] == "skylos" and hook["args"]:
547
- hook["args"] = [self.package_directory]
518
+ """Update hook configuration for custom package directory."""
519
+ hook = self._update_hook_args(hook)
520
+ hook = self._update_hook_paths(hook)
521
+ hook = self._update_hook_excludes(hook)
522
+ return hook
548
523
 
549
- # Update zuban hook
524
+ def _update_hook_args(self, hook: HookMetadata) -> HookMetadata:
525
+ """Update hook arguments for specific tools."""
526
+ if hook["id"] == "skylos" and hook["args"]:
527
+ hook["args"] = [self.package_directory, "--exclude", "tests"]
550
528
  elif hook["id"] == "zuban" and hook["args"]:
551
- # Replace the hardcoded "./crackerjack" with the dynamic package directory
552
- updated_args = []
553
- for arg in hook["args"]:
554
- if arg == "./crackerjack":
555
- updated_args.append(f"./{self.package_directory}")
556
- else:
557
- updated_args.append(arg)
558
- hook["args"] = updated_args
559
-
560
- # Update other hooks that use hardcoded "crackerjack" patterns
561
- elif hook["files"] and "crackerjack" in hook["files"]:
562
- hook["files"] = hook["files"].replace("crackerjack", self.package_directory)
529
+ hook["args"] = [
530
+ f"./{self.package_directory}" if arg == "./crackerjack" else arg
531
+ for arg in hook["args"]
532
+ ]
533
+ return hook
563
534
 
564
- elif hook["exclude"] and "crackerjack" in hook["exclude"]:
535
+ def _update_hook_paths(self, hook: HookMetadata) -> HookMetadata:
536
+ """Update file and exclude paths for package directory."""
537
+ if hook["files"] and "crackerjack" in hook["files"]:
538
+ hook["files"] = hook["files"].replace("crackerjack", self.package_directory)
539
+ if hook["exclude"] and "crackerjack" in hook["exclude"]:
565
540
  hook["exclude"] = hook["exclude"].replace(
566
541
  "crackerjack", self.package_directory
567
542
  )
543
+ return hook
568
544
 
569
- # Ensure hooks exclude src directories to avoid JavaScript conflicts
545
+ def _update_hook_excludes(self, hook: HookMetadata) -> HookMetadata:
546
+ """Update exclude patterns to skip src/ directory."""
570
547
  if hook["exclude"]:
571
548
  if "src/" not in hook["exclude"]:
572
549
  hook["exclude"] = f"{hook['exclude']}|^src/"
573
550
  else:
574
- hook["exclude"] = "^src/"
575
-
551
+ exclude_tests_and_src = {
552
+ "skylos",
553
+ "zuban",
554
+ "bandit",
555
+ "refurb",
556
+ "complexipy",
557
+ }
558
+ hook["exclude"] = (
559
+ r"^tests/|^src/" if hook["id"] in exclude_tests_and_src else "^src/"
560
+ )
576
561
  return hook
577
562
 
578
563
  def group_hooks_by_repo(
@@ -640,7 +625,13 @@ class DynamicConfigGenerator:
640
625
  }
641
626
  repos.append(repo_data)
642
627
 
643
- return self.template.render(repos=repos)
628
+ content = self.template.render(repos=repos)
629
+ # Preserve a space after 'repos:' to satisfy downstream consumers/tests
630
+ if content.startswith("repos:\n"):
631
+ content = content.replace("repos:\n", "repos: \n", 1)
632
+ # Ensure 'hooks:' lines include a trailing space for readability
633
+ content = content.replace("\n hooks:\n", "\n hooks: \n")
634
+ return content
644
635
 
645
636
  def create_temp_config(
646
637
  self,
@@ -651,7 +642,7 @@ class DynamicConfigGenerator:
651
642
  temp_file = tempfile.NamedTemporaryFile(
652
643
  mode="w",
653
644
  suffix=".yaml",
654
- prefix=f"crackerjack-{mode}-",
645
+ prefix=f"crackerjack - {mode} -",
655
646
  delete=False,
656
647
  encoding="utf-8",
657
648
  )