kirograph 0.17.0 → 0.19.0

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 (329) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +103 -1822
  3. package/dist/architecture/layers/dart.js +112 -0
  4. package/dist/architecture/layers/dart.js.map +7 -0
  5. package/dist/architecture/layers/index.js +3 -1
  6. package/dist/architecture/layers/index.js.map +2 -2
  7. package/dist/bin/banner.js +74 -6
  8. package/dist/bin/banner.js.map +2 -2
  9. package/dist/bin/commands/attack-surface.js +157 -0
  10. package/dist/bin/commands/attack-surface.js.map +7 -0
  11. package/dist/bin/commands/benchmark.js +206 -0
  12. package/dist/bin/commands/benchmark.js.map +7 -0
  13. package/dist/bin/commands/budget.js +70 -0
  14. package/dist/bin/commands/budget.js.map +7 -0
  15. package/dist/bin/commands/communities.js +77 -0
  16. package/dist/bin/commands/communities.js.map +7 -0
  17. package/dist/bin/commands/dep-confusion.js +119 -0
  18. package/dist/bin/commands/dep-confusion.js.map +7 -0
  19. package/dist/bin/commands/export.js +304 -10
  20. package/dist/bin/commands/export.js.map +2 -2
  21. package/dist/bin/commands/flows.js +97 -0
  22. package/dist/bin/commands/flows.js.map +7 -0
  23. package/dist/bin/commands/help.js +382 -101
  24. package/dist/bin/commands/help.js.map +2 -2
  25. package/dist/bin/commands/install.js +90 -8
  26. package/dist/bin/commands/install.js.map +2 -2
  27. package/dist/bin/commands/licenses.js +201 -0
  28. package/dist/bin/commands/licenses.js.map +7 -0
  29. package/dist/bin/commands/reachability.js +160 -0
  30. package/dist/bin/commands/reachability.js.map +7 -0
  31. package/dist/bin/commands/read.js +100 -0
  32. package/dist/bin/commands/read.js.map +7 -0
  33. package/dist/bin/commands/refactor.js +116 -0
  34. package/dist/bin/commands/refactor.js.map +7 -0
  35. package/dist/bin/commands/remediation.js +133 -0
  36. package/dist/bin/commands/remediation.js.map +7 -0
  37. package/dist/bin/commands/sbom.js +76 -0
  38. package/dist/bin/commands/sbom.js.map +7 -0
  39. package/dist/bin/commands/security-ci-report.js +267 -0
  40. package/dist/bin/commands/security-ci-report.js.map +7 -0
  41. package/dist/bin/commands/security-export.js +1349 -0
  42. package/dist/bin/commands/security-export.js.map +7 -0
  43. package/dist/bin/commands/security-flows.js +126 -0
  44. package/dist/bin/commands/security-flows.js.map +7 -0
  45. package/dist/bin/commands/security-secrets.js +170 -0
  46. package/dist/bin/commands/security-secrets.js.map +7 -0
  47. package/dist/bin/commands/security.js +193 -0
  48. package/dist/bin/commands/security.js.map +7 -0
  49. package/dist/bin/commands/staleness.js +144 -0
  50. package/dist/bin/commands/staleness.js.map +7 -0
  51. package/dist/bin/commands/status.js +102 -2
  52. package/dist/bin/commands/status.js.map +2 -2
  53. package/dist/bin/commands/supply-chain.js +138 -0
  54. package/dist/bin/commands/supply-chain.js.map +7 -0
  55. package/dist/bin/commands/uninit.js +109 -60
  56. package/dist/bin/commands/uninit.js.map +2 -2
  57. package/dist/bin/commands/vex.js +76 -0
  58. package/dist/bin/commands/vex.js.map +7 -0
  59. package/dist/bin/commands/vuln-suppress.js +95 -0
  60. package/dist/bin/commands/vuln-suppress.js.map +7 -0
  61. package/dist/bin/commands/vulns.js +382 -0
  62. package/dist/bin/commands/vulns.js.map +7 -0
  63. package/dist/bin/installer/auto-detect.js +125 -0
  64. package/dist/bin/installer/auto-detect.js.map +7 -0
  65. package/dist/bin/installer/cli-agent.js +28 -5
  66. package/dist/bin/installer/cli-agent.js.map +2 -2
  67. package/dist/bin/installer/common.js +47 -0
  68. package/dist/bin/installer/common.js.map +2 -2
  69. package/dist/bin/installer/config-prompt.js +12 -1
  70. package/dist/bin/installer/config-prompt.js.map +2 -2
  71. package/dist/bin/installer/detect.js +309 -0
  72. package/dist/bin/installer/detect.js.map +7 -0
  73. package/dist/bin/installer/index.js +9 -1
  74. package/dist/bin/installer/index.js.map +2 -2
  75. package/dist/bin/installer/instructions.js +195 -3
  76. package/dist/bin/installer/instructions.js.map +2 -2
  77. package/dist/bin/installer/steering.js +407 -0
  78. package/dist/bin/installer/steering.js.map +2 -2
  79. package/dist/bin/installer/targets/aider.js +3 -3
  80. package/dist/bin/installer/targets/aider.js.map +2 -2
  81. package/dist/bin/installer/targets/amp.js +3 -3
  82. package/dist/bin/installer/targets/amp.js.map +2 -2
  83. package/dist/bin/installer/targets/antigravity.js +35 -6
  84. package/dist/bin/installer/targets/antigravity.js.map +2 -2
  85. package/dist/bin/installer/targets/augment.js +3 -3
  86. package/dist/bin/installer/targets/augment.js.map +2 -2
  87. package/dist/bin/installer/targets/claude.js +49 -5
  88. package/dist/bin/installer/targets/claude.js.map +2 -2
  89. package/dist/bin/installer/targets/cline.js +32 -6
  90. package/dist/bin/installer/targets/cline.js.map +2 -2
  91. package/dist/bin/installer/targets/codex.js +64 -12
  92. package/dist/bin/installer/targets/codex.js.map +2 -2
  93. package/dist/bin/installer/targets/continue.js +2 -2
  94. package/dist/bin/installer/targets/continue.js.map +2 -2
  95. package/dist/bin/installer/targets/copilot-cli.js +101 -0
  96. package/dist/bin/installer/targets/copilot-cli.js.map +7 -0
  97. package/dist/bin/installer/targets/copilot.js +31 -5
  98. package/dist/bin/installer/targets/copilot.js.map +2 -2
  99. package/dist/bin/installer/targets/cursor.js +4 -4
  100. package/dist/bin/installer/targets/cursor.js.map +2 -2
  101. package/dist/bin/installer/targets/devin.js +2 -2
  102. package/dist/bin/installer/targets/devin.js.map +2 -2
  103. package/dist/bin/installer/targets/gemini-cli.js +2 -2
  104. package/dist/bin/installer/targets/gemini-cli.js.map +2 -2
  105. package/dist/bin/installer/targets/generic.js +2 -14
  106. package/dist/bin/installer/targets/generic.js.map +2 -2
  107. package/dist/bin/installer/targets/goose.js +3 -3
  108. package/dist/bin/installer/targets/goose.js.map +2 -2
  109. package/dist/bin/installer/targets/index.js +250 -0
  110. package/dist/bin/installer/targets/index.js.map +2 -2
  111. package/dist/bin/installer/targets/junie.js +2 -2
  112. package/dist/bin/installer/targets/junie.js.map +2 -2
  113. package/dist/bin/installer/targets/kilo.js +2 -2
  114. package/dist/bin/installer/targets/kilo.js.map +2 -2
  115. package/dist/bin/installer/targets/kiro.js +3 -3
  116. package/dist/bin/installer/targets/kiro.js.map +2 -2
  117. package/dist/bin/installer/targets/opencode.js +2 -2
  118. package/dist/bin/installer/targets/opencode.js.map +2 -2
  119. package/dist/bin/installer/targets/openhands.js +3 -3
  120. package/dist/bin/installer/targets/openhands.js.map +2 -2
  121. package/dist/bin/installer/targets/qoder.js +91 -0
  122. package/dist/bin/installer/targets/qoder.js.map +7 -0
  123. package/dist/bin/installer/targets/qwen.js +96 -0
  124. package/dist/bin/installer/targets/qwen.js.map +7 -0
  125. package/dist/bin/installer/targets/replit.js +3 -3
  126. package/dist/bin/installer/targets/replit.js.map +2 -2
  127. package/dist/bin/installer/targets/roo.js +2 -2
  128. package/dist/bin/installer/targets/roo.js.map +2 -2
  129. package/dist/bin/installer/targets/tabnine.js +3 -3
  130. package/dist/bin/installer/targets/tabnine.js.map +2 -2
  131. package/dist/bin/installer/targets/trae.js +5 -5
  132. package/dist/bin/installer/targets/trae.js.map +2 -2
  133. package/dist/bin/installer/targets/warp.js +2 -2
  134. package/dist/bin/installer/targets/warp.js.map +2 -2
  135. package/dist/bin/installer/targets/windsurf.js +35 -6
  136. package/dist/bin/installer/targets/windsurf.js.map +2 -2
  137. package/dist/bin/kirograph.js +72 -6
  138. package/dist/bin/kirograph.js.map +3 -3
  139. package/dist/compression/tracker.js +80 -0
  140. package/dist/compression/tracker.js.map +2 -2
  141. package/dist/config.js +90 -3
  142. package/dist/config.js.map +2 -2
  143. package/dist/core/pipeline.js +36 -2
  144. package/dist/core/pipeline.js.map +2 -2
  145. package/dist/db/database.js +56 -5
  146. package/dist/db/database.js.map +2 -2
  147. package/dist/db/memory-schema.sql +5 -1
  148. package/dist/db/schema.sql +3 -1
  149. package/dist/db/security-schema.sql +72 -0
  150. package/dist/extraction/extractor.js +81 -0
  151. package/dist/extraction/extractor.js.map +2 -2
  152. package/dist/extraction/grammars.js +32 -8
  153. package/dist/extraction/grammars.js.map +2 -2
  154. package/dist/extraction/languages.js +43 -1
  155. package/dist/extraction/languages.js.map +2 -2
  156. package/dist/extraction/notebook.js +300 -0
  157. package/dist/extraction/notebook.js.map +7 -0
  158. package/dist/extraction/wasm/tree-sitter-astro.wasm +0 -0
  159. package/dist/extraction/wasm/tree-sitter-gdscript.wasm +0 -0
  160. package/dist/extraction/wasm/tree-sitter-julia.wasm +0 -0
  161. package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  162. package/dist/extraction/wasm/tree-sitter-perl.wasm +0 -0
  163. package/dist/extraction/wasm/tree-sitter-powershell.wasm +0 -0
  164. package/dist/extraction/wasm/tree-sitter-r.wasm +0 -0
  165. package/dist/extraction/wasm/tree-sitter-sql.wasm +0 -0
  166. package/dist/extraction/wasm/tree-sitter-verilog.wasm +0 -0
  167. package/dist/frameworks/flutter.js +130 -0
  168. package/dist/frameworks/flutter.js.map +7 -0
  169. package/dist/frameworks/index.js +7 -1
  170. package/dist/frameworks/index.js.map +3 -3
  171. package/dist/graph/communities.js +317 -0
  172. package/dist/graph/communities.js.map +7 -0
  173. package/dist/graph/flows.js +138 -0
  174. package/dist/graph/flows.js.map +7 -0
  175. package/dist/graph/refactor.js +155 -0
  176. package/dist/graph/refactor.js.map +7 -0
  177. package/dist/index.js +1 -1
  178. package/dist/index.js.map +2 -2
  179. package/dist/mcp/cache.js +172 -0
  180. package/dist/mcp/cache.js.map +7 -0
  181. package/dist/mcp/read-modes.js +295 -0
  182. package/dist/mcp/read-modes.js.map +7 -0
  183. package/dist/mcp/server.js +2 -1
  184. package/dist/mcp/server.js.map +2 -2
  185. package/dist/mcp/tool-names.js +21 -1
  186. package/dist/mcp/tool-names.js.map +2 -2
  187. package/dist/mcp/tools.js +1160 -1
  188. package/dist/mcp/tools.js.map +3 -3
  189. package/dist/memory/database.js +32 -2
  190. package/dist/memory/database.js.map +2 -2
  191. package/dist/memory/types.js.map +1 -1
  192. package/dist/resolution/bridges/android-rn.js +298 -0
  193. package/dist/resolution/bridges/android-rn.js.map +7 -0
  194. package/dist/resolution/bridges/expo-modules.js +155 -0
  195. package/dist/resolution/bridges/expo-modules.js.map +7 -0
  196. package/dist/resolution/bridges/flutter-channel.js +385 -0
  197. package/dist/resolution/bridges/flutter-channel.js.map +7 -0
  198. package/dist/resolution/bridges/index.js +80 -0
  199. package/dist/resolution/bridges/index.js.map +7 -0
  200. package/dist/resolution/bridges/native-events.js +188 -0
  201. package/dist/resolution/bridges/native-events.js.map +7 -0
  202. package/dist/resolution/bridges/native-views.js +244 -0
  203. package/dist/resolution/bridges/native-views.js.map +7 -0
  204. package/dist/resolution/bridges/react-native.js +161 -0
  205. package/dist/resolution/bridges/react-native.js.map +7 -0
  206. package/dist/resolution/bridges/swift-objc.js +227 -0
  207. package/dist/resolution/bridges/swift-objc.js.map +7 -0
  208. package/dist/resolution/bridges/turbomodules.js +216 -0
  209. package/dist/resolution/bridges/turbomodules.js.map +7 -0
  210. package/dist/resolution/index.js +61 -2
  211. package/dist/resolution/index.js.map +2 -2
  212. package/dist/security/attack-surface.js +164 -0
  213. package/dist/security/attack-surface.js.map +7 -0
  214. package/dist/security/context-warnings.js +123 -0
  215. package/dist/security/context-warnings.js.map +7 -0
  216. package/dist/security/context-warnings.test.js +300 -0
  217. package/dist/security/context-warnings.test.js.map +7 -0
  218. package/dist/security/data-flows.js +228 -0
  219. package/dist/security/data-flows.js.map +7 -0
  220. package/dist/security/dep-confusion.js +255 -0
  221. package/dist/security/dep-confusion.js.map +7 -0
  222. package/dist/security/errors.js +51 -0
  223. package/dist/security/errors.js.map +7 -0
  224. package/dist/security/export/fix-suggestions.js +58 -0
  225. package/dist/security/export/fix-suggestions.js.map +7 -0
  226. package/dist/security/export/fix-suggestions.test.js +74 -0
  227. package/dist/security/export/fix-suggestions.test.js.map +7 -0
  228. package/dist/security/export/sbom.js +230 -0
  229. package/dist/security/export/sbom.js.map +7 -0
  230. package/dist/security/export/sbom.test.js +288 -0
  231. package/dist/security/export/sbom.test.js.map +7 -0
  232. package/dist/security/export/serialization.js +142 -0
  233. package/dist/security/export/serialization.js.map +7 -0
  234. package/dist/security/export/serialization.test.js +310 -0
  235. package/dist/security/export/serialization.test.js.map +7 -0
  236. package/dist/security/export/vex.js +220 -0
  237. package/dist/security/export/vex.js.map +7 -0
  238. package/dist/security/export/vex.test.js +278 -0
  239. package/dist/security/export/vex.test.js.map +7 -0
  240. package/dist/security/index.js +67 -0
  241. package/dist/security/index.js.map +7 -0
  242. package/dist/security/integrator-transitives.test.js +359 -0
  243. package/dist/security/integrator-transitives.test.js.map +7 -0
  244. package/dist/security/integrator.js +491 -0
  245. package/dist/security/integrator.js.map +7 -0
  246. package/dist/security/integrator.test.js +237 -0
  247. package/dist/security/integrator.test.js.map +7 -0
  248. package/dist/security/license.js +70 -0
  249. package/dist/security/license.js.map +7 -0
  250. package/dist/security/manifest/adapter.js +243 -0
  251. package/dist/security/manifest/adapter.js.map +7 -0
  252. package/dist/security/manifest/adapter.test.js +272 -0
  253. package/dist/security/manifest/adapter.test.js.map +7 -0
  254. package/dist/security/manifest/parser.js +376 -0
  255. package/dist/security/manifest/parser.js.map +7 -0
  256. package/dist/security/manifest/parser.test.js +110 -0
  257. package/dist/security/manifest/parser.test.js.map +7 -0
  258. package/dist/security/manifest/plugins/cargo.js +233 -0
  259. package/dist/security/manifest/plugins/cargo.js.map +7 -0
  260. package/dist/security/manifest/plugins/cargo.test.js +304 -0
  261. package/dist/security/manifest/plugins/cargo.test.js.map +7 -0
  262. package/dist/security/manifest/plugins/composer.js +152 -0
  263. package/dist/security/manifest/plugins/composer.js.map +7 -0
  264. package/dist/security/manifest/plugins/go.js +146 -0
  265. package/dist/security/manifest/plugins/go.js.map +7 -0
  266. package/dist/security/manifest/plugins/go.test.js +341 -0
  267. package/dist/security/manifest/plugins/go.test.js.map +7 -0
  268. package/dist/security/manifest/plugins/gradle.js +159 -0
  269. package/dist/security/manifest/plugins/gradle.js.map +7 -0
  270. package/dist/security/manifest/plugins/hex.js +159 -0
  271. package/dist/security/manifest/plugins/hex.js.map +7 -0
  272. package/dist/security/manifest/plugins/maven.js +128 -0
  273. package/dist/security/manifest/plugins/maven.js.map +7 -0
  274. package/dist/security/manifest/plugins/maven.test.js +389 -0
  275. package/dist/security/manifest/plugins/maven.test.js.map +7 -0
  276. package/dist/security/manifest/plugins/npm.js +284 -0
  277. package/dist/security/manifest/plugins/npm.js.map +7 -0
  278. package/dist/security/manifest/plugins/npm.test.js +298 -0
  279. package/dist/security/manifest/plugins/npm.test.js.map +7 -0
  280. package/dist/security/manifest/plugins/nuget.js +186 -0
  281. package/dist/security/manifest/plugins/nuget.js.map +7 -0
  282. package/dist/security/manifest/plugins/pip.js +123 -0
  283. package/dist/security/manifest/plugins/pip.js.map +7 -0
  284. package/dist/security/manifest/plugins/pip.test.js +208 -0
  285. package/dist/security/manifest/plugins/pip.test.js.map +7 -0
  286. package/dist/security/manifest/plugins/pubspec.js +212 -0
  287. package/dist/security/manifest/plugins/pubspec.js.map +7 -0
  288. package/dist/security/manifest/plugins/pyproject.js +261 -0
  289. package/dist/security/manifest/plugins/pyproject.js.map +7 -0
  290. package/dist/security/manifest/plugins/rubygems.js +185 -0
  291. package/dist/security/manifest/plugins/rubygems.js.map +7 -0
  292. package/dist/security/manifest/plugins/swift.js +200 -0
  293. package/dist/security/manifest/plugins/swift.js.map +7 -0
  294. package/dist/security/owasp.js +104 -0
  295. package/dist/security/owasp.js.map +7 -0
  296. package/dist/security/pipeline.js +125 -0
  297. package/dist/security/pipeline.js.map +7 -0
  298. package/dist/security/reachability.js +276 -0
  299. package/dist/security/reachability.js.map +7 -0
  300. package/dist/security/reachability.test.js +394 -0
  301. package/dist/security/reachability.test.js.map +7 -0
  302. package/dist/security/remediation.js +126 -0
  303. package/dist/security/remediation.js.map +7 -0
  304. package/dist/security/secrets.js +176 -0
  305. package/dist/security/secrets.js.map +7 -0
  306. package/dist/security/staleness.js +231 -0
  307. package/dist/security/staleness.js.map +7 -0
  308. package/dist/security/supply-chain.js +301 -0
  309. package/dist/security/supply-chain.js.map +7 -0
  310. package/dist/security/suppressions.js +106 -0
  311. package/dist/security/suppressions.js.map +7 -0
  312. package/dist/security/types.js +17 -0
  313. package/dist/security/types.js.map +7 -0
  314. package/dist/security/vuln/client.js +355 -0
  315. package/dist/security/vuln/client.js.map +7 -0
  316. package/dist/security/vuln/client.test.js +288 -0
  317. package/dist/security/vuln/client.test.js.map +7 -0
  318. package/dist/security/vuln/epss-client.js +95 -0
  319. package/dist/security/vuln/epss-client.js.map +7 -0
  320. package/dist/security/vuln/index.js +29 -0
  321. package/dist/security/vuln/index.js.map +7 -0
  322. package/dist/security/vuln/osv-adapter.js +321 -0
  323. package/dist/security/vuln/osv-adapter.js.map +7 -0
  324. package/dist/security/vuln/osv-adapter.test.js +391 -0
  325. package/dist/security/vuln/osv-adapter.test.js.map +7 -0
  326. package/dist/security/vuln/types.js +17 -0
  327. package/dist/security/vuln/types.js.map +7 -0
  328. package/dist/types.js.map +2 -2
  329. package/package.json +2 -1
@@ -0,0 +1,491 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var integrator_exports = {};
30
+ __export(integrator_exports, {
31
+ DependencyGraphIntegrator: () => DependencyGraphIntegrator
32
+ });
33
+ module.exports = __toCommonJS(integrator_exports);
34
+ var fs = __toESM(require("fs"));
35
+ var path = __toESM(require("path"));
36
+ var import_errors = require("../errors");
37
+ function parseNpmLockTransitives(lockPath) {
38
+ const deps = [];
39
+ try {
40
+ const content = fs.readFileSync(lockPath, "utf8");
41
+ const lockData = JSON.parse(content);
42
+ if (typeof lockData !== "object" || lockData === null) return deps;
43
+ const packages = lockData.packages;
44
+ if (typeof packages !== "object" || packages === null) {
45
+ return parseNpmLockV1Transitives(lockData);
46
+ }
47
+ for (const [key, value] of Object.entries(packages)) {
48
+ if (key === "") continue;
49
+ if (typeof value !== "object" || value === null) continue;
50
+ const pkg = value;
51
+ const parentName = key.replace(/^.*node_modules\//, "");
52
+ if (!parentName) continue;
53
+ const allDeps = {};
54
+ for (const field of ["dependencies", "optionalDependencies", "peerDependencies"]) {
55
+ const fieldDeps = pkg[field];
56
+ if (typeof fieldDeps === "object" && fieldDeps !== null) {
57
+ Object.assign(allDeps, fieldDeps);
58
+ }
59
+ }
60
+ for (const childName of Object.keys(allDeps)) {
61
+ deps.push({ parent: parentName, child: childName });
62
+ }
63
+ }
64
+ } catch {
65
+ }
66
+ return deps;
67
+ }
68
+ function parseNpmLockV1Transitives(lockData) {
69
+ const deps = [];
70
+ const topDeps = lockData.dependencies;
71
+ if (typeof topDeps !== "object" || topDeps === null) return deps;
72
+ function recurse(parentDeps) {
73
+ for (const [name, value] of Object.entries(parentDeps)) {
74
+ if (typeof value !== "object" || value === null) continue;
75
+ const pkg = value;
76
+ const requires = pkg.requires;
77
+ if (typeof requires === "object" && requires !== null) {
78
+ for (const childName of Object.keys(requires)) {
79
+ deps.push({ parent: name, child: childName });
80
+ }
81
+ }
82
+ const nested = pkg.dependencies;
83
+ if (typeof nested === "object" && nested !== null) {
84
+ recurse(nested);
85
+ }
86
+ }
87
+ }
88
+ recurse(topDeps);
89
+ return deps;
90
+ }
91
+ function parseCargoLockTransitives(lockPath) {
92
+ const deps = [];
93
+ try {
94
+ const content = fs.readFileSync(lockPath, "utf8");
95
+ const lines = content.split("\n");
96
+ let currentName = null;
97
+ let inDeps = false;
98
+ for (const line of lines) {
99
+ const trimmed = line.trim();
100
+ if (trimmed === "[[package]]") {
101
+ currentName = null;
102
+ inDeps = false;
103
+ continue;
104
+ }
105
+ if (currentName === null) {
106
+ const nameMatch = trimmed.match(/^name\s*=\s*"([^"]+)"$/);
107
+ if (nameMatch) {
108
+ currentName = nameMatch[1];
109
+ continue;
110
+ }
111
+ }
112
+ if (currentName !== null && trimmed === "dependencies = [") {
113
+ inDeps = true;
114
+ continue;
115
+ }
116
+ if (inDeps) {
117
+ if (trimmed === "]") {
118
+ inDeps = false;
119
+ continue;
120
+ }
121
+ const depMatch = trimmed.match(/^\s*"([^"\s]+)/);
122
+ if (depMatch && currentName) {
123
+ deps.push({ parent: currentName, child: depMatch[1] });
124
+ }
125
+ }
126
+ }
127
+ } catch {
128
+ }
129
+ return deps;
130
+ }
131
+ function parseGoTransitives(_lockPath) {
132
+ return [];
133
+ }
134
+ function parsePipTransitives(_lockPath) {
135
+ return [];
136
+ }
137
+ function discoverLockFiles(projectRoot) {
138
+ const lockFiles = [];
139
+ const candidates = [
140
+ { ecosystem: "npm", filename: "package-lock.json", parser: parseNpmLockTransitives },
141
+ { ecosystem: "npm", filename: "yarn.lock", parser: parseNpmLockTransitives },
142
+ { ecosystem: "cargo", filename: "Cargo.lock", parser: parseCargoLockTransitives },
143
+ { ecosystem: "go", filename: "go.sum", parser: parseGoTransitives },
144
+ { ecosystem: "python", filename: "requirements.txt", parser: parsePipTransitives }
145
+ ];
146
+ for (const candidate of candidates) {
147
+ const lockPath = path.join(projectRoot, candidate.filename);
148
+ if (fs.existsSync(lockPath)) {
149
+ lockFiles.push({
150
+ ecosystem: candidate.ecosystem,
151
+ lockPath,
152
+ parser: candidate.parser
153
+ });
154
+ }
155
+ }
156
+ return lockFiles;
157
+ }
158
+ class DependencyGraphIntegrator {
159
+ constructor(db, projectRoot) {
160
+ this.db = db;
161
+ this.projectRoot = projectRoot;
162
+ }
163
+ /**
164
+ * Create import/reference edges between code symbols and Dependency_Nodes.
165
+ *
166
+ * Per Requirement 2.1: creates `imports` edges from file nodes that contain
167
+ * import statements resolving to a dependency → the Dependency_Node.
168
+ *
169
+ * Per Requirement 2.2: creates `references` edges from code symbols that
170
+ * reference classes/functions from a dependency → the Dependency_Node.
171
+ */
172
+ async integrate() {
173
+ let importsEdgesCreated = 0;
174
+ let referencesEdgesCreated = 0;
175
+ const rawDb = this.db.getRawDb();
176
+ const depRows = rawDb.all("SELECT node_id, package_name, ecosystem FROM sec_dependencies");
177
+ if (depRows.length === 0) {
178
+ return { importsEdgesCreated, referencesEdgesCreated };
179
+ }
180
+ const depByName = /* @__PURE__ */ new Map();
181
+ for (const row of depRows) {
182
+ depByName.set(row.package_name, row.node_id);
183
+ }
184
+ const importNodes = this.db.getNodesByKind("import");
185
+ const createdImportEdges = /* @__PURE__ */ new Set();
186
+ for (const importNode of importNodes) {
187
+ const specifier = importNode.name;
188
+ const matchedDepId = this.matchImportToDependency(specifier, depByName);
189
+ if (!matchedDepId) continue;
190
+ const fileNodeId = this.findFileNodeId(rawDb, importNode.filePath);
191
+ if (!fileNodeId) continue;
192
+ const edgeKey = `${fileNodeId}\u2192${matchedDepId}`;
193
+ if (createdImportEdges.has(edgeKey)) continue;
194
+ const edge = {
195
+ source: fileNodeId,
196
+ target: matchedDepId,
197
+ kind: "imports",
198
+ line: importNode.startLine,
199
+ confidence: "inferred",
200
+ confidenceScore: 0.9
201
+ };
202
+ this.db.insertEdge(edge);
203
+ createdImportEdges.add(edgeKey);
204
+ importsEdgesCreated++;
205
+ }
206
+ const codeKinds = /* @__PURE__ */ new Set(["function", "method", "class", "variable", "constant", "property"]);
207
+ const createdRefEdges = /* @__PURE__ */ new Set();
208
+ for (const importNode of importNodes) {
209
+ const specifier = importNode.name;
210
+ const matchedDepId = this.matchImportToDependency(specifier, depByName);
211
+ if (!matchedDepId) continue;
212
+ const fileNodes = this.db.getNodesByFile(importNode.filePath);
213
+ const codeSymbols = fileNodes.filter((n) => codeKinds.has(n.kind));
214
+ if (codeSymbols.length === 0) continue;
215
+ const symbolIds = codeSymbols.map((n) => n.id);
216
+ const edges = this.db.getEdgesForNodes(symbolIds);
217
+ for (const edge of edges) {
218
+ if ((edge.kind === "calls" || edge.kind === "references") && edge.target === importNode.id && symbolIds.includes(edge.source)) {
219
+ const refKey = `${edge.source}\u2192${matchedDepId}`;
220
+ if (createdRefEdges.has(refKey)) continue;
221
+ const refEdge = {
222
+ source: edge.source,
223
+ target: matchedDepId,
224
+ kind: "references",
225
+ confidence: "inferred",
226
+ confidenceScore: 0.8
227
+ };
228
+ this.db.insertEdge(refEdge);
229
+ createdRefEdges.add(refKey);
230
+ referencesEdgesCreated++;
231
+ }
232
+ }
233
+ }
234
+ return { importsEdgesCreated, referencesEdgesCreated };
235
+ }
236
+ /**
237
+ * Find the file node ID for a given file path.
238
+ * File nodes have kind='file' and their file_path matches.
239
+ */
240
+ findFileNodeId(rawDb, filePath) {
241
+ const row = rawDb.get(
242
+ "SELECT id FROM nodes WHERE kind = ? AND file_path = ? LIMIT 1",
243
+ ["file", filePath]
244
+ );
245
+ return row ? row.id : null;
246
+ }
247
+ /**
248
+ * Match an import specifier to a dependency node ID.
249
+ *
250
+ * Handles:
251
+ * - Exact match: `express` → dep:npm:express
252
+ * - Scoped packages: `@scope/pkg` → dep:npm:@scope/pkg
253
+ * - Subpath imports: `express/Router` → dep:npm:express
254
+ * - Scoped subpath: `@angular/core/testing` → dep:npm:@angular/core
255
+ * - Go modules: `github.com/gin-gonic/gin` → dep:go:github.com/gin-gonic/gin
256
+ * - Go subpath: `github.com/gin-gonic/gin/internal` → dep:go:github.com/gin-gonic/gin
257
+ */
258
+ matchImportToDependency(specifier, depByName) {
259
+ if (!specifier) return null;
260
+ if (specifier.startsWith(".") || specifier.startsWith("/")) return null;
261
+ if (depByName.has(specifier)) {
262
+ return depByName.get(specifier);
263
+ }
264
+ if (specifier.startsWith("@")) {
265
+ const parts = specifier.split("/");
266
+ if (parts.length >= 2) {
267
+ const scopedName = `${parts[0]}/${parts[1]}`;
268
+ if (depByName.has(scopedName)) {
269
+ return depByName.get(scopedName);
270
+ }
271
+ }
272
+ }
273
+ if (!specifier.startsWith("@")) {
274
+ const slashIdx = specifier.indexOf("/");
275
+ if (slashIdx > 0) {
276
+ const baseName = specifier.slice(0, slashIdx);
277
+ if (depByName.has(baseName)) {
278
+ return depByName.get(baseName);
279
+ }
280
+ }
281
+ }
282
+ if (specifier.includes(".") && specifier.includes("/")) {
283
+ const parts = specifier.split("/");
284
+ for (let i = parts.length - 1; i >= 2; i--) {
285
+ const prefix = parts.slice(0, i).join("/");
286
+ if (depByName.has(prefix)) {
287
+ return depByName.get(prefix);
288
+ }
289
+ }
290
+ }
291
+ return null;
292
+ }
293
+ /**
294
+ * Resolve transitive dependencies up to maxDepth levels.
295
+ *
296
+ * For each ecosystem with a lock file:
297
+ * 1. Parse the lock file to extract dependency relationships
298
+ * 2. Create `depends_on` edges between Dependency_Nodes
299
+ * 3. Traverse up to maxDepth levels of transitive depth
300
+ *
301
+ * If a lock file is missing for an ecosystem, mark all dependencies of that
302
+ * ecosystem with `transitive_status: 'incomplete'` and log a warning.
303
+ *
304
+ * @param maxDepth - Maximum levels of transitive depth to resolve (default: 10)
305
+ */
306
+ async resolveTransitives(maxDepth = 10) {
307
+ let dependsOnEdgesCreated = 0;
308
+ const incompleteNodes = [];
309
+ const rawDb = this.db.getRawDb();
310
+ const depRows = rawDb.all("SELECT node_id, package_name, ecosystem FROM sec_dependencies");
311
+ if (depRows.length === 0) {
312
+ return { dependsOnEdgesCreated, incompleteNodes };
313
+ }
314
+ const depsByEcosystem = /* @__PURE__ */ new Map();
315
+ for (const row of depRows) {
316
+ if (!depsByEcosystem.has(row.ecosystem)) {
317
+ depsByEcosystem.set(row.ecosystem, /* @__PURE__ */ new Map());
318
+ }
319
+ depsByEcosystem.get(row.ecosystem).set(row.package_name, row.node_id);
320
+ }
321
+ const lockFiles = discoverLockFiles(this.projectRoot);
322
+ const ecosystemsWithLockFile = new Set(lockFiles.map((lf) => lf.ecosystem));
323
+ for (const [ecosystem, depsMap] of depsByEcosystem) {
324
+ if (!ecosystemsWithLockFile.has(ecosystem)) {
325
+ for (const [pkgName, nodeId] of depsMap) {
326
+ rawDb.run(
327
+ `UPDATE sec_dependencies SET transitive_status = 'incomplete' WHERE node_id = ?`,
328
+ [nodeId]
329
+ );
330
+ incompleteNodes.push(nodeId);
331
+ (0, import_errors.logWarn)(
332
+ `[sec:integrator] Transitive resolution incomplete for "${pkgName}" (${ecosystem}): no lock file found`
333
+ );
334
+ }
335
+ }
336
+ }
337
+ for (const lockFile of lockFiles) {
338
+ const transitives = lockFile.parser(lockFile.lockPath);
339
+ const ecosystemDeps = depsByEcosystem.get(lockFile.ecosystem);
340
+ if (!ecosystemDeps) continue;
341
+ if (transitives.length === 0 && ecosystemDeps.size > 0) {
342
+ if (lockFile.ecosystem === "go" || lockFile.ecosystem === "python") {
343
+ for (const [pkgName, nodeId] of ecosystemDeps) {
344
+ rawDb.run(
345
+ `UPDATE sec_dependencies SET transitive_status = 'incomplete' WHERE node_id = ?`,
346
+ [nodeId]
347
+ );
348
+ incompleteNodes.push(nodeId);
349
+ (0, import_errors.logWarn)(
350
+ `[sec:integrator] Transitive resolution incomplete for "${pkgName}" (${lockFile.ecosystem}): dependency tree not resolvable from lock file`
351
+ );
352
+ }
353
+ }
354
+ continue;
355
+ }
356
+ const adjacency = /* @__PURE__ */ new Map();
357
+ for (const { parent, child } of transitives) {
358
+ if (!adjacency.has(parent)) {
359
+ adjacency.set(parent, /* @__PURE__ */ new Set());
360
+ }
361
+ adjacency.get(parent).add(child);
362
+ }
363
+ const createdEdges = /* @__PURE__ */ new Set();
364
+ for (const [pkgName, nodeId] of ecosystemDeps) {
365
+ const visited = /* @__PURE__ */ new Set([pkgName]);
366
+ let frontier = [pkgName];
367
+ let depth = 0;
368
+ while (frontier.length > 0 && depth < maxDepth) {
369
+ const nextFrontier = [];
370
+ depth++;
371
+ for (const current of frontier) {
372
+ const children = adjacency.get(current);
373
+ if (!children) continue;
374
+ for (const child of children) {
375
+ if (visited.has(child)) continue;
376
+ visited.add(child);
377
+ const childNodeId = ecosystemDeps.get(child);
378
+ const parentNodeId = current === pkgName ? nodeId : ecosystemDeps.get(current);
379
+ if (parentNodeId && childNodeId) {
380
+ const edgeKey = `${parentNodeId}->${childNodeId}`;
381
+ if (!createdEdges.has(edgeKey)) {
382
+ const edge = {
383
+ source: parentNodeId,
384
+ target: childNodeId,
385
+ kind: "depends_on",
386
+ confidence: "inferred",
387
+ confidenceScore: 1
388
+ };
389
+ this.db.insertEdge(edge);
390
+ createdEdges.add(edgeKey);
391
+ dependsOnEdgesCreated++;
392
+ }
393
+ }
394
+ nextFrontier.push(child);
395
+ }
396
+ }
397
+ frontier = nextFrontier;
398
+ }
399
+ }
400
+ }
401
+ return { dependsOnEdgesCreated, incompleteNodes };
402
+ }
403
+ /**
404
+ * Remove orphaned Dependency_Nodes and their edges.
405
+ *
406
+ * A Dependency_Node is orphaned if:
407
+ * 1. It has no `declared_in` edges (manifest no longer declares it), OR
408
+ * 2. None of its source manifests still exist on disk
409
+ *
410
+ * Also removes transitive Dependency_Nodes that are no longer reachable from
411
+ * any remaining direct dependency via `depends_on` edges.
412
+ *
413
+ * @param manifestExists - Optional function to check if a manifest path exists.
414
+ * Defaults to fs.existsSync. Useful for testing.
415
+ */
416
+ async cleanup(manifestExists) {
417
+ let nodesRemoved = 0;
418
+ let edgesRemoved = 0;
419
+ const rawDb = this.db.getRawDb();
420
+ const checkExists = manifestExists ?? ((p) => fs.existsSync(p));
421
+ const orphanedByEdge = rawDb.all(
422
+ `SELECT sd.node_id FROM sec_dependencies sd
423
+ WHERE NOT EXISTS (
424
+ SELECT 1 FROM edges e
425
+ WHERE e.source = sd.node_id AND e.kind = 'declared_in'
426
+ )`
427
+ );
428
+ const orphanedNodeIds = new Set(orphanedByEdge.map((r) => r.node_id));
429
+ const allDeps = rawDb.all(
430
+ `SELECT node_id, source_manifests FROM sec_dependencies`
431
+ );
432
+ for (const dep of allDeps) {
433
+ if (orphanedNodeIds.has(dep.node_id)) continue;
434
+ const sourceManifests = JSON.parse(dep.source_manifests);
435
+ const hasValidManifest = sourceManifests.some((manifest) => {
436
+ const absolutePath = path.isAbsolute(manifest) ? manifest : path.join(this.projectRoot, manifest);
437
+ return checkExists(absolutePath);
438
+ });
439
+ if (!hasValidManifest) {
440
+ orphanedNodeIds.add(dep.node_id);
441
+ }
442
+ }
443
+ const remainingNodeIds = new Set(
444
+ allDeps.filter((d) => !orphanedNodeIds.has(d.node_id)).map((d) => d.node_id)
445
+ );
446
+ const reachableFromDirect = new Set(remainingNodeIds);
447
+ let frontier = [...remainingNodeIds];
448
+ while (frontier.length > 0) {
449
+ const placeholders = frontier.map(() => "?").join(",");
450
+ const nextRows = rawDb.all(
451
+ `SELECT DISTINCT target FROM edges WHERE source IN (${placeholders}) AND kind = 'depends_on'`,
452
+ frontier
453
+ );
454
+ frontier = [];
455
+ for (const row of nextRows) {
456
+ if (!reachableFromDirect.has(row.target)) {
457
+ reachableFromDirect.add(row.target);
458
+ frontier.push(row.target);
459
+ }
460
+ }
461
+ }
462
+ for (const dep of allDeps) {
463
+ if (!orphanedNodeIds.has(dep.node_id) && !reachableFromDirect.has(dep.node_id)) {
464
+ orphanedNodeIds.add(dep.node_id);
465
+ }
466
+ }
467
+ if (orphanedNodeIds.size === 0) {
468
+ return { nodesRemoved: 0, edgesRemoved: 0 };
469
+ }
470
+ const orphanedIds = [...orphanedNodeIds];
471
+ for (const nodeId of orphanedIds) {
472
+ const edgeCount = rawDb.get(
473
+ `SELECT COUNT(*) as c FROM edges
474
+ WHERE source = ? OR target = ?`,
475
+ [nodeId, nodeId]
476
+ );
477
+ edgesRemoved += edgeCount?.c ?? 0;
478
+ rawDb.run("DELETE FROM edges WHERE source = ? OR target = ?", [nodeId, nodeId]);
479
+ rawDb.run("DELETE FROM sec_dependencies WHERE node_id = ?", [nodeId]);
480
+ rawDb.run("DELETE FROM nodes WHERE id = ?", [nodeId]);
481
+ rawDb.run("DELETE FROM nodes_fts WHERE id = ?", [nodeId]);
482
+ nodesRemoved++;
483
+ }
484
+ return { nodesRemoved, edgesRemoved };
485
+ }
486
+ }
487
+ // Annotate the CommonJS export names for ESM import in node:
488
+ 0 && (module.exports = {
489
+ DependencyGraphIntegrator
490
+ });
491
+ //# sourceMappingURL=integrator.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/security/integrator.ts"],
4
+ "sourcesContent": ["/**\n * DependencyGraphIntegrator\n *\n * Links dependency nodes to code symbols via import and reference edges,\n * resolves transitive dependencies from lock files, and cleans up orphaned nodes.\n *\n * Integration flow:\n * 1. integrate() \u2014 Scan file nodes for import statements resolving to dependencies,\n * create `imports` and `references` edges.\n * 2. resolveTransitives(maxDepth) \u2014 Parse lock files to discover transitive dependency\n * relationships, create `depends_on` edges between Dependency_Nodes.\n * 3. cleanup() \u2014 Remove orphaned Dependency_Nodes no longer declared in any manifest.\n */\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { GraphDatabase } from '../db/database';\nimport type { Edge } from '../types';\nimport type { IntegrationResult, TransitiveResult, CleanupResult } from './types';\nimport { logWarn } from '../errors';\n\n// \u2500\u2500 Lock File Parsers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Transitive dependency relationship: parent depends on child.\n */\ninterface TransitiveDep {\n parent: string;\n child: string;\n}\n\n/**\n * Parse package-lock.json (v2/v3) to extract transitive dependency relationships.\n * Returns pairs of (parent, child) where parent depends on child.\n */\nfunction parseNpmLockTransitives(lockPath: string): TransitiveDep[] {\n const deps: TransitiveDep[] = [];\n try {\n const content = fs.readFileSync(lockPath, 'utf8');\n const lockData = JSON.parse(content);\n\n if (typeof lockData !== 'object' || lockData === null) return deps;\n\n const packages = lockData.packages;\n if (typeof packages !== 'object' || packages === null) {\n // Try lockfileVersion 1 format\n return parseNpmLockV1Transitives(lockData);\n }\n\n // lockfileVersion 2/3: packages field with nested node_modules paths\n for (const [key, value] of Object.entries(packages as Record<string, unknown>)) {\n if (key === '') continue; // skip root\n if (typeof value !== 'object' || value === null) continue;\n const pkg = value as Record<string, unknown>;\n\n // Extract the package name from the key\n const parentName = key.replace(/^.*node_modules\\//, '');\n if (!parentName) continue;\n\n // Extract this package's dependencies\n const allDeps: Record<string, unknown> = {};\n for (const field of ['dependencies', 'optionalDependencies', 'peerDependencies']) {\n const fieldDeps = pkg[field];\n if (typeof fieldDeps === 'object' && fieldDeps !== null) {\n Object.assign(allDeps, fieldDeps);\n }\n }\n\n for (const childName of Object.keys(allDeps)) {\n deps.push({ parent: parentName, child: childName });\n }\n }\n } catch {\n // Lock file parse failure \u2014 return empty\n }\n return deps;\n}\n\n/**\n * Parse lockfileVersion 1 format (nested dependencies object).\n */\nfunction parseNpmLockV1Transitives(lockData: Record<string, unknown>): TransitiveDep[] {\n const deps: TransitiveDep[] = [];\n const topDeps = lockData.dependencies;\n if (typeof topDeps !== 'object' || topDeps === null) return deps;\n\n function recurse(parentDeps: Record<string, unknown>): void {\n for (const [name, value] of Object.entries(parentDeps)) {\n if (typeof value !== 'object' || value === null) continue;\n const pkg = value as Record<string, unknown>;\n\n // Check for requires (direct dependencies of this package)\n const requires = pkg.requires;\n if (typeof requires === 'object' && requires !== null) {\n for (const childName of Object.keys(requires as Record<string, unknown>)) {\n deps.push({ parent: name, child: childName });\n }\n }\n\n // Recurse into nested dependencies\n const nested = pkg.dependencies;\n if (typeof nested === 'object' && nested !== null) {\n recurse(nested as Record<string, unknown>);\n }\n }\n }\n\n recurse(topDeps as Record<string, unknown>);\n return deps;\n}\n\n/**\n * Parse Cargo.lock to extract transitive dependency relationships.\n * Cargo.lock [[package]] blocks have a `dependencies` field listing direct deps.\n */\nfunction parseCargoLockTransitives(lockPath: string): TransitiveDep[] {\n const deps: TransitiveDep[] = [];\n try {\n const content = fs.readFileSync(lockPath, 'utf8');\n const lines = content.split('\\n');\n\n let currentName: string | null = null;\n let inDeps = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (trimmed === '[[package]]') {\n currentName = null;\n inDeps = false;\n continue;\n }\n\n if (currentName === null) {\n const nameMatch = trimmed.match(/^name\\s*=\\s*\"([^\"]+)\"$/);\n if (nameMatch) {\n currentName = nameMatch[1];\n continue;\n }\n }\n\n if (currentName !== null && trimmed === 'dependencies = [') {\n inDeps = true;\n continue;\n }\n\n if (inDeps) {\n if (trimmed === ']') {\n inDeps = false;\n continue;\n }\n // Lines like: \"serde_derive 1.0.193 (registry+...)\",\n // or simply: \"serde_derive\",\n const depMatch = trimmed.match(/^\\s*\"([^\"\\s]+)/);\n if (depMatch && currentName) {\n deps.push({ parent: currentName, child: depMatch[1] });\n }\n }\n }\n } catch {\n // Lock file parse failure \u2014 return empty\n }\n return deps;\n}\n\n/**\n * Parse go.sum to extract module dependency relationships.\n * go.sum doesn't directly encode dependency trees, so we parse go.mod\n * for the require directives. For transitive resolution, we'd need\n * `go mod graph` output, but for the MVP we mark Go deps as incomplete\n * if no explicit dependency tree is available.\n *\n * Returns empty \u2014 Go transitive resolution requires `go mod graph` which\n * is not available at index time. Nodes will be marked incomplete.\n */\nfunction parseGoTransitives(_lockPath: string): TransitiveDep[] {\n // Go modules don't have a lock file that encodes the dependency tree.\n // go.sum only provides checksums. Full transitive resolution requires\n // running `go mod graph` which is out of scope for static analysis.\n return [];\n}\n\n/**\n * Parse pip's requirements files for transitive dependencies.\n * pip doesn't have a standard lock file with dependency trees.\n * Returns empty \u2014 nodes will be marked incomplete.\n */\nfunction parsePipTransitives(_lockPath: string): TransitiveDep[] {\n return [];\n}\n\n// \u2500\u2500 Lock File Discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface LockFileInfo {\n ecosystem: string;\n lockPath: string;\n parser: (lockPath: string) => TransitiveDep[];\n}\n\n/**\n * Discover lock files in the project root for each ecosystem.\n */\nfunction discoverLockFiles(projectRoot: string): LockFileInfo[] {\n const lockFiles: LockFileInfo[] = [];\n\n const candidates: Array<{ ecosystem: string; filename: string; parser: (p: string) => TransitiveDep[] }> = [\n { ecosystem: 'npm', filename: 'package-lock.json', parser: parseNpmLockTransitives },\n { ecosystem: 'npm', filename: 'yarn.lock', parser: parseNpmLockTransitives },\n { ecosystem: 'cargo', filename: 'Cargo.lock', parser: parseCargoLockTransitives },\n { ecosystem: 'go', filename: 'go.sum', parser: parseGoTransitives },\n { ecosystem: 'python', filename: 'requirements.txt', parser: parsePipTransitives },\n ];\n\n for (const candidate of candidates) {\n const lockPath = path.join(projectRoot, candidate.filename);\n if (fs.existsSync(lockPath)) {\n lockFiles.push({\n ecosystem: candidate.ecosystem,\n lockPath,\n parser: candidate.parser,\n });\n }\n }\n\n return lockFiles;\n}\n\n// \u2500\u2500 DependencyGraphIntegrator Class \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class DependencyGraphIntegrator {\n private readonly db: GraphDatabase;\n private readonly projectRoot: string;\n\n constructor(db: GraphDatabase, projectRoot: string) {\n this.db = db;\n this.projectRoot = projectRoot;\n }\n\n /**\n * Create import/reference edges between code symbols and Dependency_Nodes.\n *\n * Per Requirement 2.1: creates `imports` edges from file nodes that contain\n * import statements resolving to a dependency \u2192 the Dependency_Node.\n *\n * Per Requirement 2.2: creates `references` edges from code symbols that\n * reference classes/functions from a dependency \u2192 the Dependency_Node.\n */\n async integrate(): Promise<IntegrationResult> {\n let importsEdgesCreated = 0;\n let referencesEdgesCreated = 0;\n\n const rawDb = this.db.getRawDb();\n\n // Get all dependency nodes with their package names and ecosystems\n const depRows: Array<{ node_id: string; package_name: string; ecosystem: string }> =\n rawDb.all('SELECT node_id, package_name, ecosystem FROM sec_dependencies');\n\n if (depRows.length === 0) {\n return { importsEdgesCreated, referencesEdgesCreated };\n }\n\n // Build a lookup map: package name \u2192 dependency node ID\n const depByName = new Map<string, string>();\n for (const row of depRows) {\n depByName.set(row.package_name, row.node_id);\n }\n\n // \u2500\u2500 Step 1: Create `imports` edges (file \u2192 dependency) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Scan import nodes. The import node's `name` field contains the module\n // specifier (e.g., 'express', '@nestjs/core', 'github.com/gin-gonic/gin').\n // For each match, create an edge from the FILE node to the Dependency_Node.\n const importNodes = this.db.getNodesByKind('import');\n\n // Track (file, dep) pairs to avoid duplicate edges\n const createdImportEdges = new Set<string>();\n\n for (const importNode of importNodes) {\n // Use the import node's `name` field which is the raw module specifier\n const specifier = importNode.name;\n\n const matchedDepId = this.matchImportToDependency(specifier, depByName);\n if (!matchedDepId) continue;\n\n // Find the file node for this import's file path\n const fileNodeId = this.findFileNodeId(rawDb, importNode.filePath);\n if (!fileNodeId) continue;\n\n const edgeKey = `${fileNodeId}\u2192${matchedDepId}`;\n if (createdImportEdges.has(edgeKey)) continue;\n\n const edge: Edge = {\n source: fileNodeId,\n target: matchedDepId,\n kind: 'imports',\n line: importNode.startLine,\n confidence: 'inferred',\n confidenceScore: 0.9,\n };\n this.db.insertEdge(edge);\n createdImportEdges.add(edgeKey);\n importsEdgesCreated++;\n }\n\n // \u2500\u2500 Step 2: Create `references` edges (code symbol \u2192 dependency) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // For each import node that matched a dependency, find code symbols in the\n // same file that call or reference that import node. Those symbols effectively\n // reference the dependency.\n const codeKinds = new Set(['function', 'method', 'class', 'variable', 'constant', 'property']);\n const createdRefEdges = new Set<string>();\n\n for (const importNode of importNodes) {\n const specifier = importNode.name;\n const matchedDepId = this.matchImportToDependency(specifier, depByName);\n if (!matchedDepId) continue;\n\n // Get all nodes in the same file\n const fileNodes = this.db.getNodesByFile(importNode.filePath);\n const codeSymbols = fileNodes.filter(n => codeKinds.has(n.kind));\n if (codeSymbols.length === 0) continue;\n\n // Check edges from code symbols to this import node\n const symbolIds = codeSymbols.map(n => n.id);\n const edges = this.db.getEdgesForNodes(symbolIds);\n\n for (const edge of edges) {\n // A code symbol calls or references the import node \u2192 it references the dependency\n if (\n (edge.kind === 'calls' || edge.kind === 'references') &&\n edge.target === importNode.id &&\n symbolIds.includes(edge.source)\n ) {\n const refKey = `${edge.source}\u2192${matchedDepId}`;\n if (createdRefEdges.has(refKey)) continue;\n\n const refEdge: Edge = {\n source: edge.source,\n target: matchedDepId,\n kind: 'references',\n confidence: 'inferred',\n confidenceScore: 0.8,\n };\n this.db.insertEdge(refEdge);\n createdRefEdges.add(refKey);\n referencesEdgesCreated++;\n }\n }\n }\n\n return { importsEdgesCreated, referencesEdgesCreated };\n }\n\n /**\n * Find the file node ID for a given file path.\n * File nodes have kind='file' and their file_path matches.\n */\n private findFileNodeId(rawDb: any, filePath: string): string | null {\n const row = rawDb.get(\n 'SELECT id FROM nodes WHERE kind = ? AND file_path = ? LIMIT 1',\n ['file', filePath],\n );\n return row ? row.id : null;\n }\n\n /**\n * Match an import specifier to a dependency node ID.\n *\n * Handles:\n * - Exact match: `express` \u2192 dep:npm:express\n * - Scoped packages: `@scope/pkg` \u2192 dep:npm:@scope/pkg\n * - Subpath imports: `express/Router` \u2192 dep:npm:express\n * - Scoped subpath: `@angular/core/testing` \u2192 dep:npm:@angular/core\n * - Go modules: `github.com/gin-gonic/gin` \u2192 dep:go:github.com/gin-gonic/gin\n * - Go subpath: `github.com/gin-gonic/gin/internal` \u2192 dep:go:github.com/gin-gonic/gin\n */\n private matchImportToDependency(\n specifier: string,\n depByName: Map<string, string>,\n ): string | null {\n if (!specifier) return null;\n\n // Skip relative imports\n if (specifier.startsWith('.') || specifier.startsWith('/')) return null;\n\n // Direct match\n if (depByName.has(specifier)) {\n return depByName.get(specifier)!;\n }\n\n // For scoped packages: @scope/name/subpath \u2192 @scope/name\n if (specifier.startsWith('@')) {\n const parts = specifier.split('/');\n if (parts.length >= 2) {\n const scopedName = `${parts[0]}/${parts[1]}`;\n if (depByName.has(scopedName)) {\n return depByName.get(scopedName)!;\n }\n }\n }\n\n // For unscoped packages: name/subpath \u2192 name\n if (!specifier.startsWith('@')) {\n const slashIdx = specifier.indexOf('/');\n if (slashIdx > 0) {\n const baseName = specifier.slice(0, slashIdx);\n if (depByName.has(baseName)) {\n return depByName.get(baseName)!;\n }\n }\n }\n\n // Go module path matching: try progressively shorter prefixes\n // e.g. github.com/gin-gonic/gin/internal \u2192 github.com/gin-gonic/gin\n if (specifier.includes('.') && specifier.includes('/')) {\n const parts = specifier.split('/');\n for (let i = parts.length - 1; i >= 2; i--) {\n const prefix = parts.slice(0, i).join('/');\n if (depByName.has(prefix)) {\n return depByName.get(prefix)!;\n }\n }\n }\n\n return null;\n }\n\n /**\n * Resolve transitive dependencies up to maxDepth levels.\n *\n * For each ecosystem with a lock file:\n * 1. Parse the lock file to extract dependency relationships\n * 2. Create `depends_on` edges between Dependency_Nodes\n * 3. Traverse up to maxDepth levels of transitive depth\n *\n * If a lock file is missing for an ecosystem, mark all dependencies of that\n * ecosystem with `transitive_status: 'incomplete'` and log a warning.\n *\n * @param maxDepth - Maximum levels of transitive depth to resolve (default: 10)\n */\n async resolveTransitives(maxDepth: number = 10): Promise<TransitiveResult> {\n let dependsOnEdgesCreated = 0;\n const incompleteNodes: string[] = [];\n const rawDb = this.db.getRawDb();\n\n // Get all dependency nodes grouped by ecosystem\n const depRows: Array<{ node_id: string; package_name: string; ecosystem: string }> =\n rawDb.all('SELECT node_id, package_name, ecosystem FROM sec_dependencies');\n\n if (depRows.length === 0) {\n return { dependsOnEdgesCreated, incompleteNodes };\n }\n\n // Group dependencies by ecosystem\n const depsByEcosystem = new Map<string, Map<string, string>>();\n for (const row of depRows) {\n if (!depsByEcosystem.has(row.ecosystem)) {\n depsByEcosystem.set(row.ecosystem, new Map());\n }\n depsByEcosystem.get(row.ecosystem)!.set(row.package_name, row.node_id);\n }\n\n // Discover available lock files\n const lockFiles = discoverLockFiles(this.projectRoot);\n const ecosystemsWithLockFile = new Set(lockFiles.map(lf => lf.ecosystem));\n\n // Mark ecosystems without lock files as incomplete\n for (const [ecosystem, depsMap] of depsByEcosystem) {\n if (!ecosystemsWithLockFile.has(ecosystem)) {\n // No lock file for this ecosystem \u2014 mark all deps as incomplete\n for (const [pkgName, nodeId] of depsMap) {\n rawDb.run(\n `UPDATE sec_dependencies SET transitive_status = 'incomplete' WHERE node_id = ?`,\n [nodeId],\n );\n incompleteNodes.push(nodeId);\n logWarn(\n `[sec:integrator] Transitive resolution incomplete for \"${pkgName}\" (${ecosystem}): ` +\n `no lock file found`,\n );\n }\n }\n }\n\n // Parse each lock file and create depends_on edges\n for (const lockFile of lockFiles) {\n const transitives = lockFile.parser(lockFile.lockPath);\n const ecosystemDeps = depsByEcosystem.get(lockFile.ecosystem);\n if (!ecosystemDeps) continue;\n\n if (transitives.length === 0 && ecosystemDeps.size > 0) {\n // Lock file exists but yielded no transitive info (e.g., go.sum)\n // Mark deps as incomplete if the parser couldn't extract tree info\n if (lockFile.ecosystem === 'go' || lockFile.ecosystem === 'python') {\n for (const [pkgName, nodeId] of ecosystemDeps) {\n rawDb.run(\n `UPDATE sec_dependencies SET transitive_status = 'incomplete' WHERE node_id = ?`,\n [nodeId],\n );\n incompleteNodes.push(nodeId);\n logWarn(\n `[sec:integrator] Transitive resolution incomplete for \"${pkgName}\" (${lockFile.ecosystem}): ` +\n `dependency tree not resolvable from lock file`,\n );\n }\n }\n continue;\n }\n\n // Build adjacency list from transitive relationships\n const adjacency = new Map<string, Set<string>>();\n for (const { parent, child } of transitives) {\n if (!adjacency.has(parent)) {\n adjacency.set(parent, new Set());\n }\n adjacency.get(parent)!.add(child);\n }\n\n // BFS from each direct dependency up to maxDepth levels\n // Create depends_on edges only between nodes that exist in our dep graph\n const createdEdges = new Set<string>();\n\n for (const [pkgName, nodeId] of ecosystemDeps) {\n const visited = new Set<string>([pkgName]);\n let frontier = [pkgName];\n let depth = 0;\n\n while (frontier.length > 0 && depth < maxDepth) {\n const nextFrontier: string[] = [];\n depth++;\n\n for (const current of frontier) {\n const children = adjacency.get(current);\n if (!children) continue;\n\n for (const child of children) {\n if (visited.has(child)) continue;\n visited.add(child);\n\n // Create depends_on edge if the child is a known dependency node\n const childNodeId = ecosystemDeps.get(child);\n const parentNodeId = current === pkgName ? nodeId : ecosystemDeps.get(current);\n\n if (parentNodeId && childNodeId) {\n const edgeKey = `${parentNodeId}->${childNodeId}`;\n if (!createdEdges.has(edgeKey)) {\n const edge: Edge = {\n source: parentNodeId,\n target: childNodeId,\n kind: 'depends_on',\n confidence: 'inferred',\n confidenceScore: 1.0,\n };\n this.db.insertEdge(edge);\n createdEdges.add(edgeKey);\n dependsOnEdgesCreated++;\n }\n }\n\n nextFrontier.push(child);\n }\n }\n\n frontier = nextFrontier;\n }\n }\n }\n\n return { dependsOnEdgesCreated, incompleteNodes };\n }\n\n /**\n * Remove orphaned Dependency_Nodes and their edges.\n *\n * A Dependency_Node is orphaned if:\n * 1. It has no `declared_in` edges (manifest no longer declares it), OR\n * 2. None of its source manifests still exist on disk\n *\n * Also removes transitive Dependency_Nodes that are no longer reachable from\n * any remaining direct dependency via `depends_on` edges.\n *\n * @param manifestExists - Optional function to check if a manifest path exists.\n * Defaults to fs.existsSync. Useful for testing.\n */\n async cleanup(manifestExists?: (absolutePath: string) => boolean): Promise<CleanupResult> {\n let nodesRemoved = 0;\n let edgesRemoved = 0;\n const rawDb = this.db.getRawDb();\n const checkExists = manifestExists ?? ((p: string) => fs.existsSync(p));\n\n // Step 1: Find dependency nodes that are orphaned because they have no\n // declared_in edges (manifest no longer declares them)\n const orphanedByEdge: Array<{ node_id: string }> = rawDb.all(\n `SELECT sd.node_id FROM sec_dependencies sd\n WHERE NOT EXISTS (\n SELECT 1 FROM edges e\n WHERE e.source = sd.node_id AND e.kind = 'declared_in'\n )`,\n );\n\n const orphanedNodeIds = new Set<string>(orphanedByEdge.map(r => r.node_id));\n\n // Step 2: Also check if source manifests still exist on disk\n const allDeps: Array<{ node_id: string; source_manifests: string }> = rawDb.all(\n `SELECT node_id, source_manifests FROM sec_dependencies`,\n );\n\n for (const dep of allDeps) {\n if (orphanedNodeIds.has(dep.node_id)) continue; // already marked\n\n const sourceManifests: string[] = JSON.parse(dep.source_manifests);\n const hasValidManifest = sourceManifests.some(manifest => {\n const absolutePath = path.isAbsolute(manifest)\n ? manifest\n : path.join(this.projectRoot, manifest);\n return checkExists(absolutePath);\n });\n\n if (!hasValidManifest) {\n orphanedNodeIds.add(dep.node_id);\n }\n }\n\n // Step 3: Find transitive Dependency_Nodes no longer reachable from any\n // remaining direct dependency via `depends_on` edges\n const remainingNodeIds = new Set<string>(\n allDeps\n .filter(d => !orphanedNodeIds.has(d.node_id))\n .map(d => d.node_id),\n );\n\n // BFS from remaining nodes following `depends_on` edges to find all reachable transitives\n const reachableFromDirect = new Set<string>(remainingNodeIds);\n let frontier = [...remainingNodeIds];\n\n while (frontier.length > 0) {\n const placeholders = frontier.map(() => '?').join(',');\n const nextRows: Array<{ target: string }> = rawDb.all(\n `SELECT DISTINCT target FROM edges WHERE source IN (${placeholders}) AND kind = 'depends_on'`,\n frontier,\n );\n\n frontier = [];\n for (const row of nextRows) {\n if (!reachableFromDirect.has(row.target)) {\n reachableFromDirect.add(row.target);\n frontier.push(row.target);\n }\n }\n }\n\n // Any dependency node that is NOT reachable from a remaining direct dependency is also orphaned\n for (const dep of allDeps) {\n if (!orphanedNodeIds.has(dep.node_id) && !reachableFromDirect.has(dep.node_id)) {\n orphanedNodeIds.add(dep.node_id);\n }\n }\n\n if (orphanedNodeIds.size === 0) {\n return { nodesRemoved: 0, edgesRemoved: 0 };\n }\n\n // Step 4: Remove orphaned nodes and their edges\n const orphanedIds = [...orphanedNodeIds];\n\n for (const nodeId of orphanedIds) {\n // Count edges being removed\n const edgeCount = rawDb.get(\n `SELECT COUNT(*) as c FROM edges\n WHERE source = ? OR target = ?`,\n [nodeId, nodeId],\n );\n edgesRemoved += edgeCount?.c ?? 0;\n\n // Delete edges connected to this node\n rawDb.run('DELETE FROM edges WHERE source = ? OR target = ?', [nodeId, nodeId]);\n\n // Remove from sec_dependencies (explicit delete before nodes for clarity)\n rawDb.run('DELETE FROM sec_dependencies WHERE node_id = ?', [nodeId]);\n\n // Remove from nodes table\n rawDb.run('DELETE FROM nodes WHERE id = ?', [nodeId]);\n\n // Clean up FTS entries\n rawDb.run('DELETE FROM nodes_fts WHERE id = ?', [nodeId]);\n\n nodesRemoved++;\n }\n\n return { nodesRemoved, edgesRemoved };\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }