gitnexus 1.6.3-rc.8 → 1.6.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 (285) hide show
  1. package/README.md +21 -5
  2. package/dist/_shared/graph/types.d.ts +16 -0
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +20 -2
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/index.js +11 -0
  7. package/dist/_shared/index.js.map +1 -1
  8. package/dist/_shared/scope-resolution/def-index.js +2 -2
  9. package/dist/_shared/scope-resolution/def-index.js.map +1 -1
  10. package/dist/_shared/scope-resolution/method-dispatch-index.d.ts +8 -0
  11. package/dist/_shared/scope-resolution/method-dispatch-index.d.ts.map +1 -1
  12. package/dist/_shared/scope-resolution/method-dispatch-index.js +2 -2
  13. package/dist/_shared/scope-resolution/method-dispatch-index.js.map +1 -1
  14. package/dist/_shared/scope-resolution/module-scope-index.d.ts +8 -0
  15. package/dist/_shared/scope-resolution/module-scope-index.d.ts.map +1 -1
  16. package/dist/_shared/scope-resolution/module-scope-index.js +10 -2
  17. package/dist/_shared/scope-resolution/module-scope-index.js.map +1 -1
  18. package/dist/_shared/scope-resolution/parsed-file.d.ts +76 -0
  19. package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -0
  20. package/dist/_shared/scope-resolution/parsed-file.js +54 -0
  21. package/dist/_shared/scope-resolution/parsed-file.js.map +1 -0
  22. package/dist/_shared/scope-resolution/position-index.d.ts +12 -0
  23. package/dist/_shared/scope-resolution/position-index.d.ts.map +1 -1
  24. package/dist/_shared/scope-resolution/position-index.js +2 -2
  25. package/dist/_shared/scope-resolution/position-index.js.map +1 -1
  26. package/dist/_shared/scope-resolution/qualified-name-index.js +2 -2
  27. package/dist/_shared/scope-resolution/qualified-name-index.js.map +1 -1
  28. package/dist/_shared/scope-resolution/reference-site.d.ts +75 -0
  29. package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -0
  30. package/dist/_shared/scope-resolution/reference-site.js +24 -0
  31. package/dist/_shared/scope-resolution/reference-site.js.map +1 -0
  32. package/dist/_shared/scope-resolution/registries/class-registry.d.ts +27 -0
  33. package/dist/_shared/scope-resolution/registries/class-registry.d.ts.map +1 -0
  34. package/dist/_shared/scope-resolution/registries/class-registry.js +30 -0
  35. package/dist/_shared/scope-resolution/registries/class-registry.js.map +1 -0
  36. package/dist/_shared/scope-resolution/registries/context.d.ts +69 -0
  37. package/dist/_shared/scope-resolution/registries/context.d.ts.map +1 -0
  38. package/dist/_shared/scope-resolution/registries/context.js +44 -0
  39. package/dist/_shared/scope-resolution/registries/context.js.map +1 -0
  40. package/dist/_shared/scope-resolution/registries/evidence.d.ts +56 -0
  41. package/dist/_shared/scope-resolution/registries/evidence.d.ts.map +1 -0
  42. package/dist/_shared/scope-resolution/registries/evidence.js +150 -0
  43. package/dist/_shared/scope-resolution/registries/evidence.js.map +1 -0
  44. package/dist/_shared/scope-resolution/registries/field-registry.d.ts +26 -0
  45. package/dist/_shared/scope-resolution/registries/field-registry.d.ts.map +1 -0
  46. package/dist/_shared/scope-resolution/registries/field-registry.js +31 -0
  47. package/dist/_shared/scope-resolution/registries/field-registry.js.map +1 -0
  48. package/dist/_shared/scope-resolution/registries/lookup-core.d.ts +81 -0
  49. package/dist/_shared/scope-resolution/registries/lookup-core.d.ts.map +1 -0
  50. package/dist/_shared/scope-resolution/registries/lookup-core.js +332 -0
  51. package/dist/_shared/scope-resolution/registries/lookup-core.js.map +1 -0
  52. package/dist/_shared/scope-resolution/registries/lookup-qualified.d.ts +33 -0
  53. package/dist/_shared/scope-resolution/registries/lookup-qualified.d.ts.map +1 -0
  54. package/dist/_shared/scope-resolution/registries/lookup-qualified.js +56 -0
  55. package/dist/_shared/scope-resolution/registries/lookup-qualified.js.map +1 -0
  56. package/dist/_shared/scope-resolution/registries/method-registry.d.ts +36 -0
  57. package/dist/_shared/scope-resolution/registries/method-registry.d.ts.map +1 -0
  58. package/dist/_shared/scope-resolution/registries/method-registry.js +32 -0
  59. package/dist/_shared/scope-resolution/registries/method-registry.js.map +1 -0
  60. package/dist/_shared/scope-resolution/registries/tie-breaks.d.ts +43 -0
  61. package/dist/_shared/scope-resolution/registries/tie-breaks.d.ts.map +1 -0
  62. package/dist/_shared/scope-resolution/registries/tie-breaks.js +60 -0
  63. package/dist/_shared/scope-resolution/registries/tie-breaks.js.map +1 -0
  64. package/dist/_shared/scope-resolution/resolve-type-ref.d.ts +1 -10
  65. package/dist/_shared/scope-resolution/resolve-type-ref.d.ts.map +1 -1
  66. package/dist/_shared/scope-resolution/resolve-type-ref.js +6 -0
  67. package/dist/_shared/scope-resolution/resolve-type-ref.js.map +1 -1
  68. package/dist/_shared/scope-resolution/scope-tree.d.ts +4 -4
  69. package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
  70. package/dist/_shared/scope-resolution/scope-tree.js +3 -2
  71. package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
  72. package/dist/_shared/scope-resolution/shadow/aggregate.d.ts +6 -2
  73. package/dist/_shared/scope-resolution/shadow/aggregate.d.ts.map +1 -1
  74. package/dist/_shared/scope-resolution/shadow/aggregate.js +5 -0
  75. package/dist/_shared/scope-resolution/shadow/aggregate.js.map +1 -1
  76. package/dist/_shared/scope-resolution/types.d.ts +11 -0
  77. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  78. package/dist/cli/ai-context.js +35 -4
  79. package/dist/cli/analyze.d.ts +27 -0
  80. package/dist/cli/analyze.js +31 -1
  81. package/dist/cli/clean.js +19 -1
  82. package/dist/cli/group.js +73 -0
  83. package/dist/cli/index-repo.js +8 -1
  84. package/dist/cli/index.js +26 -1
  85. package/dist/cli/list.js +11 -1
  86. package/dist/cli/remove.d.ts +30 -0
  87. package/dist/cli/remove.js +99 -0
  88. package/dist/cli/setup.js +185 -57
  89. package/dist/cli/tool.d.ts +5 -0
  90. package/dist/cli/tool.js +42 -0
  91. package/dist/config/ignore-service.d.ts +9 -0
  92. package/dist/config/ignore-service.js +80 -13
  93. package/dist/core/embedding-mode.d.ts +30 -0
  94. package/dist/core/embedding-mode.js +30 -0
  95. package/dist/core/embeddings/ast-utils.js +22 -22
  96. package/dist/core/embeddings/chunker.js +30 -25
  97. package/dist/core/embeddings/embedding-pipeline.d.ts +6 -0
  98. package/dist/core/embeddings/embedding-pipeline.js +15 -6
  99. package/dist/core/embeddings/text-generator.d.ts +1 -1
  100. package/dist/core/embeddings/text-generator.js +33 -24
  101. package/dist/core/embeddings/types.d.ts +43 -1
  102. package/dist/core/embeddings/types.js +101 -29
  103. package/dist/core/git-staleness.d.ts +18 -0
  104. package/dist/core/git-staleness.js +108 -0
  105. package/dist/core/graph/graph.js +115 -20
  106. package/dist/core/graph/types.d.ts +12 -1
  107. package/dist/core/group/config-parser.d.ts +4 -0
  108. package/dist/core/group/config-parser.js +18 -1
  109. package/dist/core/group/cross-impact.d.ts +41 -0
  110. package/dist/core/group/cross-impact.js +441 -0
  111. package/dist/core/group/extractors/http-patterns/php.js +126 -18
  112. package/dist/core/group/group-path-utils.d.ts +17 -0
  113. package/dist/core/group/group-path-utils.js +40 -0
  114. package/dist/core/group/resolve-at-member.d.ts +10 -0
  115. package/dist/core/group/resolve-at-member.js +31 -0
  116. package/dist/core/group/service.d.ts +9 -0
  117. package/dist/core/group/service.js +259 -25
  118. package/dist/core/group/types.d.ts +30 -0
  119. package/dist/core/ingestion/ast-cache.d.ts +16 -1
  120. package/dist/core/ingestion/ast-cache.js +14 -2
  121. package/dist/core/ingestion/call-processor.js +9 -0
  122. package/dist/core/ingestion/emit-references.d.ts +88 -0
  123. package/dist/core/ingestion/emit-references.js +229 -0
  124. package/dist/core/ingestion/filesystem-walker.js +6 -4
  125. package/dist/core/ingestion/finalize-orchestrator.d.ts +63 -0
  126. package/dist/core/ingestion/finalize-orchestrator.js +139 -0
  127. package/dist/core/ingestion/framework-detection.js +6 -2
  128. package/dist/core/ingestion/import-processor.js +4 -0
  129. package/dist/core/ingestion/import-resolvers/python.js +9 -6
  130. package/dist/core/ingestion/import-target-adapter.d.ts +73 -0
  131. package/dist/core/ingestion/import-target-adapter.js +95 -0
  132. package/dist/core/ingestion/language-provider.d.ts +36 -33
  133. package/dist/core/ingestion/languages/csharp/accessor-unwrap.d.ts +21 -0
  134. package/dist/core/ingestion/languages/csharp/accessor-unwrap.js +56 -0
  135. package/dist/core/ingestion/languages/csharp/arity-metadata.d.ts +26 -0
  136. package/dist/core/ingestion/languages/csharp/arity-metadata.js +46 -0
  137. package/dist/core/ingestion/languages/csharp/arity.d.ts +23 -0
  138. package/dist/core/ingestion/languages/csharp/arity.js +37 -0
  139. package/dist/core/ingestion/languages/csharp/cache-stats.d.ts +15 -0
  140. package/dist/core/ingestion/languages/csharp/cache-stats.js +26 -0
  141. package/dist/core/ingestion/languages/csharp/captures.d.ts +19 -0
  142. package/dist/core/ingestion/languages/csharp/captures.js +249 -0
  143. package/dist/core/ingestion/languages/csharp/import-decomposer.d.ts +19 -0
  144. package/dist/core/ingestion/languages/csharp/import-decomposer.js +93 -0
  145. package/dist/core/ingestion/languages/csharp/import-target.d.ts +25 -0
  146. package/dist/core/ingestion/languages/csharp/import-target.js +123 -0
  147. package/dist/core/ingestion/languages/csharp/index.d.ts +82 -0
  148. package/dist/core/ingestion/languages/csharp/index.js +82 -0
  149. package/dist/core/ingestion/languages/csharp/interpret.d.ts +15 -0
  150. package/dist/core/ingestion/languages/csharp/interpret.js +132 -0
  151. package/dist/core/ingestion/languages/csharp/merge-bindings.d.ts +27 -0
  152. package/dist/core/ingestion/languages/csharp/merge-bindings.js +55 -0
  153. package/dist/core/ingestion/languages/csharp/namespace-siblings.d.ts +50 -0
  154. package/dist/core/ingestion/languages/csharp/namespace-siblings.js +374 -0
  155. package/dist/core/ingestion/languages/csharp/query.d.ts +35 -0
  156. package/dist/core/ingestion/languages/csharp/query.js +515 -0
  157. package/dist/core/ingestion/languages/csharp/receiver-binding.d.ts +31 -0
  158. package/dist/core/ingestion/languages/csharp/receiver-binding.js +135 -0
  159. package/dist/core/ingestion/languages/csharp/scope-resolver.d.ts +10 -0
  160. package/dist/core/ingestion/languages/csharp/scope-resolver.js +63 -0
  161. package/dist/core/ingestion/languages/csharp/simple-hooks.d.ts +53 -0
  162. package/dist/core/ingestion/languages/csharp/simple-hooks.js +76 -0
  163. package/dist/core/ingestion/languages/csharp.js +14 -0
  164. package/dist/core/ingestion/languages/python/arity-metadata.d.ts +24 -0
  165. package/dist/core/ingestion/languages/python/arity-metadata.js +45 -0
  166. package/dist/core/ingestion/languages/python/arity.d.ts +22 -0
  167. package/dist/core/ingestion/languages/python/arity.js +38 -0
  168. package/dist/core/ingestion/languages/python/cache-stats.d.ts +17 -0
  169. package/dist/core/ingestion/languages/python/cache-stats.js +28 -0
  170. package/dist/core/ingestion/languages/python/captures.d.ts +19 -0
  171. package/dist/core/ingestion/languages/python/captures.js +106 -0
  172. package/dist/core/ingestion/languages/python/import-decomposer.d.ts +15 -0
  173. package/dist/core/ingestion/languages/python/import-decomposer.js +112 -0
  174. package/dist/core/ingestion/languages/python/import-target.d.ts +21 -0
  175. package/dist/core/ingestion/languages/python/import-target.js +99 -0
  176. package/dist/core/ingestion/languages/python/index.d.ts +80 -0
  177. package/dist/core/ingestion/languages/python/index.js +80 -0
  178. package/dist/core/ingestion/languages/python/interpret.d.ts +15 -0
  179. package/dist/core/ingestion/languages/python/interpret.js +191 -0
  180. package/dist/core/ingestion/languages/python/merge-bindings.d.ts +16 -0
  181. package/dist/core/ingestion/languages/python/merge-bindings.js +44 -0
  182. package/dist/core/ingestion/languages/python/query.d.ts +9 -0
  183. package/dist/core/ingestion/languages/python/query.js +267 -0
  184. package/dist/core/ingestion/languages/python/receiver-binding.d.ts +21 -0
  185. package/dist/core/ingestion/languages/python/receiver-binding.js +116 -0
  186. package/dist/core/ingestion/languages/python/scope-resolver.d.ts +16 -0
  187. package/dist/core/ingestion/languages/python/scope-resolver.js +53 -0
  188. package/dist/core/ingestion/languages/python/simple-hooks.d.ts +23 -0
  189. package/dist/core/ingestion/languages/python/simple-hooks.js +35 -0
  190. package/dist/core/ingestion/languages/python.js +14 -0
  191. package/dist/core/ingestion/model/method-registry.d.ts +9 -0
  192. package/dist/core/ingestion/model/method-registry.js +4 -0
  193. package/dist/core/ingestion/model/scope-resolution-indexes.d.ts +59 -0
  194. package/dist/core/ingestion/model/scope-resolution-indexes.js +42 -0
  195. package/dist/core/ingestion/model/semantic-model.d.ts +64 -0
  196. package/dist/core/ingestion/model/semantic-model.js +55 -0
  197. package/dist/core/ingestion/mro-processor.js +38 -22
  198. package/dist/core/ingestion/parsing-processor.d.ts +18 -1
  199. package/dist/core/ingestion/parsing-processor.js +45 -11
  200. package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
  201. package/dist/core/ingestion/pipeline-phases/index.js +1 -0
  202. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +10 -0
  203. package/dist/core/ingestion/pipeline-phases/parse-impl.js +17 -2
  204. package/dist/core/ingestion/pipeline-phases/parse.d.ts +18 -0
  205. package/dist/core/ingestion/pipeline.js +2 -1
  206. package/dist/core/ingestion/registry-primary-flag.d.ts +86 -0
  207. package/dist/core/ingestion/registry-primary-flag.js +111 -0
  208. package/dist/core/ingestion/resolve-references.d.ts +63 -0
  209. package/dist/core/ingestion/resolve-references.js +175 -0
  210. package/dist/core/ingestion/scope-extractor-bridge.d.ts +32 -0
  211. package/dist/core/ingestion/scope-extractor-bridge.js +44 -0
  212. package/dist/core/ingestion/scope-extractor.d.ts +86 -0
  213. package/dist/core/ingestion/scope-extractor.js +758 -0
  214. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +372 -0
  215. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +212 -0
  216. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +43 -0
  217. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +79 -0
  218. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +57 -0
  219. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +112 -0
  220. package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.d.ts +17 -0
  221. package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +46 -0
  222. package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.d.ts +19 -0
  223. package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +30 -0
  224. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.d.ts +37 -0
  225. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +113 -0
  226. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +38 -0
  227. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +73 -0
  228. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +42 -0
  229. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +198 -0
  230. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +27 -0
  231. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +131 -0
  232. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.d.ts +48 -0
  233. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.js +130 -0
  234. package/dist/core/ingestion/scope-resolution/passes/mro.d.ts +42 -0
  235. package/dist/core/ingestion/scope-resolution/passes/mro.js +99 -0
  236. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +26 -0
  237. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +61 -0
  238. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +46 -0
  239. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +327 -0
  240. package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +47 -0
  241. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +130 -0
  242. package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.d.ts +68 -0
  243. package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +125 -0
  244. package/dist/core/ingestion/scope-resolution/pipeline/registry.d.ts +17 -0
  245. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +21 -0
  246. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +66 -0
  247. package/dist/core/ingestion/scope-resolution/pipeline/run.js +157 -0
  248. package/dist/core/ingestion/scope-resolution/scope/namespace-targets.d.ts +36 -0
  249. package/dist/core/ingestion/scope-resolution/scope/namespace-targets.js +52 -0
  250. package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +127 -0
  251. package/dist/core/ingestion/scope-resolution/scope/walkers.js +349 -0
  252. package/dist/core/ingestion/scope-resolution/workspace-index.d.ts +52 -0
  253. package/dist/core/ingestion/scope-resolution/workspace-index.js +61 -0
  254. package/dist/core/ingestion/shadow-harness.d.ts +113 -0
  255. package/dist/core/ingestion/shadow-harness.js +148 -0
  256. package/dist/core/ingestion/utils/ast-helpers.d.ts +19 -1
  257. package/dist/core/ingestion/utils/ast-helpers.js +70 -0
  258. package/dist/core/ingestion/utils/max-file-size.d.ts +20 -0
  259. package/dist/core/ingestion/utils/max-file-size.js +52 -0
  260. package/dist/core/ingestion/workers/parse-worker.d.ts +9 -0
  261. package/dist/core/ingestion/workers/parse-worker.js +57 -21
  262. package/dist/core/lbug/lbug-adapter.d.ts +22 -2
  263. package/dist/core/lbug/lbug-adapter.js +58 -14
  264. package/dist/core/lbug/pool-adapter.d.ts +17 -0
  265. package/dist/core/lbug/pool-adapter.js +24 -14
  266. package/dist/core/run-analyze.d.ts +32 -0
  267. package/dist/core/run-analyze.js +74 -19
  268. package/dist/core/search/bm25-index.d.ts +18 -0
  269. package/dist/core/search/bm25-index.js +125 -12
  270. package/dist/core/tree-sitter/parser-loader.js +6 -1
  271. package/dist/mcp/local/local-backend.d.ts +67 -3
  272. package/dist/mcp/local/local-backend.js +296 -34
  273. package/dist/mcp/resources.d.ts +31 -0
  274. package/dist/mcp/resources.js +100 -17
  275. package/dist/mcp/tools.d.ts +4 -1
  276. package/dist/mcp/tools.js +75 -54
  277. package/dist/server/api.js +6 -2
  278. package/dist/storage/git.d.ts +49 -0
  279. package/dist/storage/git.js +111 -0
  280. package/dist/storage/repo-manager.d.ts +246 -1
  281. package/dist/storage/repo-manager.js +391 -9
  282. package/package.json +7 -6
  283. package/scripts/bench-scope-resolution.ts +134 -0
  284. package/scripts/ci-list-migrated-languages.ts +24 -0
  285. package/skills/gitnexus-cli.md +1 -0
@@ -5,10 +5,49 @@
5
5
  * Also maintains a global registry at ~/.gitnexus/registry.json
6
6
  * so the MCP server can discover indexed repos from any cwd.
7
7
  */
8
+ /**
9
+ * Normalise a repo path for registry comparison across platforms
10
+ * (#664 review feedback from @evander-wang).
11
+ *
12
+ * Why this exists: `path.resolve` alone is NOT enough for
13
+ * cross-platform registry stability.
14
+ * - **macOS**: tmpdirs and `/var` are symlinks to `/private/var`.
15
+ * A child process that stored `/private/var/folders/.../repo` in
16
+ * the registry cannot later be matched by an outer caller that
17
+ * supplies the symlink form `/var/folders/.../repo`. `path.resolve`
18
+ * does not follow symlinks; `realpathSync.native` does.
19
+ * - **Windows**: GitHub runners surface tmpdirs in 8.3 short-name
20
+ * form (`RUNNERA~1\...`), but `process.cwd()` often returns the
21
+ * long form (`runneradmin\...`). `realpathSync.native` normalises
22
+ * both sides to the long-name canonical path.
23
+ *
24
+ * Fallback behaviour: if the path does not exist on disk (e.g. a user
25
+ * passed `gitnexus remove some-alias` and the alias misses every
26
+ * registry entry, or the caller is resolving a path that was deleted
27
+ * after registration), we return `path.resolve(p)` rather than
28
+ * throwing. This preserves the idempotent-on-missing semantics of
29
+ * `resolveRegistryEntry` / `remove`.
30
+ *
31
+ * Backwards compatibility: this function is applied to BOTH the
32
+ * caller-supplied input AND each stored `entry.path` at compare time
33
+ * inside `resolveRegistryEntry`, so registries written by older
34
+ * versions (where `registerRepo` only ran `path.resolve`) still match
35
+ * correctly. Newly-written entries are canonicalised at write time too
36
+ * so the registry stabilises over analyze/re-analyze cycles.
37
+ */
38
+ export declare const canonicalizePath: (p: string) => string;
8
39
  export interface RepoMeta {
9
40
  repoPath: string;
10
41
  lastCommit: string;
11
42
  indexedAt: string;
43
+ /**
44
+ * Canonical `origin` remote URL captured at index time. Used to
45
+ * fingerprint the same logical repo across multiple on-disk clones
46
+ * (worktrees, agent workspaces, "clean clone for indexing"). When
47
+ * absent (no remote configured, git unavailable, etc.) the repo is
48
+ * treated as path-only and sibling-clone detection is skipped.
49
+ */
50
+ remoteUrl?: string;
12
51
  stats?: {
13
52
  files?: number;
14
53
  nodes?: number;
@@ -34,6 +73,8 @@ export interface RegistryEntry {
34
73
  storagePath: string;
35
74
  indexedAt: string;
36
75
  lastCommit: string;
76
+ /** See {@link RepoMeta.remoteUrl}. Mirrored from meta at register time. */
77
+ remoteUrl?: string;
37
78
  stats?: RepoMeta['stats'];
38
79
  }
39
80
  /**
@@ -102,16 +143,187 @@ export declare const getGlobalRegistryPath: () => string;
102
143
  * Read the global registry. Returns empty array if not found.
103
144
  */
104
145
  export declare const readRegistry: () => Promise<RegistryEntry[]>;
146
+ /**
147
+ * Options for {@link registerRepo}. All optional — callers without any
148
+ * disambiguation requirement can keep calling `registerRepo(path, meta)`
149
+ * unchanged.
150
+ */
151
+ export interface RegisterRepoOptions {
152
+ /**
153
+ * User-provided alias from `analyze --name <alias>` (#829). Overrides
154
+ * the default basename-derived registry `name`. Persisted — subsequent
155
+ * re-analyses of the same path without `--name` preserve the alias.
156
+ */
157
+ name?: string;
158
+ /**
159
+ * Allow two DIFFERENT repo paths to register under the same alias
160
+ * (#829). Mapped from the `--allow-duplicate-name` CLI flag.
161
+ *
162
+ * Scope: this flag governs cross-path alias sharing only — one repo
163
+ * path always has exactly one registry entry (and therefore exactly
164
+ * one alias). Re-analyzing the same path with `--name Y` overwrites
165
+ * a previous `--name X`; it does NOT create a second entry or a
166
+ * second alias for the same path (see the upsert-by-resolved-path
167
+ * logic in {@link registerRepo} and the
168
+ * `re-registerRepo with a different name overrides the previous
169
+ * alias` test in `test/unit/repo-manager.test.ts`).
170
+ *
171
+ * Distinct from `--force` (which only triggers pipeline re-index);
172
+ * a user accepting a duplicate alias should not be forced to also
173
+ * re-run the full pipeline.
174
+ */
175
+ allowDuplicateName?: boolean;
176
+ }
177
+ /**
178
+ * Thrown by {@link registerRepo} when a requested name is already in
179
+ * use by a DIFFERENT path. The CLI layer surfaces this as an actionable
180
+ * error instead of relying on `.message` string-matching.
181
+ *
182
+ * The colliding alias is exposed as `err.registryName` (not `err.name`).
183
+ * `err.name` keeps its inherited `Error.prototype.name` semantics (the
184
+ * class name) so downstream code can do the usual `err.name ===
185
+ * 'RegistryNameCollisionError'` checks; use the `kind` discriminant or
186
+ * `instanceof RegistryNameCollisionError` for type-safe narrowing.
187
+ */
188
+ export declare class RegistryNameCollisionError extends Error {
189
+ readonly registryName: string;
190
+ readonly existingPath: string;
191
+ readonly requestedPath: string;
192
+ readonly kind: "RegistryNameCollisionError";
193
+ constructor(registryName: string, existingPath: string, requestedPath: string);
194
+ }
105
195
  /**
106
196
  * Register (add or update) a repo in the global registry.
107
197
  * Called after `gitnexus analyze` completes.
198
+ *
199
+ * Name resolution precedence (#829, #979):
200
+ * 1. explicit `opts.name` (from `analyze --name <alias>`)
201
+ * 2. preserved alias on an existing entry for this path
202
+ * 3. `git config --get remote.origin.url` repo name (#979 — recovers
203
+ * a meaningful name for monorepo subprojects, git worktrees, and
204
+ * Gas-Town-style `<rig>/refinery/rig/` layouts where the basename
205
+ * is generic)
206
+ * 4. `path.basename(repoPath)` (the original default)
207
+ *
208
+ * Duplicate-name guard: if another path already uses the resolved
209
+ * `name`, throw {@link RegistryNameCollisionError} unless
210
+ * `opts.allowDuplicateName` is set. The guard ONLY fires when the user explicitly passed a
211
+ * `name`; un-aliased basename collisions continue to register silently
212
+ * so existing users who don't know about `--name` see no behaviour
213
+ * change.
214
+ *
215
+ * Returns the `name` that was actually written to the registry — the
216
+ * caller can re-use it to keep AGENTS.md / skill files aligned with the
217
+ * MCP-visible repo name (#979).
108
218
  */
109
- export declare const registerRepo: (repoPath: string, meta: RepoMeta) => Promise<void>;
219
+ export declare const registerRepo: (repoPath: string, meta: RepoMeta, opts?: RegisterRepoOptions) => Promise<string>;
110
220
  /**
111
221
  * Remove a repo from the global registry.
112
222
  * Called after `gitnexus clean`.
113
223
  */
114
224
  export declare const unregisterRepo: (repoPath: string) => Promise<void>;
225
+ /**
226
+ * Thrown by {@link resolveRegistryEntry} when no registered repo matches
227
+ * the caller's target string (by alias, basename, remote-inferred name,
228
+ * or resolved path). CLI callers that want idempotent "remove" semantics
229
+ * should catch this and exit 0 with a warning; non-idempotent callers
230
+ * (e.g. MCP tools) can surface the error directly.
231
+ */
232
+ export declare class RegistryNotFoundError extends Error {
233
+ readonly target: string;
234
+ readonly availableNames: string[];
235
+ readonly kind: "RegistryNotFoundError";
236
+ constructor(target: string, availableNames: string[]);
237
+ }
238
+ /**
239
+ * Thrown by {@link resolveRegistryEntry} when the target string matches
240
+ * the `name` of two or more entries — only possible when the user
241
+ * previously registered duplicates via `analyze --name X
242
+ * --allow-duplicate-name` (#829). The error carries enough information
243
+ * for the caller to render an actionable disambiguation hint without
244
+ * string-matching on `.message`.
245
+ *
246
+ * `kind` is a string literal discriminant (same pattern as
247
+ * {@link RegistryNameCollisionError}) so callers can narrow via
248
+ * `err.kind === 'RegistryAmbiguousTargetError'` without importing the
249
+ * class.
250
+ */
251
+ export declare class RegistryAmbiguousTargetError extends Error {
252
+ readonly target: string;
253
+ readonly matches: RegistryEntry[];
254
+ readonly kind: "RegistryAmbiguousTargetError";
255
+ constructor(target: string, matches: RegistryEntry[]);
256
+ }
257
+ /**
258
+ * Thrown by {@link assertSafeStoragePath} when a registry entry's
259
+ * `storagePath` does NOT point at the expected `<entry.path>/.gitnexus`
260
+ * subfolder. CLI destructive commands (`remove`, `clean --all`) should
261
+ * catch this and exit non-zero without deleting anything — the usual
262
+ * cause is a corrupted or hand-edited `~/.gitnexus/registry.json`, and
263
+ * proceeding would mean `fs.rm(recursive: true)` on whatever odd path
264
+ * the entry is pointing at.
265
+ */
266
+ export declare class UnsafeStoragePathError extends Error {
267
+ readonly entry: RegistryEntry;
268
+ readonly expectedStoragePath: string;
269
+ readonly actualStoragePath: string;
270
+ readonly kind: "UnsafeStoragePathError";
271
+ constructor(entry: RegistryEntry, expectedStoragePath: string, actualStoragePath: string);
272
+ }
273
+ /**
274
+ * Guard rail for destructive CLI paths (`remove` #664,
275
+ * `clean --all` #258, future MCP `remove` tool): verify that a
276
+ * registry entry's `storagePath` is the canonical `<repo>/.gitnexus`
277
+ * subfolder of its `path`. If not, throw {@link UnsafeStoragePathError}
278
+ * so the caller exits without touching disk.
279
+ *
280
+ * Why this exists (#1003 review — @magyargergo):
281
+ * - `~/.gitnexus/registry.json` is a plain-text user-writable file.
282
+ * A corrupted, hand-edited, or downgrade/upgrade-racing entry
283
+ * could plausibly end up with `storagePath === ""` (resolves to
284
+ * cwd), `storagePath === path` (the repo root!), `storagePath`
285
+ * equal to a parent/sibling of the repo, or simply any arbitrary
286
+ * filesystem path.
287
+ * - `fs.rm(recursive: true, force: true)` on ANY of those would be
288
+ * a runtime disaster — at best delete the user's working tree, at
289
+ * worst nuke an unrelated directory tree they happen to own.
290
+ * - `clean` (default, cwd-scoped) is safe by construction — it
291
+ * re-derives storagePath from `findRepo(cwd)` and never trusts
292
+ * the registry field. But `clean --all` DOES iterate the registry
293
+ * and trust each entry's stored storagePath (same shape as
294
+ * `remove`), so this helper must be wired into that loop too.
295
+ * - `server/api.ts` recomputes storagePath from `getStoragePath(entry.path)`
296
+ * and so is likewise safe-by-construction.
297
+ *
298
+ * Pure string check — does NOT require the paths to exist on disk.
299
+ * Windows: case-insensitive; POSIX: case-sensitive. Matches the
300
+ * comparison shape used elsewhere in this module.
301
+ */
302
+ export declare const assertSafeStoragePath: (entry: RegistryEntry) => void;
303
+ /**
304
+ * Resolve a user-supplied target string (from `gitnexus remove <target>`
305
+ * or equivalent MCP tool argument) to a single registry entry.
306
+ *
307
+ * Match precedence (first hit wins, subsequent tiers are only tried if
308
+ * the prior tier produces zero matches):
309
+ * 1. Exact resolved-path match (Windows: case-insensitive).
310
+ * Paths are unique by registry construction, so a path match can
311
+ * never be ambiguous.
312
+ * 2. Exact `name` match (case-insensitive). If ≥ 2 entries share the
313
+ * name — only possible via `--allow-duplicate-name` (#829) —
314
+ * throws {@link RegistryAmbiguousTargetError}.
315
+ *
316
+ * No fuzzy / partial matching — unambiguous, scriptable behaviour is
317
+ * more important than convenience for destructive commands.
318
+ *
319
+ * Throws {@link RegistryNotFoundError} if no entry matches.
320
+ *
321
+ * `entries` is passed in (rather than re-read) so callers that already
322
+ * hold the registry snapshot (e.g. to print a "before" state) can avoid
323
+ * a second disk read, and so tests can inject fixtures without touching
324
+ * `GITNEXUS_HOME`.
325
+ */
326
+ export declare const resolveRegistryEntry: (entries: RegistryEntry[], target: string) => RegistryEntry;
115
327
  /**
116
328
  * List all registered repos from the global registry.
117
329
  * Optionally validates that each entry's .gitnexus/ still exists.
@@ -142,3 +354,36 @@ export declare const loadCLIConfig: () => Promise<CLIConfig>;
142
354
  * Save CLI config to ~/.gitnexus/config.json
143
355
  */
144
356
  export declare const saveCLIConfig: (config: CLIConfig) => Promise<void>;
357
+ /**
358
+ * Find other registered entries whose `remoteUrl` matches the given
359
+ * one, excluding `selfPath` (case-insensitive on Windows). Entries
360
+ * without a `remoteUrl` are ignored — we cannot prove sibling-ness
361
+ * without a fingerprint.
362
+ */
363
+ export declare const findSiblingClones: (remoteUrl: string | undefined, selfPath: string) => Promise<RegistryEntry[]>;
364
+ /**
365
+ * Description of how a working directory relates to a registered index.
366
+ *
367
+ * `match` semantics:
368
+ * - `path` — `cwd` is inside the registered entry's path.
369
+ * - `sibling-by-remote` — `cwd` is in a different on-disk clone of the
370
+ * same repo (same `remoteUrl`).
371
+ * - `none` — no relationship found.
372
+ */
373
+ export interface CwdMatch {
374
+ match: 'path' | 'sibling-by-remote' | 'none';
375
+ entry?: RegistryEntry;
376
+ /** The git toplevel of `cwd`, when `cwd` is inside a git work tree. */
377
+ cwdGitRoot?: string;
378
+ /** HEAD of the cwd's clone, when resolvable. */
379
+ cwdHead?: string;
380
+ /**
381
+ * Number of commits the registered `lastCommit` is behind the
382
+ * sibling-clone HEAD, when both refs are known to the cwd's clone.
383
+ * `undefined` when the comparison cannot be performed (e.g. the
384
+ * indexed commit isn't reachable from cwd).
385
+ */
386
+ drift?: number;
387
+ /** Human-readable hint, set whenever the situation warrants warning. */
388
+ hint?: string;
389
+ }