gitnexus 1.4.9 → 1.5.0

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 (186) hide show
  1. package/README.md +6 -5
  2. package/dist/cli/ai-context.d.ts +4 -1
  3. package/dist/cli/ai-context.js +19 -11
  4. package/dist/cli/analyze.d.ts +6 -0
  5. package/dist/cli/analyze.js +105 -251
  6. package/dist/cli/eval-server.js +20 -11
  7. package/dist/cli/index-repo.js +20 -22
  8. package/dist/cli/index.js +8 -7
  9. package/dist/cli/mcp.js +1 -1
  10. package/dist/cli/serve.js +29 -1
  11. package/dist/cli/setup.js +9 -9
  12. package/dist/cli/skill-gen.js +15 -9
  13. package/dist/cli/wiki.d.ts +2 -0
  14. package/dist/cli/wiki.js +141 -26
  15. package/dist/config/ignore-service.js +102 -22
  16. package/dist/config/supported-languages.d.ts +8 -42
  17. package/dist/config/supported-languages.js +8 -43
  18. package/dist/core/augmentation/engine.js +19 -7
  19. package/dist/core/embeddings/embedder.js +19 -15
  20. package/dist/core/embeddings/embedding-pipeline.js +6 -6
  21. package/dist/core/embeddings/http-client.js +3 -3
  22. package/dist/core/embeddings/text-generator.js +9 -24
  23. package/dist/core/embeddings/types.d.ts +1 -1
  24. package/dist/core/embeddings/types.js +1 -7
  25. package/dist/core/graph/graph.js +6 -2
  26. package/dist/core/graph/types.d.ts +9 -59
  27. package/dist/core/ingestion/ast-cache.js +3 -3
  28. package/dist/core/ingestion/call-processor.d.ts +20 -2
  29. package/dist/core/ingestion/call-processor.js +347 -144
  30. package/dist/core/ingestion/call-routing.js +10 -4
  31. package/dist/core/ingestion/call-sites/extract-language-call-site.d.ts +10 -0
  32. package/dist/core/ingestion/call-sites/extract-language-call-site.js +22 -0
  33. package/dist/core/ingestion/call-sites/java.d.ts +9 -0
  34. package/dist/core/ingestion/call-sites/java.js +30 -0
  35. package/dist/core/ingestion/cluster-enricher.js +6 -8
  36. package/dist/core/ingestion/cobol/cobol-copy-expander.js +10 -3
  37. package/dist/core/ingestion/cobol/cobol-preprocessor.js +287 -81
  38. package/dist/core/ingestion/cobol/jcl-parser.js +1 -1
  39. package/dist/core/ingestion/cobol/jcl-processor.js +1 -1
  40. package/dist/core/ingestion/cobol-processor.js +102 -56
  41. package/dist/core/ingestion/community-processor.js +21 -15
  42. package/dist/core/ingestion/entry-point-scoring.d.ts +1 -1
  43. package/dist/core/ingestion/entry-point-scoring.js +5 -6
  44. package/dist/core/ingestion/export-detection.js +32 -9
  45. package/dist/core/ingestion/field-extractor.d.ts +1 -1
  46. package/dist/core/ingestion/field-extractors/configs/c-cpp.js +8 -12
  47. package/dist/core/ingestion/field-extractors/configs/csharp.js +45 -2
  48. package/dist/core/ingestion/field-extractors/configs/dart.js +5 -3
  49. package/dist/core/ingestion/field-extractors/configs/go.js +3 -7
  50. package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +5 -0
  51. package/dist/core/ingestion/field-extractors/configs/helpers.js +14 -0
  52. package/dist/core/ingestion/field-extractors/configs/jvm.js +7 -7
  53. package/dist/core/ingestion/field-extractors/configs/php.js +9 -11
  54. package/dist/core/ingestion/field-extractors/configs/python.js +1 -1
  55. package/dist/core/ingestion/field-extractors/configs/ruby.js +4 -3
  56. package/dist/core/ingestion/field-extractors/configs/rust.js +2 -5
  57. package/dist/core/ingestion/field-extractors/configs/swift.js +9 -7
  58. package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +2 -6
  59. package/dist/core/ingestion/field-extractors/generic.d.ts +5 -2
  60. package/dist/core/ingestion/field-extractors/generic.js +6 -0
  61. package/dist/core/ingestion/field-extractors/typescript.d.ts +1 -1
  62. package/dist/core/ingestion/field-extractors/typescript.js +1 -1
  63. package/dist/core/ingestion/field-types.d.ts +4 -2
  64. package/dist/core/ingestion/filesystem-walker.js +3 -3
  65. package/dist/core/ingestion/framework-detection.d.ts +1 -1
  66. package/dist/core/ingestion/framework-detection.js +355 -85
  67. package/dist/core/ingestion/heritage-processor.d.ts +24 -0
  68. package/dist/core/ingestion/heritage-processor.js +99 -8
  69. package/dist/core/ingestion/import-processor.js +44 -15
  70. package/dist/core/ingestion/import-resolvers/csharp.js +7 -3
  71. package/dist/core/ingestion/import-resolvers/dart.js +1 -1
  72. package/dist/core/ingestion/import-resolvers/go.js +4 -2
  73. package/dist/core/ingestion/import-resolvers/jvm.js +4 -4
  74. package/dist/core/ingestion/import-resolvers/php.js +4 -4
  75. package/dist/core/ingestion/import-resolvers/python.js +1 -1
  76. package/dist/core/ingestion/import-resolvers/rust.js +9 -3
  77. package/dist/core/ingestion/import-resolvers/standard.d.ts +1 -1
  78. package/dist/core/ingestion/import-resolvers/standard.js +6 -5
  79. package/dist/core/ingestion/import-resolvers/swift.js +2 -1
  80. package/dist/core/ingestion/import-resolvers/utils.js +26 -7
  81. package/dist/core/ingestion/language-config.js +5 -4
  82. package/dist/core/ingestion/language-provider.d.ts +7 -2
  83. package/dist/core/ingestion/languages/c-cpp.js +106 -21
  84. package/dist/core/ingestion/languages/cobol.js +1 -1
  85. package/dist/core/ingestion/languages/csharp.js +96 -19
  86. package/dist/core/ingestion/languages/dart.js +23 -7
  87. package/dist/core/ingestion/languages/go.js +1 -1
  88. package/dist/core/ingestion/languages/index.d.ts +1 -1
  89. package/dist/core/ingestion/languages/index.js +2 -3
  90. package/dist/core/ingestion/languages/java.js +4 -1
  91. package/dist/core/ingestion/languages/kotlin.js +60 -13
  92. package/dist/core/ingestion/languages/php.js +102 -25
  93. package/dist/core/ingestion/languages/python.js +28 -5
  94. package/dist/core/ingestion/languages/ruby.js +56 -14
  95. package/dist/core/ingestion/languages/rust.js +55 -11
  96. package/dist/core/ingestion/languages/swift.js +112 -27
  97. package/dist/core/ingestion/languages/typescript.js +95 -19
  98. package/dist/core/ingestion/markdown-processor.js +5 -5
  99. package/dist/core/ingestion/method-extractors/configs/csharp.d.ts +2 -0
  100. package/dist/core/ingestion/method-extractors/configs/csharp.js +283 -0
  101. package/dist/core/ingestion/method-extractors/configs/jvm.d.ts +3 -0
  102. package/dist/core/ingestion/method-extractors/configs/jvm.js +326 -0
  103. package/dist/core/ingestion/method-extractors/generic.d.ts +5 -0
  104. package/dist/core/ingestion/method-extractors/generic.js +137 -0
  105. package/dist/core/ingestion/method-types.d.ts +61 -0
  106. package/dist/core/ingestion/method-types.js +2 -0
  107. package/dist/core/ingestion/mro-processor.d.ts +1 -1
  108. package/dist/core/ingestion/mro-processor.js +12 -8
  109. package/dist/core/ingestion/named-binding-processor.js +2 -2
  110. package/dist/core/ingestion/named-bindings/rust.js +3 -1
  111. package/dist/core/ingestion/parsing-processor.js +74 -24
  112. package/dist/core/ingestion/pipeline.d.ts +2 -1
  113. package/dist/core/ingestion/pipeline.js +208 -102
  114. package/dist/core/ingestion/process-processor.js +12 -10
  115. package/dist/core/ingestion/resolution-context.js +3 -3
  116. package/dist/core/ingestion/route-extractors/middleware.js +31 -7
  117. package/dist/core/ingestion/route-extractors/php.js +2 -1
  118. package/dist/core/ingestion/route-extractors/response-shapes.js +8 -4
  119. package/dist/core/ingestion/structure-processor.d.ts +1 -1
  120. package/dist/core/ingestion/structure-processor.js +4 -4
  121. package/dist/core/ingestion/symbol-table.d.ts +1 -1
  122. package/dist/core/ingestion/symbol-table.js +22 -6
  123. package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -1
  124. package/dist/core/ingestion/tree-sitter-queries.js +1 -1
  125. package/dist/core/ingestion/type-env.d.ts +2 -2
  126. package/dist/core/ingestion/type-env.js +75 -50
  127. package/dist/core/ingestion/type-extractors/c-cpp.js +33 -30
  128. package/dist/core/ingestion/type-extractors/csharp.js +24 -14
  129. package/dist/core/ingestion/type-extractors/dart.js +6 -8
  130. package/dist/core/ingestion/type-extractors/go.js +7 -6
  131. package/dist/core/ingestion/type-extractors/jvm.js +10 -21
  132. package/dist/core/ingestion/type-extractors/php.js +26 -13
  133. package/dist/core/ingestion/type-extractors/python.js +11 -15
  134. package/dist/core/ingestion/type-extractors/ruby.js +8 -3
  135. package/dist/core/ingestion/type-extractors/rust.js +6 -8
  136. package/dist/core/ingestion/type-extractors/shared.js +134 -50
  137. package/dist/core/ingestion/type-extractors/swift.js +16 -13
  138. package/dist/core/ingestion/type-extractors/typescript.js +23 -15
  139. package/dist/core/ingestion/utils/ast-helpers.d.ts +8 -8
  140. package/dist/core/ingestion/utils/ast-helpers.js +72 -35
  141. package/dist/core/ingestion/utils/call-analysis.d.ts +2 -0
  142. package/dist/core/ingestion/utils/call-analysis.js +96 -49
  143. package/dist/core/ingestion/utils/event-loop.js +1 -1
  144. package/dist/core/ingestion/workers/parse-worker.d.ts +7 -2
  145. package/dist/core/ingestion/workers/parse-worker.js +364 -84
  146. package/dist/core/ingestion/workers/worker-pool.js +5 -10
  147. package/dist/core/lbug/csv-generator.js +54 -15
  148. package/dist/core/lbug/lbug-adapter.d.ts +5 -0
  149. package/dist/core/lbug/lbug-adapter.js +86 -23
  150. package/dist/core/lbug/schema.d.ts +3 -6
  151. package/dist/core/lbug/schema.js +6 -30
  152. package/dist/core/run-analyze.d.ts +49 -0
  153. package/dist/core/run-analyze.js +257 -0
  154. package/dist/core/tree-sitter/parser-loader.d.ts +1 -1
  155. package/dist/core/tree-sitter/parser-loader.js +1 -1
  156. package/dist/core/wiki/cursor-client.js +2 -7
  157. package/dist/core/wiki/generator.js +38 -23
  158. package/dist/core/wiki/graph-queries.js +10 -10
  159. package/dist/core/wiki/html-viewer.js +7 -3
  160. package/dist/core/wiki/llm-client.d.ts +23 -2
  161. package/dist/core/wiki/llm-client.js +96 -26
  162. package/dist/core/wiki/prompts.js +7 -6
  163. package/dist/mcp/core/embedder.js +1 -1
  164. package/dist/mcp/core/lbug-adapter.d.ts +4 -1
  165. package/dist/mcp/core/lbug-adapter.js +17 -7
  166. package/dist/mcp/local/local-backend.js +247 -95
  167. package/dist/mcp/resources.js +14 -6
  168. package/dist/mcp/server.js +13 -5
  169. package/dist/mcp/staleness.js +5 -1
  170. package/dist/mcp/tools.js +100 -23
  171. package/dist/server/analyze-job.d.ts +53 -0
  172. package/dist/server/analyze-job.js +146 -0
  173. package/dist/server/analyze-worker.d.ts +13 -0
  174. package/dist/server/analyze-worker.js +59 -0
  175. package/dist/server/api.js +795 -44
  176. package/dist/server/git-clone.d.ts +25 -0
  177. package/dist/server/git-clone.js +91 -0
  178. package/dist/storage/git.js +1 -3
  179. package/dist/storage/repo-manager.d.ts +5 -2
  180. package/dist/storage/repo-manager.js +4 -4
  181. package/dist/types/pipeline.d.ts +1 -21
  182. package/dist/types/pipeline.js +1 -18
  183. package/hooks/claude/gitnexus-hook.cjs +52 -22
  184. package/package.json +13 -13
  185. package/dist/core/ingestion/utils/language-detection.d.ts +0 -9
  186. package/dist/core/ingestion/utils/language-detection.js +0 -70
@@ -21,8 +21,8 @@ export const countCallArguments = (callNode) => {
21
21
  if (!callNode)
22
22
  return undefined;
23
23
  // Direct field or direct child (most languages)
24
- let argsNode = callNode.childForFieldName('arguments')
25
- ?? callNode.children.find((child) => CALL_ARGUMENT_LIST_TYPES.has(child.type));
24
+ let argsNode = callNode.childForFieldName('arguments') ??
25
+ callNode.children.find((child) => CALL_ARGUMENT_LIST_TYPES.has(child.type));
26
26
  // Kotlin/Swift: call_expression → call_suffix → value_arguments
27
27
  // Search one level deeper for languages that wrap arguments in a suffix node
28
28
  if (!argsNode) {
@@ -100,7 +100,8 @@ export const inferCallForm = (callNode, nameNode) => {
100
100
  return 'member';
101
101
  }
102
102
  // 3. PHP: the callNode itself distinguishes member vs free calls
103
- if (callNode.type === 'member_call_expression' || callNode.type === 'nullsafe_member_call_expression') {
103
+ if (callNode.type === 'member_call_expression' ||
104
+ callNode.type === 'nullsafe_member_call_expression') {
104
105
  return 'member';
105
106
  }
106
107
  if (callNode.type === 'scoped_call_expression') {
@@ -153,17 +154,20 @@ export const extractReceiverName = (nameNode) => {
153
154
  const callNode = parent.parent ?? parent;
154
155
  let receiver = null;
155
156
  // Try standard field names used across grammars
156
- receiver = parent.childForFieldName('object') // TS/JS member_expression, Python attribute, PHP, Java
157
- ?? parent.childForFieldName('value') // Rust field_expression
158
- ?? parent.childForFieldName('operand') // Go selector_expression
159
- ?? parent.childForFieldName('expression') // C# member_access_expression
160
- ?? parent.childForFieldName('argument'); // C++ field_expression
157
+ receiver =
158
+ parent.childForFieldName('object') ?? // TS/JS member_expression, Python attribute, PHP, Java
159
+ parent.childForFieldName('value') ?? // Rust field_expression
160
+ parent.childForFieldName('operand') ?? // Go selector_expression
161
+ parent.childForFieldName('expression') ?? // C# member_access_expression
162
+ parent.childForFieldName('argument'); // C++ field_expression
161
163
  // Java method_invocation: 'object' field is on the callNode, not on nameNode's parent
162
164
  if (!receiver && callNode.type === 'method_invocation') {
163
165
  receiver = callNode.childForFieldName('object');
164
166
  }
165
167
  // PHP: member_call_expression has 'object' on the call node
166
- if (!receiver && (callNode.type === 'member_call_expression' || callNode.type === 'nullsafe_member_call_expression')) {
168
+ if (!receiver &&
169
+ (callNode.type === 'member_call_expression' ||
170
+ callNode.type === 'nullsafe_member_call_expression')) {
167
171
  receiver = callNode.childForFieldName('object');
168
172
  }
169
173
  // Ruby: call node has 'receiver' field
@@ -172,7 +176,8 @@ export const extractReceiverName = (nameNode) => {
172
176
  }
173
177
  // PHP scoped_call_expression (parent::method(), self::method()):
174
178
  // nameNode's direct parent IS the scoped_call_expression (name is a direct child)
175
- if (!receiver && (parent.type === 'scoped_call_expression' || callNode.type === 'scoped_call_expression')) {
179
+ if (!receiver &&
180
+ (parent.type === 'scoped_call_expression' || callNode.type === 'scoped_call_expression')) {
176
181
  const scopedCall = parent.type === 'scoped_call_expression' ? parent : callNode;
177
182
  receiver = scopedCall.childForFieldName('scope');
178
183
  // relative_scope wraps 'parent'/'self'/'static' — unwrap to get the keyword
@@ -238,21 +243,25 @@ export const extractReceiverNode = (nameNode) => {
238
243
  return undefined;
239
244
  const callNode = parent.parent ?? parent;
240
245
  let receiver = null;
241
- receiver = parent.childForFieldName('object')
242
- ?? parent.childForFieldName('value')
243
- ?? parent.childForFieldName('operand')
244
- ?? parent.childForFieldName('expression')
245
- ?? parent.childForFieldName('argument');
246
+ receiver =
247
+ parent.childForFieldName('object') ??
248
+ parent.childForFieldName('value') ??
249
+ parent.childForFieldName('operand') ??
250
+ parent.childForFieldName('expression') ??
251
+ parent.childForFieldName('argument');
246
252
  if (!receiver && callNode.type === 'method_invocation') {
247
253
  receiver = callNode.childForFieldName('object');
248
254
  }
249
- if (!receiver && (callNode.type === 'member_call_expression' || callNode.type === 'nullsafe_member_call_expression')) {
255
+ if (!receiver &&
256
+ (callNode.type === 'member_call_expression' ||
257
+ callNode.type === 'nullsafe_member_call_expression')) {
250
258
  receiver = callNode.childForFieldName('object');
251
259
  }
252
260
  if (!receiver && parent.type === 'call') {
253
261
  receiver = parent.childForFieldName('receiver');
254
262
  }
255
- if (!receiver && (parent.type === 'scoped_call_expression' || callNode.type === 'scoped_call_expression')) {
263
+ if (!receiver &&
264
+ (parent.type === 'scoped_call_expression' || callNode.type === 'scoped_call_expression')) {
256
265
  const scopedCall = parent.type === 'scoped_call_expression' ? parent : callNode;
257
266
  receiver = scopedCall.childForFieldName('scope');
258
267
  if (receiver?.type === 'relative_scope') {
@@ -312,9 +321,9 @@ export function extractCallChain(receiverCallNode) {
312
321
  let current = receiverCallNode;
313
322
  while (CALL_EXPRESSION_TYPES.has(current.type) && chain.length < MAX_CHAIN_DEPTH) {
314
323
  // Extract the method name from this call node.
315
- const funcNode = current.childForFieldName?.('function')
316
- ?? current.childForFieldName?.('name')
317
- ?? current.childForFieldName?.('method'); // Ruby `call` node
324
+ const funcNode = current.childForFieldName?.('function') ??
325
+ current.childForFieldName?.('name') ??
326
+ current.childForFieldName?.('method'); // Ruby `call` node
318
327
  let methodName;
319
328
  let innerReceiver = null;
320
329
  if (funcNode) {
@@ -345,17 +354,20 @@ export function extractCallChain(receiverCallNode) {
345
354
  chain.unshift(methodName); // build chain outermost-last
346
355
  // Walk into the receiver of this call to continue the chain
347
356
  if (!innerReceiver && funcNode) {
348
- innerReceiver = funcNode.childForFieldName?.('object')
349
- ?? funcNode.childForFieldName?.('value')
350
- ?? funcNode.childForFieldName?.('operand')
351
- ?? funcNode.childForFieldName?.('expression');
357
+ innerReceiver =
358
+ funcNode.childForFieldName?.('object') ??
359
+ funcNode.childForFieldName?.('value') ??
360
+ funcNode.childForFieldName?.('operand') ??
361
+ funcNode.childForFieldName?.('expression');
352
362
  }
353
363
  // Java method_invocation: object field is on the call node
354
364
  if (!innerReceiver && current.type === 'method_invocation') {
355
365
  innerReceiver = current.childForFieldName?.('object');
356
366
  }
357
367
  // PHP member_call_expression
358
- if (!innerReceiver && (current.type === 'member_call_expression' || current.type === 'nullsafe_member_call_expression')) {
368
+ if (!innerReceiver &&
369
+ (current.type === 'member_call_expression' ||
370
+ current.type === 'nullsafe_member_call_expression')) {
359
371
  innerReceiver = current.childForFieldName?.('object');
360
372
  }
361
373
  // Ruby `call` node: receiver field is on the call node itself
@@ -396,9 +408,9 @@ export function extractMixedChain(receiverNode) {
396
408
  while (chain.length < MAX_CHAIN_DEPTH) {
397
409
  if (CALL_EXPRESSION_TYPES.has(current.type)) {
398
410
  // ── Call expression: extract method name + inner receiver ────────────
399
- const funcNode = current.childForFieldName?.('function')
400
- ?? current.childForFieldName?.('name')
401
- ?? current.childForFieldName?.('method');
411
+ const funcNode = current.childForFieldName?.('function') ??
412
+ current.childForFieldName?.('name') ??
413
+ current.childForFieldName?.('method');
402
414
  let methodName;
403
415
  let innerReceiver = null;
404
416
  if (funcNode) {
@@ -425,17 +437,20 @@ export function extractMixedChain(receiverNode) {
425
437
  break;
426
438
  chain.unshift({ kind: 'call', name: methodName });
427
439
  if (!innerReceiver && funcNode) {
428
- innerReceiver = funcNode.childForFieldName?.('object')
429
- ?? funcNode.childForFieldName?.('value')
430
- ?? funcNode.childForFieldName?.('operand')
431
- ?? funcNode.childForFieldName?.('argument') // C/C++ field_expression
432
- ?? funcNode.childForFieldName?.('expression')
433
- ?? null;
440
+ innerReceiver =
441
+ funcNode.childForFieldName?.('object') ??
442
+ funcNode.childForFieldName?.('value') ??
443
+ funcNode.childForFieldName?.('operand') ??
444
+ funcNode.childForFieldName?.('argument') ?? // C/C++ field_expression
445
+ funcNode.childForFieldName?.('expression') ??
446
+ null;
434
447
  }
435
448
  if (!innerReceiver && current.type === 'method_invocation') {
436
449
  innerReceiver = current.childForFieldName?.('object') ?? null;
437
450
  }
438
- if (!innerReceiver && (current.type === 'member_call_expression' || current.type === 'nullsafe_member_call_expression')) {
451
+ if (!innerReceiver &&
452
+ (current.type === 'member_call_expression' ||
453
+ current.type === 'nullsafe_member_call_expression')) {
439
454
  innerReceiver = current.childForFieldName?.('object') ?? null;
440
455
  }
441
456
  if (!innerReceiver && current.type === 'call') {
@@ -443,7 +458,8 @@ export function extractMixedChain(receiverNode) {
443
458
  }
444
459
  if (!innerReceiver)
445
460
  break;
446
- if (CALL_EXPRESSION_TYPES.has(innerReceiver.type) || FIELD_ACCESS_NODE_TYPES.has(innerReceiver.type)) {
461
+ if (CALL_EXPRESSION_TYPES.has(innerReceiver.type) ||
462
+ FIELD_ACCESS_NODE_TYPES.has(innerReceiver.type)) {
447
463
  current = innerReceiver;
448
464
  }
449
465
  else {
@@ -474,22 +490,24 @@ export function extractMixedChain(receiverNode) {
474
490
  propertyName = current.childForFieldName?.('attribute')?.text;
475
491
  }
476
492
  else {
477
- innerObject = current.childForFieldName?.('object')
478
- ?? current.childForFieldName?.('value')
479
- ?? current.childForFieldName?.('operand')
480
- ?? current.childForFieldName?.('argument') // C/C++ field_expression
481
- ?? current.childForFieldName?.('expression')
482
- ?? null;
483
- propertyName = (current.childForFieldName?.('property')
484
- ?? current.childForFieldName?.('field')
485
- ?? current.childForFieldName?.('name'))?.text;
493
+ innerObject =
494
+ current.childForFieldName?.('object') ??
495
+ current.childForFieldName?.('value') ??
496
+ current.childForFieldName?.('operand') ??
497
+ current.childForFieldName?.('argument') ?? // C/C++ field_expression
498
+ current.childForFieldName?.('expression') ??
499
+ null;
500
+ propertyName = (current.childForFieldName?.('property') ??
501
+ current.childForFieldName?.('field') ??
502
+ current.childForFieldName?.('name'))?.text;
486
503
  }
487
504
  if (!propertyName)
488
505
  break;
489
506
  chain.unshift({ kind: 'field', name: propertyName });
490
507
  if (!innerObject)
491
508
  break;
492
- if (CALL_EXPRESSION_TYPES.has(innerObject.type) || FIELD_ACCESS_NODE_TYPES.has(innerObject.type)) {
509
+ if (CALL_EXPRESSION_TYPES.has(innerObject.type) ||
510
+ FIELD_ACCESS_NODE_TYPES.has(innerObject.type)) {
493
511
  current = innerObject;
494
512
  }
495
513
  else {
@@ -518,10 +536,39 @@ export function extractMixedChain(receiverNode) {
518
536
  }
519
537
  else {
520
538
  // Simple identifier — this is the base receiver
521
- return chain.length > 0
522
- ? { chain, baseReceiverName: current.text || undefined }
523
- : undefined;
539
+ return chain.length > 0 ? { chain, baseReceiverName: current.text || undefined } : undefined;
524
540
  }
525
541
  }
526
542
  return chain.length > 0 ? { chain, baseReceiverName: undefined } : undefined;
527
543
  }
544
+ /** Arg types per call position (literals + optional TypeEnv for ids); undefined if unusable */
545
+ export const extractCallArgTypes = (callNode, inferLiteralType, typeEnvLookup) => {
546
+ let argList = callNode.childForFieldName?.('arguments') ??
547
+ callNode.children.find((c) => c.type === 'arguments' || c.type === 'argument_list' || c.type === 'value_arguments');
548
+ if (!argList) {
549
+ const callSuffix = callNode.children.find((c) => c.type === 'call_suffix');
550
+ if (callSuffix) {
551
+ argList = callSuffix.children.find((c) => c.type === 'value_arguments');
552
+ }
553
+ }
554
+ if (!argList)
555
+ return undefined;
556
+ const argTypes = [];
557
+ for (const arg of argList.namedChildren) {
558
+ if (arg.type === 'comment')
559
+ continue;
560
+ const valueNode = arg.childForFieldName?.('value') ??
561
+ arg.childForFieldName?.('expression') ??
562
+ (arg.type === 'argument' || arg.type === 'value_argument'
563
+ ? (arg.firstNamedChild ?? arg)
564
+ : arg);
565
+ let inferred = inferLiteralType(valueNode);
566
+ if (!inferred && typeEnvLookup && valueNode.type === 'identifier') {
567
+ inferred = typeEnvLookup(valueNode.text, callNode);
568
+ }
569
+ argTypes.push(inferred);
570
+ }
571
+ if (argTypes.every((t) => t === undefined))
572
+ return undefined;
573
+ return argTypes;
574
+ };
@@ -2,4 +2,4 @@
2
2
  * Yield control to the event loop so spinners/progress can render.
3
3
  * Call periodically in hot loops to prevent UI freezes.
4
4
  */
5
- export const yieldToEventLoop = () => new Promise(resolve => setImmediate(resolve));
5
+ export const yieldToEventLoop = () => new Promise((resolve) => setImmediate(resolve));
@@ -1,8 +1,8 @@
1
- import { SupportedLanguages } from '../../../config/supported-languages.js';
1
+ import { SupportedLanguages } from 'gitnexus-shared';
2
2
  import { type MixedChainStep } from '../utils/call-analysis.js';
3
3
  import type { ConstructorBinding } from '../type-env.js';
4
4
  import type { NamedBinding } from '../named-bindings/types.js';
5
- import type { NodeLabel } from '../../graph/types.js';
5
+ import type { NodeLabel } from 'gitnexus-shared';
6
6
  interface ParsedNode {
7
7
  id: string;
8
8
  label: string;
@@ -47,6 +47,9 @@ interface ParsedSymbol {
47
47
  visibility?: string;
48
48
  isStatic?: boolean;
49
49
  isReadonly?: boolean;
50
+ isAbstract?: boolean;
51
+ isFinal?: boolean;
52
+ annotations?: string[];
50
53
  }
51
54
  export interface ExtractedImport {
52
55
  filePath: string;
@@ -60,6 +63,7 @@ export interface ExtractedCall {
60
63
  calledName: string;
61
64
  /** generateId of enclosing function, or generateId('File', filePath) for top-level */
62
65
  sourceId: string;
66
+ /** From call AST; omitted for some seeds (e.g. Java `::`) so arity filter is skipped */
63
67
  argCount?: number;
64
68
  /** Discriminates free function calls from member/constructor calls */
65
69
  callForm?: 'free' | 'member' | 'constructor';
@@ -76,6 +80,7 @@ export interface ExtractedCall {
76
80
  * Length is capped at MAX_CHAIN_DEPTH (3).
77
81
  */
78
82
  receiverMixedChain?: MixedChainStep[];
83
+ argTypes?: (string | undefined)[];
79
84
  }
80
85
  export interface ExtractedAssignment {
81
86
  filePath: string;