gitnexus 1.6.2-rc.2 → 1.6.2-rc.21

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 (198) hide show
  1. package/dist/_shared/lbug/schema-constants.d.ts +1 -1
  2. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  3. package/dist/_shared/lbug/schema-constants.js +1 -0
  4. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  5. package/dist/cli/analyze.js +3 -0
  6. package/dist/core/embeddings/ast-utils.d.ts +22 -0
  7. package/dist/core/embeddings/ast-utils.js +105 -0
  8. package/dist/core/embeddings/character-chunk.d.ts +12 -0
  9. package/dist/core/embeddings/character-chunk.js +43 -0
  10. package/dist/core/embeddings/chunker.d.ts +14 -0
  11. package/dist/core/embeddings/chunker.js +234 -0
  12. package/dist/core/embeddings/embedder.js +5 -0
  13. package/dist/core/embeddings/embedding-pipeline.d.ts +29 -24
  14. package/dist/core/embeddings/embedding-pipeline.js +244 -125
  15. package/dist/core/embeddings/line-index.d.ts +7 -0
  16. package/dist/core/embeddings/line-index.js +42 -0
  17. package/dist/core/embeddings/server-mapping.d.ts +15 -0
  18. package/dist/core/embeddings/server-mapping.js +33 -0
  19. package/dist/core/embeddings/structural-extractor.d.ts +15 -0
  20. package/dist/core/embeddings/structural-extractor.js +58 -0
  21. package/dist/core/embeddings/text-generator.d.ts +20 -13
  22. package/dist/core/embeddings/text-generator.js +151 -119
  23. package/dist/core/embeddings/types.d.ts +81 -3
  24. package/dist/core/embeddings/types.js +105 -3
  25. package/dist/core/group/extractors/http-patterns/node.js +130 -0
  26. package/dist/core/group/extractors/manifest-extractor.js +20 -5
  27. package/dist/core/group/sync.js +49 -1
  28. package/dist/core/ingestion/call-extractors/configs/c-cpp.d.ts +3 -0
  29. package/dist/core/ingestion/call-extractors/configs/c-cpp.js +8 -0
  30. package/dist/core/ingestion/call-extractors/configs/csharp.d.ts +2 -0
  31. package/dist/core/ingestion/call-extractors/configs/csharp.js +6 -0
  32. package/dist/core/ingestion/call-extractors/configs/dart.d.ts +2 -0
  33. package/dist/core/ingestion/call-extractors/configs/dart.js +5 -0
  34. package/dist/core/ingestion/call-extractors/configs/go.d.ts +2 -0
  35. package/dist/core/ingestion/call-extractors/configs/go.js +5 -0
  36. package/dist/core/ingestion/call-extractors/configs/jvm.d.ts +3 -0
  37. package/dist/core/ingestion/call-extractors/configs/jvm.js +51 -0
  38. package/dist/core/ingestion/call-extractors/configs/php.d.ts +2 -0
  39. package/dist/core/ingestion/call-extractors/configs/php.js +5 -0
  40. package/dist/core/ingestion/call-extractors/configs/python.d.ts +2 -0
  41. package/dist/core/ingestion/call-extractors/configs/python.js +5 -0
  42. package/dist/core/ingestion/call-extractors/configs/ruby.d.ts +2 -0
  43. package/dist/core/ingestion/call-extractors/configs/ruby.js +5 -0
  44. package/dist/core/ingestion/call-extractors/configs/rust.d.ts +2 -0
  45. package/dist/core/ingestion/call-extractors/configs/rust.js +5 -0
  46. package/dist/core/ingestion/call-extractors/configs/swift.d.ts +2 -0
  47. package/dist/core/ingestion/call-extractors/configs/swift.js +5 -0
  48. package/dist/core/ingestion/call-extractors/configs/typescript-javascript.d.ts +3 -0
  49. package/dist/core/ingestion/call-extractors/configs/typescript-javascript.js +8 -0
  50. package/dist/core/ingestion/call-extractors/generic.d.ts +5 -0
  51. package/dist/core/ingestion/call-extractors/generic.js +59 -0
  52. package/dist/core/ingestion/call-processor.d.ts +1 -3
  53. package/dist/core/ingestion/call-processor.js +49 -47
  54. package/dist/core/ingestion/call-types.d.ts +60 -0
  55. package/dist/core/ingestion/call-types.js +2 -0
  56. package/dist/core/ingestion/class-extractors/configs/c-cpp.d.ts +3 -0
  57. package/dist/core/ingestion/class-extractors/configs/c-cpp.js +11 -0
  58. package/dist/core/ingestion/class-extractors/configs/csharp.d.ts +2 -0
  59. package/dist/core/ingestion/class-extractors/configs/csharp.js +21 -0
  60. package/dist/core/ingestion/class-extractors/configs/dart.d.ts +2 -0
  61. package/dist/core/ingestion/class-extractors/configs/dart.js +7 -0
  62. package/dist/core/ingestion/class-extractors/configs/go.d.ts +2 -0
  63. package/dist/core/ingestion/class-extractors/configs/go.js +20 -0
  64. package/dist/core/ingestion/class-extractors/configs/jvm.d.ts +3 -0
  65. package/dist/core/ingestion/class-extractors/configs/jvm.js +35 -0
  66. package/dist/core/ingestion/class-extractors/configs/php.d.ts +2 -0
  67. package/dist/core/ingestion/class-extractors/configs/php.js +7 -0
  68. package/dist/core/ingestion/class-extractors/configs/python.d.ts +2 -0
  69. package/dist/core/ingestion/class-extractors/configs/python.js +7 -0
  70. package/dist/core/ingestion/class-extractors/configs/ruby.d.ts +2 -0
  71. package/dist/core/ingestion/class-extractors/configs/ruby.js +7 -0
  72. package/dist/core/ingestion/class-extractors/configs/rust.d.ts +2 -0
  73. package/dist/core/ingestion/class-extractors/configs/rust.js +7 -0
  74. package/dist/core/ingestion/class-extractors/configs/swift.d.ts +2 -0
  75. package/dist/core/ingestion/class-extractors/configs/swift.js +18 -0
  76. package/dist/core/ingestion/class-extractors/configs/typescript-javascript.d.ts +4 -0
  77. package/dist/core/ingestion/class-extractors/configs/typescript-javascript.js +28 -0
  78. package/dist/core/ingestion/field-types.d.ts +1 -1
  79. package/dist/core/ingestion/import-resolvers/configs/c-cpp.d.ts +7 -0
  80. package/dist/core/ingestion/import-resolvers/configs/c-cpp.js +14 -0
  81. package/dist/core/ingestion/import-resolvers/configs/csharp.d.ts +8 -0
  82. package/dist/core/ingestion/import-resolvers/configs/csharp.js +27 -0
  83. package/dist/core/ingestion/import-resolvers/configs/dart.d.ts +17 -0
  84. package/dist/core/ingestion/import-resolvers/{dart.js → configs/dart.js} +26 -16
  85. package/dist/core/ingestion/import-resolvers/configs/go.d.ts +8 -0
  86. package/dist/core/ingestion/import-resolvers/configs/go.js +26 -0
  87. package/dist/core/ingestion/import-resolvers/configs/jvm.d.ts +13 -0
  88. package/dist/core/ingestion/import-resolvers/configs/jvm.js +68 -0
  89. package/dist/core/ingestion/import-resolvers/configs/php.d.ts +8 -0
  90. package/dist/core/ingestion/import-resolvers/configs/php.js +15 -0
  91. package/dist/core/ingestion/import-resolvers/configs/python.d.ts +12 -0
  92. package/dist/core/ingestion/import-resolvers/configs/python.js +41 -0
  93. package/dist/core/ingestion/import-resolvers/configs/ruby.d.ts +8 -0
  94. package/dist/core/ingestion/import-resolvers/configs/ruby.js +16 -0
  95. package/dist/core/ingestion/import-resolvers/configs/rust.d.ts +8 -0
  96. package/dist/core/ingestion/import-resolvers/configs/rust.js +54 -0
  97. package/dist/core/ingestion/import-resolvers/configs/swift.d.ts +8 -0
  98. package/dist/core/ingestion/import-resolvers/{swift.js → configs/swift.js} +10 -5
  99. package/dist/core/ingestion/import-resolvers/configs/typescript-javascript.d.ts +9 -0
  100. package/dist/core/ingestion/import-resolvers/configs/typescript-javascript.js +23 -0
  101. package/dist/core/ingestion/import-resolvers/csharp.d.ts +4 -5
  102. package/dist/core/ingestion/import-resolvers/csharp.js +4 -20
  103. package/dist/core/ingestion/import-resolvers/go.d.ts +4 -5
  104. package/dist/core/ingestion/import-resolvers/go.js +4 -19
  105. package/dist/core/ingestion/import-resolvers/jvm.d.ts +5 -10
  106. package/dist/core/ingestion/import-resolvers/jvm.js +5 -58
  107. package/dist/core/ingestion/import-resolvers/php.d.ts +4 -5
  108. package/dist/core/ingestion/import-resolvers/php.js +4 -7
  109. package/dist/core/ingestion/import-resolvers/python.d.ts +3 -6
  110. package/dist/core/ingestion/import-resolvers/python.js +3 -18
  111. package/dist/core/ingestion/import-resolvers/resolver-factory.d.ts +24 -0
  112. package/dist/core/ingestion/import-resolvers/resolver-factory.js +33 -0
  113. package/dist/core/ingestion/import-resolvers/ruby.d.ts +4 -5
  114. package/dist/core/ingestion/import-resolvers/ruby.js +4 -7
  115. package/dist/core/ingestion/import-resolvers/rust.d.ts +4 -5
  116. package/dist/core/ingestion/import-resolvers/rust.js +4 -47
  117. package/dist/core/ingestion/import-resolvers/standard.d.ts +3 -9
  118. package/dist/core/ingestion/import-resolvers/standard.js +7 -8
  119. package/dist/core/ingestion/import-resolvers/types.d.ts +24 -0
  120. package/dist/core/ingestion/language-provider.d.ts +12 -0
  121. package/dist/core/ingestion/languages/c-cpp.js +15 -12
  122. package/dist/core/ingestion/languages/csharp.js +11 -21
  123. package/dist/core/ingestion/languages/dart.js +11 -7
  124. package/dist/core/ingestion/languages/go.js +11 -20
  125. package/dist/core/ingestion/languages/java.js +11 -18
  126. package/dist/core/ingestion/languages/kotlin.js +11 -13
  127. package/dist/core/ingestion/languages/php.js +11 -7
  128. package/dist/core/ingestion/languages/python.js +11 -7
  129. package/dist/core/ingestion/languages/ruby.js +11 -7
  130. package/dist/core/ingestion/languages/rust.js +11 -7
  131. package/dist/core/ingestion/languages/swift.js +11 -18
  132. package/dist/core/ingestion/languages/typescript.js +15 -23
  133. package/dist/core/ingestion/languages/vue.js +11 -17
  134. package/dist/core/ingestion/model/index.d.ts +2 -2
  135. package/dist/core/ingestion/model/index.js +1 -1
  136. package/dist/core/ingestion/model/resolve.d.ts +3 -0
  137. package/dist/core/ingestion/model/resolve.js +6 -2
  138. package/dist/core/ingestion/parsing-processor.d.ts +1 -2
  139. package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
  140. package/dist/core/ingestion/tree-sitter-queries.js +81 -0
  141. package/dist/core/ingestion/type-env.d.ts +1 -1
  142. package/dist/core/ingestion/utils/ast-helpers.d.ts +1 -1
  143. package/dist/core/ingestion/utils/ast-helpers.js +3 -0
  144. package/dist/core/ingestion/variable-extractors/configs/c-cpp.d.ts +3 -0
  145. package/dist/core/ingestion/variable-extractors/configs/c-cpp.js +81 -0
  146. package/dist/core/ingestion/variable-extractors/configs/csharp.d.ts +9 -0
  147. package/dist/core/ingestion/variable-extractors/configs/csharp.js +63 -0
  148. package/dist/core/ingestion/variable-extractors/configs/dart.d.ts +2 -0
  149. package/dist/core/ingestion/variable-extractors/configs/dart.js +94 -0
  150. package/dist/core/ingestion/variable-extractors/configs/go.d.ts +2 -0
  151. package/dist/core/ingestion/variable-extractors/configs/go.js +83 -0
  152. package/dist/core/ingestion/variable-extractors/configs/jvm.d.ts +18 -0
  153. package/dist/core/ingestion/variable-extractors/configs/jvm.js +115 -0
  154. package/dist/core/ingestion/variable-extractors/configs/php.d.ts +14 -0
  155. package/dist/core/ingestion/variable-extractors/configs/php.js +58 -0
  156. package/dist/core/ingestion/variable-extractors/configs/python.d.ts +2 -0
  157. package/dist/core/ingestion/variable-extractors/configs/python.js +101 -0
  158. package/dist/core/ingestion/variable-extractors/configs/ruby.d.ts +11 -0
  159. package/dist/core/ingestion/variable-extractors/configs/ruby.js +52 -0
  160. package/dist/core/ingestion/variable-extractors/configs/rust.d.ts +2 -0
  161. package/dist/core/ingestion/variable-extractors/configs/rust.js +76 -0
  162. package/dist/core/ingestion/variable-extractors/configs/swift.d.ts +2 -0
  163. package/dist/core/ingestion/variable-extractors/configs/swift.js +88 -0
  164. package/dist/core/ingestion/variable-extractors/configs/typescript-javascript.d.ts +3 -0
  165. package/dist/core/ingestion/variable-extractors/configs/typescript-javascript.js +83 -0
  166. package/dist/core/ingestion/variable-extractors/generic.d.ts +5 -0
  167. package/dist/core/ingestion/variable-extractors/generic.js +80 -0
  168. package/dist/core/ingestion/variable-types.d.ts +82 -0
  169. package/dist/core/ingestion/variable-types.js +2 -0
  170. package/dist/core/ingestion/workers/parse-worker.js +196 -166
  171. package/dist/core/ingestion/workers/worker-pool.js +3 -0
  172. package/dist/core/lbug/csv-generator.js +1 -0
  173. package/dist/core/lbug/lbug-adapter.d.ts +13 -4
  174. package/dist/core/lbug/lbug-adapter.js +166 -81
  175. package/dist/core/lbug/schema.d.ts +9 -1
  176. package/dist/core/lbug/schema.js +19 -2
  177. package/dist/core/run-analyze.js +17 -4
  178. package/dist/core/tree-sitter/parser-loader.d.ts +3 -0
  179. package/dist/core/tree-sitter/parser-loader.js +17 -8
  180. package/dist/mcp/core/embedder.js +5 -0
  181. package/dist/mcp/local/local-backend.js +29 -19
  182. package/dist/server/api.js +10 -21
  183. package/package.json +5 -3
  184. package/scripts/build-tree-sitter-proto.cjs +82 -0
  185. package/vendor/node_modules/node-addon-api/node_addon_api.Makefile +6 -0
  186. package/vendor/node_modules/node-addon-api/node_addon_api.target.mk +104 -0
  187. package/vendor/node_modules/node-addon-api/node_addon_api_except.target.mk +108 -0
  188. package/vendor/node_modules/node-addon-api/node_addon_api_except_all.target.mk +104 -0
  189. package/vendor/node_modules/node-addon-api/node_addon_api_maybe.target.mk +104 -0
  190. package/vendor/tree-sitter-proto/package.json +1 -7
  191. package/dist/core/ingestion/call-sites/extract-language-call-site.d.ts +0 -10
  192. package/dist/core/ingestion/call-sites/extract-language-call-site.js +0 -22
  193. package/dist/core/ingestion/call-sites/java.d.ts +0 -9
  194. package/dist/core/ingestion/call-sites/java.js +0 -30
  195. package/dist/core/ingestion/import-resolvers/dart.d.ts +0 -7
  196. package/dist/core/ingestion/import-resolvers/swift.d.ts +0 -7
  197. package/dist/core/ingestion/import-resolvers/vue.d.ts +0 -8
  198. package/dist/core/ingestion/import-resolvers/vue.js +0 -9
@@ -7,6 +7,9 @@ import { compilePatterns, runCompiledPatterns, unquoteLiteral, } from '../tree-s
7
7
  * - Express `router.get(...)` / `app.post(...)` providers
8
8
  * - `fetch(url)` / `fetch(url, { method: 'POST' })` consumers
9
9
  * - `axios.get(url)` / `axios.delete(url)` consumers
10
+ * - `axios({ method, url })` object-form consumers
11
+ * - jQuery `$.get(url)` / `$.post(url, ...)` shorthand consumers
12
+ * - jQuery `$.ajax({ url, method | type })` consumers
10
13
  *
11
14
  * Because the JavaScript and TypeScript tree-sitter grammars share
12
15
  * node type names for every construct we query, pattern sources are
@@ -86,6 +89,45 @@ const AXIOS_SPEC = {
86
89
  arguments: (arguments . [(string) (template_string)] @path))
87
90
  `,
88
91
  };
92
+ // ─── Consumer: jQuery shorthand $.get(url) / $.post(url, ...) ────────
93
+ // `$` is a valid JS identifier, so tree-sitter parses `$.get(...)` as a
94
+ // call_expression whose function is a member_expression on identifier `$`.
95
+ const JQUERY_SHORTHAND_SPEC = {
96
+ meta: {},
97
+ query: `
98
+ (call_expression
99
+ function: (member_expression
100
+ object: (identifier) @obj (#eq? @obj "$")
101
+ property: (property_identifier) @http_method (#match? @http_method "^(get|post)$"))
102
+ arguments: (arguments . [(string) (template_string)] @path))
103
+ `,
104
+ };
105
+ // ─── Consumer: jQuery $.ajax({ url, method|type }) ───────────────────
106
+ // The query captures the options object only; key/value pairs are read
107
+ // programmatically via `readStringProp` below, which tolerates any key
108
+ // order and accepts either `method:` or `type:` (jQuery supports both).
109
+ const JQUERY_AJAX_SPEC = {
110
+ meta: {},
111
+ query: `
112
+ (call_expression
113
+ function: (member_expression
114
+ object: (identifier) @obj (#eq? @obj "$")
115
+ property: (property_identifier) @fn (#eq? @fn "ajax"))
116
+ arguments: (arguments (object) @options))
117
+ `,
118
+ };
119
+ // ─── Consumer: axios({ method, url }) object form ────────────────────
120
+ // Distinct from AXIOS_SPEC above because the call target is an identifier
121
+ // (`axios`) rather than a member expression (`axios.get`). As with the
122
+ // jQuery ajax form, option keys are resolved programmatically.
123
+ const AXIOS_OBJECT_SPEC = {
124
+ meta: {},
125
+ query: `
126
+ (call_expression
127
+ function: (identifier) @fn (#eq? @fn "axios")
128
+ arguments: (arguments (object) @options))
129
+ `,
130
+ };
89
131
  function compileBundle(language, name) {
90
132
  const mk = (spec, suffix) => compilePatterns({
91
133
  name: `${name}-${suffix}`,
@@ -99,6 +141,9 @@ function compileBundle(language, name) {
99
141
  fetchNoOptions: mk(FETCH_NO_OPTIONS_SPEC, 'fetch-no-options'),
100
142
  fetchWithOptions: mk(FETCH_WITH_OPTIONS_SPEC, 'fetch-with-options'),
101
143
  axios: mk(AXIOS_SPEC, 'axios'),
144
+ jqueryShorthand: mk(JQUERY_SHORTHAND_SPEC, 'jquery-shorthand'),
145
+ jqueryAjax: mk(JQUERY_AJAX_SPEC, 'jquery-ajax'),
146
+ axiosObject: mk(AXIOS_OBJECT_SPEC, 'axios-object'),
102
147
  };
103
148
  }
104
149
  const JAVASCRIPT_BUNDLE = compileBundle(JavaScript, 'javascript-http');
@@ -130,6 +175,32 @@ function joinPath(prefix, sub) {
130
175
  return `/${cleanSub}`;
131
176
  return `/${cleanPrefix}/${cleanSub}`;
132
177
  }
178
+ /**
179
+ * Walk `pair` children of an `object` literal and return the unquoted
180
+ * string/template_string value for the first pair whose key matches one
181
+ * of `keyNames`. Returns null when no matching pair is present or the
182
+ * value is not a string literal. Used by the jQuery ajax / axios object
183
+ * consumers to resolve `url` / `method` / `type` keys in any order.
184
+ */
185
+ function readStringProp(objectNode, keyNames) {
186
+ for (let i = 0; i < objectNode.namedChildCount; i++) {
187
+ const pair = objectNode.namedChild(i);
188
+ if (!pair || pair.type !== 'pair')
189
+ continue;
190
+ const keyNode = pair.childForFieldName('key');
191
+ const valueNode = pair.childForFieldName('value');
192
+ if (!keyNode || !valueNode)
193
+ continue;
194
+ if (!keyNames.includes(keyNode.text))
195
+ continue;
196
+ if (valueNode.type !== 'string' && valueNode.type !== 'template_string')
197
+ continue;
198
+ const lit = unquoteLiteral(valueNode.text);
199
+ if (lit !== null)
200
+ return lit;
201
+ }
202
+ return null;
203
+ }
133
204
  /**
134
205
  * For a standalone `decorator` node (child of class_body / program),
135
206
  * find the related `class_declaration` node that it decorates. In
@@ -335,6 +406,65 @@ function scanBundle(bundle, tree) {
335
406
  confidence: 0.7,
336
407
  });
337
408
  }
409
+ // Consumer: jQuery shorthand $.get(url) / $.post(url, ...)
410
+ for (const match of runCompiledPatterns(bundle.jqueryShorthand, tree)) {
411
+ const methodNode = match.captures.http_method;
412
+ const pathNode = match.captures.path;
413
+ if (!methodNode || !pathNode)
414
+ continue;
415
+ const path = unquoteLiteral(pathNode.text);
416
+ if (path === null)
417
+ continue;
418
+ out.push({
419
+ role: 'consumer',
420
+ framework: 'jquery',
421
+ method: methodNode.text.toUpperCase(),
422
+ path,
423
+ name: null,
424
+ confidence: 0.7,
425
+ });
426
+ }
427
+ // Consumer: jQuery $.ajax({ url, method|type }). jQuery accepts either
428
+ // `method:` or `type:`; both default to GET when absent.
429
+ for (const match of runCompiledPatterns(bundle.jqueryAjax, tree)) {
430
+ const optionsNode = match.captures.options;
431
+ if (!optionsNode)
432
+ continue;
433
+ const path = readStringProp(optionsNode, ['url']);
434
+ if (path === null)
435
+ continue;
436
+ const rawMethod = readStringProp(optionsNode, ['method', 'type']);
437
+ const method = (rawMethod ?? 'GET').toUpperCase();
438
+ out.push({
439
+ role: 'consumer',
440
+ framework: 'jquery',
441
+ method,
442
+ path,
443
+ name: null,
444
+ confidence: 0.7,
445
+ });
446
+ }
447
+ // Consumer: axios({ method, url }) object form. Structurally distinct
448
+ // from axios.<verb>(url) (identifier vs member_expression call), so no
449
+ // dedup against the member-form loop above is required.
450
+ for (const match of runCompiledPatterns(bundle.axiosObject, tree)) {
451
+ const optionsNode = match.captures.options;
452
+ if (!optionsNode)
453
+ continue;
454
+ const path = readStringProp(optionsNode, ['url']);
455
+ if (path === null)
456
+ continue;
457
+ const rawMethod = readStringProp(optionsNode, ['method']);
458
+ const method = (rawMethod ?? 'GET').toUpperCase();
459
+ out.push({
460
+ role: 'consumer',
461
+ framework: 'axios',
462
+ method,
463
+ path,
464
+ name: null,
465
+ confidence: 0.7,
466
+ });
467
+ }
338
468
  return out;
339
469
  }
340
470
  export const JAVASCRIPT_HTTP_PLUGIN = {
@@ -68,14 +68,29 @@ export function manifestSymbolUid(repo, contractId) {
68
68
  }
69
69
  export class ManifestExtractor {
70
70
  async extractFromManifest(links, dbExecutors) {
71
- const contracts = [];
72
- const crossLinks = [];
73
- for (const link of links) {
71
+ const resolveCache = new Map();
72
+ const resolveOnce = (repo, link) => {
73
+ const key = `${repo}\u0000${link.type}\u0000${link.contract}`;
74
+ let pending = resolveCache.get(key);
75
+ if (!pending) {
76
+ pending = this.resolveSymbol(repo, link, dbExecutors);
77
+ resolveCache.set(key, pending);
78
+ }
79
+ return pending;
80
+ };
81
+ const perLink = await Promise.all(links.map(async (link) => {
74
82
  const contractId = this.buildContractId(link.type, link.contract);
75
83
  const providerRepo = link.role === 'provider' ? link.from : link.to;
76
84
  const consumerRepo = link.role === 'provider' ? link.to : link.from;
77
- const providerSymbol = await this.resolveSymbol(providerRepo, link, dbExecutors);
78
- const consumerSymbol = await this.resolveSymbol(consumerRepo, link, dbExecutors);
85
+ const [providerSymbol, consumerSymbol] = await Promise.all([
86
+ resolveOnce(providerRepo, link),
87
+ resolveOnce(consumerRepo, link),
88
+ ]);
89
+ return { link, contractId, providerRepo, consumerRepo, providerSymbol, consumerSymbol };
90
+ }));
91
+ const contracts = [];
92
+ const crossLinks = [];
93
+ for (const { link, contractId, providerRepo, consumerRepo, providerSymbol, consumerSymbol, } of perLink) {
79
94
  const providerRef = providerSymbol || { filePath: '', name: link.contract };
80
95
  const consumerRef = consumerSymbol || { filePath: '', name: link.contract };
81
96
  // When the resolver finds a real graph symbol we keep its uid, otherwise
@@ -6,6 +6,7 @@ import { readRegistry } from '../../storage/repo-manager.js';
6
6
  import { HttpRouteExtractor } from './extractors/http-route-extractor.js';
7
7
  import { GrpcExtractor } from './extractors/grpc-extractor.js';
8
8
  import { TopicExtractor } from './extractors/topic-extractor.js';
9
+ import { ManifestExtractor } from './extractors/manifest-extractor.js';
9
10
  import { runExactMatch } from './matching.js';
10
11
  import { detectServiceBoundaries, assignService } from './service-boundary-detector.js';
11
12
  import { writeContractRegistry } from './storage.js';
@@ -34,10 +35,28 @@ function defaultResolveHandle(allEntries) {
34
35
  };
35
36
  };
36
37
  }
38
+ /**
39
+ * Dedupe cross-links that point from the same consumer endpoint to the same
40
+ * provider endpoint for the same contract. Preserves first-seen order so the
41
+ * caller controls precedence (e.g., pass manifest links first).
42
+ */
43
+ function dedupeCrossLinks(links) {
44
+ const seen = new Set();
45
+ const out = [];
46
+ for (const link of links) {
47
+ const key = `${link.from.repo}::${link.from.symbolUid}|${link.to.repo}::${link.to.symbolUid}|${link.type}|${link.contractId}`;
48
+ if (seen.has(key))
49
+ continue;
50
+ seen.add(key);
51
+ out.push(link);
52
+ }
53
+ return out;
54
+ }
37
55
  export async function syncGroup(config, opts) {
38
56
  const missingRepos = [];
39
57
  const repoSnapshots = {};
40
58
  let autoContracts = [];
59
+ let manifestCrossLinks = [];
41
60
  let dbExecutors;
42
61
  const eo = opts?.extractorOverride;
43
62
  if (eo && eo.length === 0) {
@@ -124,8 +143,37 @@ export async function syncGroup(config, opts) {
124
143
  }
125
144
  }
126
145
  }
146
+ // Process manifest links declared in group.yaml.
147
+ // ManifestExtractor is fully implemented but was never wired into this
148
+ // pipeline — config.links were parsed and validated but silently dropped.
149
+ // Placed after the DB try/finally: resolveSymbol falls back to synthetic
150
+ // UIDs when dbExecutors is undefined or a pool is closed, so cross-links
151
+ // are always generated regardless of whether real DB executors are available.
152
+ if (config.links.length > 0) {
153
+ // Warn about dangling links that reference repos not declared in config.repos.
154
+ // They still generate cross-links via synthetic UIDs (determinism is preserved),
155
+ // but the operator probably meant something that now silently does nothing useful.
156
+ const knownRepos = new Set(Object.keys(config.repos));
157
+ for (const link of config.links) {
158
+ const dangling = [link.from, link.to].filter((r) => !knownRepos.has(r));
159
+ if (dangling.length > 0) {
160
+ console.warn(`[group/sync] manifest link ${link.type}:${link.contract} references repos not in config.repos: ${dangling.join(', ')} — cross-links will use synthetic UIDs`);
161
+ }
162
+ }
163
+ const manifestEx = new ManifestExtractor();
164
+ const manifestResult = await manifestEx.extractFromManifest(config.links, dbExecutors);
165
+ autoContracts.push(...manifestResult.contracts);
166
+ manifestCrossLinks = manifestResult.crossLinks;
167
+ if (opts?.verbose) {
168
+ console.log(` manifest: ${manifestCrossLinks.length} cross-links from ${config.links.length} declared links`);
169
+ }
170
+ }
127
171
  const { matched, unmatched } = runExactMatch(autoContracts);
128
- const crossLinks = matched;
172
+ // Dedupe cross-links. Manifest contracts participate in runExactMatch, so a
173
+ // manifest-declared link can also emit a matchType:'exact' CrossLink with the
174
+ // same endpoints. Prefer the manifest version — it reflects operator intent
175
+ // and carries matchType:'manifest' which downstream consumers may rely on.
176
+ const crossLinks = dedupeCrossLinks([...manifestCrossLinks, ...matched]);
129
177
  const allContracts = autoContracts;
130
178
  const registry = {
131
179
  version: 1,
@@ -0,0 +1,3 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const cCallConfig: CallExtractionConfig;
3
+ export declare const cppCallConfig: CallExtractionConfig;
@@ -0,0 +1,8 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/c-cpp.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ export const cCallConfig = {
4
+ language: SupportedLanguages.C,
5
+ };
6
+ export const cppCallConfig = {
7
+ language: SupportedLanguages.CPlusPlus,
8
+ };
@@ -0,0 +1,2 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const csharpCallConfig: CallExtractionConfig;
@@ -0,0 +1,6 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/csharp.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ export const csharpCallConfig = {
4
+ language: SupportedLanguages.CSharp,
5
+ typeAsReceiverHeuristic: true,
6
+ };
@@ -0,0 +1,2 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const dartCallConfig: CallExtractionConfig;
@@ -0,0 +1,5 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/dart.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ export const dartCallConfig = {
4
+ language: SupportedLanguages.Dart,
5
+ };
@@ -0,0 +1,2 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const goCallConfig: CallExtractionConfig;
@@ -0,0 +1,5 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/go.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ export const goCallConfig = {
4
+ language: SupportedLanguages.Go,
5
+ };
@@ -0,0 +1,3 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const javaCallConfig: CallExtractionConfig;
3
+ export declare const kotlinCallConfig: CallExtractionConfig;
@@ -0,0 +1,51 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/jvm.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ // ---------------------------------------------------------------------------
4
+ // Java method_reference (::) parsing — absorbs call-sites/java.ts
5
+ // ---------------------------------------------------------------------------
6
+ /**
7
+ * Parse Java `method_reference` nodes (`expr::method`, `Type::new`,
8
+ * `this::m`, `super::m`).
9
+ */
10
+ function parseJavaMethodReference(callNode) {
11
+ if (callNode.type !== 'method_reference')
12
+ return null;
13
+ const recv = callNode.namedChild(0);
14
+ if (!recv)
15
+ return null;
16
+ // Type::new → constructor call
17
+ for (const c of callNode.children) {
18
+ if (c.type === 'new') {
19
+ if (recv.type !== 'identifier')
20
+ return null;
21
+ return { calledName: recv.text, callForm: 'constructor' };
22
+ }
23
+ }
24
+ // expr::method → member call with receiver
25
+ const rhs = callNode.child(callNode.childCount - 1);
26
+ if (!rhs || rhs.type !== 'identifier')
27
+ return null;
28
+ const methodName = rhs.text;
29
+ if (recv.type === 'identifier') {
30
+ return { calledName: methodName, callForm: 'member', receiverName: recv.text };
31
+ }
32
+ if (recv.type === 'this') {
33
+ return { calledName: methodName, callForm: 'member', receiverName: 'this' };
34
+ }
35
+ if (recv.type === 'super') {
36
+ return { calledName: methodName, callForm: 'member', receiverName: 'super' };
37
+ }
38
+ return null;
39
+ }
40
+ // ---------------------------------------------------------------------------
41
+ // Configs
42
+ // ---------------------------------------------------------------------------
43
+ export const javaCallConfig = {
44
+ language: SupportedLanguages.Java,
45
+ extractLanguageCallSite: parseJavaMethodReference,
46
+ typeAsReceiverHeuristic: true,
47
+ };
48
+ export const kotlinCallConfig = {
49
+ language: SupportedLanguages.Kotlin,
50
+ typeAsReceiverHeuristic: true,
51
+ };
@@ -0,0 +1,2 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const phpCallConfig: CallExtractionConfig;
@@ -0,0 +1,5 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/php.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ export const phpCallConfig = {
4
+ language: SupportedLanguages.PHP,
5
+ };
@@ -0,0 +1,2 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const pythonCallConfig: CallExtractionConfig;
@@ -0,0 +1,5 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/python.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ export const pythonCallConfig = {
4
+ language: SupportedLanguages.Python,
5
+ };
@@ -0,0 +1,2 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const rubyCallConfig: CallExtractionConfig;
@@ -0,0 +1,5 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/ruby.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ export const rubyCallConfig = {
4
+ language: SupportedLanguages.Ruby,
5
+ };
@@ -0,0 +1,2 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const rustCallConfig: CallExtractionConfig;
@@ -0,0 +1,5 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/rust.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ export const rustCallConfig = {
4
+ language: SupportedLanguages.Rust,
5
+ };
@@ -0,0 +1,2 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const swiftCallConfig: CallExtractionConfig;
@@ -0,0 +1,5 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/swift.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ export const swiftCallConfig = {
4
+ language: SupportedLanguages.Swift,
5
+ };
@@ -0,0 +1,3 @@
1
+ import type { CallExtractionConfig } from '../../call-types.js';
2
+ export declare const typescriptCallConfig: CallExtractionConfig;
3
+ export declare const javascriptCallConfig: CallExtractionConfig;
@@ -0,0 +1,8 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/configs/typescript-javascript.ts
2
+ import { SupportedLanguages } from '../../../../_shared/index.js';
3
+ export const typescriptCallConfig = {
4
+ language: SupportedLanguages.TypeScript,
5
+ };
6
+ export const javascriptCallConfig = {
7
+ language: SupportedLanguages.JavaScript,
8
+ };
@@ -0,0 +1,5 @@
1
+ import type { CallExtractor, CallExtractionConfig } from '../call-types.js';
2
+ /**
3
+ * Create a CallExtractor from a declarative config.
4
+ */
5
+ export declare function createCallExtractor(config: CallExtractionConfig): CallExtractor;
@@ -0,0 +1,59 @@
1
+ // gitnexus/src/core/ingestion/call-extractors/generic.ts
2
+ import { inferCallForm, extractReceiverName, extractReceiverNode, extractMixedChain, countCallArguments, } from '../utils/call-analysis.js';
3
+ /**
4
+ * Create a CallExtractor from a declarative config.
5
+ */
6
+ export function createCallExtractor(config) {
7
+ return {
8
+ language: config.language,
9
+ extract(callNode, callNameNode) {
10
+ // ── Path 1: Language-specific call site ──────────────────────────
11
+ // Non-standard call shapes (e.g. Java `::` method references) are
12
+ // handled entirely by the config hook. When it returns a result,
13
+ // the generic path is skipped — no argCount, no mixed chain.
14
+ //
15
+ // Note: `extractLanguageCallSite` is called on every `extract()`
16
+ // invocation — both `extract(callNode, undefined)` (parse-worker
17
+ // Path 1) and `extract(callNode, callNameNode)` (Path 2).
18
+ // Language hooks must therefore be idempotent and cheap (e.g. a
19
+ // single node-type check).
20
+ if (config.extractLanguageCallSite) {
21
+ const seed = config.extractLanguageCallSite(callNode);
22
+ if (seed) {
23
+ return {
24
+ ...seed,
25
+ ...(config.typeAsReceiverHeuristic ? { typeAsReceiverHeuristic: true } : {}),
26
+ };
27
+ }
28
+ }
29
+ // ── Path 2: Generic extraction via @call.name ────────────────────
30
+ if (!callNameNode)
31
+ return null;
32
+ const calledName = callNameNode.text;
33
+ const callForm = inferCallForm(callNode, callNameNode);
34
+ let receiverName = callForm === 'member' ? extractReceiverName(callNameNode) : undefined;
35
+ let receiverMixedChain;
36
+ // When the receiver is a complex expression (call chain, field chain,
37
+ // or mixed), extractReceiverName returns undefined. Walk the receiver
38
+ // node to build a unified mixed chain for deferred resolution.
39
+ if (callForm === 'member' && receiverName === undefined) {
40
+ const receiverNode = extractReceiverNode(callNameNode);
41
+ if (receiverNode) {
42
+ const extracted = extractMixedChain(receiverNode);
43
+ if (extracted && extracted.chain.length > 0) {
44
+ receiverMixedChain = extracted.chain;
45
+ receiverName = extracted.baseReceiverName;
46
+ }
47
+ }
48
+ }
49
+ return {
50
+ calledName,
51
+ ...(callForm !== undefined ? { callForm } : {}),
52
+ ...(receiverName !== undefined ? { receiverName } : {}),
53
+ argCount: countCallArguments(callNode),
54
+ ...(receiverMixedChain !== undefined ? { receiverMixedChain } : {}),
55
+ ...(config.typeAsReceiverHeuristic ? { typeAsReceiverHeuristic: true } : {}),
56
+ };
57
+ },
58
+ };
59
+ }
@@ -1,13 +1,11 @@
1
1
  import { KnowledgeGraph } from '../graph/types.js';
2
2
  import { ASTCache } from './ast-cache.js';
3
- import type { SymbolDefinition, SymbolTableReader } from './model/symbol-table.js';
3
+ import type { SymbolDefinition, SymbolTableReader, HeritageMap, ExtractedHeritage } from './model/index.js';
4
4
  import type { ResolutionContext } from './model/resolution-context.js';
5
5
  import type { TieredCandidates } from './model/resolution-context.js';
6
6
  import type { TypeEnvironment } from './type-env.js';
7
- import type { HeritageMap } from './model/heritage-map.js';
8
7
  import type { BindingAccumulator } from './binding-accumulator.js';
9
8
  import type { ExtractedCall, ExtractedAssignment, ExtractedRoute, ExtractedFetchCall, FileConstructorBindings } from './workers/parse-worker.js';
10
- import type { ExtractedHeritage } from './model/heritage-map.js';
11
9
  import type { LiteralTypeInferrer } from './type-extractors/types.js';
12
10
  import type { SyntaxNode } from './utils/ast-helpers.js';
13
11
  /** Per-file resolved type bindings for exported symbols.