@lzehrung/codegraph 2.1.0 → 2.1.2

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 (536) hide show
  1. package/README.md +27 -29
  2. package/codegraph-skill/codegraph/SKILL.md +27 -26
  3. package/dist/agent/artifact.d.ts.map +1 -1
  4. package/dist/agent/artifact.js +105 -14
  5. package/dist/agent/artifact.js.map +1 -1
  6. package/dist/agent/candidateTests.d.ts +12 -0
  7. package/dist/agent/candidateTests.d.ts.map +1 -0
  8. package/dist/agent/candidateTests.js +17 -0
  9. package/dist/agent/candidateTests.js.map +1 -0
  10. package/dist/agent/explain.d.ts +3 -0
  11. package/dist/agent/explain.d.ts.map +1 -1
  12. package/dist/agent/explain.js +8 -0
  13. package/dist/agent/explain.js.map +1 -1
  14. package/dist/agent/explore.d.ts.map +1 -1
  15. package/dist/agent/explore.js +11 -6
  16. package/dist/agent/explore.js.map +1 -1
  17. package/dist/agent/fileView.d.ts.map +1 -1
  18. package/dist/agent/fileView.js +113 -120
  19. package/dist/agent/fileView.js.map +1 -1
  20. package/dist/agent/orient.d.ts.map +1 -1
  21. package/dist/agent/orient.js +7 -4
  22. package/dist/agent/orient.js.map +1 -1
  23. package/dist/agent/packet.d.ts.map +1 -1
  24. package/dist/agent/packet.js +5 -12
  25. package/dist/agent/packet.js.map +1 -1
  26. package/dist/agent/query-index/candidates.d.ts +13 -2
  27. package/dist/agent/query-index/candidates.d.ts.map +1 -1
  28. package/dist/agent/query-index/candidates.js +28 -39
  29. package/dist/agent/query-index/candidates.js.map +1 -1
  30. package/dist/agent/query-index/content.d.ts +1 -1
  31. package/dist/agent/query-index/content.js +4 -4
  32. package/dist/agent/query-index/content.js.map +1 -1
  33. package/dist/agent/query-index/schema.d.ts.map +1 -1
  34. package/dist/agent/query-index/schema.js.map +1 -1
  35. package/dist/agent/query-index/sessionStore.d.ts.map +1 -1
  36. package/dist/agent/query-index/sessionStore.js +42 -26
  37. package/dist/agent/query-index/sessionStore.js.map +1 -1
  38. package/dist/agent/query-index/store.d.ts +10 -4
  39. package/dist/agent/query-index/store.d.ts.map +1 -1
  40. package/dist/agent/query-index/store.js +115 -10
  41. package/dist/agent/query-index/store.js.map +1 -1
  42. package/dist/agent/query-index/update.d.ts.map +1 -1
  43. package/dist/agent/query-index/update.js +24 -9
  44. package/dist/agent/query-index/update.js.map +1 -1
  45. package/dist/agent/refactorPlan.d.ts.map +1 -1
  46. package/dist/agent/refactorPlan.js +6 -14
  47. package/dist/agent/refactorPlan.js.map +1 -1
  48. package/dist/agent/renamePreview.d.ts +2 -5
  49. package/dist/agent/renamePreview.d.ts.map +1 -1
  50. package/dist/agent/renamePreview.js +133 -80
  51. package/dist/agent/renamePreview.js.map +1 -1
  52. package/dist/agent/search.d.ts +3 -1
  53. package/dist/agent/search.d.ts.map +1 -1
  54. package/dist/agent/search.js +103 -35
  55. package/dist/agent/search.js.map +1 -1
  56. package/dist/agent/semanticSymbols.d.ts.map +1 -1
  57. package/dist/agent/semanticSymbols.js +2 -1
  58. package/dist/agent/semanticSymbols.js.map +1 -1
  59. package/dist/agent/session.d.ts +4 -0
  60. package/dist/agent/session.d.ts.map +1 -1
  61. package/dist/agent/session.js +20 -7
  62. package/dist/agent/session.js.map +1 -1
  63. package/dist/agent-tools.d.ts +1 -1
  64. package/dist/agent-tools.d.ts.map +1 -1
  65. package/dist/agent-tools.js +12 -21
  66. package/dist/agent-tools.js.map +1 -1
  67. package/dist/bin/cli.js +29242 -25373
  68. package/dist/bin/queryIndexWorker.js +131 -42
  69. package/dist/bin/rawQueryWorker.js +270 -0
  70. package/dist/chunking/chunkFile.d.ts +5 -0
  71. package/dist/chunking/chunkFile.d.ts.map +1 -1
  72. package/dist/chunking/chunkFile.js +14 -15
  73. package/dist/chunking/chunkFile.js.map +1 -1
  74. package/dist/cli/affected.d.ts.map +1 -1
  75. package/dist/cli/affected.js +17 -10
  76. package/dist/cli/affected.js.map +1 -1
  77. package/dist/cli/callHierarchy.d.ts.map +1 -1
  78. package/dist/cli/callHierarchy.js +9 -2
  79. package/dist/cli/callHierarchy.js.map +1 -1
  80. package/dist/cli/commandTable.d.ts.map +1 -1
  81. package/dist/cli/commandTable.js +16 -4
  82. package/dist/cli/commandTable.js.map +1 -1
  83. package/dist/cli/doctor.d.ts +7 -0
  84. package/dist/cli/doctor.d.ts.map +1 -1
  85. package/dist/cli/doctor.js +166 -0
  86. package/dist/cli/doctor.js.map +1 -1
  87. package/dist/cli/graph.d.ts +2 -1
  88. package/dist/cli/graph.d.ts.map +1 -1
  89. package/dist/cli/graph.js +60 -16
  90. package/dist/cli/graph.js.map +1 -1
  91. package/dist/cli/graphDelta.d.ts +2 -1
  92. package/dist/cli/graphDelta.d.ts.map +1 -1
  93. package/dist/cli/graphDelta.js +5 -0
  94. package/dist/cli/graphDelta.js.map +1 -1
  95. package/dist/cli/grep.d.ts +1 -1
  96. package/dist/cli/grep.d.ts.map +1 -1
  97. package/dist/cli/grep.js +14 -4
  98. package/dist/cli/grep.js.map +1 -1
  99. package/dist/cli/help.d.ts +34 -34
  100. package/dist/cli/help.d.ts.map +1 -1
  101. package/dist/cli/help.js +17 -8
  102. package/dist/cli/help.js.map +1 -1
  103. package/dist/cli/impact.d.ts +2 -1
  104. package/dist/cli/impact.d.ts.map +1 -1
  105. package/dist/cli/impact.js +5 -0
  106. package/dist/cli/impact.js.map +1 -1
  107. package/dist/cli/index.d.ts +2 -1
  108. package/dist/cli/index.d.ts.map +1 -1
  109. package/dist/cli/index.js +3 -0
  110. package/dist/cli/index.js.map +1 -1
  111. package/dist/cli/indexPolicy.d.ts.map +1 -1
  112. package/dist/cli/indexPolicy.js.map +1 -1
  113. package/dist/cli/inspect.d.ts +2 -1
  114. package/dist/cli/inspect.d.ts.map +1 -1
  115. package/dist/cli/inspect.js +25 -13
  116. package/dist/cli/inspect.js.map +1 -1
  117. package/dist/cli/install.js +1 -1
  118. package/dist/cli/install.js.map +1 -1
  119. package/dist/cli/invocationContext.d.ts.map +1 -1
  120. package/dist/cli/invocationContext.js +3 -0
  121. package/dist/cli/invocationContext.js.map +1 -1
  122. package/dist/cli/links.d.ts +2 -0
  123. package/dist/cli/links.d.ts.map +1 -1
  124. package/dist/cli/links.js +1 -1
  125. package/dist/cli/links.js.map +1 -1
  126. package/dist/cli/navigation.d.ts +41 -1
  127. package/dist/cli/navigation.d.ts.map +1 -1
  128. package/dist/cli/navigation.js +4 -1
  129. package/dist/cli/navigation.js.map +1 -1
  130. package/dist/cli/options.d.ts.map +1 -1
  131. package/dist/cli/options.js +32 -11
  132. package/dist/cli/options.js.map +1 -1
  133. package/dist/cli/renamePreview.d.ts.map +1 -1
  134. package/dist/cli/renamePreview.js +7 -1
  135. package/dist/cli/renamePreview.js.map +1 -1
  136. package/dist/cli/review.d.ts +2 -1
  137. package/dist/cli/review.d.ts.map +1 -1
  138. package/dist/cli/review.js +5 -0
  139. package/dist/cli/review.js.map +1 -1
  140. package/dist/cli/rootPolicy.d.ts.map +1 -1
  141. package/dist/cli/rootPolicy.js +36 -3
  142. package/dist/cli/rootPolicy.js.map +1 -1
  143. package/dist/cli/skill.js +2 -2
  144. package/dist/cli/skill.js.map +1 -1
  145. package/dist/cli/sql.js +1 -1
  146. package/dist/cli/symbols.d.ts.map +1 -1
  147. package/dist/cli/symbols.js +4 -2
  148. package/dist/cli/symbols.js.map +1 -1
  149. package/dist/cli/viewer.d.ts.map +1 -1
  150. package/dist/cli/viewer.js +46 -34
  151. package/dist/cli/viewer.js.map +1 -1
  152. package/dist/cli.d.ts.map +1 -1
  153. package/dist/cli.js +36 -16
  154. package/dist/cli.js.map +1 -1
  155. package/dist/config.d.ts +3 -0
  156. package/dist/config.d.ts.map +1 -1
  157. package/dist/config.js +35 -3
  158. package/dist/config.js.map +1 -1
  159. package/dist/documentLinks/check.d.ts +2 -1
  160. package/dist/documentLinks/check.d.ts.map +1 -1
  161. package/dist/documentLinks/check.js +22 -11
  162. package/dist/documentLinks/check.js.map +1 -1
  163. package/dist/duplicate-token-normalization.d.ts.map +1 -1
  164. package/dist/duplicate-token-normalization.js +10 -2
  165. package/dist/duplicate-token-normalization.js.map +1 -1
  166. package/dist/duplicates/scoring.d.ts +0 -10
  167. package/dist/duplicates/scoring.d.ts.map +1 -1
  168. package/dist/duplicates/scoring.js +9 -9
  169. package/dist/duplicates/scoring.js.map +1 -1
  170. package/dist/duplicates/types.d.ts +2 -0
  171. package/dist/duplicates/types.d.ts.map +1 -1
  172. package/dist/duplicates/unitCache.d.ts +15 -9
  173. package/dist/duplicates/unitCache.d.ts.map +1 -1
  174. package/dist/duplicates/unitCache.js +184 -33
  175. package/dist/duplicates/unitCache.js.map +1 -1
  176. package/dist/duplicates/units.d.ts +6 -15
  177. package/dist/duplicates/units.d.ts.map +1 -1
  178. package/dist/duplicates/units.js +42 -20
  179. package/dist/duplicates/units.js.map +1 -1
  180. package/dist/duplicates.d.ts.map +1 -1
  181. package/dist/duplicates.js +59 -0
  182. package/dist/duplicates.js.map +1 -1
  183. package/dist/frameworks/angularjs.d.ts.map +1 -1
  184. package/dist/frameworks/angularjs.js +18 -12
  185. package/dist/frameworks/angularjs.js.map +1 -1
  186. package/dist/graph-builder.d.ts.map +1 -1
  187. package/dist/graph-builder.js +12 -9
  188. package/dist/graph-builder.js.map +1 -1
  189. package/dist/graph-edge-collector.d.ts +1 -0
  190. package/dist/graph-edge-collector.d.ts.map +1 -1
  191. package/dist/graph-edge-collector.js +1 -1
  192. package/dist/graph-edge-collector.js.map +1 -1
  193. package/dist/graphs/grep.d.ts.map +1 -1
  194. package/dist/graphs/grep.js +7 -2
  195. package/dist/graphs/grep.js.map +1 -1
  196. package/dist/graphs/specifiers.d.ts.map +1 -1
  197. package/dist/graphs/specifiers.js +8 -2
  198. package/dist/graphs/specifiers.js.map +1 -1
  199. package/dist/graphs/symbol-graph-detailed.d.ts +10 -1
  200. package/dist/graphs/symbol-graph-detailed.d.ts.map +1 -1
  201. package/dist/graphs/symbol-graph-detailed.js +21 -5
  202. package/dist/graphs/symbol-graph-detailed.js.map +1 -1
  203. package/dist/impact/analyzer.d.ts.map +1 -1
  204. package/dist/impact/analyzer.js +19 -2
  205. package/dist/impact/analyzer.js.map +1 -1
  206. package/dist/impact/budgets.d.ts.map +1 -1
  207. package/dist/impact/budgets.js +5 -3
  208. package/dist/impact/budgets.js.map +1 -1
  209. package/dist/impact/call-compatibility/textScanner.d.ts +23 -0
  210. package/dist/impact/call-compatibility/textScanner.d.ts.map +1 -0
  211. package/dist/impact/call-compatibility/textScanner.js +615 -0
  212. package/dist/impact/call-compatibility/textScanner.js.map +1 -0
  213. package/dist/impact/callCompatibility.d.ts +8 -1
  214. package/dist/impact/callCompatibility.d.ts.map +1 -1
  215. package/dist/impact/callCompatibility.js +64 -587
  216. package/dist/impact/callCompatibility.js.map +1 -1
  217. package/dist/impact/context.d.ts.map +1 -1
  218. package/dist/impact/context.js +4 -1
  219. package/dist/impact/context.js.map +1 -1
  220. package/dist/impact/direct.d.ts +1 -1
  221. package/dist/impact/direct.d.ts.map +1 -1
  222. package/dist/impact/direct.js +7 -6
  223. package/dist/impact/direct.js.map +1 -1
  224. package/dist/impact/index.d.ts +6 -0
  225. package/dist/impact/index.d.ts.map +1 -1
  226. package/dist/impact/index.js +0 -8
  227. package/dist/impact/index.js.map +1 -1
  228. package/dist/impact/map.js +2 -2
  229. package/dist/impact/map.js.map +1 -1
  230. package/dist/impact/memberResolutionCoverage.d.ts.map +1 -1
  231. package/dist/impact/memberResolutionCoverage.js +5 -1
  232. package/dist/impact/memberResolutionCoverage.js.map +1 -1
  233. package/dist/impact/parse.d.ts.map +1 -1
  234. package/dist/impact/parse.js +108 -37
  235. package/dist/impact/parse.js.map +1 -1
  236. package/dist/impact/referenceCache.js +1 -1
  237. package/dist/impact/referenceCache.js.map +1 -1
  238. package/dist/impact/report-suggestions.d.ts.map +1 -1
  239. package/dist/impact/report-suggestions.js +347 -72
  240. package/dist/impact/report-suggestions.js.map +1 -1
  241. package/dist/impact/report.d.ts.map +1 -1
  242. package/dist/impact/report.js +13 -2
  243. package/dist/impact/report.js.map +1 -1
  244. package/dist/impact/reportCompact.d.ts.map +1 -1
  245. package/dist/impact/reportCompact.js +8 -0
  246. package/dist/impact/reportCompact.js.map +1 -1
  247. package/dist/impact/reportFull.d.ts.map +1 -1
  248. package/dist/impact/reportFull.js +1 -0
  249. package/dist/impact/reportFull.js.map +1 -1
  250. package/dist/impact/reportParts.d.ts +9 -0
  251. package/dist/impact/reportParts.d.ts.map +1 -1
  252. package/dist/impact/severity.d.ts +3 -2
  253. package/dist/impact/severity.d.ts.map +1 -1
  254. package/dist/impact/severity.js +16 -5
  255. package/dist/impact/severity.js.map +1 -1
  256. package/dist/impact/streaming.d.ts +32 -2
  257. package/dist/impact/streaming.d.ts.map +1 -1
  258. package/dist/impact/streaming.js +62 -3
  259. package/dist/impact/streaming.js.map +1 -1
  260. package/dist/impact/suggestions.d.ts.map +1 -1
  261. package/dist/impact/suggestions.js +1 -1
  262. package/dist/impact/suggestions.js.map +1 -1
  263. package/dist/impact/transitive.d.ts.map +1 -1
  264. package/dist/impact/transitive.js +13 -5
  265. package/dist/impact/transitive.js.map +1 -1
  266. package/dist/impact/types.d.ts +21 -20
  267. package/dist/impact/types.d.ts.map +1 -1
  268. package/dist/impact/types.js.map +1 -1
  269. package/dist/index.d.ts +2 -2
  270. package/dist/index.d.ts.map +1 -1
  271. package/dist/index.js +1 -1
  272. package/dist/index.js.map +1 -1
  273. package/dist/indexer/build-cache/location.d.ts +19 -0
  274. package/dist/indexer/build-cache/location.d.ts.map +1 -0
  275. package/dist/indexer/build-cache/location.js +132 -0
  276. package/dist/indexer/build-cache/location.js.map +1 -0
  277. package/dist/indexer/build-cache/manifest.d.ts +14 -6
  278. package/dist/indexer/build-cache/manifest.d.ts.map +1 -1
  279. package/dist/indexer/build-cache/manifest.js +194 -30
  280. package/dist/indexer/build-cache/manifest.js.map +1 -1
  281. package/dist/indexer/build-cache/module-cache.d.ts +24 -2
  282. package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
  283. package/dist/indexer/build-cache/module-cache.js +98 -32
  284. package/dist/indexer/build-cache/module-cache.js.map +1 -1
  285. package/dist/indexer/build-cache/options.d.ts +3 -1
  286. package/dist/indexer/build-cache/options.d.ts.map +1 -1
  287. package/dist/indexer/build-cache/options.js +10 -2
  288. package/dist/indexer/build-cache/options.js.map +1 -1
  289. package/dist/indexer/build-cache/project-snapshot.d.ts +33 -13
  290. package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
  291. package/dist/indexer/build-cache/project-snapshot.js +472 -91
  292. package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
  293. package/dist/indexer/build-cache/reports.d.ts.map +1 -1
  294. package/dist/indexer/build-cache/reports.js +10 -1
  295. package/dist/indexer/build-cache/reports.js.map +1 -1
  296. package/dist/indexer/build-cache/resolver-environment.d.ts +9 -0
  297. package/dist/indexer/build-cache/resolver-environment.d.ts.map +1 -0
  298. package/dist/indexer/build-cache/resolver-environment.js +160 -0
  299. package/dist/indexer/build-cache/resolver-environment.js.map +1 -0
  300. package/dist/indexer/build-cache.d.ts +4 -3
  301. package/dist/indexer/build-cache.d.ts.map +1 -1
  302. package/dist/indexer/build-cache.js +4 -3
  303. package/dist/indexer/build-cache.js.map +1 -1
  304. package/dist/indexer/build-index.d.ts.map +1 -1
  305. package/dist/indexer/build-index.js +268 -96
  306. package/dist/indexer/build-index.js.map +1 -1
  307. package/dist/indexer/build-manifest.d.ts +1 -0
  308. package/dist/indexer/build-manifest.d.ts.map +1 -1
  309. package/dist/indexer/build-manifest.js +15 -5
  310. package/dist/indexer/build-manifest.js.map +1 -1
  311. package/dist/indexer/build-workers.d.ts +1 -1
  312. package/dist/indexer/build-workers.d.ts.map +1 -1
  313. package/dist/indexer/build-workers.js +57 -42
  314. package/dist/indexer/build-workers.js.map +1 -1
  315. package/dist/indexer/call-hierarchy.d.ts.map +1 -1
  316. package/dist/indexer/call-hierarchy.js.map +1 -1
  317. package/dist/indexer/finalize.d.ts.map +1 -1
  318. package/dist/indexer/finalize.js +7 -4
  319. package/dist/indexer/finalize.js.map +1 -1
  320. package/dist/indexer/import-types.d.ts +8 -0
  321. package/dist/indexer/import-types.d.ts.map +1 -1
  322. package/dist/indexer/imports/jsTextImports.d.ts.map +1 -1
  323. package/dist/indexer/imports/jsTextImports.js +14 -6
  324. package/dist/indexer/imports/jsTextImports.js.map +1 -1
  325. package/dist/indexer/imports/languageSpecific.d.ts.map +1 -1
  326. package/dist/indexer/imports/languageSpecific.js +10 -5
  327. package/dist/indexer/imports/languageSpecific.js.map +1 -1
  328. package/dist/indexer/imports/nativeCaptures.d.ts.map +1 -1
  329. package/dist/indexer/imports/nativeCaptures.js +4 -1
  330. package/dist/indexer/imports/nativeCaptures.js.map +1 -1
  331. package/dist/indexer/imports/python.d.ts.map +1 -1
  332. package/dist/indexer/imports/python.js +19 -9
  333. package/dist/indexer/imports/python.js.map +1 -1
  334. package/dist/indexer/incremental-plan.d.ts +2 -1
  335. package/dist/indexer/incremental-plan.d.ts.map +1 -1
  336. package/dist/indexer/incremental-plan.js +7 -4
  337. package/dist/indexer/incremental-plan.js.map +1 -1
  338. package/dist/indexer/load-current-index.d.ts.map +1 -1
  339. package/dist/indexer/load-current-index.js.map +1 -1
  340. package/dist/indexer/locals-and-exports.d.ts.map +1 -1
  341. package/dist/indexer/locals-and-exports.js +77 -22
  342. package/dist/indexer/locals-and-exports.js.map +1 -1
  343. package/dist/indexer/navigation-goto.d.ts.map +1 -1
  344. package/dist/indexer/navigation-goto.js +26 -16
  345. package/dist/indexer/navigation-goto.js.map +1 -1
  346. package/dist/indexer/navigation-local.d.ts.map +1 -1
  347. package/dist/indexer/navigation-local.js +7 -4
  348. package/dist/indexer/navigation-local.js.map +1 -1
  349. package/dist/indexer/navigation-references.d.ts +1 -1
  350. package/dist/indexer/navigation-references.d.ts.map +1 -1
  351. package/dist/indexer/navigation-references.js +34 -17
  352. package/dist/indexer/navigation-references.js.map +1 -1
  353. package/dist/indexer/navigation-resolve.d.ts.map +1 -1
  354. package/dist/indexer/navigation-resolve.js +116 -53
  355. package/dist/indexer/navigation-resolve.js.map +1 -1
  356. package/dist/indexer/navigation.d.ts +2 -1
  357. package/dist/indexer/navigation.d.ts.map +1 -1
  358. package/dist/indexer/navigation.js +34 -20
  359. package/dist/indexer/navigation.js.map +1 -1
  360. package/dist/indexer/parse-context.d.ts +2 -2
  361. package/dist/indexer/parse-context.d.ts.map +1 -1
  362. package/dist/indexer/parse-context.js +25 -4
  363. package/dist/indexer/parse-context.js.map +1 -1
  364. package/dist/indexer/reference-context.d.ts +2 -2
  365. package/dist/indexer/reference-context.d.ts.map +1 -1
  366. package/dist/indexer/reference-context.js +4 -2
  367. package/dist/indexer/reference-context.js.map +1 -1
  368. package/dist/indexer/scope-types.d.ts +3 -0
  369. package/dist/indexer/scope-types.d.ts.map +1 -1
  370. package/dist/indexer/scope.js +37 -38
  371. package/dist/indexer/scope.js.map +1 -1
  372. package/dist/indexer/shared.d.ts.map +1 -1
  373. package/dist/indexer/shared.js +3 -1
  374. package/dist/indexer/shared.js.map +1 -1
  375. package/dist/indexer/type-hierarchy.d.ts.map +1 -1
  376. package/dist/indexer/type-hierarchy.js +12 -8
  377. package/dist/indexer/type-hierarchy.js.map +1 -1
  378. package/dist/indexer/types.d.ts +27 -1
  379. package/dist/indexer/types.d.ts.map +1 -1
  380. package/dist/indexer/workspace-symbols.d.ts.map +1 -1
  381. package/dist/indexer/workspace-symbols.js +5 -3
  382. package/dist/indexer/workspace-symbols.js.map +1 -1
  383. package/dist/installer/locks.d.ts +10 -0
  384. package/dist/installer/locks.d.ts.map +1 -0
  385. package/dist/installer/locks.js +232 -0
  386. package/dist/installer/locks.js.map +1 -0
  387. package/dist/installer/registry.d.ts.map +1 -1
  388. package/dist/installer/registry.js +75 -235
  389. package/dist/installer/registry.js.map +1 -1
  390. package/dist/languages/definitions/csharp.d.ts.map +1 -1
  391. package/dist/languages/definitions/csharp.js +8 -0
  392. package/dist/languages/definitions/csharp.js.map +1 -1
  393. package/dist/languages/definitions/java.d.ts.map +1 -1
  394. package/dist/languages/definitions/java.js +3 -0
  395. package/dist/languages/definitions/java.js.map +1 -1
  396. package/dist/languages/definitions/python.d.ts.map +1 -1
  397. package/dist/languages/definitions/python.js +2 -0
  398. package/dist/languages/definitions/python.js.map +1 -1
  399. package/dist/languages/definitions/rust.d.ts.map +1 -1
  400. package/dist/languages/definitions/rust.js +2 -0
  401. package/dist/languages/definitions/rust.js.map +1 -1
  402. package/dist/languages/importStatementParsers.d.ts +2 -0
  403. package/dist/languages/importStatementParsers.d.ts.map +1 -1
  404. package/dist/languages/importStatementParsers.js +24 -10
  405. package/dist/languages/importStatementParsers.js.map +1 -1
  406. package/dist/mcp/http.d.ts +3 -1
  407. package/dist/mcp/http.d.ts.map +1 -1
  408. package/dist/mcp/http.js +69 -20
  409. package/dist/mcp/http.js.map +1 -1
  410. package/dist/mcp/server.d.ts +58 -16
  411. package/dist/mcp/server.d.ts.map +1 -1
  412. package/dist/mcp/server.js +447 -140
  413. package/dist/mcp/server.js.map +1 -1
  414. package/dist/mcp/tools.d.ts +51 -1
  415. package/dist/mcp/tools.d.ts.map +1 -1
  416. package/dist/mcp/tools.js +129 -3
  417. package/dist/mcp/tools.js.map +1 -1
  418. package/dist/native/byteIndex.d.ts +26 -0
  419. package/dist/native/byteIndex.d.ts.map +1 -0
  420. package/dist/native/byteIndex.js +70 -0
  421. package/dist/native/byteIndex.js.map +1 -0
  422. package/dist/native/projectedTree.d.ts +3 -2
  423. package/dist/native/projectedTree.d.ts.map +1 -1
  424. package/dist/native/projectedTree.js +6 -50
  425. package/dist/native/projectedTree.js.map +1 -1
  426. package/dist/native/queryResults.d.ts +7 -1
  427. package/dist/native/queryResults.d.ts.map +1 -1
  428. package/dist/native/queryResults.js +13 -5
  429. package/dist/native/queryResults.js.map +1 -1
  430. package/dist/review/candidates.d.ts.map +1 -1
  431. package/dist/review/candidates.js +4 -1
  432. package/dist/review/candidates.js.map +1 -1
  433. package/dist/review/changes.d.ts +2 -0
  434. package/dist/review/changes.d.ts.map +1 -1
  435. package/dist/review/changes.js +10 -0
  436. package/dist/review/changes.js.map +1 -1
  437. package/dist/review/deleted.d.ts.map +1 -1
  438. package/dist/review/deleted.js +20 -2
  439. package/dist/review/deleted.js.map +1 -1
  440. package/dist/review/summaries.d.ts +5 -0
  441. package/dist/review/summaries.d.ts.map +1 -1
  442. package/dist/review/summaries.js +32 -21
  443. package/dist/review/summaries.js.map +1 -1
  444. package/dist/review/types.d.ts +3 -1
  445. package/dist/review/types.d.ts.map +1 -1
  446. package/dist/review/types.js +8 -1
  447. package/dist/review/types.js.map +1 -1
  448. package/dist/review.d.ts.map +1 -1
  449. package/dist/review.js +14 -5
  450. package/dist/review.js.map +1 -1
  451. package/dist/session.d.ts +20 -4
  452. package/dist/session.d.ts.map +1 -1
  453. package/dist/session.js +76 -16
  454. package/dist/session.js.map +1 -1
  455. package/dist/sql/types.d.ts.map +1 -1
  456. package/dist/sqlite/query.d.ts +29 -0
  457. package/dist/sqlite/query.d.ts.map +1 -1
  458. package/dist/sqlite/query.js +98 -11
  459. package/dist/sqlite/query.js.map +1 -1
  460. package/dist/sqlite/rawQueryWorker.d.ts +22 -0
  461. package/dist/sqlite/rawQueryWorker.d.ts.map +1 -0
  462. package/dist/sqlite/rawQueryWorker.js +31 -0
  463. package/dist/sqlite/rawQueryWorker.js.map +1 -0
  464. package/dist/sqlite/rawQueryWorkerPool.d.ts +66 -0
  465. package/dist/sqlite/rawQueryWorkerPool.d.ts.map +1 -0
  466. package/dist/sqlite/rawQueryWorkerPool.js +142 -0
  467. package/dist/sqlite/rawQueryWorkerPool.js.map +1 -0
  468. package/dist/sqlite/schema.d.ts +2 -1
  469. package/dist/sqlite/schema.d.ts.map +1 -1
  470. package/dist/sqlite/schema.js +15 -1
  471. package/dist/sqlite/schema.js.map +1 -1
  472. package/dist/sqlite/write.d.ts.map +1 -1
  473. package/dist/sqlite/write.js +15 -0
  474. package/dist/sqlite/write.js.map +1 -1
  475. package/dist/sqlite-driver.d.ts +11 -0
  476. package/dist/sqlite-driver.d.ts.map +1 -1
  477. package/dist/sqlite-driver.js +28 -2
  478. package/dist/sqlite-driver.js.map +1 -1
  479. package/dist/sqlite.d.ts +1 -1
  480. package/dist/sqlite.d.ts.map +1 -1
  481. package/dist/sqlite.js +1 -1
  482. package/dist/sqlite.js.map +1 -1
  483. package/dist/util/bloomFilter.d.ts +3 -2
  484. package/dist/util/bloomFilter.d.ts.map +1 -1
  485. package/dist/util/bloomFilter.js +8 -8
  486. package/dist/util/bloomFilter.js.map +1 -1
  487. package/dist/util/concurrency.d.ts +1 -0
  488. package/dist/util/concurrency.d.ts.map +1 -1
  489. package/dist/util/concurrency.js +9 -2
  490. package/dist/util/concurrency.js.map +1 -1
  491. package/dist/util/confinedFile.d.ts +42 -2
  492. package/dist/util/confinedFile.d.ts.map +1 -1
  493. package/dist/util/confinedFile.js +114 -3
  494. package/dist/util/confinedFile.js.map +1 -1
  495. package/dist/util/errors.d.ts +2 -0
  496. package/dist/util/errors.d.ts.map +1 -1
  497. package/dist/util/errors.js +18 -0
  498. package/dist/util/errors.js.map +1 -1
  499. package/dist/util/git.d.ts +2 -0
  500. package/dist/util/git.d.ts.map +1 -1
  501. package/dist/util/git.js +174 -26
  502. package/dist/util/git.js.map +1 -1
  503. package/dist/util/identifiers.d.ts +75 -0
  504. package/dist/util/identifiers.d.ts.map +1 -0
  505. package/dist/util/identifiers.js +82 -0
  506. package/dist/util/identifiers.js.map +1 -0
  507. package/dist/util/paths.d.ts.map +1 -1
  508. package/dist/util/paths.js +45 -9
  509. package/dist/util/paths.js.map +1 -1
  510. package/dist/util/projectFiles.d.ts.map +1 -1
  511. package/dist/util/projectFiles.js +43 -14
  512. package/dist/util/projectFiles.js.map +1 -1
  513. package/dist/util/resolution/jvm.d.ts.map +1 -1
  514. package/dist/util/resolution/jvm.js +20 -9
  515. package/dist/util/resolution/jvm.js.map +1 -1
  516. package/dist/util/resolution/php.d.ts.map +1 -1
  517. package/dist/util/resolution/php.js +6 -5
  518. package/dist/util/resolution/php.js.map +1 -1
  519. package/dist/util/resolution/tsconfig.d.ts.map +1 -1
  520. package/dist/util/resolution/tsconfig.js +26 -12
  521. package/dist/util/resolution/tsconfig.js.map +1 -1
  522. package/dist/util/rustTestModules.d.ts.map +1 -1
  523. package/dist/util/rustTestModules.js +4 -2
  524. package/dist/util/rustTestModules.js.map +1 -1
  525. package/dist/util/specifiers.d.ts.map +1 -1
  526. package/dist/util/specifiers.js +10 -3
  527. package/dist/util/specifiers.js.map +1 -1
  528. package/dist/util/sqliteSchema.d.ts.map +1 -1
  529. package/dist/util/sqliteSchema.js +10 -1
  530. package/dist/util/sqliteSchema.js.map +1 -1
  531. package/dist/worker/nativeExtractWorker.d.ts +4 -2
  532. package/dist/worker/nativeExtractWorker.d.ts.map +1 -1
  533. package/dist/worker/nativeExtractWorker.js +12 -11
  534. package/dist/worker/nativeExtractWorker.js.map +1 -1
  535. package/docs/mcp.md +35 -14
  536. package/package.json +3 -3
@@ -4,12 +4,14 @@ import fsp from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import { performance } from "node:perf_hooks";
6
6
  import { languageExtensionPatterns, supportForFile } from "../languages.js";
7
+ import { isJsTsLanguage } from "../languages/js-family.js";
7
8
  import { loadWorkspaceConfig, resolveWorkspacePackage } from "../util/workspace.js";
8
9
  import { DEFAULT_PROJECT_PATTERNS, discoverProjectFiles, listProjectFiles, } from "../util/projectFiles.js";
9
10
  import { getGitHead, isGitRepo, getGitBlobHashes, listChangedFiles } from "../util/git.js";
10
- import { clearImportResolutionCaches, resolveSpecifier } from "../util/resolution.js";
11
- import { assertFilePathWithinRoot, fileIdentityKey, initializeFileIdentityCaseSensitivity, normalizePath, } from "../util/paths.js";
11
+ import { clearResolutionCaches, resolveSpecifier } from "../util/resolution.js";
12
+ import { assertFilePathWithinRoot, fileIdentityKey, initializeFileIdentityCaseSensitivity, isFilePathWithinRoot, normalizePath, } from "../util/paths.js";
12
13
  import { mapLimit } from "../util/concurrency.js";
14
+ import { readConfinedUtf8File } from "../util/confinedFile.js";
13
15
  import { resolveWorkerThreadCount } from "../util/workerThreads.js";
14
16
  import { logWithLevel } from "../logging.js";
15
17
  import { collectGraph } from "../graph-builder.js";
@@ -26,8 +28,9 @@ import { initNativeBackendReport } from "../native/nativeBackendReport.js";
26
28
  import { closeDuplicateUnitCacheDatabase } from "../duplicates.js";
27
29
  import { isNativeRequiredUnavailableError } from "../native/treeSitterNative.js";
28
30
  import { isNodeSqliteUnavailableError } from "../sqlite-driver.js";
29
- import { buildBloomFilterForFile, cacheSignatureForFile, closeDiskCacheDatabase, collectWorkspaceManifestDependencyEdges, computeConfigHash, createFallbackImportExtractionHandler, diffBuildOptions, fileSignature, graphOptionsEqual, initFileReport, initManifestReport, loadManifest, normalizeGraphOptions, normalizeIndexedFileInputs, normalizeLanguageExtensions, projectSnapshotFilesSignature, recordConfigHashResult, recordFileFailure, sanitizeManifestEntriesForRoot, sanitizeManifestTransientFilesForRoot, tryLoadFromCache, tryLoadPersistedBloomFilters, tryLoadProjectIndexSnapshot, verifyManifestEntries, writeProjectIndexSnapshot, writeToCache, } from "./build-cache.js";
30
- import { cacheRoot } from "./build-cache/module-cache.js";
31
+ import { buildBloomFilterForFile, cacheSignatureForFile, closeDiskCacheDatabase, collectWorkspaceManifestDependencyEdges, computeConfigHash, createFallbackImportExtractionHandler, diffBuildOptions, fileSignature, fileSignatureFromSource, graphOptionsEqual, initFileReport, initManifestReport, loadManifest, normalizeGraphOptions, normalizeIndexedFileInputs, normalizeIndexedFileInputsWithinRoot, normalizeLanguageExtensions, projectSnapshotFilesSignature, recordConfigHashResult, recordFileFailure, sanitizeManifestEntriesForRoot, sanitizeManifestTransientFilesForRoot, tryLoadFromCache, tryLoadPersistedBloomFilters, tryLoadProjectIndexSnapshot, tryLoadProjectSnapshotModules, verifyManifestEntries, writeModulesToCache, writeProjectIndexSnapshot, writeToCache, } from "./build-cache.js";
32
+ import { computeResolverEnvironmentFingerprint } from "./build-cache/resolver-environment.js";
33
+ import { cacheRoot } from "./build-cache/location.js";
31
34
  import { SymbolKind, } from "./types.js";
32
35
  import { isNonNativeParserUnavailableError, isParserSyntaxTree } from "../parserBackend.js";
33
36
  import { isUnsupportedParserInputError } from "../languages/filePrep.js";
@@ -35,7 +38,7 @@ import { buildSqlFactCache, buildSqlModuleIndex, sqlCorpusSignature } from "../s
35
38
  import { finalizeProjectIndex } from "./finalize.js";
36
39
  import { toManifestFileEntry, writeIndexManifestSnapshot } from "./build-manifest.js";
37
40
  import { prepareFileContextForBuild, setupWorkerPool, teardownWorkerPool, } from "./build-workers.js";
38
- import { buildIncrementalGitDiffOptions, canUseIncrementalDiscoveryFastPath, collectDeletedTrackedFileDependents, collectTrackedFileDependents, isMissingGitRevisionError, listUntrackedProjectFiles, partitionTrackedManifestFiles, probePathExistence, } from "./incremental-plan.js";
41
+ import { buildIncrementalGitDiffOptions, canUseIncrementalDiscoveryFastPath, buildTrackedFileReverseDependencies, collectDeletedTrackedFileDependents, collectTrackedFileDependents, isMissingGitRevisionError, listUntrackedProjectFiles, partitionTrackedManifestFiles, probePathExistence, } from "./incremental-plan.js";
39
42
  import { parsedCacheMaxEntries, setParsedCacheEntry } from "./parsed-cache.js";
40
43
  function initParserBackendDegradationReport(report) {
41
44
  if (!report)
@@ -74,13 +77,17 @@ function recordParserBackendDegradation(report, entry) {
74
77
  return;
75
78
  parserReport.files.push(entry);
76
79
  }
80
+ function isConfinedFileReadError(error) {
81
+ return (error instanceof Error &&
82
+ /outside project root|possible path confinement race|changed between verification and open|confined file target/u.test(error.message));
83
+ }
77
84
  function createEmptyModuleIndex(file) {
78
85
  return { file, exports: [], imports: [], locals: [] };
79
86
  }
80
87
  async function resolveCrossModuleSymbolExports(file, mod, support, projectRoot, graphOptions, workspaceConfig, logLevel) {
81
88
  if (!support.supportsCrossModuleSymbols)
82
89
  return;
83
- if (support.id !== "ts" && support.id !== "js")
90
+ if (!isJsTsLanguage(support.id))
84
91
  return;
85
92
  const { matchPath } = await import("../util/resolution.js").then((mod) => mod.loadNearestTsconfigFor(file, projectRoot, logLevel));
86
93
  for (const entry of mod.exports) {
@@ -88,29 +95,43 @@ async function resolveCrossModuleSymbolExports(file, mod, support, projectRoot,
88
95
  continue;
89
96
  }
90
97
  if (entry.fromModule.startsWith(".")) {
98
+ entry.moduleSpecifier ??= entry.fromModule;
91
99
  const resolved = await resolveSpecifier(file, entry.fromModule, projectRoot, matchPath, workspaceConfig, {
92
100
  resolveNodeModules: !!graphOptions.resolveNodeModules,
93
101
  ...(graphOptions.resolutionHints ? { resolutionHints: graphOptions.resolutionHints } : {}),
94
102
  });
95
- if (typeof resolved === "string")
103
+ if (typeof resolved === "string" && isFilePathWithinRoot(projectRoot, resolved))
96
104
  entry.fromModule = resolved;
97
105
  continue;
98
106
  }
99
107
  const pkgResolved = await resolveWorkspacePackage(entry.fromModule, workspaceConfig);
100
- if (pkgResolved)
101
- entry.fromModule = pkgResolved;
108
+ if (pkgResolved) {
109
+ entry.moduleSpecifier ??= entry.fromModule;
110
+ if (isFilePathWithinRoot(projectRoot, pkgResolved))
111
+ entry.fromModule = pkgResolved;
112
+ }
102
113
  }
103
114
  }
104
115
  async function buildIndexedModuleForFile(args) {
105
- const prepared = await prepareFileContextForBuild(args.file, args.support, args.opts, args.workerSetup, args.report);
116
+ const prepared = await prepareFileContextForBuild(args.file, args.support, args.opts, args.workerSetup, args.report, args.confinedRoot, args.projectRoot, args.trustedSource);
106
117
  const { source, sup, nativeQueries, embeddedBlocks } = prepared;
107
118
  let resolvedLang = prepared.lang;
108
119
  let tree;
109
- const graphOnlyLanguage = isGraphOnlyLanguage(sup.id);
120
+ const graphOnlyLanguage = isGraphOnlyLanguage(sup.id), nativeSourceLimitFallback = prepared.nativeFallbackReason === "queryFailure" &&
121
+ !!prepared.nativeError?.startsWith("source exceeds native byte limit");
110
122
  if (prepared.syntaxTree) {
111
- tree = new ProjectedSyntaxTree(source, prepared.syntaxTree);
123
+ const parsedTree = new ProjectedSyntaxTree(source, prepared.syntaxTree);
124
+ tree = parsedTree;
125
+ setParsedCacheEntry(args.parsedMap, args.file, {
126
+ source,
127
+ tree: parsedTree,
128
+ sup,
129
+ ...(resolvedLang ? { lang: resolvedLang } : {}),
130
+ ...(embeddedBlocks ? { embeddedBlocks } : {}),
131
+ nativeQueries,
132
+ }, args.parsedCacheMaxEntries);
112
133
  }
113
- else if (!nativeQueries && !graphOnlyLanguage && sup.id !== "sql") {
134
+ else if (!nativeQueries && !graphOnlyLanguage && sup.id !== "sql" && !nativeSourceLimitFallback) {
114
135
  const parseAttempt = attemptParsePreparedFileContext(prepared);
115
136
  const parsed = parseAttempt.parsed;
116
137
  if (parsed) {
@@ -135,14 +156,24 @@ async function buildIndexedModuleForFile(args) {
135
156
  if (parsed) {
136
157
  tree = parsed.tree;
137
158
  resolvedLang = parsed.lang ?? resolvedLang;
159
+ setParsedCacheEntry(args.parsedMap, args.file, parsed, args.parsedCacheMaxEntries);
138
160
  }
139
161
  }
140
162
  const lacksParserContext = !nativeQueries && !tree;
141
- if (args.bloomFilterCache) {
142
- const filter = buildBloomFilterFromSource(source, sup.id);
163
+ if (args.bloomFilterCache && !nativeSourceLimitFallback) {
164
+ const filter = buildBloomFilterFromSource(source, sup);
143
165
  args.bloomFilterCache.set(args.file, filter);
144
166
  }
145
- const imports = sup.id === "sql"
167
+ // Single builder so an option added here always reaches both the primary source and
168
+ // every embedded (SFC) block, instead of one path silently missing a future option.
169
+ const sharedImportOptions = {
170
+ graphOptions: args.graphOptions,
171
+ ...(args.opts?.native ? { native: args.opts.native } : {}),
172
+ ...(args.opts?.logLevel ? { logLevel: args.opts.logLevel } : {}),
173
+ ...(args.opts?.languageExtensions ? { languageExtensions: args.opts.languageExtensions } : {}),
174
+ ...(args.onFallbackImportExtraction ? { onFallbackImportExtraction: args.onFallbackImportExtraction } : {}),
175
+ };
176
+ const imports = nativeSourceLimitFallback || sup.id === "sql"
146
177
  ? []
147
178
  : await collectImportsForFile(args.file, args.projectRoot, {
148
179
  source,
@@ -150,21 +181,13 @@ async function buildIndexedModuleForFile(args) {
150
181
  sup,
151
182
  ...(resolvedLang ? { lang: resolvedLang } : {}),
152
183
  ...(nativeQueries !== undefined ? { nativeQueries } : {}),
153
- graphOptions: args.graphOptions,
154
- ...(args.opts?.native ? { native: args.opts.native } : {}),
155
- ...(args.opts?.logLevel ? { logLevel: args.opts.logLevel } : {}),
156
- ...(args.opts?.languageExtensions ? { languageExtensions: args.opts.languageExtensions } : {}),
157
- ...(args.onFallbackImportExtraction ? { onFallbackImportExtraction: args.onFallbackImportExtraction } : {}),
184
+ ...sharedImportOptions,
158
185
  });
159
186
  for (const block of embeddedBlocks ?? []) {
160
187
  imports.push(...(await collectImportsForFile(args.file, args.projectRoot, {
161
188
  source: block.source,
162
189
  sup: block.sup,
163
- graphOptions: args.graphOptions,
164
- ...(args.opts?.native ? { native: args.opts.native } : {}),
165
- ...(args.opts?.logLevel ? { logLevel: args.opts.logLevel } : {}),
166
- ...(args.opts?.languageExtensions ? { languageExtensions: args.opts.languageExtensions } : {}),
167
- ...(args.onFallbackImportExtraction ? { onFallbackImportExtraction: args.onFallbackImportExtraction } : {}),
190
+ ...sharedImportOptions,
168
191
  })));
169
192
  }
170
193
  collectJsonDependencies(imports, args.jsonDependencies);
@@ -187,14 +210,16 @@ async function buildIndexedModuleForFile(args) {
187
210
  await resolveCrossModuleSymbolExports(args.file, mod, sup, args.projectRoot, args.graphOptions, args.workspaceConfig, args.opts?.logLevel);
188
211
  const sigInfo = args.fileSignatures.get(args.file);
189
212
  const cacheable = !prepared.nativeFallbackReason && !lacksParserContext;
213
+ let cacheWrite;
190
214
  if (sigInfo && cacheable) {
191
215
  const cacheSig = args.cacheEnabled
192
- ? await moduleCacheSignatureForFile(args.file, sigInfo, args.opts)
216
+ ? await moduleCacheSignatureForFile(args.file, sigInfo, args.opts, args.resolverEnvironmentFingerprint)
193
217
  : sigInfo.cacheSig;
194
- writeToCache(args.projectRoot, args.file, cacheSig, mod, args.opts);
218
+ cacheWrite = { file: args.file, sig: cacheSig, mod };
195
219
  }
196
220
  return {
197
221
  module: mod,
222
+ ...(cacheWrite !== undefined ? { cacheWrite } : {}),
198
223
  graphContext: {
199
224
  source,
200
225
  sup,
@@ -242,19 +267,24 @@ function graphEdgeKey(edge) {
242
267
  const target = edge.to.type === "file" ? `file:${fileIdentityKey(edge.to.path)}` : `external:${edge.to.name}`;
243
268
  return `${from}::${target}::${edge.raw ?? ""}::${edge.typeOnly ? 1 : 0}`;
244
269
  }
245
- async function moduleCacheSignatureForFile(file, sigInfo, opts) {
270
+ async function moduleCacheSignatureForFile(file, sigInfo, opts, resolverEnvironmentFingerprint) {
246
271
  const baseSignature = await cacheSignatureForFile(file, sigInfo, opts);
247
272
  const normalizedExtensions = normalizeLanguageExtensions(opts?.languageExtensions);
248
- if (!normalizedExtensions)
273
+ const resolveNodeModules = normalizeGraphOptions(opts?.graph).resolveNodeModules;
274
+ if (!normalizedExtensions && !resolveNodeModules)
249
275
  return baseSignature;
250
276
  // Combine via a hash rather than raw concatenation: the disk cache stores this string in a
251
277
  // SQLite TEXT column, and node:sqlite's DatabaseSync silently truncates TEXT bind parameters
252
278
  // at embedded NUL bytes, so a raw separator character risks the stored and freshly-computed
253
279
  // signatures never matching (permanent cache miss) if either baseSignature or the serialized
254
- // extensions ever contained one.
280
+ // extensions ever contained one. A cached ModuleIndex's ImportBinding.resolved values differ
281
+ // depending on whether resolveNodeModules was on at write time (resolved node_modules targets
282
+ // vs. external), so that state and the environment that produced it must be part of the key.
255
283
  const hash = crypto.createHash("sha1");
256
284
  hash.update(baseSignature);
257
- hash.update(JSON.stringify(Object.entries(normalizedExtensions)));
285
+ hash.update(JSON.stringify(Object.entries(normalizedExtensions ?? {})));
286
+ hash.update(resolveNodeModules ? "\0resolveNodeModules" : "");
287
+ hash.update(resolverEnvironmentFingerprint === null ? "\0resolverEnvironmentTooLarge" : (resolverEnvironmentFingerprint ?? ""));
258
288
  return hash.digest("hex");
259
289
  }
260
290
  function projectPatternsForLanguageExtensions(opts) {
@@ -325,21 +355,25 @@ function expandStarImports(modules, opts) {
325
355
  }
326
356
  }
327
357
  function toProjectIndexManifestEntry(entry) {
358
+ // A git signature alone is already a strong content identity (`fileSignature()` derives
359
+ // `cacheSig` the same way: `gitSig ?? contentHash ?? sig`), so entries sourced from the disk
360
+ // manifest (which does not persist `cacheSig`) still get one whenever `gitSig` is available.
361
+ const cacheSig = entry.cacheSig ?? entry.gitSig;
328
362
  return {
329
363
  sig: entry.sig,
330
364
  ...(entry.gitSig ? { gitSig: entry.gitSig } : {}),
365
+ ...(cacheSig ? { cacheSig } : {}),
331
366
  };
332
367
  }
333
368
  function projectIndexManifestEntries(entries) {
334
369
  return new Map(Array.from(entries, ([file, entry]) => [file, toProjectIndexManifestEntry(entry)]));
335
370
  }
336
371
  function createIndexBuildRunState(projectRoot, opts, graphOptions = normalizeGraphOptions(opts?.graph)) {
337
- const report = opts?.report;
338
- if (report)
339
- initNativeBackendReport(report);
372
+ const report = opts?.report ?? { timings: {} };
373
+ initNativeBackendReport(report);
340
374
  const cacheMode = opts?.cache ?? "off";
341
375
  return {
342
- normalizedProjectRoot: normalizePath(projectRoot),
376
+ normalizedProjectRoot: normalizePath(path.resolve(projectRoot)),
343
377
  report,
344
378
  timings: report?.timings,
345
379
  totalStart: performance.now(),
@@ -371,7 +405,14 @@ function buildConcurrency(opts) {
371
405
  async function prepareFileSignatures(args) {
372
406
  const entries = await mapLimit(args.files, args.concurrency, async (file) => {
373
407
  const gitSig = args.gitSigMap.get(file);
374
- const sigInfo = await fileSignature(file, args.opts?.cacheStrict, gitSig, {
408
+ const source = args.confinedRoot
409
+ ? await readConfinedUtf8File(args.confinedRoot, args.projectRoot, file)
410
+ : undefined;
411
+ if (source !== undefined) {
412
+ args.trustedSources?.set(file, source);
413
+ return [file, fileSignatureFromSource(source, gitSig)];
414
+ }
415
+ const sigInfo = await fileSignature(file, args.needsContentHash ? args.opts?.cacheStrict : false, gitSig, {
375
416
  forceContentHash: args.cacheEnabled && !gitSig,
376
417
  });
377
418
  return [file, sigInfo];
@@ -382,7 +423,7 @@ async function buildProjectIndexFromExport(projectRoot, opts, helperOpts) {
382
423
  return buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpts);
383
424
  }
384
425
  async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperOpts) {
385
- clearImportResolutionCaches();
426
+ clearResolutionCaches();
386
427
  await initializeFileIdentityCaseSensitivity(projectRoot);
387
428
  const { normalizedProjectRoot, report, timings, totalStart, cacheMode, cacheEnabled, graphOptions, onFallbackImportExtraction, } = createIndexBuildRunState(projectRoot, opts);
388
429
  const manifestMode = helperOpts?.manifestMode ?? "off";
@@ -390,7 +431,11 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
390
431
  const shouldWriteManifest = manifestMode === "read-write";
391
432
  const projectFiles = helperOpts?.projectFiles;
392
433
  initManifestReport(report, useManifest, false);
393
- const normalizedFiles = Array.from(new Set(normalizeIndexedFileInputs(projectRoot, rawFiles ?? [], "Index file")));
434
+ const confinedRoot = helperOpts?.confineReads ? await fsp.realpath(projectRoot) : undefined;
435
+ const [trustedSources, normalizedFiles] = [
436
+ confinedRoot ? new Map() : undefined,
437
+ Array.from(new Set(normalizeIndexedFileInputs(projectRoot, rawFiles ?? [], "Index file"))),
438
+ ];
394
439
  if (!normalizedFiles.length && helperOpts?.warnNoFilesMessage) {
395
440
  logWithLevel(opts?.logLevel, "warn", helperOpts.warnNoFilesMessage);
396
441
  }
@@ -398,11 +443,21 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
398
443
  if (fileReport)
399
444
  fileReport.total = normalizedFiles.length;
400
445
  const manifestStart = performance.now();
401
- const manifest = useManifest && !helperOpts?.ignoreExistingManifest ? await loadManifest(projectRoot, opts) : null;
446
+ const manifest = useManifest && !helperOpts?.ignoreExistingManifest ? await loadManifest(projectRoot, opts, report) : null;
402
447
  const manifestFiles = sanitizeManifestEntriesForRoot(projectRoot, manifest?.files);
403
448
  const manifestOptionDiffs = manifest ? diffBuildOptions(manifest.buildOptions, opts) : [];
404
449
  const languageExtensionsChanged = manifestOptionDiffs.includes("languageExtensions");
405
450
  const implementationChanged = manifestOptionDiffs.includes("implementation");
451
+ let resolverEnvironmentFingerprint;
452
+ let resolverEnvironmentMatchesManifest = true;
453
+ if (cacheEnabled && graphOptions.resolveNodeModules) {
454
+ resolverEnvironmentFingerprint = await computeResolverEnvironmentFingerprint(projectRoot, normalizedFiles);
455
+ if (useManifest) {
456
+ resolverEnvironmentMatchesManifest =
457
+ resolverEnvironmentFingerprint !== null &&
458
+ manifest?.resolverEnvironmentFingerprint === resolverEnvironmentFingerprint;
459
+ }
460
+ }
406
461
  if (timings && useManifest) {
407
462
  timings.manifestMs = Math.round(performance.now() - manifestStart);
408
463
  }
@@ -426,13 +481,14 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
426
481
  const cachedGraphEntries = manifest &&
427
482
  !languageExtensionsChanged &&
428
483
  !implementationChanged &&
484
+ resolverEnvironmentMatchesManifest &&
429
485
  graphOptionsEqual(manifest.graphOptions, graphOptions)
430
486
  ? new Map(Object.entries(manifestFiles).filter(([file]) => !staleCachedEdgeFiles.has(file)))
431
487
  : undefined;
488
+ const manifestEntries = shouldWriteManifest ? new Map() : undefined;
432
489
  if (report?.manifest) {
433
490
  report.manifest.reused = !!cachedGraphEntries;
434
491
  }
435
- const manifestEntries = shouldWriteManifest ? new Map() : undefined;
436
492
  const manifestEntriesForIndex = useManifest
437
493
  ? projectIndexManifestEntries(cachedGraphEntries ?? [])
438
494
  : new Map();
@@ -455,11 +511,14 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
455
511
  })
456
512
  .sort((left, right) => left.localeCompare(right));
457
513
  const fileSignatures = await prepareFileSignatures({
514
+ projectRoot,
458
515
  files: sqlFiles,
459
516
  opts,
460
517
  gitSigMap,
461
518
  cacheEnabled,
519
+ needsContentHash: true,
462
520
  concurrency: conc,
521
+ ...(confinedRoot ? { confinedRoot, trustedSources } : {}),
463
522
  });
464
523
  const sqlCorpusSig = sqlCorpusSignature(sqlFiles, fileSignatures);
465
524
  let sqlFactCachePromise;
@@ -482,7 +541,9 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
482
541
  const bloomFilterCache = useBloomFilters
483
542
  ? new (await import("../util/bloomFilter.js")).BloomFilterCache()
484
543
  : undefined;
485
- const persistedBloomFilters = bloomFilterCache ? await tryLoadPersistedBloomFilters(projectRoot, opts) : null;
544
+ const persistedBloomFilters = bloomFilterCache
545
+ ? await tryLoadPersistedBloomFilters(projectRoot, opts, report)
546
+ : null;
486
547
  const parsedMap = new Map();
487
548
  const workspaceConfig = await loadWorkspaceConfig(projectRoot);
488
549
  const parseStart = performance.now();
@@ -509,9 +570,16 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
509
570
  let sigInfo = fileSignatures.get(file);
510
571
  if (!sigInfo) {
511
572
  const gitSig = gitSigMap.get(file);
512
- sigInfo = await fileSignature(file, opts?.cacheStrict, gitSig, {
513
- forceContentHash: cacheEnabled && !gitSig,
514
- });
573
+ const source = confinedRoot ? await readConfinedUtf8File(confinedRoot, projectRoot, file) : undefined;
574
+ if (source !== undefined) {
575
+ trustedSources?.set(file, source);
576
+ sigInfo = fileSignatureFromSource(source, gitSig);
577
+ }
578
+ else {
579
+ sigInfo = await fileSignature(file, opts?.cacheStrict, gitSig, {
580
+ forceContentHash: cacheEnabled && !gitSig,
581
+ });
582
+ }
515
583
  fileSignatures.set(file, sigInfo);
516
584
  }
517
585
  manifestEntriesForIndex.set(file, toProjectIndexManifestEntry(sigInfo));
@@ -520,8 +588,13 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
520
588
  if (initialManifestEntry)
521
589
  manifestEntries.set(file, initialManifestEntry);
522
590
  }
523
- const cacheSig = cacheEnabled ? await moduleCacheSignatureForFile(file, sigInfo, opts) : sigInfo.cacheSig;
524
- let mod = cacheEnabled ? tryLoadFromCache(projectRoot, file, cacheSig, opts, report) : null;
591
+ const cacheSig = cacheEnabled
592
+ ? await moduleCacheSignatureForFile(file, sigInfo, opts, resolverEnvironmentFingerprint)
593
+ : sigInfo.cacheSig;
594
+ const canReuseModuleCache = cacheEnabled && (!graphOptions.resolveNodeModules || resolverEnvironmentFingerprint !== null);
595
+ let mod = canReuseModuleCache
596
+ ? tryLoadFromCache(projectRoot, file, cacheSig, opts, report)
597
+ : null;
525
598
  if (mod && fileReport) {
526
599
  fileReport.cached = (fileReport.cached ?? 0) + 1;
527
600
  }
@@ -555,7 +628,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
555
628
  ...(sqlFactCache ? { sqlFactCache } : {}),
556
629
  });
557
630
  if (bloomFilterCache) {
558
- const persistedFilter = persistedBloomFilters?.get(file);
631
+ const persistedFilter = persistedBloomFilters?.get(file, sigInfo);
559
632
  if (persistedFilter) {
560
633
  bloomFilterCache.set(file, persistedFilter);
561
634
  }
@@ -565,15 +638,16 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
565
638
  bloomFilterCache.set(file, filter);
566
639
  }
567
640
  }
568
- return [file, mod, edges];
641
+ return [file, mod, edges, undefined];
569
642
  }
570
643
  if (fileReport)
571
644
  fileReport.parsed = (fileReport.parsed ?? 0) + 1;
572
645
  const support = supportForFile(file, opts?.languageExtensions);
573
646
  if (!support)
574
- return [file, createEmptyModuleIndex(file), []];
647
+ return [file, createEmptyModuleIndex(file), [], undefined];
575
648
  ensureBuildProgressStarted();
576
649
  let graphContext;
650
+ let cacheWrite;
577
651
  if (!mod) {
578
652
  const built = await buildIndexedModuleForFile({
579
653
  file,
@@ -584,6 +658,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
584
658
  graphOptions,
585
659
  workspaceConfig,
586
660
  workerSetup,
661
+ ...(resolverEnvironmentFingerprint !== undefined ? { resolverEnvironmentFingerprint } : {}),
587
662
  parsedMap,
588
663
  parsedCacheMaxEntries: parsedCacheMaxEntries(opts),
589
664
  jsonDependencies,
@@ -591,9 +666,11 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
591
666
  onFallbackImportExtraction,
592
667
  fileSignatures,
593
668
  cacheEnabled,
669
+ ...(confinedRoot ? { confinedRoot, trustedSource: trustedSources?.get(file) } : {}),
594
670
  });
595
671
  mod = built.module;
596
672
  graphContext = built.graphContext;
673
+ cacheWrite = built.cacheWrite;
597
674
  }
598
675
  else {
599
676
  collectJsonDependencies(mod.imports, jsonDependencies);
@@ -619,13 +696,15 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
619
696
  allFiles: normalizedFiles,
620
697
  ...(sqlFactCache ? { sqlFactCache } : {}),
621
698
  });
622
- return [file, mod ?? createEmptyModuleIndex(file), edges];
699
+ return [file, mod ?? createEmptyModuleIndex(file), edges, cacheWrite];
623
700
  }
624
701
  catch (error) {
625
702
  if (isNativeRequiredUnavailableError(error) || isNodeSqliteUnavailableError(error))
626
703
  throw error;
704
+ if (isConfinedFileReadError(error))
705
+ throw error;
627
706
  if (isUnsupportedParserInputError(error) || isNonNativeParserUnavailableError(error)) {
628
- return [file, createEmptyModuleIndex(file), []];
707
+ return [file, createEmptyModuleIndex(file), [], undefined];
629
708
  }
630
709
  recordFileFailure(report, file, error);
631
710
  logWithLevel(opts?.logLevel, "warn", `Warning: Failed to process file ${file}:`, error);
@@ -662,11 +741,17 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
662
741
  graph.nodes.add(edge.to.path);
663
742
  }
664
743
  };
665
- for (const [file, mod, edges] of fileResults) {
744
+ const pendingCacheWrites = [];
745
+ for (const [file, mod, edges, cacheWrite] of fileResults) {
666
746
  modules.set(fileIdentityKey(file), mod);
667
747
  appendUniqueGraphEdges(edges);
748
+ if (cacheWrite)
749
+ pendingCacheWrites.push(cacheWrite);
750
+ }
751
+ if (pendingCacheWrites.length) {
752
+ writeModulesToCache(projectRoot, pendingCacheWrites, opts);
668
753
  }
669
- const workspaceManifestEdges = await collectWorkspaceManifestDependencyEdges(projectRoot, opts?.discovery, new Set(normalizedFiles), opts?.logLevel);
754
+ const workspaceManifestEdges = await collectWorkspaceManifestDependencyEdges(projectRoot, normalizedFiles.filter((file) => path.basename(file) === "package.json"), opts?.discovery, opts?.logLevel);
670
755
  appendUniqueGraphEdges(workspaceManifestEdges);
671
756
  if (timings)
672
757
  timings.graphMs = Math.round(performance.now() - graphStart);
@@ -674,11 +759,23 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
674
759
  ensureJsonModule(modules, jsonPath);
675
760
  }
676
761
  expandStarImports(modules, opts);
762
+ if (manifestEntries) {
763
+ for (const [file, signature] of fileSignatures) {
764
+ if (manifestEntries.has(file))
765
+ continue;
766
+ manifestEntries.set(file, {
767
+ sig: signature.sig,
768
+ ...(signature.gitSig ? { gitSig: signature.gitSig } : {}),
769
+ edges: [],
770
+ });
771
+ }
772
+ }
677
773
  if (manifestEntries) {
678
774
  await writeIndexManifestSnapshot({
679
775
  projectRoot,
680
776
  opts,
681
777
  graphOptions,
778
+ ...(resolverEnvironmentFingerprint ? { resolverEnvironmentFingerprint } : {}),
682
779
  files: manifestEntries,
683
780
  timings,
684
781
  manifestReport: report?.manifest,
@@ -686,6 +783,12 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
686
783
  ...(helperOpts?.symlinkDirectories !== undefined ? { symlinkDirectories: helperOpts.symlinkDirectories } : {}),
687
784
  });
688
785
  }
786
+ const indexManifestEntries = manifestEntries
787
+ ? projectIndexManifestEntries(Array.from(manifestEntries, ([file, entry]) => {
788
+ const cacheSig = fileSignatures.get(file)?.cacheSig;
789
+ return [file, { ...entry, ...(cacheSig ? { cacheSig } : {}) }];
790
+ }))
791
+ : manifestEntriesForIndex;
689
792
  const index = await finalizeProjectIndex({
690
793
  projectRoot,
691
794
  normalizedProjectRoot,
@@ -698,10 +801,10 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
698
801
  bloomFilterCache,
699
802
  ...(projectFiles !== undefined ? { projectFiles } : {}),
700
803
  buildReport: report,
701
- manifestEntries: manifestEntriesForIndex,
804
+ manifestEntries: indexManifestEntries,
702
805
  });
703
806
  if (manifestEntries) {
704
- await writeProjectIndexSnapshot(projectRoot, opts, index, projectSnapshotFilesSignature(manifestEntries));
807
+ await writeProjectIndexSnapshot(projectRoot, opts, index, projectSnapshotFilesSignature(manifestEntries, projectRoot));
705
808
  }
706
809
  if (buildStartedAt !== undefined) {
707
810
  emitIndexLifecycleProgress(opts, "complete", "build", index.byFile.size, performance.now() - buildStartedAt);
@@ -721,34 +824,29 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
721
824
  // full-tree symlink probe. Off and memory modes never read or write this disk
722
825
  // manifest, keeping read-only builds from mutating the project root. A missing or
723
826
  // unusable manifest falls back to probing once.
724
- // A symlink hint never expires on its own: `knownSymlinkDirectories` disables probing entirely, so
725
- // a directory symlinked in after the hint was recorded (e.g. `npm link`) would
726
- // otherwise never be discovered. `--cache-strict`/`--cache-verify` are explicit asks
727
- // for maximum correctness over speed, so both force a fresh probe here too.
827
+ // The manifest records the project-root directory mtime alongside symlink hints. A changed
828
+ // root mtime triggers the cheap full-tree probe, while strict modes always probe.
728
829
  const wantsMaxSymlinkCorrectness = !!opts?.cacheStrict || !!opts?.cacheVerify;
729
830
  const symlinkHintManifest = helperOpts?.ignoreExistingManifest || wantsMaxSymlinkCorrectness || !useDiskCache
730
831
  ? null
731
832
  : await loadManifest(projectRoot, opts);
732
- const knownSymlinkDirectories = symlinkHintManifest?.symlinkDirectories;
833
+ const rootMtime = symlinkHintManifest ? (await fsp.stat(projectRoot)).mtimeMs : undefined;
834
+ const symlinkHintIsFresh = symlinkHintManifest?.symlinkDirectoriesRootMtimeMs !== undefined &&
835
+ rootMtime === symlinkHintManifest.symlinkDirectoriesRootMtimeMs;
836
+ const knownSymlinkDirectories = symlinkHintIsFresh ? symlinkHintManifest?.symlinkDirectories : undefined;
733
837
  let discoveredSymlinkDirectories = knownSymlinkDirectories;
734
838
  const onSymlinkDirectoriesDiscovered = (directories) => {
735
839
  discoveredSymlinkDirectories = Array.from(directories);
736
840
  };
737
841
  // When the hint is unknown, listProjectFiles() and discoverProjectFiles() must run
738
- // sequentially rather than in Promise.all: both would otherwise start their own
739
- // full-tree symlink probe concurrently, since the callback only reports back after
740
- // listProjectFiles() resolves, too late to inform a probe discoverProjectFiles()
741
- // already started on its own. Sequencing costs a little parallelism on that one
742
- // cold-start case, but avoids paying for two full-tree walks instead of one. Once a
743
- // hint is known (the common warm case), both calls skip probing entirely, so running
744
- // them sequentially here costs no meaningful time either way.
842
+ // sequentially rather than in Promise.all to avoid duplicate full-tree probes.
745
843
  const discoveredFiles = await listProjectFiles(projectRoot, projectPatternsForLanguageExtensions(opts), {
746
844
  ...opts?.discovery,
747
845
  ...(opts?.logLevel ? { logLevel: opts.logLevel } : {}),
748
846
  ...(knownSymlinkDirectories !== undefined ? { knownSymlinkDirectories } : {}),
749
847
  onSymlinkDirectoriesDiscovered,
750
848
  });
751
- const additionalFileCandidates = normalizeIndexedFileInputs(projectRoot, opts?.additionalFiles ?? [], "Additional index file");
849
+ const additionalFileCandidates = await normalizeIndexedFileInputsWithinRoot(projectRoot, opts?.additionalFiles ?? [], "Additional index file");
752
850
  const additionalFileExistence = await probePathExistence(additionalFileCandidates, buildConcurrency(opts));
753
851
  const additionalFiles = additionalFileCandidates.filter((file) => additionalFileExistence.get(file));
754
852
  const discoveredFileSet = new Set(discoveredFiles);
@@ -795,9 +893,11 @@ export async function buildProjectIndex(projectRoot, opts) {
795
893
  export async function buildProjectIndexFromFiles(projectRoot, inputFiles, opts) {
796
894
  try {
797
895
  const useDiskCache = (opts?.cache ?? "off") === "disk";
798
- return await buildIndexFromFileListShared(projectRoot, inputFiles, opts, {
896
+ const normalizedInputFiles = await normalizeIndexedFileInputsWithinRoot(projectRoot, inputFiles, "Index file");
897
+ return await buildIndexFromFileListShared(projectRoot, normalizedInputFiles, opts, {
799
898
  manifestMode: useDiskCache ? "read-only" : "off",
800
899
  warnNoFilesMessage: `Warning: No files provided for indexing in ${projectRoot}. Check the explicit file list and include/ignore filters. Diagnostic: codegraph doctor`,
900
+ confineReads: true,
801
901
  });
802
902
  }
803
903
  finally {
@@ -838,7 +938,7 @@ async function buildDeclaredScopeIndex(projectRoot, scopeFiles, opts) {
838
938
  */
839
939
  export async function buildProjectIndexIncremental(projectRoot, opts) {
840
940
  await initializeFileIdentityCaseSensitivity(projectRoot);
841
- clearImportResolutionCaches();
941
+ clearResolutionCaches();
842
942
  const graphOptions = normalizeGraphOptions(opts?.graph);
843
943
  const strictIncremental = opts?.incrementalStrict ?? false;
844
944
  if (strictIncremental && graphOptions.fast)
@@ -889,7 +989,7 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
889
989
  }
890
990
  startCheckProgress();
891
991
  const manifestStart = performance.now();
892
- const manifest = await loadManifest(projectRoot, opts);
992
+ const manifest = await loadManifest(projectRoot, opts, report);
893
993
  if (timings)
894
994
  timings.manifestMs = Math.round(performance.now() - manifestStart);
895
995
  const manifestUsed = !!manifest;
@@ -907,8 +1007,21 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
907
1007
  const currentConfigHashResult = await computeConfigHash(projectRoot, opts?.logLevel);
908
1008
  const currentConfigHash = recordConfigHashResult(manifestReport, currentConfigHashResult, opts?.logLevel);
909
1009
  const configChanged = !!currentConfigHashResult.error || !manifest?.configHash || currentConfigHash !== manifest.configHash;
1010
+ let resolverEnvironmentFingerprint;
1011
+ let resolverEnvironmentMatchesManifest = true;
1012
+ if (manifest && graphOptions.resolveNodeModules) {
1013
+ resolverEnvironmentFingerprint = await computeResolverEnvironmentFingerprint(projectRoot, Object.keys(manifest.files));
1014
+ resolverEnvironmentMatchesManifest =
1015
+ resolverEnvironmentFingerprint !== null &&
1016
+ manifest.resolverEnvironmentFingerprint === resolverEnvironmentFingerprint;
1017
+ }
910
1018
  const requiresFullRebuild = optionDiffs.some((diff) => diff === "discovery" || diff === "native" || diff === "implementation" || diff === "languageExtensions");
911
- if (!manifest || !graphOptionsEqual(manifest.graphOptions, graphOptions) || configChanged || requiresFullRebuild) {
1019
+ const graphOptionsChanged = !graphOptionsEqual(manifest?.graphOptions, graphOptions);
1020
+ if (!manifest ||
1021
+ graphOptionsChanged ||
1022
+ configChanged ||
1023
+ requiresFullRebuild ||
1024
+ !resolverEnvironmentMatchesManifest) {
912
1025
  if (manifest && configChanged) {
913
1026
  logWithLevel(opts?.logLevel, "warn", "Configuration changed, rebuilding index...");
914
1027
  }
@@ -920,6 +1033,9 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
920
1033
  else if (configChanged) {
921
1034
  reason = "configChanged";
922
1035
  }
1036
+ else if (!graphOptionsChanged && !resolverEnvironmentMatchesManifest) {
1037
+ reason = "resolverEnvironmentChanged";
1038
+ }
923
1039
  manifestReport.reason = reason;
924
1040
  manifestReport.reused = false;
925
1041
  }
@@ -979,9 +1095,9 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
979
1095
  const trackedEntryKeys = Object.keys(trackedEntries);
980
1096
  let manifestRequiresSanitization = manifestFileKeys.length !== trackedEntryKeys.length ||
981
1097
  manifestFileKeys.some((file) => !Object.hasOwn(trackedEntries, file));
982
- const explicitFiles = normalizeIndexedFileInputs(projectRoot, opts?.files ?? [], "Incremental file");
983
- const additionalFiles = normalizeIndexedFileInputs(projectRoot, opts?.additionalFiles ?? [], "Additional index file");
984
- const previousTransientFiles = sanitizeManifestTransientFilesForRoot(projectRoot, manifest.transientFiles).filter((file) => Object.hasOwn(trackedEntries, file));
1098
+ const explicitFiles = await normalizeIndexedFileInputsWithinRoot(projectRoot, opts?.files ?? [], "Incremental file");
1099
+ const additionalFiles = await normalizeIndexedFileInputsWithinRoot(projectRoot, opts?.additionalFiles ?? [], "Additional index file");
1100
+ const previousTransientFiles = sanitizeManifestTransientFilesForRoot(projectRoot, projectRoot, manifest.transientFiles).filter((file) => Object.hasOwn(trackedEntries, file));
985
1101
  const previousTransientFileSet = new Set(previousTransientFiles);
986
1102
  const needsGitScan = !!opts?.gitBase || !!opts?.changedSince;
987
1103
  const gitFiles = needsGitScan ? await listChangedFiles(projectRoot, buildIncrementalGitDiffOptions(opts)) : [];
@@ -1067,6 +1183,7 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1067
1183
  projectRoot,
1068
1184
  opts,
1069
1185
  graphOptions,
1186
+ ...(resolverEnvironmentFingerprint ? { resolverEnvironmentFingerprint } : {}),
1070
1187
  files: {},
1071
1188
  timings,
1072
1189
  manifestReport,
@@ -1087,6 +1204,10 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1087
1204
  };
1088
1205
  }
1089
1206
  const changedFiles = new Set();
1207
+ if (!resolverEnvironmentMatchesManifest) {
1208
+ for (const file of allFiles)
1209
+ changedFiles.add(file);
1210
+ }
1090
1211
  const markAsChanged = (file) => {
1091
1212
  if (allFiles.has(file))
1092
1213
  changedFiles.add(file);
@@ -1109,7 +1230,7 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1109
1230
  const explicitFileSet = new Set(explicitFiles);
1110
1231
  const explicitFilesCoverAllFiles = explicitFileSet.size === allFiles.size && [...allFiles].every((file) => explicitFileSet.has(file));
1111
1232
  const explicitFilesAreChangeInputs = !opts?.filesAreProjectScope;
1112
- if (explicitFileSet.size && explicitFilesAreChangeInputs && (!explicitFilesCoverAllFiles || report)) {
1233
+ if (explicitFileSet.size && explicitFilesAreChangeInputs && (!explicitFilesCoverAllFiles || opts?.report)) {
1113
1234
  explicitFileSet.forEach(markAsChanged);
1114
1235
  }
1115
1236
  dependentFilesOfDeletedTracked.forEach(markAsChanged);
@@ -1119,7 +1240,7 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1119
1240
  if (changedFiles.size || deletedTrackedFiles.size || manifestRequiresSanitization)
1120
1241
  return null;
1121
1242
  const manifestEntryMap = new Map(Object.entries(trackedEntries));
1122
- const snapshotLoad = await tryLoadProjectIndexSnapshot(projectRoot, opts, manifestEntryMap);
1243
+ const snapshotLoad = await tryLoadProjectIndexSnapshot(projectRoot, opts, manifestEntryMap, report);
1123
1244
  if (!snapshotLoad)
1124
1245
  return null;
1125
1246
  const snapshot = snapshotLoad.index;
@@ -1199,10 +1320,12 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1199
1320
  })
1200
1321
  : new Map();
1201
1322
  const fileSignatures = await prepareFileSignatures({
1323
+ projectRoot,
1202
1324
  files: Array.from(allFiles),
1203
1325
  opts,
1204
1326
  gitSigMap,
1205
1327
  cacheEnabled,
1328
+ needsContentHash: cacheEnabled || manifestUsed || opts?.cacheStrict === true,
1206
1329
  concurrency: conc,
1207
1330
  });
1208
1331
  const modules = new Map();
@@ -1223,8 +1346,9 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1223
1346
  changedFiles.add(file);
1224
1347
  }
1225
1348
  }
1349
+ const reverseDeps = buildTrackedFileReverseDependencies(trackedEntries);
1226
1350
  const invalidateCachedDependents = () => {
1227
- const dependentFilesOfChanged = collectTrackedFileDependents(trackedEntries, changedFiles);
1351
+ const dependentFilesOfChanged = collectTrackedFileDependents(trackedEntries, changedFiles, reverseDeps);
1228
1352
  for (const file of dependentFilesOfChanged) {
1229
1353
  const key = fileIdentityKey(file);
1230
1354
  if (modules.has(key)) {
@@ -1248,20 +1372,32 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1248
1372
  completeCheckProgress(allFiles.size);
1249
1373
  return unchangedSnapshot;
1250
1374
  }
1251
- const persistedBloomFilters = bloomFilterCache ? await tryLoadPersistedBloomFilters(projectRoot, opts) : null;
1375
+ const snapshotModules = cacheEnabled
1376
+ ? await tryLoadProjectSnapshotModules(projectRoot, opts, fileSignatures, report)
1377
+ : null;
1378
+ const persistedBloomFilters = bloomFilterCache
1379
+ ? await tryLoadPersistedBloomFilters(projectRoot, opts, report)
1380
+ : null;
1252
1381
  for (const file of allFiles) {
1253
1382
  if (changedFiles.has(file))
1254
1383
  continue;
1255
1384
  const sigInfo = fileSignatures.get(file);
1256
- const cacheSig = cacheEnabled ? await moduleCacheSignatureForFile(file, sigInfo, opts) : sigInfo.cacheSig;
1257
- const cached = cacheEnabled ? tryLoadFromCache(projectRoot, file, cacheSig, opts, report) : null;
1385
+ let cached = null;
1386
+ const snapshotMod = snapshotModules?.get(fileIdentityKey(file));
1387
+ if (snapshotMod) {
1388
+ cached = snapshotMod;
1389
+ }
1390
+ else if (cacheEnabled) {
1391
+ const cacheSig = await moduleCacheSignatureForFile(file, sigInfo, opts, resolverEnvironmentFingerprint);
1392
+ cached = tryLoadFromCache(projectRoot, file, cacheSig, opts, report);
1393
+ }
1258
1394
  if (cached) {
1259
1395
  if (fileReport)
1260
1396
  fileReport.cached = (fileReport.cached ?? 0) + 1;
1261
1397
  modules.set(fileIdentityKey(file), cached);
1262
1398
  collectJsonDependencies(cached.imports, jsonDependencies);
1263
1399
  if (bloomFilterCache) {
1264
- const persistedFilter = persistedBloomFilters?.get(file);
1400
+ const persistedFilter = persistedBloomFilters?.get(file, sigInfo);
1265
1401
  if (persistedFilter) {
1266
1402
  bloomFilterCache.set(file, persistedFilter);
1267
1403
  }
@@ -1312,8 +1448,9 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1312
1448
  onFallbackImportExtraction,
1313
1449
  fileSignatures,
1314
1450
  cacheEnabled,
1451
+ ...(resolverEnvironmentFingerprint !== undefined ? { resolverEnvironmentFingerprint } : {}),
1315
1452
  });
1316
- return [file, built.module];
1453
+ return [file, built.module, built.cacheWrite];
1317
1454
  }
1318
1455
  catch (error) {
1319
1456
  if (isNativeRequiredUnavailableError(error) || isNodeSqliteUnavailableError(error))
@@ -1323,7 +1460,7 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1323
1460
  }
1324
1461
  recordFileFailure(report, file, error);
1325
1462
  logWithLevel(opts?.logLevel, "warn", `Warning: Failed to process file ${file}:`, error);
1326
- return [file, createEmptyModuleIndex(file)];
1463
+ return [file, createEmptyModuleIndex(file), undefined];
1327
1464
  }
1328
1465
  finally {
1329
1466
  if (opts?.onProgress) {
@@ -1338,8 +1475,14 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1338
1475
  }
1339
1476
  }
1340
1477
  });
1341
- for (const [file, mod] of fileResults) {
1478
+ const pendingIncrementalCacheWrites = [];
1479
+ for (const [file, mod, cacheWrite] of fileResults) {
1342
1480
  modules.set(fileIdentityKey(file), mod);
1481
+ if (cacheWrite)
1482
+ pendingIncrementalCacheWrites.push(cacheWrite);
1483
+ }
1484
+ if (pendingIncrementalCacheWrites.length) {
1485
+ writeModulesToCache(projectRoot, pendingIncrementalCacheWrites, opts);
1343
1486
  }
1344
1487
  if (timings)
1345
1488
  timings.parseMs = Math.round(performance.now() - parseStart);
@@ -1349,7 +1492,9 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1349
1492
  }
1350
1493
  expandStarImports(modules, opts);
1351
1494
  const retainedTrackedEntries = Object.entries(trackedEntries).filter(([file]) => !deletedTrackedFiles.has(file));
1352
- const cachedGraphEntries = new Map(retainedTrackedEntries);
1495
+ const cachedGraphEntries = resolverEnvironmentMatchesManifest
1496
+ ? new Map(retainedTrackedEntries)
1497
+ : new Map();
1353
1498
  const manifestEntries = new Map(cachedGraphEntries);
1354
1499
  const baseGraph = cachedGraphEntries.size > 0 ? { nodes: new Set(), edges: [] } : undefined;
1355
1500
  if (baseGraph) {
@@ -1385,6 +1530,7 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1385
1530
  dynamicImportHeuristics: !!graphOptions.dynamicImportHeuristics,
1386
1531
  ...(opts?.native ? { native: opts.native } : {}),
1387
1532
  ...(opts?.languageExtensions ? { languageExtensions: opts.languageExtensions } : {}),
1533
+ threads: conc,
1388
1534
  ...(opts?.logLevel ? { logLevel: opts.logLevel } : {}),
1389
1535
  ...(graphOptions.resolutionHints ? { resolutionHints: graphOptions.resolutionHints } : {}),
1390
1536
  allFiles: Array.from(allFiles),
@@ -1402,10 +1548,21 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1402
1548
  });
1403
1549
  if (timings)
1404
1550
  timings.graphMs = Math.round(performance.now() - graphStart);
1551
+ for (const file of new Set([...changedFiles, ...transientFiles])) {
1552
+ const signature = fileSignatures.get(file);
1553
+ if (!signature || manifestEntries.has(file))
1554
+ continue;
1555
+ manifestEntries.set(file, {
1556
+ sig: signature.sig,
1557
+ ...(signature.gitSig ? { gitSig: signature.gitSig } : {}),
1558
+ edges: [],
1559
+ });
1560
+ }
1405
1561
  await writeIndexManifestSnapshot({
1406
1562
  projectRoot,
1407
1563
  opts,
1408
1564
  graphOptions,
1565
+ ...(resolverEnvironmentFingerprint ? { resolverEnvironmentFingerprint } : {}),
1409
1566
  files: manifestEntries,
1410
1567
  timings,
1411
1568
  manifestReport,
@@ -1422,10 +1579,20 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1422
1579
  modules,
1423
1580
  parsedMap,
1424
1581
  bloomFilterCache,
1425
- manifestEntries: projectIndexManifestEntries(manifestEntries),
1582
+ manifestEntries: projectIndexManifestEntries(
1583
+ // `manifestEntries` (a `ManifestFileEntry`) never carries `cacheSig` -- that field
1584
+ // only lives on `FileSignature`. Overlay each entry with the `cacheSig` this build
1585
+ // actually computed (content-hash-derived for non-git files, since caching is enabled
1586
+ // whenever this path runs) so incremental writes preserve the same strong identity a
1587
+ // cold build produces, instead of leaving snapshot/bloom reuse to fall back to the
1588
+ // weak `mtime:size` `sig`.
1589
+ Array.from(manifestEntries, ([file, entry]) => {
1590
+ const cacheSig = fileSignatures.get(file)?.cacheSig;
1591
+ return [file, { ...entry, ...(cacheSig ? { cacheSig } : {}) }];
1592
+ })),
1426
1593
  buildReport: report,
1427
1594
  });
1428
- await writeProjectIndexSnapshot(projectRoot, opts, index, projectSnapshotFilesSignature(manifestEntries));
1595
+ await writeProjectIndexSnapshot(projectRoot, opts, index, projectSnapshotFilesSignature(manifestEntries, projectRoot));
1429
1596
  if (updateStartedAt !== undefined) {
1430
1597
  emitIndexLifecycleProgress(opts, "complete", "update", index.byFile.size, performance.now() - updateStartedAt);
1431
1598
  }
@@ -1458,8 +1625,8 @@ export async function buildGraphDelta(projectRoot, opts) {
1458
1625
  const strictIncremental = opts?.incrementalStrict ?? false;
1459
1626
  if (strictIncremental && graphOptions.fast)
1460
1627
  graphOptions.fast = false;
1461
- const explicitFiles = normalizeIndexedFileInputs(projectRoot, opts?.files ?? [], "Graph delta file");
1462
- const additionalFiles = normalizeIndexedFileInputs(projectRoot, opts?.additionalFiles ?? [], "Additional graph delta file");
1628
+ const explicitFiles = await normalizeIndexedFileInputsWithinRoot(projectRoot, opts?.files ?? [], "Graph delta file");
1629
+ const additionalFiles = await normalizeIndexedFileInputsWithinRoot(projectRoot, opts?.additionalFiles ?? [], "Additional graph delta file");
1463
1630
  const needsGitScan = !!opts?.gitBase || !!opts?.changedSince;
1464
1631
  const gitFiles = needsGitScan ? await listChangedFiles(projectRoot, buildIncrementalGitDiffOptions(opts)) : [];
1465
1632
  const { trackedFiles } = await partitionTrackedManifestFiles(trackedEntries);
@@ -1484,14 +1651,19 @@ export async function buildGraphDelta(projectRoot, opts) {
1484
1651
  }
1485
1652
  const candidateExistence = await probePathExistence([...explicitFiles, ...additionalFiles, ...manifestDiffFiles, ...gitFiles], buildConcurrency(opts));
1486
1653
  const existsInCandidateSnapshot = (file) => candidateExistence.get(file) ?? false;
1487
- const existingExplicitFiles = explicitFiles.filter(existsInCandidateSnapshot);
1654
+ const normalizeChangedFiles = (files) => files.map((file) => {
1655
+ if (!existsInCandidateSnapshot(file))
1656
+ return file;
1657
+ const [normalizedFile] = normalizeIndexedFileInputs(projectRoot, [file], "Graph delta file");
1658
+ return normalizedFile ?? file;
1659
+ }), normalizedManifestDiffFiles = normalizeChangedFiles(manifestDiffFiles), normalizedGitFiles = normalizeChangedFiles(gitFiles), existingExplicitFiles = explicitFiles.filter(existsInCandidateSnapshot);
1488
1660
  const existingAdditionalFiles = additionalFiles.filter(existsInCandidateSnapshot);
1489
1661
  const allFiles = new Set([
1490
1662
  ...trackedFiles,
1491
1663
  ...existingExplicitFiles,
1492
1664
  ...existingAdditionalFiles,
1493
- ...manifestDiffFiles.filter(existsInCandidateSnapshot),
1494
- ...gitFiles.filter(existsInCandidateSnapshot),
1665
+ ...normalizedManifestDiffFiles.filter((_, index) => existsInCandidateSnapshot(manifestDiffFiles[index])),
1666
+ ...normalizedGitFiles.filter((_, index) => existsInCandidateSnapshot(gitFiles[index])),
1495
1667
  ]);
1496
1668
  const changedFiles = new Set();
1497
1669
  const changedFileKeys = new Set();
@@ -1503,8 +1675,8 @@ export async function buildGraphDelta(projectRoot, opts) {
1503
1675
  changedFiles.add(file);
1504
1676
  };
1505
1677
  existingExplicitFiles.forEach(addChangedFile);
1506
- manifestDiffFiles.forEach(addChangedFile);
1507
- gitFiles.forEach(addChangedFile);
1678
+ normalizedManifestDiffFiles.forEach(addChangedFile);
1679
+ normalizedGitFiles.forEach(addChangedFile);
1508
1680
  if (languageExtensionsChanged) {
1509
1681
  for (const file of trackedFiles) {
1510
1682
  if (languageSupportChangedForFile(file))