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,405 @@
1
+ """Pyscn adapter for ACB QA framework - Python security static analysis.
2
+
3
+ Pyscn is a Python static code analyzer for security that detects:
4
+ - Security vulnerabilities in Python code
5
+ - Common security anti-patterns
6
+ - Potential injection attacks
7
+ - Insecure cryptography usage
8
+ - Authentication and authorization issues
9
+
10
+ ACB Patterns:
11
+ - MODULE_ID and MODULE_STATUS at module level
12
+ - depends.set() registration after class definition
13
+ - Extends BaseToolAdapter for tool execution
14
+ - Async execution with JSON output parsing
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import json
20
+ import logging
21
+ import typing as t
22
+ from contextlib import suppress
23
+ from pathlib import Path
24
+ from uuid import UUID
25
+
26
+ from acb.depends import depends
27
+ from pydantic import Field
28
+
29
+ from crackerjack.adapters._tool_adapter_base import (
30
+ BaseToolAdapter,
31
+ ToolAdapterSettings,
32
+ ToolExecutionResult,
33
+ ToolIssue,
34
+ )
35
+ from crackerjack.models.qa_results import QACheckType
36
+
37
+ if t.TYPE_CHECKING:
38
+ from crackerjack.models.qa_config import QACheckConfig
39
+
40
+ # ACB Module Registration (REQUIRED)
41
+ MODULE_ID = UUID(
42
+ "01937d86-6b2c-7d3e-8f4a-b5c6d7e8f9a3"
43
+ ) # Static UUID7 for reproducible module identity
44
+ MODULE_STATUS = "experimental"
45
+
46
+ # Module-level logger for structured logging
47
+ logger = logging.getLogger(__name__)
48
+
49
+
50
+ class PyscnSettings(ToolAdapterSettings):
51
+ """Settings for Pyscn adapter."""
52
+
53
+ tool_name: str = "pyscn"
54
+ use_json_output: bool = True
55
+ severity_threshold: str = "low" # low, medium, high, critical
56
+ confidence_threshold: str = "low" # low, medium, high
57
+ exclude_rules: list[str] = Field(default_factory=list)
58
+ include_rules: list[str] = Field(default_factory=list)
59
+ recursive: bool = True
60
+ max_depth: int | None = None
61
+
62
+
63
+ class PyscnAdapter(BaseToolAdapter):
64
+ """Adapter for Pyscn - Python security static analyzer.
65
+
66
+ Performs static security analysis to detect vulnerabilities in Python code:
67
+ - Security anti-patterns and insecure practices
68
+ - Potential injection vulnerabilities
69
+ - Weak cryptography implementations
70
+ - Authentication/authorization flaws
71
+ - Privilege escalation risks
72
+ - Data exposure issues
73
+
74
+ Features:
75
+ - JSON output for structured issue reporting
76
+ - Configurable severity and confidence thresholds
77
+ - Rule inclusion/exclusion filtering
78
+ - Recursive directory scanning with depth control
79
+
80
+ Example:
81
+ ```python
82
+ settings = PyscnSettings(
83
+ severity_threshold="medium",
84
+ confidence_threshold="medium",
85
+ exclude_rules=["SCN001"],
86
+ recursive=True,
87
+ )
88
+ adapter = PyscnAdapter(settings=settings)
89
+ await adapter.init()
90
+ result = await adapter.check(files=[Path("src/")])
91
+ ```
92
+ """
93
+
94
+ settings: PyscnSettings | None = None
95
+
96
+ def __init__(self, settings: PyscnSettings | None = None) -> None:
97
+ """Initialize Pyscn adapter.
98
+
99
+ Args:
100
+ settings: Optional settings override
101
+ """
102
+ super().__init__(settings=settings)
103
+ logger.debug(
104
+ "PyscnAdapter initialized", extra={"has_settings": settings is not None}
105
+ )
106
+
107
+ async def init(self) -> None:
108
+ """Initialize adapter with default settings."""
109
+ if not self.settings:
110
+ self.settings = PyscnSettings()
111
+ logger.info("Using default PyscnSettings")
112
+ await super().init()
113
+ logger.debug(
114
+ "PyscnAdapter initialization complete",
115
+ extra={
116
+ "severity_threshold": self.settings.severity_threshold,
117
+ "confidence_threshold": self.settings.confidence_threshold,
118
+ "recursive": self.settings.recursive,
119
+ },
120
+ )
121
+
122
+ @property
123
+ def adapter_name(self) -> str:
124
+ """Human-readable adapter name."""
125
+ return "Pyscn (Security Analysis)"
126
+
127
+ @property
128
+ def module_id(self) -> UUID:
129
+ """Reference to module-level MODULE_ID."""
130
+ return MODULE_ID
131
+
132
+ @property
133
+ def tool_name(self) -> str:
134
+ """CLI tool name."""
135
+ return "pyscn"
136
+
137
+ def build_command(
138
+ self,
139
+ files: list[Path],
140
+ config: QACheckConfig | None = None,
141
+ ) -> list[str]:
142
+ """Build Pyscn command.
143
+
144
+ Args:
145
+ files: Files/directories to scan
146
+ config: Optional configuration override
147
+
148
+ Returns:
149
+ Command as list of strings
150
+ """
151
+ if not self.settings:
152
+ raise RuntimeError("Settings not initialized")
153
+
154
+ cmd = [self.tool_name]
155
+
156
+ # JSON output
157
+ if self.settings.use_json_output:
158
+ cmd.extend(["--format", "json"])
159
+
160
+ # Severity threshold
161
+ cmd.extend(["--severity", self.settings.severity_threshold])
162
+
163
+ # Confidence threshold
164
+ cmd.extend(["--confidence", self.settings.confidence_threshold])
165
+
166
+ # Exclude rules
167
+ for rule in self.settings.exclude_rules:
168
+ cmd.extend(["--exclude", rule])
169
+
170
+ # Include rules
171
+ for rule in self.settings.include_rules:
172
+ cmd.extend(["--include", rule])
173
+
174
+ # Recursive scanning
175
+ if self.settings.recursive:
176
+ cmd.append("--recursive")
177
+
178
+ # Max depth
179
+ if self.settings.max_depth is not None:
180
+ cmd.extend(["--max-depth", str(self.settings.max_depth)])
181
+
182
+ # Add targets
183
+ cmd.extend([str(f) for f in files])
184
+
185
+ logger.info(
186
+ "Built Pyscn command",
187
+ extra={
188
+ "file_count": len(files),
189
+ "severity_threshold": self.settings.severity_threshold,
190
+ "confidence_threshold": self.settings.confidence_threshold,
191
+ "recursive": self.settings.recursive,
192
+ },
193
+ )
194
+ return cmd
195
+
196
+ async def parse_output(
197
+ self,
198
+ result: ToolExecutionResult,
199
+ ) -> list[ToolIssue]:
200
+ """Parse Pyscn JSON output into standardized issues.
201
+
202
+ Args:
203
+ result: Raw execution result from Pyscn
204
+
205
+ Returns:
206
+ List of parsed issues
207
+ """
208
+ if not result.raw_output:
209
+ logger.debug("No output to parse")
210
+ return []
211
+
212
+ try:
213
+ data = json.loads(result.raw_output)
214
+ logger.debug(
215
+ "Parsed Pyscn JSON output",
216
+ extra={"issues_count": len(data.get("issues", []))},
217
+ )
218
+ except json.JSONDecodeError as e:
219
+ logger.debug(
220
+ "JSON parse failed, falling back to text parsing",
221
+ extra={"error": str(e), "output_preview": result.raw_output[:200]},
222
+ )
223
+ return self._parse_text_output(result.raw_output)
224
+
225
+ issues = []
226
+
227
+ # Pyscn JSON format:
228
+ # {
229
+ # "issues": [
230
+ # {
231
+ # "file": "path/to/file.py",
232
+ # "line": 42,
233
+ # "column": 10,
234
+ # "message": "Potential security vulnerability...",
235
+ # "severity": "high",
236
+ # "confidence": "medium",
237
+ # "rule_id": "SCN123",
238
+ # "rule_name": "insecure_crypto"
239
+ # }
240
+ # ]
241
+ # }
242
+
243
+ for issue_data in data.get("issues", []):
244
+ issue = ToolIssue(
245
+ file_path=Path(issue_data.get("file", "")),
246
+ line_number=issue_data.get("line"),
247
+ column_number=issue_data.get("column"),
248
+ message=issue_data.get("message", ""),
249
+ code=issue_data.get("rule_id"),
250
+ severity=issue_data.get("severity", "error"),
251
+ )
252
+ issues.append(issue)
253
+
254
+ logger.info(
255
+ "Parsed Pyscn output",
256
+ extra={
257
+ "total_issues": len(issues),
258
+ "errors": sum(1 for i in issues if i.severity == "error"),
259
+ "warnings": sum(1 for i in issues if i.severity == "warning"),
260
+ "files_affected": len({str(i.file_path) for i in issues}),
261
+ },
262
+ )
263
+ return issues
264
+
265
+ def _parse_text_output(self, output: str) -> list[ToolIssue]:
266
+ """Parse Pyscn text output (fallback).
267
+
268
+ Args:
269
+ output: Text output from Pyscn
270
+
271
+ Returns:
272
+ List of ToolIssue objects
273
+ """
274
+ issues = []
275
+ lines = output.strip().split("\n")
276
+
277
+ for line in lines:
278
+ # Pyscn text format: "file.py:10:5: error: Potential security vulnerability..."
279
+ if ":" not in line:
280
+ continue
281
+
282
+ issue = self._parse_text_line(line)
283
+ if issue:
284
+ issues.append(issue)
285
+
286
+ logger.info(
287
+ "Parsed Pyscn text output (fallback)",
288
+ extra={
289
+ "total_issues": len(issues),
290
+ "files_with_issues": len({str(i.file_path) for i in issues}),
291
+ },
292
+ )
293
+ return issues
294
+
295
+ def _parse_text_line(self, line: str) -> ToolIssue | None:
296
+ """Parse a single text output line.
297
+
298
+ Args:
299
+ line: Line of text output
300
+
301
+ Returns:
302
+ ToolIssue if parsing successful, None otherwise
303
+ """
304
+ parts = line.split(":", maxsplit=4)
305
+ if len(parts) < 4:
306
+ return None
307
+
308
+ try:
309
+ file_path = Path(parts[0].strip())
310
+ line_number = int(parts[1].strip())
311
+ column_number = (
312
+ int(parts[2].strip()) if parts[2].strip().isdigit() else None
313
+ )
314
+
315
+ severity_and_message = parts[3].strip() if len(parts) > 3 else ""
316
+ message = parts[4].strip() if len(parts) > 4 else ""
317
+
318
+ severity = self._parse_severity(severity_and_message, message)
319
+ message = self._extract_message(severity_and_message, message, severity)
320
+
321
+ return ToolIssue(
322
+ file_path=file_path,
323
+ line_number=line_number,
324
+ column_number=column_number,
325
+ message=message,
326
+ severity=severity,
327
+ )
328
+
329
+ except (ValueError, IndexError):
330
+ return None
331
+
332
+ def _parse_severity(self, severity_and_message: str, message: str) -> str:
333
+ """Parse severity from text line.
334
+
335
+ Args:
336
+ severity_and_message: Part containing severity
337
+ message: Explicit message if present
338
+
339
+ Returns:
340
+ Severity level (error or warning)
341
+ """
342
+ if severity_and_message.lower().startswith("warning"):
343
+ return "warning"
344
+ return "error"
345
+
346
+ def _extract_message(
347
+ self, severity_and_message: str, message: str, severity: str
348
+ ) -> str:
349
+ """Extract message from text line.
350
+
351
+ Args:
352
+ severity_and_message: Part containing severity and possibly message
353
+ message: Explicit message if present
354
+ severity: Parsed severity level
355
+
356
+ Returns:
357
+ Extracted message
358
+ """
359
+ if message:
360
+ return message
361
+
362
+ # Extract from severity_and_message
363
+ if severity_and_message.lower().startswith(severity):
364
+ return severity_and_message[len(severity) :].strip()
365
+
366
+ return severity_and_message
367
+
368
+ def _get_check_type(self) -> QACheckType:
369
+ """Return SAST check type."""
370
+ return QACheckType.SAST
371
+
372
+ def get_default_config(self) -> QACheckConfig:
373
+ """Get default configuration for Pyscn adapter.
374
+
375
+ Returns:
376
+ QACheckConfig with sensible defaults
377
+ """
378
+ from crackerjack.models.qa_config import QACheckConfig
379
+
380
+ return QACheckConfig(
381
+ check_id=MODULE_ID,
382
+ check_name=self.adapter_name,
383
+ check_type=QACheckType.SAST,
384
+ enabled=False, # Disabled by default as experimental
385
+ file_patterns=["**/*.py"],
386
+ exclude_patterns=[
387
+ "**/.venv/**",
388
+ "**/venv/**",
389
+ "**/build/**",
390
+ "**/dist/**",
391
+ ],
392
+ timeout_seconds=120, # Security scanning can be slower
393
+ parallel_safe=True,
394
+ stage="comprehensive", # Security checks in comprehensive stage
395
+ settings={
396
+ "severity_threshold": "medium",
397
+ "confidence_threshold": "medium",
398
+ "recursive": True,
399
+ },
400
+ )
401
+
402
+
403
+ # ACB Registration (REQUIRED at module level)
404
+ with suppress(Exception):
405
+ depends.set(PyscnAdapter)
@@ -0,0 +1,241 @@
1
+ """Semgrep adapter for ACB QA framework - Modern security scanning.
2
+
3
+ Semgrep is a fast, open-source, static analysis tool for finding bugs,
4
+ enforcing code standards, and finding security vulnerabilities.
5
+
6
+ ACB Patterns:
7
+ - MODULE_ID and MODULE_STATUS at module level
8
+ - depends.set() registration after class definition
9
+ - Extends BaseToolAdapter for tool execution
10
+ - Async execution with JSON output parsing
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import json
16
+ import logging
17
+ import typing as t
18
+ from contextlib import suppress
19
+ from pathlib import Path
20
+ from uuid import UUID
21
+
22
+ from acb.depends import depends
23
+
24
+ from crackerjack.adapters._tool_adapter_base import (
25
+ BaseToolAdapter,
26
+ ToolAdapterSettings,
27
+ ToolExecutionResult,
28
+ ToolIssue,
29
+ )
30
+ from crackerjack.models.qa_results import QACheckType
31
+
32
+ if t.TYPE_CHECKING:
33
+ from crackerjack.models.qa_config import QACheckConfig
34
+
35
+ # ACB Module Registration (REQUIRED)
36
+ MODULE_ID = UUID(
37
+ "01937d86-4f2a-7b3c-8d9e-f3b4d3c2b1a1"
38
+ ) # Static UUID7 for reproducible module identity
39
+ MODULE_STATUS = "stable"
40
+
41
+ # Module-level logger for structured logging
42
+ logger = logging.getLogger(__name__)
43
+
44
+
45
+ class SemgrepSettings(ToolAdapterSettings):
46
+ """Settings for Semgrep adapter."""
47
+
48
+ tool_name: str = "semgrep"
49
+ use_json_output: bool = True
50
+ config: str = "p/python" # Default ruleset
51
+ exclude_tests: bool = True
52
+ timeout_seconds: int = 1200
53
+
54
+
55
+ class SemgrepAdapter(BaseToolAdapter):
56
+ """Adapter for Semgrep - Modern static analysis."""
57
+
58
+ settings: SemgrepSettings | None = None
59
+
60
+ def __init__(self, settings: SemgrepSettings | None = None) -> None:
61
+ """Initialize Semgrep adapter."""
62
+ super().__init__(settings=settings)
63
+ logger.debug(
64
+ "SemgrepAdapter initialized", extra={"has_settings": settings is not None}
65
+ )
66
+
67
+ async def init(self) -> None:
68
+ """Initialize adapter with default settings."""
69
+ if not self.settings:
70
+ self.settings = SemgrepSettings()
71
+ logger.info("Using default SemgrepSettings")
72
+ await super().init()
73
+ logger.debug(
74
+ "SemgrepAdapter initialization complete",
75
+ extra={
76
+ "config": self.settings.config,
77
+ "exclude_tests": self.settings.exclude_tests,
78
+ },
79
+ )
80
+
81
+ @property
82
+ def adapter_name(self) -> str:
83
+ """Human-readable adapter name."""
84
+ return "Semgrep (Security)"
85
+
86
+ @property
87
+ def module_id(self) -> UUID:
88
+ """Reference to module-level MODULE_ID."""
89
+ return MODULE_ID
90
+
91
+ @property
92
+ def tool_name(self) -> str:
93
+ """CLI tool name."""
94
+ return "semgrep"
95
+
96
+ def build_command(
97
+ self,
98
+ files: list[Path],
99
+ config: QACheckConfig | None = None,
100
+ ) -> list[str]:
101
+ """Build Semgrep command."""
102
+ if not self.settings:
103
+ raise RuntimeError("Settings not initialized")
104
+
105
+ cmd = [self.tool_name, "scan"]
106
+
107
+ # JSON output
108
+ if self.settings.use_json_output:
109
+ cmd.append("--json")
110
+
111
+ # Config
112
+ cmd.extend(["--config", self.settings.config])
113
+
114
+ # Add targets
115
+ cmd.extend([str(f) for f in files])
116
+
117
+ logger.info(
118
+ "Built Semgrep command",
119
+ extra={
120
+ "file_count": len(files),
121
+ "config": self.settings.config,
122
+ },
123
+ )
124
+ return cmd
125
+
126
+ async def parse_output(
127
+ self,
128
+ result: ToolExecutionResult,
129
+ ) -> list[ToolIssue]:
130
+ """Parse Semgrep JSON output into standardized issues."""
131
+ if not result.raw_output:
132
+ logger.debug("No output to parse")
133
+ return []
134
+
135
+ try:
136
+ data = json.loads(result.raw_output)
137
+ logger.debug(
138
+ "Parsed Semgrep JSON output",
139
+ extra={"results_count": len(data.get("results", []))},
140
+ )
141
+ except json.JSONDecodeError as e:
142
+ logger.debug(
143
+ "JSON parse failed, falling back to text parsing",
144
+ extra={"error": str(e), "output_preview": result.raw_output[:200]},
145
+ )
146
+ return [] # No text parsing for semgrep for now
147
+
148
+ issues = []
149
+ for item in data.get("results", []):
150
+ file_path = Path(item.get("path", ""))
151
+ start_line = item.get("start", {}).get("line")
152
+ message = item.get("extra", {}).get("message", "")
153
+ code = item.get("check_id")
154
+ severity = item.get("extra", {}).get("severity", "WARNING").lower()
155
+
156
+ issue = ToolIssue(
157
+ file_path=file_path,
158
+ line_number=start_line,
159
+ message=message,
160
+ code=code,
161
+ severity=severity,
162
+ )
163
+ issues.append(issue)
164
+
165
+ logger.info(
166
+ "Parsed Semgrep output",
167
+ extra={
168
+ "total_issues": len(issues),
169
+ "files_affected": len({str(i.file_path) for i in issues}),
170
+ },
171
+ )
172
+ return issues
173
+
174
+ def _get_check_type(self) -> QACheckType:
175
+ """Return SAST check type."""
176
+ return QACheckType.SAST
177
+
178
+ def _detect_package_directory(self) -> str:
179
+ """Detect the package directory name from pyproject.toml.
180
+
181
+ Returns:
182
+ Package directory name (e.g., 'crackerjack', 'session_mgmt_mcp')
183
+ """
184
+ from contextlib import suppress
185
+
186
+ current_dir = Path.cwd()
187
+
188
+ # Try to read package name from pyproject.toml
189
+ pyproject_path = current_dir / "pyproject.toml"
190
+ if pyproject_path.exists():
191
+ with suppress(Exception):
192
+ import tomllib
193
+
194
+ with pyproject_path.open("rb") as f:
195
+ data = tomllib.load(f)
196
+
197
+ if "project" in data and "name" in data["project"]:
198
+ # Convert package name to directory name (replace - with _)
199
+ package_name = str(data["project"]["name"]).replace("-", "_")
200
+
201
+ # Verify directory exists
202
+ if (current_dir / package_name).exists():
203
+ return package_name
204
+
205
+ # Fallback to directory name if package dir exists
206
+ if (current_dir / current_dir.name).exists():
207
+ return current_dir.name
208
+
209
+ # Default fallback
210
+ return "src"
211
+
212
+ def get_default_config(self) -> QACheckConfig:
213
+ """Get default configuration for Semgrep adapter."""
214
+ from crackerjack.models.qa_config import QACheckConfig
215
+
216
+ # Dynamically detect package directory
217
+ package_dir = self._detect_package_directory()
218
+
219
+ return QACheckConfig(
220
+ check_id=MODULE_ID,
221
+ check_name=self.adapter_name,
222
+ check_type=QACheckType.SAST,
223
+ enabled=True,
224
+ file_patterns=[f"{package_dir}/**/*.py"],
225
+ exclude_patterns=[
226
+ "**/test_*.py",
227
+ "**/tests/**",
228
+ ],
229
+ timeout_seconds=1200,
230
+ parallel_safe=True,
231
+ stage="comprehensive",
232
+ settings={
233
+ "config": "p/python",
234
+ "exclude_tests": True,
235
+ },
236
+ )
237
+
238
+
239
+ # ACB Registration (REQUIRED at module level)
240
+ with suppress(Exception):
241
+ depends.set(SemgrepAdapter)