gitnexus 1.4.10 → 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 +3 -2
  185. package/dist/core/ingestion/utils/language-detection.d.ts +0 -9
  186. package/dist/core/ingestion/utils/language-detection.js +0 -70
@@ -0,0 +1,137 @@
1
+ // gitnexus/src/core/ingestion/method-extractors/generic.ts
2
+ /** Owner node types where member functions are effectively static (JVM semantics). */
3
+ const STATIC_OWNER_TYPES = new Set(['companion_object', 'object_declaration']);
4
+ /**
5
+ * Create a MethodExtractor from a declarative config.
6
+ */
7
+ export function createMethodExtractor(config) {
8
+ const typeDeclarationSet = new Set(config.typeDeclarationNodes);
9
+ const methodNodeSet = new Set(config.methodNodeTypes);
10
+ const bodyNodeSet = new Set(config.bodyNodeTypes);
11
+ return {
12
+ language: config.language,
13
+ isTypeDeclaration(node) {
14
+ return typeDeclarationSet.has(node.type);
15
+ },
16
+ extract(node, context) {
17
+ if (!typeDeclarationSet.has(node.type))
18
+ return null;
19
+ // Resolve owner name: field-based → type_identifier → simple_identifier → "Companion"
20
+ let ownerName;
21
+ const nameField = node.childForFieldName('name');
22
+ if (nameField) {
23
+ ownerName = nameField.text;
24
+ }
25
+ else {
26
+ for (let i = 0; i < node.namedChildCount; i++) {
27
+ const child = node.namedChild(i);
28
+ if (child && (child.type === 'type_identifier' || child.type === 'simple_identifier')) {
29
+ ownerName = child.text;
30
+ break;
31
+ }
32
+ }
33
+ }
34
+ // Unnamed companion objects use "Companion" (Kotlin convention)
35
+ if (!ownerName && node.type === 'companion_object') {
36
+ ownerName = 'Companion';
37
+ }
38
+ if (!ownerName)
39
+ return null;
40
+ const methods = [];
41
+ const bodies = findBodies(node, bodyNodeSet);
42
+ for (const body of bodies) {
43
+ extractMethodsFromBody(body, node, context, config, methodNodeSet, methods);
44
+ }
45
+ // Extract primary constructor from the owner node itself (e.g. C# 12)
46
+ if (config.extractPrimaryConstructor) {
47
+ const primaryCtor = config.extractPrimaryConstructor(node, context);
48
+ if (primaryCtor)
49
+ methods.push(primaryCtor);
50
+ }
51
+ return { ownerName, methods };
52
+ },
53
+ };
54
+ }
55
+ function findBodies(node, bodyNodeSet) {
56
+ const result = [];
57
+ const bodyField = node.childForFieldName('body');
58
+ if (bodyField && bodyNodeSet.has(bodyField.type)) {
59
+ result.push(bodyField);
60
+ addNestedBodies(bodyField, bodyNodeSet, result);
61
+ return result;
62
+ }
63
+ for (let i = 0; i < node.namedChildCount; i++) {
64
+ const child = node.namedChild(i);
65
+ if (child && bodyNodeSet.has(child.type)) {
66
+ result.push(child);
67
+ }
68
+ }
69
+ if (result.length === 0 && bodyField) {
70
+ // Fallback: body field exists but its type is not in bodyNodeTypes.
71
+ // This may indicate a config typo — log for debugging if NODE_ENV is development.
72
+ if (process.env.NODE_ENV === 'development') {
73
+ console.warn(`[MethodExtractor] body field type '${bodyField.type}' not in bodyNodeTypes for node '${node.type}'`);
74
+ }
75
+ result.push(bodyField);
76
+ addNestedBodies(bodyField, bodyNodeSet, result);
77
+ }
78
+ return result;
79
+ }
80
+ function addNestedBodies(parent, bodyNodeSet, out) {
81
+ for (let i = 0; i < parent.namedChildCount; i++) {
82
+ const child = parent.namedChild(i);
83
+ if (child && bodyNodeSet.has(child.type) && !out.includes(child)) {
84
+ out.push(child);
85
+ }
86
+ }
87
+ }
88
+ function extractMethodsFromBody(body, ownerNode, context, config, methodNodeSet, out) {
89
+ for (let i = 0; i < body.namedChildCount; i++) {
90
+ const child = body.namedChild(i);
91
+ if (!child)
92
+ continue;
93
+ if (methodNodeSet.has(child.type)) {
94
+ const method = buildMethod(child, ownerNode, context, config);
95
+ if (method)
96
+ out.push(method);
97
+ }
98
+ // Recurse into enum constant anonymous class bodies
99
+ if (child.type === 'enum_constant') {
100
+ for (let j = 0; j < child.namedChildCount; j++) {
101
+ const innerBody = child.namedChild(j);
102
+ if (innerBody && innerBody.type === 'class_body') {
103
+ extractMethodsFromBody(innerBody, ownerNode, context, config, methodNodeSet, out);
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ function buildMethod(node, ownerNode, context, config) {
110
+ const name = config.extractName(node);
111
+ if (!name)
112
+ return null;
113
+ const isAbstract = config.isAbstract(node, ownerNode);
114
+ let isFinal = config.isFinal(node);
115
+ // Domain invariant: abstract methods cannot be final
116
+ if (isAbstract)
117
+ isFinal = false;
118
+ // companion_object / object_declaration members are effectively static on JVM
119
+ const isStatic = STATIC_OWNER_TYPES.has(ownerNode.type) || config.isStatic(node);
120
+ return {
121
+ name,
122
+ receiverType: config.extractReceiverType?.(node) ?? null,
123
+ returnType: config.extractReturnType(node) ?? null,
124
+ parameters: config.extractParameters(node),
125
+ visibility: config.extractVisibility(node),
126
+ isStatic,
127
+ isAbstract,
128
+ isFinal,
129
+ ...(config.isVirtual?.(node) ? { isVirtual: true } : {}),
130
+ ...(config.isOverride?.(node) ? { isOverride: true } : {}),
131
+ ...(config.isAsync?.(node) ? { isAsync: true } : {}),
132
+ ...(config.isPartial?.(node) ? { isPartial: true } : {}),
133
+ annotations: config.extractAnnotations?.(node) ?? [],
134
+ sourceFile: context.filePath,
135
+ line: node.startPosition.row + 1,
136
+ };
137
+ }
@@ -0,0 +1,61 @@
1
+ import type { SupportedLanguages } from 'gitnexus-shared';
2
+ import type { FieldVisibility } from './field-types.js';
3
+ import type { SyntaxNode } from './utils/ast-helpers.js';
4
+ export type MethodVisibility = FieldVisibility;
5
+ export interface ParameterInfo {
6
+ name: string;
7
+ type: string | null;
8
+ isOptional: boolean;
9
+ isVariadic: boolean;
10
+ }
11
+ export interface MethodInfo {
12
+ name: string;
13
+ receiverType: string | null;
14
+ returnType: string | null;
15
+ parameters: ParameterInfo[];
16
+ visibility: MethodVisibility;
17
+ isStatic: boolean;
18
+ isAbstract: boolean;
19
+ isFinal: boolean;
20
+ isVirtual?: boolean;
21
+ isOverride?: boolean;
22
+ isAsync?: boolean;
23
+ isPartial?: boolean;
24
+ annotations: string[];
25
+ sourceFile: string;
26
+ line: number;
27
+ }
28
+ export interface MethodExtractorContext {
29
+ filePath: string;
30
+ language: SupportedLanguages;
31
+ }
32
+ export interface ExtractedMethods {
33
+ ownerName: string;
34
+ methods: MethodInfo[];
35
+ }
36
+ export interface MethodExtractor {
37
+ language: SupportedLanguages;
38
+ extract(node: SyntaxNode, context: MethodExtractorContext): ExtractedMethods | null;
39
+ isTypeDeclaration(node: SyntaxNode): boolean;
40
+ }
41
+ export interface MethodExtractionConfig {
42
+ language: SupportedLanguages;
43
+ typeDeclarationNodes: string[];
44
+ methodNodeTypes: string[];
45
+ bodyNodeTypes: string[];
46
+ extractName: (node: SyntaxNode) => string | undefined;
47
+ extractReturnType: (node: SyntaxNode) => string | undefined;
48
+ extractParameters: (node: SyntaxNode) => ParameterInfo[];
49
+ extractVisibility: (node: SyntaxNode) => MethodVisibility;
50
+ isStatic: (node: SyntaxNode) => boolean;
51
+ isAbstract: (node: SyntaxNode, ownerNode: SyntaxNode) => boolean;
52
+ isFinal: (node: SyntaxNode) => boolean;
53
+ extractAnnotations?: (node: SyntaxNode) => string[];
54
+ extractReceiverType?: (node: SyntaxNode) => string | undefined;
55
+ isVirtual?: (node: SyntaxNode) => boolean;
56
+ isOverride?: (node: SyntaxNode) => boolean;
57
+ isAsync?: (node: SyntaxNode) => boolean;
58
+ isPartial?: (node: SyntaxNode) => boolean;
59
+ /** Extract a primary constructor from the owner node itself (e.g. C# 12 class Point(int x, int y)). */
60
+ extractPrimaryConstructor?: (ownerNode: SyntaxNode, context: MethodExtractorContext) => MethodInfo | null;
61
+ }
@@ -0,0 +1,2 @@
1
+ // gitnexus/src/core/ingestion/method-types.ts
2
+ export {};
@@ -19,7 +19,7 @@
19
19
  * Cypher: MATCH (c:Class)-[r:CodeRelation {type: 'OVERRIDES'}]->(m:Method)
20
20
  */
21
21
  import { KnowledgeGraph } from '../graph/types.js';
22
- import { SupportedLanguages } from '../../config/supported-languages.js';
22
+ import { SupportedLanguages } from 'gitnexus-shared';
23
23
  export interface MROEntry {
24
24
  classId: string;
25
25
  className: string;
@@ -119,14 +119,14 @@ function c3Linearize(classId, parentMap, cache, inProgress) {
119
119
  // Add the direct parents list as the final sequence
120
120
  const sequences = [...parentLinearizations, [...directParents]];
121
121
  const result = [];
122
- while (sequences.some(s => s.length > 0)) {
122
+ while (sequences.some((s) => s.length > 0)) {
123
123
  // Find a good head: one that doesn't appear in the tail of any other sequence
124
124
  let head = null;
125
125
  for (const seq of sequences) {
126
126
  if (seq.length === 0)
127
127
  continue;
128
128
  const candidate = seq[0];
129
- const inTail = sequences.some(other => other.length > 1 && other.indexOf(candidate, 1) !== -1);
129
+ const inTail = sequences.some((other) => other.length > 1 && other.indexOf(candidate, 1) !== -1);
130
130
  if (!inTail) {
131
131
  head = candidate;
132
132
  break;
@@ -153,7 +153,7 @@ function c3Linearize(classId, parentMap, cache, inProgress) {
153
153
  /** Resolve by MRO order — first ancestor in linearized order wins. */
154
154
  function resolveByMroOrder(methodName, defs, mroOrder, reasonPrefix) {
155
155
  for (const ancestorId of mroOrder) {
156
- const match = defs.find(d => d.classId === ancestorId);
156
+ const match = defs.find((d) => d.classId === ancestorId);
157
157
  if (match) {
158
158
  return {
159
159
  resolvedTo: match.methodId,
@@ -162,7 +162,11 @@ function resolveByMroOrder(methodName, defs, mroOrder, reasonPrefix) {
162
162
  };
163
163
  }
164
164
  }
165
- return { resolvedTo: defs[0].methodId, reason: `${reasonPrefix} fallback: first definition`, confidence: 0.7 };
165
+ return {
166
+ resolvedTo: defs[0].methodId,
167
+ reason: `${reasonPrefix} fallback: first definition`,
168
+ confidence: 0.7,
169
+ };
166
170
  }
167
171
  function resolveCsharpJava(methodName, defs, parentEdgeTypes) {
168
172
  const classDefs = [];
@@ -186,7 +190,7 @@ function resolveCsharpJava(methodName, defs, parentEdgeTypes) {
186
190
  if (interfaceDefs.length > 1) {
187
191
  return {
188
192
  resolvedTo: null,
189
- reason: `ambiguous: ${methodName} defined in multiple interfaces: ${interfaceDefs.map(d => d.className).join(', ')}`,
193
+ reason: `ambiguous: ${methodName} defined in multiple interfaces: ${interfaceDefs.map((d) => d.className).join(', ')}`,
190
194
  confidence: 0.5,
191
195
  };
192
196
  }
@@ -231,7 +235,7 @@ export function computeMRO(graph) {
231
235
  }
232
236
  // Get the parent names for the MRO entry
233
237
  const mroNames = mroOrder
234
- .map(id => graph.getNode(id)?.properties.name)
238
+ .map((id) => graph.getNode(id)?.properties.name)
235
239
  .filter((n) => n !== undefined);
236
240
  // Collect methods from all ancestors, grouped by method name
237
241
  const methodsByName = new Map();
@@ -254,7 +258,7 @@ export function computeMRO(graph) {
254
258
  methodsByName.set(methodName, defs);
255
259
  }
256
260
  // Avoid duplicates (same method seen via multiple paths)
257
- if (!defs.some(d => d.methodId === methodId)) {
261
+ if (!defs.some((d) => d.methodId === methodId)) {
258
262
  defs.push({
259
263
  classId: ancestorId,
260
264
  className: ancestorNode.properties.name,
@@ -275,7 +279,7 @@ export function computeMRO(graph) {
275
279
  continue;
276
280
  // Own method shadows inherited — no ambiguity
277
281
  const ownMethods = methodMap.get(classId) ?? [];
278
- const ownDefinesIt = ownMethods.some(mid => {
282
+ const ownDefinesIt = ownMethods.some((mid) => {
279
283
  const mn = graph.getNode(mid);
280
284
  return mn?.properties.name === methodName;
281
285
  });
@@ -30,8 +30,8 @@ export function walkBindingChain(name, currentFilePath, symbolTable, namedImport
30
30
  visited.add(key);
31
31
  const targetName = binding.exportedName;
32
32
  const resolvedDefs = targetName !== lookupName || depth > 0
33
- ? symbolTable.lookupFuzzy(targetName).filter(def => def.filePath === binding.sourcePath)
34
- : allDefs.filter(def => def.filePath === binding.sourcePath);
33
+ ? symbolTable.lookupFuzzy(targetName).filter((def) => def.filePath === binding.sourcePath)
34
+ : allDefs.filter((def) => def.filePath === binding.sourcePath);
35
35
  if (resolvedDefs.length > 0)
36
36
  return resolvedDefs;
37
37
  // No definition in source file → follow re-export chain
@@ -42,7 +42,9 @@ function collectRustBindings(node, bindings) {
42
42
  let hasDeeper = false;
43
43
  for (let i = 0; i < node.namedChildCount; i++) {
44
44
  const child = node.namedChild(i);
45
- if (child?.type === 'use_list' || child?.type === 'use_as_clause' || child?.type === 'scoped_use_list') {
45
+ if (child?.type === 'use_list' ||
46
+ child?.type === 'use_as_clause' ||
47
+ child?.type === 'scoped_use_list') {
46
48
  hasDeeper = true;
47
49
  break;
48
50
  }
@@ -2,9 +2,9 @@ import Parser from 'tree-sitter';
2
2
  import { loadParser, loadLanguage, isLanguageAvailable } from '../tree-sitter/parser-loader.js';
3
3
  import { getProvider } from './languages/index.js';
4
4
  import { generateId } from '../../lib/utils.js';
5
- import { getLanguageFromFilename } from './utils/language-detection.js';
5
+ import { getLanguageFromFilename } from 'gitnexus-shared';
6
6
  import { yieldToEventLoop } from './utils/event-loop.js';
7
- import { getDefinitionNodeFromCaptures, findEnclosingClassId, extractMethodSignature, getLabelFromCaptures, CLASS_CONTAINER_TYPES } from './utils/ast-helpers.js';
7
+ import { getDefinitionNodeFromCaptures, findEnclosingClassId, extractMethodSignature, getLabelFromCaptures, CLASS_CONTAINER_TYPES, } from './utils/ast-helpers.js';
8
8
  import { detectFrameworkFromAST } from './framework-detection.js';
9
9
  import { buildTypeEnv } from './type-env.js';
10
10
  import { getTreeSitterBufferSize, TREE_SITTER_MAX_BUFFER } from './constants.js';
@@ -20,7 +20,19 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
20
20
  parseableFiles.push({ path: file.path, content: file.content });
21
21
  }
22
22
  if (parseableFiles.length === 0)
23
- return { imports: [], calls: [], assignments: [], heritage: [], routes: [], fetchCalls: [], decoratorRoutes: [], toolDefs: [], ormQueries: [], constructorBindings: [], typeEnvBindings: [] };
23
+ return {
24
+ imports: [],
25
+ calls: [],
26
+ assignments: [],
27
+ heritage: [],
28
+ routes: [],
29
+ fetchCalls: [],
30
+ decoratorRoutes: [],
31
+ toolDefs: [],
32
+ ormQueries: [],
33
+ constructorBindings: [],
34
+ typeEnvBindings: [],
35
+ };
24
36
  const total = files.length;
25
37
  // Dispatch to worker pool — pool handles splitting into chunks and sub-batching
26
38
  const chunkResults = await workerPool.dispatch(parseableFiles, (filesProcessed) => {
@@ -87,7 +99,19 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
87
99
  }
88
100
  // Final progress
89
101
  onFileProgress?.(total, total, 'done');
90
- return { imports: allImports, calls: allCalls, assignments: allAssignments, heritage: allHeritage, routes: allRoutes, fetchCalls: allFetchCalls, decoratorRoutes: allDecoratorRoutes, toolDefs: allToolDefs, ormQueries: allORMQueries, constructorBindings: allConstructorBindings, typeEnvBindings: allTypeEnvBindings };
102
+ return {
103
+ imports: allImports,
104
+ calls: allCalls,
105
+ assignments: allAssignments,
106
+ heritage: allHeritage,
107
+ routes: allRoutes,
108
+ fetchCalls: allFetchCalls,
109
+ decoratorRoutes: allDecoratorRoutes,
110
+ toolDefs: allToolDefs,
111
+ ormQueries: allORMQueries,
112
+ constructorBindings: allConstructorBindings,
113
+ typeEnvBindings: allTypeEnvBindings,
114
+ };
91
115
  };
92
116
  // ============================================================================
93
117
  // Sequential fallback (original implementation)
@@ -178,7 +202,9 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
178
202
  }
179
203
  let tree;
180
204
  try {
181
- tree = parser.parse(file.content, undefined, { bufferSize: getTreeSitterBufferSize(file.content.length) });
205
+ tree = parser.parse(file.content, undefined, {
206
+ bufferSize: getTreeSitterBufferSize(file.content.length),
207
+ });
182
208
  }
183
209
  catch (parseError) {
184
210
  console.warn(`Skipping unparseable file: ${file.path}`);
@@ -202,10 +228,12 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
202
228
  continue;
203
229
  }
204
230
  // Build per-file type environment for FieldExtractor context (lightweight — skipped if no fieldExtractor)
205
- const typeEnv = provider.fieldExtractor ? buildTypeEnv(tree, language, { enclosingFunctionFinder: provider.enclosingFunctionFinder }) : null;
206
- matches.forEach(match => {
231
+ const typeEnv = provider.fieldExtractor
232
+ ? buildTypeEnv(tree, language, { enclosingFunctionFinder: provider.enclosingFunctionFinder })
233
+ : null;
234
+ matches.forEach((match) => {
207
235
  const captureMap = {};
208
- match.captures.forEach(c => {
236
+ match.captures.forEach((c) => {
209
237
  captureMap[c.name] = c.node;
210
238
  });
211
239
  const nodeLabel = getLabelFromCaptures(captureMap, provider);
@@ -217,19 +245,27 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
217
245
  return;
218
246
  const nodeName = nameNode ? nameNode.text : 'init';
219
247
  const definitionNodeForRange = getDefinitionNodeFromCaptures(captureMap);
220
- const startLine = definitionNodeForRange ? definitionNodeForRange.startPosition.row : (nameNode ? nameNode.startPosition.row : 0);
248
+ const startLine = definitionNodeForRange
249
+ ? definitionNodeForRange.startPosition.row
250
+ : nameNode
251
+ ? nameNode.startPosition.row
252
+ : 0;
221
253
  const nodeId = generateId(nodeLabel, `${file.path}:${nodeName}`);
222
254
  const definitionNode = getDefinitionNodeFromCaptures(captureMap);
223
255
  const frameworkHint = definitionNode
224
256
  ? detectFrameworkFromAST(language, (definitionNode.text || '').slice(0, 300))
225
257
  : null;
226
258
  // Extract method signature for Method/Constructor nodes
227
- const methodSig = (nodeLabel === 'Function' || nodeLabel === 'Method' || nodeLabel === 'Constructor')
259
+ const methodSig = nodeLabel === 'Function' || nodeLabel === 'Method' || nodeLabel === 'Constructor'
228
260
  ? extractMethodSignature(definitionNode)
229
261
  : undefined;
230
262
  // Language-specific return type fallback (e.g. Ruby YARD @return [Type])
231
263
  // Also upgrades uninformative AST types like PHP `array` with PHPDoc `@return User[]`
232
- if (methodSig && (!methodSig.returnType || methodSig.returnType === 'array' || methodSig.returnType === 'iterable') && definitionNode) {
264
+ if (methodSig &&
265
+ (!methodSig.returnType ||
266
+ methodSig.returnType === 'array' ||
267
+ methodSig.returnType === 'iterable') &&
268
+ definitionNode) {
233
269
  const tc = provider.typeConfig;
234
270
  if (tc?.extractReturnType) {
235
271
  const docReturn = tc.extractReturnType(definitionNode);
@@ -247,23 +283,34 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
247
283
  endLine: definitionNodeForRange ? definitionNodeForRange.endPosition.row : startLine,
248
284
  language: language,
249
285
  isExported: cachedExportCheck(provider.exportChecker, nameNode || definitionNodeForRange, nodeName),
250
- ...(frameworkHint ? {
251
- astFrameworkMultiplier: frameworkHint.entryPointMultiplier,
252
- astFrameworkReason: frameworkHint.reason,
253
- } : {}),
254
- ...(methodSig ? {
255
- parameterCount: methodSig.parameterCount,
256
- ...(methodSig.requiredParameterCount !== undefined ? { requiredParameterCount: methodSig.requiredParameterCount } : {}),
257
- ...(methodSig.parameterTypes ? { parameterTypes: methodSig.parameterTypes } : {}),
258
- returnType: methodSig.returnType,
259
- } : {}),
286
+ ...(frameworkHint
287
+ ? {
288
+ astFrameworkMultiplier: frameworkHint.entryPointMultiplier,
289
+ astFrameworkReason: frameworkHint.reason,
290
+ }
291
+ : {}),
292
+ ...(methodSig
293
+ ? {
294
+ parameterCount: methodSig.parameterCount,
295
+ ...(methodSig.requiredParameterCount !== undefined
296
+ ? { requiredParameterCount: methodSig.requiredParameterCount }
297
+ : {}),
298
+ ...(methodSig.parameterTypes ? { parameterTypes: methodSig.parameterTypes } : {}),
299
+ returnType: methodSig.returnType,
300
+ }
301
+ : {}),
260
302
  },
261
303
  };
262
304
  graph.addNode(node);
263
305
  // Compute enclosing class for Method/Constructor/Property/Function — used for both ownerId and HAS_METHOD
264
306
  // Function is included because Kotlin/Rust/Python capture class methods as Function nodes
265
- const needsOwner = nodeLabel === 'Method' || nodeLabel === 'Constructor' || nodeLabel === 'Property' || nodeLabel === 'Function';
266
- const enclosingClassId = needsOwner ? cachedFindEnclosingClassId(nameNode || definitionNodeForRange, file.path) : null;
307
+ const needsOwner = nodeLabel === 'Method' ||
308
+ nodeLabel === 'Constructor' ||
309
+ nodeLabel === 'Property' ||
310
+ nodeLabel === 'Function';
311
+ const enclosingClassId = needsOwner
312
+ ? cachedFindEnclosingClassId(nameNode || definitionNodeForRange, file.path)
313
+ : null;
267
314
  // Extract declared type and field metadata for Property nodes
268
315
  let declaredType;
269
316
  let seqVisibility;
@@ -275,7 +322,10 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
275
322
  const classNode = seqFindEnclosingClassNode(definitionNode);
276
323
  if (classNode) {
277
324
  const fieldMap = seqGetFieldInfo(classNode, provider, {
278
- typeEnv, symbolTable: NOOP_SYMBOL_TABLE_SEQ, filePath: file.path, language,
325
+ typeEnv,
326
+ symbolTable: NOOP_SYMBOL_TABLE_SEQ,
327
+ filePath: file.path,
328
+ language,
279
329
  });
280
330
  const info = fieldMap?.get(nodeName);
281
331
  if (info) {
@@ -1,4 +1,5 @@
1
- import { PipelineProgress, PipelineResult } from '../../types/pipeline.js';
1
+ import { type PipelineProgress } from 'gitnexus-shared';
2
+ import { PipelineResult } from '../../types/pipeline.js';
2
3
  /** A group of files with no mutual dependencies, safe to process in parallel. */
3
4
  type IndependentFileGroup = readonly string[];
4
5
  /** Kahn's algorithm: returns files grouped by topological level.