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
@@ -9,7 +9,7 @@
9
9
  * DESIGN: Returns null for unknown frameworks, which causes a 1.0 multiplier
10
10
  * (no bonus, no penalty) - same behavior as before this feature.
11
11
  */
12
- import { SupportedLanguages } from '../../config/supported-languages.js';
12
+ import { SupportedLanguages } from 'gitnexus-shared';
13
13
  // ============================================================================
14
14
  // PATH-BASED FRAMEWORK DETECTION
15
15
  // ============================================================================
@@ -33,20 +33,27 @@ export function detectFrameworkFromPath(filePath) {
33
33
  }
34
34
  }
35
35
  // Next.js - App Router (page.tsx files)
36
- if (p.includes('/app/') && (p.endsWith('page.tsx') || p.endsWith('page.ts') ||
37
- p.endsWith('page.jsx') || p.endsWith('page.js'))) {
36
+ if (p.includes('/app/') &&
37
+ (p.endsWith('page.tsx') ||
38
+ p.endsWith('page.ts') ||
39
+ p.endsWith('page.jsx') ||
40
+ p.endsWith('page.js'))) {
38
41
  return { framework: 'nextjs-app', entryPointMultiplier: 3.0, reason: 'nextjs-app-page' };
39
42
  }
40
43
  // Next.js - API Routes
41
- if (p.includes('/pages/api/') || (p.includes('/app/') && p.includes('/api/') && p.endsWith('route.ts'))) {
44
+ if (p.includes('/pages/api/') ||
45
+ (p.includes('/app/') && p.includes('/api/') && p.endsWith('route.ts'))) {
42
46
  return { framework: 'nextjs-api', entryPointMultiplier: 3.0, reason: 'nextjs-api-route' };
43
47
  }
44
48
  // Next.js - Layout files (moderate - they're entry-ish but not the main entry)
45
- if (p.includes('/app/') && !p.includes('_layout') && (p.endsWith('layout.tsx') || p.endsWith('layout.ts'))) {
49
+ if (p.includes('/app/') &&
50
+ !p.includes('_layout') &&
51
+ (p.endsWith('layout.tsx') || p.endsWith('layout.ts'))) {
46
52
  return { framework: 'nextjs-app', entryPointMultiplier: 2.0, reason: 'nextjs-layout' };
47
53
  }
48
54
  // Expo Router - screen/layout/api files in app/ directory
49
- if (p.includes('/app/') && (p.endsWith('.tsx') || p.endsWith('.ts') || p.endsWith('.jsx') || p.endsWith('.js'))) {
55
+ if (p.includes('/app/') &&
56
+ (p.endsWith('.tsx') || p.endsWith('.ts') || p.endsWith('.jsx') || p.endsWith('.js'))) {
50
57
  const fn = p.split('/').pop() || '';
51
58
  if (fn.startsWith('_layout')) {
52
59
  return { framework: 'expo-router', entryPointMultiplier: 2.0, reason: 'expo-layout' };
@@ -123,11 +130,19 @@ export function detectFrameworkFromPath(filePath) {
123
130
  // ========== KOTLIN FRAMEWORKS ==========
124
131
  // Spring Boot Kotlin controllers
125
132
  if ((p.includes('/controller/') || p.includes('/controllers/')) && p.endsWith('.kt')) {
126
- return { framework: 'spring-kotlin', entryPointMultiplier: 3.0, reason: 'spring-kotlin-controller' };
133
+ return {
134
+ framework: 'spring-kotlin',
135
+ entryPointMultiplier: 3.0,
136
+ reason: 'spring-kotlin-controller',
137
+ };
127
138
  }
128
139
  // Spring Boot - files ending in Controller.kt
129
140
  if (p.endsWith('controller.kt')) {
130
- return { framework: 'spring-kotlin', entryPointMultiplier: 3.0, reason: 'spring-kotlin-controller-file' };
141
+ return {
142
+ framework: 'spring-kotlin',
143
+ entryPointMultiplier: 3.0,
144
+ reason: 'spring-kotlin-controller-file',
145
+ };
131
146
  }
132
147
  // Ktor routes
133
148
  if (p.includes('/routes/') && p.endsWith('.kt')) {
@@ -227,7 +242,7 @@ export function detectFrameworkFromPath(filePath) {
227
242
  return { framework: 'c-cpp', entryPointMultiplier: 3.0, reason: 'c-main' };
228
243
  }
229
244
  // C/C++ src folder entry points (if named specifically)
230
- if ((p.includes('/src/') && (p.endsWith('/app.c') || p.endsWith('/app.cpp')))) {
245
+ if (p.includes('/src/') && (p.endsWith('/app.c') || p.endsWith('/app.cpp'))) {
231
246
  return { framework: 'c-cpp', entryPointMultiplier: 2.5, reason: 'c-app' };
232
247
  }
233
248
  // ========== PHP / LARAVEL FRAMEWORKS ==========
@@ -290,7 +305,9 @@ export function detectFrameworkFromPath(filePath) {
290
305
  }
291
306
  // ========== SWIFT / iOS ==========
292
307
  // iOS App entry points (highest priority)
293
- if (p.endsWith('/appdelegate.swift') || p.endsWith('/scenedelegate.swift') || p.endsWith('/app.swift')) {
308
+ if (p.endsWith('/appdelegate.swift') ||
309
+ p.endsWith('/scenedelegate.swift') ||
310
+ p.endsWith('/app.swift')) {
294
311
  return { framework: 'ios', entryPointMultiplier: 3.0, reason: 'ios-app-entry' };
295
312
  }
296
313
  // SwiftUI App entry (@main)
@@ -298,7 +315,8 @@ export function detectFrameworkFromPath(filePath) {
298
315
  return { framework: 'swiftui', entryPointMultiplier: 3.0, reason: 'swiftui-app' };
299
316
  }
300
317
  // UIKit ViewControllers (high priority - screen entry points)
301
- if ((p.includes('/viewcontrollers/') || p.includes('/controllers/') || p.includes('/screens/')) && p.endsWith('.swift')) {
318
+ if ((p.includes('/viewcontrollers/') || p.includes('/controllers/') || p.includes('/screens/')) &&
319
+ p.endsWith('.swift')) {
302
320
  return { framework: 'uikit', entryPointMultiplier: 2.5, reason: 'uikit-viewcontroller' };
303
321
  }
304
322
  // ViewController by filename convention
@@ -311,7 +329,11 @@ export function detectFrameworkFromPath(filePath) {
311
329
  }
312
330
  // Coordinator by filename
313
331
  if (p.endsWith('coordinator.swift')) {
314
- return { framework: 'ios-coordinator', entryPointMultiplier: 2.5, reason: 'ios-coordinator-file' };
332
+ return {
333
+ framework: 'ios-coordinator',
334
+ entryPointMultiplier: 2.5,
335
+ reason: 'ios-coordinator-file',
336
+ };
315
337
  }
316
338
  // SwiftUI Views (moderate - reusable components)
317
339
  if ((p.includes('/views/') || p.includes('/scenes/')) && p.endsWith('.swift')) {
@@ -331,7 +353,8 @@ export function detectFrameworkFromPath(filePath) {
331
353
  return { framework: 'flutter', entryPointMultiplier: 3.0, reason: 'flutter-main' };
332
354
  }
333
355
  // Flutter screens/pages/views (high priority - route entry points)
334
- if ((p.includes('/screens/') || p.includes('/pages/') || p.includes('/views/')) && p.endsWith('.dart')) {
356
+ if ((p.includes('/screens/') || p.includes('/pages/') || p.includes('/views/')) &&
357
+ p.endsWith('.dart')) {
335
358
  return { framework: 'flutter', entryPointMultiplier: 2.5, reason: 'flutter-screen' };
336
359
  }
337
360
  // Flutter routes
@@ -339,7 +362,11 @@ export function detectFrameworkFromPath(filePath) {
339
362
  return { framework: 'flutter', entryPointMultiplier: 2.5, reason: 'flutter-routes' };
340
363
  }
341
364
  // Flutter BLoC / controllers / presentation (state management entry points)
342
- if ((p.includes('/bloc/') || p.includes('/controllers/') || p.includes('/cubit/') || p.includes('/presentation/')) && p.endsWith('.dart')) {
365
+ if ((p.includes('/bloc/') ||
366
+ p.includes('/controllers/') ||
367
+ p.includes('/cubit/') ||
368
+ p.includes('/presentation/')) &&
369
+ p.endsWith('.dart')) {
343
370
  return { framework: 'flutter', entryPointMultiplier: 2.0, reason: 'flutter-state-management' };
344
371
  }
345
372
  // Flutter services / domain
@@ -352,8 +379,8 @@ export function detectFrameworkFromPath(filePath) {
352
379
  }
353
380
  // ========== GENERIC PATTERNS ==========
354
381
  // Any language: index files in API folders
355
- if (p.includes('/api/') && (p.endsWith('/index.ts') || p.endsWith('/index.js') ||
356
- p.endsWith('/__init__.py'))) {
382
+ if (p.includes('/api/') &&
383
+ (p.endsWith('/index.ts') || p.endsWith('/index.js') || p.endsWith('/__init__.py'))) {
357
384
  return { framework: 'api', entryPointMultiplier: 1.8, reason: 'api-index' };
358
385
  }
359
386
  // No framework detected - return null for graceful fallback (1.0 multiplier)
@@ -368,121 +395,364 @@ export function detectFrameworkFromPath(filePath) {
368
395
  */
369
396
  export const FRAMEWORK_AST_PATTERNS = {
370
397
  // JavaScript/TypeScript decorators
371
- 'nestjs': ['@Controller', '@Get', '@Post', '@Put', '@Delete', '@Patch'],
372
- 'expo-router': ['router.push', 'router.replace', 'router.navigate', 'useRouter', 'useLocalSearchParams', 'useSegments', 'expo-router'],
373
- 'express': ['app.get', 'app.post', 'app.put', 'app.delete', 'router.get', 'router.post'],
398
+ nestjs: ['@Controller', '@Get', '@Post', '@Put', '@Delete', '@Patch'],
399
+ 'expo-router': [
400
+ 'router.push',
401
+ 'router.replace',
402
+ 'router.navigate',
403
+ 'useRouter',
404
+ 'useLocalSearchParams',
405
+ 'useSegments',
406
+ 'expo-router',
407
+ ],
408
+ express: ['app.get', 'app.post', 'app.put', 'app.delete', 'router.get', 'router.post'],
374
409
  // Python decorators
375
- 'fastapi': ['@app.get', '@app.post', '@app.put', '@app.delete', '@router.get'],
376
- 'flask': ['@app.route', '@blueprint.route'],
410
+ fastapi: ['@app.get', '@app.post', '@app.put', '@app.delete', '@router.get'],
411
+ flask: ['@app.route', '@blueprint.route'],
377
412
  // Java annotations
378
- 'spring': ['@RestController', '@Controller', '@GetMapping', '@PostMapping', '@RequestMapping'],
379
- 'jaxrs': ['@Path', '@GET', '@POST', '@PUT', '@DELETE'],
413
+ spring: ['@RestController', '@Controller', '@GetMapping', '@PostMapping', '@RequestMapping'],
414
+ jaxrs: ['@Path', '@GET', '@POST', '@PUT', '@DELETE'],
380
415
  // C# attributes
381
- 'aspnet': ['[ApiController]', '[HttpGet]', '[HttpPost]', '[HttpPut]', '[HttpDelete]',
382
- '[Route]', '[Authorize]', '[AllowAnonymous]'],
383
- 'signalr': ['[HubMethodName]', ': Hub', ': Hub<'],
384
- 'blazor': ['@page', '[Parameter]', '@inject'],
385
- 'efcore': ['DbContext', 'DbSet<', 'OnModelCreating'],
416
+ aspnet: [
417
+ '[ApiController]',
418
+ '[HttpGet]',
419
+ '[HttpPost]',
420
+ '[HttpPut]',
421
+ '[HttpDelete]',
422
+ '[Route]',
423
+ '[Authorize]',
424
+ '[AllowAnonymous]',
425
+ ],
426
+ signalr: ['[HubMethodName]', ': Hub', ': Hub<'],
427
+ blazor: ['@page', '[Parameter]', '@inject'],
428
+ efcore: ['DbContext', 'DbSet<', 'OnModelCreating'],
386
429
  // Go patterns (function signatures include framework types)
387
- 'go-http': ['http.Handler', 'http.HandlerFunc', 'ServeHTTP', 'http.ResponseWriter', 'http.Request'],
388
- 'gin': ['gin.Context', 'gin.Default', 'gin.New'],
389
- 'echo': ['echo.Context', 'echo.New'],
390
- 'fiber': ['fiber.Ctx', 'fiber.New', 'fiber.App'],
430
+ 'go-http': [
431
+ 'http.Handler',
432
+ 'http.HandlerFunc',
433
+ 'ServeHTTP',
434
+ 'http.ResponseWriter',
435
+ 'http.Request',
436
+ ],
437
+ gin: ['gin.Context', 'gin.Default', 'gin.New'],
438
+ echo: ['echo.Context', 'echo.New'],
439
+ fiber: ['fiber.Ctx', 'fiber.New', 'fiber.App'],
391
440
  'go-grpc': ['grpc.Server', 'RegisterServer', 'pb.Unimplemented'],
392
441
  // ORM patterns
393
- 'prisma': ['prisma.', 'PrismaClient', '@prisma/client'],
394
- 'supabase': ['supabase.from', 'createClient', '@supabase/supabase-js'],
442
+ prisma: ['prisma.', 'PrismaClient', '@prisma/client'],
443
+ supabase: ['supabase.from', 'createClient', '@supabase/supabase-js'],
395
444
  // PHP/Laravel
396
- 'laravel': ['Route::get', 'Route::post', 'Route::put', 'Route::delete',
397
- 'Route::resource', 'Route::apiResource', '#[Route('],
445
+ laravel: [
446
+ 'Route::get',
447
+ 'Route::post',
448
+ 'Route::put',
449
+ 'Route::delete',
450
+ 'Route::resource',
451
+ 'Route::apiResource',
452
+ '#[Route(',
453
+ ],
398
454
  // Rust macros (proc-macro attributes in definition text)
399
- 'actix': ['#[get', '#[post', '#[put', '#[delete', '#[actix_web', 'HttpRequest', 'HttpResponse'],
400
- 'axum': ['Router::new', 'axum::extract', 'axum::routing'],
401
- 'rocket': ['#[get', '#[post', '#[launch', 'rocket::'],
402
- 'tokio': ['#[tokio::main]', '#[tokio::test]'],
455
+ actix: ['#[get', '#[post', '#[put', '#[delete', '#[actix_web', 'HttpRequest', 'HttpResponse'],
456
+ axum: ['Router::new', 'axum::extract', 'axum::routing'],
457
+ rocket: ['#[get', '#[post', '#[launch', 'rocket::'],
458
+ tokio: ['#[tokio::main]', '#[tokio::test]'],
403
459
  // C++ patterns (Qt, Boost)
404
- 'qt': ['Q_OBJECT', 'Q_INVOKABLE', 'Q_PROPERTY', 'Q_SIGNALS', 'Q_SLOTS', 'Q_SIGNAL', 'Q_SLOT', 'QWidget', 'QApplication'],
460
+ qt: [
461
+ 'Q_OBJECT',
462
+ 'Q_INVOKABLE',
463
+ 'Q_PROPERTY',
464
+ 'Q_SIGNALS',
465
+ 'Q_SLOTS',
466
+ 'Q_SIGNAL',
467
+ 'Q_SLOT',
468
+ 'QWidget',
469
+ 'QApplication',
470
+ ],
405
471
  // Swift/iOS
406
- 'uikit': ['viewDidLoad', 'viewWillAppear', 'viewDidAppear', 'UIViewController', '@IBOutlet', '@IBAction', '@objc'],
407
- 'swiftui': ['@main', 'WindowGroup', 'ContentView', '@StateObject', '@ObservedObject', '@EnvironmentObject', '@Published'],
408
- 'vapor': ['app.get', 'app.post', 'req.content.decode', 'Vapor'],
472
+ uikit: [
473
+ 'viewDidLoad',
474
+ 'viewWillAppear',
475
+ 'viewDidAppear',
476
+ 'UIViewController',
477
+ '@IBOutlet',
478
+ '@IBAction',
479
+ '@objc',
480
+ ],
481
+ swiftui: [
482
+ '@main',
483
+ 'WindowGroup',
484
+ 'ContentView',
485
+ '@StateObject',
486
+ '@ObservedObject',
487
+ '@EnvironmentObject',
488
+ '@Published',
489
+ ],
490
+ vapor: ['app.get', 'app.post', 'req.content.decode', 'Vapor'],
409
491
  // Ruby patterns (class-level macros in definition text)
410
- 'rails': ['ApplicationController', 'ApplicationRecord', 'ActiveRecord::Base',
411
- 'before_action', 'after_action', 'has_many', 'belongs_to', 'has_one', 'validates'],
412
- 'sinatra': ['Sinatra::Base', 'Sinatra::Application'],
492
+ rails: [
493
+ 'ApplicationController',
494
+ 'ApplicationRecord',
495
+ 'ActiveRecord::Base',
496
+ 'before_action',
497
+ 'after_action',
498
+ 'has_many',
499
+ 'belongs_to',
500
+ 'has_one',
501
+ 'validates',
502
+ ],
503
+ sinatra: ['Sinatra::Base', 'Sinatra::Application'],
413
504
  // Dart/Flutter
414
- 'flutter': ['StatelessWidget', 'StatefulWidget', 'BuildContext', 'Widget build',
415
- 'ChangeNotifier', 'GetxController', 'Cubit<', 'Bloc<', 'ConsumerWidget'],
416
- 'riverpod': ['@riverpod', 'ref.watch', 'ref.read', 'AsyncNotifier', 'Notifier'],
505
+ flutter: [
506
+ 'StatelessWidget',
507
+ 'StatefulWidget',
508
+ 'BuildContext',
509
+ 'Widget build',
510
+ 'ChangeNotifier',
511
+ 'GetxController',
512
+ 'Cubit<',
513
+ 'Bloc<',
514
+ 'ConsumerWidget',
515
+ ],
516
+ riverpod: ['@riverpod', 'ref.watch', 'ref.read', 'AsyncNotifier', 'Notifier'],
417
517
  };
418
518
  export const AST_FRAMEWORK_PATTERNS_BY_LANGUAGE = {
419
519
  [SupportedLanguages.JavaScript]: [
420
- { framework: 'nestjs', entryPointMultiplier: 3.2, reason: 'nestjs-decorator', patterns: FRAMEWORK_AST_PATTERNS.nestjs },
421
- { framework: 'expo-router', entryPointMultiplier: 2.5, reason: 'expo-router-navigation', patterns: FRAMEWORK_AST_PATTERNS['expo-router'] },
520
+ {
521
+ framework: 'nestjs',
522
+ entryPointMultiplier: 3.2,
523
+ reason: 'nestjs-decorator',
524
+ patterns: FRAMEWORK_AST_PATTERNS.nestjs,
525
+ },
526
+ {
527
+ framework: 'expo-router',
528
+ entryPointMultiplier: 2.5,
529
+ reason: 'expo-router-navigation',
530
+ patterns: FRAMEWORK_AST_PATTERNS['expo-router'],
531
+ },
422
532
  ],
423
533
  [SupportedLanguages.TypeScript]: [
424
- { framework: 'nestjs', entryPointMultiplier: 3.2, reason: 'nestjs-decorator', patterns: FRAMEWORK_AST_PATTERNS.nestjs },
425
- { framework: 'expo-router', entryPointMultiplier: 2.5, reason: 'expo-router-navigation', patterns: FRAMEWORK_AST_PATTERNS['expo-router'] },
534
+ {
535
+ framework: 'nestjs',
536
+ entryPointMultiplier: 3.2,
537
+ reason: 'nestjs-decorator',
538
+ patterns: FRAMEWORK_AST_PATTERNS.nestjs,
539
+ },
540
+ {
541
+ framework: 'expo-router',
542
+ entryPointMultiplier: 2.5,
543
+ reason: 'expo-router-navigation',
544
+ patterns: FRAMEWORK_AST_PATTERNS['expo-router'],
545
+ },
426
546
  ],
427
547
  [SupportedLanguages.Python]: [
428
- { framework: 'fastapi', entryPointMultiplier: 3.0, reason: 'fastapi-decorator', patterns: FRAMEWORK_AST_PATTERNS.fastapi },
429
- { framework: 'flask', entryPointMultiplier: 2.8, reason: 'flask-decorator', patterns: FRAMEWORK_AST_PATTERNS.flask },
548
+ {
549
+ framework: 'fastapi',
550
+ entryPointMultiplier: 3.0,
551
+ reason: 'fastapi-decorator',
552
+ patterns: FRAMEWORK_AST_PATTERNS.fastapi,
553
+ },
554
+ {
555
+ framework: 'flask',
556
+ entryPointMultiplier: 2.8,
557
+ reason: 'flask-decorator',
558
+ patterns: FRAMEWORK_AST_PATTERNS.flask,
559
+ },
430
560
  ],
431
561
  [SupportedLanguages.Java]: [
432
- { framework: 'spring', entryPointMultiplier: 3.2, reason: 'spring-annotation', patterns: FRAMEWORK_AST_PATTERNS.spring },
433
- { framework: 'jaxrs', entryPointMultiplier: 3.0, reason: 'jaxrs-annotation', patterns: FRAMEWORK_AST_PATTERNS.jaxrs },
562
+ {
563
+ framework: 'spring',
564
+ entryPointMultiplier: 3.2,
565
+ reason: 'spring-annotation',
566
+ patterns: FRAMEWORK_AST_PATTERNS.spring,
567
+ },
568
+ {
569
+ framework: 'jaxrs',
570
+ entryPointMultiplier: 3.0,
571
+ reason: 'jaxrs-annotation',
572
+ patterns: FRAMEWORK_AST_PATTERNS.jaxrs,
573
+ },
434
574
  ],
435
575
  [SupportedLanguages.Kotlin]: [
436
- { framework: 'spring-kotlin', entryPointMultiplier: 3.2, reason: 'spring-kotlin-annotation', patterns: FRAMEWORK_AST_PATTERNS.spring },
437
- { framework: 'jaxrs', entryPointMultiplier: 3.0, reason: 'jaxrs-annotation', patterns: FRAMEWORK_AST_PATTERNS.jaxrs },
438
- { framework: 'ktor', entryPointMultiplier: 2.8, reason: 'ktor-routing', patterns: ['routing', 'embeddedServer', 'Application.module'] },
439
- { framework: 'android-kotlin', entryPointMultiplier: 2.5, reason: 'android-annotation', patterns: ['@AndroidEntryPoint', 'AppCompatActivity', 'Fragment('] },
576
+ {
577
+ framework: 'spring-kotlin',
578
+ entryPointMultiplier: 3.2,
579
+ reason: 'spring-kotlin-annotation',
580
+ patterns: FRAMEWORK_AST_PATTERNS.spring,
581
+ },
582
+ {
583
+ framework: 'jaxrs',
584
+ entryPointMultiplier: 3.0,
585
+ reason: 'jaxrs-annotation',
586
+ patterns: FRAMEWORK_AST_PATTERNS.jaxrs,
587
+ },
588
+ {
589
+ framework: 'ktor',
590
+ entryPointMultiplier: 2.8,
591
+ reason: 'ktor-routing',
592
+ patterns: ['routing', 'embeddedServer', 'Application.module'],
593
+ },
594
+ {
595
+ framework: 'android-kotlin',
596
+ entryPointMultiplier: 2.5,
597
+ reason: 'android-annotation',
598
+ patterns: ['@AndroidEntryPoint', 'AppCompatActivity', 'Fragment('],
599
+ },
440
600
  ],
441
601
  [SupportedLanguages.CSharp]: [
442
- { framework: 'aspnet', entryPointMultiplier: 3.2, reason: 'aspnet-attribute', patterns: FRAMEWORK_AST_PATTERNS.aspnet },
443
- { framework: 'signalr', entryPointMultiplier: 2.8, reason: 'signalr-attribute', patterns: FRAMEWORK_AST_PATTERNS.signalr },
444
- { framework: 'blazor', entryPointMultiplier: 2.5, reason: 'blazor-attribute', patterns: FRAMEWORK_AST_PATTERNS.blazor },
445
- { framework: 'efcore', entryPointMultiplier: 2.0, reason: 'efcore-pattern', patterns: FRAMEWORK_AST_PATTERNS.efcore },
602
+ {
603
+ framework: 'aspnet',
604
+ entryPointMultiplier: 3.2,
605
+ reason: 'aspnet-attribute',
606
+ patterns: FRAMEWORK_AST_PATTERNS.aspnet,
607
+ },
608
+ {
609
+ framework: 'signalr',
610
+ entryPointMultiplier: 2.8,
611
+ reason: 'signalr-attribute',
612
+ patterns: FRAMEWORK_AST_PATTERNS.signalr,
613
+ },
614
+ {
615
+ framework: 'blazor',
616
+ entryPointMultiplier: 2.5,
617
+ reason: 'blazor-attribute',
618
+ patterns: FRAMEWORK_AST_PATTERNS.blazor,
619
+ },
620
+ {
621
+ framework: 'efcore',
622
+ entryPointMultiplier: 2.0,
623
+ reason: 'efcore-pattern',
624
+ patterns: FRAMEWORK_AST_PATTERNS.efcore,
625
+ },
446
626
  ],
447
627
  [SupportedLanguages.PHP]: [
448
- { framework: 'laravel', entryPointMultiplier: 3.0, reason: 'php-route-attribute', patterns: FRAMEWORK_AST_PATTERNS.laravel },
628
+ {
629
+ framework: 'laravel',
630
+ entryPointMultiplier: 3.0,
631
+ reason: 'php-route-attribute',
632
+ patterns: FRAMEWORK_AST_PATTERNS.laravel,
633
+ },
449
634
  ],
450
635
  [SupportedLanguages.Go]: [
451
- { framework: 'go-http', entryPointMultiplier: 2.5, reason: 'go-http-handler', patterns: FRAMEWORK_AST_PATTERNS['go-http'] },
452
- { framework: 'gin', entryPointMultiplier: 3.0, reason: 'gin-handler', patterns: FRAMEWORK_AST_PATTERNS.gin },
453
- { framework: 'echo', entryPointMultiplier: 3.0, reason: 'echo-handler', patterns: FRAMEWORK_AST_PATTERNS.echo },
454
- { framework: 'fiber', entryPointMultiplier: 3.0, reason: 'fiber-handler', patterns: FRAMEWORK_AST_PATTERNS.fiber },
455
- { framework: 'go-grpc', entryPointMultiplier: 2.8, reason: 'grpc-service', patterns: FRAMEWORK_AST_PATTERNS['go-grpc'] },
636
+ {
637
+ framework: 'go-http',
638
+ entryPointMultiplier: 2.5,
639
+ reason: 'go-http-handler',
640
+ patterns: FRAMEWORK_AST_PATTERNS['go-http'],
641
+ },
642
+ {
643
+ framework: 'gin',
644
+ entryPointMultiplier: 3.0,
645
+ reason: 'gin-handler',
646
+ patterns: FRAMEWORK_AST_PATTERNS.gin,
647
+ },
648
+ {
649
+ framework: 'echo',
650
+ entryPointMultiplier: 3.0,
651
+ reason: 'echo-handler',
652
+ patterns: FRAMEWORK_AST_PATTERNS.echo,
653
+ },
654
+ {
655
+ framework: 'fiber',
656
+ entryPointMultiplier: 3.0,
657
+ reason: 'fiber-handler',
658
+ patterns: FRAMEWORK_AST_PATTERNS.fiber,
659
+ },
660
+ {
661
+ framework: 'go-grpc',
662
+ entryPointMultiplier: 2.8,
663
+ reason: 'grpc-service',
664
+ patterns: FRAMEWORK_AST_PATTERNS['go-grpc'],
665
+ },
456
666
  ],
457
667
  [SupportedLanguages.Rust]: [
458
- { framework: 'actix-web', entryPointMultiplier: 3.0, reason: 'actix-attribute', patterns: FRAMEWORK_AST_PATTERNS.actix },
459
- { framework: 'axum', entryPointMultiplier: 3.0, reason: 'axum-routing', patterns: FRAMEWORK_AST_PATTERNS.axum },
460
- { framework: 'rocket', entryPointMultiplier: 3.0, reason: 'rocket-attribute', patterns: FRAMEWORK_AST_PATTERNS.rocket },
461
- { framework: 'tokio', entryPointMultiplier: 2.5, reason: 'tokio-runtime', patterns: FRAMEWORK_AST_PATTERNS.tokio },
668
+ {
669
+ framework: 'actix-web',
670
+ entryPointMultiplier: 3.0,
671
+ reason: 'actix-attribute',
672
+ patterns: FRAMEWORK_AST_PATTERNS.actix,
673
+ },
674
+ {
675
+ framework: 'axum',
676
+ entryPointMultiplier: 3.0,
677
+ reason: 'axum-routing',
678
+ patterns: FRAMEWORK_AST_PATTERNS.axum,
679
+ },
680
+ {
681
+ framework: 'rocket',
682
+ entryPointMultiplier: 3.0,
683
+ reason: 'rocket-attribute',
684
+ patterns: FRAMEWORK_AST_PATTERNS.rocket,
685
+ },
686
+ {
687
+ framework: 'tokio',
688
+ entryPointMultiplier: 2.5,
689
+ reason: 'tokio-runtime',
690
+ patterns: FRAMEWORK_AST_PATTERNS.tokio,
691
+ },
462
692
  ],
463
693
  [SupportedLanguages.C]: [], // C has no framework-specific AST patterns (POSIX/socket patterns are in entry-point-scoring)
464
694
  [SupportedLanguages.CPlusPlus]: [
465
- { framework: 'qt', entryPointMultiplier: 2.8, reason: 'qt-macro', patterns: FRAMEWORK_AST_PATTERNS.qt },
695
+ {
696
+ framework: 'qt',
697
+ entryPointMultiplier: 2.8,
698
+ reason: 'qt-macro',
699
+ patterns: FRAMEWORK_AST_PATTERNS.qt,
700
+ },
466
701
  ],
467
702
  [SupportedLanguages.Swift]: [
468
- { framework: 'uikit', entryPointMultiplier: 2.5, reason: 'uikit-lifecycle', patterns: FRAMEWORK_AST_PATTERNS.uikit },
469
- { framework: 'swiftui', entryPointMultiplier: 2.8, reason: 'swiftui-pattern', patterns: FRAMEWORK_AST_PATTERNS.swiftui },
470
- { framework: 'vapor', entryPointMultiplier: 3.0, reason: 'vapor-routing', patterns: FRAMEWORK_AST_PATTERNS.vapor },
703
+ {
704
+ framework: 'uikit',
705
+ entryPointMultiplier: 2.5,
706
+ reason: 'uikit-lifecycle',
707
+ patterns: FRAMEWORK_AST_PATTERNS.uikit,
708
+ },
709
+ {
710
+ framework: 'swiftui',
711
+ entryPointMultiplier: 2.8,
712
+ reason: 'swiftui-pattern',
713
+ patterns: FRAMEWORK_AST_PATTERNS.swiftui,
714
+ },
715
+ {
716
+ framework: 'vapor',
717
+ entryPointMultiplier: 3.0,
718
+ reason: 'vapor-routing',
719
+ patterns: FRAMEWORK_AST_PATTERNS.vapor,
720
+ },
471
721
  ],
472
722
  [SupportedLanguages.Ruby]: [
473
- { framework: 'rails', entryPointMultiplier: 3.0, reason: 'rails-pattern', patterns: FRAMEWORK_AST_PATTERNS.rails },
474
- { framework: 'sinatra', entryPointMultiplier: 2.8, reason: 'sinatra-pattern', patterns: FRAMEWORK_AST_PATTERNS.sinatra },
723
+ {
724
+ framework: 'rails',
725
+ entryPointMultiplier: 3.0,
726
+ reason: 'rails-pattern',
727
+ patterns: FRAMEWORK_AST_PATTERNS.rails,
728
+ },
729
+ {
730
+ framework: 'sinatra',
731
+ entryPointMultiplier: 2.8,
732
+ reason: 'sinatra-pattern',
733
+ patterns: FRAMEWORK_AST_PATTERNS.sinatra,
734
+ },
475
735
  ],
476
736
  [SupportedLanguages.Dart]: [
477
- { framework: 'flutter', entryPointMultiplier: 2.5, reason: 'flutter-widget', patterns: FRAMEWORK_AST_PATTERNS.flutter },
478
- { framework: 'riverpod', entryPointMultiplier: 2.8, reason: 'riverpod-pattern', patterns: FRAMEWORK_AST_PATTERNS.riverpod },
737
+ {
738
+ framework: 'flutter',
739
+ entryPointMultiplier: 2.5,
740
+ reason: 'flutter-widget',
741
+ patterns: FRAMEWORK_AST_PATTERNS.flutter,
742
+ },
743
+ {
744
+ framework: 'riverpod',
745
+ entryPointMultiplier: 2.8,
746
+ reason: 'riverpod-pattern',
747
+ patterns: FRAMEWORK_AST_PATTERNS.riverpod,
748
+ },
479
749
  ],
480
750
  [SupportedLanguages.Cobol]: [], // Standalone regex processor — no AST framework patterns
481
751
  };
482
752
  /** Pre-lowercased patterns for O(1) pattern matching at runtime */
483
753
  const AST_PATTERNS_LOWERED = Object.fromEntries(Object.entries(AST_FRAMEWORK_PATTERNS_BY_LANGUAGE).map(([lang, cfgs]) => [
484
754
  lang,
485
- cfgs.map(cfg => ({ ...cfg, patterns: cfg.patterns.map(p => p.toLowerCase()) })),
755
+ cfgs.map((cfg) => ({ ...cfg, patterns: cfg.patterns.map((p) => p.toLowerCase()) })),
486
756
  ]));
487
757
  /**
488
758
  * Detect framework entry points from AST definition text (decorators/annotations/attributes).
@@ -15,8 +15,22 @@
15
15
  */
16
16
  import { KnowledgeGraph } from '../graph/types.js';
17
17
  import { ASTCache } from './ast-cache.js';
18
+ import { SupportedLanguages } from 'gitnexus-shared';
18
19
  import type { ExtractedHeritage } from './workers/parse-worker.js';
19
20
  import type { ResolutionContext } from './resolution-context.js';
21
+ /**
22
+ * Determine whether a heritage.extends capture is actually an IMPLEMENTS relationship.
23
+ * Uses the symbol table first (authoritative — Tier 1); falls back to provider-defined
24
+ * heuristics for external symbols not present in the graph:
25
+ * - interfaceNamePattern: matched against parent name (e.g., /^I[A-Z]/ for C#/Java)
26
+ * - heritageDefaultEdge: 'IMPLEMENTS' causes all unresolved parents to map to IMPLEMENTS
27
+ * - All others: default EXTENDS
28
+ */
29
+ /** Exported for implementor-map construction (C#/Java: `extends` rows in base_list may be interfaces). */
30
+ export declare const resolveExtendsType: (parentName: string, currentFilePath: string, ctx: ResolutionContext, language: SupportedLanguages) => {
31
+ type: "EXTENDS" | "IMPLEMENTS";
32
+ idPrefix: string;
33
+ };
20
34
  export declare const processHeritage: (graph: KnowledgeGraph, files: {
21
35
  path: string;
22
36
  content: string;
@@ -26,3 +40,13 @@ export declare const processHeritage: (graph: KnowledgeGraph, files: {
26
40
  * No AST parsing — workers already extracted className + parentName + kind.
27
41
  */
28
42
  export declare const processHeritageFromExtracted: (graph: KnowledgeGraph, extractedHeritage: ExtractedHeritage[], ctx: ResolutionContext, onProgress?: (current: number, total: number) => void) => Promise<void>;
43
+ /**
44
+ * Walk source files with the same heritage captures as parse-worker, producing
45
+ * {@link ExtractedHeritage} rows without mutating the graph. Used on the
46
+ * sequential pipeline path so `buildImplementorMap(..., ctx)` can run before
47
+ * `processCalls` (worker path defers calls until heritage from all chunks exists).
48
+ */
49
+ export declare function extractExtractedHeritageFromFiles(files: {
50
+ path: string;
51
+ content: string;
52
+ }[], astCache: ASTCache): Promise<ExtractedHeritage[]>;