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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (533) hide show
  1. crackerjack/README.md +19 -0
  2. crackerjack/__init__.py +96 -2
  3. crackerjack/__main__.py +637 -138
  4. crackerjack/adapters/README.md +18 -0
  5. crackerjack/adapters/__init__.py +39 -0
  6. crackerjack/adapters/_output_paths.py +167 -0
  7. crackerjack/adapters/_qa_adapter_base.py +309 -0
  8. crackerjack/adapters/_tool_adapter_base.py +706 -0
  9. crackerjack/adapters/ai/README.md +65 -0
  10. crackerjack/adapters/ai/__init__.py +5 -0
  11. crackerjack/adapters/ai/claude.py +853 -0
  12. crackerjack/adapters/complexity/README.md +53 -0
  13. crackerjack/adapters/complexity/__init__.py +10 -0
  14. crackerjack/adapters/complexity/complexipy.py +641 -0
  15. crackerjack/adapters/dependency/__init__.py +22 -0
  16. crackerjack/adapters/dependency/pip_audit.py +418 -0
  17. crackerjack/adapters/format/README.md +72 -0
  18. crackerjack/adapters/format/__init__.py +11 -0
  19. crackerjack/adapters/format/mdformat.py +313 -0
  20. crackerjack/adapters/format/ruff.py +516 -0
  21. crackerjack/adapters/lint/README.md +47 -0
  22. crackerjack/adapters/lint/__init__.py +11 -0
  23. crackerjack/adapters/lint/codespell.py +273 -0
  24. crackerjack/adapters/lsp/README.md +49 -0
  25. crackerjack/adapters/lsp/__init__.py +27 -0
  26. crackerjack/adapters/lsp/_base.py +194 -0
  27. crackerjack/adapters/lsp/_client.py +358 -0
  28. crackerjack/adapters/lsp/_manager.py +193 -0
  29. crackerjack/adapters/lsp/skylos.py +283 -0
  30. crackerjack/adapters/lsp/zuban.py +557 -0
  31. crackerjack/adapters/refactor/README.md +59 -0
  32. crackerjack/adapters/refactor/__init__.py +12 -0
  33. crackerjack/adapters/refactor/creosote.py +318 -0
  34. crackerjack/adapters/refactor/refurb.py +406 -0
  35. crackerjack/adapters/refactor/skylos.py +494 -0
  36. crackerjack/adapters/sast/README.md +132 -0
  37. crackerjack/adapters/sast/__init__.py +32 -0
  38. crackerjack/adapters/sast/_base.py +201 -0
  39. crackerjack/adapters/sast/bandit.py +423 -0
  40. crackerjack/adapters/sast/pyscn.py +405 -0
  41. crackerjack/adapters/sast/semgrep.py +241 -0
  42. crackerjack/adapters/security/README.md +111 -0
  43. crackerjack/adapters/security/__init__.py +17 -0
  44. crackerjack/adapters/security/gitleaks.py +339 -0
  45. crackerjack/adapters/type/README.md +52 -0
  46. crackerjack/adapters/type/__init__.py +12 -0
  47. crackerjack/adapters/type/pyrefly.py +402 -0
  48. crackerjack/adapters/type/ty.py +402 -0
  49. crackerjack/adapters/type/zuban.py +522 -0
  50. crackerjack/adapters/utility/README.md +51 -0
  51. crackerjack/adapters/utility/__init__.py +10 -0
  52. crackerjack/adapters/utility/checks.py +884 -0
  53. crackerjack/agents/README.md +264 -0
  54. crackerjack/agents/__init__.py +66 -0
  55. crackerjack/agents/architect_agent.py +238 -0
  56. crackerjack/agents/base.py +167 -0
  57. crackerjack/agents/claude_code_bridge.py +641 -0
  58. crackerjack/agents/coordinator.py +600 -0
  59. crackerjack/agents/documentation_agent.py +520 -0
  60. crackerjack/agents/dry_agent.py +585 -0
  61. crackerjack/agents/enhanced_coordinator.py +279 -0
  62. crackerjack/agents/enhanced_proactive_agent.py +185 -0
  63. crackerjack/agents/error_middleware.py +53 -0
  64. crackerjack/agents/formatting_agent.py +230 -0
  65. crackerjack/agents/helpers/__init__.py +9 -0
  66. crackerjack/agents/helpers/performance/__init__.py +22 -0
  67. crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
  68. crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
  69. crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
  70. crackerjack/agents/helpers/refactoring/__init__.py +22 -0
  71. crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
  72. crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
  73. crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
  74. crackerjack/agents/helpers/test_creation/__init__.py +19 -0
  75. crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
  76. crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
  77. crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
  78. crackerjack/agents/import_optimization_agent.py +1181 -0
  79. crackerjack/agents/performance_agent.py +325 -0
  80. crackerjack/agents/performance_helpers.py +205 -0
  81. crackerjack/agents/proactive_agent.py +55 -0
  82. crackerjack/agents/refactoring_agent.py +511 -0
  83. crackerjack/agents/refactoring_helpers.py +247 -0
  84. crackerjack/agents/security_agent.py +793 -0
  85. crackerjack/agents/semantic_agent.py +479 -0
  86. crackerjack/agents/semantic_helpers.py +356 -0
  87. crackerjack/agents/test_creation_agent.py +570 -0
  88. crackerjack/agents/test_specialist_agent.py +526 -0
  89. crackerjack/agents/tracker.py +110 -0
  90. crackerjack/api.py +647 -0
  91. crackerjack/cli/README.md +394 -0
  92. crackerjack/cli/__init__.py +24 -0
  93. crackerjack/cli/cache_handlers.py +209 -0
  94. crackerjack/cli/cache_handlers_enhanced.py +680 -0
  95. crackerjack/cli/facade.py +162 -0
  96. crackerjack/cli/formatting.py +13 -0
  97. crackerjack/cli/handlers/__init__.py +85 -0
  98. crackerjack/cli/handlers/advanced.py +103 -0
  99. crackerjack/cli/handlers/ai_features.py +62 -0
  100. crackerjack/cli/handlers/analytics.py +479 -0
  101. crackerjack/cli/handlers/changelog.py +271 -0
  102. crackerjack/cli/handlers/config_handlers.py +16 -0
  103. crackerjack/cli/handlers/coverage.py +84 -0
  104. crackerjack/cli/handlers/documentation.py +280 -0
  105. crackerjack/cli/handlers/main_handlers.py +497 -0
  106. crackerjack/cli/handlers/monitoring.py +371 -0
  107. crackerjack/cli/handlers.py +700 -0
  108. crackerjack/cli/interactive.py +488 -0
  109. crackerjack/cli/options.py +1216 -0
  110. crackerjack/cli/semantic_handlers.py +292 -0
  111. crackerjack/cli/utils.py +19 -0
  112. crackerjack/cli/version.py +19 -0
  113. crackerjack/code_cleaner.py +1307 -0
  114. crackerjack/config/README.md +472 -0
  115. crackerjack/config/__init__.py +275 -0
  116. crackerjack/config/global_lock_config.py +207 -0
  117. crackerjack/config/hooks.py +390 -0
  118. crackerjack/config/loader.py +239 -0
  119. crackerjack/config/settings.py +141 -0
  120. crackerjack/config/tool_commands.py +331 -0
  121. crackerjack/core/README.md +393 -0
  122. crackerjack/core/__init__.py +0 -0
  123. crackerjack/core/async_workflow_orchestrator.py +738 -0
  124. crackerjack/core/autofix_coordinator.py +282 -0
  125. crackerjack/core/container.py +105 -0
  126. crackerjack/core/enhanced_container.py +583 -0
  127. crackerjack/core/file_lifecycle.py +472 -0
  128. crackerjack/core/performance.py +244 -0
  129. crackerjack/core/performance_monitor.py +357 -0
  130. crackerjack/core/phase_coordinator.py +1227 -0
  131. crackerjack/core/proactive_workflow.py +267 -0
  132. crackerjack/core/resource_manager.py +425 -0
  133. crackerjack/core/retry.py +275 -0
  134. crackerjack/core/service_watchdog.py +601 -0
  135. crackerjack/core/session_coordinator.py +239 -0
  136. crackerjack/core/timeout_manager.py +563 -0
  137. crackerjack/core/websocket_lifecycle.py +410 -0
  138. crackerjack/core/workflow/__init__.py +21 -0
  139. crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
  140. crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
  141. crackerjack/core/workflow/workflow_issue_parser.py +714 -0
  142. crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
  143. crackerjack/core/workflow/workflow_security_gates.py +400 -0
  144. crackerjack/core/workflow_orchestrator.py +2243 -0
  145. crackerjack/data/README.md +11 -0
  146. crackerjack/data/__init__.py +8 -0
  147. crackerjack/data/models.py +79 -0
  148. crackerjack/data/repository.py +210 -0
  149. crackerjack/decorators/README.md +180 -0
  150. crackerjack/decorators/__init__.py +35 -0
  151. crackerjack/decorators/error_handling.py +649 -0
  152. crackerjack/decorators/error_handling_decorators.py +334 -0
  153. crackerjack/decorators/helpers.py +58 -0
  154. crackerjack/decorators/patterns.py +281 -0
  155. crackerjack/decorators/utils.py +58 -0
  156. crackerjack/docs/INDEX.md +11 -0
  157. crackerjack/docs/README.md +11 -0
  158. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  159. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  160. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  161. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  162. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  163. crackerjack/documentation/README.md +11 -0
  164. crackerjack/documentation/__init__.py +31 -0
  165. crackerjack/documentation/ai_templates.py +756 -0
  166. crackerjack/documentation/dual_output_generator.py +767 -0
  167. crackerjack/documentation/mkdocs_integration.py +518 -0
  168. crackerjack/documentation/reference_generator.py +1065 -0
  169. crackerjack/dynamic_config.py +678 -0
  170. crackerjack/errors.py +378 -0
  171. crackerjack/events/README.md +11 -0
  172. crackerjack/events/__init__.py +16 -0
  173. crackerjack/events/telemetry.py +175 -0
  174. crackerjack/events/workflow_bus.py +346 -0
  175. crackerjack/exceptions/README.md +301 -0
  176. crackerjack/exceptions/__init__.py +5 -0
  177. crackerjack/exceptions/config.py +4 -0
  178. crackerjack/exceptions/tool_execution_error.py +245 -0
  179. crackerjack/executors/README.md +591 -0
  180. crackerjack/executors/__init__.py +13 -0
  181. crackerjack/executors/async_hook_executor.py +938 -0
  182. crackerjack/executors/cached_hook_executor.py +316 -0
  183. crackerjack/executors/hook_executor.py +1295 -0
  184. crackerjack/executors/hook_lock_manager.py +708 -0
  185. crackerjack/executors/individual_hook_executor.py +739 -0
  186. crackerjack/executors/lsp_aware_hook_executor.py +349 -0
  187. crackerjack/executors/progress_hook_executor.py +282 -0
  188. crackerjack/executors/tool_proxy.py +433 -0
  189. crackerjack/hooks/README.md +485 -0
  190. crackerjack/hooks/lsp_hook.py +93 -0
  191. crackerjack/intelligence/README.md +557 -0
  192. crackerjack/intelligence/__init__.py +37 -0
  193. crackerjack/intelligence/adaptive_learning.py +693 -0
  194. crackerjack/intelligence/agent_orchestrator.py +485 -0
  195. crackerjack/intelligence/agent_registry.py +377 -0
  196. crackerjack/intelligence/agent_selector.py +439 -0
  197. crackerjack/intelligence/integration.py +250 -0
  198. crackerjack/interactive.py +719 -0
  199. crackerjack/managers/README.md +369 -0
  200. crackerjack/managers/__init__.py +11 -0
  201. crackerjack/managers/async_hook_manager.py +135 -0
  202. crackerjack/managers/hook_manager.py +585 -0
  203. crackerjack/managers/publish_manager.py +631 -0
  204. crackerjack/managers/test_command_builder.py +391 -0
  205. crackerjack/managers/test_executor.py +474 -0
  206. crackerjack/managers/test_manager.py +1357 -0
  207. crackerjack/managers/test_progress.py +187 -0
  208. crackerjack/mcp/README.md +374 -0
  209. crackerjack/mcp/__init__.py +0 -0
  210. crackerjack/mcp/cache.py +352 -0
  211. crackerjack/mcp/client_runner.py +121 -0
  212. crackerjack/mcp/context.py +802 -0
  213. crackerjack/mcp/dashboard.py +657 -0
  214. crackerjack/mcp/enhanced_progress_monitor.py +493 -0
  215. crackerjack/mcp/file_monitor.py +394 -0
  216. crackerjack/mcp/progress_components.py +607 -0
  217. crackerjack/mcp/progress_monitor.py +1016 -0
  218. crackerjack/mcp/rate_limiter.py +336 -0
  219. crackerjack/mcp/server.py +24 -0
  220. crackerjack/mcp/server_core.py +526 -0
  221. crackerjack/mcp/service_watchdog.py +505 -0
  222. crackerjack/mcp/state.py +407 -0
  223. crackerjack/mcp/task_manager.py +259 -0
  224. crackerjack/mcp/tools/README.md +27 -0
  225. crackerjack/mcp/tools/__init__.py +19 -0
  226. crackerjack/mcp/tools/core_tools.py +469 -0
  227. crackerjack/mcp/tools/error_analyzer.py +283 -0
  228. crackerjack/mcp/tools/execution_tools.py +384 -0
  229. crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
  230. crackerjack/mcp/tools/intelligence_tools.py +264 -0
  231. crackerjack/mcp/tools/monitoring_tools.py +628 -0
  232. crackerjack/mcp/tools/proactive_tools.py +367 -0
  233. crackerjack/mcp/tools/progress_tools.py +222 -0
  234. crackerjack/mcp/tools/semantic_tools.py +584 -0
  235. crackerjack/mcp/tools/utility_tools.py +358 -0
  236. crackerjack/mcp/tools/workflow_executor.py +699 -0
  237. crackerjack/mcp/websocket/README.md +31 -0
  238. crackerjack/mcp/websocket/__init__.py +14 -0
  239. crackerjack/mcp/websocket/app.py +54 -0
  240. crackerjack/mcp/websocket/endpoints.py +492 -0
  241. crackerjack/mcp/websocket/event_bridge.py +188 -0
  242. crackerjack/mcp/websocket/jobs.py +406 -0
  243. crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
  244. crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
  245. crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
  246. crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
  247. crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
  248. crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
  249. crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
  250. crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
  251. crackerjack/mcp/websocket/monitoring/factory.py +109 -0
  252. crackerjack/mcp/websocket/monitoring/filters.py +10 -0
  253. crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
  254. crackerjack/mcp/websocket/monitoring/models.py +90 -0
  255. crackerjack/mcp/websocket/monitoring/utils.py +171 -0
  256. crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
  257. crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
  258. crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
  259. crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
  260. crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
  261. crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
  262. crackerjack/mcp/websocket/monitoring_endpoints.py +21 -0
  263. crackerjack/mcp/websocket/server.py +174 -0
  264. crackerjack/mcp/websocket/websocket_handler.py +276 -0
  265. crackerjack/mcp/websocket_server.py +10 -0
  266. crackerjack/models/README.md +308 -0
  267. crackerjack/models/__init__.py +40 -0
  268. crackerjack/models/config.py +730 -0
  269. crackerjack/models/config_adapter.py +265 -0
  270. crackerjack/models/protocols.py +1535 -0
  271. crackerjack/models/pydantic_models.py +320 -0
  272. crackerjack/models/qa_config.py +145 -0
  273. crackerjack/models/qa_results.py +134 -0
  274. crackerjack/models/resource_protocols.py +299 -0
  275. crackerjack/models/results.py +35 -0
  276. crackerjack/models/semantic_models.py +258 -0
  277. crackerjack/models/task.py +173 -0
  278. crackerjack/models/test_models.py +60 -0
  279. crackerjack/monitoring/README.md +11 -0
  280. crackerjack/monitoring/__init__.py +0 -0
  281. crackerjack/monitoring/ai_agent_watchdog.py +405 -0
  282. crackerjack/monitoring/metrics_collector.py +427 -0
  283. crackerjack/monitoring/regression_prevention.py +580 -0
  284. crackerjack/monitoring/websocket_server.py +406 -0
  285. crackerjack/orchestration/README.md +340 -0
  286. crackerjack/orchestration/__init__.py +43 -0
  287. crackerjack/orchestration/advanced_orchestrator.py +894 -0
  288. crackerjack/orchestration/cache/README.md +312 -0
  289. crackerjack/orchestration/cache/__init__.py +37 -0
  290. crackerjack/orchestration/cache/memory_cache.py +338 -0
  291. crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
  292. crackerjack/orchestration/config.py +297 -0
  293. crackerjack/orchestration/coverage_improvement.py +180 -0
  294. crackerjack/orchestration/execution_strategies.py +361 -0
  295. crackerjack/orchestration/hook_orchestrator.py +1398 -0
  296. crackerjack/orchestration/strategies/README.md +401 -0
  297. crackerjack/orchestration/strategies/__init__.py +39 -0
  298. crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
  299. crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
  300. crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
  301. crackerjack/orchestration/test_progress_streamer.py +647 -0
  302. crackerjack/plugins/README.md +11 -0
  303. crackerjack/plugins/__init__.py +15 -0
  304. crackerjack/plugins/base.py +200 -0
  305. crackerjack/plugins/hooks.py +254 -0
  306. crackerjack/plugins/loader.py +335 -0
  307. crackerjack/plugins/managers.py +264 -0
  308. crackerjack/py313.py +191 -0
  309. crackerjack/security/README.md +11 -0
  310. crackerjack/security/__init__.py +0 -0
  311. crackerjack/security/audit.py +197 -0
  312. crackerjack/services/README.md +374 -0
  313. crackerjack/services/__init__.py +9 -0
  314. crackerjack/services/ai/README.md +295 -0
  315. crackerjack/services/ai/__init__.py +7 -0
  316. crackerjack/services/ai/advanced_optimizer.py +878 -0
  317. crackerjack/services/ai/contextual_ai_assistant.py +542 -0
  318. crackerjack/services/ai/embeddings.py +444 -0
  319. crackerjack/services/ai/intelligent_commit.py +328 -0
  320. crackerjack/services/ai/predictive_analytics.py +510 -0
  321. crackerjack/services/anomaly_detector.py +392 -0
  322. crackerjack/services/api_extractor.py +617 -0
  323. crackerjack/services/backup_service.py +467 -0
  324. crackerjack/services/bounded_status_operations.py +530 -0
  325. crackerjack/services/cache.py +369 -0
  326. crackerjack/services/changelog_automation.py +399 -0
  327. crackerjack/services/command_execution_service.py +305 -0
  328. crackerjack/services/config_integrity.py +132 -0
  329. crackerjack/services/config_merge.py +546 -0
  330. crackerjack/services/config_service.py +198 -0
  331. crackerjack/services/config_template.py +493 -0
  332. crackerjack/services/coverage_badge_service.py +173 -0
  333. crackerjack/services/coverage_ratchet.py +381 -0
  334. crackerjack/services/debug.py +733 -0
  335. crackerjack/services/dependency_analyzer.py +460 -0
  336. crackerjack/services/dependency_monitor.py +622 -0
  337. crackerjack/services/documentation_generator.py +493 -0
  338. crackerjack/services/documentation_service.py +704 -0
  339. crackerjack/services/enhanced_filesystem.py +497 -0
  340. crackerjack/services/enterprise_optimizer.py +865 -0
  341. crackerjack/services/error_pattern_analyzer.py +676 -0
  342. crackerjack/services/file_filter.py +221 -0
  343. crackerjack/services/file_hasher.py +149 -0
  344. crackerjack/services/file_io_service.py +361 -0
  345. crackerjack/services/file_modifier.py +615 -0
  346. crackerjack/services/filesystem.py +381 -0
  347. crackerjack/services/git.py +422 -0
  348. crackerjack/services/health_metrics.py +615 -0
  349. crackerjack/services/heatmap_generator.py +744 -0
  350. crackerjack/services/incremental_executor.py +380 -0
  351. crackerjack/services/initialization.py +823 -0
  352. crackerjack/services/input_validator.py +668 -0
  353. crackerjack/services/intelligent_commit.py +327 -0
  354. crackerjack/services/log_manager.py +289 -0
  355. crackerjack/services/logging.py +228 -0
  356. crackerjack/services/lsp_client.py +628 -0
  357. crackerjack/services/memory_optimizer.py +414 -0
  358. crackerjack/services/metrics.py +587 -0
  359. crackerjack/services/monitoring/README.md +30 -0
  360. crackerjack/services/monitoring/__init__.py +9 -0
  361. crackerjack/services/monitoring/dependency_monitor.py +678 -0
  362. crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
  363. crackerjack/services/monitoring/health_metrics.py +716 -0
  364. crackerjack/services/monitoring/metrics.py +587 -0
  365. crackerjack/services/monitoring/performance_benchmarks.py +410 -0
  366. crackerjack/services/monitoring/performance_cache.py +388 -0
  367. crackerjack/services/monitoring/performance_monitor.py +569 -0
  368. crackerjack/services/parallel_executor.py +527 -0
  369. crackerjack/services/pattern_cache.py +333 -0
  370. crackerjack/services/pattern_detector.py +478 -0
  371. crackerjack/services/patterns/__init__.py +142 -0
  372. crackerjack/services/patterns/agents.py +107 -0
  373. crackerjack/services/patterns/code/__init__.py +15 -0
  374. crackerjack/services/patterns/code/detection.py +118 -0
  375. crackerjack/services/patterns/code/imports.py +107 -0
  376. crackerjack/services/patterns/code/paths.py +159 -0
  377. crackerjack/services/patterns/code/performance.py +119 -0
  378. crackerjack/services/patterns/code/replacement.py +36 -0
  379. crackerjack/services/patterns/core.py +212 -0
  380. crackerjack/services/patterns/documentation/__init__.py +14 -0
  381. crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
  382. crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
  383. crackerjack/services/patterns/documentation/docstrings.py +89 -0
  384. crackerjack/services/patterns/formatting.py +226 -0
  385. crackerjack/services/patterns/operations.py +339 -0
  386. crackerjack/services/patterns/security/__init__.py +23 -0
  387. crackerjack/services/patterns/security/code_injection.py +122 -0
  388. crackerjack/services/patterns/security/credentials.py +190 -0
  389. crackerjack/services/patterns/security/path_traversal.py +221 -0
  390. crackerjack/services/patterns/security/unsafe_operations.py +216 -0
  391. crackerjack/services/patterns/templates.py +62 -0
  392. crackerjack/services/patterns/testing/__init__.py +18 -0
  393. crackerjack/services/patterns/testing/error_patterns.py +107 -0
  394. crackerjack/services/patterns/testing/pytest_output.py +126 -0
  395. crackerjack/services/patterns/tool_output/__init__.py +16 -0
  396. crackerjack/services/patterns/tool_output/bandit.py +72 -0
  397. crackerjack/services/patterns/tool_output/other.py +97 -0
  398. crackerjack/services/patterns/tool_output/pyright.py +67 -0
  399. crackerjack/services/patterns/tool_output/ruff.py +44 -0
  400. crackerjack/services/patterns/url_sanitization.py +114 -0
  401. crackerjack/services/patterns/utilities.py +42 -0
  402. crackerjack/services/patterns/utils.py +339 -0
  403. crackerjack/services/patterns/validation.py +46 -0
  404. crackerjack/services/patterns/versioning.py +62 -0
  405. crackerjack/services/predictive_analytics.py +523 -0
  406. crackerjack/services/profiler.py +280 -0
  407. crackerjack/services/quality/README.md +415 -0
  408. crackerjack/services/quality/__init__.py +11 -0
  409. crackerjack/services/quality/anomaly_detector.py +392 -0
  410. crackerjack/services/quality/pattern_cache.py +333 -0
  411. crackerjack/services/quality/pattern_detector.py +479 -0
  412. crackerjack/services/quality/qa_orchestrator.py +491 -0
  413. crackerjack/services/quality/quality_baseline.py +395 -0
  414. crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
  415. crackerjack/services/quality/quality_intelligence.py +949 -0
  416. crackerjack/services/regex_patterns.py +58 -0
  417. crackerjack/services/regex_utils.py +483 -0
  418. crackerjack/services/secure_path_utils.py +524 -0
  419. crackerjack/services/secure_status_formatter.py +450 -0
  420. crackerjack/services/secure_subprocess.py +635 -0
  421. crackerjack/services/security.py +239 -0
  422. crackerjack/services/security_logger.py +495 -0
  423. crackerjack/services/server_manager.py +411 -0
  424. crackerjack/services/smart_scheduling.py +167 -0
  425. crackerjack/services/status_authentication.py +460 -0
  426. crackerjack/services/status_security_manager.py +315 -0
  427. crackerjack/services/terminal_utils.py +0 -0
  428. crackerjack/services/thread_safe_status_collector.py +441 -0
  429. crackerjack/services/tool_filter.py +368 -0
  430. crackerjack/services/tool_version_service.py +43 -0
  431. crackerjack/services/unified_config.py +115 -0
  432. crackerjack/services/validation_rate_limiter.py +220 -0
  433. crackerjack/services/vector_store.py +689 -0
  434. crackerjack/services/version_analyzer.py +461 -0
  435. crackerjack/services/version_checker.py +223 -0
  436. crackerjack/services/websocket_resource_limiter.py +438 -0
  437. crackerjack/services/zuban_lsp_service.py +391 -0
  438. crackerjack/slash_commands/README.md +11 -0
  439. crackerjack/slash_commands/__init__.py +59 -0
  440. crackerjack/slash_commands/init.md +112 -0
  441. crackerjack/slash_commands/run.md +197 -0
  442. crackerjack/slash_commands/status.md +127 -0
  443. crackerjack/tools/README.md +11 -0
  444. crackerjack/tools/__init__.py +30 -0
  445. crackerjack/tools/_git_utils.py +105 -0
  446. crackerjack/tools/check_added_large_files.py +139 -0
  447. crackerjack/tools/check_ast.py +105 -0
  448. crackerjack/tools/check_json.py +103 -0
  449. crackerjack/tools/check_jsonschema.py +297 -0
  450. crackerjack/tools/check_toml.py +103 -0
  451. crackerjack/tools/check_yaml.py +110 -0
  452. crackerjack/tools/codespell_wrapper.py +72 -0
  453. crackerjack/tools/end_of_file_fixer.py +202 -0
  454. crackerjack/tools/format_json.py +128 -0
  455. crackerjack/tools/mdformat_wrapper.py +114 -0
  456. crackerjack/tools/trailing_whitespace.py +198 -0
  457. crackerjack/tools/validate_input_validator_patterns.py +236 -0
  458. crackerjack/tools/validate_regex_patterns.py +188 -0
  459. crackerjack/ui/README.md +11 -0
  460. crackerjack/ui/__init__.py +1 -0
  461. crackerjack/ui/dashboard_renderer.py +28 -0
  462. crackerjack/ui/templates/README.md +11 -0
  463. crackerjack/utils/console_utils.py +13 -0
  464. crackerjack/utils/dependency_guard.py +230 -0
  465. crackerjack/utils/retry_utils.py +275 -0
  466. crackerjack/workflows/README.md +590 -0
  467. crackerjack/workflows/__init__.py +46 -0
  468. crackerjack/workflows/actions.py +811 -0
  469. crackerjack/workflows/auto_fix.py +444 -0
  470. crackerjack/workflows/container_builder.py +499 -0
  471. crackerjack/workflows/definitions.py +443 -0
  472. crackerjack/workflows/engine.py +177 -0
  473. crackerjack/workflows/event_bridge.py +242 -0
  474. crackerjack-0.45.2.dist-info/METADATA +1678 -0
  475. crackerjack-0.45.2.dist-info/RECORD +478 -0
  476. {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
  477. crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
  478. crackerjack/.gitignore +0 -14
  479. crackerjack/.libcst.codemod.yaml +0 -18
  480. crackerjack/.pdm.toml +0 -1
  481. crackerjack/.pre-commit-config.yaml +0 -91
  482. crackerjack/.pytest_cache/.gitignore +0 -2
  483. crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
  484. crackerjack/.pytest_cache/README.md +0 -8
  485. crackerjack/.pytest_cache/v/cache/nodeids +0 -1
  486. crackerjack/.pytest_cache/v/cache/stepwise +0 -1
  487. crackerjack/.ruff_cache/.gitignore +0 -1
  488. crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
  489. crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
  490. crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
  491. crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
  492. crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
  493. crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
  494. crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  495. crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
  496. crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
  497. crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
  498. crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
  499. crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
  500. crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
  501. crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
  502. crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
  503. crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
  504. crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
  505. crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
  506. crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
  507. crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
  508. crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
  509. crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
  510. crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
  511. crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
  512. crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
  513. crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
  514. crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
  515. crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
  516. crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
  517. crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
  518. crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
  519. crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
  520. crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
  521. crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
  522. crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
  523. crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
  524. crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
  525. crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
  526. crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
  527. crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
  528. crackerjack/crackerjack.py +0 -855
  529. crackerjack/pyproject.toml +0 -214
  530. crackerjack-0.18.2.dist-info/METADATA +0 -420
  531. crackerjack-0.18.2.dist-info/RECORD +0 -59
  532. crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
  533. {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,391 @@
1
+ """Zuban Language Server Protocol (LSP) service for real-time type checking."""
2
+
3
+ import asyncio
4
+ import json
5
+ import logging
6
+ import subprocess
7
+ import time
8
+ import typing as t
9
+ from contextlib import suppress
10
+ from pathlib import Path
11
+
12
+ from acb.console import Console
13
+ from acb.depends import depends
14
+
15
+ from .security_logger import get_security_logger
16
+
17
+ logger = logging.getLogger("crackerjack.zuban_lsp")
18
+
19
+
20
+ class ZubanLSPService:
21
+ """Manages zuban language server lifecycle and communication."""
22
+
23
+ def __init__(
24
+ self,
25
+ port: int = 8677,
26
+ mode: str = "tcp",
27
+ console: Console | None = None,
28
+ ) -> None:
29
+ """Initialize Zuban LSP service.
30
+
31
+ Args:
32
+ port: TCP port for server (default: 8677)
33
+ mode: Transport mode, "tcp" or "stdio" (default: "tcp")
34
+ console: Rich console for output (optional)
35
+ """
36
+ self.port = port
37
+ self.mode = mode
38
+ self.console = console or depends.get_sync(Console)
39
+ self.process: subprocess.Popen[bytes] | None = None
40
+ self.start_time: float = 0.0
41
+ self.security_logger = get_security_logger()
42
+ self._health_check_failures = 0
43
+ self._max_health_failures = 3
44
+
45
+ @property
46
+ def is_running(self) -> bool:
47
+ """Check if LSP server process is running."""
48
+ return self.process is not None and self.process.poll() is None
49
+
50
+ @property
51
+ def uptime(self) -> float:
52
+ """Get server uptime in seconds."""
53
+ if self.is_running and self.start_time > 0:
54
+ return time.time() - self.start_time
55
+ return 0.0
56
+
57
+ async def start(self) -> bool:
58
+ """Start the zuban LSP server.
59
+
60
+ Returns:
61
+ True if started successfully, False otherwise
62
+ """
63
+ if self.is_running:
64
+ logger.info("Zuban LSP server already running")
65
+ return True
66
+
67
+ try:
68
+ self.console.print("[cyan]🚀 Starting Zuban LSP server...[/cyan]")
69
+
70
+ # Build command based on transport mode
71
+ if self.mode == "tcp":
72
+ # For TCP mode, we'll need to configure zuban to listen on port
73
+ # Currently zuban server only supports stdio, so we use stdio mode
74
+ cmd = ["uv", "run", "zuban", "server"]
75
+ else:
76
+ cmd = ["uv", "run", "zuban", "server"]
77
+
78
+ # Start the process
79
+ self.process = subprocess.Popen(
80
+ cmd,
81
+ stdin=subprocess.PIPE,
82
+ stdout=subprocess.PIPE,
83
+ stderr=subprocess.PIPE,
84
+ cwd=Path.cwd(),
85
+ start_new_session=True,
86
+ )
87
+
88
+ self.start_time = time.time()
89
+ self._health_check_failures = 0
90
+
91
+ # Log the startup
92
+ self.security_logger.log_subprocess_execution(
93
+ command=cmd,
94
+ purpose="zuban_lsp_server_start",
95
+ )
96
+
97
+ # Wait a moment for startup
98
+ await asyncio.sleep(1.0)
99
+
100
+ # Verify it started successfully
101
+ if not self.is_running:
102
+ error_output = ""
103
+ if self.process and self.process.stderr:
104
+ with suppress(Exception):
105
+ error_output = self.process.stderr.read().decode()
106
+
107
+ self.console.print("[red]❌ Failed to start Zuban LSP server[/red]")
108
+ if error_output:
109
+ logger.error(f"Zuban LSP startup error: {error_output}")
110
+ return False
111
+
112
+ self.console.print(
113
+ f"[green]✅ Zuban LSP server started (PID: {self.process.pid})[/green]"
114
+ )
115
+ logger.info(f"Zuban LSP server started with PID {self.process.pid}")
116
+ return True
117
+
118
+ except Exception as e:
119
+ self.console.print(f"[red]❌ Error starting Zuban LSP server: {e}[/red]")
120
+ logger.error(f"Failed to start Zuban LSP server: {e}")
121
+ return False
122
+
123
+ async def stop(self) -> None:
124
+ """Gracefully stop the LSP server."""
125
+ if not self.process:
126
+ return
127
+
128
+ self.console.print("[yellow]🛑 Stopping Zuban LSP server...[/yellow]")
129
+
130
+ try:
131
+ # Try graceful shutdown first
132
+ self.process.terminate()
133
+
134
+ # Wait for graceful shutdown
135
+ try:
136
+ self.process.wait(timeout=5.0)
137
+ self.console.print(
138
+ "[green]✅ Zuban LSP server stopped gracefully[/green]"
139
+ )
140
+ except subprocess.TimeoutExpired:
141
+ # Force kill if graceful shutdown fails
142
+ self.process.kill()
143
+ self.process.wait(timeout=2.0)
144
+ self.console.print("[yellow]⚠️ Zuban LSP server force stopped[/yellow]")
145
+
146
+ except Exception as e:
147
+ logger.error(f"Error stopping Zuban LSP server: {e}")
148
+
149
+ finally:
150
+ self.process = None
151
+ self.start_time = 0.0
152
+ self._health_check_failures = 0
153
+
154
+ async def health_check(self) -> bool:
155
+ """Check if LSP server is responsive.
156
+
157
+ Returns:
158
+ True if server is healthy, False otherwise
159
+ """
160
+ if not self.is_running:
161
+ return False
162
+
163
+ try:
164
+ # For stdio mode, we check if process is alive and responsive
165
+ if self.mode == "stdio":
166
+ return self._check_stdio_health()
167
+ else:
168
+ # For TCP mode, we would check port connectivity
169
+ return self._check_tcp_health()
170
+
171
+ except Exception as e:
172
+ logger.warning(f"Health check failed: {e}")
173
+ self._health_check_failures += 1
174
+ return False
175
+
176
+ def _check_stdio_health(self) -> bool:
177
+ """Check health for stdio mode server."""
178
+ if not self.process:
179
+ return False
180
+
181
+ # Simple check - is process still alive?
182
+ return self.process.poll() is None
183
+
184
+ def _check_tcp_health(self) -> bool:
185
+ """Check health for TCP mode server."""
186
+ # TODO: Implement TCP health check when zuban supports TCP mode
187
+ # For now, fall back to process check
188
+ return self._check_stdio_health()
189
+
190
+ async def restart(self) -> bool:
191
+ """Restart the LSP server.
192
+
193
+ Returns:
194
+ True if restarted successfully, False otherwise
195
+ """
196
+ self.console.print("[cyan]🔄 Restarting Zuban LSP server...[/cyan]")
197
+
198
+ await self.stop()
199
+ await asyncio.sleep(2.0) # Brief pause between stop and start
200
+
201
+ success = await self.start()
202
+ if success:
203
+ self.console.print(
204
+ "[green]✅ Zuban LSP server restarted successfully[/green]"
205
+ )
206
+ else:
207
+ self.console.print("[red]❌ Failed to restart Zuban LSP server[/red]")
208
+
209
+ return success
210
+
211
+ def get_status(self) -> dict[str, t.Any]:
212
+ """Get current status of the LSP server.
213
+
214
+ Returns:
215
+ Dictionary with server status information
216
+ """
217
+ return {
218
+ "running": self.is_running,
219
+ "pid": self.process.pid if self.process else None,
220
+ "uptime": self.uptime,
221
+ "port": self.port,
222
+ "mode": self.mode,
223
+ "health_failures": self._health_check_failures,
224
+ "max_health_failures": self._max_health_failures,
225
+ "healthy": self.is_running
226
+ and self._health_check_failures < self._max_health_failures,
227
+ }
228
+
229
+ async def send_lsp_request(
230
+ self, method: str, params: dict[str, t.Any] | None = None
231
+ ) -> dict[str, t.Any] | None:
232
+ """Send an LSP request to the server.
233
+
234
+ Args:
235
+ method: LSP method name (e.g., "initialize", "textDocument/didOpen")
236
+ params: Request parameters (optional)
237
+
238
+ Returns:
239
+ LSP response or None if failed
240
+ """
241
+ if not self.is_running or not self.process or not self.process.stdin:
242
+ return None
243
+
244
+ try:
245
+ request_id = int(time.time() * 1000)
246
+ request = {
247
+ "jsonrpc": "2.0",
248
+ "id": request_id,
249
+ "method": method,
250
+ }
251
+
252
+ if params is not None:
253
+ request["params"] = params
254
+
255
+ request_json = json.dumps(request)
256
+ content_length = len(request_json.encode())
257
+
258
+ # LSP protocol: Content-Length header + \r\n\r\n + JSON
259
+ message = f"Content-Length: {content_length}\r\n\r\n{request_json}"
260
+
261
+ self.process.stdin.write(message.encode())
262
+ self.process.stdin.flush()
263
+
264
+ # For notifications (no response expected), return success
265
+ if method.startswith("textDocument/did"):
266
+ return {"status": "notification_sent", "id": request_id}
267
+
268
+ # For requests that expect responses, attempt to read response
269
+ try:
270
+ response = await self._read_lsp_response(request_id, timeout=5.0)
271
+ return response
272
+ except TimeoutError:
273
+ logger.warning(f"LSP request {method} timed out")
274
+ return {"status": "timeout", "id": request_id}
275
+
276
+ except Exception as e:
277
+ logger.error(f"Failed to send LSP request: {e}")
278
+ return None
279
+
280
+ async def _read_lsp_response(
281
+ self, expected_id: int, timeout: float = 5.0
282
+ ) -> dict[str, t.Any] | None:
283
+ """Read LSP response from server with timeout.
284
+
285
+ Args:
286
+ expected_id: Expected request ID for the response
287
+ timeout: Timeout in seconds
288
+
289
+ Returns:
290
+ LSP response dictionary or None if failed
291
+ """
292
+ if not self.process or not self.process.stdout:
293
+ return None
294
+
295
+ try:
296
+ # Read with timeout
297
+ response_data = await asyncio.wait_for(
298
+ self._read_message_from_stdout(), timeout=timeout
299
+ )
300
+
301
+ if not response_data:
302
+ return None
303
+
304
+ response = json.loads(response_data)
305
+ typed_response = t.cast(dict[str, t.Any], response)
306
+
307
+ # Check if this is the response we're looking for
308
+ if typed_response.get("id") == expected_id:
309
+ return typed_response
310
+
311
+ # Log if we got a different response
312
+ logger.debug(
313
+ f"Received response for ID {typed_response.get('id')}, expected {expected_id}"
314
+ )
315
+ return typed_response
316
+
317
+ except TimeoutError:
318
+ raise
319
+ except Exception as e:
320
+ logger.error(f"Failed to read LSP response: {e}")
321
+ return None
322
+
323
+ async def _read_message_from_stdout(self) -> str | None:
324
+ """Read a complete LSP message from stdout.
325
+
326
+ Returns:
327
+ Message content as string, or None if failed
328
+ """
329
+ if not self.process or not self.process.stdout:
330
+ return None
331
+
332
+ try:
333
+ # Read the Content-Length header
334
+ header_line = await self._read_line_async()
335
+ if not header_line or not header_line.startswith("Content-Length:"):
336
+ return None
337
+
338
+ # Extract content length
339
+ content_length = int(header_line.split(":", 1)[1].strip())
340
+
341
+ # Read the empty line separator
342
+ empty_line = await self._read_line_async()
343
+ if empty_line.strip(): # Should be empty
344
+ logger.warning("Expected empty line after Content-Length header")
345
+
346
+ # Read the JSON content
347
+ content_bytes = await self._read_bytes_async(content_length)
348
+ return content_bytes.decode("utf-8")
349
+
350
+ except Exception as e:
351
+ logger.error(f"Failed to read LSP message: {e}")
352
+ return None
353
+
354
+ async def _read_line_async(self) -> str:
355
+ """Read a line from stdout asynchronously."""
356
+ if not self.process or not self.process.stdout:
357
+ return ""
358
+
359
+ # This is a simplified implementation
360
+ # In a production system, you'd want to use proper async I/O
361
+ loop = asyncio.get_event_loop()
362
+ line = await loop.run_in_executor(None, self.process.stdout.readline) # type: ignore[call-arg]
363
+ return line.decode("utf-8").rstrip("\r\n")
364
+
365
+ async def _read_bytes_async(self, count: int) -> bytes:
366
+ """Read specified number of bytes from stdout asynchronously."""
367
+ if not self.process or not self.process.stdout:
368
+ return b""
369
+
370
+ loop = asyncio.get_event_loop()
371
+ data = await loop.run_in_executor(None, self.process.stdout.read, count) # type: ignore[call-arg]
372
+ return data
373
+
374
+
375
+ async def create_zuban_lsp_service(
376
+ port: int = 8677,
377
+ mode: str = "tcp",
378
+ console: Console | None = None,
379
+ ) -> ZubanLSPService:
380
+ """Factory function to create and optionally start Zuban LSP service.
381
+
382
+ Args:
383
+ port: TCP port for server (default: 8677)
384
+ mode: Transport mode, "tcp" or "stdio" (default: "tcp")
385
+ console: Rich console for output (optional)
386
+
387
+ Returns:
388
+ Configured ZubanLSPService instance
389
+ """
390
+ service = ZubanLSPService(port=port, mode=mode, console=console)
391
+ return service
@@ -0,0 +1,11 @@
1
+ > Crackerjack Docs: [Main](<../../README.md>) | [Crackerjack Package](<../README.md>) | [Slash Commands](<./README.md>)
2
+
3
+ # Slash Commands
4
+
5
+ Slash command handlers and related routing.
6
+
7
+ ## Related
8
+
9
+ - [Crackerjack Package](<../README.md>) - Parent package
10
+ - [MCP](<../mcp/README.md>) - MCP server slash command integration
11
+ - [CLI](<../cli/README.md>) - Command-line interface handlers
@@ -0,0 +1,59 @@
1
+ from pathlib import Path
2
+
3
+ from ..errors import ErrorCode, ExecutionError
4
+ from ..services.input_validator import validate_and_sanitize_string
5
+
6
+ SLASH_COMMANDS_DIR = Path(__file__).parent
7
+
8
+
9
+ def get_slash_command_path(command_name: str) -> Path:
10
+ try:
11
+ sanitized_name = validate_and_sanitize_string(
12
+ command_name, max_length=50, strict_alphanumeric=True
13
+ )
14
+
15
+ command_path = SLASH_COMMANDS_DIR / f"{sanitized_name}.md"
16
+
17
+ if not str(command_path.resolve()).startswith(
18
+ str(SLASH_COMMANDS_DIR.resolve())
19
+ ):
20
+ raise ExecutionError(
21
+ message=f"Command path outside allowed directory: {command_name}",
22
+ error_code=ErrorCode.VALIDATION_ERROR,
23
+ )
24
+
25
+ return command_path
26
+
27
+ except Exception as e:
28
+ if isinstance(e, ExecutionError):
29
+ raise
30
+ raise ExecutionError(
31
+ message=f"Invalid command name: {command_name}",
32
+ error_code=ErrorCode.VALIDATION_ERROR,
33
+ ) from e
34
+
35
+
36
+ def list_available_commands() -> list[str]:
37
+ try:
38
+ commands = []
39
+ for file_path in SLASH_COMMANDS_DIR.glob("*.md"):
40
+ command_name = file_path.stem
41
+
42
+ try:
43
+ validate_and_sanitize_string(
44
+ command_name, max_length=50, strict_alphanumeric=True
45
+ )
46
+ commands.append(command_name)
47
+ except ExecutionError:
48
+ continue
49
+
50
+ return sorted(commands)
51
+
52
+ except Exception as e:
53
+ raise ExecutionError(
54
+ message="Failed to list[t.Any] available commands",
55
+ error_code=ErrorCode.FILE_READ_ERROR,
56
+ ) from e
57
+
58
+
59
+ __all__ = ["SLASH_COMMANDS_DIR", "get_slash_command_path", "list_available_commands"]
@@ -0,0 +1,112 @@
1
+ ______________________________________________________________________
2
+
3
+ ## description: Initialize or update crackerjack configuration for a Python project with best practices, quality hooks, and AI guidelines.
4
+
5
+ # /crackerjack:init
6
+
7
+ Initialize or update crackerjack configuration for a Python project.
8
+
9
+ ## Usage
10
+
11
+ ```
12
+ /crackerjack:init
13
+ /crackerjack:init --force
14
+ ```
15
+
16
+ ## Description
17
+
18
+ This slash command initializes a new Python project with crackerjack's best practices or updates an existing project's configuration to the latest standards.
19
+
20
+ ## What It Does
21
+
22
+ 1. **Checks Project State**: Verifies which configuration files exist
23
+ 1. **Smart Merge Configuration**:
24
+ - `pyproject.toml` - Intelligently merges tool configurations, preserves higher coverage requirements
25
+ - `CLAUDE.md` - Appends crackerjack guidelines without overwriting existing content
26
+ - `RULES.md` - Copies only if missing, preserves existing coding standards
27
+ 1. **Preserves Project Identity**: Never overwrites existing project metadata, dependencies, or configurations
28
+
29
+ ## When to Use /crackerjack:init
30
+
31
+ ### Automatic Detection
32
+
33
+ The MCP server can detect when initialization is needed:
34
+
35
+ - **Missing Core Files**: No pyproject.toml
36
+ - **New Project**: Git repository just initialized
37
+ - **Manual Request**: User explicitly asks for initialization
38
+
39
+ ### Recommended Frequency
40
+
41
+ - **New Projects**: Always run on project creation
42
+ - **Weekly**: For active development projects
43
+ - **After Tool Updates**: When crackerjack or dependencies update
44
+ - **Team Onboarding**: When new developers join
45
+
46
+ ## Options
47
+
48
+ - `--force`: Force reinitialization even if configuration exists
49
+
50
+ ## Example
51
+
52
+ ```
53
+ User: Set up this Python project with best practices
54
+ AI: I'll initialize crackerjack configuration for your project.
55
+
56
+ /crackerjack:init
57
+
58
+ [AI executes initialization and reports results]
59
+
60
+ The project has been initialized with:
61
+ ✅ pyproject.toml - Project configuration
62
+ ✅ CLAUDE.md - AI guidelines
63
+ ✅ RULES.md - Coding standards
64
+
65
+ Your project now follows Python best practices!
66
+ ```
67
+
68
+ ## Auto-Init Behavior
69
+
70
+ When connected via MCP, crackerjack can automatically suggest initialization when:
71
+
72
+ 1. Running `/crackerjack:run` in an uninitialized project
73
+ 1. Detecting missing critical configuration files
74
+ 1. Finding configuration files that need updates
75
+
76
+ This ensures projects always have up-to-date quality standards without manual intervention.
77
+
78
+ ## Smart Merge Behavior
79
+
80
+ **Crackerjack uses intelligent smart merging instead of destructive overwrites:**
81
+
82
+ ### pyproject.toml Smart Merge
83
+
84
+ - **Preserves Project Identity**: Project name, version, description, dependencies remain untouched
85
+ - **Ensures Crackerjack Dependency**: Adds `crackerjack` to `[dependency-groups].dev` if missing
86
+ - **Merges Tool Configurations**: Adds missing tool sections (`[tool.ruff]`, `[tool.pyright]`, etc.)
87
+ - **Preserves Higher Coverage**: If target has higher `--cov-fail-under` than source, keeps the higher value
88
+ - **Adds Missing Pytest Markers**: Appends new test markers while preserving existing ones
89
+
90
+ ### CLAUDE.md Smart Append
91
+
92
+ - **Non-Destructive**: Appends crackerjack guidelines with clear markers
93
+ - **Prevents Duplicates**: Skips if crackerjack section already exists
94
+ - **Clear Boundaries**: Uses `<!-- CRACKERJACK_START -->` and `<!-- CRACKERJACK_END -->` markers
95
+
96
+ ### Universal Compatibility
97
+
98
+ This smart merge approach works with **any Python package**, not just specific projects:
99
+
100
+ - ✅ **MCP Servers** (session-mgmt-mcp, excalidraw-mcp)
101
+ - ✅ **Django Projects** with existing configurations
102
+ - ✅ **Flask Applications** with established tooling
103
+ - ✅ **Data Science Projects** with Jupyter-specific settings
104
+ - ✅ **CLI Tools** with complex pyproject.toml configurations
105
+
106
+ ### Example Smart Merge Results
107
+
108
+ **Before**: Project with 85% coverage requirement
109
+ **After**: Keeps 85% coverage, adds all crackerjack tools, preserves project identity
110
+
111
+ **Before**: CLAUDE.md with project-specific guidelines
112
+ **After**: Original content + crackerjack section appended with clear markers