@vyuhlabs/dxkit 2.4.5 → 2.4.7

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 (356) hide show
  1. package/CHANGELOG.md +1022 -0
  2. package/README.md +160 -45
  3. package/dist/analysis-result.d.ts +112 -0
  4. package/dist/analysis-result.d.ts.map +1 -0
  5. package/dist/analysis-result.js +52 -0
  6. package/dist/analysis-result.js.map +1 -0
  7. package/dist/analyzers/bom/detailed.d.ts.map +1 -1
  8. package/dist/analyzers/bom/detailed.js +19 -0
  9. package/dist/analyzers/bom/detailed.js.map +1 -1
  10. package/dist/analyzers/bom/gather.d.ts +27 -26
  11. package/dist/analyzers/bom/gather.d.ts.map +1 -1
  12. package/dist/analyzers/bom/gather.js +26 -87
  13. package/dist/analyzers/bom/gather.js.map +1 -1
  14. package/dist/analyzers/bom/index.d.ts +0 -7
  15. package/dist/analyzers/bom/index.d.ts.map +1 -1
  16. package/dist/analyzers/bom/index.js +98 -48
  17. package/dist/analyzers/bom/index.js.map +1 -1
  18. package/dist/analyzers/bom/types.d.ts +11 -13
  19. package/dist/analyzers/bom/types.d.ts.map +1 -1
  20. package/dist/analyzers/cache.d.ts +95 -0
  21. package/dist/analyzers/cache.d.ts.map +1 -0
  22. package/dist/analyzers/cache.js +309 -0
  23. package/dist/analyzers/cache.js.map +1 -0
  24. package/dist/analyzers/coverage-runner.d.ts +56 -0
  25. package/dist/analyzers/coverage-runner.d.ts.map +1 -0
  26. package/dist/analyzers/coverage-runner.js +72 -0
  27. package/dist/analyzers/coverage-runner.js.map +1 -0
  28. package/dist/analyzers/dashboard/index.d.ts +24 -0
  29. package/dist/analyzers/dashboard/index.d.ts.map +1 -0
  30. package/dist/analyzers/dashboard/index.js +666 -0
  31. package/dist/analyzers/dashboard/index.js.map +1 -0
  32. package/dist/analyzers/developer/gather.d.ts.map +1 -1
  33. package/dist/analyzers/developer/gather.js +205 -37
  34. package/dist/analyzers/developer/gather.js.map +1 -1
  35. package/dist/analyzers/developer/index.d.ts +1 -1
  36. package/dist/analyzers/developer/index.d.ts.map +1 -1
  37. package/dist/analyzers/developer/index.js +19 -8
  38. package/dist/analyzers/developer/index.js.map +1 -1
  39. package/dist/analyzers/dispatcher.d.ts +37 -0
  40. package/dist/analyzers/dispatcher.d.ts.map +1 -1
  41. package/dist/analyzers/dispatcher.js +56 -9
  42. package/dist/analyzers/dispatcher.js.map +1 -1
  43. package/dist/analyzers/docs/shallow.d.ts +17 -5
  44. package/dist/analyzers/docs/shallow.d.ts.map +1 -1
  45. package/dist/analyzers/docs/shallow.js +65 -2
  46. package/dist/analyzers/docs/shallow.js.map +1 -1
  47. package/dist/analyzers/dx/shallow.d.ts +17 -5
  48. package/dist/analyzers/dx/shallow.d.ts.map +1 -1
  49. package/dist/analyzers/dx/shallow.js +66 -2
  50. package/dist/analyzers/dx/shallow.js.map +1 -1
  51. package/dist/analyzers/health/actions.d.ts +1 -1
  52. package/dist/analyzers/health/actions.d.ts.map +1 -1
  53. package/dist/analyzers/health/actions.js +27 -9
  54. package/dist/analyzers/health/actions.js.map +1 -1
  55. package/dist/analyzers/health/detailed.d.ts +2 -1
  56. package/dist/analyzers/health/detailed.d.ts.map +1 -1
  57. package/dist/analyzers/health/detailed.js +11 -7
  58. package/dist/analyzers/health/detailed.js.map +1 -1
  59. package/dist/analyzers/health.d.ts +27 -0
  60. package/dist/analyzers/health.d.ts.map +1 -1
  61. package/dist/analyzers/health.js +271 -33
  62. package/dist/analyzers/health.js.map +1 -1
  63. package/dist/analyzers/licenses/gather.d.ts +35 -8
  64. package/dist/analyzers/licenses/gather.d.ts.map +1 -1
  65. package/dist/analyzers/licenses/gather.js +70 -13
  66. package/dist/analyzers/licenses/gather.js.map +1 -1
  67. package/dist/analyzers/licenses/index.d.ts +1 -1
  68. package/dist/analyzers/licenses/index.d.ts.map +1 -1
  69. package/dist/analyzers/licenses/index.js +52 -11
  70. package/dist/analyzers/licenses/index.js.map +1 -1
  71. package/dist/analyzers/licenses/types.d.ts +15 -0
  72. package/dist/analyzers/licenses/types.d.ts.map +1 -1
  73. package/dist/analyzers/maintainability/shallow.d.ts +17 -5
  74. package/dist/analyzers/maintainability/shallow.d.ts.map +1 -1
  75. package/dist/analyzers/maintainability/shallow.js +80 -2
  76. package/dist/analyzers/maintainability/shallow.js.map +1 -1
  77. package/dist/analyzers/quality/detailed.d.ts.map +1 -1
  78. package/dist/analyzers/quality/detailed.js +4 -6
  79. package/dist/analyzers/quality/detailed.js.map +1 -1
  80. package/dist/analyzers/quality/gather.d.ts +1 -14
  81. package/dist/analyzers/quality/gather.d.ts.map +1 -1
  82. package/dist/analyzers/quality/gather.js +48 -137
  83. package/dist/analyzers/quality/gather.js.map +1 -1
  84. package/dist/analyzers/quality/index.d.ts +9 -2
  85. package/dist/analyzers/quality/index.d.ts.map +1 -1
  86. package/dist/analyzers/quality/index.js +189 -117
  87. package/dist/analyzers/quality/index.js.map +1 -1
  88. package/dist/analyzers/quality/shallow.d.ts +50 -5
  89. package/dist/analyzers/quality/shallow.d.ts.map +1 -1
  90. package/dist/analyzers/quality/shallow.js +155 -2
  91. package/dist/analyzers/quality/shallow.js.map +1 -1
  92. package/dist/analyzers/quality/types.d.ts +14 -0
  93. package/dist/analyzers/quality/types.d.ts.map +1 -1
  94. package/dist/analyzers/security/actions.d.ts +11 -4
  95. package/dist/analyzers/security/actions.d.ts.map +1 -1
  96. package/dist/analyzers/security/actions.js +87 -37
  97. package/dist/analyzers/security/actions.js.map +1 -1
  98. package/dist/analyzers/security/aggregator.d.ts +236 -0
  99. package/dist/analyzers/security/aggregator.d.ts.map +1 -0
  100. package/dist/analyzers/security/aggregator.js +347 -0
  101. package/dist/analyzers/security/aggregator.js.map +1 -0
  102. package/dist/analyzers/security/detailed.d.ts +2 -2
  103. package/dist/analyzers/security/detailed.d.ts.map +1 -1
  104. package/dist/analyzers/security/detailed.js +10 -9
  105. package/dist/analyzers/security/detailed.js.map +1 -1
  106. package/dist/analyzers/security/gather.d.ts +103 -1
  107. package/dist/analyzers/security/gather.d.ts.map +1 -1
  108. package/dist/analyzers/security/gather.js +281 -9
  109. package/dist/analyzers/security/gather.js.map +1 -1
  110. package/dist/analyzers/security/index.d.ts +15 -0
  111. package/dist/analyzers/security/index.d.ts.map +1 -1
  112. package/dist/analyzers/security/index.js +463 -50
  113. package/dist/analyzers/security/index.js.map +1 -1
  114. package/dist/analyzers/security/shallow.d.ts +50 -6
  115. package/dist/analyzers/security/shallow.d.ts.map +1 -1
  116. package/dist/analyzers/security/shallow.js +154 -2
  117. package/dist/analyzers/security/shallow.js.map +1 -1
  118. package/dist/analyzers/security/types.d.ts +51 -0
  119. package/dist/analyzers/security/types.d.ts.map +1 -1
  120. package/dist/analyzers/tests/detailed.d.ts.map +1 -1
  121. package/dist/analyzers/tests/detailed.js +2 -3
  122. package/dist/analyzers/tests/detailed.js.map +1 -1
  123. package/dist/analyzers/tests/gather.d.ts +2 -1
  124. package/dist/analyzers/tests/gather.d.ts.map +1 -1
  125. package/dist/analyzers/tests/gather.js +98 -69
  126. package/dist/analyzers/tests/gather.js.map +1 -1
  127. package/dist/analyzers/tests/index.d.ts +11 -2
  128. package/dist/analyzers/tests/index.d.ts.map +1 -1
  129. package/dist/analyzers/tests/index.js +85 -18
  130. package/dist/analyzers/tests/index.js.map +1 -1
  131. package/dist/analyzers/tests/shallow.d.ts +19 -5
  132. package/dist/analyzers/tests/shallow.d.ts.map +1 -1
  133. package/dist/analyzers/tests/shallow.js +89 -2
  134. package/dist/analyzers/tests/shallow.js.map +1 -1
  135. package/dist/analyzers/tests/types.d.ts +41 -1
  136. package/dist/analyzers/tests/types.d.ts.map +1 -1
  137. package/dist/analyzers/tools/autogen-header.d.ts +8 -0
  138. package/dist/analyzers/tools/autogen-header.d.ts.map +1 -0
  139. package/dist/analyzers/tools/autogen-header.js +107 -0
  140. package/dist/analyzers/tools/autogen-header.js.map +1 -0
  141. package/dist/analyzers/tools/cloc.d.ts.map +1 -1
  142. package/dist/analyzers/tools/cloc.js +36 -5
  143. package/dist/analyzers/tools/cloc.js.map +1 -1
  144. package/dist/analyzers/tools/coverage.d.ts +1 -1
  145. package/dist/analyzers/tools/coverage.d.ts.map +1 -1
  146. package/dist/analyzers/tools/coverage.js.map +1 -1
  147. package/dist/analyzers/tools/debug-statements.d.ts +17 -0
  148. package/dist/analyzers/tools/debug-statements.d.ts.map +1 -0
  149. package/dist/analyzers/tools/debug-statements.js +58 -0
  150. package/dist/analyzers/tools/debug-statements.js.map +1 -0
  151. package/dist/analyzers/tools/default-exclusions.gitignore +28 -0
  152. package/dist/analyzers/tools/exclusions.d.ts +33 -6
  153. package/dist/analyzers/tools/exclusions.d.ts.map +1 -1
  154. package/dist/analyzers/tools/exclusions.js +95 -26
  155. package/dist/analyzers/tools/exclusions.js.map +1 -1
  156. package/dist/analyzers/tools/generic.d.ts +17 -2
  157. package/dist/analyzers/tools/generic.d.ts.map +1 -1
  158. package/dist/analyzers/tools/generic.js +206 -109
  159. package/dist/analyzers/tools/generic.js.map +1 -1
  160. package/dist/analyzers/tools/gitleaks.d.ts.map +1 -1
  161. package/dist/analyzers/tools/gitleaks.js +48 -1
  162. package/dist/analyzers/tools/gitleaks.js.map +1 -1
  163. package/dist/analyzers/tools/graphify.d.ts +30 -2
  164. package/dist/analyzers/tools/graphify.d.ts.map +1 -1
  165. package/dist/analyzers/tools/graphify.js +131 -15
  166. package/dist/analyzers/tools/graphify.js.map +1 -1
  167. package/dist/analyzers/tools/jscpd.d.ts +12 -2
  168. package/dist/analyzers/tools/jscpd.d.ts.map +1 -1
  169. package/dist/analyzers/tools/jscpd.js +129 -6
  170. package/dist/analyzers/tools/jscpd.js.map +1 -1
  171. package/dist/analyzers/tools/minified-detection.d.ts +9 -0
  172. package/dist/analyzers/tools/minified-detection.d.ts.map +1 -0
  173. package/dist/analyzers/tools/minified-detection.js +147 -0
  174. package/dist/analyzers/tools/minified-detection.js.map +1 -0
  175. package/dist/analyzers/tools/nuget-package-reference.d.ts +131 -0
  176. package/dist/analyzers/tools/nuget-package-reference.d.ts.map +1 -0
  177. package/dist/analyzers/tools/nuget-package-reference.js +175 -0
  178. package/dist/analyzers/tools/nuget-package-reference.js.map +1 -0
  179. package/dist/analyzers/tools/osv-scanner-deps.d.ts +48 -0
  180. package/dist/analyzers/tools/osv-scanner-deps.d.ts.map +1 -0
  181. package/dist/analyzers/tools/{osv-scanner-maven.js → osv-scanner-deps.js} +78 -46
  182. package/dist/analyzers/tools/osv-scanner-deps.js.map +1 -0
  183. package/dist/analyzers/tools/osv.d.ts +36 -0
  184. package/dist/analyzers/tools/osv.d.ts.map +1 -1
  185. package/dist/analyzers/tools/osv.js +26 -0
  186. package/dist/analyzers/tools/osv.js.map +1 -1
  187. package/dist/analyzers/tools/parallel.d.ts +1 -1
  188. package/dist/analyzers/tools/parallel.d.ts.map +1 -1
  189. package/dist/analyzers/tools/parallel.js +2 -2
  190. package/dist/analyzers/tools/parallel.js.map +1 -1
  191. package/dist/analyzers/tools/risk-score.d.ts +7 -0
  192. package/dist/analyzers/tools/risk-score.d.ts.map +1 -1
  193. package/dist/analyzers/tools/risk-score.js +9 -2
  194. package/dist/analyzers/tools/risk-score.js.map +1 -1
  195. package/dist/analyzers/tools/run-tests-helper.d.ts +43 -0
  196. package/dist/analyzers/tools/run-tests-helper.d.ts.map +1 -0
  197. package/dist/analyzers/tools/run-tests-helper.js +156 -0
  198. package/dist/analyzers/tools/run-tests-helper.js.map +1 -0
  199. package/dist/analyzers/tools/runner.d.ts.map +1 -1
  200. package/dist/analyzers/tools/runner.js +75 -12
  201. package/dist/analyzers/tools/runner.js.map +1 -1
  202. package/dist/analyzers/tools/semgrep.d.ts +39 -2
  203. package/dist/analyzers/tools/semgrep.d.ts.map +1 -1
  204. package/dist/analyzers/tools/semgrep.js +131 -9
  205. package/dist/analyzers/tools/semgrep.js.map +1 -1
  206. package/dist/analyzers/tools/timing.d.ts +17 -3
  207. package/dist/analyzers/tools/timing.d.ts.map +1 -1
  208. package/dist/analyzers/tools/timing.js +36 -14
  209. package/dist/analyzers/tools/timing.js.map +1 -1
  210. package/dist/analyzers/tools/tool-registry.d.ts +10 -0
  211. package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
  212. package/dist/analyzers/tools/tool-registry.js +120 -1
  213. package/dist/analyzers/tools/tool-registry.js.map +1 -1
  214. package/dist/analyzers/tools/tools-unavailable-prose.d.ts +18 -0
  215. package/dist/analyzers/tools/tools-unavailable-prose.d.ts.map +1 -0
  216. package/dist/analyzers/tools/tools-unavailable-prose.js +69 -0
  217. package/dist/analyzers/tools/tools-unavailable-prose.js.map +1 -0
  218. package/dist/analyzers/tools/upgrade-plan-resolver.d.ts.map +1 -1
  219. package/dist/analyzers/tools/upgrade-plan-resolver.js +7 -0
  220. package/dist/analyzers/tools/upgrade-plan-resolver.js.map +1 -1
  221. package/dist/analyzers/tools/vendored-advisor.d.ts +43 -0
  222. package/dist/analyzers/tools/vendored-advisor.d.ts.map +1 -0
  223. package/dist/analyzers/tools/vendored-advisor.js +107 -0
  224. package/dist/analyzers/tools/vendored-advisor.js.map +1 -0
  225. package/dist/analyzers/tools/walk-paths.d.ts +78 -0
  226. package/dist/analyzers/tools/walk-paths.d.ts.map +1 -0
  227. package/dist/analyzers/tools/walk-paths.js +150 -0
  228. package/dist/analyzers/tools/walk-paths.js.map +1 -0
  229. package/dist/analyzers/tools/walk-source-files.d.ts +70 -0
  230. package/dist/analyzers/tools/walk-source-files.d.ts.map +1 -0
  231. package/dist/analyzers/tools/walk-source-files.js +369 -0
  232. package/dist/analyzers/tools/walk-source-files.js.map +1 -0
  233. package/dist/analyzers/types.d.ts +204 -4
  234. package/dist/analyzers/types.d.ts.map +1 -1
  235. package/dist/analyzers/xlsx/bom.d.ts.map +1 -1
  236. package/dist/analyzers/xlsx/bom.js +8 -1
  237. package/dist/analyzers/xlsx/bom.js.map +1 -1
  238. package/dist/cli.d.ts.map +1 -1
  239. package/dist/cli.js +557 -189
  240. package/dist/cli.js.map +1 -1
  241. package/dist/constants.d.ts +1 -0
  242. package/dist/constants.d.ts.map +1 -1
  243. package/dist/detect.d.ts.map +1 -1
  244. package/dist/detect.js +24 -7
  245. package/dist/detect.js.map +1 -1
  246. package/dist/doctor.d.ts.map +1 -1
  247. package/dist/doctor.js +103 -53
  248. package/dist/doctor.js.map +1 -1
  249. package/dist/languages/capabilities/provider.d.ts +130 -1
  250. package/dist/languages/capabilities/provider.d.ts.map +1 -1
  251. package/dist/languages/capabilities/types.d.ts +68 -7
  252. package/dist/languages/capabilities/types.d.ts.map +1 -1
  253. package/dist/languages/csharp.d.ts +15 -1
  254. package/dist/languages/csharp.d.ts.map +1 -1
  255. package/dist/languages/csharp.js +624 -146
  256. package/dist/languages/csharp.js.map +1 -1
  257. package/dist/languages/go.d.ts.map +1 -1
  258. package/dist/languages/go.js +89 -11
  259. package/dist/languages/go.js.map +1 -1
  260. package/dist/languages/index.d.ts +131 -2
  261. package/dist/languages/index.d.ts.map +1 -1
  262. package/dist/languages/index.js +208 -0
  263. package/dist/languages/index.js.map +1 -1
  264. package/dist/languages/java.d.ts.map +1 -1
  265. package/dist/languages/java.js +121 -32
  266. package/dist/languages/java.js.map +1 -1
  267. package/dist/languages/kotlin.d.ts.map +1 -1
  268. package/dist/languages/kotlin.js +140 -32
  269. package/dist/languages/kotlin.js.map +1 -1
  270. package/dist/languages/python.d.ts.map +1 -1
  271. package/dist/languages/python.js +149 -44
  272. package/dist/languages/python.js.map +1 -1
  273. package/dist/languages/ruby.d.ts +115 -0
  274. package/dist/languages/ruby.d.ts.map +1 -0
  275. package/dist/languages/ruby.js +665 -0
  276. package/dist/languages/ruby.js.map +1 -0
  277. package/dist/languages/rust.d.ts.map +1 -1
  278. package/dist/languages/rust.js +103 -16
  279. package/dist/languages/rust.js.map +1 -1
  280. package/dist/languages/types.d.ts +228 -5
  281. package/dist/languages/types.d.ts.map +1 -1
  282. package/dist/languages/typescript.d.ts.map +1 -1
  283. package/dist/languages/typescript.js +201 -14
  284. package/dist/languages/typescript.js.map +1 -1
  285. package/dist/scoring/dimensions/documentation.d.ts +53 -0
  286. package/dist/scoring/dimensions/documentation.d.ts.map +1 -0
  287. package/dist/scoring/dimensions/documentation.js +106 -0
  288. package/dist/scoring/dimensions/documentation.js.map +1 -0
  289. package/dist/scoring/dimensions/dx.d.ts +53 -0
  290. package/dist/scoring/dimensions/dx.d.ts.map +1 -0
  291. package/dist/scoring/dimensions/dx.js +105 -0
  292. package/dist/scoring/dimensions/dx.js.map +1 -0
  293. package/dist/scoring/dimensions/maintainability.d.ts +53 -0
  294. package/dist/scoring/dimensions/maintainability.d.ts.map +1 -0
  295. package/dist/scoring/dimensions/maintainability.js +101 -0
  296. package/dist/scoring/dimensions/maintainability.js.map +1 -0
  297. package/dist/scoring/dimensions/quality.d.ts +108 -0
  298. package/dist/scoring/dimensions/quality.d.ts.map +1 -0
  299. package/dist/scoring/dimensions/quality.js +174 -0
  300. package/dist/scoring/dimensions/quality.js.map +1 -0
  301. package/dist/scoring/dimensions/security.d.ts +84 -0
  302. package/dist/scoring/dimensions/security.d.ts.map +1 -0
  303. package/dist/scoring/dimensions/security.js +135 -0
  304. package/dist/scoring/dimensions/security.js.map +1 -0
  305. package/dist/scoring/dimensions/testing.d.ts +56 -0
  306. package/dist/scoring/dimensions/testing.d.ts.map +1 -0
  307. package/dist/scoring/dimensions/testing.js +98 -0
  308. package/dist/scoring/dimensions/testing.js.map +1 -0
  309. package/dist/scoring/evaluator.d.ts +27 -0
  310. package/dist/scoring/evaluator.d.ts.map +1 -0
  311. package/dist/scoring/evaluator.js +124 -0
  312. package/dist/scoring/evaluator.js.map +1 -0
  313. package/dist/scoring/format.d.ts +34 -0
  314. package/dist/scoring/format.d.ts.map +1 -0
  315. package/dist/scoring/format.js +63 -0
  316. package/dist/scoring/format.js.map +1 -0
  317. package/dist/scoring/index.d.ts +37 -0
  318. package/dist/scoring/index.d.ts.map +1 -0
  319. package/dist/scoring/index.js +57 -0
  320. package/dist/scoring/index.js.map +1 -0
  321. package/dist/scoring/overall.d.ts +54 -0
  322. package/dist/scoring/overall.d.ts.map +1 -0
  323. package/dist/scoring/overall.js +76 -0
  324. package/dist/scoring/overall.js.map +1 -0
  325. package/dist/scoring/result.d.ts +111 -0
  326. package/dist/scoring/result.d.ts.map +1 -0
  327. package/dist/scoring/result.js +14 -0
  328. package/dist/scoring/result.js.map +1 -0
  329. package/dist/scoring/spec.d.ts +76 -0
  330. package/dist/scoring/spec.d.ts.map +1 -0
  331. package/dist/scoring/spec.js +22 -0
  332. package/dist/scoring/spec.js.map +1 -0
  333. package/dist/scoring/thresholds.d.ts +56 -0
  334. package/dist/scoring/thresholds.d.ts.map +1 -0
  335. package/dist/scoring/thresholds.js +75 -0
  336. package/dist/scoring/thresholds.js.map +1 -0
  337. package/dist/tools-cli.d.ts.map +1 -1
  338. package/dist/tools-cli.js +21 -2
  339. package/dist/tools-cli.js.map +1 -1
  340. package/dist/types.d.ts +17 -1
  341. package/dist/types.d.ts.map +1 -1
  342. package/package.json +1 -1
  343. package/templates/.claude/commands/dashboard.md +17 -9
  344. package/templates/.claude/rules/ruby.md +11 -0
  345. package/templates/configs/ruby/README.md +6 -0
  346. package/dist/analyzers/scoring.d.ts +0 -49
  347. package/dist/analyzers/scoring.d.ts.map +0 -1
  348. package/dist/analyzers/scoring.js +0 -422
  349. package/dist/analyzers/scoring.js.map +0 -1
  350. package/dist/analyzers/security/scoring.d.ts +0 -29
  351. package/dist/analyzers/security/scoring.d.ts.map +0 -1
  352. package/dist/analyzers/security/scoring.js +0 -40
  353. package/dist/analyzers/security/scoring.js.map +0 -1
  354. package/dist/analyzers/tools/osv-scanner-maven.d.ts +0 -42
  355. package/dist/analyzers/tools/osv-scanner-maven.d.ts.map +0 -1
  356. package/dist/analyzers/tools/osv-scanner-maven.js.map +0 -1
@@ -0,0 +1,665 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ruby = void 0;
37
+ exports.extractRubyImportsRaw = extractRubyImportsRaw;
38
+ exports.mapRubocopSeverity = mapRubocopSeverity;
39
+ exports.parseRubocopOutput = parseRubocopOutput;
40
+ exports.parseSimpleCovResultset = parseSimpleCovResultset;
41
+ exports.gatherSimpleCovOutcome = gatherSimpleCovOutcome;
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ const coverage_1 = require("../analyzers/tools/coverage");
45
+ const walk_paths_1 = require("../analyzers/tools/walk-paths");
46
+ const exclusions_1 = require("../analyzers/tools/exclusions");
47
+ const osv_scanner_deps_1 = require("../analyzers/tools/osv-scanner-deps");
48
+ const runner_1 = require("../analyzers/tools/runner");
49
+ const run_tests_helper_1 = require("../analyzers/tools/run-tests-helper");
50
+ const tool_registry_1 = require("../analyzers/tools/tool-registry");
51
+ // ─── Detection ──────────────────────────────────────────────────────────────
52
+ /**
53
+ * Walk the project tree (bounded depth) looking for a `.rb` source file.
54
+ * G9 discipline (Recipe v3): manifest-only detection (Gemfile alone)
55
+ * over-activates on mixed-stack repos and scaffolded-but-empty projects.
56
+ * The pack only matters when there is actual Ruby source to analyze.
57
+ */
58
+ function detectRuby(cwd) {
59
+ // Depth-unlimited via the canonical walker. The previous depth-5
60
+ // cap missed nested Ruby projects in monorepos and engines layouts.
61
+ return (0, walk_paths_1.walkPaths)(cwd, { extensions: ['.rb'] }).length > 0;
62
+ }
63
+ // ─── Imports (regex extraction, no resolver) ────────────────────────────────
64
+ /**
65
+ * Capture Ruby require / require_relative / autoload specifiers from source
66
+ * text. Three forms recognised:
67
+ *
68
+ * require 'json' → 'json'
69
+ * require_relative '../foo/bar' → '../foo/bar'
70
+ * autoload :Sym, 'foo/bar' → 'foo/bar'
71
+ *
72
+ * Ruby's metaprogramming (`__send__`, `Object.const_missing`, Rails'
73
+ * Zeitwerk autoloader) makes static import analysis fundamentally
74
+ * best-effort — many "imports" in idiomatic Ruby never appear as
75
+ * literal `require` calls. This parser extracts the literal-string
76
+ * cases only; downstream consumers should treat the output as a lower
77
+ * bound. Future v4 candidate: explicit best-effort contract on the
78
+ * imports envelope so consumers can distinguish "exhaustive" (TS, Go)
79
+ * from "best-effort" (Ruby, kotlin/Java reflection paths).
80
+ *
81
+ * Comments are stripped (single-line `#`) before matching so a
82
+ * commented-out `# require 'foo'` does not false-match. Multi-line
83
+ * `=begin ... =end` blocks containing requires are not extracted
84
+ * (acceptable: comment-out-import is intentional non-use).
85
+ *
86
+ * Both single and double quotes are accepted; dynamic `require x` (no
87
+ * literal string) is skipped — there is no specifier to capture.
88
+ *
89
+ * Exported for unit tests; consumed by `gatherRubyImportsResult`.
90
+ */
91
+ function extractRubyImportsRaw(content) {
92
+ const out = [];
93
+ // Strip line comments first so `# require 'foo'` doesn't false-match.
94
+ // Conservative: only `#` at start-of-line or after whitespace, to avoid
95
+ // mangling `#{interpolation}` inside double-quoted strings.
96
+ const stripped = content.replace(/(^|\s)#[^\n]*/g, '$1');
97
+ const requireRe = /^\s*(?:require|require_relative)\s+['"]([^'"]+)['"]/gm;
98
+ let m;
99
+ while ((m = requireRe.exec(stripped)) !== null) {
100
+ out.push(m[1]);
101
+ }
102
+ // autoload :Sym, 'path' — capture the path arg only (the symbol is the
103
+ // local binding name, not the import target).
104
+ const autoloadRe = /^\s*autoload\s+:[A-Za-z_]\w*\s*,\s*['"]([^'"]+)['"]/gm;
105
+ while ((m = autoloadRe.exec(stripped)) !== null) {
106
+ out.push(m[1]);
107
+ }
108
+ return out;
109
+ }
110
+ /**
111
+ * Enumerate `.rb` files under cwd and capture per-file imports. Ruby has
112
+ * no file-level resolver — `require 'foo'` searches `$LOAD_PATH` (a
113
+ * runtime-mutable array), Rails projects defer wholly to Zeitwerk's
114
+ * convention-based autoload, and `require_relative` paths sometimes
115
+ * lack the `.rb` extension. Mirrors rust/kotlin/csharp/java packs:
116
+ * `extracted` is populated for completeness, `edges` is always empty,
117
+ * file-level resolution is left to graphify if downstream consumers
118
+ * need it.
119
+ */
120
+ function gatherRubyImportsResult(cwd) {
121
+ const excludes = (0, exclusions_1.getFindExcludeFlags)(cwd);
122
+ const raw = (0, runner_1.run)(`find . -type f -name "*.rb" ${excludes} 2>/dev/null`, cwd);
123
+ if (!raw)
124
+ return null;
125
+ const extracted = new Map();
126
+ for (const line of raw.split('\n')) {
127
+ const p = line.trim();
128
+ if (!p)
129
+ continue;
130
+ const rel = p.replace(/^\.\//, '');
131
+ let content;
132
+ try {
133
+ content = fs.readFileSync(path.join(cwd, rel), 'utf-8');
134
+ }
135
+ catch {
136
+ continue;
137
+ }
138
+ extracted.set(rel, extractRubyImportsRaw(content));
139
+ }
140
+ if (extracted.size === 0)
141
+ return null;
142
+ return {
143
+ schemaVersion: 1,
144
+ tool: 'ruby-imports',
145
+ sourceExtensions: ['.rb'],
146
+ extracted,
147
+ edges: new Map(),
148
+ };
149
+ }
150
+ const rubyImportsProvider = {
151
+ source: 'ruby',
152
+ async gather(cwd) {
153
+ return gatherRubyImportsResult(cwd);
154
+ },
155
+ };
156
+ // ─── Test framework (Gemfile / Gemfile.lock text scan) ──────────────────────
157
+ /**
158
+ * Detect the Ruby test framework by scanning Gemfile + Gemfile.lock for
159
+ * known gem names. Order of precedence: rspec → minitest → test-unit.
160
+ *
161
+ * - RSpec ('rspec', 'rspec-rails') — by far the most common Ruby
162
+ * test runner, takes precedence when present.
163
+ * - Minitest — Ruby stdlib's runner, often used directly or via
164
+ * Rails' default `test/` directory.
165
+ * - test-unit — Ruby 1.8-era runner; still used by some legacy
166
+ * projects and by Ruby itself's stdlib tests.
167
+ *
168
+ * Falls back to test-file glob counts when no Gemfile is present (a
169
+ * vendored library directory or scratch script repo). The glob counts
170
+ * mirror the test patterns declared on the pack: `*_spec.rb` → rspec,
171
+ * `*_test.rb` / `test_*.rb` → minitest.
172
+ *
173
+ * Returns null when nothing identifies a framework — analyzers should
174
+ * treat null as "test-runner unknown" rather than "no tests."
175
+ */
176
+ function gatherRubyTestFrameworkResult(cwd) {
177
+ const manifests = ['Gemfile', 'Gemfile.lock'];
178
+ let combined = '';
179
+ for (const rel of manifests) {
180
+ if (!(0, runner_1.fileExists)(cwd, rel))
181
+ continue;
182
+ try {
183
+ combined += fs.readFileSync(path.join(cwd, rel), 'utf-8') + '\n';
184
+ }
185
+ catch {
186
+ /* ignore unreadable */
187
+ }
188
+ }
189
+ if (combined) {
190
+ if (/\brspec(?:-rails)?\b/.test(combined)) {
191
+ return { schemaVersion: 1, tool: 'ruby', name: 'rspec' };
192
+ }
193
+ if (/\bminitest\b/.test(combined)) {
194
+ return { schemaVersion: 1, tool: 'ruby', name: 'minitest' };
195
+ }
196
+ if (/\btest-unit\b/.test(combined)) {
197
+ return { schemaVersion: 1, tool: 'ruby', name: 'test-unit' };
198
+ }
199
+ }
200
+ // Glob-count fallback: no Gemfile (or Gemfile mentions no known runner).
201
+ // Run two cheap finds and pick the framework whose convention dominates.
202
+ const excludes = (0, exclusions_1.getFindExcludeFlags)(cwd);
203
+ const specCount = (0, runner_1.run)(`find . -type f -name "*_spec.rb" ${excludes} 2>/dev/null | wc -l`, cwd);
204
+ const testCount = (0, runner_1.run)(`find . -type f \\( -name "*_test.rb" -o -name "test_*.rb" \\) ${excludes} 2>/dev/null | wc -l`, cwd);
205
+ const specs = parseInt(specCount, 10) || 0;
206
+ const tests = parseInt(testCount, 10) || 0;
207
+ if (specs === 0 && tests === 0)
208
+ return null;
209
+ return {
210
+ schemaVersion: 1,
211
+ tool: 'ruby',
212
+ name: specs >= tests ? 'rspec' : 'minitest',
213
+ };
214
+ }
215
+ const rubyTestFrameworkProvider = {
216
+ source: 'ruby',
217
+ async gather(cwd) {
218
+ return gatherRubyTestFrameworkResult(cwd);
219
+ },
220
+ };
221
+ // ─── Lint (rubocop --format json) ───────────────────────────────────────────
222
+ /**
223
+ * Map RuboCop's severity strings to dxkit's four-tier scheme. RuboCop
224
+ * canonically emits 5 severities (see `RuboCop::Cop::Severity::CODES`
225
+ * in the upstream source — `lib/rubocop/cop/severity.rb`):
226
+ *
227
+ * - `convention` → low (style + naming — the bulk of findings)
228
+ * - `refactor` → low (complexity hints; Metrics/* cops)
229
+ * - `warning` → medium (Lint/* cops — actual code-quality risk)
230
+ * - `error` → high (real defects; rare in default config)
231
+ * - `fatal` → critical (rubocop-internal failure or syntax error)
232
+ *
233
+ * Defensive `'low'` default for unknown severities — matches the
234
+ * mapDetektSeverity / mapRuffSeverity contract: never silently drop a
235
+ * finding, even if rubocop adds a new tier we don't recognize yet.
236
+ *
237
+ * Exported for unit tests.
238
+ */
239
+ function mapRubocopSeverity(severity) {
240
+ if (typeof severity !== 'string')
241
+ return 'low';
242
+ switch (severity.toLowerCase()) {
243
+ case 'fatal':
244
+ return 'critical';
245
+ case 'error':
246
+ return 'high';
247
+ case 'warning':
248
+ return 'medium';
249
+ case 'convention':
250
+ case 'refactor':
251
+ return 'low';
252
+ default:
253
+ return 'low';
254
+ }
255
+ }
256
+ /**
257
+ * Pure parser for RuboCop's JSON output (rubocop --format json). The
258
+ * shape is fixed per the upstream `RuboCop::Formatter::JSONFormatter`
259
+ * contract — `metadata` + `files[*].offenses[*]` + `summary`. We only
260
+ * need the offenses; metadata + summary are surface for future
261
+ * enrichment (per-file attribution, top-N rules) but not needed for
262
+ * the dxkit lint envelope which carries SeverityCounts only.
263
+ *
264
+ * Returns zero counts on malformed input rather than throwing —
265
+ * matches mapDetektSeverity / parseEslintFinal conventions. The
266
+ * gather function distinguishes "rubocop ran fine, found nothing"
267
+ * from "rubocop missing / parse error" via LintGatherOutcome's
268
+ * kind field.
269
+ *
270
+ * Exported for unit tests; consumed by `gatherRubyLintResult`.
271
+ */
272
+ function parseRubocopOutput(raw) {
273
+ const counts = { critical: 0, high: 0, medium: 0, low: 0 };
274
+ let data;
275
+ try {
276
+ data = JSON.parse(raw);
277
+ }
278
+ catch {
279
+ return counts;
280
+ }
281
+ for (const file of data.files ?? []) {
282
+ for (const offense of file.offenses ?? []) {
283
+ counts[mapRubocopSeverity(offense.severity)]++;
284
+ }
285
+ }
286
+ return counts;
287
+ }
288
+ /**
289
+ * Single source of truth for the ruby pack's lint gathering. Consumed
290
+ * by `rubyLintProvider` (capability dispatcher).
291
+ *
292
+ * RuboCop is invoked with `--format json` so we always get a
293
+ * machine-readable payload (the default formatter is human-text).
294
+ * Exit code: rubocop exits 1 when offenses are found, 0 when clean.
295
+ * We tolerate any exit code (rubocop writes valid JSON to stdout
296
+ * regardless) and rely on parseRubocopOutput's empty-on-malformed
297
+ * contract.
298
+ */
299
+ function gatherRubyLintResult(cwd) {
300
+ const rubocop = (0, tool_registry_1.findTool)(tool_registry_1.TOOL_DEFS.rubocop, cwd);
301
+ if (!rubocop.available || !rubocop.path) {
302
+ return { kind: 'unavailable', reason: 'not installed' };
303
+ }
304
+ const raw = (0, runner_1.run)(`${rubocop.path} --format json . 2>/dev/null`, cwd, 120000);
305
+ if (!raw) {
306
+ return { kind: 'unavailable', reason: 'no rubocop output' };
307
+ }
308
+ const counts = parseRubocopOutput(raw);
309
+ const envelope = { schemaVersion: 1, tool: 'rubocop', counts };
310
+ return { kind: 'success', envelope };
311
+ }
312
+ const rubyLintProvider = {
313
+ source: 'ruby',
314
+ async gather(cwd) {
315
+ const outcome = gatherRubyLintResult(cwd);
316
+ return outcome.kind === 'success' ? outcome.envelope : null;
317
+ },
318
+ };
319
+ /**
320
+ * Pure parser for SimpleCov `.resultset.json`. Returns null when the
321
+ * input has no parseable suites (empty file, missing `coverage` key,
322
+ * or malformed JSON) — distinct from "0% coverage" (where suites
323
+ * exist with zero hits).
324
+ *
325
+ * Exported for unit tests; consumed by `gatherSimpleCovCoverageResult`.
326
+ */
327
+ function parseSimpleCovResultset(raw, sourceFile, cwd) {
328
+ let data;
329
+ try {
330
+ data = JSON.parse(raw);
331
+ }
332
+ catch {
333
+ return null;
334
+ }
335
+ // Per-file line arrays unioned across suites (max per index).
336
+ const merged = new Map();
337
+ for (const suite of Object.values(data)) {
338
+ const cov = suite?.coverage;
339
+ if (!cov || typeof cov !== 'object')
340
+ continue;
341
+ for (const [absPath, entry] of Object.entries(cov)) {
342
+ const lines = entry?.lines;
343
+ if (!Array.isArray(lines))
344
+ continue;
345
+ const existing = merged.get(absPath);
346
+ if (!existing) {
347
+ merged.set(absPath, lines.slice());
348
+ continue;
349
+ }
350
+ // Union: per index, keep max(existing, new). null stays null only if
351
+ // both are null; any int wins over null; max int wins between two ints.
352
+ const len = Math.max(existing.length, lines.length);
353
+ const out = new Array(len);
354
+ for (let i = 0; i < len; i++) {
355
+ const a = existing[i] ?? null;
356
+ const b = lines[i] ?? null;
357
+ if (a === null && b === null)
358
+ out[i] = null;
359
+ else if (a === null)
360
+ out[i] = b;
361
+ else if (b === null)
362
+ out[i] = a;
363
+ else
364
+ out[i] = Math.max(a, b);
365
+ }
366
+ merged.set(absPath, out);
367
+ }
368
+ }
369
+ if (merged.size === 0)
370
+ return null;
371
+ const files = new Map();
372
+ let totalCovered = 0;
373
+ let totalExecutable = 0;
374
+ for (const [absPath, lines] of merged) {
375
+ let covered = 0;
376
+ let executable = 0;
377
+ for (const v of lines) {
378
+ if (v === null)
379
+ continue;
380
+ executable += 1;
381
+ if (v > 0)
382
+ covered += 1;
383
+ }
384
+ const rel = (0, coverage_1.toRelative)(absPath, cwd);
385
+ files.set(rel, {
386
+ path: rel,
387
+ covered,
388
+ total: executable,
389
+ pct: (0, coverage_1.round1)(executable > 0 ? (covered / executable) * 100 : 0),
390
+ });
391
+ totalCovered += covered;
392
+ totalExecutable += executable;
393
+ }
394
+ return {
395
+ source: 'simplecov',
396
+ sourceFile,
397
+ linePercent: (0, coverage_1.round1)(totalExecutable > 0 ? (totalCovered / totalExecutable) * 100 : 0),
398
+ files,
399
+ };
400
+ }
401
+ /**
402
+ * Probe SimpleCov's canonical artifact path. The default formatter
403
+ * writes `coverage/.resultset.json`; the simplecov-json gem writes
404
+ * `coverage/coverage.json` (less common). We probe the canonical
405
+ * path first — it ships with vanilla SimpleCov and is the most
406
+ * likely to exist.
407
+ */
408
+ function findSimpleCovResultset(cwd) {
409
+ const candidates = ['coverage/.resultset.json', 'coverage/coverage.json'];
410
+ for (const rel of candidates) {
411
+ if ((0, runner_1.fileExists)(cwd, rel))
412
+ return rel;
413
+ }
414
+ return null;
415
+ }
416
+ /**
417
+ * Probe SimpleCov state and produce the discriminated outcome. Three
418
+ * paths, all distinguishable downstream:
419
+ * 1. `success` — parseable JSON found at `.resultset.json` or
420
+ * `coverage.json`; envelope ready to ship.
421
+ * 2. `html-only` — `coverage/index.html` exists but no JSON;
422
+ * SimpleCov ran, but in a format we can't parse.
423
+ * Includes a hint string for the user.
424
+ * 3. `unavailable` — neither JSON nor HTML; tool didn't run.
425
+ */
426
+ function gatherSimpleCovOutcome(cwd) {
427
+ const reportRel = findSimpleCovResultset(cwd);
428
+ if (reportRel) {
429
+ try {
430
+ const raw = fs.readFileSync(path.join(cwd, reportRel), 'utf-8');
431
+ const coverage = parseSimpleCovResultset(raw, reportRel, cwd);
432
+ if (coverage) {
433
+ return {
434
+ kind: 'success',
435
+ envelope: { schemaVersion: 1, tool: `coverage:${coverage.source}`, coverage },
436
+ };
437
+ }
438
+ }
439
+ catch {
440
+ // Fall through to the html-only / unavailable check — a corrupt
441
+ // JSON shouldn't masquerade as "tool didn't run" when the user
442
+ // clearly did run SimpleCov (HTML is the tell).
443
+ }
444
+ }
445
+ if ((0, runner_1.fileExists)(cwd, 'coverage/index.html')) {
446
+ return {
447
+ kind: 'html-only',
448
+ hint: 'SimpleCov produced HTML output only. ' +
449
+ 'Install the simplecov-json gem to emit `coverage/coverage.json`, ' +
450
+ 'or keep the default formatter (which produces the binary intermediate ' +
451
+ '`coverage/.resultset.json` that dxkit also reads).',
452
+ };
453
+ }
454
+ return { kind: 'unavailable' };
455
+ }
456
+ /**
457
+ * Single source of truth for the ruby pack's coverage gathering.
458
+ * Consumed by `rubyCoverageProvider` (capability dispatcher).
459
+ *
460
+ * Thin adapter over `gatherSimpleCovOutcome`: collapses the three-way
461
+ * outcome to the dispatcher's binary `CoverageResult | null` contract.
462
+ * Callers that need the html-only signal should use
463
+ * `gatherSimpleCovOutcome` directly.
464
+ */
465
+ function gatherSimpleCovCoverageResult(cwd) {
466
+ const outcome = gatherSimpleCovOutcome(cwd);
467
+ return outcome.kind === 'success' ? outcome.envelope : null;
468
+ }
469
+ /**
470
+ * Check that SimpleCov is required + started in the project's
471
+ * `spec_helper.rb` or `rails_helper.rb`. Without this, `bundle exec
472
+ * rspec` runs cleanly but writes no `.resultset.json` — the user
473
+ * spends 30+ seconds running tests then sees "tests ran but no
474
+ * coverage artifact was produced." Better to short-circuit upfront
475
+ * with the actionable hint.
476
+ *
477
+ * Looks for the canonical setup form: `require 'simplecov'` followed
478
+ * eventually by `SimpleCov.start`. Tolerates double quotes and any
479
+ * whitespace. spec_helper / rails_helper are the conventional
480
+ * locations; we check both because Rails projects use the latter.
481
+ */
482
+ function simplecovIsRequired(cwd) {
483
+ const candidates = ['spec/spec_helper.rb', 'spec/rails_helper.rb', 'test/test_helper.rb'];
484
+ for (const c of candidates) {
485
+ const abs = path.join(cwd, c);
486
+ let raw;
487
+ try {
488
+ raw = fs.readFileSync(abs, 'utf-8');
489
+ }
490
+ catch {
491
+ continue;
492
+ }
493
+ const hasRequire = /\brequire\s+['"]simplecov['"]/.test(raw);
494
+ const hasStart = /\bSimpleCov\.start\b/.test(raw);
495
+ if (hasRequire && hasStart)
496
+ return true;
497
+ }
498
+ return false;
499
+ }
500
+ /**
501
+ * Run `bundle exec rspec` from cwd (D021).
502
+ *
503
+ * SimpleCov is the canonical Ruby coverage tool. It's required from
504
+ * `spec_helper.rb` (not invoked separately) and writes its resultset
505
+ * during the rspec run itself — `bundle exec rspec` is therefore the
506
+ * coverage command, no extra flags needed.
507
+ *
508
+ * Preflight (in order, cheapest first):
509
+ * 1. `Gemfile` must exist — without one, bundler can't resolve the
510
+ * gem set and rspec won't be invokable.
511
+ * 2. `simplecov` gem must be installed (registry-tracked via
512
+ * `TOOL_DEFS.simplecov`, library-only gem detected via
513
+ * `gemPackage`).
514
+ * 3. `simplecov` must be `require`d AND `SimpleCov.start` called in
515
+ * `spec_helper.rb` / `rails_helper.rb` / `test_helper.rb`. SimpleCov
516
+ * is opt-in per-project; merely installing the gem doesn't
517
+ * instrument the test run. This check matches the G_v4_3
518
+ * gatherSimpleCovOutcome shape (html-only outcome surfaces
519
+ * separately on the read side).
520
+ *
521
+ * If all three pass, rspec is invoked via bundler so it resolves to
522
+ * the project's pinned version + plugins. Artifact is the canonical
523
+ * `coverage/.resultset.json` that `gatherSimpleCovOutcome` reads.
524
+ */
525
+ function runRubyTestsWithCoverage(cwd) {
526
+ return Promise.resolve((0, run_tests_helper_1.runTestsWithCoverage)({
527
+ pack: 'ruby',
528
+ cmd: 'bundle exec rspec',
529
+ cwd,
530
+ artifact: 'coverage/.resultset.json',
531
+ preflight: (cwd) => {
532
+ if (!(0, runner_1.fileExists)(cwd, 'Gemfile')) {
533
+ return 'no Gemfile in this directory — not a Ruby/bundler project';
534
+ }
535
+ if (!(0, tool_registry_1.findTool)(tool_registry_1.TOOL_DEFS.simplecov, cwd).available) {
536
+ return 'simplecov gem not installed — run `vyuh-dxkit tools install`';
537
+ }
538
+ if (!simplecovIsRequired(cwd)) {
539
+ return "simplecov not required/started in spec_helper.rb — add `require 'simplecov'` + `SimpleCov.start` at the top";
540
+ }
541
+ return null;
542
+ },
543
+ }));
544
+ }
545
+ const rubyCoverageProvider = {
546
+ source: 'ruby',
547
+ async gather(cwd) {
548
+ return gatherSimpleCovCoverageResult(cwd);
549
+ },
550
+ async runTests(cwd) {
551
+ return runRubyTestsWithCoverage(cwd);
552
+ },
553
+ };
554
+ // ─── DepVulns (osv-scanner against Gemfile.lock) ────────────────────────────
555
+ //
556
+ // Parser + manifest discovery + tool invocation + CVSS resolution all
557
+ // live in `src/analyzers/tools/osv-scanner-deps.ts` — language-agnostic
558
+ // SSOT (CLAUDE.md rule #2). Same module powers kotlin/java's Maven
559
+ // scanning. ParseOsvScannerFindings is exported there for unit tests
560
+ // and is exercised by both Maven and RubyGems fixtures.
561
+ //
562
+ // bundler-audit alternative: deliberately NOT used. Its JSON output
563
+ // is unstable upstream (line-oriented text is the canonical format),
564
+ // and osv-scanner gives us SSOT consistency across Maven/RubyGems/PyPI
565
+ // + stable JSON + CVSS resolution + the same enrichment surface. If a
566
+ // future customer needs bundler-audit specifically (e.g. air-gapped
567
+ // env where osv.dev queries are unavailable), it can be added as a
568
+ // secondary tool without disturbing this primary path.
569
+ const RUBY_DEP_MANIFESTS = ['Gemfile.lock'];
570
+ const rubyDepVulnsProvider = {
571
+ source: 'ruby',
572
+ async gather(cwd) {
573
+ const outcome = await (0, osv_scanner_deps_1.gatherOsvScannerDepVulnsResult)(cwd, 'ruby', 'RubyGems', RUBY_DEP_MANIFESTS);
574
+ return outcome.kind === 'success' ? outcome.envelope : null;
575
+ },
576
+ async gatherOutcome(cwd) {
577
+ return (0, osv_scanner_deps_1.gatherOsvScannerDepVulnsResult)(cwd, 'ruby', 'RubyGems', RUBY_DEP_MANIFESTS);
578
+ },
579
+ };
580
+ // ─── Pack export ────────────────────────────────────────────────────────────
581
+ exports.ruby = {
582
+ id: 'ruby',
583
+ displayName: 'Ruby',
584
+ sourceExtensions: ['.rb'],
585
+ testFilePatterns: [
586
+ '*_spec.rb',
587
+ '*_test.rb',
588
+ 'test_*.rb',
589
+ 'spec/**/*_spec.rb',
590
+ 'test/**/*_test.rb',
591
+ ],
592
+ extraExcludes: ['vendor/bundle', '.bundle', 'coverage', 'tmp', 'log'],
593
+ // D027 (2.4.7): YARD documentation convention uses `##` block
594
+ // comments (distinguished from regular `#` line comments). Plain
595
+ // `#` would over-match every commented-out line; `##` is the
596
+ // documented-block marker.
597
+ docCommentPatterns: ['^[[:space:]]*##'],
598
+ // D034 (2.4.7): OpenSSL TLS-bypass idioms for Ruby's stdlib
599
+ // `net/http` and `httpclient` gems. `VERIFY_NONE` is the constant
600
+ // ruby code sets on `http.verify_mode` to disable cert checks.
601
+ tlsBypassPatterns: [
602
+ 'OpenSSL::SSL::VERIFY_NONE',
603
+ 'verify_mode[[:space:]]*=[[:space:]]*.*VERIFY_NONE',
604
+ ],
605
+ upgradeCommand(name, version) {
606
+ return `# Edit Gemfile: \`gem '${name}', '${version}'\`, then \`bundle install\``;
607
+ },
608
+ // Rails (`app/controllers/`, `app/services/`, `app/models/`,
609
+ // `app/views/`) is the dominant Ruby application shape. Sinatra
610
+ // and Hanami sometimes diverge but typically also adopt the Rails
611
+ // app/<role> convention. Paths are anchored at `/app/<role>/` to
612
+ // avoid matching a top-level `models/` directory in a non-Rails
613
+ // gem.
614
+ architecturalShape: {
615
+ primaryComponentPaths: [
616
+ '/app/controllers/',
617
+ '/app/services/',
618
+ '/app/jobs/',
619
+ '/app/helpers/',
620
+ '/app/views/',
621
+ '/app/channels/',
622
+ '/app/workers/',
623
+ ],
624
+ routePaths: ['/app/controllers/', '/app/channels/'],
625
+ modelPaths: ['/app/models/', '/app/serializers/'],
626
+ vocabulary: {
627
+ components: 'controllers/services',
628
+ models: 'models',
629
+ routes: 'routes',
630
+ },
631
+ testGapPriority: {
632
+ high: ['/app/controllers/', '/app/services/', '/app/jobs/', '/app/workers/'],
633
+ medium: ['/app/helpers/', '/app/views/', '/app/channels/', '/app/serializers/'],
634
+ },
635
+ },
636
+ clocLanguageNames: ['Ruby'],
637
+ detect: detectRuby,
638
+ tools: ['osv-scanner', 'rubocop', 'simplecov'],
639
+ semgrepRulesets: ['p/ruby'],
640
+ capabilities: {
641
+ imports: rubyImportsProvider,
642
+ testFramework: rubyTestFrameworkProvider,
643
+ coverage: rubyCoverageProvider,
644
+ lint: rubyLintProvider,
645
+ depVulns: rubyDepVulnsProvider,
646
+ },
647
+ mapLintSeverity: mapRubocopSeverity,
648
+ permissions: [
649
+ 'Bash(bundle:*)',
650
+ 'Bash(rake:*)',
651
+ 'Bash(rspec:*)',
652
+ 'Bash(rubocop:*)',
653
+ 'Bash(ruby:*)',
654
+ ],
655
+ ruleFile: 'ruby.md',
656
+ templateFiles: [],
657
+ cliBinaries: ['ruby', 'bundle'],
658
+ defaultVersion: '3.3.0',
659
+ projectYamlBlock: ({ config, enabled }) => [
660
+ ` ruby:`,
661
+ ` enabled: ${enabled}`,
662
+ ` version: "${config.versions['ruby'] ?? '3.3.0'}"`,
663
+ ].join('\n'),
664
+ };
665
+ //# sourceMappingURL=ruby.js.map