@lbroth/rothunter 1.0.0-rc.1

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 (269) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +141 -0
  3. package/dist/adapters/llm.d.ts +68 -0
  4. package/dist/adapters/llm.d.ts.map +1 -0
  5. package/dist/adapters/llm.js +189 -0
  6. package/dist/adapters/llm.js.map +1 -0
  7. package/dist/config.d.ts +37 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +81 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/detector-registry.d.ts +32 -0
  12. package/dist/detector-registry.d.ts.map +1 -0
  13. package/dist/detector-registry.js +74 -0
  14. package/dist/detector-registry.js.map +1 -0
  15. package/dist/detectors/api-race.d.ts +6 -0
  16. package/dist/detectors/api-race.d.ts.map +1 -0
  17. package/dist/detectors/api-race.js +222 -0
  18. package/dist/detectors/api-race.js.map +1 -0
  19. package/dist/detectors/bad-config.d.ts +6 -0
  20. package/dist/detectors/bad-config.d.ts.map +1 -0
  21. package/dist/detectors/bad-config.js +529 -0
  22. package/dist/detectors/bad-config.js.map +1 -0
  23. package/dist/detectors/console-log-prod.d.ts +6 -0
  24. package/dist/detectors/console-log-prod.d.ts.map +1 -0
  25. package/dist/detectors/console-log-prod.js +72 -0
  26. package/dist/detectors/console-log-prod.js.map +1 -0
  27. package/dist/detectors/dead-api.d.ts +10 -0
  28. package/dist/detectors/dead-api.d.ts.map +1 -0
  29. package/dist/detectors/dead-api.js +115 -0
  30. package/dist/detectors/dead-api.js.map +1 -0
  31. package/dist/detectors/dead-export.d.ts +12 -0
  32. package/dist/detectors/dead-export.d.ts.map +1 -0
  33. package/dist/detectors/dead-export.js +140 -0
  34. package/dist/detectors/dead-export.js.map +1 -0
  35. package/dist/detectors/dead-handler.d.ts +12 -0
  36. package/dist/detectors/dead-handler.d.ts.map +1 -0
  37. package/dist/detectors/dead-handler.js +40 -0
  38. package/dist/detectors/dead-handler.js.map +1 -0
  39. package/dist/detectors/dead-module.d.ts +14 -0
  40. package/dist/detectors/dead-module.d.ts.map +1 -0
  41. package/dist/detectors/dead-module.js +50 -0
  42. package/dist/detectors/dead-module.js.map +1 -0
  43. package/dist/detectors/deep-nesting.d.ts +12 -0
  44. package/dist/detectors/deep-nesting.d.ts.map +1 -0
  45. package/dist/detectors/deep-nesting.js +133 -0
  46. package/dist/detectors/deep-nesting.js.map +1 -0
  47. package/dist/detectors/duplicate-function.d.ts +9 -0
  48. package/dist/detectors/duplicate-function.d.ts.map +1 -0
  49. package/dist/detectors/duplicate-function.js +199 -0
  50. package/dist/detectors/duplicate-function.js.map +1 -0
  51. package/dist/detectors/duplicate-type.d.ts +9 -0
  52. package/dist/detectors/duplicate-type.d.ts.map +1 -0
  53. package/dist/detectors/duplicate-type.js +166 -0
  54. package/dist/detectors/duplicate-type.js.map +1 -0
  55. package/dist/detectors/hot-hub-file.d.ts +11 -0
  56. package/dist/detectors/hot-hub-file.d.ts.map +1 -0
  57. package/dist/detectors/hot-hub-file.js +42 -0
  58. package/dist/detectors/hot-hub-file.js.map +1 -0
  59. package/dist/detectors/long-file.d.ts +12 -0
  60. package/dist/detectors/long-file.d.ts.map +1 -0
  61. package/dist/detectors/long-file.js +82 -0
  62. package/dist/detectors/long-file.js.map +1 -0
  63. package/dist/detectors/long-function.d.ts +12 -0
  64. package/dist/detectors/long-function.d.ts.map +1 -0
  65. package/dist/detectors/long-function.js +45 -0
  66. package/dist/detectors/long-function.js.map +1 -0
  67. package/dist/detectors/magic-numbers.d.ts +10 -0
  68. package/dist/detectors/magic-numbers.d.ts.map +1 -0
  69. package/dist/detectors/magic-numbers.js +332 -0
  70. package/dist/detectors/magic-numbers.js.map +1 -0
  71. package/dist/detectors/mutable-globals.d.ts +6 -0
  72. package/dist/detectors/mutable-globals.d.ts.map +1 -0
  73. package/dist/detectors/mutable-globals.js +95 -0
  74. package/dist/detectors/mutable-globals.js.map +1 -0
  75. package/dist/detectors/mutation.d.ts +11 -0
  76. package/dist/detectors/mutation.d.ts.map +1 -0
  77. package/dist/detectors/mutation.js +397 -0
  78. package/dist/detectors/mutation.js.map +1 -0
  79. package/dist/detectors/public-any.d.ts +6 -0
  80. package/dist/detectors/public-any.d.ts.map +1 -0
  81. package/dist/detectors/public-any.js +52 -0
  82. package/dist/detectors/public-any.js.map +1 -0
  83. package/dist/detectors/race-condition.d.ts +6 -0
  84. package/dist/detectors/race-condition.d.ts.map +1 -0
  85. package/dist/detectors/race-condition.js +608 -0
  86. package/dist/detectors/race-condition.js.map +1 -0
  87. package/dist/detectors/shared-db-write.d.ts +6 -0
  88. package/dist/detectors/shared-db-write.d.ts.map +1 -0
  89. package/dist/detectors/shared-db-write.js +656 -0
  90. package/dist/detectors/shared-db-write.js.map +1 -0
  91. package/dist/detectors/silent-catch.d.ts +6 -0
  92. package/dist/detectors/silent-catch.d.ts.map +1 -0
  93. package/dist/detectors/silent-catch.js +167 -0
  94. package/dist/detectors/silent-catch.js.map +1 -0
  95. package/dist/detectors/similar-functions.d.ts +15 -0
  96. package/dist/detectors/similar-functions.d.ts.map +1 -0
  97. package/dist/detectors/similar-functions.js +334 -0
  98. package/dist/detectors/similar-functions.js.map +1 -0
  99. package/dist/detectors/skip-tests.d.ts +6 -0
  100. package/dist/detectors/skip-tests.d.ts.map +1 -0
  101. package/dist/detectors/skip-tests.js +69 -0
  102. package/dist/detectors/skip-tests.js.map +1 -0
  103. package/dist/detectors/todo-comments.d.ts +29 -0
  104. package/dist/detectors/todo-comments.d.ts.map +1 -0
  105. package/dist/detectors/todo-comments.js +154 -0
  106. package/dist/detectors/todo-comments.js.map +1 -0
  107. package/dist/detectors/unused-deps.d.ts +8 -0
  108. package/dist/detectors/unused-deps.d.ts.map +1 -0
  109. package/dist/detectors/unused-deps.js +115 -0
  110. package/dist/detectors/unused-deps.js.map +1 -0
  111. package/dist/extraction/api-race-confirmer.d.ts +31 -0
  112. package/dist/extraction/api-race-confirmer.d.ts.map +1 -0
  113. package/dist/extraction/api-race-confirmer.js +110 -0
  114. package/dist/extraction/api-race-confirmer.js.map +1 -0
  115. package/dist/extraction/llm-confirmer.d.ts +25 -0
  116. package/dist/extraction/llm-confirmer.d.ts.map +1 -0
  117. package/dist/extraction/llm-confirmer.js +118 -0
  118. package/dist/extraction/llm-confirmer.js.map +1 -0
  119. package/dist/extraction/mutation-confirmer.d.ts +30 -0
  120. package/dist/extraction/mutation-confirmer.d.ts.map +1 -0
  121. package/dist/extraction/mutation-confirmer.js +73 -0
  122. package/dist/extraction/mutation-confirmer.js.map +1 -0
  123. package/dist/extraction/prompt-chunking.d.ts +37 -0
  124. package/dist/extraction/prompt-chunking.d.ts.map +1 -0
  125. package/dist/extraction/prompt-chunking.js +61 -0
  126. package/dist/extraction/prompt-chunking.js.map +1 -0
  127. package/dist/extraction/race-confirmer.d.ts +28 -0
  128. package/dist/extraction/race-confirmer.d.ts.map +1 -0
  129. package/dist/extraction/race-confirmer.js +68 -0
  130. package/dist/extraction/race-confirmer.js.map +1 -0
  131. package/dist/extraction/shared-db-write-confirmer.d.ts +31 -0
  132. package/dist/extraction/shared-db-write-confirmer.d.ts.map +1 -0
  133. package/dist/extraction/shared-db-write-confirmer.js +141 -0
  134. package/dist/extraction/shared-db-write-confirmer.js.map +1 -0
  135. package/dist/extraction/triage-confirmer.d.ts +59 -0
  136. package/dist/extraction/triage-confirmer.d.ts.map +1 -0
  137. package/dist/extraction/triage-confirmer.js +104 -0
  138. package/dist/extraction/triage-confirmer.js.map +1 -0
  139. package/dist/graph/cfg.d.ts +45 -0
  140. package/dist/graph/cfg.d.ts.map +1 -0
  141. package/dist/graph/cfg.js +198 -0
  142. package/dist/graph/cfg.js.map +1 -0
  143. package/dist/graph/decorator-entries.d.ts +2 -0
  144. package/dist/graph/decorator-entries.d.ts.map +1 -0
  145. package/dist/graph/decorator-entries.js +89 -0
  146. package/dist/graph/decorator-entries.js.map +1 -0
  147. package/dist/graph/entry-points.d.ts +12 -0
  148. package/dist/graph/entry-points.d.ts.map +1 -0
  149. package/dist/graph/entry-points.js +282 -0
  150. package/dist/graph/entry-points.js.map +1 -0
  151. package/dist/graph/handler-conventions.d.ts +2 -0
  152. package/dist/graph/handler-conventions.d.ts.map +1 -0
  153. package/dist/graph/handler-conventions.js +26 -0
  154. package/dist/graph/handler-conventions.js.map +1 -0
  155. package/dist/graph/iac-entries.d.ts +2 -0
  156. package/dist/graph/iac-entries.d.ts.map +1 -0
  157. package/dist/graph/iac-entries.js +123 -0
  158. package/dist/graph/iac-entries.js.map +1 -0
  159. package/dist/graph/import-graph.d.ts +48 -0
  160. package/dist/graph/import-graph.d.ts.map +1 -0
  161. package/dist/graph/import-graph.js +86 -0
  162. package/dist/graph/import-graph.js.map +1 -0
  163. package/dist/graph/monorepo-detect.d.ts +3 -0
  164. package/dist/graph/monorepo-detect.d.ts.map +1 -0
  165. package/dist/graph/monorepo-detect.js +166 -0
  166. package/dist/graph/monorepo-detect.js.map +1 -0
  167. package/dist/graph/tsconfig-paths.d.ts +23 -0
  168. package/dist/graph/tsconfig-paths.d.ts.map +1 -0
  169. package/dist/graph/tsconfig-paths.js +217 -0
  170. package/dist/graph/tsconfig-paths.js.map +1 -0
  171. package/dist/multi-workspace-scanner.d.ts +13 -0
  172. package/dist/multi-workspace-scanner.d.ts.map +1 -0
  173. package/dist/multi-workspace-scanner.js +130 -0
  174. package/dist/multi-workspace-scanner.js.map +1 -0
  175. package/dist/normalizers/type-normalizer.d.ts +16 -0
  176. package/dist/normalizers/type-normalizer.d.ts.map +1 -0
  177. package/dist/normalizers/type-normalizer.js +189 -0
  178. package/dist/normalizers/type-normalizer.js.map +1 -0
  179. package/dist/parsers/typescript-parser.d.ts +57 -0
  180. package/dist/parsers/typescript-parser.d.ts.map +1 -0
  181. package/dist/parsers/typescript-parser.js +502 -0
  182. package/dist/parsers/typescript-parser.js.map +1 -0
  183. package/dist/reporter/json-reporter.d.ts +12 -0
  184. package/dist/reporter/json-reporter.d.ts.map +1 -0
  185. package/dist/reporter/json-reporter.js +28 -0
  186. package/dist/reporter/json-reporter.js.map +1 -0
  187. package/dist/reporter/markdown-reporter.d.ts +11 -0
  188. package/dist/reporter/markdown-reporter.d.ts.map +1 -0
  189. package/dist/reporter/markdown-reporter.js +77 -0
  190. package/dist/reporter/markdown-reporter.js.map +1 -0
  191. package/dist/rothunter.d.ts +125 -0
  192. package/dist/rothunter.d.ts.map +1 -0
  193. package/dist/rothunter.js +1038 -0
  194. package/dist/rothunter.js.map +1 -0
  195. package/dist/server/false-positives.d.ts +34 -0
  196. package/dist/server/false-positives.d.ts.map +1 -0
  197. package/dist/server/false-positives.js +85 -0
  198. package/dist/server/false-positives.js.map +1 -0
  199. package/dist/server/index.d.ts +2 -0
  200. package/dist/server/index.d.ts.map +1 -0
  201. package/dist/server/index.js +1529 -0
  202. package/dist/server/index.js.map +1 -0
  203. package/dist/server/marked-to-fix.d.ts +16 -0
  204. package/dist/server/marked-to-fix.d.ts.map +1 -0
  205. package/dist/server/marked-to-fix.js +36 -0
  206. package/dist/server/marked-to-fix.js.map +1 -0
  207. package/dist/server/scan-store.d.ts +147 -0
  208. package/dist/server/scan-store.d.ts.map +1 -0
  209. package/dist/server/scan-store.js +291 -0
  210. package/dist/server/scan-store.js.map +1 -0
  211. package/dist/server/settings-store.d.ts +28 -0
  212. package/dist/server/settings-store.d.ts.map +1 -0
  213. package/dist/server/settings-store.js +46 -0
  214. package/dist/server/settings-store.js.map +1 -0
  215. package/dist/server/workspace-store.d.ts +39 -0
  216. package/dist/server/workspace-store.d.ts.map +1 -0
  217. package/dist/server/workspace-store.js +108 -0
  218. package/dist/server/workspace-store.js.map +1 -0
  219. package/dist/types/detector-input.d.ts +37 -0
  220. package/dist/types/detector-input.d.ts.map +1 -0
  221. package/dist/types/detector-input.js +2 -0
  222. package/dist/types/detector-input.js.map +1 -0
  223. package/dist/types.d.ts +110 -0
  224. package/dist/types.d.ts.map +1 -0
  225. package/dist/types.js +2 -0
  226. package/dist/types.js.map +1 -0
  227. package/dist/utils/clustering.d.ts +14 -0
  228. package/dist/utils/clustering.d.ts.map +1 -0
  229. package/dist/utils/clustering.js +56 -0
  230. package/dist/utils/clustering.js.map +1 -0
  231. package/dist/utils/gitignore.d.ts +32 -0
  232. package/dist/utils/gitignore.d.ts.map +1 -0
  233. package/dist/utils/gitignore.js +122 -0
  234. package/dist/utils/gitignore.js.map +1 -0
  235. package/dist/utils/hash.d.ts +11 -0
  236. package/dist/utils/hash.d.ts.map +1 -0
  237. package/dist/utils/hash.js +14 -0
  238. package/dist/utils/hash.js.map +1 -0
  239. package/dist/utils/ignore-annotation.d.ts +28 -0
  240. package/dist/utils/ignore-annotation.d.ts.map +1 -0
  241. package/dist/utils/ignore-annotation.js +46 -0
  242. package/dist/utils/ignore-annotation.js.map +1 -0
  243. package/dist/utils/llm-json.d.ts +2 -0
  244. package/dist/utils/llm-json.d.ts.map +1 -0
  245. package/dist/utils/llm-json.js +53 -0
  246. package/dist/utils/llm-json.js.map +1 -0
  247. package/dist/utils/logger.d.ts +3 -0
  248. package/dist/utils/logger.d.ts.map +1 -0
  249. package/dist/utils/logger.js +4 -0
  250. package/dist/utils/logger.js.map +1 -0
  251. package/dist/utils/project-conventions.d.ts +2 -0
  252. package/dist/utils/project-conventions.d.ts.map +1 -0
  253. package/dist/utils/project-conventions.js +108 -0
  254. package/dist/utils/project-conventions.js.map +1 -0
  255. package/dist/utils/regex.d.ts +9 -0
  256. package/dist/utils/regex.d.ts.map +1 -0
  257. package/dist/utils/regex.js +11 -0
  258. package/dist/utils/regex.js.map +1 -0
  259. package/dist/utils/snippet.d.ts +20 -0
  260. package/dist/utils/snippet.d.ts.map +1 -0
  261. package/dist/utils/snippet.js +28 -0
  262. package/dist/utils/snippet.js.map +1 -0
  263. package/dist/utils/source-reader.d.ts +19 -0
  264. package/dist/utils/source-reader.d.ts.map +1 -0
  265. package/dist/utils/source-reader.js +32 -0
  266. package/dist/utils/source-reader.js.map +1 -0
  267. package/logo.png +0 -0
  268. package/package.json +92 -0
  269. package/scripts/start-llm.mjs +161 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-store.js","sourceRoot":"","sources":["../../src/server/scan-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;;;;;;;;;GAUG;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACjB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE;IACnC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9F,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,iBAAiB,CAAC,QAAQ,EAAE;IACrC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC;AA2BH,MAAM,UAAU,iBAAiB,CAAC,QAAoC;IACpE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,KAAK,EAAE,CAAC;YACR,cAAc,EAAE,CAAC;YACjB,aAAa,EAAE,CAAC;YAChB,YAAY,EAAE,CAAC;YACf,YAAY,EAAE,CAAC;YACf,UAAU,EAAE,EAAE;SACf,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9C,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAC;IAChD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAChD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACtB,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC;IACD,KAAK,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;QACpC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1B,UAAU,CAAC,EAAE,CAAC,GAAG;YACf,KAAK,EAAE,GAAG,CAAC,MAAM;YACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC9C,YAAY,EAAE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC;SACpC,CAAC;IACJ,CAAC;IACD,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,MAAM;QACtB,cAAc,EAAE,KAAK;QACrB,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC;QAClD,YAAY,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC;QACnC,YAAY,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC;QACpC,UAAU;KACX,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,MAA6B,EAAE,CAAS;IAC1D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAClC,uEAAuE;IACvE,uEAAuE;IACvE,uBAAuB;IACvB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvF,OAAO,MAAM,CAAC,GAAG,CAAE,CAAC;AACtB,CAAC;AAuCD,uEAAuE;AACvE,sEAAsE;AACtE,wEAAwE;AACxE,4CAA4C;AAC5C,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;AACnD,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAC;AACjE,kEAAkE;AAClE,uEAAuE;AACvE,qEAAqE;AACrE,0CAA0C;AAC1C,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;AAEhD,MAAM,UAAU,aAAa;IAC3B,OAAO,KAAK,CAAC,IAAI,GAAG,gBAAgB,EAAE,CAAC;QACrC,6DAA6D;QAC7D,IAAI,OAAO,GAAkB,IAAI,CAAC;QAClC,IAAI,SAAS,GAAG,QAAQ,CAAC;QACzB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;gBAAE,SAAS;YACxD,IAAI,CAAC,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;gBAC5B,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;gBACxB,OAAO,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO;YAAE,MAAM,CAAC,kCAAkC;QACvD,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtB,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,qEAAqE;AACrE,sEAAsE;AACtE,uEAAuE;AACvE,wEAAwE;AACxE,IAAI,aAAa,GAAkB,IAAI,CAAC;AAaxC,MAAM,SAAS,GAAiB,EAAE,CAAC;AACnC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAElC,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,SAAS,CAAC,MAAM,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,MAAM,KAAK,GAAG,GAAS,EAAE;YACvB,aAAa,GAAG,MAAM,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,GAAS,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACnE,IAAI,aAAa,KAAK,IAAI;YAAE,KAAK,EAAE,CAAC;;YAC/B,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,aAAa,GAAG,IAAI,CAAC;IACrB,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC;IAC/B,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAG,GAAa,CAAC,OAAO,EAAE,EAAE,0CAA0C,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAC5D,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1B,MAAM,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACzC,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,KAAmB;IAC3D,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,MAAM,OAAO,GAAG,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;IACrD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAkB,EAAE,KAAwB;IAChF,MAAM,GAAG,GAAiB,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAA8B,EAAE,CAAC;IACjH,QAAQ,KAAK,CAAC,KAAK,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC;YACzB,IAAI,KAAK,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;gBACxB,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;gBACxB,MAAM,CAAC,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;YAClC,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;gBAC1B,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;gBAC5B,MAAM,CAAC,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;YACtC,CAAC;YACD,MAAM;QACR,KAAK,WAAW;YACd,MAAM,CAAC,KAAK,GAAG,WAAW,CAAC;YAC3B,GAAG,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;YAC9B,2DAA2D;YAC3D,kEAAkE;YAClE,gEAAgE;YAChE,eAAe;YACf,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACtE,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC;gBACxC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;oBAC1C,MAAM,CAAC,aAAa,GAAG,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;gBAC1D,CAAC;YACH,CAAC;YACD,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC,QAAQ,CAAC;YACvC,MAAM;QACR,KAAK,WAAW;YACd,MAAM,CAAC,KAAK,GAAG,WAAW,CAAC;YAC3B,GAAG,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;YAC3B,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;YAC9B,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;YACnB,iEAAiE;YACjE,2CAA2C;YAC3C,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;gBAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC;gBACxC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;oBAC1C,MAAM,CAAC,aAAa,GAAG,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;gBAC1D,CAAC;gBACD,MAAM,CAAC,cAAc,GAAG,SAAS,CAAC;YACpC,CAAC;YACD,MAAM;QACR,KAAK,aAAa;YAChB,MAAM,CAAC,KAAK,GAAG,aAAa,CAAC;YAC7B,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC;YACzB,GAAG,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;YAC3B,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC;YAC5B,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;YAC9B,GAAG,CAAC,OAAO,GAAG;gBACZ,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,CAAC;YACF,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACpC,MAAM;QACR,KAAK,MAAM;YACT,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC;YACtB,GAAG,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;YAC9B,GAAG,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;YAClC,MAAM;IACV,CAAC;IACD,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC;IACtB,OAAO,GAAG,CAAC;AACb,CAAC;AAYD,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAiC,CAAC;AAEzE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAkB;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IACnE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,OAAO,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACnE,mEAAmE;IACnE,oCAAoC;IACpC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,aAAqB;IACzD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IAC5D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,CAAC;QACH,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,oCAAoC;IACtC,CAAC;IACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACnD,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC;IAEhE,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACzD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,mCAAmC,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;IAClD,gBAAgB,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1D,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Per-server app settings — survive restarts via ~/.rothunter/settings.json.
3
+ * The Settings page in the dashboard edits this; scan start picks defaults
4
+ * from here when the request body omits them.
5
+ */
6
+ export interface AppSettings {
7
+ detectors: Record<string, boolean>;
8
+ minConfidence: number;
9
+ /**
10
+ * Number of LLM verdict requests in flight at once. 1 = sequential
11
+ * (original behaviour). 4-8 is a good default on llama.cpp run with
12
+ * `--parallel N -cb` (continuous batching), or on vLLM where dynamic
13
+ * batching is on by default.
14
+ */
15
+ llmConcurrency: number;
16
+ /**
17
+ * Confidence floor at which a negative LLM verdict routes a finding
18
+ * to the auto-FP bucket. `0.6` keeps almost every LLM "intentional"
19
+ * call out of the open list; `0.85` is strict (only very-confident
20
+ * verdicts auto-FP); `1` effectively disables auto-FP routing. The
21
+ * Findings UI shows the LLM reason on every routed entry so the
22
+ * operator can un-mark with one click if a verdict was wrong.
23
+ */
24
+ llmAutoFpThreshold: number;
25
+ }
26
+ export declare function readSettings(): AppSettings;
27
+ export declare function writeSettings(s: AppSettings): Promise<void>;
28
+ //# sourceMappingURL=settings-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-store.d.ts","sourceRoot":"","sources":["../../src/server/settings-store.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAeD,wBAAgB,YAAY,IAAI,WAAW,CAsB1C;AAED,wBAAsB,aAAa,CAAC,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjE"}
@@ -0,0 +1,46 @@
1
+ import * as path from 'node:path';
2
+ import * as os from 'node:os';
3
+ import * as fs from 'node:fs/promises';
4
+ import { existsSync, readFileSync } from 'node:fs';
5
+ import { CONFIG_DIR } from './workspace-store.js';
6
+ import { DETECTOR_IDS } from '../detector-registry.js';
7
+ const SETTINGS_FILE = path.join(CONFIG_DIR, 'settings.json');
8
+ function defaultSettings() {
9
+ const detectors = {};
10
+ for (const id of DETECTOR_IDS)
11
+ detectors[id] = true;
12
+ // Auto-tune LLM concurrency: default to half the CPU cores, clamped
13
+ // to [1, 8]. Most laptops land at 4 — a sane balance between local
14
+ // llama.cpp throughput and OS responsiveness during a scan.
15
+ const cores = Math.max(1, os.cpus().length);
16
+ const auto = Math.max(1, Math.min(8, Math.floor(cores / 2)));
17
+ return { detectors, minConfidence: 0.6, llmConcurrency: auto, llmAutoFpThreshold: 0.6 };
18
+ }
19
+ export function readSettings() {
20
+ try {
21
+ if (!existsSync(SETTINGS_FILE))
22
+ return defaultSettings();
23
+ const raw = JSON.parse(readFileSync(SETTINGS_FILE, 'utf-8'));
24
+ const base = defaultSettings();
25
+ return {
26
+ detectors: { ...base.detectors, ...(raw.detectors ?? {}) },
27
+ minConfidence: typeof raw.minConfidence === 'number' ? raw.minConfidence : base.minConfidence,
28
+ llmConcurrency: typeof raw.llmConcurrency === 'number' && raw.llmConcurrency >= 1
29
+ ? Math.min(16, Math.floor(raw.llmConcurrency))
30
+ : base.llmConcurrency,
31
+ llmAutoFpThreshold: typeof raw.llmAutoFpThreshold === 'number' &&
32
+ raw.llmAutoFpThreshold >= 0 &&
33
+ raw.llmAutoFpThreshold <= 1
34
+ ? raw.llmAutoFpThreshold
35
+ : base.llmAutoFpThreshold,
36
+ };
37
+ }
38
+ catch {
39
+ return defaultSettings();
40
+ }
41
+ }
42
+ export async function writeSettings(s) {
43
+ await fs.mkdir(CONFIG_DIR, { recursive: true });
44
+ await fs.writeFile(SETTINGS_FILE, JSON.stringify(s, null, 2), 'utf-8');
45
+ }
46
+ //# sourceMappingURL=settings-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-store.js","sourceRoot":"","sources":["../../src/server/settings-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AA4BvD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;AAE7D,SAAS,eAAe;IACtB,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,KAAK,MAAM,EAAE,IAAI,YAAY;QAAE,SAAS,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IACpD,oEAAoE;IACpE,mEAAmE;IACnE,4DAA4D;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;YAAE,OAAO,eAAe,EAAE,CAAC;QACzD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAyB,CAAC;QACrF,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;QAC/B,OAAO;YACL,SAAS,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE;YAC1D,aAAa,EAAE,OAAO,GAAG,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa;YAC7F,cAAc,EACZ,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ,IAAI,GAAG,CAAC,cAAc,IAAI,CAAC;gBAC/D,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAC9C,CAAC,CAAC,IAAI,CAAC,cAAc;YACzB,kBAAkB,EAChB,OAAO,GAAG,CAAC,kBAAkB,KAAK,QAAQ;gBAC1C,GAAG,CAAC,kBAAkB,IAAI,CAAC;gBAC3B,GAAG,CAAC,kBAAkB,IAAI,CAAC;gBACzB,CAAC,CAAC,GAAG,CAAC,kBAAkB;gBACxB,CAAC,CAAC,IAAI,CAAC,kBAAkB;SAC9B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,eAAe,EAAE,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,CAAc;IAChD,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Workspace selection + filesystem allow-roots. Two responsibilities:
3
+ * 1. Persist the operator's active workspace (and recent picks) under
4
+ * ~/.rothunter/workspace.json so server restarts remember the choice.
5
+ * 2. Guard every fs-reaching endpoint against paths outside the
6
+ * configured allow-roots — defaults to $HOME (+ /workspace inside the
7
+ * Docker image) unless ROTHUNTER_FS_ROOTS overrides.
8
+ *
9
+ * Module-level mutables (WORKSPACE_ROOT, RECENT_WORKSPACES) are exposed
10
+ * through getters/setters so the rest of the server can hold a reference
11
+ * to "current workspace" without each caller re-reading the persisted
12
+ * config every time.
13
+ */
14
+ export declare const CONFIG_DIR: string;
15
+ export declare const CONFIG_FILE: string;
16
+ export declare const FS_CASE_INSENSITIVE: boolean;
17
+ export declare const FS_ALLOW_ROOTS: string[];
18
+ export declare function isUnderAllowRoot(abs: string): boolean;
19
+ interface PersistedWorkspaceConfig {
20
+ current: string;
21
+ recent: string[];
22
+ }
23
+ export declare function readPersistedWorkspace(): PersistedWorkspaceConfig | null;
24
+ /**
25
+ * Boot-time workspace initialisation. Must be called once before any
26
+ * getWorkspaceRoot() reader. Throws when no candidate falls inside the
27
+ * allow-roots — the server is unusable in that state, so we let the
28
+ * caller decide whether to exit or fall back.
29
+ */
30
+ export declare function initWorkspaceStore(initial: string): {
31
+ workspaceRoot: string;
32
+ recent: string[];
33
+ };
34
+ export declare function getWorkspaceRoot(): string;
35
+ export declare function getRecentWorkspaces(): ReadonlyArray<string>;
36
+ export declare function setWorkspaceRoot(next: string): void;
37
+ export declare function persistCurrentWorkspace(): Promise<void>;
38
+ export {};
39
+ //# sourceMappingURL=workspace-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-store.d.ts","sourceRoot":"","sources":["../../src/server/workspace-store.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,UAAU,QAAwC,CAAC;AAChE,eAAO,MAAM,WAAW,QAA0C,CAAC;AAInE,eAAO,MAAM,mBAAmB,SAAgE,CAAC;AAkBjG,eAAO,MAAM,cAAc,UAAqB,CAAC;AAEjD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAerD;AAED,UAAU,wBAAwB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,sBAAsB,IAAI,wBAAwB,GAAG,IAAI,CAOxE;AAUD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAM/F;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,mBAAmB,IAAI,aAAa,CAAC,MAAM,CAAC,CAE3D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAInD;AAED,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM7D"}
@@ -0,0 +1,108 @@
1
+ import * as path from 'node:path';
2
+ import * as os from 'node:os';
3
+ import * as fs from 'node:fs/promises';
4
+ import { existsSync, realpathSync, readFileSync } from 'node:fs';
5
+ /**
6
+ * Workspace selection + filesystem allow-roots. Two responsibilities:
7
+ * 1. Persist the operator's active workspace (and recent picks) under
8
+ * ~/.rothunter/workspace.json so server restarts remember the choice.
9
+ * 2. Guard every fs-reaching endpoint against paths outside the
10
+ * configured allow-roots — defaults to $HOME (+ /workspace inside the
11
+ * Docker image) unless ROTHUNTER_FS_ROOTS overrides.
12
+ *
13
+ * Module-level mutables (WORKSPACE_ROOT, RECENT_WORKSPACES) are exposed
14
+ * through getters/setters so the rest of the server can hold a reference
15
+ * to "current workspace" without each caller re-reading the persisted
16
+ * config every time.
17
+ */
18
+ export const CONFIG_DIR = path.join(os.homedir(), '.rothunter');
19
+ export const CONFIG_FILE = path.join(CONFIG_DIR, 'workspace.json');
20
+ // macOS HFS+/APFS and Windows NTFS are case-insensitive by default.
21
+ // Fold case on the prefix comparison so `/Users/Foo` matches `/users/foo`.
22
+ export const FS_CASE_INSENSITIVE = process.platform === 'darwin' || process.platform === 'win32';
23
+ function loadFsAllowRoots() {
24
+ const raw = process.env.ROTHUNTER_FS_ROOTS;
25
+ const explicit = !!raw;
26
+ const roots = raw ? raw.split(':').filter(Boolean) : [os.homedir()];
27
+ if (!explicit && existsSync('/workspace'))
28
+ roots.push('/workspace');
29
+ const resolved = roots.map((r) => {
30
+ const abs = path.resolve(r);
31
+ try {
32
+ return realpathSync(abs);
33
+ }
34
+ catch {
35
+ return abs; // path may not exist yet (e.g. fresh container)
36
+ }
37
+ });
38
+ return [...new Set(resolved)];
39
+ }
40
+ export const FS_ALLOW_ROOTS = loadFsAllowRoots();
41
+ export function isUnderAllowRoot(abs) {
42
+ let resolved = path.resolve(abs);
43
+ try {
44
+ resolved = realpathSync(resolved);
45
+ }
46
+ catch {
47
+ // Path may not exist yet (POST /api/workspace before mkdir, etc.).
48
+ // Fall back to the un-resolved form — the caller's existsSync gate
49
+ // catches "missing path" cases separately.
50
+ }
51
+ const needle = FS_CASE_INSENSITIVE ? resolved.toLowerCase() : resolved;
52
+ return FS_ALLOW_ROOTS.some((root) => {
53
+ const r = FS_CASE_INSENSITIVE ? root.toLowerCase() : root;
54
+ if (needle === r)
55
+ return true;
56
+ return needle.startsWith(r + path.sep);
57
+ });
58
+ }
59
+ export function readPersistedWorkspace() {
60
+ try {
61
+ if (!existsSync(CONFIG_FILE))
62
+ return null;
63
+ return JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'));
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ }
69
+ async function writePersistedWorkspace(cfg) {
70
+ await fs.mkdir(CONFIG_DIR, { recursive: true });
71
+ await fs.writeFile(CONFIG_FILE, JSON.stringify(cfg, null, 2), 'utf-8');
72
+ }
73
+ let WORKSPACE_ROOT;
74
+ let RECENT_WORKSPACES;
75
+ /**
76
+ * Boot-time workspace initialisation. Must be called once before any
77
+ * getWorkspaceRoot() reader. Throws when no candidate falls inside the
78
+ * allow-roots — the server is unusable in that state, so we let the
79
+ * caller decide whether to exit or fall back.
80
+ */
81
+ export function initWorkspaceStore(initial) {
82
+ const persisted = readPersistedWorkspace();
83
+ WORKSPACE_ROOT = initial;
84
+ RECENT_WORKSPACES = (persisted?.recent ?? [initial]).filter((p) => isUnderAllowRoot(p));
85
+ if (RECENT_WORKSPACES.length === 0)
86
+ RECENT_WORKSPACES = [initial];
87
+ return { workspaceRoot: WORKSPACE_ROOT, recent: RECENT_WORKSPACES };
88
+ }
89
+ export function getWorkspaceRoot() {
90
+ return WORKSPACE_ROOT;
91
+ }
92
+ export function getRecentWorkspaces() {
93
+ return RECENT_WORKSPACES;
94
+ }
95
+ export function setWorkspaceRoot(next) {
96
+ WORKSPACE_ROOT = next;
97
+ // Move to head of recent list (MRU).
98
+ RECENT_WORKSPACES = [next, ...RECENT_WORKSPACES.filter((p) => p !== next)].slice(0, 10);
99
+ }
100
+ export async function persistCurrentWorkspace() {
101
+ try {
102
+ await writePersistedWorkspace({ current: WORKSPACE_ROOT, recent: RECENT_WORKSPACES });
103
+ }
104
+ catch {
105
+ // Persist failures should not crash the server; the next switch will retry.
106
+ }
107
+ }
108
+ //# sourceMappingURL=workspace-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-store.js","sourceRoot":"","sources":["../../src/server/workspace-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { Project } from 'ts-morph';
2
+ import type { SymbolRecord } from '../types.js';
3
+ import type { ImportRecord } from '../graph/import-graph.js';
4
+ /**
5
+ * Shared input shape for file-walking detectors. Eleven detectors used
6
+ * to declare their own near-identical `{ workspaceRoot, files, project? }`
7
+ * interface — the duplicate-type detector flagged them as a cluster.
8
+ * One canonical type here, each detector either uses this directly or
9
+ * extends it with detector-specific fields.
10
+ */
11
+ export interface FileWalkingDetectorInput {
12
+ workspaceRoot: string;
13
+ files: ReadonlyArray<string>;
14
+ /**
15
+ * Optional pre-built ts-morph Project — the orchestrator builds one
16
+ * shared Project per scan and passes it down so detectors don't have
17
+ * to re-parse the same source tree N times. When absent, detectors
18
+ * fall back to readFileSync via `utils/source-reader.ts`.
19
+ */
20
+ project?: Project;
21
+ }
22
+ /**
23
+ * Detectors whose input is the parsed symbol set (no per-file walking).
24
+ * Used by long-function / deep-nesting / public-any / hot-hub-file.
25
+ */
26
+ export interface SymbolDetectorInput {
27
+ symbols: ReadonlyArray<SymbolRecord>;
28
+ }
29
+ /**
30
+ * Detectors that consume the import graph directly (dead-export,
31
+ * dead-api, dead-handler, unused-deps). Shape kept here so changes to
32
+ * the import record propagate via a single canonical reference.
33
+ */
34
+ export interface ImportGraphDetectorInput {
35
+ imports: ReadonlyArray<ImportRecord>;
36
+ }
37
+ //# sourceMappingURL=detector-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector-input.d.ts","sourceRoot":"","sources":["../../src/types/detector-input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;;;;GAMG;AACH,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CACtC;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CACtC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=detector-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector-input.js","sourceRoot":"","sources":["../../src/types/detector-input.ts"],"names":[],"mappings":""}
@@ -0,0 +1,110 @@
1
+ export type SymbolKind = 'interface' | 'type-alias' | 'class' | 'enum' | 'function';
2
+ export interface FieldStructure {
3
+ name: string;
4
+ type: string;
5
+ optional: boolean;
6
+ readonly: boolean;
7
+ }
8
+ export interface TypeStructure {
9
+ kind: 'object' | 'union' | 'intersection' | 'literal' | 'unknown';
10
+ fields?: FieldStructure[];
11
+ members?: TypeStructure[];
12
+ raw?: string;
13
+ }
14
+ export interface FunctionStructure {
15
+ kind: 'function';
16
+ /** Parameters in declaration order. Reuses FieldStructure (name, type, optional). */
17
+ params: FieldStructure[];
18
+ /** TypeScript-rendered return type. */
19
+ returnType: string;
20
+ /** Whether the function is `async`. */
21
+ async: boolean;
22
+ /** Whether the function is a `*` generator. */
23
+ generator: boolean;
24
+ /** Raw body source including the braces, exactly as the user wrote it. */
25
+ body: string;
26
+ /**
27
+ * Body after whitespace/comment collapse, used as the body-similarity hash
28
+ * input. Local identifier renaming happens at the normalizer level so the
29
+ * raw text here is still recognizable in evidence snippets.
30
+ */
31
+ bodyNormalized: string;
32
+ /**
33
+ * Token shingles (4-grams of identifier-anonymised tokens) used for the
34
+ * near-duplicate Layer-4 pairwise Jaccard pass.
35
+ */
36
+ bodyShingles: ReadonlySet<string>;
37
+ }
38
+ export type AnyStructure = TypeStructure | FunctionStructure;
39
+ export interface SourceRange {
40
+ startLine: number;
41
+ endLine: number;
42
+ }
43
+ export interface SymbolRecord {
44
+ id: string;
45
+ kind: SymbolKind;
46
+ name: string;
47
+ file: string;
48
+ /** Logical workspace name when running in multi-workspace mode. Undefined for single-workspace scans. */
49
+ workspace?: string;
50
+ range: SourceRange;
51
+ source: string;
52
+ exported: boolean;
53
+ /** True iff the symbol is the file's default export (`export default X`). */
54
+ isDefault?: boolean;
55
+ structure?: AnyStructure;
56
+ hashStrict?: string;
57
+ hashStructural?: string;
58
+ hashNormalizedNames?: string;
59
+ canonicalSignature?: string;
60
+ description?: string;
61
+ domain?: string;
62
+ embeddingSignature?: number[];
63
+ embeddingSemantic?: number[];
64
+ }
65
+ export interface Evidence {
66
+ file: string;
67
+ range: SourceRange;
68
+ snippet: string;
69
+ note?: string;
70
+ }
71
+ export type Severity = 'low' | 'medium' | 'high';
72
+ export interface Finding {
73
+ detectorId: string;
74
+ severity: Severity;
75
+ confidence: number;
76
+ layer: 1 | 2 | 3;
77
+ title: string;
78
+ description: string;
79
+ evidence: Evidence[];
80
+ suggestion?: string;
81
+ fingerprint: string;
82
+ /**
83
+ * Unix-ms timestamp when this finding was confirmed resolved by a
84
+ * single-finding re-run (POST /api/findings/:fp/rerun). The persisted
85
+ * scan record keeps the entry around — flipped to `resolved` instead
86
+ * of deleted — so History / Findings views can surface the fix as a
87
+ * "completed" item rather than silently dropping it.
88
+ */
89
+ resolvedAt?: number;
90
+ /**
91
+ * Auto-flagged by an LLM verdict as a false positive during this scan.
92
+ * Populated when the relevant confirmer (mutation, triage, …) returns
93
+ * `intentional` / `not real` with high confidence. Surface-level effect
94
+ * matches the manual FP store: the finding moves to the FP bucket
95
+ * instead of cluttering the open list. Differs from the persisted FP
96
+ * store in that it is scan-scoped and recomputed every run — if the
97
+ * code changes and the LLM no longer thinks it is intentional, the
98
+ * finding comes back automatically.
99
+ */
100
+ llmFalsePositive?: {
101
+ confidence: number;
102
+ reason: string;
103
+ };
104
+ }
105
+ export interface Detector {
106
+ id: string;
107
+ name: string;
108
+ run(symbols: SymbolRecord[]): Promise<Finding[]>;
109
+ }
110
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import type { SymbolRecord } from '../types.js';
2
+ /** Bucket a list of symbols by a hash extractor (skipping symbols whose hash is empty). */
3
+ export declare function bucketBy(symbols: SymbolRecord[], hashFn: (s: SymbolRecord) => string | undefined): Map<string, SymbolRecord[]>;
4
+ /** First non-empty hash from a cluster, picked by the layer that matched. */
5
+ export declare function representativeHash<MatchedBy extends string>(group: SymbolRecord[], matchedBy: MatchedBy, pickers: Record<MatchedBy, (s: SymbolRecord) => string | undefined>): string;
6
+ /** Flat-array union-find with path compression + rank balancing. */
7
+ export declare class UnionFind {
8
+ private readonly parent;
9
+ private readonly rank;
10
+ constructor(n: number);
11
+ find(x: number): number;
12
+ union(a: number, b: number): void;
13
+ }
14
+ //# sourceMappingURL=clustering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clustering.d.ts","sourceRoot":"","sources":["../../src/utils/clustering.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,2FAA2F;AAC3F,wBAAgB,QAAQ,CACtB,OAAO,EAAE,YAAY,EAAE,EACvB,MAAM,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,MAAM,GAAG,SAAS,GAC9C,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,CAU7B;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,SAAS,SAAS,MAAM,EACzD,KAAK,EAAE,YAAY,EAAE,EACrB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,MAAM,GAAG,SAAS,CAAC,GAClE,MAAM,CAOR;AAED,oEAAoE;AACpE,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAW;gBAEpB,CAAC,EAAE,MAAM;IAKrB,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAQvB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;CAalC"}
@@ -0,0 +1,56 @@
1
+ /** Bucket a list of symbols by a hash extractor (skipping symbols whose hash is empty). */
2
+ export function bucketBy(symbols, hashFn) {
3
+ const out = new Map();
4
+ for (const s of symbols) {
5
+ const h = hashFn(s);
6
+ if (!h)
7
+ continue;
8
+ const list = out.get(h) ?? [];
9
+ list.push(s);
10
+ out.set(h, list);
11
+ }
12
+ return out;
13
+ }
14
+ /** First non-empty hash from a cluster, picked by the layer that matched. */
15
+ export function representativeHash(group, matchedBy, pickers) {
16
+ const pick = pickers[matchedBy];
17
+ for (const s of group) {
18
+ const h = pick(s);
19
+ if (h)
20
+ return h;
21
+ }
22
+ return 'unknown';
23
+ }
24
+ /** Flat-array union-find with path compression + rank balancing. */
25
+ export class UnionFind {
26
+ parent;
27
+ rank;
28
+ constructor(n) {
29
+ this.parent = Array.from({ length: n }, (_, i) => i);
30
+ this.rank = new Array(n).fill(0);
31
+ }
32
+ find(x) {
33
+ while (this.parent[x] !== x) {
34
+ this.parent[x] = this.parent[this.parent[x]];
35
+ x = this.parent[x];
36
+ }
37
+ return x;
38
+ }
39
+ union(a, b) {
40
+ const ra = this.find(a);
41
+ const rb = this.find(b);
42
+ if (ra === rb)
43
+ return;
44
+ if (this.rank[ra] < this.rank[rb]) {
45
+ this.parent[ra] = rb;
46
+ }
47
+ else if (this.rank[ra] > this.rank[rb]) {
48
+ this.parent[rb] = ra;
49
+ }
50
+ else {
51
+ this.parent[rb] = ra;
52
+ this.rank[ra]++;
53
+ }
54
+ }
55
+ }
56
+ //# sourceMappingURL=clustering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clustering.js","sourceRoot":"","sources":["../../src/utils/clustering.ts"],"names":[],"mappings":"AAEA,2FAA2F;AAC3F,MAAM,UAAU,QAAQ,CACtB,OAAuB,EACvB,MAA+C;IAE/C,MAAM,GAAG,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACb,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,kBAAkB,CAChC,KAAqB,EACrB,SAAoB,EACpB,OAAmE;IAEnE,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,oEAAoE;AACpE,MAAM,OAAO,SAAS;IACH,MAAM,CAAW;IACjB,IAAI,CAAW;IAEhC,YAAY,CAAS;QACnB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,CAAS;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAE,CAAE,CAAC;YAC/C,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC;QACtB,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,KAAK,CAAC,CAAS,EAAE,CAAS;QACxB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO;QACtB,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAE,EAAE,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;QACvB,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,EAAE,CAAE,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,32 @@
1
+ import { type Ignore } from 'ignore';
2
+ /**
3
+ * Load every `.gitignore` reachable from `workspaceRoot` AND the
4
+ * workspace-root `.rothunterignore` (gitignore-syntax extension, only
5
+ * for rothunter). Returns a unified matcher.
6
+ *
7
+ * The matcher answers "is this workspace-relative path ignored?" — used
8
+ * by the parser + by any detector that walks the filesystem on its own.
9
+ *
10
+ * Rules:
11
+ * - Top-level `.gitignore` always loads (when present).
12
+ * - Nested `.gitignore`s load too, prefixed with their relative dir so
13
+ * a pattern like `dist/` inside `packages/foo/.gitignore` matches
14
+ * `packages/foo/dist/...` and not the root `dist/`.
15
+ * - `.rothunterignore` at the workspace root loads with the same
16
+ * syntax — use this for files that ARE in git but should be hidden
17
+ * from rothunter (fixtures, vendored SDKs, generated test data).
18
+ * - `node_modules/` and `.git/` are always ignored regardless of
19
+ * what the operator's files say — the cost of scanning them is
20
+ * prohibitive on every repo and never produces useful findings.
21
+ *
22
+ * Always returns a non-null matcher; the always-on rules (`node_modules`
23
+ * + `.git`) ensure callers get sensible defaults even when no ignore
24
+ * file exists.
25
+ */
26
+ export declare function loadGitignore(workspaceRoot: string): Ignore;
27
+ /**
28
+ * Filter a workspace-relative path list through the gitignore matcher,
29
+ * preserving order.
30
+ */
31
+ export declare function filterGitignored(matcher: Ignore, files: ReadonlyArray<string>): string[];
32
+ //# sourceMappingURL=gitignore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"AAEA,OAAe,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAmF3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAExF"}