trail-code 0.0.0-stage → 0.28.0-semantic.3

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 (593) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +567 -2
  3. package/dist/ai/crux.d.ts +88 -0
  4. package/dist/ai/crux.d.ts.map +1 -0
  5. package/dist/ai/crux.js +219 -0
  6. package/dist/ai/crux.js.map +1 -0
  7. package/dist/ai/failure.d.ts +60 -0
  8. package/dist/ai/failure.d.ts.map +1 -0
  9. package/dist/ai/failure.js +86 -0
  10. package/dist/ai/failure.js.map +1 -0
  11. package/dist/ai/llm/anthropic.d.ts +37 -0
  12. package/dist/ai/llm/anthropic.d.ts.map +1 -0
  13. package/dist/ai/llm/anthropic.js +144 -0
  14. package/dist/ai/llm/anthropic.js.map +1 -0
  15. package/dist/ai/llm/factory.d.ts +28 -0
  16. package/dist/ai/llm/factory.d.ts.map +1 -0
  17. package/dist/ai/llm/factory.js +36 -0
  18. package/dist/ai/llm/factory.js.map +1 -0
  19. package/dist/ai/llm/litellm.d.ts +34 -0
  20. package/dist/ai/llm/litellm.d.ts.map +1 -0
  21. package/dist/ai/llm/litellm.js +45 -0
  22. package/dist/ai/llm/litellm.js.map +1 -0
  23. package/dist/ai/llm/openai.d.ts +145 -0
  24. package/dist/ai/llm/openai.d.ts.map +1 -0
  25. package/dist/ai/llm/openai.js +629 -0
  26. package/dist/ai/llm/openai.js.map +1 -0
  27. package/dist/ai/llm/orcarouter.d.ts +34 -0
  28. package/dist/ai/llm/orcarouter.d.ts.map +1 -0
  29. package/dist/ai/llm/orcarouter.js +45 -0
  30. package/dist/ai/llm/orcarouter.js.map +1 -0
  31. package/dist/ai/llm/recover-tool.d.ts +21 -0
  32. package/dist/ai/llm/recover-tool.d.ts.map +1 -0
  33. package/dist/ai/llm/recover-tool.js +109 -0
  34. package/dist/ai/llm/recover-tool.js.map +1 -0
  35. package/dist/ai/llm/types.d.ts +122 -0
  36. package/dist/ai/llm/types.d.ts.map +1 -0
  37. package/dist/ai/llm/types.js +33 -0
  38. package/dist/ai/llm/types.js.map +1 -0
  39. package/dist/ai/providers.d.ts +59 -0
  40. package/dist/ai/providers.d.ts.map +1 -0
  41. package/dist/ai/providers.js +54 -0
  42. package/dist/ai/providers.js.map +1 -0
  43. package/dist/ai/summarize.d.ts +25 -0
  44. package/dist/ai/summarize.d.ts.map +1 -0
  45. package/dist/ai/summarize.js +34 -0
  46. package/dist/ai/summarize.js.map +1 -0
  47. package/dist/ai/synthesize.d.ts +40 -0
  48. package/dist/ai/synthesize.d.ts.map +1 -0
  49. package/dist/ai/synthesize.js +230 -0
  50. package/dist/ai/synthesize.js.map +1 -0
  51. package/dist/ask/ask.d.ts +199 -0
  52. package/dist/ask/ask.d.ts.map +1 -0
  53. package/dist/ask/ask.js +1291 -0
  54. package/dist/ask/ask.js.map +1 -0
  55. package/dist/ask/file-rank.d.ts +72 -0
  56. package/dist/ask/file-rank.d.ts.map +1 -0
  57. package/dist/ask/file-rank.js +160 -0
  58. package/dist/ask/file-rank.js.map +1 -0
  59. package/dist/ask/file-selection.d.ts +22 -0
  60. package/dist/ask/file-selection.d.ts.map +1 -0
  61. package/dist/ask/file-selection.js +66 -0
  62. package/dist/ask/file-selection.js.map +1 -0
  63. package/dist/ask/fuse.d.ts +195 -0
  64. package/dist/ask/fuse.d.ts.map +1 -0
  65. package/dist/ask/fuse.js +344 -0
  66. package/dist/ask/fuse.js.map +1 -0
  67. package/dist/ask/graphrank.d.ts +61 -0
  68. package/dist/ask/graphrank.d.ts.map +1 -0
  69. package/dist/ask/graphrank.js +130 -0
  70. package/dist/ask/graphrank.js.map +1 -0
  71. package/dist/ask/index-file.d.ts +44 -0
  72. package/dist/ask/index-file.d.ts.map +1 -0
  73. package/dist/ask/index-file.js +128 -0
  74. package/dist/ask/index-file.js.map +1 -0
  75. package/dist/ask/semantic.d.ts +42 -0
  76. package/dist/ask/semantic.d.ts.map +1 -0
  77. package/dist/ask/semantic.js +293 -0
  78. package/dist/ask/semantic.js.map +1 -0
  79. package/dist/bin/graft.d.ts +3 -0
  80. package/dist/bin/graft.d.ts.map +1 -0
  81. package/dist/bin/graft.js +14 -0
  82. package/dist/bin/graft.js.map +1 -0
  83. package/dist/bin/trail.d.ts +3 -0
  84. package/dist/bin/trail.d.ts.map +1 -0
  85. package/dist/bin/trail.js +13 -0
  86. package/dist/bin/trail.js.map +1 -0
  87. package/dist/blast/blast-cli.d.ts +35 -0
  88. package/dist/blast/blast-cli.d.ts.map +1 -0
  89. package/dist/blast/blast-cli.js +155 -0
  90. package/dist/blast/blast-cli.js.map +1 -0
  91. package/dist/blast/blast.d.ts +128 -0
  92. package/dist/blast/blast.d.ts.map +1 -0
  93. package/dist/blast/blast.js +383 -0
  94. package/dist/blast/blast.js.map +1 -0
  95. package/dist/blast/diff.d.ts +53 -0
  96. package/dist/blast/diff.d.ts.map +1 -0
  97. package/dist/blast/diff.js +193 -0
  98. package/dist/blast/diff.js.map +1 -0
  99. package/dist/blast/evidence.d.ts +51 -0
  100. package/dist/blast/evidence.d.ts.map +1 -0
  101. package/dist/blast/evidence.js +162 -0
  102. package/dist/blast/evidence.js.map +1 -0
  103. package/dist/blast/modules.d.ts +33 -0
  104. package/dist/blast/modules.d.ts.map +1 -0
  105. package/dist/blast/modules.js +83 -0
  106. package/dist/blast/modules.js.map +1 -0
  107. package/dist/blast/name.d.ts +74 -0
  108. package/dist/blast/name.d.ts.map +1 -0
  109. package/dist/blast/name.js +269 -0
  110. package/dist/blast/name.js.map +1 -0
  111. package/dist/blast/owners.d.ts +85 -0
  112. package/dist/blast/owners.d.ts.map +1 -0
  113. package/dist/blast/owners.js +272 -0
  114. package/dist/blast/owners.js.map +1 -0
  115. package/dist/blast/render.d.ts +46 -0
  116. package/dist/blast/render.d.ts.map +1 -0
  117. package/dist/blast/render.js +422 -0
  118. package/dist/blast/render.js.map +1 -0
  119. package/dist/blast/viz.d.ts +37 -0
  120. package/dist/blast/viz.d.ts.map +1 -0
  121. package/dist/blast/viz.js +180 -0
  122. package/dist/blast/viz.js.map +1 -0
  123. package/dist/brand.d.ts +111 -0
  124. package/dist/brand.d.ts.map +1 -0
  125. package/dist/brand.js +282 -0
  126. package/dist/brand.js.map +1 -0
  127. package/dist/claude/build-progress.d.ts +30 -0
  128. package/dist/claude/build-progress.d.ts.map +1 -0
  129. package/dist/claude/build-progress.js +81 -0
  130. package/dist/claude/build-progress.js.map +1 -0
  131. package/dist/claude/hermes-skill-template.d.ts +16 -0
  132. package/dist/claude/hermes-skill-template.d.ts.map +1 -0
  133. package/dist/claude/hermes-skill-template.js +154 -0
  134. package/dist/claude/hermes-skill-template.js.map +1 -0
  135. package/dist/claude/init.d.ts +65 -0
  136. package/dist/claude/init.d.ts.map +1 -0
  137. package/dist/claude/init.js +258 -0
  138. package/dist/claude/init.js.map +1 -0
  139. package/dist/claude/paths.d.ts +9 -0
  140. package/dist/claude/paths.d.ts.map +1 -0
  141. package/dist/claude/paths.js +22 -0
  142. package/dist/claude/paths.js.map +1 -0
  143. package/dist/claude/session-metrics.d.ts +73 -0
  144. package/dist/claude/session-metrics.d.ts.map +1 -0
  145. package/dist/claude/session-metrics.js +209 -0
  146. package/dist/claude/session-metrics.js.map +1 -0
  147. package/dist/claude/settings-merge.d.ts +76 -0
  148. package/dist/claude/settings-merge.d.ts.map +1 -0
  149. package/dist/claude/settings-merge.js +283 -0
  150. package/dist/claude/settings-merge.js.map +1 -0
  151. package/dist/claude/skill-template.d.ts +13 -0
  152. package/dist/claude/skill-template.d.ts.map +1 -0
  153. package/dist/claude/skill-template.js +290 -0
  154. package/dist/claude/skill-template.js.map +1 -0
  155. package/dist/claude/state.d.ts +85 -0
  156. package/dist/claude/state.d.ts.map +1 -0
  157. package/dist/claude/state.js +88 -0
  158. package/dist/claude/state.js.map +1 -0
  159. package/dist/claude/stats.d.ts +5 -0
  160. package/dist/claude/stats.d.ts.map +1 -0
  161. package/dist/claude/stats.js +24 -0
  162. package/dist/claude/stats.js.map +1 -0
  163. package/dist/cli-epilogue.d.ts +12 -0
  164. package/dist/cli-epilogue.d.ts.map +1 -0
  165. package/dist/cli-epilogue.js +72 -0
  166. package/dist/cli-epilogue.js.map +1 -0
  167. package/dist/cli-meta.d.ts +82 -0
  168. package/dist/cli-meta.d.ts.map +1 -0
  169. package/dist/cli-meta.js +238 -0
  170. package/dist/cli-meta.js.map +1 -0
  171. package/dist/cli-picker.d.ts +139 -0
  172. package/dist/cli-picker.d.ts.map +1 -0
  173. package/dist/cli-picker.js +439 -0
  174. package/dist/cli-picker.js.map +1 -0
  175. package/dist/cli.d.ts +3 -0
  176. package/dist/cli.d.ts.map +1 -0
  177. package/dist/cli.js +1638 -0
  178. package/dist/cli.js.map +1 -0
  179. package/dist/context/batches.d.ts +29 -0
  180. package/dist/context/batches.d.ts.map +1 -0
  181. package/dist/context/batches.js +130 -0
  182. package/dist/context/batches.js.map +1 -0
  183. package/dist/context/build.d.ts +57 -0
  184. package/dist/context/build.d.ts.map +1 -0
  185. package/dist/context/build.js +396 -0
  186. package/dist/context/build.js.map +1 -0
  187. package/dist/context/check.d.ts +42 -0
  188. package/dist/context/check.d.ts.map +1 -0
  189. package/dist/context/check.js +162 -0
  190. package/dist/context/check.js.map +1 -0
  191. package/dist/context/map-dir.d.ts +13 -0
  192. package/dist/context/map-dir.d.ts.map +1 -0
  193. package/dist/context/map-dir.js +81 -0
  194. package/dist/context/map-dir.js.map +1 -0
  195. package/dist/context/node-file.d.ts +109 -0
  196. package/dist/context/node-file.d.ts.map +1 -0
  197. package/dist/context/node-file.js +390 -0
  198. package/dist/context/node-file.js.map +1 -0
  199. package/dist/context/price.d.ts +49 -0
  200. package/dist/context/price.d.ts.map +1 -0
  201. package/dist/context/price.js +83 -0
  202. package/dist/context/price.js.map +1 -0
  203. package/dist/context/savings.d.ts +67 -0
  204. package/dist/context/savings.d.ts.map +1 -0
  205. package/dist/context/savings.js +125 -0
  206. package/dist/context/savings.js.map +1 -0
  207. package/dist/engine.d.ts +85 -0
  208. package/dist/engine.d.ts.map +1 -0
  209. package/dist/engine.js +122 -0
  210. package/dist/engine.js.map +1 -0
  211. package/dist/graph/bindings.d.ts +64 -0
  212. package/dist/graph/bindings.d.ts.map +1 -0
  213. package/dist/graph/bindings.js +713 -0
  214. package/dist/graph/bindings.js.map +1 -0
  215. package/dist/graph/build-run.d.ts +25 -0
  216. package/dist/graph/build-run.d.ts.map +1 -0
  217. package/dist/graph/build-run.js +121 -0
  218. package/dist/graph/build-run.js.map +1 -0
  219. package/dist/graph/build.d.ts +88 -0
  220. package/dist/graph/build.d.ts.map +1 -0
  221. package/dist/graph/build.js +386 -0
  222. package/dist/graph/build.js.map +1 -0
  223. package/dist/graph/cards.d.ts +46 -0
  224. package/dist/graph/cards.d.ts.map +1 -0
  225. package/dist/graph/cards.js +280 -0
  226. package/dist/graph/cards.js.map +1 -0
  227. package/dist/graph/check.d.ts +25 -0
  228. package/dist/graph/check.d.ts.map +1 -0
  229. package/dist/graph/check.js +192 -0
  230. package/dist/graph/check.js.map +1 -0
  231. package/dist/graph/container.d.ts +63 -0
  232. package/dist/graph/container.d.ts.map +1 -0
  233. package/dist/graph/container.js +191 -0
  234. package/dist/graph/container.js.map +1 -0
  235. package/dist/graph/depth-parser.d.ts +61 -0
  236. package/dist/graph/depth-parser.d.ts.map +1 -0
  237. package/dist/graph/depth-parser.js +153 -0
  238. package/dist/graph/depth-parser.js.map +1 -0
  239. package/dist/graph/enrich.d.ts +62 -0
  240. package/dist/graph/enrich.d.ts.map +1 -0
  241. package/dist/graph/enrich.js +258 -0
  242. package/dist/graph/enrich.js.map +1 -0
  243. package/dist/graph/extract-cache.d.ts +101 -0
  244. package/dist/graph/extract-cache.d.ts.map +1 -0
  245. package/dist/graph/extract-cache.js +199 -0
  246. package/dist/graph/extract-cache.js.map +1 -0
  247. package/dist/graph/extract.d.ts +85 -0
  248. package/dist/graph/extract.d.ts.map +1 -0
  249. package/dist/graph/extract.js +2377 -0
  250. package/dist/graph/extract.js.map +1 -0
  251. package/dist/graph/fingerprint.d.ts +76 -0
  252. package/dist/graph/fingerprint.d.ts.map +1 -0
  253. package/dist/graph/fingerprint.js +160 -0
  254. package/dist/graph/fingerprint.js.map +1 -0
  255. package/dist/graph/generic.d.ts +74 -0
  256. package/dist/graph/generic.d.ts.map +1 -0
  257. package/dist/graph/generic.js +773 -0
  258. package/dist/graph/generic.js.map +1 -0
  259. package/dist/graph/invariants.d.ts +33 -0
  260. package/dist/graph/invariants.d.ts.map +1 -0
  261. package/dist/graph/invariants.js +52 -0
  262. package/dist/graph/invariants.js.map +1 -0
  263. package/dist/graph/load.d.ts +29 -0
  264. package/dist/graph/load.d.ts.map +1 -0
  265. package/dist/graph/load.js +97 -0
  266. package/dist/graph/load.js.map +1 -0
  267. package/dist/graph/lsp/client.d.ts +61 -0
  268. package/dist/graph/lsp/client.d.ts.map +1 -0
  269. package/dist/graph/lsp/client.js +217 -0
  270. package/dist/graph/lsp/client.js.map +1 -0
  271. package/dist/graph/lsp/enrich.d.ts +11 -0
  272. package/dist/graph/lsp/enrich.d.ts.map +1 -0
  273. package/dist/graph/lsp/enrich.js +163 -0
  274. package/dist/graph/lsp/enrich.js.map +1 -0
  275. package/dist/graph/lsp/registry.d.ts +22 -0
  276. package/dist/graph/lsp/registry.d.ts.map +1 -0
  277. package/dist/graph/lsp/registry.js +71 -0
  278. package/dist/graph/lsp/registry.js.map +1 -0
  279. package/dist/graph/map.d.ts +107 -0
  280. package/dist/graph/map.d.ts.map +1 -0
  281. package/dist/graph/map.js +239 -0
  282. package/dist/graph/map.js.map +1 -0
  283. package/dist/graph/markdown.d.ts +22 -0
  284. package/dist/graph/markdown.d.ts.map +1 -0
  285. package/dist/graph/markdown.js +143 -0
  286. package/dist/graph/markdown.js.map +1 -0
  287. package/dist/graph/native.d.ts +46 -0
  288. package/dist/graph/native.d.ts.map +1 -0
  289. package/dist/graph/native.js +169 -0
  290. package/dist/graph/native.js.map +1 -0
  291. package/dist/graph/queries/c.scm +13 -0
  292. package/dist/graph/queries/c_sharp.scm +19 -0
  293. package/dist/graph/queries/clojure.scm +58 -0
  294. package/dist/graph/queries/cpp.scm +23 -0
  295. package/dist/graph/queries/dart.scm +42 -0
  296. package/dist/graph/queries/elixir.scm +54 -0
  297. package/dist/graph/queries/gleam.scm +51 -0
  298. package/dist/graph/queries/java.scm +20 -0
  299. package/dist/graph/queries/kotlin.scm +43 -0
  300. package/dist/graph/queries/lua.scm +36 -0
  301. package/dist/graph/queries/nix.scm +32 -0
  302. package/dist/graph/queries/php.scm +40 -0
  303. package/dist/graph/queries/ruby.scm +65 -0
  304. package/dist/graph/queries/rust.scm +41 -0
  305. package/dist/graph/queries/scala.scm +66 -0
  306. package/dist/graph/queries/solidity.scm +43 -0
  307. package/dist/graph/queries/swift.scm +51 -0
  308. package/dist/graph/refresh.d.ts +106 -0
  309. package/dist/graph/refresh.d.ts.map +1 -0
  310. package/dist/graph/refresh.js +430 -0
  311. package/dist/graph/refresh.js.map +1 -0
  312. package/dist/graph/relations.d.ts +14 -0
  313. package/dist/graph/relations.d.ts.map +1 -0
  314. package/dist/graph/relations.js +8 -0
  315. package/dist/graph/relations.js.map +1 -0
  316. package/dist/graph/resolve.d.ts +17 -0
  317. package/dist/graph/resolve.d.ts.map +1 -0
  318. package/dist/graph/resolve.js +716 -0
  319. package/dist/graph/resolve.js.map +1 -0
  320. package/dist/graph/root.d.ts +11 -0
  321. package/dist/graph/root.d.ts.map +1 -0
  322. package/dist/graph/root.js +40 -0
  323. package/dist/graph/root.js.map +1 -0
  324. package/dist/graph/scopes.d.ts +40 -0
  325. package/dist/graph/scopes.d.ts.map +1 -0
  326. package/dist/graph/scopes.js +383 -0
  327. package/dist/graph/scopes.js.map +1 -0
  328. package/dist/graph/seed.d.ts +38 -0
  329. package/dist/graph/seed.d.ts.map +1 -0
  330. package/dist/graph/seed.js +229 -0
  331. package/dist/graph/seed.js.map +1 -0
  332. package/dist/graph/source-files.d.ts +46 -0
  333. package/dist/graph/source-files.d.ts.map +1 -0
  334. package/dist/graph/source-files.js +118 -0
  335. package/dist/graph/source-files.js.map +1 -0
  336. package/dist/graph/traverse-cli.d.ts +55 -0
  337. package/dist/graph/traverse-cli.d.ts.map +1 -0
  338. package/dist/graph/traverse-cli.js +189 -0
  339. package/dist/graph/traverse-cli.js.map +1 -0
  340. package/dist/graph/traverse.d.ts +112 -0
  341. package/dist/graph/traverse.d.ts.map +1 -0
  342. package/dist/graph/traverse.js +192 -0
  343. package/dist/graph/traverse.js.map +1 -0
  344. package/dist/graph/types.d.ts +78 -0
  345. package/dist/graph/types.d.ts.map +1 -0
  346. package/dist/graph/types.js +14 -0
  347. package/dist/graph/types.js.map +1 -0
  348. package/dist/graph/wasm-runtime.d.ts +19 -0
  349. package/dist/graph/wasm-runtime.d.ts.map +1 -0
  350. package/dist/graph/wasm-runtime.js +38 -0
  351. package/dist/graph/wasm-runtime.js.map +1 -0
  352. package/dist/graph/workspace-cli.d.ts +56 -0
  353. package/dist/graph/workspace-cli.d.ts.map +1 -0
  354. package/dist/graph/workspace-cli.js +111 -0
  355. package/dist/graph/workspace-cli.js.map +1 -0
  356. package/dist/graph/workspace.d.ts +172 -0
  357. package/dist/graph/workspace.d.ts.map +1 -0
  358. package/dist/graph/workspace.js +714 -0
  359. package/dist/graph/workspace.js.map +1 -0
  360. package/dist/graph/write.d.ts +13 -0
  361. package/dist/graph/write.d.ts.map +1 -0
  362. package/dist/graph/write.js +86 -0
  363. package/dist/graph/write.js.map +1 -0
  364. package/dist/hosts/antigravity.d.ts +14 -0
  365. package/dist/hosts/antigravity.d.ts.map +1 -0
  366. package/dist/hosts/antigravity.js +59 -0
  367. package/dist/hosts/antigravity.js.map +1 -0
  368. package/dist/hosts/auto.d.ts +37 -0
  369. package/dist/hosts/auto.d.ts.map +1 -0
  370. package/dist/hosts/auto.js +141 -0
  371. package/dist/hosts/auto.js.map +1 -0
  372. package/dist/hosts/claude-global.d.ts +72 -0
  373. package/dist/hosts/claude-global.d.ts.map +1 -0
  374. package/dist/hosts/claude-global.js +230 -0
  375. package/dist/hosts/claude-global.js.map +1 -0
  376. package/dist/hosts/config-write.d.ts +36 -0
  377. package/dist/hosts/config-write.d.ts.map +1 -0
  378. package/dist/hosts/config-write.js +64 -0
  379. package/dist/hosts/config-write.js.map +1 -0
  380. package/dist/hosts/init.d.ts +28 -0
  381. package/dist/hosts/init.d.ts.map +1 -0
  382. package/dist/hosts/init.js +89 -0
  383. package/dist/hosts/init.js.map +1 -0
  384. package/dist/hosts/instructions.d.ts +14 -0
  385. package/dist/hosts/instructions.d.ts.map +1 -0
  386. package/dist/hosts/instructions.js +95 -0
  387. package/dist/hosts/instructions.js.map +1 -0
  388. package/dist/hosts/mcp-config.d.ts +78 -0
  389. package/dist/hosts/mcp-config.d.ts.map +1 -0
  390. package/dist/hosts/mcp-config.js +251 -0
  391. package/dist/hosts/mcp-config.js.map +1 -0
  392. package/dist/hosts/plan.d.ts +32 -0
  393. package/dist/hosts/plan.d.ts.map +1 -0
  394. package/dist/hosts/plan.js +73 -0
  395. package/dist/hosts/plan.js.map +1 -0
  396. package/dist/hosts/registry.d.ts +41 -0
  397. package/dist/hosts/registry.d.ts.map +1 -0
  398. package/dist/hosts/registry.js +164 -0
  399. package/dist/hosts/registry.js.map +1 -0
  400. package/dist/hosts/retract.d.ts +47 -0
  401. package/dist/hosts/retract.d.ts.map +1 -0
  402. package/dist/hosts/retract.js +520 -0
  403. package/dist/hosts/retract.js.map +1 -0
  404. package/dist/hosts/sections.d.ts +47 -0
  405. package/dist/hosts/sections.d.ts.map +1 -0
  406. package/dist/hosts/sections.js +127 -0
  407. package/dist/hosts/sections.js.map +1 -0
  408. package/dist/index.d.ts +41 -0
  409. package/dist/index.d.ts.map +1 -0
  410. package/dist/index.js +32 -0
  411. package/dist/index.js.map +1 -0
  412. package/dist/ingest/fs.d.ts +79 -0
  413. package/dist/ingest/fs.d.ts.map +1 -0
  414. package/dist/ingest/fs.js +306 -0
  415. package/dist/ingest/fs.js.map +1 -0
  416. package/dist/init-guard.d.ts +16 -0
  417. package/dist/init-guard.d.ts.map +1 -0
  418. package/dist/init-guard.js +27 -0
  419. package/dist/init-guard.js.map +1 -0
  420. package/dist/mcp/instructions.d.ts +5 -0
  421. package/dist/mcp/instructions.d.ts.map +1 -0
  422. package/dist/mcp/instructions.js +64 -0
  423. package/dist/mcp/instructions.js.map +1 -0
  424. package/dist/mcp/kept-listing.d.ts +27 -0
  425. package/dist/mcp/kept-listing.d.ts.map +1 -0
  426. package/dist/mcp/kept-listing.js +63 -0
  427. package/dist/mcp/kept-listing.js.map +1 -0
  428. package/dist/mcp/server.d.ts +4 -0
  429. package/dist/mcp/server.d.ts.map +1 -0
  430. package/dist/mcp/server.js +147 -0
  431. package/dist/mcp/server.js.map +1 -0
  432. package/dist/mcp/tool-names.d.ts +27 -0
  433. package/dist/mcp/tool-names.d.ts.map +1 -0
  434. package/dist/mcp/tool-names.js +47 -0
  435. package/dist/mcp/tool-names.js.map +1 -0
  436. package/dist/mcp/tools.d.ts +22 -0
  437. package/dist/mcp/tools.d.ts.map +1 -0
  438. package/dist/mcp/tools.js +440 -0
  439. package/dist/mcp/tools.js.map +1 -0
  440. package/dist/node-version.d.ts +15 -0
  441. package/dist/node-version.d.ts.map +1 -0
  442. package/dist/node-version.js +23 -0
  443. package/dist/node-version.js.map +1 -0
  444. package/dist/search/grep-cli.d.ts +35 -0
  445. package/dist/search/grep-cli.d.ts.map +1 -0
  446. package/dist/search/grep-cli.js +115 -0
  447. package/dist/search/grep-cli.js.map +1 -0
  448. package/dist/search/grep.d.ts +60 -0
  449. package/dist/search/grep.d.ts.map +1 -0
  450. package/dist/search/grep.js +143 -0
  451. package/dist/search/grep.js.map +1 -0
  452. package/dist/search/ignored-code.d.ts +9 -0
  453. package/dist/search/ignored-code.d.ts.map +1 -0
  454. package/dist/search/ignored-code.js +73 -0
  455. package/dist/search/ignored-code.js.map +1 -0
  456. package/dist/search/user-regexp.d.ts +26 -0
  457. package/dist/search/user-regexp.d.ts.map +1 -0
  458. package/dist/search/user-regexp.js +150 -0
  459. package/dist/search/user-regexp.js.map +1 -0
  460. package/dist/telemetry/contract.d.ts +117 -0
  461. package/dist/telemetry/contract.d.ts.map +1 -0
  462. package/dist/telemetry/contract.js +341 -0
  463. package/dist/telemetry/contract.js.map +1 -0
  464. package/dist/telemetry/flush.d.ts +21 -0
  465. package/dist/telemetry/flush.d.ts.map +1 -0
  466. package/dist/telemetry/flush.js +85 -0
  467. package/dist/telemetry/flush.js.map +1 -0
  468. package/dist/telemetry/gate.d.ts +30 -0
  469. package/dist/telemetry/gate.d.ts.map +1 -0
  470. package/dist/telemetry/gate.js +81 -0
  471. package/dist/telemetry/gate.js.map +1 -0
  472. package/dist/telemetry/identity.d.ts +40 -0
  473. package/dist/telemetry/identity.d.ts.map +1 -0
  474. package/dist/telemetry/identity.js +80 -0
  475. package/dist/telemetry/identity.js.map +1 -0
  476. package/dist/telemetry/index.d.ts +18 -0
  477. package/dist/telemetry/index.d.ts.map +1 -0
  478. package/dist/telemetry/index.js +16 -0
  479. package/dist/telemetry/index.js.map +1 -0
  480. package/dist/telemetry/key.d.ts +21 -0
  481. package/dist/telemetry/key.d.ts.map +1 -0
  482. package/dist/telemetry/key.js +49 -0
  483. package/dist/telemetry/key.js.map +1 -0
  484. package/dist/telemetry/notice.d.ts +19 -0
  485. package/dist/telemetry/notice.d.ts.map +1 -0
  486. package/dist/telemetry/notice.js +93 -0
  487. package/dist/telemetry/notice.js.map +1 -0
  488. package/dist/telemetry/queue.d.ts +35 -0
  489. package/dist/telemetry/queue.d.ts.map +1 -0
  490. package/dist/telemetry/queue.js +162 -0
  491. package/dist/telemetry/queue.js.map +1 -0
  492. package/dist/telemetry/send.d.ts +19 -0
  493. package/dist/telemetry/send.d.ts.map +1 -0
  494. package/dist/telemetry/send.js +84 -0
  495. package/dist/telemetry/send.js.map +1 -0
  496. package/dist/telemetry/sessions.d.ts +25 -0
  497. package/dist/telemetry/sessions.d.ts.map +1 -0
  498. package/dist/telemetry/sessions.js +104 -0
  499. package/dist/telemetry/sessions.js.map +1 -0
  500. package/dist/telemetry/track.d.ts +62 -0
  501. package/dist/telemetry/track.d.ts.map +1 -0
  502. package/dist/telemetry/track.js +143 -0
  503. package/dist/telemetry/track.js.map +1 -0
  504. package/dist/upkeep-run.d.ts +22 -0
  505. package/dist/upkeep-run.d.ts.map +1 -0
  506. package/dist/upkeep-run.js +85 -0
  507. package/dist/upkeep-run.js.map +1 -0
  508. package/dist/upkeep.d.ts +127 -0
  509. package/dist/upkeep.d.ts.map +1 -0
  510. package/dist/upkeep.js +252 -0
  511. package/dist/upkeep.js.map +1 -0
  512. package/dist/util/actions-folder.d.ts +2 -0
  513. package/dist/util/actions-folder.d.ts.map +1 -0
  514. package/dist/util/actions-folder.js +9 -0
  515. package/dist/util/actions-folder.js.map +1 -0
  516. package/dist/util/browser.d.ts +3 -0
  517. package/dist/util/browser.d.ts.map +1 -0
  518. package/dist/util/browser.js +14 -0
  519. package/dist/util/browser.js.map +1 -0
  520. package/dist/util/child-process.d.ts +15 -0
  521. package/dist/util/child-process.d.ts.map +1 -0
  522. package/dist/util/child-process.js +15 -0
  523. package/dist/util/child-process.js.map +1 -0
  524. package/dist/util/front-matter.d.ts +46 -0
  525. package/dist/util/front-matter.d.ts.map +1 -0
  526. package/dist/util/front-matter.js +113 -0
  527. package/dist/util/front-matter.js.map +1 -0
  528. package/dist/util/id.d.ts +7 -0
  529. package/dist/util/id.d.ts.map +1 -0
  530. package/dist/util/id.js +14 -0
  531. package/dist/util/id.js.map +1 -0
  532. package/dist/util/paths.d.ts +29 -0
  533. package/dist/util/paths.d.ts.map +1 -0
  534. package/dist/util/paths.js +71 -0
  535. package/dist/util/paths.js.map +1 -0
  536. package/dist/util/private-file.d.ts +14 -0
  537. package/dist/util/private-file.d.ts.map +1 -0
  538. package/dist/util/private-file.js +82 -0
  539. package/dist/util/private-file.js.map +1 -0
  540. package/dist/util/source.d.ts +4 -0
  541. package/dist/util/source.d.ts.map +1 -0
  542. package/dist/util/source.js +12 -0
  543. package/dist/util/source.js.map +1 -0
  544. package/dist/util/spinner.d.ts +15 -0
  545. package/dist/util/spinner.d.ts.map +1 -0
  546. package/dist/util/spinner.js +52 -0
  547. package/dist/util/spinner.js.map +1 -0
  548. package/dist/util/state.d.ts +120 -0
  549. package/dist/util/state.d.ts.map +1 -0
  550. package/dist/util/state.js +264 -0
  551. package/dist/util/state.js.map +1 -0
  552. package/dist/vendor/grammars/tree-sitter-go.LICENSE +21 -0
  553. package/dist/vendor/grammars/tree-sitter-go.wasm +0 -0
  554. package/dist/vendor/grammars/tree-sitter-java.LICENSE +21 -0
  555. package/dist/vendor/grammars/tree-sitter-java.wasm +0 -0
  556. package/dist/vendor/grammars/tree-sitter-kotlin.LICENSE +9 -0
  557. package/dist/vendor/grammars/tree-sitter-kotlin.wasm +0 -0
  558. package/dist/vendor/grammars/tree-sitter-php.LICENSE +22 -0
  559. package/dist/vendor/grammars/tree-sitter-php.wasm +0 -0
  560. package/dist/vendor/grammars/tree-sitter-python.LICENSE +21 -0
  561. package/dist/vendor/grammars/tree-sitter-python.wasm +0 -0
  562. package/dist/vendor/grammars/tree-sitter-r.LICENSE +9 -0
  563. package/dist/vendor/grammars/tree-sitter-r.wasm +0 -0
  564. package/dist/vendor/grammars/tree-sitter-swift.LICENSE +21 -0
  565. package/dist/vendor/grammars/tree-sitter-swift.wasm +0 -0
  566. package/dist/vendor/grammars/tree-sitter-tsx.wasm +0 -0
  567. package/dist/vendor/grammars/tree-sitter-typescript.LICENSE +21 -0
  568. package/dist/vendor/grammars/tree-sitter-typescript.wasm +0 -0
  569. package/dist/viewer/app.js +2 -0
  570. package/dist/viewer/index.html +49 -0
  571. package/dist/viewer/style.css +154 -0
  572. package/dist/viz/assemble.d.ts +83 -0
  573. package/dist/viz/assemble.d.ts.map +1 -0
  574. package/dist/viz/assemble.js +101 -0
  575. package/dist/viz/assemble.js.map +1 -0
  576. package/dist/viz/export.d.ts +39 -0
  577. package/dist/viz/export.d.ts.map +1 -0
  578. package/dist/viz/export.js +98 -0
  579. package/dist/viz/export.js.map +1 -0
  580. package/dist/viz/serve.d.ts +13 -0
  581. package/dist/viz/serve.d.ts.map +1 -0
  582. package/dist/viz/serve.js +130 -0
  583. package/dist/viz/serve.js.map +1 -0
  584. package/package.json +115 -4
  585. package/scripts/build-grammar-wasm.mjs +112 -0
  586. package/scripts/build-viewer.mjs +44 -0
  587. package/scripts/graph-quality.mjs +117 -0
  588. package/scripts/pack-trail.mjs +53 -0
  589. package/scripts/postinstall.mjs +65 -0
  590. package/scripts/run-tests.mjs +72 -0
  591. package/scripts/stamp-telemetry-key.mjs +56 -0
  592. package/scripts/tally-audit.mjs +140 -0
  593. package/scripts/vendor-grammars.mjs +53 -0
@@ -0,0 +1,716 @@
1
+ /**
2
+ * Resolve {@link RawEdge} intents into concrete {@link EdgeV1} edges by matching
3
+ * names/specifiers against the whole-repo node index.
4
+ *
5
+ * Confidence is a two-tier provenance model:
6
+ * - `extracted`: the target is certain — a match within the same file, an
7
+ * import specifier, or a structural containment.
8
+ * - `inferred`: a bare function target was resolved by a unique name match
9
+ * across files, which name-shadowing could in principle fool.
10
+ * Ambiguous cross-file matches (a name defined in several files) are dropped
11
+ * rather than guessed. Member calls are stricter: they require a receiver type
12
+ * and owner-qualified method match because a unique bare method name says
13
+ * nothing about the receiver.
14
+ */
15
+ import { posix } from "node:path";
16
+ import { toPosixPath } from "../util/paths.js";
17
+ import { languageOf } from "./extract.js";
18
+ import { genericLangOf } from "./generic.js";
19
+ const IMPORT_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs", ".py"];
20
+ /** C/C++ source + header extensions, for resolving `#include` targets. */
21
+ const C_EXT = /\.(c|h|cc|cpp|cxx|hpp|hh|hxx|inl|ipp|c\+\+|h\+\+)$/i;
22
+ /** Python source + stub extensions, for the constructor-call fallback below. */
23
+ const PY_EXT = /\.pyi?$/i;
24
+ /** What a bare Python call falls back to when no function of that name exists:
25
+ * construction. Only `class` — Python enums, dataclasses and NamedTuples are all
26
+ * classes, so no other kind is reachable this way. */
27
+ const PY_CTOR_KINDS = ["class"];
28
+ /** Swift is Python's case with more nominal kinds: `Animal(legs: 4)` is an ordinary
29
+ * call node with no `new` to mark construction, and struct/enum initializers are as
30
+ * routine as class ones (a struct gets a memberwise init for free). Same fallback
31
+ * shape — types are tried only once functions (and methods, see extract.ts's
32
+ * implicit-self widening) have found nothing. */
33
+ const SWIFT_EXT = /\.swift$/i;
34
+ const SWIFT_CTOR_KINDS = ["class", "struct", "enum"];
35
+ /**
36
+ * Languages whose symbols can genuinely reach each other. A call edge may not
37
+ * cross a family boundary.
38
+ *
39
+ * This exists because name resolution is repo-wide and used to be language-blind.
40
+ * A Go file calling the builtin `make(...)` has nothing in the repo to resolve
41
+ * against, so the unique-global fallback below matched a TypeScript helper named
42
+ * `make` in a frontend test file — and then every `make(map[...])` in the backend
43
+ * became an edge into that file. One symbol collected 1040 in-edges across 476
44
+ * files, and any pull request touching that test dragged the entire Go backend
45
+ * into its blast radius. Uniqueness is what made it fire: the rarer the collision,
46
+ * the more confident the old code was that it had found the right target.
47
+ *
48
+ * Only real interop is grouped here. TS/TSX/JS import each other freely; Kotlin,
49
+ * Scala and Clojure compile against Java on one classpath; C and C++ share
50
+ * headers. Everything else stands alone.
51
+ */
52
+ const FAMILIES = [
53
+ ["typescript", "tsx"],
54
+ ["java", "kotlin", "scala", "clojure"],
55
+ ["c", "cpp"],
56
+ ];
57
+ const FAMILY_OF = new Map();
58
+ for (const group of FAMILIES)
59
+ for (const lang of group)
60
+ FAMILY_OF.set(lang, group[0]);
61
+ /**
62
+ * The language family a path belongs to, or null when no tier claims the file.
63
+ * A language of its own is its own family, so the common case needs no entry above.
64
+ */
65
+ function familyOf(path) {
66
+ const lang = languageOf(path) ?? genericLangOf(path)?.name ?? null;
67
+ if (!lang)
68
+ return null;
69
+ return FAMILY_OF.get(lang) ?? lang;
70
+ }
71
+ /**
72
+ * Could a reference in `file` reach a definition in `candidatePath`?
73
+ *
74
+ * An unknown family never filters: absence of data is not evidence of a mismatch,
75
+ * and refusing edges for every extension graft cannot name would lose real ones.
76
+ */
77
+ function reachable(file, candidatePath) {
78
+ const from = familyOf(file);
79
+ if (from === null)
80
+ return true;
81
+ const to = familyOf(candidatePath);
82
+ return to === null || from === to;
83
+ }
84
+ export function resolveEdges(nodes, rawEdges, opts = {}) {
85
+ const byId = new Map(nodes.map((n) => [n.id, n]));
86
+ const globalName = new Map();
87
+ const perFileName = new Map();
88
+ // Owner-qualified method index: "Owner.method" → candidate method nodes, for
89
+ // typed member-call resolution (recvType + name → a specific class's method).
90
+ const ownerMethod = new Map();
91
+ // Go package resolution: dir (posix) → its `.go` file node ids, for import mapping.
92
+ const goFilesByDir = new Map();
93
+ // Java package resolution: a file's package-path suffix (`com/acme/Foo.java`) → its
94
+ // file node ids. A Java import names a type by its fully-qualified name, which by
95
+ // language convention mirrors the directory path under whatever source root the
96
+ // project uses (`src/main/java/`, `src/`, …) — so the suffix is the portable key.
97
+ const javaFilesBySuffix = new Map();
98
+ // C/C++ header resolution: a file's path-suffix (`net/socket.h`, `socket.h`) → its
99
+ // file node ids, so an `#include` reached through an `-I` dir (not relative to the
100
+ // including file) still resolves to the in-repo header when the suffix is unique.
101
+ const cFilesBySuffix = new Map();
102
+ // Rust crate roots: the directory holding a `lib.rs` or `main.rs`. A `use crate::a::b`
103
+ // resolves to `<crate root>/a/b.rs` (or `.../a/b/mod.rs`), relative to the crate the
104
+ // importing file belongs to — so a workspace with several crates stays unambiguous.
105
+ const rustCrateRoots = [];
106
+ // PHP class resolution: a file's path-suffix (`Models/User.php`, `User.php`) → its file
107
+ // node ids. A `use App\Models\User` names a PSR-4 class whose file mirrors the namespace
108
+ // tail under some (unknown) source root, so the suffix is the portable key.
109
+ const phpFilesBySuffix = new Map();
110
+ // Gleam module resolution: a file's path-suffix (`app/thing.gleam`) → its file
111
+ // node ids. A Gleam package roots every module at its own `src/` (or `test/`),
112
+ // so an `import app/thing` is exactly that suffix under some unknown root.
113
+ const gleamFilesBySuffix = new Map();
114
+ const hasGoModules = !!opts.goModules?.length;
115
+ for (const n of nodes) {
116
+ if (n.kind === "file") {
117
+ if (hasGoModules && n.path.endsWith(".go")) {
118
+ const dir = posix.dirname(toPosixPath(n.path));
119
+ push(goFilesByDir, dir, n.id);
120
+ }
121
+ if (n.path.endsWith(".java")) {
122
+ // Index every directory-boundary suffix, since the source root is unknown:
123
+ // `src/main/java/com/acme/Foo.java` is reachable as `com/acme/Foo.java`,
124
+ // `acme/Foo.java`, and so on. The import's own FQN picks the right depth.
125
+ const parts = toPosixPath(n.path).split("/");
126
+ for (let i = 0; i < parts.length; i++)
127
+ push(javaFilesBySuffix, parts.slice(i).join("/"), n.id);
128
+ }
129
+ if (C_EXT.test(n.path)) {
130
+ const parts = toPosixPath(n.path).split("/");
131
+ for (let i = 0; i < parts.length; i++)
132
+ push(cFilesBySuffix, parts.slice(i).join("/"), n.id);
133
+ }
134
+ if (n.path.endsWith(".php")) {
135
+ const parts = toPosixPath(n.path).split("/");
136
+ for (let i = 0; i < parts.length; i++)
137
+ push(phpFilesBySuffix, parts.slice(i).join("/"), n.id);
138
+ }
139
+ if (n.path.endsWith(".gleam")) {
140
+ const parts = toPosixPath(n.path).split("/");
141
+ for (let i = 0; i < parts.length; i++)
142
+ push(gleamFilesBySuffix, parts.slice(i).join("/"), n.id);
143
+ }
144
+ {
145
+ const p = toPosixPath(n.path);
146
+ if (p === "lib.rs" || p === "main.rs")
147
+ rustCrateRoots.push("");
148
+ else if (p.endsWith("/lib.rs") || p.endsWith("/main.rs"))
149
+ rustCrateRoots.push(posix.dirname(p));
150
+ }
151
+ continue;
152
+ }
153
+ push(globalName, n.name, n);
154
+ let fileMap = perFileName.get(n.path);
155
+ if (!fileMap)
156
+ perFileName.set(n.path, (fileMap = new Map()));
157
+ push(fileMap, n.name, n);
158
+ if (n.kind === "method") {
159
+ const owner = n.owner ?? ownerFromMethodId(n.id);
160
+ if (owner)
161
+ push(ownerMethod, `${owner}.${n.name}`, n);
162
+ }
163
+ }
164
+ // classParents: class/interface name → its declared base-class names, from raw
165
+ // `extends` edges (source id's own name → the base name). Used to walk up an
166
+ // inheritance chain when a receiver's own type has no matching method.
167
+ const classParents = new Map();
168
+ for (const e of rawEdges) {
169
+ if (e.relation !== "extends" || !e.name)
170
+ continue;
171
+ // The declaring class's own bare name — read from its node (keyed by n.name, set
172
+ // once at mint time) rather than re-derived by slicing e.source, which breaks once
173
+ // ids can carry a dedup ordinal (A3's `Cache~2`).
174
+ const ownName = byId.get(e.source)?.name;
175
+ if (!ownName)
176
+ continue;
177
+ push(classParents, ownName, e.name);
178
+ }
179
+ // classTraits: class name → trait names from raw `implements` edges in PHP files.
180
+ // PHP models `use SomeTrait;` as implements; trait methods live on the trait owner,
181
+ // not the using class, so resolveTypedMember walks these after the class lookup fails.
182
+ const classTraits = new Map();
183
+ for (const e of rawEdges) {
184
+ if (e.relation !== "implements" || !e.name || !e.file.endsWith(".php"))
185
+ continue;
186
+ const ownName = byId.get(e.source)?.name;
187
+ if (!ownName)
188
+ continue;
189
+ push(classTraits, ownName, e.name);
190
+ }
191
+ const out = [];
192
+ const seen = new Set();
193
+ const add = (source, target, relation, confidence) => {
194
+ const key = `${source}\0${relation}\0${target}`;
195
+ if (seen.has(key))
196
+ return;
197
+ seen.add(key);
198
+ out.push({ source, target, relation, confidence });
199
+ };
200
+ for (const e of rawEdges) {
201
+ if (e.relation === "contains" && e.targetId) {
202
+ add(e.source, e.targetId, "contains", "extracted");
203
+ }
204
+ else if (e.relation === "imports" && e.specifier) {
205
+ const target = hasGoModules && e.file.endsWith(".go")
206
+ ? resolveGoImport(e.specifier, opts.goModules, goFilesByDir)
207
+ : e.file.endsWith(".java")
208
+ ? resolveJavaImport(e.specifier, javaFilesBySuffix)
209
+ : C_EXT.test(e.file)
210
+ ? resolveCInclude(e.specifier, e.file, byId, cFilesBySuffix)
211
+ : e.file.endsWith(".rs")
212
+ ? resolveRustUse(e.specifier, e.file, byId, rustCrateRoots)
213
+ : e.file.endsWith(".php")
214
+ ? resolvePhpUse(e.specifier, phpFilesBySuffix)
215
+ : e.file.endsWith(".gleam")
216
+ ? resolveGleamImport(e.specifier, gleamFilesBySuffix)
217
+ : resolveImport(e.specifier, e.file, byId);
218
+ add(e.source, target, "imports", "extracted");
219
+ }
220
+ else if (e.relation === "extends" || e.relation === "implements") {
221
+ // `implements` also resolves to a `trait` — PHP models trait composition
222
+ // (`use SomeTrait;`) as an implements edge, and a trait is a valid target.
223
+ const kinds = e.relation === "implements" ? ["interface", "trait"] : ["class", "interface"];
224
+ const hit = resolveName(e.name, e.file, kinds, perFileName, globalName);
225
+ // an unresolved base is usually an external/imported type — keep the name.
226
+ add(e.source, hit?.id ?? e.name, e.relation, hit?.confidence ?? "inferred");
227
+ }
228
+ else if (e.relation === "references" && e.name) {
229
+ if (e.specifier) {
230
+ // A named import gives both halves needed for sound resolution: the module
231
+ // it came from and the exported name. Resolve inside that file only, so a
232
+ // same-named symbol elsewhere in the repo cannot become a false edge.
233
+ const targetFile = e.file.endsWith(".php")
234
+ ? resolvePhpUse(e.specifier, phpFilesBySuffix)
235
+ : e.file.endsWith(".gleam")
236
+ ? resolveGleamImport(e.specifier, gleamFilesBySuffix)
237
+ : resolveImport(e.specifier, e.file, byId);
238
+ if (!byId.has(targetFile))
239
+ continue; // external or unresolved module
240
+ const candidates = narrowGleamByKind(perFileName.get(targetFile)?.get(e.name) ?? [], e.file, TYPE_KINDS);
241
+ if (candidates.length === 1)
242
+ add(e.source, candidates[0].id, "references", "extracted");
243
+ }
244
+ else if (e.file.endsWith(".php") && byId.get(e.source)?.origin === "ast") {
245
+ // PHP attribute without a `use` import (same-file or globally unique class).
246
+ const refKinds = ["class", "interface", "trait", "enum"];
247
+ const hit = resolveName(e.name, e.file, refKinds, perFileName, globalName);
248
+ if (hit && hit.id !== e.source)
249
+ add(e.source, hit.id, "references", hit.confidence);
250
+ }
251
+ else if (e.file.endsWith(".java") && byId.get(e.source)?.origin === "ast") {
252
+ // Java annotation without a specifier (same-file or globally unique
253
+ // `@interface`). Annotation types are `interface` kind — a class of the
254
+ // same name is not a match, so `@Entity` cannot collapse onto an in-repo
255
+ // `class Entity` (#103). Kind alone still cannot tell `@interface Service`
256
+ // from `interface Service`, so only accept a candidate whose header
257
+ // contains the literal `@interface` (`includes`, not `startsWith`: a
258
+ // meta-annotated type is `@Documented @Retention(...) public @interface
259
+ // JsonAdapter`). Unresolved targets keep the bare name, matching
260
+ // heritage, rather than dropping the way PHP attributes do.
261
+ const refKinds = ["interface"];
262
+ const hit = resolveName(e.name, e.file, refKinds, perFileName, globalName);
263
+ const anno = hit ? byId.get(hit.id) : undefined;
264
+ if (hit && hit.id !== e.source && anno?.signature?.includes("@interface"))
265
+ add(e.source, hit.id, "references", hit.confidence);
266
+ else
267
+ add(e.source, e.name, "references", "inferred");
268
+ }
269
+ else if (byId.get(e.source)?.origin === "generic") {
270
+ // Breadth tier: a bare-name structural reference (extends / implements /
271
+ // object-creation / module alias) the grammar marked but cannot type. Resolve
272
+ // to a type-like definition, drop-rather-than-guess, never a self-loop. Gated on
273
+ // generic origin so depth-tier references (which always carry a specifier) are
274
+ // provably untouched.
275
+ const refKinds = ["class", "interface", "struct", "enum", "type", "module"];
276
+ const hit = resolveName(e.name, e.file, refKinds, perFileName, globalName);
277
+ if (hit && hit.id !== e.source)
278
+ add(e.source, hit.id, "references", hit.confidence);
279
+ }
280
+ }
281
+ else if (e.relation === "calls") {
282
+ // Gleam (generic.ts's module pass): the call carries the module it targets —
283
+ // a qualified `list.map(…)` or a `{ … }`-imported bare name. That is both
284
+ // halves of a sound resolution, so look the name up in that module's file
285
+ // alone. A module that is not an in-repo file is the stdlib or a hex
286
+ // dependency: there is nothing to point at, and its labels (`map`, `try`,
287
+ // `new`) collide with in-repo names constantly, so the call drops.
288
+ if (e.specifier && e.file.endsWith(".gleam")) {
289
+ const targetFile = resolveGleamImport(e.specifier, gleamFilesBySuffix);
290
+ if (!byId.has(targetFile))
291
+ continue;
292
+ const candidates = narrowGleamByKind(perFileName.get(targetFile)?.get(e.name) ?? [], e.file, CALLABLE_KINDS);
293
+ if (candidates.length === 1)
294
+ add(e.source, candidates[0].id, "calls", "extracted");
295
+ continue;
296
+ }
297
+ if (e.viaMember) {
298
+ if (!e.recvType)
299
+ continue;
300
+ const hit = resolveTypedMember(e.recvType, e.name, e.file, ownerMethod, classParents, classTraits, e.argCount);
301
+ if (hit === "ambiguous")
302
+ continue; // drop — never guess past an ambiguous owner
303
+ if (hit) {
304
+ add(e.source, hit.id, "calls", hit.confidence);
305
+ continue;
306
+ }
307
+ // No owner-qualified match means the call is unresolved. A unique bare
308
+ // method name is not evidence that this receiver has that method — a
309
+ // name-fallback here was measured to HALVE call-edge precision (73%→37%
310
+ // vs a compiler-grade oracle) for a 3x count inflation, i.e. noise. See #35.
311
+ //
312
+ // One carve-out, which is NOT that fallback: a Swift `implicitSelf` edge
313
+ // carries two readings of one bare call — member (tried above, in
314
+ // Swift's own inner-scope-first order) and free function. Zero members
315
+ // on the whole owner chain means the call was a free-function call after
316
+ // all, so it falls through to bare-name resolution; an ambiguous member
317
+ // set has already dropped it above, and a resolved member never reaches
318
+ // here — a name defined as both member and free function yields the
319
+ // member edge alone, exactly as Swift dispatches it.
320
+ if (!e.implicitSelf)
321
+ continue;
322
+ }
323
+ // Every language's bare-name call is a free function, except R (Phase 4):
324
+ // an untyped `obj$method()` there sets e.kinds to also allow a "method"
325
+ // match — see extract.ts's calleeName R branch for why (R6 methods are
326
+ // never kind "function", so without this every such call would be
327
+ // unconditionally unresolvable rather than just occasionally ambiguous).
328
+ // Three cases, because "a bare call" means something different per tier:
329
+ //
330
+ // - generic (breadth tier): tags.scm captures ALL calls as bare names, since it
331
+ // cannot type a receiver. In method-heavy languages those target methods, so
332
+ // widen to methods — ONLY here, leaving depth-tier precision untouched (an
333
+ // ambiguous function-vs-method name still drops).
334
+ // - Java (depth tier): an implicit-`this` call is spelled as a member call in
335
+ // extract.ts, so the only bare call reaching here is `new Foo()`, whose target
336
+ // is a TYPE. Against the function index every constructor edge would drop.
337
+ // - everything else: functions, exactly as before.
338
+ //
339
+ // R (depth tier, Phase 4) sets `e.kinds` itself for an untyped `obj$method()`
340
+ // (see above), and that explicit choice wins over the per-tier default.
341
+ const srcOrigin = byId.get(e.source)?.origin;
342
+ const callKinds = e.kinds ??
343
+ (srcOrigin === "generic"
344
+ ? ["function", "method"]
345
+ : e.file.endsWith(".java")
346
+ ? ["class", "struct", "enum", "interface"]
347
+ : ["function"]);
348
+ let hit = resolveName(e.name, e.file, callKinds, perFileName, globalName);
349
+ // Python is the Java case without the `new` to mark it: `Widget()` is an
350
+ // ordinary call node, so a constructor edge dies against the function-only
351
+ // index. Java can widen to types outright; Python has free functions, so
352
+ // widening would trade real function edges for type ones. Hence a fallback,
353
+ // not a swap — types are tried only once functions have found nothing, and
354
+ // resolveName's same-file-then-unique-global rule still drops the ambiguous.
355
+ if (!hit && PY_EXT.test(e.file)) {
356
+ hit = resolveName(e.name, e.file, PY_CTOR_KINDS, perFileName, globalName);
357
+ }
358
+ if (!hit && SWIFT_EXT.test(e.file)) {
359
+ hit = resolveName(e.name, e.file, SWIFT_CTOR_KINDS, perFileName, globalName);
360
+ }
361
+ if (hit)
362
+ add(e.source, hit.id, "calls", hit.confidence); // drop unresolved calls (too noisy)
363
+ }
364
+ }
365
+ return out;
366
+ }
367
+ function push(map, key, val) {
368
+ const arr = map.get(key);
369
+ if (arr)
370
+ arr.push(val);
371
+ else
372
+ map.set(key, [val]);
373
+ }
374
+ /** Derive a method's owner from its dotted id when extract did not stamp `owner`
375
+ * (PHP trait/interface methods today). `app.php#Loggable.log` → `Loggable`. */
376
+ function ownerFromMethodId(id) {
377
+ const post = id.includes("#") ? id.split("#")[1] : id;
378
+ const segs = post.split(".");
379
+ return segs.length >= 2 ? segs[segs.length - 2] : undefined;
380
+ }
381
+ /**
382
+ * Resolve a bare symbol name: same-file match first (certain → `extracted`),
383
+ * else a unique cross-file match (→ `inferred`), else null (ambiguous/unknown).
384
+ */
385
+ function resolveName(name, file, kinds, perFileName, globalName) {
386
+ const local = (perFileName.get(file)?.get(name) ?? []).filter((n) => kinds.includes(n.kind));
387
+ // Same-file requires a UNIQUE match, exactly as the cross-file branch below does.
388
+ // Returning `local[0]` meant a file holding two same-named types (`Alpha.Builder` and
389
+ // `Beta.Builder`, `Alpha.Inner` and `Beta.Inner`) silently resolved to whichever came
390
+ // first in document order — and labelled it `extracted`, i.e. certain. That is the
391
+ // guess this module's header says it does not make.
392
+ if (local.length === 1)
393
+ return { id: local[0].id, confidence: "extracted" };
394
+ // Cross-file: also require a language that could actually reach this one.
395
+ // Without it a unique name match ANYWHERE in the repo wins, which is how a Go
396
+ // builtin ended up resolving into a TypeScript test — see FAMILIES above.
397
+ const global = (globalName.get(name) ?? []).filter((n) => kinds.includes(n.kind) && reachable(file, n.path));
398
+ if (global.length === 1)
399
+ return { id: global[0].id, confidence: "inferred" };
400
+ return null;
401
+ }
402
+ /**
403
+ * Resolve a typed member call (`recvType.name`) against the owner-qualified method
404
+ * index, walking the receiver's extends chain when its own type has no match.
405
+ *
406
+ * Returns:
407
+ * - `{ id, confidence }` — resolved: a single candidate at some owner level (or the
408
+ * same-file one among several).
409
+ * - `"ambiguous"` — several candidates at some owner level and none is same-file;
410
+ * per the inviolable philosophy we drop and stop rather than guess, and we do
411
+ * NOT continue up the chain past this level.
412
+ * - `null` — the whole chain (recvType + ancestors, breadth-first, depth ≤ 3,
413
+ * cycle-guarded) had zero candidates at every level.
414
+ */
415
+ /**
416
+ * Narrow an overload set to the candidates a call of `argCount` arguments could
417
+ * reach. Only Java emits `argCount`/`arity`, so for every other language this is
418
+ * the identity function and resolution is byte-for-byte what it was.
419
+ *
420
+ * Deliberately conservative in both directions:
421
+ * - A variadic candidate (`String... xs`) accepts anything from `arity - 1`
422
+ * upward, so it is never filtered out by count.
423
+ * - A candidate with no recorded arity (a graph built before this field) is
424
+ * kept, since absence of data is not evidence of a mismatch.
425
+ * - If narrowing leaves nothing, the ORIGINAL set is returned. An empty result
426
+ * would silently drop a real edge; handing the full set back lets the existing
427
+ * same-file / "ambiguous" logic make the call exactly as before.
428
+ */
429
+ function narrowByArity(candidates, argCount) {
430
+ if (argCount === undefined || candidates.length < 2)
431
+ return candidates;
432
+ const fits = candidates.filter((c) => {
433
+ if (c.arity === undefined)
434
+ return true;
435
+ return c.variadic ? argCount >= c.arity - 1 : c.arity === argCount;
436
+ });
437
+ return fits.length > 0 ? fits : candidates;
438
+ }
439
+ function resolveTypedMember(recvType, name, file, ownerMethod, classParents, classTraits, argCount) {
440
+ const MAX_DEPTH = 3;
441
+ const visited = new Set([recvType]);
442
+ let frontier = [recvType];
443
+ for (let depth = 0; depth <= MAX_DEPTH && frontier.length; depth++) {
444
+ for (const type of frontier) {
445
+ const all = ownerMethod.get(`${type}.${name}`)?.filter((c) => reachable(file, c.path));
446
+ if (all && all.length > 0) {
447
+ const candidates = narrowByArity(all, argCount);
448
+ if (candidates.length === 1) {
449
+ const c = candidates[0];
450
+ return { id: c.id, confidence: c.path === file ? "extracted" : "inferred" };
451
+ }
452
+ // Swift: several candidates surviving arity narrowing are a genuine
453
+ // overload set distinguished only by parameter TYPES (`save(Int)` vs
454
+ // `save(String)`), which this pass cannot read — the same-file tiebreak
455
+ // below would pick whichever overload appears first in the file and
456
+ // stamp it `extracted`, a confidently wrong edge. Drop instead.
457
+ if (SWIFT_EXT.test(file))
458
+ return "ambiguous";
459
+ const sameFile = candidates.find((c) => c.path === file);
460
+ if (sameFile)
461
+ return { id: sameFile.id, confidence: "extracted" };
462
+ return "ambiguous"; // several, none same-file — drop and stop
463
+ }
464
+ const traitHit = resolveTraitMember(type, name, file, ownerMethod, classTraits, argCount);
465
+ if (traitHit === "ambiguous")
466
+ return "ambiguous";
467
+ if (traitHit)
468
+ return traitHit;
469
+ }
470
+ const next = [];
471
+ for (const type of frontier) {
472
+ for (const parent of classParents.get(type) ?? []) {
473
+ if (visited.has(parent))
474
+ continue;
475
+ visited.add(parent);
476
+ next.push(parent);
477
+ }
478
+ }
479
+ frontier = next;
480
+ }
481
+ return null; // chain exhausted, no candidate anywhere
482
+ }
483
+ /** Resolve a member call against methods declared on PHP traits used by `type`. */
484
+ function resolveTraitMember(type, name, file, ownerMethod, classTraits, argCount) {
485
+ const traits = classTraits.get(type);
486
+ if (!traits?.length)
487
+ return null;
488
+ const matches = [];
489
+ for (const trait of traits) {
490
+ const all = ownerMethod.get(`${trait}.${name}`)?.filter((c) => reachable(file, c.path));
491
+ if (!all?.length)
492
+ continue;
493
+ matches.push(...narrowByArity(all, argCount));
494
+ }
495
+ if (matches.length === 0)
496
+ return null;
497
+ if (matches.length === 1) {
498
+ const c = matches[0];
499
+ return { id: c.id, confidence: c.path === file ? "extracted" : "inferred" };
500
+ }
501
+ return "ambiguous";
502
+ }
503
+ /**
504
+ * Resolve a module specifier to a file node id when it points inside the repo;
505
+ * otherwise return the raw specifier (external package or unresolved path).
506
+ */
507
+ function resolveImport(spec, file, byId) {
508
+ if (!spec.startsWith("."))
509
+ return spec;
510
+ // Belt-and-braces: `node.path` is posix by construction (`../util/paths.ts`),
511
+ // but this also accepts a hand-written or hand-edited graph.
512
+ const dir = posix.dirname(toPosixPath(file));
513
+ const base = posix.normalize(posix.join(dir, spec));
514
+ const noExt = base.replace(/\.(js|jsx|mjs|cjs|ts|tsx|py)$/, "");
515
+ const candidates = [
516
+ base,
517
+ ...IMPORT_EXTS.map((e) => noExt + e),
518
+ ...IMPORT_EXTS.map((e) => `${noExt}/index${e}`),
519
+ ];
520
+ for (const c of candidates)
521
+ if (byId.has(c))
522
+ return c;
523
+ return spec;
524
+ }
525
+ /**
526
+ * Resolve a Java import's fully-qualified type name to an in-repo file node;
527
+ * otherwise return the raw specifier (JDK or third-party type).
528
+ *
529
+ * Java names a *type*, not a path, and states no source root — `com.acme.Foo` may
530
+ * live under `src/main/java/`, `src/`, or a module dir. Matching on the path SUFFIX
531
+ * (`com/acme/Foo.java`) is therefore root-agnostic and needs no build-file parsing,
532
+ * which is what keeps this deterministic and dependency-free.
533
+ *
534
+ * `import static com.acme.Foo.bar` names a member, so when the full name misses, the
535
+ * last segment is dropped and the enclosing type retried. A wildcard (`com.acme.*`)
536
+ * names a package rather than one file and is deliberately left unresolved: picking a
537
+ * representative would invent an edge the source does not state.
538
+ *
539
+ * A suffix shared by two files (the same FQN under two source roots, e.g. a
540
+ * duplicated test tree) is ambiguous, so it stays unresolved rather than guessing.
541
+ */
542
+ function resolveJavaImport(spec, filesBySuffix) {
543
+ const hit = (fqn) => {
544
+ const suffix = `${fqn.split(".").join("/")}.java`;
545
+ const files = filesBySuffix.get(suffix);
546
+ return files && files.length === 1 ? files[0] : null;
547
+ };
548
+ const direct = hit(spec);
549
+ if (direct)
550
+ return direct;
551
+ // `import static a.b.C.member` → retry as `a.b.C`.
552
+ const dot = spec.lastIndexOf(".");
553
+ if (dot > 0) {
554
+ const enclosing = hit(spec.slice(0, dot));
555
+ if (enclosing)
556
+ return enclosing;
557
+ }
558
+ return spec;
559
+ }
560
+ /**
561
+ * Resolve a C/C++ `#include "path"` to an in-repo file node: relative to the including
562
+ * file first (the common case, and certain), else a UNIQUE path-suffix match — which
563
+ * covers a header reached through an `-I` include directory rather than a relative path.
564
+ * Anything ambiguous or not found stays the raw path (a system or out-of-repo header),
565
+ * never a guessed edge.
566
+ */
567
+ function resolveCInclude(spec, file, byId, bySuffix) {
568
+ const dir = posix.dirname(toPosixPath(file));
569
+ const relJoin = posix.normalize(posix.join(dir, spec));
570
+ if (byId.has(relJoin))
571
+ return relJoin; // relative to the including file — certain
572
+ const hits = bySuffix.get(spec.replace(/^\.?\//, ""));
573
+ if (hits && hits.length === 1)
574
+ return hits[0]; // unique suffix — an -I-reached header
575
+ return spec; // system/out-of-repo/ambiguous — keep the string, do not guess
576
+ }
577
+ /**
578
+ * Resolve a PHP `use` fully-qualified name (`App\Models\User`) to the in-repo class file.
579
+ * PSR-4 maps the namespace to a directory under some (unknown) source root and the class
580
+ * to a `<Class>.php` file, so we match the longest namespace-tail suffix that names exactly
581
+ * one file: `App/Models/User.php`, then `Models/User.php`, then `User.php`. The longest
582
+ * unique match wins; an ambiguous tail or a vendor/out-of-repo class stays the raw name.
583
+ */
584
+ function resolvePhpUse(fqn, bySuffix) {
585
+ const parts = fqn.split("\\").filter(Boolean);
586
+ if (parts.length === 0)
587
+ return fqn;
588
+ for (let i = 0; i < parts.length; i++) {
589
+ const suffix = `${parts.slice(i).join("/")}.php`;
590
+ const hits = bySuffix.get(suffix);
591
+ if (hits && hits.length === 1)
592
+ return hits[0];
593
+ if (hits && hits.length > 1)
594
+ break; // ambiguous at the most specific level — do not guess
595
+ }
596
+ return fqn;
597
+ }
598
+ const CALLABLE_KINDS = ["function", "method"];
599
+ const TYPE_KINDS = ["class", "interface", "struct", "enum", "type", "module"];
600
+ /**
601
+ * A Gleam type and its constructor idiomatically share a name — `pub type Cfg {
602
+ * Cfg(…) }` defines both — so a module-scoped lookup finds two candidates and
603
+ * would drop the edge for the single most common shape in the language. The use
604
+ * site says which one it meant: `thing.Cfg(…)` applies the constructor,
605
+ * `x: thing.Cfg` annotates the type. Narrow by kind ONLY when the name is
606
+ * genuinely doubled, so a lone match still resolves whatever its kind, and only
607
+ * for Gleam, leaving every other language's specifier lookup untouched.
608
+ */
609
+ function narrowGleamByKind(candidates, file, kinds) {
610
+ if (candidates.length <= 1 || !file.endsWith(".gleam"))
611
+ return candidates;
612
+ const narrowed = candidates.filter((c) => kinds.includes(c.kind));
613
+ return narrowed.length ? narrowed : candidates;
614
+ }
615
+ /**
616
+ * Resolve a Gleam `import app/thing` to the in-repo module file. A Gleam package
617
+ * roots every module at its `src/` (tests at `test/`), so the import path IS the
618
+ * file's path-suffix — `app/thing` → `…/app/thing.gleam` — with no per-package
619
+ * config to consult. Only a unique match resolves; the stdlib, a hex dependency,
620
+ * and a module name that two packages in one repo both define all stay the raw
621
+ * module path, so an import never becomes a guessed file edge.
622
+ */
623
+ function resolveGleamImport(spec, bySuffix) {
624
+ const file = `${toPosixPath(spec)}.gleam`;
625
+ const hits = bySuffix.get(file);
626
+ // A file's own full path names it exactly (generic.ts scopes same-file names
627
+ // this way), even when a nested package has a file ending in the same path.
628
+ if (hits?.includes(file))
629
+ return file;
630
+ return hits && hits.length === 1 ? hits[0] : spec;
631
+ }
632
+ /**
633
+ * Resolve a Rust `crate`-relative module path (`crate/a/b`, from `use crate::a::b::Item`)
634
+ * to the in-repo module file — `<crate root>/a/b.rs` or `<crate root>/a/b/mod.rs`, where
635
+ * the crate root is the `lib.rs`/`main.rs` directory the importing file lives under. The
636
+ * per-file crate root keeps a multi-crate workspace unambiguous. Not found or ambiguous
637
+ * (two roots, both `a/b.rs` and `a/b/mod.rs`) stays a `crate::…` string — never a guess.
638
+ */
639
+ function resolveRustUse(spec, file, byId, crateRoots) {
640
+ const full = spec.replace(/^crate\/?/, ""); // "crate/a/b/Item" → "a/b/Item"; "crate" → ""
641
+ const fpath = toPosixPath(file);
642
+ // the crate this file belongs to: the longest root that contains it (workspace-safe)
643
+ const owning = crateRoots
644
+ .filter((r) => r === "" ? true : fpath === r || fpath.startsWith(`${r}/`))
645
+ .sort((a, b) => b.length - a.length);
646
+ // No owning crate root (e.g. an integration test under `tests/`, whose `crate::` is the
647
+ // TEST binary's own root, not a lib) → do NOT search every crate in a workspace: that
648
+ // resolves `crate::util` to some unrelated crate's util.rs. Keep it a string instead.
649
+ if (owning.length === 0)
650
+ return full === "" ? "crate" : `crate::${full.replace(/\//g, "::")}`;
651
+ const roots = [owning[0]];
652
+ const segs = full === "" ? [] : full.split("/");
653
+ const hitsFor = (rels) => {
654
+ const hits = new Set();
655
+ for (const r of roots)
656
+ for (const rel of rels) {
657
+ const cand = r === "" ? rel : `${r}/${rel}`;
658
+ if (byId.has(cand))
659
+ hits.add(cand);
660
+ }
661
+ return hits;
662
+ };
663
+ // Try the longest module prefix first, shrinking toward — but NOT past — the first
664
+ // segment. `crate::a::b::C` resolves as module `a/b` (C is the item); `crate::net` as
665
+ // module `net`. The first prefix naming exactly one in-repo file wins; two matches at a
666
+ // level are ambiguous → drop rather than guess.
667
+ for (let k = segs.length; k >= 1; k--) {
668
+ const modPath = segs.slice(0, k).join("/");
669
+ const hits = hitsFor([`${modPath}.rs`, `${modPath}/mod.rs`]);
670
+ if (hits.size === 1)
671
+ return [...hits][0];
672
+ if (hits.size > 1)
673
+ break;
674
+ }
675
+ // The crate root (`lib.rs`/`main.rs`) is a target ONLY for `use crate::Item` or
676
+ // `use crate::{…}` — a deeper path whose module chain didn't resolve is genuinely
677
+ // unknown (a re-export, an inline `mod`, or out-of-tree), so keep it as a string.
678
+ if (segs.length <= 1) {
679
+ const hits = hitsFor(["lib.rs", "main.rs"]);
680
+ if (hits.size === 1)
681
+ return [...hits][0];
682
+ }
683
+ return full === "" ? "crate" : `crate::${full.replace(/\//g, "::")}`;
684
+ }
685
+ /**
686
+ * Resolve a Go import package path to an in-repo file node when it points inside one of
687
+ * the repo's modules; otherwise return the raw specifier (stdlib or third-party package).
688
+ *
689
+ * Go imports name a *package* (a directory), not a file. The package path is relative to
690
+ * the owning module's path, so the in-repo directory is `<module go.mod dir>/<subpath>`.
691
+ * This handles a `go.mod` anywhere in the tree — repo root or a subdirectory (monorepo).
692
+ * When several modules' paths prefix the spec, the longest (most specific) wins. A package
693
+ * dir may hold several `.go` files; we pick a deterministic representative (lowest id).
694
+ */
695
+ function resolveGoImport(spec, modules, filesByDir) {
696
+ let best = null;
697
+ for (const mod of modules) {
698
+ let subpath = null;
699
+ if (spec === mod.module)
700
+ subpath = "";
701
+ else if (spec.startsWith(mod.module + "/"))
702
+ subpath = spec.slice(mod.module.length + 1);
703
+ if (subpath === null)
704
+ continue;
705
+ if (!best || mod.module.length > best.mod.module.length)
706
+ best = { mod, subpath };
707
+ }
708
+ if (!best)
709
+ return spec; // stdlib / third-party — keep the package path
710
+ const dir = posix.normalize(posix.join(best.mod.dir, best.subpath));
711
+ const files = filesByDir.get(dir);
712
+ if (!files || files.length === 0)
713
+ return spec;
714
+ return [...files].sort()[0];
715
+ }
716
+ //# sourceMappingURL=resolve.js.map