gitnexus 1.6.2-rc.9 → 1.6.2

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 (220) 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/_shared/mro-strategy.d.ts +38 -16
  6. package/dist/_shared/mro-strategy.d.ts.map +1 -1
  7. package/dist/cli/ai-context.js +0 -58
  8. package/dist/cli/analyze.js +3 -0
  9. package/dist/core/embeddings/ast-utils.d.ts +22 -0
  10. package/dist/core/embeddings/ast-utils.js +105 -0
  11. package/dist/core/embeddings/character-chunk.d.ts +12 -0
  12. package/dist/core/embeddings/character-chunk.js +43 -0
  13. package/dist/core/embeddings/chunker.d.ts +14 -0
  14. package/dist/core/embeddings/chunker.js +234 -0
  15. package/dist/core/embeddings/embedding-pipeline.d.ts +20 -24
  16. package/dist/core/embeddings/embedding-pipeline.js +176 -107
  17. package/dist/core/embeddings/line-index.d.ts +7 -0
  18. package/dist/core/embeddings/line-index.js +42 -0
  19. package/dist/core/embeddings/server-mapping.d.ts +15 -0
  20. package/dist/core/embeddings/server-mapping.js +33 -0
  21. package/dist/core/embeddings/structural-extractor.d.ts +15 -0
  22. package/dist/core/embeddings/structural-extractor.js +58 -0
  23. package/dist/core/embeddings/text-generator.d.ts +20 -13
  24. package/dist/core/embeddings/text-generator.js +151 -119
  25. package/dist/core/embeddings/types.d.ts +81 -3
  26. package/dist/core/embeddings/types.js +105 -3
  27. package/dist/core/group/extractors/http-patterns/node.js +130 -0
  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 +2 -4
  53. package/dist/core/ingestion/call-processor.js +221 -89
  54. package/dist/core/ingestion/call-routing.d.ts +8 -12
  55. package/dist/core/ingestion/call-routing.js +13 -34
  56. package/dist/core/ingestion/call-types.d.ts +135 -0
  57. package/dist/core/ingestion/call-types.js +2 -0
  58. package/dist/core/ingestion/class-extractors/configs/c-cpp.d.ts +3 -0
  59. package/dist/core/ingestion/class-extractors/configs/c-cpp.js +11 -0
  60. package/dist/core/ingestion/class-extractors/configs/csharp.d.ts +2 -0
  61. package/dist/core/ingestion/class-extractors/configs/csharp.js +21 -0
  62. package/dist/core/ingestion/class-extractors/configs/dart.d.ts +2 -0
  63. package/dist/core/ingestion/class-extractors/configs/dart.js +7 -0
  64. package/dist/core/ingestion/class-extractors/configs/go.d.ts +2 -0
  65. package/dist/core/ingestion/class-extractors/configs/go.js +20 -0
  66. package/dist/core/ingestion/class-extractors/configs/jvm.d.ts +3 -0
  67. package/dist/core/ingestion/class-extractors/configs/jvm.js +35 -0
  68. package/dist/core/ingestion/class-extractors/configs/php.d.ts +2 -0
  69. package/dist/core/ingestion/class-extractors/configs/php.js +7 -0
  70. package/dist/core/ingestion/class-extractors/configs/python.d.ts +2 -0
  71. package/dist/core/ingestion/class-extractors/configs/python.js +7 -0
  72. package/dist/core/ingestion/class-extractors/configs/ruby.d.ts +2 -0
  73. package/dist/core/ingestion/class-extractors/configs/ruby.js +7 -0
  74. package/dist/core/ingestion/class-extractors/configs/rust.d.ts +2 -0
  75. package/dist/core/ingestion/class-extractors/configs/rust.js +7 -0
  76. package/dist/core/ingestion/class-extractors/configs/swift.d.ts +2 -0
  77. package/dist/core/ingestion/class-extractors/configs/swift.js +18 -0
  78. package/dist/core/ingestion/class-extractors/configs/typescript-javascript.d.ts +4 -0
  79. package/dist/core/ingestion/class-extractors/configs/typescript-javascript.js +28 -0
  80. package/dist/core/ingestion/field-types.d.ts +1 -1
  81. package/dist/core/ingestion/heritage-extractors/configs/go.d.ts +13 -0
  82. package/dist/core/ingestion/heritage-extractors/configs/go.js +20 -0
  83. package/dist/core/ingestion/heritage-extractors/configs/ruby.d.ts +18 -0
  84. package/dist/core/ingestion/heritage-extractors/configs/ruby.js +65 -0
  85. package/dist/core/ingestion/heritage-extractors/generic.d.ts +23 -0
  86. package/dist/core/ingestion/heritage-extractors/generic.js +47 -0
  87. package/dist/core/ingestion/heritage-processor.d.ts +9 -0
  88. package/dist/core/ingestion/heritage-processor.js +120 -85
  89. package/dist/core/ingestion/heritage-types.d.ts +73 -0
  90. package/dist/core/ingestion/heritage-types.js +2 -0
  91. package/dist/core/ingestion/import-resolvers/configs/c-cpp.d.ts +7 -0
  92. package/dist/core/ingestion/import-resolvers/configs/c-cpp.js +14 -0
  93. package/dist/core/ingestion/import-resolvers/configs/csharp.d.ts +8 -0
  94. package/dist/core/ingestion/import-resolvers/configs/csharp.js +27 -0
  95. package/dist/core/ingestion/import-resolvers/configs/dart.d.ts +17 -0
  96. package/dist/core/ingestion/import-resolvers/{dart.js → configs/dart.js} +26 -16
  97. package/dist/core/ingestion/import-resolvers/configs/go.d.ts +8 -0
  98. package/dist/core/ingestion/import-resolvers/configs/go.js +26 -0
  99. package/dist/core/ingestion/import-resolvers/configs/jvm.d.ts +13 -0
  100. package/dist/core/ingestion/import-resolvers/configs/jvm.js +68 -0
  101. package/dist/core/ingestion/import-resolvers/configs/php.d.ts +8 -0
  102. package/dist/core/ingestion/import-resolvers/configs/php.js +15 -0
  103. package/dist/core/ingestion/import-resolvers/configs/python.d.ts +12 -0
  104. package/dist/core/ingestion/import-resolvers/configs/python.js +41 -0
  105. package/dist/core/ingestion/import-resolvers/configs/ruby.d.ts +8 -0
  106. package/dist/core/ingestion/import-resolvers/configs/ruby.js +16 -0
  107. package/dist/core/ingestion/import-resolvers/configs/rust.d.ts +8 -0
  108. package/dist/core/ingestion/import-resolvers/configs/rust.js +54 -0
  109. package/dist/core/ingestion/import-resolvers/configs/swift.d.ts +8 -0
  110. package/dist/core/ingestion/import-resolvers/{swift.js → configs/swift.js} +10 -5
  111. package/dist/core/ingestion/import-resolvers/configs/typescript-javascript.d.ts +9 -0
  112. package/dist/core/ingestion/import-resolvers/configs/typescript-javascript.js +23 -0
  113. package/dist/core/ingestion/import-resolvers/csharp.d.ts +4 -5
  114. package/dist/core/ingestion/import-resolvers/csharp.js +4 -20
  115. package/dist/core/ingestion/import-resolvers/go.d.ts +4 -5
  116. package/dist/core/ingestion/import-resolvers/go.js +4 -19
  117. package/dist/core/ingestion/import-resolvers/jvm.d.ts +5 -10
  118. package/dist/core/ingestion/import-resolvers/jvm.js +5 -58
  119. package/dist/core/ingestion/import-resolvers/php.d.ts +4 -5
  120. package/dist/core/ingestion/import-resolvers/php.js +4 -7
  121. package/dist/core/ingestion/import-resolvers/python.d.ts +3 -6
  122. package/dist/core/ingestion/import-resolvers/python.js +3 -18
  123. package/dist/core/ingestion/import-resolvers/resolver-factory.d.ts +24 -0
  124. package/dist/core/ingestion/import-resolvers/resolver-factory.js +33 -0
  125. package/dist/core/ingestion/import-resolvers/ruby.d.ts +4 -5
  126. package/dist/core/ingestion/import-resolvers/ruby.js +4 -7
  127. package/dist/core/ingestion/import-resolvers/rust.d.ts +4 -5
  128. package/dist/core/ingestion/import-resolvers/rust.js +4 -47
  129. package/dist/core/ingestion/import-resolvers/standard.d.ts +3 -9
  130. package/dist/core/ingestion/import-resolvers/standard.js +7 -8
  131. package/dist/core/ingestion/import-resolvers/types.d.ts +24 -0
  132. package/dist/core/ingestion/language-provider.d.ts +80 -0
  133. package/dist/core/ingestion/languages/c-cpp.js +18 -12
  134. package/dist/core/ingestion/languages/csharp.js +13 -21
  135. package/dist/core/ingestion/languages/dart.js +13 -7
  136. package/dist/core/ingestion/languages/go.js +14 -20
  137. package/dist/core/ingestion/languages/java.js +13 -18
  138. package/dist/core/ingestion/languages/kotlin.js +13 -13
  139. package/dist/core/ingestion/languages/php.js +13 -7
  140. package/dist/core/ingestion/languages/python.js +13 -7
  141. package/dist/core/ingestion/languages/ruby.js +103 -22
  142. package/dist/core/ingestion/languages/rust.js +13 -7
  143. package/dist/core/ingestion/languages/swift.js +13 -18
  144. package/dist/core/ingestion/languages/typescript.js +18 -23
  145. package/dist/core/ingestion/languages/vue.js +13 -17
  146. package/dist/core/ingestion/model/heritage-map.d.ts +35 -0
  147. package/dist/core/ingestion/model/heritage-map.js +110 -9
  148. package/dist/core/ingestion/model/index.d.ts +2 -2
  149. package/dist/core/ingestion/model/index.js +1 -1
  150. package/dist/core/ingestion/model/resolve.d.ts +33 -28
  151. package/dist/core/ingestion/model/resolve.js +111 -27
  152. package/dist/core/ingestion/parsing-processor.d.ts +1 -2
  153. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +1 -0
  154. package/dist/core/ingestion/pipeline-phases/parse-impl.js +9 -3
  155. package/dist/core/ingestion/pipeline-phases/parse.d.ts +7 -0
  156. package/dist/core/ingestion/pipeline.d.ts +11 -0
  157. package/dist/core/ingestion/pipeline.js +9 -2
  158. package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
  159. package/dist/core/ingestion/tree-sitter-queries.js +81 -0
  160. package/dist/core/ingestion/type-env.d.ts +1 -1
  161. package/dist/core/ingestion/utils/ast-helpers.d.ts +1 -1
  162. package/dist/core/ingestion/utils/ast-helpers.js +22 -2
  163. package/dist/core/ingestion/utils/ruby-self-call.d.ts +52 -0
  164. package/dist/core/ingestion/utils/ruby-self-call.js +59 -0
  165. package/dist/core/ingestion/variable-extractors/configs/c-cpp.d.ts +3 -0
  166. package/dist/core/ingestion/variable-extractors/configs/c-cpp.js +81 -0
  167. package/dist/core/ingestion/variable-extractors/configs/csharp.d.ts +9 -0
  168. package/dist/core/ingestion/variable-extractors/configs/csharp.js +63 -0
  169. package/dist/core/ingestion/variable-extractors/configs/dart.d.ts +2 -0
  170. package/dist/core/ingestion/variable-extractors/configs/dart.js +94 -0
  171. package/dist/core/ingestion/variable-extractors/configs/go.d.ts +2 -0
  172. package/dist/core/ingestion/variable-extractors/configs/go.js +83 -0
  173. package/dist/core/ingestion/variable-extractors/configs/jvm.d.ts +18 -0
  174. package/dist/core/ingestion/variable-extractors/configs/jvm.js +115 -0
  175. package/dist/core/ingestion/variable-extractors/configs/php.d.ts +14 -0
  176. package/dist/core/ingestion/variable-extractors/configs/php.js +58 -0
  177. package/dist/core/ingestion/variable-extractors/configs/python.d.ts +2 -0
  178. package/dist/core/ingestion/variable-extractors/configs/python.js +101 -0
  179. package/dist/core/ingestion/variable-extractors/configs/ruby.d.ts +11 -0
  180. package/dist/core/ingestion/variable-extractors/configs/ruby.js +52 -0
  181. package/dist/core/ingestion/variable-extractors/configs/rust.d.ts +2 -0
  182. package/dist/core/ingestion/variable-extractors/configs/rust.js +76 -0
  183. package/dist/core/ingestion/variable-extractors/configs/swift.d.ts +2 -0
  184. package/dist/core/ingestion/variable-extractors/configs/swift.js +88 -0
  185. package/dist/core/ingestion/variable-extractors/configs/typescript-javascript.d.ts +3 -0
  186. package/dist/core/ingestion/variable-extractors/configs/typescript-javascript.js +83 -0
  187. package/dist/core/ingestion/variable-extractors/generic.d.ts +5 -0
  188. package/dist/core/ingestion/variable-extractors/generic.js +80 -0
  189. package/dist/core/ingestion/variable-types.d.ts +82 -0
  190. package/dist/core/ingestion/variable-types.js +2 -0
  191. package/dist/core/ingestion/workers/parse-worker.js +244 -217
  192. package/dist/core/ingestion/workers/worker-pool.js +3 -0
  193. package/dist/core/lbug/csv-generator.js +1 -0
  194. package/dist/core/lbug/lbug-adapter.d.ts +4 -5
  195. package/dist/core/lbug/lbug-adapter.js +38 -14
  196. package/dist/core/lbug/schema.d.ts +2 -1
  197. package/dist/core/lbug/schema.js +10 -1
  198. package/dist/core/run-analyze.js +6 -7
  199. package/dist/core/tree-sitter/parser-loader.d.ts +3 -0
  200. package/dist/core/tree-sitter/parser-loader.js +17 -8
  201. package/dist/mcp/local/local-backend.js +29 -19
  202. package/dist/server/api.js +2 -0
  203. package/dist/types/pipeline.d.ts +6 -0
  204. package/package.json +8 -7
  205. package/scripts/build-tree-sitter-proto.cjs +82 -0
  206. package/vendor/node_modules/node-addon-api/node_addon_api.Makefile +6 -0
  207. package/vendor/node_modules/node-addon-api/node_addon_api.target.mk +104 -0
  208. package/vendor/node_modules/node-addon-api/node_addon_api_except.target.mk +108 -0
  209. package/vendor/node_modules/node-addon-api/node_addon_api_except_all.target.mk +104 -0
  210. package/vendor/node_modules/node-addon-api/node_addon_api_maybe.target.mk +104 -0
  211. package/vendor/tree-sitter-proto/package.json +1 -7
  212. package/dist/core/ingestion/call-sites/extract-language-call-site.d.ts +0 -10
  213. package/dist/core/ingestion/call-sites/extract-language-call-site.js +0 -22
  214. package/dist/core/ingestion/call-sites/java.d.ts +0 -9
  215. package/dist/core/ingestion/call-sites/java.js +0 -30
  216. package/dist/core/ingestion/import-resolvers/dart.d.ts +0 -7
  217. package/dist/core/ingestion/import-resolvers/swift.d.ts +0 -7
  218. package/dist/core/ingestion/import-resolvers/vue.d.ts +0 -8
  219. package/dist/core/ingestion/import-resolvers/vue.js +0 -9
  220. package/scripts/preinstall-cleanup.cjs +0 -34
@@ -54,6 +54,69 @@ const resolveHeritageId = (name, filePath, ctx, fallbackLabel, fallbackKey) => {
54
54
  confidence: TIER_CONFIDENCE['global'],
55
55
  };
56
56
  };
57
+ /**
58
+ * Resolve a single HeritageInfo to a graph edge, using the same resolution
59
+ * logic as processHeritageFromExtracted. This bridges the heritage extractor
60
+ * output format to the graph-resolution side.
61
+ */
62
+ const resolveAndAddHeritageEdge = (graph, item, filePath, language, ctx) => {
63
+ if (item.kind === 'extends') {
64
+ const { type: relType, idPrefix } = resolveExtendsType(item.parentName, filePath, ctx, getHeritageStrategyForLanguage(language));
65
+ const child = resolveHeritageId(item.className, filePath, ctx, 'Class', `${filePath}:${item.className}`);
66
+ const parent = resolveHeritageId(item.parentName, filePath, ctx, idPrefix);
67
+ if (child.id && parent.id && child.id !== parent.id) {
68
+ graph.addRelationship({
69
+ id: generateId(relType, `${child.id}->${parent.id}`),
70
+ sourceId: child.id,
71
+ targetId: parent.id,
72
+ type: relType,
73
+ confidence: Math.sqrt(child.confidence * parent.confidence),
74
+ reason: '',
75
+ });
76
+ }
77
+ }
78
+ else if (item.kind === 'implements') {
79
+ const cls = resolveHeritageId(item.className, filePath, ctx, 'Class', `${filePath}:${item.className}`);
80
+ const iface = resolveHeritageId(item.parentName, filePath, ctx, 'Interface');
81
+ if (cls.id && iface.id) {
82
+ graph.addRelationship({
83
+ id: generateId('IMPLEMENTS', `${cls.id}->${iface.id}`),
84
+ sourceId: cls.id,
85
+ targetId: iface.id,
86
+ type: 'IMPLEMENTS',
87
+ confidence: Math.sqrt(cls.confidence * iface.confidence),
88
+ reason: '',
89
+ });
90
+ }
91
+ }
92
+ else if (item.kind === 'trait-impl' ||
93
+ item.kind === 'include' ||
94
+ item.kind === 'extend' ||
95
+ item.kind === 'prepend') {
96
+ // Fallback label for an unresolved child name. Rust `trait-impl` children
97
+ // are structs; Ruby mixin children are classes or modules (Trait). For
98
+ // Ruby mixin kinds the common case resolves through the type registry
99
+ // post-plan-001, so the fallback only fires for true-unresolved references
100
+ // (e.g. mixin inside a singleton_class). `Class` is strictly better than
101
+ // `Struct` there because it matches the label the structure phase would
102
+ // emit for a Ruby `class` — the dominant shape. Ruby modules that fail
103
+ // to resolve still lose their `Trait` label in the synthesized id, but
104
+ // they fail to resolve rarely and the tradeoff is documented.
105
+ const childFallbackLabel = item.kind === 'trait-impl' ? 'Struct' : 'Class';
106
+ const strct = resolveHeritageId(item.className, filePath, ctx, childFallbackLabel, `${filePath}:${item.className}`);
107
+ const trait = resolveHeritageId(item.parentName, filePath, ctx, 'Trait');
108
+ if (strct.id && trait.id) {
109
+ graph.addRelationship({
110
+ id: generateId('IMPLEMENTS', `${strct.id}->${trait.id}:${item.kind}`),
111
+ sourceId: strct.id,
112
+ targetId: trait.id,
113
+ type: 'IMPLEMENTS',
114
+ confidence: Math.sqrt(strct.confidence * trait.confidence),
115
+ reason: item.kind,
116
+ });
117
+ }
118
+ }
119
+ };
57
120
  export const processHeritage = async (graph, files, astCache, ctx, onProgress) => {
58
121
  const parser = await loadParser();
59
122
  const logSkipped = isVerboseIngestionEnabled();
@@ -98,78 +161,31 @@ export const processHeritage = async (graph, files, astCache, ctx, onProgress) =
98
161
  let query;
99
162
  let matches;
100
163
  try {
101
- const language = parser.getLanguage();
102
- query = new Parser.Query(language, queryStr);
164
+ const treeSitterLang = parser.getLanguage();
165
+ query = new Parser.Query(treeSitterLang, queryStr);
103
166
  matches = query.matches(tree.rootNode);
104
167
  }
105
168
  catch (queryError) {
106
169
  console.warn(`Heritage query error for ${file.path}:`, queryError);
107
170
  continue;
108
171
  }
109
- // 4. Process heritage matches
172
+ // 4. Process heritage matches via provider heritage extractor
173
+ const heritageExtractor = provider.heritageExtractor;
110
174
  matches.forEach((match) => {
111
175
  const captureMap = {};
112
176
  match.captures.forEach((c) => {
113
177
  captureMap[c.name] = c.node;
114
178
  });
115
- // EXTENDS or IMPLEMENTS: resolve via symbol table for languages where
116
- // the tree-sitter query can't distinguish classes from interfaces (C#, Java)
117
- if (captureMap['heritage.class'] && captureMap['heritage.extends']) {
118
- // Go struct embedding: skip named fields (only anonymous fields are embedded)
119
- const extendsNode = captureMap['heritage.extends'];
120
- const fieldDecl = extendsNode.parent;
121
- if (fieldDecl?.type === 'field_declaration' && fieldDecl.childForFieldName('name')) {
122
- return; // Named field, not struct embedding
123
- }
124
- const className = captureMap['heritage.class'].text;
125
- const parentClassName = captureMap['heritage.extends'].text;
126
- const { type: relType, idPrefix } = resolveExtendsType(parentClassName, file.path, ctx, getHeritageStrategyForLanguage(language));
127
- const child = resolveHeritageId(className, file.path, ctx, 'Class', `${file.path}:${className}`);
128
- const parent = resolveHeritageId(parentClassName, file.path, ctx, idPrefix);
129
- if (child.id && parent.id && child.id !== parent.id) {
130
- graph.addRelationship({
131
- id: generateId(relType, `${child.id}->${parent.id}`),
132
- sourceId: child.id,
133
- targetId: parent.id,
134
- type: relType,
135
- confidence: Math.sqrt(child.confidence * parent.confidence),
136
- reason: '',
137
- });
138
- }
139
- }
140
- // IMPLEMENTS: Class implements Interface (TypeScript only)
141
- if (captureMap['heritage.class'] && captureMap['heritage.implements']) {
142
- const className = captureMap['heritage.class'].text;
143
- const interfaceName = captureMap['heritage.implements'].text;
144
- const cls = resolveHeritageId(className, file.path, ctx, 'Class', `${file.path}:${className}`);
145
- const iface = resolveHeritageId(interfaceName, file.path, ctx, 'Interface');
146
- if (cls.id && iface.id) {
147
- graph.addRelationship({
148
- id: generateId('IMPLEMENTS', `${cls.id}->${iface.id}`),
149
- sourceId: cls.id,
150
- targetId: iface.id,
151
- type: 'IMPLEMENTS',
152
- confidence: Math.sqrt(cls.confidence * iface.confidence),
153
- reason: '',
154
- });
155
- }
156
- }
157
- // IMPLEMENTS (Rust): impl Trait for Struct
158
- if (captureMap['heritage.trait'] && captureMap['heritage.class']) {
159
- const structName = captureMap['heritage.class'].text;
160
- const traitName = captureMap['heritage.trait'].text;
161
- const strct = resolveHeritageId(structName, file.path, ctx, 'Struct', `${file.path}:${structName}`);
162
- const trait = resolveHeritageId(traitName, file.path, ctx, 'Trait');
163
- if (strct.id && trait.id) {
164
- graph.addRelationship({
165
- id: generateId('IMPLEMENTS', `${strct.id}->${trait.id}`),
166
- sourceId: strct.id,
167
- targetId: trait.id,
168
- type: 'IMPLEMENTS',
169
- confidence: Math.sqrt(strct.confidence * trait.confidence),
170
- reason: 'trait-impl',
171
- });
172
- }
179
+ if (!captureMap['heritage.class'])
180
+ return;
181
+ if (!heritageExtractor)
182
+ return;
183
+ const heritageItems = heritageExtractor.extract(captureMap, {
184
+ filePath: file.path,
185
+ language,
186
+ });
187
+ for (const item of heritageItems) {
188
+ resolveAndAddHeritageEdge(graph, item, file.path, language, ctx);
173
189
  }
174
190
  });
175
191
  // Tree is now owned by the LRU cache — no manual delete needed
@@ -228,7 +244,11 @@ export const processHeritageFromExtracted = async (graph, extractedHeritage, ctx
228
244
  h.kind === 'include' ||
229
245
  h.kind === 'extend' ||
230
246
  h.kind === 'prepend') {
231
- const strct = resolveHeritageId(h.className, h.filePath, ctx, 'Struct', `${h.filePath}:${h.className}`);
247
+ // See the per-item call above (processHeritageFromExtractedItem) for
248
+ // rationale: `Class` is the correct fallback for Ruby mixin kinds,
249
+ // `Struct` stays the Rust `trait-impl` default.
250
+ const childFallbackLabel = h.kind === 'trait-impl' ? 'Struct' : 'Class';
251
+ const strct = resolveHeritageId(h.className, h.filePath, ctx, childFallbackLabel, `${h.filePath}:${h.className}`);
232
252
  const trait = resolveHeritageId(h.parentName, h.filePath, ctx, 'Trait');
233
253
  if (strct.id && trait.id) {
234
254
  graph.addRelationship({
@@ -249,6 +269,15 @@ export const processHeritageFromExtracted = async (graph, extractedHeritage, ctx
249
269
  * {@link ExtractedHeritage} rows without mutating the graph. Used on the
250
270
  * sequential pipeline path so `buildHeritageMap(..., ctx)` can run before
251
271
  * `processCalls` (worker path defers calls until heritage from all chunks exists).
272
+ *
273
+ * This prepass extracts BOTH capture-based heritage (`@heritage.*` — extends /
274
+ * implements / trait-impl) AND call-based heritage (`@call.name` routed through
275
+ * `heritageExtractor.extractFromCall` — Ruby `include` / `extend` / `prepend`).
276
+ * Without the second pass, sequential-mode `sequentialHeritageMap` would not
277
+ * know about Ruby mixin ancestry before `processCalls` resolves calls against
278
+ * it, silently dropping mixed-in methods from the graph. This function stays
279
+ * read-only — `processCalls` still owns emission of heritage graph edges via
280
+ * its `rubyHeritage` return path.
252
281
  */
253
282
  export async function extractExtractedHeritageFromFiles(files, astCache) {
254
283
  const parser = await loadParser();
@@ -283,40 +312,46 @@ export async function extractExtractedHeritageFromFiles(files, astCache) {
283
312
  catch {
284
313
  continue;
285
314
  }
315
+ const callBasedEnabled = !!provider.heritageExtractor?.extractFromCall;
286
316
  for (const match of matches) {
287
317
  const captureMap = {};
288
318
  match.captures.forEach((c) => {
289
319
  captureMap[c.name] = c.node;
290
320
  });
291
321
  if (captureMap['heritage.class']) {
292
- if (captureMap['heritage.extends']) {
293
- const extendsNode = captureMap['heritage.extends'];
294
- const fieldDecl = extendsNode.parent;
295
- const isNamedField = fieldDecl?.type === 'field_declaration' && fieldDecl.childForFieldName('name');
296
- if (!isNamedField) {
322
+ if (provider.heritageExtractor) {
323
+ const heritageItems = provider.heritageExtractor.extract(captureMap, {
324
+ filePath: file.path,
325
+ language,
326
+ });
327
+ for (const item of heritageItems) {
297
328
  out.push({
298
329
  filePath: file.path,
299
- className: captureMap['heritage.class'].text,
300
- parentName: captureMap['heritage.extends'].text,
301
- kind: 'extends',
330
+ className: item.className,
331
+ parentName: item.parentName,
332
+ kind: item.kind,
302
333
  });
303
334
  }
304
335
  }
305
- if (captureMap['heritage.implements']) {
306
- out.push({
307
- filePath: file.path,
308
- className: captureMap['heritage.class'].text,
309
- parentName: captureMap['heritage.implements'].text,
310
- kind: 'implements',
311
- });
312
- }
313
- if (captureMap['heritage.trait']) {
314
- out.push({
315
- filePath: file.path,
316
- className: captureMap['heritage.class'].text,
317
- parentName: captureMap['heritage.trait'].text,
318
- kind: 'trait-impl',
319
- });
336
+ continue;
337
+ }
338
+ // Call-based heritage (e.g. Ruby include/extend/prepend). Matches the
339
+ // routing the worker path performs inline in parse-worker.ts — see the
340
+ // `provider.heritageExtractor?.extractFromCall` branch there. We only
341
+ // need call-based records here; other @call captures are consumed by
342
+ // processCalls later in the sequential loop.
343
+ if (callBasedEnabled && captureMap['call'] && captureMap['call.name']) {
344
+ const calledName = captureMap['call.name'].text;
345
+ const heritageItems = provider.heritageExtractor.extractFromCall(calledName, captureMap['call'], { filePath: file.path, language });
346
+ if (heritageItems) {
347
+ for (const item of heritageItems) {
348
+ out.push({
349
+ filePath: file.path,
350
+ className: item.className,
351
+ parentName: item.parentName,
352
+ kind: item.kind,
353
+ });
354
+ }
320
355
  }
321
356
  }
322
357
  }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Types for the language-agnostic heritage extraction pipeline.
3
+ *
4
+ * Follows the same pattern as call-types.ts, variable-types.ts, and
5
+ * method-types.ts: defines the domain interfaces consumed by
6
+ * createHeritageExtractor() and the per-language configs.
7
+ *
8
+ * Heritage extraction handles extends/implements/trait-impl captures from
9
+ * tree-sitter queries, plus call-based heritage for languages like Ruby
10
+ * (include/extend/prepend expressed as method calls).
11
+ */
12
+ import type { SupportedLanguages } from '../../_shared/index.js';
13
+ import type { SyntaxNode } from './utils/ast-helpers.js';
14
+ import type { CaptureMap } from './language-provider.js';
15
+ /**
16
+ * Per-match heritage extraction result. The parse worker adds filePath to
17
+ * produce the final {@link ExtractedHeritage} that enters the resolution
18
+ * pipeline (heritage-processor.ts / heritage-map.ts).
19
+ */
20
+ export interface HeritageInfo {
21
+ className: string;
22
+ parentName: string;
23
+ /** 'extends' | 'implements' | 'trait-impl' | 'include' | 'extend' | 'prepend' */
24
+ kind: string;
25
+ }
26
+ export interface HeritageExtractorContext {
27
+ filePath: string;
28
+ language: SupportedLanguages;
29
+ }
30
+ export interface HeritageExtractor {
31
+ readonly language: SupportedLanguages;
32
+ /**
33
+ * Extract heritage records from tree-sitter @heritage.* captures.
34
+ *
35
+ * @param captureMap The capture map from a single tree-sitter match
36
+ * @param context File path and language context
37
+ * @returns Array of heritage records (may be empty if captures don't match)
38
+ */
39
+ extract(captureMap: CaptureMap, context: HeritageExtractorContext): HeritageInfo[];
40
+ /**
41
+ * Extract heritage from a call node (for languages where heritage is
42
+ * expressed as method calls, e.g., Ruby include/extend/prepend).
43
+ *
44
+ * @param calledName The method name (e.g. 'include', 'extend', 'prepend')
45
+ * @param callNode The tree-sitter call AST node
46
+ * @param context File path and language context
47
+ * @returns Heritage records if the call is heritage-related, or null to
48
+ * fall through to the call router / normal call handling.
49
+ */
50
+ extractFromCall?(calledName: string, callNode: SyntaxNode, context: HeritageExtractorContext): HeritageInfo[] | null;
51
+ }
52
+ export interface HeritageExtractionConfig {
53
+ language: SupportedLanguages;
54
+ /**
55
+ * Called for heritage.extends captures. Return true to skip this extends
56
+ * capture. Used by Go to skip named struct fields that match the
57
+ * field_declaration pattern but are not anonymous embeddings.
58
+ *
59
+ * Default: never skip (all extends captures are valid).
60
+ */
61
+ shouldSkipExtends?: (extendsNode: SyntaxNode) => boolean;
62
+ /**
63
+ * Call-based heritage extraction for languages where heritage is expressed
64
+ * as method calls (e.g., Ruby include/extend/prepend).
65
+ *
66
+ * callNames: set of method names that trigger heritage extraction.
67
+ * extract: extract heritage items from the call node + method name.
68
+ */
69
+ callBasedHeritage?: {
70
+ readonly callNames: ReadonlySet<string>;
71
+ extract(calledName: string, callNode: SyntaxNode, filePath: string): HeritageInfo[];
72
+ };
73
+ }
@@ -0,0 +1,2 @@
1
+ // gitnexus/src/core/ingestion/heritage-types.ts
2
+ export {};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * C / C++ import resolution configs.
3
+ * Both use standard resolution for #include directives.
4
+ */
5
+ import type { ImportResolutionConfig } from '../types.js';
6
+ export declare const cImportConfig: ImportResolutionConfig;
7
+ export declare const cppImportConfig: ImportResolutionConfig;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * C / C++ import resolution configs.
3
+ * Both use standard resolution for #include directives.
4
+ */
5
+ import { SupportedLanguages } from '../../../../_shared/index.js';
6
+ import { createStandardStrategy } from '../standard.js';
7
+ export const cImportConfig = {
8
+ language: SupportedLanguages.C,
9
+ strategies: [createStandardStrategy(SupportedLanguages.C)],
10
+ };
11
+ export const cppImportConfig = {
12
+ language: SupportedLanguages.CPlusPlus,
13
+ strategies: [createStandardStrategy(SupportedLanguages.CPlusPlus)],
14
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * C# import resolution config.
3
+ * Namespace-based strategy via .csproj configs, then standard fallback.
4
+ */
5
+ import type { ImportResolutionConfig, ImportResolverStrategy } from '../types.js';
6
+ /** C# namespace-based resolution strategy via .csproj configs. */
7
+ export declare const csharpNamespaceStrategy: ImportResolverStrategy;
8
+ export declare const csharpImportConfig: ImportResolutionConfig;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * C# import resolution config.
3
+ * Namespace-based strategy via .csproj configs, then standard fallback.
4
+ */
5
+ import { SupportedLanguages } from '../../../../_shared/index.js';
6
+ import { createStandardStrategy } from '../standard.js';
7
+ import { resolveCSharpImportInternal, resolveCSharpNamespaceDir } from '../csharp.js';
8
+ /** C# namespace-based resolution strategy via .csproj configs. */
9
+ export const csharpNamespaceStrategy = (rawImportPath, _filePath, ctx) => {
10
+ const csharpConfigs = ctx.configs.csharpConfigs;
11
+ if (csharpConfigs.length > 0) {
12
+ const resolvedFiles = resolveCSharpImportInternal(rawImportPath, csharpConfigs, ctx.normalizedFileList, ctx.allFileList, ctx.index);
13
+ if (resolvedFiles.length > 1) {
14
+ const dirSuffix = resolveCSharpNamespaceDir(rawImportPath, csharpConfigs);
15
+ if (dirSuffix) {
16
+ return { kind: 'package', files: resolvedFiles, dirSuffix };
17
+ }
18
+ }
19
+ if (resolvedFiles.length > 0)
20
+ return { kind: 'files', files: resolvedFiles };
21
+ }
22
+ return null;
23
+ };
24
+ export const csharpImportConfig = {
25
+ language: SupportedLanguages.CSharp,
26
+ strategies: [csharpNamespaceStrategy, createStandardStrategy(SupportedLanguages.CSharp)],
27
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Dart import resolution config.
3
+ * SDK/package strategy first, then relative import strategy (with ./ prepending).
4
+ */
5
+ import type { ImportResolutionConfig, ImportResolverStrategy } from '../types.js';
6
+ /**
7
+ * Dart SDK and package: import strategy.
8
+ * Absorbs dart: SDK imports and external packages (returns empty result to stop chain).
9
+ * Returns null for relative imports to let the next strategy handle them.
10
+ */
11
+ export declare const dartPackageStrategy: ImportResolverStrategy;
12
+ /**
13
+ * Dart relative import strategy — prepends "./" for bare relative paths,
14
+ * then delegates to standard resolution.
15
+ */
16
+ export declare const dartRelativeStrategy: ImportResolverStrategy;
17
+ export declare const dartImportConfig: ImportResolutionConfig;
@@ -1,21 +1,25 @@
1
1
  /**
2
- * Dart import resolution.
3
- * Handles package: imports (local packages) and relative imports.
4
- * SDK imports (dart:*) and external packages are skipped.
2
+ * Dart import resolution config.
3
+ * SDK/package strategy first, then relative import strategy (with ./ prepending).
5
4
  */
6
- import { resolveStandard } from './standard.js';
7
- import { SupportedLanguages } from '../../../_shared/index.js';
8
- export function resolveDartImport(rawImportPath, filePath, ctx) {
5
+ import { SupportedLanguages } from '../../../../_shared/index.js';
6
+ import { resolveStandard } from '../standard.js';
7
+ /**
8
+ * Dart SDK and package: import strategy.
9
+ * Absorbs dart: SDK imports and external packages (returns empty result to stop chain).
10
+ * Returns null for relative imports to let the next strategy handle them.
11
+ */
12
+ export const dartPackageStrategy = (rawImportPath, _filePath, ctx) => {
9
13
  // Strip surrounding quotes from configurable_uri capture
10
14
  const stripped = rawImportPath.replace(/^['"]|['"]$/g, '');
11
15
  // Skip dart: SDK imports (dart:async, dart:io, etc.)
12
16
  if (stripped.startsWith('dart:'))
13
- return null;
17
+ return { kind: 'files', files: [] };
14
18
  // Local package: imports → resolve to lib/<path>
15
19
  if (stripped.startsWith('package:')) {
16
20
  const slashIdx = stripped.indexOf('/');
17
21
  if (slashIdx === -1)
18
- return null;
22
+ return { kind: 'files', files: [] };
19
23
  const relPath = stripped.slice(slashIdx + 1);
20
24
  const candidates = [`lib/${relPath}`, relPath];
21
25
  const files = [];
@@ -31,14 +35,20 @@ export function resolveDartImport(rawImportPath, filePath, ctx) {
31
35
  }
32
36
  if (files.length > 0)
33
37
  return { kind: 'files', files };
34
- return null;
38
+ return { kind: 'files', files: [] }; // external package
35
39
  }
36
- // Relative imports — use standard resolution.
37
- // Dart relative imports don't require a leading "./" (e.g. `import 'models.dart'`).
38
- // The standard resolver only recognises paths starting with "." as relative, so
39
- // prepend "./" when the path doesn't already start with "." to ensure correct
40
- // same-directory resolution (without this, "models.dart" would be mangled by the
41
- // generic dot-to-slash conversion intended for Java-style package imports).
40
+ return null;
41
+ };
42
+ /**
43
+ * Dart relative import strategy prepends "./" for bare relative paths,
44
+ * then delegates to standard resolution.
45
+ */
46
+ export const dartRelativeStrategy = (rawImportPath, filePath, ctx) => {
47
+ const stripped = rawImportPath.replace(/^['"]|['"]$/g, '');
42
48
  const relPath = stripped.startsWith('.') ? stripped : './' + stripped;
43
49
  return resolveStandard(relPath, filePath, ctx, SupportedLanguages.Dart);
44
- }
50
+ };
51
+ export const dartImportConfig = {
52
+ language: SupportedLanguages.Dart,
53
+ strategies: [dartPackageStrategy, dartRelativeStrategy],
54
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Go import resolution config.
3
+ * Go-specific package strategy (go.mod), then standard fallback.
4
+ */
5
+ import type { ImportResolutionConfig, ImportResolverStrategy } from '../types.js';
6
+ /** Go-specific package resolution strategy — resolves go.mod-based package imports. */
7
+ export declare const goPackageStrategy: ImportResolverStrategy;
8
+ export declare const goImportConfig: ImportResolutionConfig;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Go import resolution config.
3
+ * Go-specific package strategy (go.mod), then standard fallback.
4
+ */
5
+ import { SupportedLanguages } from '../../../../_shared/index.js';
6
+ import { createStandardStrategy } from '../standard.js';
7
+ import { resolveGoPackageDir, resolveGoPackage } from '../go.js';
8
+ /** Go-specific package resolution strategy — resolves go.mod-based package imports. */
9
+ export const goPackageStrategy = (rawImportPath, _filePath, ctx) => {
10
+ const goModule = ctx.configs.goModule;
11
+ if (goModule && rawImportPath.startsWith(goModule.modulePath)) {
12
+ const pkgSuffix = resolveGoPackageDir(rawImportPath, goModule);
13
+ if (pkgSuffix) {
14
+ const pkgFiles = resolveGoPackage(rawImportPath, goModule, ctx.normalizedFileList, ctx.allFileList);
15
+ if (pkgFiles.length > 0) {
16
+ return { kind: 'package', files: pkgFiles, dirSuffix: pkgSuffix };
17
+ }
18
+ }
19
+ // Fall through if no files found (package might be external)
20
+ }
21
+ return null;
22
+ };
23
+ export const goImportConfig = {
24
+ language: SupportedLanguages.Go,
25
+ strategies: [goPackageStrategy, createStandardStrategy(SupportedLanguages.Go)],
26
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Java / Kotlin import resolution configs.
3
+ * JVM-specific wildcard/member strategy, then standard fallback.
4
+ */
5
+ import type { ImportResolutionConfig, ImportResolverStrategy } from '../types.js';
6
+ /** Java JVM resolution strategy — wildcard and member import resolution. */
7
+ export declare const javaJvmStrategy: ImportResolverStrategy;
8
+ /**
9
+ * Kotlin JVM resolution strategy — wildcard/member with Java-interop + top-level function imports.
10
+ */
11
+ export declare const kotlinJvmStrategy: ImportResolverStrategy;
12
+ export declare const javaImportConfig: ImportResolutionConfig;
13
+ export declare const kotlinImportConfig: ImportResolutionConfig;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Java / Kotlin import resolution configs.
3
+ * JVM-specific wildcard/member strategy, then standard fallback.
4
+ */
5
+ import { SupportedLanguages } from '../../../../_shared/index.js';
6
+ import { createStandardStrategy } from '../standard.js';
7
+ import { resolveJvmWildcard, resolveJvmMemberImport, KOTLIN_EXTENSIONS } from '../jvm.js';
8
+ /** Java JVM resolution strategy — wildcard and member import resolution. */
9
+ export const javaJvmStrategy = (rawImportPath, _filePath, ctx) => {
10
+ if (rawImportPath.endsWith('.*')) {
11
+ const matchedFiles = resolveJvmWildcard(rawImportPath, ctx.normalizedFileList, ctx.allFileList, ['.java'], ctx.index);
12
+ if (matchedFiles.length > 0)
13
+ return { kind: 'files', files: matchedFiles };
14
+ }
15
+ else {
16
+ const memberResolved = resolveJvmMemberImport(rawImportPath, ctx.normalizedFileList, ctx.allFileList, ['.java'], ctx.index);
17
+ if (memberResolved)
18
+ return { kind: 'files', files: [memberResolved] };
19
+ }
20
+ return null;
21
+ };
22
+ /**
23
+ * Kotlin JVM resolution strategy — wildcard/member with Java-interop + top-level function imports.
24
+ */
25
+ export const kotlinJvmStrategy = (rawImportPath, _filePath, ctx) => {
26
+ if (rawImportPath.endsWith('.*')) {
27
+ const matchedFiles = resolveJvmWildcard(rawImportPath, ctx.normalizedFileList, ctx.allFileList, KOTLIN_EXTENSIONS, ctx.index);
28
+ if (matchedFiles.length === 0) {
29
+ const javaMatches = resolveJvmWildcard(rawImportPath, ctx.normalizedFileList, ctx.allFileList, ['.java'], ctx.index);
30
+ if (javaMatches.length > 0)
31
+ return { kind: 'files', files: javaMatches };
32
+ }
33
+ if (matchedFiles.length > 0)
34
+ return { kind: 'files', files: matchedFiles };
35
+ }
36
+ else {
37
+ let memberResolved = resolveJvmMemberImport(rawImportPath, ctx.normalizedFileList, ctx.allFileList, KOTLIN_EXTENSIONS, ctx.index);
38
+ if (!memberResolved) {
39
+ memberResolved = resolveJvmMemberImport(rawImportPath, ctx.normalizedFileList, ctx.allFileList, ['.java'], ctx.index);
40
+ }
41
+ if (memberResolved)
42
+ return { kind: 'files', files: [memberResolved] };
43
+ // Kotlin: top-level function imports (e.g. import models.getUser) have only 2 segments,
44
+ // which resolveJvmMemberImport skips (requires >=3). Fall back to package-directory scan
45
+ // for lowercase last segments (function/property imports). Uppercase last segments
46
+ // (class imports like models.User) fall through to standard suffix resolution.
47
+ const segments = rawImportPath.split('.');
48
+ const lastSeg = segments[segments.length - 1];
49
+ if (segments.length >= 2 && lastSeg[0] && lastSeg[0] === lastSeg[0].toLowerCase()) {
50
+ const pkgWildcard = segments.slice(0, -1).join('.') + '.*';
51
+ let dirFiles = resolveJvmWildcard(pkgWildcard, ctx.normalizedFileList, ctx.allFileList, KOTLIN_EXTENSIONS, ctx.index);
52
+ if (dirFiles.length === 0) {
53
+ dirFiles = resolveJvmWildcard(pkgWildcard, ctx.normalizedFileList, ctx.allFileList, ['.java'], ctx.index);
54
+ }
55
+ if (dirFiles.length > 0)
56
+ return { kind: 'files', files: dirFiles };
57
+ }
58
+ }
59
+ return null;
60
+ };
61
+ export const javaImportConfig = {
62
+ language: SupportedLanguages.Java,
63
+ strategies: [javaJvmStrategy, createStandardStrategy(SupportedLanguages.Java)],
64
+ };
65
+ export const kotlinImportConfig = {
66
+ language: SupportedLanguages.Kotlin,
67
+ strategies: [kotlinJvmStrategy, createStandardStrategy(SupportedLanguages.Kotlin)],
68
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * PHP import resolution config.
3
+ * PSR-4 strategy via composer.json — no standard fallback (PSR-4 includes its own suffix matching).
4
+ */
5
+ import type { ImportResolutionConfig, ImportResolverStrategy } from '../types.js';
6
+ /** PHP PSR-4 resolution strategy via composer.json autoload mappings. */
7
+ export declare const phpPsr4Strategy: ImportResolverStrategy;
8
+ export declare const phpImportConfig: ImportResolutionConfig;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * PHP import resolution config.
3
+ * PSR-4 strategy via composer.json — no standard fallback (PSR-4 includes its own suffix matching).
4
+ */
5
+ import { SupportedLanguages } from '../../../../_shared/index.js';
6
+ import { resolvePhpImportInternal } from '../php.js';
7
+ /** PHP PSR-4 resolution strategy via composer.json autoload mappings. */
8
+ export const phpPsr4Strategy = (rawImportPath, _filePath, ctx) => {
9
+ const resolved = resolvePhpImportInternal(rawImportPath, ctx.configs.composerConfig, ctx.allFilePaths, ctx.normalizedFileList, ctx.allFileList, ctx.index);
10
+ return resolved ? { kind: 'files', files: [resolved] } : null;
11
+ };
12
+ export const phpImportConfig = {
13
+ language: SupportedLanguages.PHP,
14
+ strategies: [phpPsr4Strategy],
15
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Python import resolution config.
3
+ * PEP 328 relative + proximity-based strategy, then standard fallback.
4
+ */
5
+ import type { ImportResolutionConfig, ImportResolverStrategy } from '../types.js';
6
+ /**
7
+ * Python import resolution strategy — PEP 328 relative + proximity-based bare imports.
8
+ * Returns null to continue chain for non-relative imports.
9
+ * Absorbs unresolved relative imports (returns empty result to stop the chain).
10
+ */
11
+ export declare const pythonImportStrategy: ImportResolverStrategy;
12
+ export declare const pythonImportConfig: ImportResolutionConfig;