gitnexus 1.6.6-rc.98 → 1.6.6

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 (541) hide show
  1. package/README.md +122 -68
  2. package/dist/_shared/graph/types.d.ts +17 -1
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +3 -5
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/index.js +2 -4
  7. package/dist/_shared/index.js.map +1 -1
  8. package/dist/_shared/scope-resolution/module-scope-index.d.ts +1 -2
  9. package/dist/_shared/scope-resolution/module-scope-index.d.ts.map +1 -1
  10. package/dist/_shared/scope-resolution/module-scope-index.js +1 -2
  11. package/dist/_shared/scope-resolution/module-scope-index.js.map +1 -1
  12. package/dist/_shared/scope-resolution/parsed-file.d.ts +24 -0
  13. package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
  14. package/dist/_shared/scope-resolution/reference-site.d.ts +13 -1
  15. package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
  16. package/dist/_shared/scope-resolution/registries/context.d.ts +1 -0
  17. package/dist/_shared/scope-resolution/registries/context.d.ts.map +1 -1
  18. package/dist/_shared/scope-resolution/registries/context.js +6 -0
  19. package/dist/_shared/scope-resolution/registries/context.js.map +1 -1
  20. package/dist/_shared/scope-resolution/registries/evidence.d.ts +2 -3
  21. package/dist/_shared/scope-resolution/registries/evidence.d.ts.map +1 -1
  22. package/dist/_shared/scope-resolution/registries/evidence.js +2 -3
  23. package/dist/_shared/scope-resolution/registries/evidence.js.map +1 -1
  24. package/dist/_shared/scope-resolution/registries/macro-registry.d.ts +29 -0
  25. package/dist/_shared/scope-resolution/registries/macro-registry.d.ts.map +1 -0
  26. package/dist/_shared/scope-resolution/registries/macro-registry.js +32 -0
  27. package/dist/_shared/scope-resolution/registries/macro-registry.js.map +1 -0
  28. package/dist/_shared/scope-resolution/symbol-definition.d.ts +9 -0
  29. package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
  30. package/dist/_shared/scope-resolution/types.d.ts +1 -1
  31. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  32. package/dist/cli/ai-context.d.ts +35 -1
  33. package/dist/cli/ai-context.js +111 -12
  34. package/dist/cli/analyze-config.d.ts +92 -0
  35. package/dist/cli/analyze-config.js +364 -0
  36. package/dist/cli/analyze.d.ts +17 -1
  37. package/dist/cli/analyze.js +224 -71
  38. package/dist/cli/cli-message.d.ts +1 -1
  39. package/dist/cli/doctor.d.ts +18 -0
  40. package/dist/cli/doctor.js +32 -0
  41. package/dist/cli/i18n/en.d.ts +2 -2
  42. package/dist/cli/i18n/en.js +2 -2
  43. package/dist/cli/i18n/resources.d.ts +2 -2
  44. package/dist/cli/i18n/zh-CN.js +2 -2
  45. package/dist/cli/index.js +4 -2
  46. package/dist/cli/resolve-invocation.d.ts +21 -0
  47. package/dist/cli/resolve-invocation.js +68 -0
  48. package/dist/cli/setup.d.ts +33 -0
  49. package/dist/cli/setup.js +96 -35
  50. package/dist/cli/skill-gen.js +2 -2
  51. package/dist/cli/wiki.js +20 -4
  52. package/dist/core/embeddings/embedder.d.ts +1 -1
  53. package/dist/core/embeddings/embedder.js +14 -1
  54. package/dist/core/embeddings/runtime-support.d.ts +41 -0
  55. package/dist/core/embeddings/runtime-support.js +65 -0
  56. package/dist/core/group/extractors/grpc-patterns/proto.js +2 -1
  57. package/dist/core/group/extractors/http-patterns/java.js +15 -1
  58. package/dist/core/ingestion/call-processor.d.ts +57 -227
  59. package/dist/core/ingestion/call-processor.js +172 -2595
  60. package/dist/core/ingestion/call-routing.d.ts +6 -5
  61. package/dist/core/ingestion/call-routing.js +6 -6
  62. package/dist/core/ingestion/call-types.d.ts +0 -75
  63. package/dist/core/ingestion/class-extractors/configs/c-cpp.js +26 -1
  64. package/dist/core/ingestion/class-extractors/configs/ruby.js +3 -0
  65. package/dist/core/ingestion/class-extractors/generic.js +9 -11
  66. package/dist/core/ingestion/class-types.d.ts +23 -0
  67. package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +11 -0
  68. package/dist/core/ingestion/cobol/cobol-preprocessor.js +227 -73
  69. package/dist/core/ingestion/cobol-processor.d.ts +1 -0
  70. package/dist/core/ingestion/cobol-processor.js +51 -2
  71. package/dist/core/ingestion/emit-references.js +8 -2
  72. package/dist/core/ingestion/export-detection.d.ts +2 -1
  73. package/dist/core/ingestion/export-detection.js +2 -6
  74. package/dist/core/ingestion/field-extractors/configs/dart.d.ts +0 -6
  75. package/dist/core/ingestion/field-extractors/configs/dart.js +62 -44
  76. package/dist/core/ingestion/field-extractors/configs/go.d.ts +0 -9
  77. package/dist/core/ingestion/field-extractors/configs/go.js +40 -1
  78. package/dist/core/ingestion/field-extractors/configs/jvm.js +43 -4
  79. package/dist/core/ingestion/field-extractors/configs/php.js +1 -2
  80. package/dist/core/ingestion/field-extractors/configs/swift.d.ts +12 -1
  81. package/dist/core/ingestion/field-extractors/configs/swift.js +31 -6
  82. package/dist/core/ingestion/field-extractors/generic.d.ts +6 -0
  83. package/dist/core/ingestion/field-extractors/generic.js +5 -4
  84. package/dist/core/ingestion/field-extractors/typescript.js +0 -29
  85. package/dist/core/ingestion/filesystem-walker.d.ts +0 -9
  86. package/dist/core/ingestion/filesystem-walker.js +0 -11
  87. package/dist/core/ingestion/finalize-orchestrator.js +14 -2
  88. package/dist/core/ingestion/import-resolvers/configs/swift.d.ts +21 -0
  89. package/dist/core/ingestion/import-resolvers/configs/swift.js +72 -11
  90. package/dist/core/ingestion/import-resolvers/python.d.ts +1 -1
  91. package/dist/core/ingestion/import-resolvers/standard.d.ts +2 -2
  92. package/dist/core/ingestion/import-resolvers/standard.js +6 -5
  93. package/dist/core/ingestion/import-resolvers/utils.d.ts +2 -5
  94. package/dist/core/ingestion/import-resolvers/utils.js +1 -9
  95. package/dist/core/ingestion/language-provider.d.ts +39 -119
  96. package/dist/core/ingestion/language-provider.js +0 -2
  97. package/dist/core/ingestion/languages/c/capture-side-channel.d.ts +62 -0
  98. package/dist/core/ingestion/languages/c/capture-side-channel.js +65 -0
  99. package/dist/core/ingestion/languages/c/captures.js +41 -23
  100. package/dist/core/ingestion/languages/c/import-decomposer.d.ts +9 -0
  101. package/dist/core/ingestion/languages/c/import-decomposer.js +15 -0
  102. package/dist/core/ingestion/languages/c/import-target.js +52 -9
  103. package/dist/core/ingestion/languages/c/index.d.ts +2 -1
  104. package/dist/core/ingestion/languages/c/index.js +2 -1
  105. package/dist/core/ingestion/languages/c/query.js +15 -0
  106. package/dist/core/ingestion/languages/c/scope-resolver.js +47 -4
  107. package/dist/core/ingestion/languages/c/static-linkage.d.ts +8 -0
  108. package/dist/core/ingestion/languages/c/static-linkage.js +46 -1
  109. package/dist/core/ingestion/languages/c-cpp.js +16 -7
  110. package/dist/core/ingestion/languages/cobol/captures.js +25 -2
  111. package/dist/core/ingestion/languages/cpp/adl.d.ts +88 -4
  112. package/dist/core/ingestion/languages/cpp/adl.js +380 -160
  113. package/dist/core/ingestion/languages/cpp/arity-metadata.js +2 -8
  114. package/dist/core/ingestion/languages/cpp/capture-side-channel.d.ts +65 -0
  115. package/dist/core/ingestion/languages/cpp/capture-side-channel.js +78 -0
  116. package/dist/core/ingestion/languages/cpp/captures.js +162 -54
  117. package/dist/core/ingestion/languages/cpp/file-local-linkage.d.ts +18 -52
  118. package/dist/core/ingestion/languages/cpp/file-local-linkage.js +49 -1
  119. package/dist/core/ingestion/languages/cpp/import-decomposer.d.ts +7 -0
  120. package/dist/core/ingestion/languages/cpp/import-decomposer.js +12 -0
  121. package/dist/core/ingestion/languages/cpp/index.d.ts +1 -0
  122. package/dist/core/ingestion/languages/cpp/index.js +1 -0
  123. package/dist/core/ingestion/languages/cpp/inline-namespaces.d.ts +8 -0
  124. package/dist/core/ingestion/languages/cpp/inline-namespaces.js +21 -0
  125. package/dist/core/ingestion/languages/cpp/query.js +21 -0
  126. package/dist/core/ingestion/languages/cpp/range-bindings.js +20 -5
  127. package/dist/core/ingestion/languages/cpp/scope-resolver.js +52 -5
  128. package/dist/core/ingestion/languages/cpp/two-phase-lookup.d.ts +20 -0
  129. package/dist/core/ingestion/languages/cpp/two-phase-lookup.js +83 -3
  130. package/dist/core/ingestion/languages/csharp/captures.js +205 -41
  131. package/dist/core/ingestion/languages/csharp/index.d.ts +3 -4
  132. package/dist/core/ingestion/languages/csharp/index.js +3 -4
  133. package/dist/core/ingestion/languages/csharp/interpret.js +17 -3
  134. package/dist/core/ingestion/languages/csharp/namespace-siblings.d.ts +17 -7
  135. package/dist/core/ingestion/languages/csharp/namespace-siblings.js +129 -124
  136. package/dist/core/ingestion/languages/csharp/qualified-type-names.d.ts +14 -0
  137. package/dist/core/ingestion/languages/csharp/qualified-type-names.js +59 -0
  138. package/dist/core/ingestion/languages/csharp/query.js +13 -0
  139. package/dist/core/ingestion/languages/csharp/receiver-binding.js +10 -6
  140. package/dist/core/ingestion/languages/csharp/scope-resolver.js +8 -1
  141. package/dist/core/ingestion/languages/csharp.js +0 -5
  142. package/dist/core/ingestion/languages/dart/arity-metadata.d.ts +25 -0
  143. package/dist/core/ingestion/languages/dart/arity-metadata.js +35 -0
  144. package/dist/core/ingestion/languages/dart/arity.d.ts +19 -0
  145. package/dist/core/ingestion/languages/dart/arity.js +31 -0
  146. package/dist/core/ingestion/languages/dart/built-ins.d.ts +11 -0
  147. package/dist/core/ingestion/languages/dart/built-ins.js +34 -0
  148. package/dist/core/ingestion/languages/dart/cache-stats.d.ts +13 -0
  149. package/dist/core/ingestion/languages/dart/cache-stats.js +24 -0
  150. package/dist/core/ingestion/languages/dart/captures.d.ts +29 -0
  151. package/dist/core/ingestion/languages/dart/captures.js +445 -0
  152. package/dist/core/ingestion/languages/dart/expand-wildcards.d.ts +13 -0
  153. package/dist/core/ingestion/languages/dart/expand-wildcards.js +31 -0
  154. package/dist/core/ingestion/languages/dart/import-target.d.ts +15 -0
  155. package/dist/core/ingestion/languages/dart/import-target.js +65 -0
  156. package/dist/core/ingestion/languages/dart/index.d.ts +28 -0
  157. package/dist/core/ingestion/languages/dart/index.js +28 -0
  158. package/dist/core/ingestion/languages/dart/interpret.d.ts +24 -0
  159. package/dist/core/ingestion/languages/dart/interpret.js +95 -0
  160. package/dist/core/ingestion/languages/dart/merge-bindings.d.ts +10 -0
  161. package/dist/core/ingestion/languages/dart/merge-bindings.js +39 -0
  162. package/dist/core/ingestion/languages/dart/query.d.ts +26 -0
  163. package/dist/core/ingestion/languages/dart/query.js +142 -0
  164. package/dist/core/ingestion/languages/dart/receiver-binding.d.ts +24 -0
  165. package/dist/core/ingestion/languages/dart/receiver-binding.js +87 -0
  166. package/dist/core/ingestion/languages/dart/scope-resolver.d.ts +29 -0
  167. package/dist/core/ingestion/languages/dart/scope-resolver.js +194 -0
  168. package/dist/core/ingestion/languages/dart/signature-bindings.d.ts +23 -0
  169. package/dist/core/ingestion/languages/dart/signature-bindings.js +51 -0
  170. package/dist/core/ingestion/languages/dart/simple-hooks.d.ts +20 -0
  171. package/dist/core/ingestion/languages/dart/simple-hooks.js +47 -0
  172. package/dist/core/ingestion/languages/dart.d.ts +0 -1
  173. package/dist/core/ingestion/languages/dart.js +15 -29
  174. package/dist/core/ingestion/languages/go/arity-metadata.d.ts +1 -0
  175. package/dist/core/ingestion/languages/go/arity-metadata.js +31 -1
  176. package/dist/core/ingestion/languages/go/captures.js +247 -26
  177. package/dist/core/ingestion/languages/go/interface-impls.js +476 -50
  178. package/dist/core/ingestion/languages/go/interpret.js +21 -11
  179. package/dist/core/ingestion/languages/go/method-owners.js +20 -8
  180. package/dist/core/ingestion/languages/go/query.js +15 -7
  181. package/dist/core/ingestion/languages/go/range-binding.js +24 -9
  182. package/dist/core/ingestion/languages/go/receiver-binding.js +1 -1
  183. package/dist/core/ingestion/languages/go/scope-resolver.js +2 -2
  184. package/dist/core/ingestion/languages/go/simple-hooks.js +10 -5
  185. package/dist/core/ingestion/languages/go/type-binding.d.ts +1 -0
  186. package/dist/core/ingestion/languages/go/type-binding.js +40 -2
  187. package/dist/core/ingestion/languages/go.d.ts +0 -1
  188. package/dist/core/ingestion/languages/go.js +0 -5
  189. package/dist/core/ingestion/languages/index.d.ts +0 -5
  190. package/dist/core/ingestion/languages/index.js +0 -3
  191. package/dist/core/ingestion/languages/java/captures.js +252 -23
  192. package/dist/core/ingestion/languages/java/interpret.js +12 -6
  193. package/dist/core/ingestion/languages/java/package-siblings.js +18 -5
  194. package/dist/core/ingestion/languages/java/query.js +16 -1
  195. package/dist/core/ingestion/languages/java/scope-resolver.d.ts +2 -8
  196. package/dist/core/ingestion/languages/java/scope-resolver.js +2 -8
  197. package/dist/core/ingestion/languages/java.js +0 -5
  198. package/dist/core/ingestion/languages/javascript/captures.js +185 -11
  199. package/dist/core/ingestion/languages/javascript/query.js +107 -1
  200. package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +57 -0
  201. package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +60 -0
  202. package/dist/core/ingestion/languages/kotlin/captures.js +213 -22
  203. package/dist/core/ingestion/languages/kotlin/companion-scopes.d.ts +7 -0
  204. package/dist/core/ingestion/languages/kotlin/companion-scopes.js +10 -0
  205. package/dist/core/ingestion/languages/kotlin/index.d.ts +1 -0
  206. package/dist/core/ingestion/languages/kotlin/index.js +1 -0
  207. package/dist/core/ingestion/languages/kotlin/query.js +30 -0
  208. package/dist/core/ingestion/languages/kotlin/scope-resolver.d.ts +5 -7
  209. package/dist/core/ingestion/languages/kotlin/scope-resolver.js +22 -7
  210. package/dist/core/ingestion/languages/kotlin.js +8 -5
  211. package/dist/core/ingestion/languages/php/captures.js +135 -19
  212. package/dist/core/ingestion/languages/php/import-decomposer.js +21 -63
  213. package/dist/core/ingestion/languages/php/index.d.ts +3 -4
  214. package/dist/core/ingestion/languages/php/index.js +3 -4
  215. package/dist/core/ingestion/languages/php/query.js +5 -0
  216. package/dist/core/ingestion/languages/php/receiver-binding.js +8 -4
  217. package/dist/core/ingestion/languages/php.js +0 -4
  218. package/dist/core/ingestion/languages/python/captures.js +128 -13
  219. package/dist/core/ingestion/languages/python/depends-references.js +1 -1
  220. package/dist/core/ingestion/languages/python/import-target.d.ts +4 -5
  221. package/dist/core/ingestion/languages/python/import-target.js +108 -16
  222. package/dist/core/ingestion/languages/python/index-stats.d.ts +18 -0
  223. package/dist/core/ingestion/languages/python/index-stats.js +25 -0
  224. package/dist/core/ingestion/languages/python/index.d.ts +3 -4
  225. package/dist/core/ingestion/languages/python/index.js +3 -4
  226. package/dist/core/ingestion/languages/python/query.js +17 -0
  227. package/dist/core/ingestion/languages/python/scope-resolver.js +7 -6
  228. package/dist/core/ingestion/languages/python.d.ts +0 -2
  229. package/dist/core/ingestion/languages/python.js +0 -7
  230. package/dist/core/ingestion/languages/ruby/captures.js +174 -31
  231. package/dist/core/ingestion/languages/ruby/import-target.js +2 -1
  232. package/dist/core/ingestion/languages/ruby/interpret.js +2 -1
  233. package/dist/core/ingestion/languages/ruby/query.js +10 -0
  234. package/dist/core/ingestion/languages/ruby/scope-resolver.js +61 -11
  235. package/dist/core/ingestion/languages/ruby.js +4 -53
  236. package/dist/core/ingestion/languages/rust/captures.js +95 -13
  237. package/dist/core/ingestion/languages/rust/query.js +64 -1
  238. package/dist/core/ingestion/languages/rust/range-binding.js +40 -12
  239. package/dist/core/ingestion/languages/rust/receiver-binding.js +9 -0
  240. package/dist/core/ingestion/languages/rust/scope-resolver.js +75 -1
  241. package/dist/core/ingestion/languages/rust.d.ts +0 -2
  242. package/dist/core/ingestion/languages/rust.js +0 -6
  243. package/dist/core/ingestion/languages/swift/arity-metadata.d.ts +24 -0
  244. package/dist/core/ingestion/languages/swift/arity-metadata.js +41 -0
  245. package/dist/core/ingestion/languages/swift/arity.d.ts +29 -0
  246. package/dist/core/ingestion/languages/swift/arity.js +42 -0
  247. package/dist/core/ingestion/languages/swift/base-type.d.ts +20 -0
  248. package/dist/core/ingestion/languages/swift/base-type.js +27 -0
  249. package/dist/core/ingestion/languages/swift/cache-stats.d.ts +15 -0
  250. package/dist/core/ingestion/languages/swift/cache-stats.js +26 -0
  251. package/dist/core/ingestion/languages/swift/captures.d.ts +35 -0
  252. package/dist/core/ingestion/languages/swift/captures.js +495 -0
  253. package/dist/core/ingestion/languages/swift/implicit-imports.d.ts +34 -0
  254. package/dist/core/ingestion/languages/swift/implicit-imports.js +57 -0
  255. package/dist/core/ingestion/languages/swift/import-decomposer.d.ts +24 -0
  256. package/dist/core/ingestion/languages/swift/import-decomposer.js +84 -0
  257. package/dist/core/ingestion/languages/swift/import-target.d.ts +33 -0
  258. package/dist/core/ingestion/languages/swift/import-target.js +81 -0
  259. package/dist/core/ingestion/languages/swift/index.d.ts +37 -0
  260. package/dist/core/ingestion/languages/swift/index.js +37 -0
  261. package/dist/core/ingestion/languages/swift/interpret.d.ts +15 -0
  262. package/dist/core/ingestion/languages/swift/interpret.js +89 -0
  263. package/dist/core/ingestion/languages/swift/merge-bindings.d.ts +20 -0
  264. package/dist/core/ingestion/languages/swift/merge-bindings.js +48 -0
  265. package/dist/core/ingestion/languages/swift/query.d.ts +46 -0
  266. package/dist/core/ingestion/languages/swift/query.js +194 -0
  267. package/dist/core/ingestion/languages/swift/receiver-binding.d.ts +40 -0
  268. package/dist/core/ingestion/languages/swift/receiver-binding.js +161 -0
  269. package/dist/core/ingestion/languages/swift/scope-resolver.d.ts +50 -0
  270. package/dist/core/ingestion/languages/swift/scope-resolver.js +189 -0
  271. package/dist/core/ingestion/languages/swift/sibling-type-bindings.d.ts +34 -0
  272. package/dist/core/ingestion/languages/swift/sibling-type-bindings.js +65 -0
  273. package/dist/core/ingestion/languages/swift/signature-bindings.d.ts +25 -0
  274. package/dist/core/ingestion/languages/swift/signature-bindings.js +66 -0
  275. package/dist/core/ingestion/languages/swift/simple-hooks.d.ts +37 -0
  276. package/dist/core/ingestion/languages/swift/simple-hooks.js +60 -0
  277. package/dist/core/ingestion/languages/swift/target-grouping.d.ts +51 -0
  278. package/dist/core/ingestion/languages/swift/target-grouping.js +93 -0
  279. package/dist/core/ingestion/languages/swift/target-siblings.d.ts +30 -0
  280. package/dist/core/ingestion/languages/swift/target-siblings.js +71 -0
  281. package/dist/core/ingestion/languages/swift.d.ts +0 -5
  282. package/dist/core/ingestion/languages/swift.js +11 -87
  283. package/dist/core/ingestion/languages/typescript/array-callback.d.ts +3 -29
  284. package/dist/core/ingestion/languages/typescript/array-callback.js +4 -43
  285. package/dist/core/ingestion/languages/typescript/captures.js +147 -17
  286. package/dist/core/ingestion/languages/typescript/index.d.ts +3 -4
  287. package/dist/core/ingestion/languages/typescript/index.js +3 -4
  288. package/dist/core/ingestion/languages/typescript/query.d.ts +2 -3
  289. package/dist/core/ingestion/languages/typescript/query.js +125 -4
  290. package/dist/core/ingestion/languages/typescript/receiver-binding.js +0 -1
  291. package/dist/core/ingestion/languages/typescript.d.ts +2 -3
  292. package/dist/core/ingestion/languages/typescript.js +46 -23
  293. package/dist/core/ingestion/languages/vue/captures.d.ts +46 -0
  294. package/dist/core/ingestion/languages/vue/captures.js +67 -0
  295. package/dist/core/ingestion/languages/vue/import-target.d.ts +27 -0
  296. package/dist/core/ingestion/languages/vue/import-target.js +58 -0
  297. package/dist/core/ingestion/languages/vue/index.d.ts +49 -0
  298. package/dist/core/ingestion/languages/vue/index.js +49 -0
  299. package/dist/core/ingestion/languages/vue/scope-resolver.d.ts +55 -0
  300. package/dist/core/ingestion/languages/vue/scope-resolver.js +292 -0
  301. package/dist/core/ingestion/languages/vue.js +12 -4
  302. package/dist/core/ingestion/local-symbol-pruner.d.ts +11 -0
  303. package/dist/core/ingestion/local-symbol-pruner.js +63 -0
  304. package/dist/core/ingestion/method-extractors/configs/dart.js +14 -1
  305. package/dist/core/ingestion/method-extractors/configs/jvm.js +37 -20
  306. package/dist/core/ingestion/method-extractors/configs/php.js +0 -1
  307. package/dist/core/ingestion/method-extractors/configs/swift.js +11 -4
  308. package/dist/core/ingestion/method-types.d.ts +2 -2
  309. package/dist/core/ingestion/model/index.d.ts +0 -3
  310. package/dist/core/ingestion/model/index.js +0 -8
  311. package/dist/core/ingestion/model/resolve.d.ts +7 -43
  312. package/dist/core/ingestion/model/resolve.js +7 -226
  313. package/dist/core/ingestion/model/scope-resolution-indexes.d.ts +46 -1
  314. package/dist/core/ingestion/model/semantic-model.d.ts +4 -6
  315. package/dist/core/ingestion/model/semantic-model.js +1 -1
  316. package/dist/core/ingestion/model/symbol-table.d.ts +3 -4
  317. package/dist/core/ingestion/model/symbol-table.js +3 -4
  318. package/dist/core/ingestion/parsing-processor.d.ts +30 -24
  319. package/dist/core/ingestion/parsing-processor.js +76 -640
  320. package/dist/core/ingestion/pipeline-phases/communities.d.ts +1 -1
  321. package/dist/core/ingestion/pipeline-phases/communities.js +5 -2
  322. package/dist/core/ingestion/pipeline-phases/cross-file.d.ts +9 -8
  323. package/dist/core/ingestion/pipeline-phases/cross-file.js +16 -12
  324. package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
  325. package/dist/core/ingestion/pipeline-phases/index.js +1 -0
  326. package/dist/core/ingestion/pipeline-phases/mro.d.ts +1 -1
  327. package/dist/core/ingestion/pipeline-phases/mro.js +2 -2
  328. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +44 -22
  329. package/dist/core/ingestion/pipeline-phases/parse-impl.js +426 -565
  330. package/dist/core/ingestion/pipeline-phases/parse.d.ts +13 -33
  331. package/dist/core/ingestion/pipeline-phases/parse.js +2 -2
  332. package/dist/core/ingestion/pipeline-phases/processes.d.ts +1 -1
  333. package/dist/core/ingestion/pipeline-phases/processes.js +5 -3
  334. package/dist/core/ingestion/pipeline-phases/prune-local-symbols.d.ts +14 -0
  335. package/dist/core/ingestion/pipeline-phases/prune-local-symbols.js +26 -0
  336. package/dist/core/ingestion/pipeline.d.ts +27 -19
  337. package/dist/core/ingestion/pipeline.js +4 -2
  338. package/dist/core/ingestion/resolve-references.js +15 -3
  339. package/dist/core/ingestion/route-extractors/laravel.d.ts +10 -0
  340. package/dist/core/ingestion/route-extractors/laravel.js +88 -9
  341. package/dist/core/ingestion/scope-extractor-bridge.d.ts +2 -1
  342. package/dist/core/ingestion/scope-extractor-bridge.js +2 -2
  343. package/dist/core/ingestion/scope-extractor.js +13 -0
  344. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +181 -15
  345. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +21 -10
  346. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +10 -2
  347. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +7 -1
  348. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +58 -6
  349. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +24 -5
  350. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +68 -1
  351. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +189 -29
  352. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.js +21 -1
  353. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +1 -1
  354. package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +8 -11
  355. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +171 -50
  356. package/dist/core/ingestion/scope-resolution/pipeline/registry.d.ts +3 -4
  357. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +9 -4
  358. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +28 -5
  359. package/dist/core/ingestion/scope-resolution/pipeline/run.js +191 -24
  360. package/dist/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.js +31 -0
  361. package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +72 -0
  362. package/dist/core/ingestion/scope-resolution/scope/walkers.js +440 -39
  363. package/dist/core/ingestion/scope-resolution/workspace-index.d.ts +18 -2
  364. package/dist/core/ingestion/scope-resolution/workspace-index.js +94 -7
  365. package/dist/core/ingestion/tree-sitter-queries.d.ts +14 -14
  366. package/dist/core/ingestion/tree-sitter-queries.js +380 -158
  367. package/dist/core/ingestion/ts-js-hoc-utils.d.ts +12 -0
  368. package/dist/core/ingestion/ts-js-hoc-utils.js +105 -0
  369. package/dist/core/ingestion/type-env.d.ts +2 -1
  370. package/dist/core/ingestion/type-env.js +6 -8
  371. package/dist/core/ingestion/type-extractors/c-cpp.js +8 -10
  372. package/dist/core/ingestion/type-extractors/csharp.js +18 -34
  373. package/dist/core/ingestion/type-extractors/go.js +2 -10
  374. package/dist/core/ingestion/type-extractors/jvm.js +6 -5
  375. package/dist/core/ingestion/type-extractors/php.js +1 -1
  376. package/dist/core/ingestion/type-extractors/python.js +1 -1
  377. package/dist/core/ingestion/type-extractors/ruby.js +2 -2
  378. package/dist/core/ingestion/type-extractors/rust.js +0 -16
  379. package/dist/core/ingestion/type-extractors/shared.d.ts +2 -2
  380. package/dist/core/ingestion/type-extractors/shared.js +25 -11
  381. package/dist/core/ingestion/type-extractors/swift.js +5 -5
  382. package/dist/core/ingestion/type-extractors/types.d.ts +1 -1
  383. package/dist/core/ingestion/type-extractors/typescript.js +1 -1
  384. package/dist/core/ingestion/utils/ast-helpers.d.ts +119 -1
  385. package/dist/core/ingestion/utils/ast-helpers.js +260 -13
  386. package/dist/core/ingestion/utils/callable-labels.d.ts +13 -0
  387. package/dist/core/ingestion/utils/callable-labels.js +14 -0
  388. package/dist/core/ingestion/utils/deferred-resolution-profile.d.ts +10 -0
  389. package/dist/core/ingestion/utils/deferred-resolution-profile.js +30 -0
  390. package/dist/core/ingestion/utils/heap-probe.d.ts +20 -0
  391. package/dist/core/ingestion/utils/heap-probe.js +39 -0
  392. package/dist/core/ingestion/utils/heritage-marker.d.ts +33 -0
  393. package/dist/core/ingestion/utils/heritage-marker.js +41 -0
  394. package/dist/core/ingestion/utils/qualified-name.d.ts +37 -0
  395. package/dist/core/ingestion/utils/qualified-name.js +67 -0
  396. package/dist/core/ingestion/variable-extractors/configs/c-cpp.js +49 -0
  397. package/dist/core/ingestion/variable-extractors/configs/dart.js +76 -62
  398. package/dist/core/ingestion/variable-extractors/configs/go.js +74 -7
  399. package/dist/core/ingestion/variable-extractors/configs/jvm.js +35 -8
  400. package/dist/core/ingestion/variable-extractors/generic.js +40 -12
  401. package/dist/core/ingestion/variable-types.d.ts +9 -0
  402. package/dist/core/ingestion/vue-sfc-extractor.d.ts +97 -7
  403. package/dist/core/ingestion/vue-sfc-extractor.js +433 -11
  404. package/dist/core/ingestion/workers/parse-worker.d.ts +0 -11
  405. package/dist/core/ingestion/workers/parse-worker.js +358 -187
  406. package/dist/core/ingestion/workers/worker-pool.d.ts +78 -9
  407. package/dist/core/ingestion/workers/worker-pool.js +346 -49
  408. package/dist/core/lbug/csv-generator.js +20 -2
  409. package/dist/core/lbug/lbug-adapter.js +29 -10
  410. package/dist/core/lbug/native-check.js +17 -5
  411. package/dist/core/lbug/pool-adapter.d.ts +0 -19
  412. package/dist/core/lbug/pool-adapter.js +40 -77
  413. package/dist/core/lbug/query-result-utils.d.ts +19 -0
  414. package/dist/core/lbug/query-result-utils.js +28 -0
  415. package/dist/core/run-analyze.d.ts +9 -2
  416. package/dist/core/run-analyze.js +24 -3
  417. package/dist/core/tree-sitter/parser-loader.d.ts +13 -0
  418. package/dist/core/tree-sitter/parser-loader.js +4 -0
  419. package/dist/core/tree-sitter/safe-parse.d.ts +70 -3
  420. package/dist/core/tree-sitter/safe-parse.js +214 -11
  421. package/dist/core/wiki/generator.js +13 -5
  422. package/dist/core/wiki/graph-queries.d.ts +3 -0
  423. package/dist/core/wiki/graph-queries.js +9 -1
  424. package/dist/core/wiki/llm-client.d.ts +1 -1
  425. package/dist/core/wiki/llm-client.js +7 -2
  426. package/dist/core/wiki/local-cli-client.d.ts +2 -1
  427. package/dist/core/wiki/local-cli-client.js +62 -4
  428. package/dist/mcp/compatible-stdio-transport.d.ts +3 -0
  429. package/dist/mcp/compatible-stdio-transport.js +22 -0
  430. package/dist/mcp/core/embedder.d.ts +1 -1
  431. package/dist/mcp/core/embedder.js +13 -1
  432. package/dist/mcp/local/local-backend.d.ts +37 -5
  433. package/dist/mcp/local/local-backend.js +227 -129
  434. package/dist/mcp/resources.js +3 -3
  435. package/dist/mcp/server.js +9 -1
  436. package/dist/storage/git.d.ts +11 -0
  437. package/dist/storage/git.js +30 -0
  438. package/dist/storage/parse-cache.d.ts +23 -1
  439. package/dist/storage/parse-cache.js +138 -32
  440. package/dist/storage/parsedfile-store.d.ts +142 -0
  441. package/dist/storage/parsedfile-store.js +367 -0
  442. package/dist/storage/repo-manager.d.ts +2 -1
  443. package/dist/storage/scope-index-store.d.ts +114 -0
  444. package/dist/storage/scope-index-store.js +236 -0
  445. package/dist/types/pipeline.d.ts +6 -3
  446. package/hooks/antigravity/gitnexus-antigravity-hook.cjs +2 -1
  447. package/hooks/claude/gitnexus-hook.cjs +2 -1
  448. package/hooks/claude/resolve-analyze-cmd.cjs +323 -0
  449. package/package.json +4 -5
  450. package/scripts/bench-scope-resolution.ts +1 -3
  451. package/scripts/cross-platform-tests.ts +4 -1
  452. package/skills/gitnexus-cli.md +8 -6
  453. package/skills/gitnexus-debugging.md +15 -15
  454. package/skills/gitnexus-exploring.md +11 -11
  455. package/skills/gitnexus-guide.md +1 -1
  456. package/skills/gitnexus-impact-analysis.md +10 -10
  457. package/skills/gitnexus-pr-review.md +19 -19
  458. package/skills/gitnexus-refactoring.md +25 -25
  459. package/web/assets/{agent-BRX-afm3.js → agent-EkX7webX.js} +156 -131
  460. package/web/assets/{architectureDiagram-UL44E2DR-B1oYB8-c.js → architectureDiagram-UL44E2DR-BoczH8cv.js} +1 -1
  461. package/web/assets/{chunk-LCXTWHL2-SPC6pgWI.js → chunk-LCXTWHL2-By5HB3b-.js} +1 -1
  462. package/web/assets/{chunk-RG4AUYOV-DZXr4Yv3.js → chunk-RG4AUYOV-BQE_DkpL.js} +1 -1
  463. package/web/assets/{classDiagram-KGZ6W3CR-BqpOj8L9.js → classDiagram-KGZ6W3CR-Dj_02GUH.js} +1 -1
  464. package/web/assets/{classDiagram-v2-72OJOZXJ-FmElywK2.js → classDiagram-v2-72OJOZXJ-D-NArMpf.js} +1 -1
  465. package/web/assets/{diagram-3NCE3AQN-BWtJXMDq.js → diagram-3NCE3AQN-VXtXDO95.js} +1 -1
  466. package/web/assets/{diagram-GF46GFSD-Hh-fChxU.js → diagram-GF46GFSD-B1qab2Ah.js} +1 -1
  467. package/web/assets/{diagram-QXG6HAR7-DYeQHxGU.js → diagram-QXG6HAR7-BSCHGzzT.js} +1 -1
  468. package/web/assets/{diagram-WEQXMOUZ-DYGU4T0y.js → diagram-WEQXMOUZ-DHtknmNT.js} +1 -1
  469. package/web/assets/{erDiagram-L5TCEMPS-bN3wlP2A.js → erDiagram-L5TCEMPS-Db-IYTmm.js} +1 -1
  470. package/web/assets/{flowDiagram-H6V6AXG4-YACVtF3-.js → flowDiagram-H6V6AXG4-BHDoyVoW.js} +1 -1
  471. package/web/assets/{index-BhnAdWTt.js → index-BR0IhgbR.js} +10 -10
  472. package/web/assets/{infoDiagram-3YFTVSEB-BWBzD28-.js → infoDiagram-3YFTVSEB-6h8wbWEe.js} +1 -1
  473. package/web/assets/{ishikawaDiagram-BNXS4ZKH-B8qYT-j9.js → ishikawaDiagram-BNXS4ZKH-Dx2OkPk1.js} +1 -1
  474. package/web/assets/{kanban-definition-75IXJCU3-BeoPr5Tl.js → kanban-definition-75IXJCU3-CIIEZfqV.js} +1 -1
  475. package/web/assets/{mindmap-definition-2TDM6QVE-CdLLN_so.js → mindmap-definition-2TDM6QVE-DUAqydRq.js} +1 -1
  476. package/web/assets/{pieDiagram-CU6KROY3-DEd2a_k_.js → pieDiagram-CU6KROY3-BntYuYZa.js} +1 -1
  477. package/web/assets/{requirementDiagram-JXO7QTGE-QNeTo5C_.js → requirementDiagram-JXO7QTGE-QCD6I29n.js} +1 -1
  478. package/web/assets/{sequenceDiagram-VS2MUI6T-BHC7q7yJ.js → sequenceDiagram-VS2MUI6T-DScFwLz2.js} +1 -1
  479. package/web/assets/{stateDiagram-7D4R322I-KONnc2Px.js → stateDiagram-7D4R322I-AkRAm6Hl.js} +1 -1
  480. package/web/assets/{stateDiagram-v2-36443NZ5-C2QfuMlu.js → stateDiagram-v2-36443NZ5-BCK1vigR.js} +1 -1
  481. package/web/assets/{timeline-definition-O6YCAMPW-D4t4NJx1.js → timeline-definition-O6YCAMPW-BvpIVXjX.js} +1 -1
  482. package/web/assets/{vennDiagram-MWXL3ELB-6bctC9Yg.js → vennDiagram-MWXL3ELB-BYGWk6dK.js} +1 -1
  483. package/web/assets/{wardleyDiagram-CUQ6CDDI-BPZYNTvC.js → wardleyDiagram-CUQ6CDDI-Dk1z7H2T.js} +1 -1
  484. package/web/assets/{xychartDiagram-N2JHSOCM-lBI9O6DW.js → xychartDiagram-N2JHSOCM-2N6NCSWN.js} +1 -1
  485. package/web/index.html +1 -1
  486. package/dist/_shared/scope-resolution/shadow/aggregate.d.ts +0 -63
  487. package/dist/_shared/scope-resolution/shadow/aggregate.d.ts.map +0 -1
  488. package/dist/_shared/scope-resolution/shadow/aggregate.js +0 -122
  489. package/dist/_shared/scope-resolution/shadow/aggregate.js.map +0 -1
  490. package/dist/_shared/scope-resolution/shadow/diff.d.ts +0 -59
  491. package/dist/_shared/scope-resolution/shadow/diff.d.ts.map +0 -1
  492. package/dist/_shared/scope-resolution/shadow/diff.js +0 -79
  493. package/dist/_shared/scope-resolution/shadow/diff.js.map +0 -1
  494. package/dist/core/ingestion/ast-cache.d.ts +0 -26
  495. package/dist/core/ingestion/ast-cache.js +0 -48
  496. package/dist/core/ingestion/heritage-extractors/configs/go.d.ts +0 -13
  497. package/dist/core/ingestion/heritage-extractors/configs/go.js +0 -20
  498. package/dist/core/ingestion/heritage-extractors/configs/ruby.d.ts +0 -18
  499. package/dist/core/ingestion/heritage-extractors/configs/ruby.js +0 -65
  500. package/dist/core/ingestion/heritage-extractors/generic.d.ts +0 -23
  501. package/dist/core/ingestion/heritage-extractors/generic.js +0 -47
  502. package/dist/core/ingestion/heritage-processor.d.ts +0 -54
  503. package/dist/core/ingestion/heritage-processor.js +0 -367
  504. package/dist/core/ingestion/heritage-types.d.ts +0 -73
  505. package/dist/core/ingestion/heritage-types.js +0 -2
  506. package/dist/core/ingestion/import-processor.d.ts +0 -23
  507. package/dist/core/ingestion/import-processor.js +0 -377
  508. package/dist/core/ingestion/model/heritage-map.d.ts +0 -105
  509. package/dist/core/ingestion/model/heritage-map.js +0 -294
  510. package/dist/core/ingestion/model/resolution-context.d.ts +0 -93
  511. package/dist/core/ingestion/model/resolution-context.js +0 -337
  512. package/dist/core/ingestion/named-bindings/csharp.d.ts +0 -3
  513. package/dist/core/ingestion/named-bindings/csharp.js +0 -37
  514. package/dist/core/ingestion/named-bindings/java.d.ts +0 -3
  515. package/dist/core/ingestion/named-bindings/java.js +0 -29
  516. package/dist/core/ingestion/named-bindings/kotlin.d.ts +0 -3
  517. package/dist/core/ingestion/named-bindings/kotlin.js +0 -36
  518. package/dist/core/ingestion/named-bindings/php.d.ts +0 -3
  519. package/dist/core/ingestion/named-bindings/php.js +0 -61
  520. package/dist/core/ingestion/named-bindings/python.d.ts +0 -3
  521. package/dist/core/ingestion/named-bindings/python.js +0 -49
  522. package/dist/core/ingestion/named-bindings/rust.d.ts +0 -3
  523. package/dist/core/ingestion/named-bindings/rust.js +0 -66
  524. package/dist/core/ingestion/named-bindings/types.d.ts +0 -16
  525. package/dist/core/ingestion/named-bindings/types.js +0 -6
  526. package/dist/core/ingestion/named-bindings/typescript.d.ts +0 -3
  527. package/dist/core/ingestion/named-bindings/typescript.js +0 -58
  528. package/dist/core/ingestion/pipeline-phases/cross-file-impl.d.ts +0 -17
  529. package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +0 -209
  530. package/dist/core/ingestion/pipeline-phases/orm-extraction.d.ts +0 -22
  531. package/dist/core/ingestion/pipeline-phases/orm-extraction.js +0 -92
  532. package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.d.ts +0 -70
  533. package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.js +0 -312
  534. package/dist/core/ingestion/registry-primary-flag.d.ts +0 -89
  535. package/dist/core/ingestion/registry-primary-flag.js +0 -122
  536. package/dist/core/ingestion/shadow-harness.d.ts +0 -113
  537. package/dist/core/ingestion/shadow-harness.js +0 -148
  538. package/dist/core/ingestion/utils/ruby-self-call.d.ts +0 -52
  539. package/dist/core/ingestion/utils/ruby-self-call.js +0 -59
  540. package/scripts/ci-list-migrated-languages.ts +0 -24
  541. package/scripts/run-parity.ts +0 -128
@@ -7,6 +7,7 @@
7
7
  */
8
8
  import fs from 'fs/promises';
9
9
  import path from 'path';
10
+ import { createHash } from 'crypto';
10
11
  import { initLbug, executeQuery, executeParameterized, closeLbug, isLbugReady, } from '../../core/lbug/pool-adapter.js';
11
12
  import { isValidQueryParams } from '../../core/lbug/query-params.js';
12
13
  import { isWalCorruptionError, WAL_RECOVERY_SUGGESTION } from '../../core/lbug/lbug-config.js';
@@ -142,7 +143,20 @@ function logQueryError(context, err) {
142
143
  const msg = err instanceof Error ? err.message : String(err);
143
144
  logger.error({ context, err: msg }, 'GitNexus query failed');
144
145
  }
145
- const isReadOnlyDbError = (err) => /read-only database/i.test(err instanceof Error ? err.message : String(err));
146
+ const isReadOnlyDbError = (err) => {
147
+ // Walk the `cause` chain (bounded) so a wrapped read-only error (e.g. the
148
+ // pool adapter's `{ cause }` wrapper) is still detected here — this is the
149
+ // copy the MCP cypher handler uses to surface its curated read-only message
150
+ // (#2068 follow-up). Mirrors lbug-adapter's isReadOnlyDbError.
151
+ let cur = err;
152
+ for (let depth = 0; depth < 5 && cur != null; depth++) {
153
+ const msg = cur instanceof Error ? cur.message : String(cur);
154
+ if (/read-only database/i.test(msg))
155
+ return true;
156
+ cur = cur instanceof Error ? cur.cause : undefined;
157
+ }
158
+ return false;
159
+ };
146
160
  /**
147
161
  * Per-query latency telemetry for production aggregation (#553).
148
162
  *
@@ -234,9 +248,16 @@ export function resolveWorktreeCwd(repoPath, launchCwd) {
234
248
  return repoPath;
235
249
  }
236
250
  /**
237
- * Length of the base64url path hash appended to a colliding repo id.
251
+ * Length of the path-derived suffix appended to a colliding repo id.
238
252
  * Exported so tests can pin the suffix shape without re-deriving the
239
- * literal; see `repoId()` and the hashed-id resolution tier (#1658).
253
+ * literal; see `assignRepoId()` and the hashed-id resolution tier (#1658).
254
+ *
255
+ * Note: base64url is an *encoding*, not a hash — it preserves byte order, so
256
+ * two paths that share a long common prefix (sibling clones under one parent)
257
+ * collapse to the same sliced suffix. `assignRepoId()` keeps the legacy
258
+ * base64url suffix only for the first colliding duplicate (id compatibility)
259
+ * and falls back to a content hash of the resolved path on a real collision
260
+ * (#2054).
240
261
  */
241
262
  export const REPO_ID_HASH_LENGTH = 6;
242
263
  export class LocalBackend {
@@ -296,10 +317,32 @@ export class LocalBackend {
296
317
  */
297
318
  async refreshRepos() {
298
319
  const entries = await listRegisteredRepos({ validate: true });
299
- const freshIds = new Set();
300
- for (const entry of entries) {
301
- const id = this.repoId(entry.name, entry.path);
302
- freshIds.add(id);
320
+ // Build the next map from scratch and swap it in atomically. Mutating the
321
+ // live map in place let stale entries influence fresh id assignment: a
322
+ // bare-name id, once handed to the first registry entry, stuck to it across
323
+ // refreshes and reorders, and colliding path suffixes silently overwrote
324
+ // each other so sibling clones disappeared from `list_repos` (#2054).
325
+ const nextRepos = new Map();
326
+ const nextContext = new Map();
327
+ const assigned = new Map(); // id -> resolved repo path
328
+ // Assign ids over a path-sorted view so a registered clone always gets the
329
+ // same id regardless of the registry's on-disk order: the bare name and
330
+ // each path-derived suffix become a pure function of the resolved-path set,
331
+ // not of iteration order, so a memorized id can't drift to a different
332
+ // clone after a registry reorder (#2067 follow-up).
333
+ const ordered = [...entries].sort((a, b) => {
334
+ const ra = path.resolve(a.path);
335
+ const rb = path.resolve(b.path);
336
+ return ra < rb ? -1 : ra > rb ? 1 : 0;
337
+ });
338
+ for (const entry of ordered) {
339
+ // path.resolve (not canonicalizePath) matches the pre-#2054 collision
340
+ // check and keeps refreshRepos free of mockable deps on the hot init
341
+ // path. registerRepo writes path.resolve'd paths (not realpath), and
342
+ // resolveRepoFromCache canonicalizes both sides when matching by path, so
343
+ // keying id assignment on path.resolve here is consistent and correct.
344
+ const resolved = path.resolve(entry.path);
345
+ const id = this.assignRepoId(entry.name, entry.path, resolved, assigned);
303
346
  const storagePath = entry.storagePath;
304
347
  const lbugPath = path.join(storagePath, 'lbug');
305
348
  // Clean up any leftover KuzuDB files from before the LadybugDB migration.
@@ -319,10 +362,10 @@ export class LocalBackend {
319
362
  remoteUrl: entry.remoteUrl,
320
363
  stats: entry.stats,
321
364
  };
322
- this.repos.set(id, handle);
365
+ nextRepos.set(id, handle);
323
366
  // Build lightweight context (no LadybugDB needed)
324
367
  const s = entry.stats || {};
325
- this.contextCache.set(id, {
368
+ nextContext.set(id, {
326
369
  projectName: entry.name,
327
370
  stats: {
328
371
  fileCount: s.files || 0,
@@ -332,36 +375,78 @@ export class LocalBackend {
332
375
  },
333
376
  });
334
377
  }
335
- // Prune repos that no longer exist in the registry
336
- for (const id of this.repos.keys()) {
337
- if (!freshIds.has(id)) {
338
- this.repos.delete(id);
339
- this.contextCache.delete(id);
340
- this.initializedRepos.delete(id);
341
- }
378
+ // Prune per-clone pool state for databases that are no longer registered.
379
+ // The LadybugDB pool and the init/staleness/reinit maps are keyed by the
380
+ // immutable lbugPath (see ensureInitialized), so a repo id that merely
381
+ // moves to a different clone needs NO eviction — distinct clones have
382
+ // distinct lbugPaths and can never share a pool entry, which is what closes
383
+ // the resolve→query wrong-clone window for good (#2067). Only a path that
384
+ // dropped out of the registry must release its pooled connection + state.
385
+ const liveLbugPaths = new Set([...nextRepos.values()].map((h) => h.lbugPath));
386
+ for (const prev of this.repos.values()) {
387
+ if (liveLbugPaths.has(prev.lbugPath))
388
+ continue;
389
+ this.initializedRepos.delete(prev.lbugPath);
390
+ this.lastStalenessCheck.delete(prev.lbugPath);
391
+ this.reinitPromises.delete(prev.lbugPath);
392
+ closeLbug(prev.lbugPath).catch(() => { });
342
393
  }
394
+ this.repos = nextRepos;
395
+ this.contextCache = nextContext;
343
396
  }
344
397
  /**
345
- * Generate a stable repo ID from name + path.
346
- * If names collide, append a hash of the path.
398
+ * Assign a collision-free in-memory id for a registered repo.
399
+ *
400
+ * - Unique name → the bare lowercased name.
401
+ * - Duplicate name → a path-derived suffix. The *first* colliding clone keeps
402
+ * the legacy `base64url(path)` suffix so ids generated before #2054 still
403
+ * resolve (the #1658 hashed-id tier). base64url is an encoding, not a hash:
404
+ * it preserves byte order, so sibling clones under one parent (e.g.
405
+ * `.../REPO_2` and `.../REPO_3`) yield identical leading characters and thus
406
+ * the same sliced suffix. Any further collision therefore falls back to a
407
+ * content hash of the *resolved* path (order-insensitive), extended
408
+ * deterministically until unique.
409
+ *
410
+ * `assigned` maps every id handed out in this refresh to its resolved path,
411
+ * so a candidate is "free" when it is unused or already owned by this exact
412
+ * path. This method records its own assignment into `assigned` before
413
+ * returning, so the map-update is the function's invariant, not a caller
414
+ * obligation. A returned id never overwrites a different path's handle (#2054).
347
415
  */
348
- repoId(name, repoPath) {
416
+ assignRepoId(name, repoPath, resolved, assigned) {
349
417
  const base = name.toLowerCase();
350
- // Check for name collision with a different path
351
- for (const [id, handle] of this.repos) {
352
- if (id === base && handle.repoPath !== path.resolve(repoPath)) {
353
- // Collision — use path hash
354
- // Lowercase the hash so it survives the `paramLower` lookup in
355
- // resolveRepoFromCache base64url retains mixed case, but the id
356
- // tier compares against `repoParam.toLowerCase()` (#1658 follow-up).
357
- const hash = Buffer.from(repoPath)
358
- .toString('base64url')
359
- .slice(0, REPO_ID_HASH_LENGTH)
360
- .toLowerCase();
361
- return `${base}-${hash}`;
362
- }
363
- }
364
- return base;
418
+ const free = (id) => {
419
+ const owner = assigned.get(id);
420
+ return owner === undefined || owner === resolved;
421
+ };
422
+ // Record the assignment so subsequent entries in the same refresh see this
423
+ // id as taken (the function owns its own invariant).
424
+ const claim = (id) => {
425
+ assigned.set(id, resolved);
426
+ return id;
427
+ };
428
+ if (free(base))
429
+ return claim(base);
430
+ // Legacy suffix from the *raw* path — kept byte-for-byte so the first
431
+ // colliding duplicate keeps the id it had before #2054 (#1658 tier).
432
+ const legacy = `${base}-${Buffer.from(repoPath)
433
+ .toString('base64url')
434
+ .slice(0, REPO_ID_HASH_LENGTH)
435
+ .toLowerCase()}`;
436
+ if (free(legacy))
437
+ return claim(legacy);
438
+ // Real collision — hash the resolved path. Lowercase hex survives the
439
+ // `paramLower` lookup in resolveRepoFromCache.
440
+ const digest = createHash('sha256').update(resolved).digest('hex');
441
+ for (let len = REPO_ID_HASH_LENGTH; len <= digest.length; len++) {
442
+ const candidate = `${base}-${digest.slice(0, len)}`;
443
+ if (free(candidate))
444
+ return claim(candidate);
445
+ }
446
+ // Two distinct resolved paths sharing a full SHA-256 digest is a hash
447
+ // break, not a runtime condition — fail loudly rather than silently
448
+ // overwrite a different repo's handle (#2054 invariant).
449
+ throw new Error(`GitNexus internal: unable to assign a unique repo id for "${name}" at ${repoPath}`);
365
450
  }
366
451
  // ─── Repo Resolution ─────────────────────────────────────────────
367
452
  /**
@@ -521,44 +606,52 @@ export class LocalBackend {
521
606
  };
522
607
  }
523
608
  // ─── Lazy LadybugDB Init ────────────────────────────────────────────
524
- async ensureInitialized(repoId) {
609
+ /**
610
+ * Ensure the LadybugDB pool is open for the *resolved* repo.
611
+ *
612
+ * Takes the `RepoHandle` the caller resolved — NOT a bare id — and keys the
613
+ * pool (and the init/staleness/reinit maps) by the immutable `lbugPath`. Two
614
+ * things matter for multi-clone correctness: (1) the handle is the one the
615
+ * caller resolved, so a concurrent `refreshRepos` can't substitute a different
616
+ * clone; (2) the pool key is the database path, so distinct clones never share
617
+ * a pool entry even when their name-derived id transiently collides (#2067).
618
+ */
619
+ async ensureInitialized(repo) {
620
+ const poolKey = repo.lbugPath;
525
621
  // If a reinit is already in progress for this repo, wait for it
526
- const pending = this.reinitPromises.get(repoId);
622
+ const pending = this.reinitPromises.get(poolKey);
527
623
  if (pending)
528
624
  return pending;
529
- const handle = this.repos.get(repoId);
530
- if (!handle)
531
- throw new Error(`Unknown repo: ${repoId}`);
532
625
  // Check if the index was rebuilt since we opened the connection (#297).
533
626
  // Throttle staleness checks to at most once per 5 seconds per repo to
534
627
  // avoid an fs.readFile round-trip on every tool invocation.
535
- if (this.initializedRepos.has(repoId) && isLbugReady(repoId)) {
628
+ if (this.initializedRepos.has(poolKey) && isLbugReady(poolKey)) {
536
629
  const now = Date.now();
537
- const lastCheck = this.lastStalenessCheck.get(repoId) ?? 0;
630
+ const lastCheck = this.lastStalenessCheck.get(poolKey) ?? 0;
538
631
  if (now - lastCheck < 5000)
539
632
  return; // Checked recently — skip
540
- this.lastStalenessCheck.set(repoId, now);
633
+ this.lastStalenessCheck.set(poolKey, now);
541
634
  try {
542
- const metaPath = path.join(handle.storagePath, 'meta.json');
635
+ const metaPath = path.join(repo.storagePath, 'meta.json');
543
636
  const metaRaw = await fs.readFile(metaPath, 'utf-8');
544
637
  const meta = JSON.parse(metaRaw);
545
- if (meta.indexedAt && meta.indexedAt !== handle.indexedAt) {
638
+ if (meta.indexedAt && meta.indexedAt !== repo.indexedAt) {
546
639
  // Index was rebuilt — close stale connection and re-init.
547
640
  // Wrap in reinitPromises to prevent TOCTOU race where concurrent
548
641
  // callers both detect staleness and double-close the pool.
549
642
  const reinit = (async () => {
550
643
  try {
551
- await closeLbug(repoId);
552
- this.initializedRepos.delete(repoId);
553
- handle.indexedAt = meta.indexedAt;
554
- await initLbug(repoId, handle.lbugPath);
555
- this.initializedRepos.add(repoId);
644
+ await closeLbug(poolKey);
645
+ this.initializedRepos.delete(poolKey);
646
+ repo.indexedAt = meta.indexedAt;
647
+ await initLbug(poolKey, repo.lbugPath);
648
+ this.initializedRepos.add(poolKey);
556
649
  }
557
650
  finally {
558
- this.reinitPromises.delete(repoId);
651
+ this.reinitPromises.delete(poolKey);
559
652
  }
560
653
  })();
561
- this.reinitPromises.set(repoId, reinit);
654
+ this.reinitPromises.set(poolKey, reinit);
562
655
  return reinit;
563
656
  }
564
657
  else {
@@ -570,12 +663,12 @@ export class LocalBackend {
570
663
  }
571
664
  }
572
665
  try {
573
- await initLbug(repoId, handle.lbugPath);
574
- this.initializedRepos.add(repoId);
666
+ await initLbug(poolKey, repo.lbugPath);
667
+ this.initializedRepos.add(poolKey);
575
668
  }
576
669
  catch (err) {
577
670
  // If lock error, mark as not initialized so next call retries
578
- this.initializedRepos.delete(repoId);
671
+ this.initializedRepos.delete(poolKey);
579
672
  throw err;
580
673
  }
581
674
  }
@@ -771,7 +864,7 @@ export class LocalBackend {
771
864
  if (!params.query?.trim()) {
772
865
  return { error: 'query parameter is required and cannot be empty.' };
773
866
  }
774
- await this.ensureInitialized(repo.id);
867
+ await this.ensureInitialized(repo);
775
868
  const processLimit = params.limit || 5;
776
869
  const maxSymbolsPerProcess = params.max_symbols || 10;
777
870
  const includeContent = params.include_content ?? false;
@@ -846,7 +939,7 @@ export class LocalBackend {
846
939
  // Find processes this symbol participates in
847
940
  let processRows = [];
848
941
  try {
849
- processRows = await executeParameterized(repo.id, `
942
+ processRows = await executeParameterized(repo.lbugPath, `
850
943
  MATCH (n {id: $nodeId})-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
851
944
  RETURN p.id AS pid, p.label AS label, p.heuristicLabel AS heuristicLabel, p.processType AS processType, p.stepCount AS stepCount, r.step AS step
852
945
  `, { nodeId: sym.nodeId });
@@ -858,7 +951,7 @@ export class LocalBackend {
858
951
  let cohesion = 0;
859
952
  let module;
860
953
  try {
861
- const cohesionRows = await executeParameterized(repo.id, `
954
+ const cohesionRows = await executeParameterized(repo.lbugPath, `
862
955
  MATCH (n {id: $nodeId})-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
863
956
  RETURN c.cohesion AS cohesion, c.heuristicLabel AS module
864
957
  LIMIT 1
@@ -875,7 +968,7 @@ export class LocalBackend {
875
968
  let content;
876
969
  if (includeContent) {
877
970
  try {
878
- const contentRows = await executeParameterized(repo.id, `
971
+ const contentRows = await executeParameterized(repo.lbugPath, `
879
972
  MATCH (n {id: $nodeId})
880
973
  RETURN n.content AS content
881
974
  `, { nodeId: sym.nodeId });
@@ -998,7 +1091,7 @@ export class LocalBackend {
998
1091
  }
999
1092
  let ftsResponse;
1000
1093
  try {
1001
- ftsResponse = await searchFTSFromLbug(query, limit, repo.id);
1094
+ ftsResponse = await searchFTSFromLbug(query, limit, repo.lbugPath);
1002
1095
  }
1003
1096
  catch (err) {
1004
1097
  logger.error({ err: err.message }, 'GitNexus: BM25/FTS search failed (FTS indexes may not exist) -');
@@ -1017,12 +1110,12 @@ export class LocalBackend {
1017
1110
  // the nodes that actually scored highest in the BM25 index.
1018
1111
  const nodeIds = bm25Result.nodeIds?.length ? bm25Result.nodeIds : null;
1019
1112
  const symbols = nodeIds
1020
- ? await executeParameterized(repo.id, `
1113
+ ? await executeParameterized(repo.lbugPath, `
1021
1114
  MATCH (n)
1022
1115
  WHERE n.id IN $nodeIds
1023
1116
  RETURN n.id AS id, n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine
1024
1117
  `, { nodeIds })
1025
- : await executeParameterized(repo.id, `
1118
+ : await executeParameterized(repo.lbugPath, `
1026
1119
  MATCH (n)
1027
1120
  WHERE n.filePath = $filePath
1028
1121
  RETURN n.id AS id, n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine
@@ -1069,7 +1162,7 @@ export class LocalBackend {
1069
1162
  async semanticSearch(repo, query, limit) {
1070
1163
  try {
1071
1164
  // Check if embedding table exists before loading the model (avoids heavy model init when embeddings are off)
1072
- const tableCheck = await executeQuery(repo.id, `MATCH (e:${EMBEDDING_TABLE_NAME}) RETURN COUNT(*) AS cnt LIMIT 1`);
1165
+ const tableCheck = await executeQuery(repo.lbugPath, `MATCH (e:${EMBEDDING_TABLE_NAME}) RETURN COUNT(*) AS cnt LIMIT 1`);
1073
1166
  if (!tableCheck.length || (tableCheck[0].cnt ?? tableCheck[0][0]) === 0)
1074
1167
  return [];
1075
1168
  const { embedQuery, getEmbeddingDims } = await import('../core/embedder.js');
@@ -1090,7 +1183,7 @@ export class LocalBackend {
1090
1183
  emb.startLine AS startLine, emb.endLine AS endLine, distance
1091
1184
  ORDER BY distance
1092
1185
  `;
1093
- const embResults = await executeQuery(repo.id, vectorQuery);
1186
+ const embResults = await executeQuery(repo.lbugPath, vectorQuery);
1094
1187
  return embResults.map((row) => ({
1095
1188
  nodeId: row.nodeId ?? row[0],
1096
1189
  chunkIndex: row.chunkIndex ?? row[1] ?? 0,
@@ -1117,7 +1210,7 @@ export class LocalBackend {
1117
1210
  const exactLimit = getExactScanLimit();
1118
1211
  if (embeddingCount > exactLimit)
1119
1212
  return [];
1120
- const rows = await executeQuery(repo.id, `
1213
+ const rows = await executeQuery(repo.lbugPath, `
1121
1214
  MATCH (e:${EMBEDDING_TABLE_NAME})
1122
1215
  RETURN e.nodeId AS nodeId, e.chunkIndex AS chunkIndex,
1123
1216
  e.startLine AS startLine, e.endLine AS endLine, e.embedding AS embedding
@@ -1152,7 +1245,7 @@ export class LocalBackend {
1152
1245
  const nodeQuery = label === 'File'
1153
1246
  ? `MATCH (n:File {id: $nodeId}) RETURN n.name AS name, n.filePath AS filePath`
1154
1247
  : `MATCH (n:\`${label}\` {id: $nodeId}) RETURN n.name AS name, n.filePath AS filePath`;
1155
- const nodeRows = await executeParameterized(repo.id, nodeQuery, { nodeId });
1248
+ const nodeRows = await executeParameterized(repo.lbugPath, nodeQuery, { nodeId });
1156
1249
  if (nodeRows.length > 0) {
1157
1250
  const nodeRow = nodeRows[0];
1158
1251
  results.push({
@@ -1180,8 +1273,8 @@ export class LocalBackend {
1180
1273
  return this.cypher(repo, { query, params });
1181
1274
  }
1182
1275
  async cypher(repo, request) {
1183
- await this.ensureInitialized(repo.id);
1184
- if (!isLbugReady(repo.id)) {
1276
+ await this.ensureInitialized(repo);
1277
+ if (!isLbugReady(repo.lbugPath)) {
1185
1278
  return { error: 'LadybugDB not ready. Index may be corrupted.' };
1186
1279
  }
1187
1280
  if (request.params !== undefined && !isValidQueryParams(request.params)) {
@@ -1190,7 +1283,7 @@ export class LocalBackend {
1190
1283
  };
1191
1284
  }
1192
1285
  try {
1193
- const result = await executeParameterized(repo.id, request.query, request.params ?? {});
1286
+ const result = await executeParameterized(repo.lbugPath, request.query, request.params ?? {});
1194
1287
  return result;
1195
1288
  }
1196
1289
  catch (err) {
@@ -1283,7 +1376,7 @@ export class LocalBackend {
1283
1376
  .sort((a, b) => b.symbolCount - a.symbolCount);
1284
1377
  }
1285
1378
  async overview(repo, params) {
1286
- await this.ensureInitialized(repo.id);
1379
+ await this.ensureInitialized(repo);
1287
1380
  const limit = params.limit || 20;
1288
1381
  const result = {
1289
1382
  repo: repo.name,
@@ -1296,7 +1389,7 @@ export class LocalBackend {
1296
1389
  try {
1297
1390
  // Fetch more raw communities than the display limit so aggregation has enough data
1298
1391
  const rawLimit = Math.max(limit * 5, 200);
1299
- const clusters = await executeQuery(repo.id, `
1392
+ const clusters = await executeQuery(repo.lbugPath, `
1300
1393
  MATCH (c:Community)
1301
1394
  RETURN c.id AS id, c.label AS label, c.heuristicLabel AS heuristicLabel, c.cohesion AS cohesion, c.symbolCount AS symbolCount
1302
1395
  ORDER BY c.symbolCount DESC
@@ -1317,7 +1410,7 @@ export class LocalBackend {
1317
1410
  }
1318
1411
  if (params.showProcesses !== false) {
1319
1412
  try {
1320
- const processes = await executeQuery(repo.id, `
1413
+ const processes = await executeQuery(repo.lbugPath, `
1321
1414
  MATCH (p:Process)
1322
1415
  RETURN p.id AS id, p.label AS label, p.heuristicLabel AS heuristicLabel, p.processType AS processType, p.stepCount AS stepCount
1323
1416
  ORDER BY p.stepCount DESC
@@ -1355,7 +1448,7 @@ export class LocalBackend {
1355
1448
  if (ids.length === 0)
1356
1449
  return;
1357
1450
  try {
1358
- const rows = await executeParameterized(repo.id, `
1451
+ const rows = await executeParameterized(repo.lbugPath, `
1359
1452
  MATCH (n:\`Class\`) WHERE n.id IN $ids RETURN n.id AS id, 'Class' AS label
1360
1453
  UNION ALL
1361
1454
  MATCH (n:\`Interface\`) WHERE n.id IN $ids RETURN n.id AS id, 'Interface' AS label
@@ -1440,7 +1533,7 @@ export class LocalBackend {
1440
1533
  const selectClause = `n.id AS id, n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine${include_content ? ', n.content AS content' : ''}`;
1441
1534
  // Direct UID — zero-ambiguity path.
1442
1535
  if (uid) {
1443
- const rows = await executeParameterized(repo.id, `MATCH (n {id: $uid}) RETURN ${selectClause} LIMIT 1`, { uid });
1536
+ const rows = await executeParameterized(repo.lbugPath, `MATCH (n {id: $uid}) RETURN ${selectClause} LIMIT 1`, { uid });
1444
1537
  if (rows.length === 0)
1445
1538
  return { kind: 'not_found' };
1446
1539
  const r = rows[0];
@@ -1476,7 +1569,7 @@ export class LocalBackend {
1476
1569
  }
1477
1570
  // LIMIT 20 (was 10) — scoring is the point now, so give the ranker
1478
1571
  // headroom instead of arbitrary truncation.
1479
- const rows = await executeParameterized(repo.id, `MATCH (n) ${whereClause} RETURN ${selectClause} LIMIT 20`, queryParams);
1572
+ const rows = await executeParameterized(repo.lbugPath, `MATCH (n) ${whereClause} RETURN ${selectClause} LIMIT 20`, queryParams);
1480
1573
  if (rows.length === 0)
1481
1574
  return { kind: 'not_found' };
1482
1575
  // Normalise row shape across object / tuple returns from LadybugDB.
@@ -1509,7 +1602,7 @@ export class LocalBackend {
1509
1602
  if (ambiguousType) {
1510
1603
  const candidateIds = normalized.map((s) => s.id).filter(Boolean);
1511
1604
  for (const label of ['Class', 'Interface']) {
1512
- const labelRows = await executeParameterized(repo.id, `MATCH (n:\`${label}\`) WHERE n.id IN $candidateIds RETURN n.id AS id LIMIT 1`, { candidateIds }).catch(() => []);
1605
+ const labelRows = await executeParameterized(repo.lbugPath, `MATCH (n:\`${label}\`) WHERE n.id IN $candidateIds RETURN n.id AS id LIMIT 1`, { candidateIds }).catch(() => []);
1513
1606
  if (labelRows.length > 0) {
1514
1607
  const preferredId = labelRows[0].id ?? labelRows[0][0];
1515
1608
  const preferred = normalized.find((s) => s.id === preferredId);
@@ -1588,7 +1681,7 @@ export class LocalBackend {
1588
1681
  }
1589
1682
  }
1590
1683
  async _contextImpl(repo, params) {
1591
- await this.ensureInitialized(repo.id);
1684
+ await this.ensureInitialized(repo);
1592
1685
  const { name, uid, file_path, kind, include_content } = params;
1593
1686
  if (!name && !uid) {
1594
1687
  return { error: 'Either "name" or "uid" parameter is required.' };
@@ -1616,7 +1709,7 @@ export class LocalBackend {
1616
1709
  const resolvedLabel = outcome.resolvedLabel;
1617
1710
  const symId = sym.id;
1618
1711
  // Categorized incoming refs
1619
- const incomingRows = await executeParameterized(repo.id, `
1712
+ const incomingRows = await executeParameterized(repo.lbugPath, `
1620
1713
  MATCH (caller)-[r:CodeRelation]->(n {id: $symId})
1621
1714
  WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'USES', 'HAS_METHOD', 'HAS_PROPERTY', 'METHOD_OVERRIDES', 'OVERRIDES', 'METHOD_IMPLEMENTS', 'ACCESSES']
1622
1715
  RETURN r.type AS relType, caller.id AS uid, caller.name AS name, caller.filePath AS filePath, labels(caller)[0] AS kind
@@ -1636,7 +1729,7 @@ export class LocalBackend {
1636
1729
  if (!isClassLike && symRawType === '') {
1637
1730
  try {
1638
1731
  // Single UNION query instead of two serial round-trips.
1639
- const typeCheck = await executeParameterized(repo.id, `
1732
+ const typeCheck = await executeParameterized(repo.lbugPath, `
1640
1733
  MATCH (n:Class) WHERE n.id = $symId RETURN 'Class' AS label LIMIT 1
1641
1734
  UNION ALL
1642
1735
  MATCH (n:Interface) WHERE n.id = $symId RETURN 'Interface' AS label LIMIT 1
@@ -1654,7 +1747,7 @@ export class LocalBackend {
1654
1747
  try {
1655
1748
  // Run incoming-ref queries in parallel — they are independent.
1656
1749
  const [ctorIncoming, fileIncoming, typedPropertyIncoming, typedProperties] = await Promise.all([
1657
- executeParameterized(repo.id, `
1750
+ executeParameterized(repo.lbugPath, `
1658
1751
  MATCH (n)-[hm:CodeRelation]->(ctor:Constructor)
1659
1752
  WHERE n.id = $symId AND hm.type = 'HAS_METHOD'
1660
1753
  MATCH (caller)-[r:CodeRelation]->(ctor)
@@ -1662,7 +1755,7 @@ export class LocalBackend {
1662
1755
  RETURN r.type AS relType, caller.id AS uid, caller.name AS name, caller.filePath AS filePath, labels(caller)[0] AS kind
1663
1756
  LIMIT 30
1664
1757
  `, { symId }),
1665
- executeParameterized(repo.id, `
1758
+ executeParameterized(repo.lbugPath, `
1666
1759
  MATCH (f:File)-[rel:CodeRelation]->(n)
1667
1760
  WHERE n.id = $symId AND rel.type = 'DEFINES'
1668
1761
  MATCH (caller)-[r:CodeRelation]->(f)
@@ -1670,7 +1763,7 @@ export class LocalBackend {
1670
1763
  RETURN r.type AS relType, caller.id AS uid, caller.name AS name, caller.filePath AS filePath, labels(caller)[0] AS kind
1671
1764
  LIMIT 30
1672
1765
  `, { symId }),
1673
- executeParameterized(repo.id, `
1766
+ executeParameterized(repo.lbugPath, `
1674
1767
  MATCH (p:\`Property\`)
1675
1768
  WHERE p.declaredType = $name
1676
1769
  OR p.declaredType STARTS WITH $genericPrefix
@@ -1684,7 +1777,7 @@ export class LocalBackend {
1684
1777
  genericPrefix: `${sym.name}<`,
1685
1778
  genericArg: `<${sym.name}>`,
1686
1779
  }),
1687
- executeParameterized(repo.id, `
1780
+ executeParameterized(repo.lbugPath, `
1688
1781
  MATCH (p:\`Property\`)
1689
1782
  WHERE p.declaredType = $name
1690
1783
  OR p.declaredType STARTS WITH $genericPrefix
@@ -1716,7 +1809,7 @@ export class LocalBackend {
1716
1809
  }
1717
1810
  }
1718
1811
  // Categorized outgoing refs
1719
- const outgoingRows = await executeParameterized(repo.id, `
1812
+ const outgoingRows = await executeParameterized(repo.lbugPath, `
1720
1813
  MATCH (n {id: $symId})-[r:CodeRelation]->(target)
1721
1814
  WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'USES', 'HAS_METHOD', 'HAS_PROPERTY', 'METHOD_OVERRIDES', 'OVERRIDES', 'METHOD_IMPLEMENTS', 'ACCESSES']
1722
1815
  RETURN r.type AS relType, target.id AS uid, target.name AS name, target.filePath AS filePath, labels(target)[0] AS kind
@@ -1725,7 +1818,7 @@ export class LocalBackend {
1725
1818
  // Process participation
1726
1819
  let processRows = [];
1727
1820
  try {
1728
- processRows = await executeParameterized(repo.id, `
1821
+ processRows = await executeParameterized(repo.lbugPath, `
1729
1822
  MATCH (n {id: $symId})-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
1730
1823
  RETURN p.id AS pid, p.heuristicLabel AS label, r.step AS step, p.stepCount AS stepCount
1731
1824
  `, { symId });
@@ -1756,7 +1849,7 @@ export class LocalBackend {
1756
1849
  let methodMetadata;
1757
1850
  if (isMethodLike) {
1758
1851
  try {
1759
- const metaRows = await executeParameterized(repo.id, `
1852
+ const metaRows = await executeParameterized(repo.lbugPath, `
1760
1853
  MATCH (n {id: $symId})
1761
1854
  RETURN n.visibility AS visibility, n.isStatic AS isStatic, n.isAbstract AS isAbstract,
1762
1855
  n.isFinal AS isFinal, n.isVirtual AS isVirtual, n.isOverride AS isOverride,
@@ -1821,13 +1914,13 @@ export class LocalBackend {
1821
1914
  * Routes cluster/process types to direct graph queries.
1822
1915
  */
1823
1916
  async explore(repo, params) {
1824
- await this.ensureInitialized(repo.id);
1917
+ await this.ensureInitialized(repo);
1825
1918
  const { name, type } = params;
1826
1919
  if (type === 'symbol') {
1827
1920
  return this.context(repo, { name });
1828
1921
  }
1829
1922
  if (type === 'cluster') {
1830
- const clusters = await executeParameterized(repo.id, `
1923
+ const clusters = await executeParameterized(repo.lbugPath, `
1831
1924
  MATCH (c:Community)
1832
1925
  WHERE c.label = $clusterName OR c.heuristicLabel = $clusterName
1833
1926
  RETURN c.id AS id, c.label AS label, c.heuristicLabel AS heuristicLabel, c.cohesion AS cohesion, c.symbolCount AS symbolCount
@@ -1847,7 +1940,7 @@ export class LocalBackend {
1847
1940
  totalSymbols += s;
1848
1941
  weightedCohesion += (c.cohesion || 0) * s;
1849
1942
  }
1850
- const members = await executeParameterized(repo.id, `
1943
+ const members = await executeParameterized(repo.lbugPath, `
1851
1944
  MATCH (n)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
1852
1945
  WHERE c.label = $clusterName OR c.heuristicLabel = $clusterName
1853
1946
  RETURN DISTINCT n.name AS name, labels(n)[0] AS type, n.filePath AS filePath
@@ -1870,7 +1963,7 @@ export class LocalBackend {
1870
1963
  };
1871
1964
  }
1872
1965
  if (type === 'process') {
1873
- const processes = await executeParameterized(repo.id, `
1966
+ const processes = await executeParameterized(repo.lbugPath, `
1874
1967
  MATCH (p:Process)
1875
1968
  WHERE p.label = $processName OR p.heuristicLabel = $processName
1876
1969
  RETURN p.id AS id, p.label AS label, p.heuristicLabel AS heuristicLabel, p.processType AS processType, p.stepCount AS stepCount
@@ -1880,7 +1973,7 @@ export class LocalBackend {
1880
1973
  return { error: `Process '${name}' not found` };
1881
1974
  const proc = processes[0];
1882
1975
  const procId = proc.id || proc[0];
1883
- const steps = await executeParameterized(repo.id, `
1976
+ const steps = await executeParameterized(repo.lbugPath, `
1884
1977
  MATCH (n)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p {id: $procId})
1885
1978
  RETURN n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, r.step AS step
1886
1979
  ORDER BY r.step
@@ -1908,7 +2001,7 @@ export class LocalBackend {
1908
2001
  * Maps changed lines to indexed symbols, then finds affected processes.
1909
2002
  */
1910
2003
  async detectChanges(repo, params) {
1911
- await this.ensureInitialized(repo.id);
2004
+ await this.ensureInitialized(repo);
1912
2005
  const scope = params.scope || 'unstaged';
1913
2006
  const { execFileSync } = await import('child_process');
1914
2007
  // Build git diff args based on scope (using execFileSync to avoid shell injection)
@@ -2019,7 +2112,7 @@ export class LocalBackend {
2019
2112
  n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine
2020
2113
  `;
2021
2114
  try {
2022
- const rows = await executeParameterized(repo.id, symbolQuery, queryParams);
2115
+ const rows = await executeParameterized(repo.lbugPath, symbolQuery, queryParams);
2023
2116
  for (const sym of rows) {
2024
2117
  changedSymbols.push({
2025
2118
  id: sym.id || sym[0],
@@ -2040,7 +2133,7 @@ export class LocalBackend {
2040
2133
  const symIds = changedSymbols.map((s) => s.id);
2041
2134
  const symNameById = new Map(changedSymbols.map((s) => [s.id, s.name]));
2042
2135
  try {
2043
- const procs = await executeParameterized(repo.id, `
2136
+ const procs = await executeParameterized(repo.lbugPath, `
2044
2137
  MATCH (n)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
2045
2138
  WHERE n.id IN $ids
2046
2139
  RETURN n.id AS nodeId, p.id AS pid, p.heuristicLabel AS label,
@@ -2093,7 +2186,7 @@ export class LocalBackend {
2093
2186
  * Additional refs found via text search are tagged "text_search" (lower confidence).
2094
2187
  */
2095
2188
  async rename(repo, params) {
2096
- await this.ensureInitialized(repo.id);
2189
+ await this.ensureInitialized(repo);
2097
2190
  const { new_name, file_path } = params;
2098
2191
  const dry_run = params.dry_run ?? true;
2099
2192
  if (!params.symbol_name && !params.symbol_uid) {
@@ -2275,7 +2368,7 @@ export class LocalBackend {
2275
2368
  }
2276
2369
  }
2277
2370
  async _impactImpl(repo, params) {
2278
- await this.ensureInitialized(repo.id);
2371
+ await this.ensureInitialized(repo);
2279
2372
  const { target, direction } = params;
2280
2373
  const maxDepth = params.maxDepth || 3;
2281
2374
  // Map legacy relation type names before filtering (backward compat for OVERRIDES → METHOD_OVERRIDES)
@@ -2403,14 +2496,14 @@ export class LocalBackend {
2403
2496
  try {
2404
2497
  // Run both seed queries in parallel — they are independent.
2405
2498
  const [ctorRows, fileRows] = await Promise.all([
2406
- executeParameterized(repo.id, `
2499
+ executeParameterized(repo.lbugPath, `
2407
2500
  MATCH (n)-[hm:CodeRelation]->(c:Constructor)
2408
2501
  WHERE n.id = $symId AND hm.type = 'HAS_METHOD'
2409
2502
  RETURN c.id AS id, c.name AS name, labels(c)[0] AS type, c.filePath AS filePath
2410
2503
  `, { symId }),
2411
2504
  // Restrict to DEFINES edges only — other File->Class edge types (if
2412
2505
  // any) should not be treated as the owning file relationship.
2413
- executeParameterized(repo.id, `
2506
+ executeParameterized(repo.lbugPath, `
2414
2507
  MATCH (f:File)-[rel:CodeRelation]->(n)
2415
2508
  WHERE n.id = $symId AND rel.type = 'DEFINES'
2416
2509
  RETURN f.id AS id, f.name AS name, labels(f)[0] AS type, f.filePath AS filePath
@@ -2430,7 +2523,7 @@ export class LocalBackend {
2430
2523
  frontier.push(rid);
2431
2524
  }
2432
2525
  }
2433
- const typedPropertyRows = await executeParameterized(repo.id, `
2526
+ const typedPropertyRows = await executeParameterized(repo.lbugPath, `
2434
2527
  MATCH (p:\`Property\`)
2435
2528
  WHERE p.declaredType = $name
2436
2529
  OR p.declaredType STARTS WITH $genericPrefix
@@ -2461,7 +2554,7 @@ export class LocalBackend {
2461
2554
  ? `MATCH (caller)-[r:CodeRelation]->(n) WHERE n.id IN $frontierIds AND r.type IN $relTypes${confidenceFilter} RETURN n.id AS sourceId, caller.id AS id, caller.name AS name, labels(caller)[0] AS type, caller.filePath AS filePath, r.type AS relType, r.confidence AS confidence`
2462
2555
  : `MATCH (n)-[r:CodeRelation]->(callee) WHERE n.id IN $frontierIds AND r.type IN $relTypes${confidenceFilter} RETURN n.id AS sourceId, callee.id AS id, callee.name AS name, labels(callee)[0] AS type, callee.filePath AS filePath, r.type AS relType, r.confidence AS confidence`;
2463
2556
  try {
2464
- const related = await executeParameterized(repo.id, query, {
2557
+ const related = await executeParameterized(repo.lbugPath, query, {
2465
2558
  frontierIds: frontier,
2466
2559
  relTypes: relationTypes,
2467
2560
  ...(safeMinConfidence > 0 ? { minConfidence: safeMinConfidence } : {}),
@@ -2541,7 +2634,7 @@ export class LocalBackend {
2541
2634
  const ids = chunk.map((item) => String(item.id ?? ''));
2542
2635
  try {
2543
2636
  // Use parameterized list to avoid building long query strings
2544
- const rows = await executeParameterized(repo.id, `
2637
+ const rows = await executeParameterized(repo.lbugPath, `
2545
2638
  MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
2546
2639
  WHERE s.id IN $ids
2547
2640
  WITH p, COUNT(DISTINCT s.id) AS hits, MIN(r.step) AS minStep
@@ -2607,7 +2700,7 @@ export class LocalBackend {
2607
2700
  try {
2608
2701
  const pIds = Array.from(processesMissingMinStep);
2609
2702
  const allImpactedIds = impacted.map((it) => String(it.id ?? ''));
2610
- const missingRows = await executeParameterized(repo.id, `
2703
+ const missingRows = await executeParameterized(repo.lbugPath, `
2611
2704
  MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
2612
2705
  WHERE p.id IN $pIds AND s.id IN $ids
2613
2706
  RETURN p.id AS pid, MIN(r.step) AS minStep
@@ -2659,7 +2752,7 @@ export class LocalBackend {
2659
2752
  if (!idsChunk || idsChunk.length === 0)
2660
2753
  return;
2661
2754
  try {
2662
- const rows = await executeParameterized(repo.id, `
2755
+ const rows = await executeParameterized(repo.lbugPath, `
2663
2756
  MATCH (s)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
2664
2757
  WHERE s.id IN $ids
2665
2758
  RETURN c.heuristicLabel AS name, COUNT(DISTINCT s.id) AS hits
@@ -2688,7 +2781,7 @@ export class LocalBackend {
2688
2781
  if (!idsChunk || idsChunk.length === 0)
2689
2782
  return;
2690
2783
  try {
2691
- const rows = await executeParameterized(repo.id, `
2784
+ const rows = await executeParameterized(repo.lbugPath, `
2692
2785
  MATCH (s)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
2693
2786
  WHERE s.id IN $ids
2694
2787
  RETURN DISTINCT c.heuristicLabel AS name
@@ -2815,7 +2908,7 @@ export class LocalBackend {
2815
2908
  for (let i = 0; i < pageIdArr.length; i += CHUNK_SIZE) {
2816
2909
  const chunkIds = pageIdArr.slice(i, i + CHUNK_SIZE);
2817
2910
  try {
2818
- const rows = await executeParameterized(repo.id, `
2911
+ const rows = await executeParameterized(repo.lbugPath, `
2819
2912
  MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
2820
2913
  WHERE s.id IN $ids
2821
2914
  RETURN s.id AS sid, p.id AS pid, p.heuristicLabel AS pName,
@@ -2876,20 +2969,25 @@ export class LocalBackend {
2876
2969
  // resolves the await regardless of how long this body runs.
2877
2970
  if (opts.signal?.aborted)
2878
2971
  return null;
2972
+ let repo;
2879
2973
  try {
2880
2974
  await this.refreshRepos();
2881
- await this.ensureInitialized(repoId);
2975
+ // Fetch the resolved handle BEFORE init and pass it through, so a
2976
+ // concurrent refresh can't remap the id to a different clone (#2067).
2977
+ repo = this.repos.get(repoId);
2978
+ if (repo)
2979
+ await this.ensureInitialized(repo);
2882
2980
  }
2883
2981
  catch {
2884
2982
  return null;
2885
2983
  }
2886
- const repo = this.repos.get(repoId);
2887
2984
  if (!repo)
2888
- return null;
2985
+ return null; // unknown repo → null (preserves contract)
2889
2986
  const dir = direction === 'downstream' ? 'downstream' : 'upstream';
2890
2987
  let rows;
2891
2988
  try {
2892
- rows = await executeParameterized(repoId, `MATCH (n) WHERE n.id = $uid
2989
+ rows = await executeParameterized(repo.lbugPath, // pool keyed by the resolved clone's path, not the id
2990
+ `MATCH (n) WHERE n.id = $uid
2893
2991
  RETURN n.id AS id, n.name AS name, n.filePath AS filePath, labels(n)[0] AS type
2894
2992
  LIMIT 1`, { uid });
2895
2993
  }
@@ -3199,10 +3297,10 @@ export class LocalBackend {
3199
3297
  return result;
3200
3298
  }
3201
3299
  async routeMap(repo, params) {
3202
- await this.ensureInitialized(repo.id);
3300
+ await this.ensureInitialized(repo);
3203
3301
  const routeFilter = params.route ? `AND n.name CONTAINS $route` : '';
3204
3302
  const queryParams = params.route ? { route: params.route } : {};
3205
- const routes = await this.fetchRoutesWithConsumers(repo.id, routeFilter, queryParams);
3303
+ const routes = await this.fetchRoutesWithConsumers(repo.lbugPath, routeFilter, queryParams);
3206
3304
  if (routes.length === 0) {
3207
3305
  return {
3208
3306
  routes: [],
@@ -3212,7 +3310,7 @@ export class LocalBackend {
3212
3310
  : 'No routes found in this project.',
3213
3311
  };
3214
3312
  }
3215
- const flowMap = await this.fetchLinkedFlowsBatch(repo.id, routes.map((r) => r.id));
3313
+ const flowMap = await this.fetchLinkedFlowsBatch(repo.lbugPath, routes.map((r) => r.id));
3216
3314
  return {
3217
3315
  routes: routes.map((r) => ({
3218
3316
  route: r.name,
@@ -3225,10 +3323,10 @@ export class LocalBackend {
3225
3323
  };
3226
3324
  }
3227
3325
  async shapeCheck(repo, params) {
3228
- await this.ensureInitialized(repo.id);
3326
+ await this.ensureInitialized(repo);
3229
3327
  const routeFilter = params.route ? `AND n.name CONTAINS $route` : '';
3230
3328
  const queryParams = params.route ? { route: params.route } : {};
3231
- const allRoutes = await this.fetchRoutesWithConsumers(repo.id, routeFilter, queryParams);
3329
+ const allRoutes = await this.fetchRoutesWithConsumers(repo.lbugPath, routeFilter, queryParams);
3232
3330
  const results = allRoutes
3233
3331
  .filter((r) => ((r.responseKeys && r.responseKeys.length > 0) ||
3234
3332
  (r.errorKeys && r.errorKeys.length > 0)) &&
@@ -3291,10 +3389,10 @@ export class LocalBackend {
3291
3389
  };
3292
3390
  }
3293
3391
  async toolMap(repo, params) {
3294
- await this.ensureInitialized(repo.id);
3392
+ await this.ensureInitialized(repo);
3295
3393
  const toolFilter = params.tool ? `AND n.name CONTAINS $tool` : '';
3296
3394
  const queryParams = params.tool ? { tool: params.tool } : {};
3297
- const rows = await executeParameterized(repo.id, `
3395
+ const rows = await executeParameterized(repo.lbugPath, `
3298
3396
  MATCH (n:Tool)
3299
3397
  WHERE n.id STARTS WITH 'Tool:' ${toolFilter}
3300
3398
  RETURN n.id AS id, n.name AS name, n.filePath AS filePath, n.description AS description
@@ -3307,7 +3405,7 @@ export class LocalBackend {
3307
3405
  };
3308
3406
  }
3309
3407
  const toolIds = rows.map((r) => r.id ?? r[0]);
3310
- const flowMap = await this.fetchLinkedFlowsBatch(repo.id, toolIds);
3408
+ const flowMap = await this.fetchLinkedFlowsBatch(repo.lbugPath, toolIds);
3311
3409
  return {
3312
3410
  tools: rows.map((r) => {
3313
3411
  const id = r.id ?? r[0];
@@ -3322,7 +3420,7 @@ export class LocalBackend {
3322
3420
  };
3323
3421
  }
3324
3422
  async apiImpact(repo, params) {
3325
- await this.ensureInitialized(repo.id);
3423
+ await this.ensureInitialized(repo);
3326
3424
  if (!params.route && !params.file) {
3327
3425
  return { error: 'Either "route" or "file" parameter is required.' };
3328
3426
  }
@@ -3337,12 +3435,12 @@ export class LocalBackend {
3337
3435
  routeFilter = `AND n.filePath CONTAINS $file`;
3338
3436
  queryParams.file = params.file;
3339
3437
  }
3340
- const routes = await this.fetchRoutesWithConsumers(repo.id, routeFilter, queryParams);
3438
+ const routes = await this.fetchRoutesWithConsumers(repo.lbugPath, routeFilter, queryParams);
3341
3439
  if (routes.length === 0) {
3342
3440
  const target = params.route || params.file;
3343
3441
  return { error: `No routes found matching "${target}".` };
3344
3442
  }
3345
- const flowMap = await this.fetchLinkedFlowsBatch(repo.id, routes.map((r) => r.id));
3443
+ const flowMap = await this.fetchLinkedFlowsBatch(repo.lbugPath, routes.map((r) => r.id));
3346
3444
  // Count how many routes share the same handler file (for middleware partial detection)
3347
3445
  const routeCountByHandler = new Map();
3348
3446
  for (const r of routes) {
@@ -3451,10 +3549,10 @@ export class LocalBackend {
3451
3549
  */
3452
3550
  async queryClusters(repoName, limit = 100) {
3453
3551
  const repo = await this.resolveRepo(repoName);
3454
- await this.ensureInitialized(repo.id);
3552
+ await this.ensureInitialized(repo);
3455
3553
  try {
3456
3554
  const rawLimit = Math.max(limit * 5, 200);
3457
- const clusters = await executeQuery(repo.id, `
3555
+ const clusters = await executeQuery(repo.lbugPath, `
3458
3556
  MATCH (c:Community)
3459
3557
  RETURN c.id AS id, c.label AS label, c.heuristicLabel AS heuristicLabel, c.cohesion AS cohesion, c.symbolCount AS symbolCount
3460
3558
  ORDER BY c.symbolCount DESC
@@ -3479,9 +3577,9 @@ export class LocalBackend {
3479
3577
  */
3480
3578
  async queryProcesses(repoName, limit = 50) {
3481
3579
  const repo = await this.resolveRepo(repoName);
3482
- await this.ensureInitialized(repo.id);
3580
+ await this.ensureInitialized(repo);
3483
3581
  try {
3484
- const processes = await executeQuery(repo.id, `
3582
+ const processes = await executeQuery(repo.lbugPath, `
3485
3583
  MATCH (p:Process)
3486
3584
  RETURN p.id AS id, p.label AS label, p.heuristicLabel AS heuristicLabel, p.processType AS processType, p.stepCount AS stepCount
3487
3585
  ORDER BY p.stepCount DESC
@@ -3507,8 +3605,8 @@ export class LocalBackend {
3507
3605
  */
3508
3606
  async queryClusterDetail(name, repoName) {
3509
3607
  const repo = await this.resolveRepo(repoName);
3510
- await this.ensureInitialized(repo.id);
3511
- const clusters = await executeParameterized(repo.id, `
3608
+ await this.ensureInitialized(repo);
3609
+ const clusters = await executeParameterized(repo.lbugPath, `
3512
3610
  MATCH (c:Community)
3513
3611
  WHERE c.label = $clusterName OR c.heuristicLabel = $clusterName
3514
3612
  RETURN c.id AS id, c.label AS label, c.heuristicLabel AS heuristicLabel, c.cohesion AS cohesion, c.symbolCount AS symbolCount
@@ -3528,7 +3626,7 @@ export class LocalBackend {
3528
3626
  totalSymbols += s;
3529
3627
  weightedCohesion += (c.cohesion || 0) * s;
3530
3628
  }
3531
- const members = await executeParameterized(repo.id, `
3629
+ const members = await executeParameterized(repo.lbugPath, `
3532
3630
  MATCH (n)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
3533
3631
  WHERE c.label = $clusterName OR c.heuristicLabel = $clusterName
3534
3632
  RETURN DISTINCT n.name AS name, labels(n)[0] AS type, n.filePath AS filePath
@@ -3556,8 +3654,8 @@ export class LocalBackend {
3556
3654
  */
3557
3655
  async queryProcessDetail(name, repoName) {
3558
3656
  const repo = await this.resolveRepo(repoName);
3559
- await this.ensureInitialized(repo.id);
3560
- const processes = await executeParameterized(repo.id, `
3657
+ await this.ensureInitialized(repo);
3658
+ const processes = await executeParameterized(repo.lbugPath, `
3561
3659
  MATCH (p:Process)
3562
3660
  WHERE p.label = $processName OR p.heuristicLabel = $processName
3563
3661
  RETURN p.id AS id, p.label AS label, p.heuristicLabel AS heuristicLabel, p.processType AS processType, p.stepCount AS stepCount
@@ -3567,7 +3665,7 @@ export class LocalBackend {
3567
3665
  return { error: `Process '${name}' not found` };
3568
3666
  const proc = processes[0];
3569
3667
  const procId = proc.id || proc[0];
3570
- const steps = await executeParameterized(repo.id, `
3668
+ const steps = await executeParameterized(repo.lbugPath, `
3571
3669
  MATCH (n)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p {id: $procId})
3572
3670
  RETURN n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, r.step AS step
3573
3671
  ORDER BY r.step