gitnexus 1.4.0 → 1.4.1

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 (131) hide show
  1. package/README.md +194 -214
  2. package/dist/cli/ai-context.d.ts +1 -2
  3. package/dist/cli/ai-context.js +90 -117
  4. package/dist/cli/analyze.d.ts +0 -2
  5. package/dist/cli/analyze.js +2 -20
  6. package/dist/cli/index.js +25 -17
  7. package/dist/cli/setup.js +19 -17
  8. package/dist/core/augmentation/engine.js +20 -20
  9. package/dist/core/embeddings/embedding-pipeline.js +26 -26
  10. package/dist/core/graph/types.d.ts +2 -5
  11. package/dist/core/ingestion/ast-cache.js +2 -3
  12. package/dist/core/ingestion/call-processor.d.ts +5 -5
  13. package/dist/core/ingestion/call-processor.js +258 -173
  14. package/dist/core/ingestion/cluster-enricher.js +16 -16
  15. package/dist/core/ingestion/entry-point-scoring.d.ts +1 -2
  16. package/dist/core/ingestion/entry-point-scoring.js +22 -81
  17. package/dist/core/ingestion/framework-detection.d.ts +1 -5
  18. package/dist/core/ingestion/framework-detection.js +8 -39
  19. package/dist/core/ingestion/heritage-processor.d.ts +4 -13
  20. package/dist/core/ingestion/heritage-processor.js +28 -92
  21. package/dist/core/ingestion/import-processor.d.ts +19 -17
  22. package/dist/core/ingestion/import-processor.js +695 -170
  23. package/dist/core/ingestion/parsing-processor.d.ts +10 -1
  24. package/dist/core/ingestion/parsing-processor.js +177 -41
  25. package/dist/core/ingestion/pipeline.js +26 -49
  26. package/dist/core/ingestion/process-processor.js +1 -2
  27. package/dist/core/ingestion/symbol-table.d.ts +1 -12
  28. package/dist/core/ingestion/symbol-table.js +12 -19
  29. package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
  30. package/dist/core/ingestion/tree-sitter-queries.js +485 -590
  31. package/dist/core/ingestion/utils.d.ts +0 -67
  32. package/dist/core/ingestion/utils.js +9 -692
  33. package/dist/core/ingestion/workers/parse-worker.d.ts +3 -20
  34. package/dist/core/ingestion/workers/parse-worker.js +345 -84
  35. package/dist/core/ingestion/workers/worker-pool.js +0 -8
  36. package/dist/core/kuzu/csv-generator.js +3 -19
  37. package/dist/core/kuzu/kuzu-adapter.js +19 -14
  38. package/dist/core/kuzu/schema.d.ts +3 -3
  39. package/dist/core/kuzu/schema.js +288 -303
  40. package/dist/core/search/bm25-index.js +6 -7
  41. package/dist/core/search/hybrid-search.js +3 -3
  42. package/dist/core/wiki/diagrams.d.ts +27 -0
  43. package/dist/core/wiki/diagrams.js +163 -0
  44. package/dist/core/wiki/generator.d.ts +50 -2
  45. package/dist/core/wiki/generator.js +548 -49
  46. package/dist/core/wiki/graph-queries.d.ts +42 -0
  47. package/dist/core/wiki/graph-queries.js +276 -97
  48. package/dist/core/wiki/html-viewer.js +192 -192
  49. package/dist/core/wiki/llm-client.js +73 -11
  50. package/dist/core/wiki/prompts.d.ts +52 -8
  51. package/dist/core/wiki/prompts.js +200 -86
  52. package/dist/mcp/core/kuzu-adapter.d.ts +3 -1
  53. package/dist/mcp/core/kuzu-adapter.js +44 -13
  54. package/dist/mcp/local/local-backend.js +128 -128
  55. package/dist/mcp/resources.js +42 -42
  56. package/dist/mcp/server.js +19 -18
  57. package/dist/mcp/tools.js +104 -103
  58. package/hooks/claude/gitnexus-hook.cjs +155 -238
  59. package/hooks/claude/pre-tool-use.sh +79 -79
  60. package/hooks/claude/session-start.sh +42 -42
  61. package/package.json +96 -96
  62. package/scripts/patch-tree-sitter-swift.cjs +74 -74
  63. package/skills/gitnexus-cli.md +82 -82
  64. package/skills/gitnexus-debugging.md +89 -89
  65. package/skills/gitnexus-exploring.md +78 -78
  66. package/skills/gitnexus-guide.md +64 -64
  67. package/skills/gitnexus-impact-analysis.md +97 -97
  68. package/skills/gitnexus-pr-review.md +163 -163
  69. package/skills/gitnexus-refactoring.md +121 -121
  70. package/vendor/leiden/index.cjs +355 -355
  71. package/vendor/leiden/utils.cjs +392 -392
  72. package/dist/cli/lazy-action.d.ts +0 -6
  73. package/dist/cli/lazy-action.js +0 -18
  74. package/dist/cli/skill-gen.d.ts +0 -26
  75. package/dist/cli/skill-gen.js +0 -549
  76. package/dist/core/ingestion/constants.d.ts +0 -16
  77. package/dist/core/ingestion/constants.js +0 -16
  78. package/dist/core/ingestion/export-detection.d.ts +0 -18
  79. package/dist/core/ingestion/export-detection.js +0 -230
  80. package/dist/core/ingestion/language-config.d.ts +0 -46
  81. package/dist/core/ingestion/language-config.js +0 -167
  82. package/dist/core/ingestion/mro-processor.d.ts +0 -45
  83. package/dist/core/ingestion/mro-processor.js +0 -369
  84. package/dist/core/ingestion/named-binding-extraction.d.ts +0 -61
  85. package/dist/core/ingestion/named-binding-extraction.js +0 -363
  86. package/dist/core/ingestion/resolvers/csharp.d.ts +0 -22
  87. package/dist/core/ingestion/resolvers/csharp.js +0 -109
  88. package/dist/core/ingestion/resolvers/go.d.ts +0 -19
  89. package/dist/core/ingestion/resolvers/go.js +0 -42
  90. package/dist/core/ingestion/resolvers/index.d.ts +0 -16
  91. package/dist/core/ingestion/resolvers/index.js +0 -11
  92. package/dist/core/ingestion/resolvers/jvm.d.ts +0 -23
  93. package/dist/core/ingestion/resolvers/jvm.js +0 -87
  94. package/dist/core/ingestion/resolvers/php.d.ts +0 -15
  95. package/dist/core/ingestion/resolvers/php.js +0 -35
  96. package/dist/core/ingestion/resolvers/rust.d.ts +0 -15
  97. package/dist/core/ingestion/resolvers/rust.js +0 -73
  98. package/dist/core/ingestion/resolvers/standard.d.ts +0 -28
  99. package/dist/core/ingestion/resolvers/standard.js +0 -145
  100. package/dist/core/ingestion/resolvers/utils.d.ts +0 -33
  101. package/dist/core/ingestion/resolvers/utils.js +0 -120
  102. package/dist/core/ingestion/symbol-resolver.d.ts +0 -32
  103. package/dist/core/ingestion/symbol-resolver.js +0 -83
  104. package/dist/core/ingestion/type-env.d.ts +0 -27
  105. package/dist/core/ingestion/type-env.js +0 -86
  106. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +0 -2
  107. package/dist/core/ingestion/type-extractors/c-cpp.js +0 -60
  108. package/dist/core/ingestion/type-extractors/csharp.d.ts +0 -2
  109. package/dist/core/ingestion/type-extractors/csharp.js +0 -89
  110. package/dist/core/ingestion/type-extractors/go.d.ts +0 -2
  111. package/dist/core/ingestion/type-extractors/go.js +0 -105
  112. package/dist/core/ingestion/type-extractors/index.d.ts +0 -21
  113. package/dist/core/ingestion/type-extractors/index.js +0 -29
  114. package/dist/core/ingestion/type-extractors/jvm.d.ts +0 -3
  115. package/dist/core/ingestion/type-extractors/jvm.js +0 -121
  116. package/dist/core/ingestion/type-extractors/php.d.ts +0 -2
  117. package/dist/core/ingestion/type-extractors/php.js +0 -31
  118. package/dist/core/ingestion/type-extractors/python.d.ts +0 -2
  119. package/dist/core/ingestion/type-extractors/python.js +0 -41
  120. package/dist/core/ingestion/type-extractors/rust.d.ts +0 -2
  121. package/dist/core/ingestion/type-extractors/rust.js +0 -39
  122. package/dist/core/ingestion/type-extractors/shared.d.ts +0 -17
  123. package/dist/core/ingestion/type-extractors/shared.js +0 -97
  124. package/dist/core/ingestion/type-extractors/swift.d.ts +0 -2
  125. package/dist/core/ingestion/type-extractors/swift.js +0 -43
  126. package/dist/core/ingestion/type-extractors/types.d.ts +0 -14
  127. package/dist/core/ingestion/type-extractors/types.js +0 -1
  128. package/dist/core/ingestion/type-extractors/typescript.d.ts +0 -2
  129. package/dist/core/ingestion/type-extractors/typescript.js +0 -46
  130. package/dist/mcp/compatible-stdio-transport.d.ts +0 -25
  131. package/dist/mcp/compatible-stdio-transport.js +0 -200
@@ -10,7 +10,6 @@
10
10
  * This module is language-agnostic - language-specific patterns are defined per language.
11
11
  */
12
12
  import { detectFrameworkFromPath } from './framework-detection.js';
13
- import { SupportedLanguages } from '../../config/supported-languages.js';
14
13
  // ============================================================================
15
14
  // NAME PATTERNS - All 9 supported languages
16
15
  // ============================================================================
@@ -35,112 +34,65 @@ const ENTRY_POINT_PATTERNS = {
35
34
  /^emit[A-Z]/, // emitEvent
36
35
  ],
37
36
  // JavaScript/TypeScript
38
- [SupportedLanguages.JavaScript]: [
37
+ 'javascript': [
39
38
  /^use[A-Z]/, // React hooks (useEffect, etc.)
40
39
  ],
41
- [SupportedLanguages.TypeScript]: [
40
+ 'typescript': [
42
41
  /^use[A-Z]/, // React hooks
43
42
  ],
44
43
  // Python
45
- [SupportedLanguages.Python]: [
44
+ 'python': [
46
45
  /^app$/, // Flask/FastAPI app
47
46
  /^(get|post|put|delete|patch)_/i, // REST conventions
48
47
  /^api_/, // API functions
49
48
  /^view_/, // Django views
50
49
  ],
51
50
  // Java
52
- [SupportedLanguages.Java]: [
51
+ 'java': [
53
52
  /^do[A-Z]/, // doGet, doPost (Servlets)
54
53
  /^create[A-Z]/, // Factory patterns
55
54
  /^build[A-Z]/, // Builder patterns
56
55
  /Service$/, // UserService
57
56
  ],
58
57
  // C#
59
- [SupportedLanguages.CSharp]: [
60
- /^(Get|Post|Put|Delete|Patch)/, // ASP.NET action methods
58
+ 'csharp': [
59
+ /^(Get|Post|Put|Delete)/, // ASP.NET conventions
61
60
  /Action$/, // MVC actions
62
- /^On[A-Z]/, // Event handlers / Blazor lifecycle
61
+ /^On[A-Z]/, // Event handlers
63
62
  /Async$/, // Async entry points
64
- /^Configure$/, // Startup.Configure
65
- /^ConfigureServices$/, // Startup.ConfigureServices
66
- /^Handle$/, // MediatR / generic handler
67
- /^Execute$/, // Command pattern
68
- /^Invoke$/, // Middleware Invoke
69
- /^Map[A-Z]/, // Minimal API MapGet, MapPost
70
- /Service$/, // Service classes
71
- /^Seed/, // Database seeding
72
63
  ],
73
64
  // Go
74
- [SupportedLanguages.Go]: [
65
+ 'go': [
75
66
  /Handler$/, // http.Handler pattern
76
67
  /^Serve/, // ServeHTTP
77
68
  /^New[A-Z]/, // Constructor pattern (returns new instance)
78
69
  /^Make[A-Z]/, // Make functions
79
70
  ],
80
71
  // Rust
81
- [SupportedLanguages.Rust]: [
72
+ 'rust': [
82
73
  /^(get|post|put|delete)_handler$/i,
83
74
  /^handle_/, // handle_request
84
75
  /^new$/, // Constructor pattern
85
76
  /^run$/, // run entry point
86
77
  /^spawn/, // Async spawn
87
78
  ],
88
- // C - explicit main() boost plus common C entry point conventions
89
- [SupportedLanguages.C]: [
79
+ // C - explicit main() boost (critical for C programs)
80
+ 'c': [
90
81
  /^main$/, // THE entry point
91
- /^init_/, // init_server, init_client
92
- /_init$/, // module_init, server_init
93
- /^start_/, // start_server
94
- /_start$/, // thread_start
95
- /^run_/, // run_loop
96
- /_run$/, // event_run
97
- /^stop_/, // stop_server
98
- /_stop$/, // service_stop
99
- /^open_/, // open_connection
100
- /_open$/, // file_open
101
- /^close_/, // close_connection
102
- /_close$/, // socket_close
103
- /^create_/, // create_session
104
- /_create$/, // object_create
105
- /^destroy_/, // destroy_session
106
- /_destroy$/, // object_destroy
107
- /^handle_/, // handle_request
108
- /_handler$/, // signal_handler
109
- /_callback$/, // event_callback
110
- /^cmd_/, // tmux: cmd_new_window, cmd_attach_session
111
- /^server_/, // server_start, server_loop
112
- /^client_/, // client_connect
113
- /^session_/, // session_create
114
- /^window_/, // window_resize (tmux)
115
- /^key_/, // key_press
116
- /^input_/, // input_parse
117
- /^output_/, // output_write
118
- /^notify_/, // notify_client
119
- /^control_/, // control_start
82
+ /^init_/, // Initialization functions
83
+ /^start_/, // Start functions
84
+ /^run_/, // Run functions
120
85
  ],
121
- // C++ - same as C plus OOP/template patterns
122
- [SupportedLanguages.CPlusPlus]: [
86
+ // C++ - same as C plus class patterns
87
+ 'cpp': [
123
88
  /^main$/, // THE entry point
124
89
  /^init_/,
125
- /_init$/,
126
90
  /^Create[A-Z]/, // Factory patterns
127
- /^create_/,
128
91
  /^Run$/, // Run methods
129
- /^run$/,
130
92
  /^Start$/, // Start methods
131
- /^start$/,
132
- /^handle_/,
133
- /_handler$/,
134
- /_callback$/,
135
- /^OnEvent/, // Event callbacks
136
- /^on_/,
137
- /::Run$/, // Class::Run
138
- /::Start$/, // Class::Start
139
- /::Init$/, // Class::Init
140
- /::Execute$/, // Class::Execute
141
93
  ],
142
94
  // Swift / iOS
143
- [SupportedLanguages.Swift]: [
95
+ 'swift': [
144
96
  /^viewDidLoad$/, // UIKit lifecycle
145
97
  /^viewWillAppear$/, // UIKit lifecycle
146
98
  /^viewDidAppear$/, // UIKit lifecycle
@@ -159,7 +111,7 @@ const ENTRY_POINT_PATTERNS = {
159
111
  /^makeBody$/, // SwiftUI ViewModifier
160
112
  ],
161
113
  // PHP / Laravel
162
- [SupportedLanguages.PHP]: [
114
+ 'php': [
163
115
  /Controller$/, // UserController (class name convention)
164
116
  /^handle$/, // Job::handle(), Listener::handle()
165
117
  /^execute$/, // Command::execute()
@@ -179,14 +131,6 @@ const ENTRY_POINT_PATTERNS = {
179
131
  /^delete$/, // Repository::delete()
180
132
  ],
181
133
  };
182
- /** Pre-computed merged patterns (universal + language-specific) to avoid per-call array allocation. */
183
- const MERGED_ENTRY_POINT_PATTERNS = {};
184
- const UNIVERSAL_PATTERNS = ENTRY_POINT_PATTERNS['*'] || [];
185
- for (const [lang, patterns] of Object.entries(ENTRY_POINT_PATTERNS)) {
186
- if (lang === '*')
187
- continue;
188
- MERGED_ENTRY_POINT_PATTERNS[lang] = [...UNIVERSAL_PATTERNS, ...patterns];
189
- }
190
134
  // ============================================================================
191
135
  // UTILITY PATTERNS - Functions that should be penalized
192
136
  // ============================================================================
@@ -252,7 +196,9 @@ export function calculateEntryPointScore(name, language, isExported, callerCount
252
196
  }
253
197
  else {
254
198
  // Check positive patterns
255
- const allPatterns = MERGED_ENTRY_POINT_PATTERNS[language] || UNIVERSAL_PATTERNS;
199
+ const universalPatterns = ENTRY_POINT_PATTERNS['*'] || [];
200
+ const langPatterns = ENTRY_POINT_PATTERNS[language] || [];
201
+ const allPatterns = [...universalPatterns, ...langPatterns];
256
202
  if (allPatterns.some(p => p.test(name))) {
257
203
  nameMultiplier = 1.5; // Bonus for matching entry point pattern
258
204
  reasons.push('entry-pattern');
@@ -307,13 +253,8 @@ export function isTestFile(filePath) {
307
253
  p.endsWith('test.swift') ||
308
254
  p.includes('uitests/') ||
309
255
  // C# test patterns
310
- p.endsWith('tests.cs') ||
311
- p.endsWith('test.cs') ||
312
256
  p.includes('.tests/') ||
313
- p.includes('.test/') ||
314
- p.includes('.integrationtests/') ||
315
- p.includes('.unittests/') ||
316
- p.includes('/testproject/') ||
257
+ p.includes('tests.cs') ||
317
258
  // PHP/Laravel test patterns
318
259
  p.endsWith('test.php') ||
319
260
  p.endsWith('spec.php') ||
@@ -33,9 +33,6 @@ export declare const FRAMEWORK_AST_PATTERNS: {
33
33
  spring: string[];
34
34
  jaxrs: string[];
35
35
  aspnet: string[];
36
- signalr: string[];
37
- blazor: string[];
38
- efcore: string[];
39
36
  'go-http': string[];
40
37
  laravel: string[];
41
38
  actix: string[];
@@ -45,10 +42,9 @@ export declare const FRAMEWORK_AST_PATTERNS: {
45
42
  swiftui: string[];
46
43
  combine: string[];
47
44
  };
48
- import { SupportedLanguages } from '../../config/supported-languages.js';
49
45
  /**
50
46
  * Detect framework entry points from AST definition text (decorators/annotations/attributes).
51
47
  * Returns null if no known pattern is found.
52
48
  * Note: callers should slice definitionText to ~300 chars since annotations appear at the start.
53
49
  */
54
- export declare function detectFrameworkFromAST(language: SupportedLanguages, definitionText: string): FrameworkHint | null;
50
+ export declare function detectFrameworkFromAST(language: string, definitionText: string): FrameworkHint | null;
@@ -140,29 +140,6 @@ export function detectFrameworkFromPath(filePath) {
140
140
  if (p.endsWith('controller.cs')) {
141
141
  return { framework: 'aspnet', entryPointMultiplier: 3.0, reason: 'aspnet-controller-file' };
142
142
  }
143
- // ASP.NET Services
144
- if ((p.includes('/services/') || p.includes('/service/')) && p.endsWith('.cs')) {
145
- return { framework: 'aspnet', entryPointMultiplier: 1.8, reason: 'aspnet-service' };
146
- }
147
- // ASP.NET Middleware
148
- if (p.includes('/middleware/') && p.endsWith('.cs')) {
149
- return { framework: 'aspnet', entryPointMultiplier: 2.5, reason: 'aspnet-middleware' };
150
- }
151
- // SignalR Hubs
152
- if (p.includes('/hubs/') && p.endsWith('.cs')) {
153
- return { framework: 'signalr', entryPointMultiplier: 2.5, reason: 'signalr-hub' };
154
- }
155
- if (p.endsWith('hub.cs')) {
156
- return { framework: 'signalr', entryPointMultiplier: 2.5, reason: 'signalr-hub-file' };
157
- }
158
- // Minimal API / Program.cs / Startup.cs
159
- if (p.endsWith('/program.cs') || p.endsWith('/startup.cs')) {
160
- return { framework: 'aspnet', entryPointMultiplier: 3.0, reason: 'aspnet-entry' };
161
- }
162
- // Background services / Hosted services
163
- if ((p.includes('/backgroundservices/') || p.includes('/hostedservices/')) && p.endsWith('.cs')) {
164
- return { framework: 'aspnet', entryPointMultiplier: 2.0, reason: 'aspnet-background-service' };
165
- }
166
143
  // Blazor pages
167
144
  if (p.includes('/pages/') && p.endsWith('.razor')) {
168
145
  return { framework: 'blazor', entryPointMultiplier: 2.5, reason: 'blazor-page' };
@@ -319,11 +296,7 @@ export const FRAMEWORK_AST_PATTERNS = {
319
296
  'spring': ['@RestController', '@Controller', '@GetMapping', '@PostMapping', '@RequestMapping'],
320
297
  'jaxrs': ['@Path', '@GET', '@POST', '@PUT', '@DELETE'],
321
298
  // C# attributes
322
- 'aspnet': ['[ApiController]', '[HttpGet]', '[HttpPost]', '[HttpPut]', '[HttpDelete]',
323
- '[Route]', '[Authorize]', '[AllowAnonymous]'],
324
- 'signalr': ['[HubMethodName]', ': Hub', ': Hub<'],
325
- 'blazor': ['@page', '[Parameter]', '@inject'],
326
- 'efcore': ['DbContext', 'DbSet<', 'OnModelCreating'],
299
+ 'aspnet': ['[ApiController]', '[HttpGet]', '[HttpPost]', '[Route]'],
327
300
  // Go patterns (function signatures)
328
301
  'go-http': ['http.Handler', 'http.HandlerFunc', 'ServeHTTP'],
329
302
  // PHP/Laravel
@@ -338,35 +311,31 @@ export const FRAMEWORK_AST_PATTERNS = {
338
311
  'swiftui': ['@main', 'WindowGroup', 'ContentView', '@StateObject', '@ObservedObject'],
339
312
  'combine': ['sink', 'assign', 'Publisher', 'Subscriber'],
340
313
  };
341
- import { SupportedLanguages } from '../../config/supported-languages.js';
342
314
  const AST_FRAMEWORK_PATTERNS_BY_LANGUAGE = {
343
- [SupportedLanguages.JavaScript]: [
315
+ javascript: [
344
316
  { framework: 'nestjs', entryPointMultiplier: 3.2, reason: 'nestjs-decorator', patterns: FRAMEWORK_AST_PATTERNS.nestjs },
345
317
  ],
346
- [SupportedLanguages.TypeScript]: [
318
+ typescript: [
347
319
  { framework: 'nestjs', entryPointMultiplier: 3.2, reason: 'nestjs-decorator', patterns: FRAMEWORK_AST_PATTERNS.nestjs },
348
320
  ],
349
- [SupportedLanguages.Python]: [
321
+ python: [
350
322
  { framework: 'fastapi', entryPointMultiplier: 3.0, reason: 'fastapi-decorator', patterns: FRAMEWORK_AST_PATTERNS.fastapi },
351
323
  { framework: 'flask', entryPointMultiplier: 2.8, reason: 'flask-decorator', patterns: FRAMEWORK_AST_PATTERNS.flask },
352
324
  ],
353
- [SupportedLanguages.Java]: [
325
+ java: [
354
326
  { framework: 'spring', entryPointMultiplier: 3.2, reason: 'spring-annotation', patterns: FRAMEWORK_AST_PATTERNS.spring },
355
327
  { framework: 'jaxrs', entryPointMultiplier: 3.0, reason: 'jaxrs-annotation', patterns: FRAMEWORK_AST_PATTERNS.jaxrs },
356
328
  ],
357
- [SupportedLanguages.Kotlin]: [
329
+ kotlin: [
358
330
  { framework: 'spring-kotlin', entryPointMultiplier: 3.2, reason: 'spring-kotlin-annotation', patterns: FRAMEWORK_AST_PATTERNS.spring },
359
331
  { framework: 'jaxrs', entryPointMultiplier: 3.0, reason: 'jaxrs-annotation', patterns: FRAMEWORK_AST_PATTERNS.jaxrs },
360
332
  { framework: 'ktor', entryPointMultiplier: 2.8, reason: 'ktor-routing', patterns: ['routing', 'embeddedServer', 'Application.module'] },
361
333
  { framework: 'android-kotlin', entryPointMultiplier: 2.5, reason: 'android-annotation', patterns: ['@AndroidEntryPoint', 'AppCompatActivity', 'Fragment('] },
362
334
  ],
363
- [SupportedLanguages.CSharp]: [
335
+ csharp: [
364
336
  { framework: 'aspnet', entryPointMultiplier: 3.2, reason: 'aspnet-attribute', patterns: FRAMEWORK_AST_PATTERNS.aspnet },
365
- { framework: 'signalr', entryPointMultiplier: 2.8, reason: 'signalr-attribute', patterns: FRAMEWORK_AST_PATTERNS.signalr },
366
- { framework: 'blazor', entryPointMultiplier: 2.5, reason: 'blazor-attribute', patterns: FRAMEWORK_AST_PATTERNS.blazor },
367
- { framework: 'efcore', entryPointMultiplier: 2.0, reason: 'efcore-pattern', patterns: FRAMEWORK_AST_PATTERNS.efcore },
368
337
  ],
369
- [SupportedLanguages.PHP]: [
338
+ php: [
370
339
  { framework: 'laravel', entryPointMultiplier: 3.0, reason: 'php-route-attribute', patterns: FRAMEWORK_AST_PATTERNS.laravel },
371
340
  ],
372
341
  };
@@ -2,28 +2,19 @@
2
2
  * Heritage Processor
3
3
  *
4
4
  * Extracts class inheritance relationships:
5
- * - EXTENDS: Class extends another Class (TS, JS, Python, C#, C++)
6
- * - IMPLEMENTS: Class implements an Interface (TS, C#, Java, Kotlin, PHP)
7
- *
8
- * Languages like C# use a single `base_list` for both class and interface parents.
9
- * We resolve the correct edge type by checking the symbol table: if the parent is
10
- * registered as an Interface, we emit IMPLEMENTS; otherwise EXTENDS. For unresolved
11
- * external symbols, the fallback heuristic is language-gated:
12
- * - C# / Java: apply the `I[A-Z]` naming convention (e.g. IDisposable → IMPLEMENTS)
13
- * - Swift: default to IMPLEMENTS (protocol conformance is more common than class inheritance)
14
- * - All other languages: default to EXTENDS
5
+ * - EXTENDS: Class extends another Class (TS, JS, Python)
6
+ * - IMPLEMENTS: Class implements an Interface (TS only)
15
7
  */
16
8
  import { KnowledgeGraph } from '../graph/types.js';
17
9
  import { ASTCache } from './ast-cache.js';
18
10
  import { SymbolTable } from './symbol-table.js';
19
11
  import type { ExtractedHeritage } from './workers/parse-worker.js';
20
- import type { ImportMap, PackageMap } from './import-processor.js';
21
12
  export declare const processHeritage: (graph: KnowledgeGraph, files: {
22
13
  path: string;
23
14
  content: string;
24
- }[], astCache: ASTCache, symbolTable: SymbolTable, importMap: ImportMap, packageMap?: PackageMap, onProgress?: (current: number, total: number) => void) => Promise<void>;
15
+ }[], astCache: ASTCache, symbolTable: SymbolTable, onProgress?: (current: number, total: number) => void) => Promise<void>;
25
16
  /**
26
17
  * Fast path: resolve pre-extracted heritage from workers.
27
18
  * No AST parsing — workers already extracted className + parentName + kind.
28
19
  */
29
- export declare const processHeritageFromExtracted: (graph: KnowledgeGraph, extractedHeritage: ExtractedHeritage[], symbolTable: SymbolTable, importMap: ImportMap, packageMap?: PackageMap, onProgress?: (current: number, total: number) => void) => Promise<void>;
20
+ export declare const processHeritageFromExtracted: (graph: KnowledgeGraph, extractedHeritage: ExtractedHeritage[], symbolTable: SymbolTable, onProgress?: (current: number, total: number) => void) => Promise<void>;
@@ -2,59 +2,16 @@
2
2
  * Heritage Processor
3
3
  *
4
4
  * Extracts class inheritance relationships:
5
- * - EXTENDS: Class extends another Class (TS, JS, Python, C#, C++)
6
- * - IMPLEMENTS: Class implements an Interface (TS, C#, Java, Kotlin, PHP)
7
- *
8
- * Languages like C# use a single `base_list` for both class and interface parents.
9
- * We resolve the correct edge type by checking the symbol table: if the parent is
10
- * registered as an Interface, we emit IMPLEMENTS; otherwise EXTENDS. For unresolved
11
- * external symbols, the fallback heuristic is language-gated:
12
- * - C# / Java: apply the `I[A-Z]` naming convention (e.g. IDisposable → IMPLEMENTS)
13
- * - Swift: default to IMPLEMENTS (protocol conformance is more common than class inheritance)
14
- * - All other languages: default to EXTENDS
5
+ * - EXTENDS: Class extends another Class (TS, JS, Python)
6
+ * - IMPLEMENTS: Class implements an Interface (TS only)
15
7
  */
16
8
  import Parser from 'tree-sitter';
17
- import { isLanguageAvailable, loadParser, loadLanguage } from '../tree-sitter/parser-loader.js';
9
+ import { loadParser, loadLanguage } from '../tree-sitter/parser-loader.js';
18
10
  import { LANGUAGE_QUERIES } from './tree-sitter-queries.js';
19
11
  import { generateId } from '../../lib/utils.js';
20
- import { getLanguageFromFilename, isVerboseIngestionEnabled, yieldToEventLoop } from './utils.js';
21
- import { SupportedLanguages } from '../../config/supported-languages.js';
22
- import { getTreeSitterBufferSize } from './constants.js';
23
- import { resolveSymbol } from './symbol-resolver.js';
24
- /** C#/Java convention: interfaces start with I followed by an uppercase letter */
25
- const INTERFACE_NAME_RE = /^I[A-Z]/;
26
- /**
27
- * Determine whether a heritage.extends capture is actually an IMPLEMENTS relationship.
28
- * Uses the symbol table first (authoritative — Tier 1); falls back to a language-gated
29
- * heuristic for external symbols not present in the graph:
30
- * - C# / Java: `I[A-Z]` naming convention
31
- * - Swift: default IMPLEMENTS (protocol conformance is the norm)
32
- * - All others: default EXTENDS
33
- */
34
- const resolveExtendsType = (parentName, currentFilePath, symbolTable, importMap, language, packageMap) => {
35
- const resolved = resolveSymbol(parentName, currentFilePath, symbolTable, importMap, packageMap);
36
- if (resolved) {
37
- const isInterface = resolved.type === 'Interface';
38
- return isInterface
39
- ? { type: 'IMPLEMENTS', idPrefix: 'Interface' }
40
- : { type: 'EXTENDS', idPrefix: 'Class' };
41
- }
42
- // Unresolved symbol — fall back to language-specific heuristic
43
- if (language === SupportedLanguages.CSharp || language === SupportedLanguages.Java) {
44
- if (INTERFACE_NAME_RE.test(parentName)) {
45
- return { type: 'IMPLEMENTS', idPrefix: 'Interface' };
46
- }
47
- }
48
- else if (language === SupportedLanguages.Swift) {
49
- // Protocol conformance is far more common than class inheritance in Swift
50
- return { type: 'IMPLEMENTS', idPrefix: 'Interface' };
51
- }
52
- return { type: 'EXTENDS', idPrefix: 'Class' };
53
- };
54
- export const processHeritage = async (graph, files, astCache, symbolTable, importMap, packageMap, onProgress) => {
12
+ import { getLanguageFromFilename, yieldToEventLoop } from './utils.js';
13
+ export const processHeritage = async (graph, files, astCache, symbolTable, onProgress) => {
55
14
  const parser = await loadParser();
56
- const logSkipped = isVerboseIngestionEnabled();
57
- const skippedByLang = logSkipped ? new Map() : null;
58
15
  for (let i = 0; i < files.length; i++) {
59
16
  const file = files[i];
60
17
  onProgress?.(i + 1, files.length);
@@ -64,12 +21,6 @@ export const processHeritage = async (graph, files, astCache, symbolTable, impor
64
21
  const language = getLanguageFromFilename(file.path);
65
22
  if (!language)
66
23
  continue;
67
- if (!isLanguageAvailable(language)) {
68
- if (skippedByLang) {
69
- skippedByLang.set(language, (skippedByLang.get(language) ?? 0) + 1);
70
- }
71
- continue;
72
- }
73
24
  const queryStr = LANGUAGE_QUERIES[language];
74
25
  if (!queryStr)
75
26
  continue;
@@ -81,7 +32,7 @@ export const processHeritage = async (graph, files, astCache, symbolTable, impor
81
32
  if (!tree) {
82
33
  // Use larger bufferSize for files > 32KB
83
34
  try {
84
- tree = parser.parse(file.content, undefined, { bufferSize: getTreeSitterBufferSize(file.content.length) });
35
+ tree = parser.parse(file.content, undefined, { bufferSize: 1024 * 256 });
85
36
  }
86
37
  catch (parseError) {
87
38
  // Skip files that can't be parsed
@@ -108,29 +59,23 @@ export const processHeritage = async (graph, files, astCache, symbolTable, impor
108
59
  match.captures.forEach(c => {
109
60
  captureMap[c.name] = c.node;
110
61
  });
111
- // EXTENDS or IMPLEMENTS: resolve via symbol table for languages where
112
- // the tree-sitter query can't distinguish classes from interfaces (C#, Java)
62
+ // EXTENDS: Class extends another Class
113
63
  if (captureMap['heritage.class'] && captureMap['heritage.extends']) {
114
- // Go struct embedding: skip named fields (only anonymous fields are embedded)
115
- const extendsNode = captureMap['heritage.extends'];
116
- const fieldDecl = extendsNode.parent;
117
- if (fieldDecl?.type === 'field_declaration' && fieldDecl.childForFieldName('name')) {
118
- return; // Named field, not struct embedding
119
- }
120
64
  const className = captureMap['heritage.class'].text;
121
65
  const parentClassName = captureMap['heritage.extends'].text;
122
- const { type: relType, idPrefix } = resolveExtendsType(parentClassName, file.path, symbolTable, importMap, language, packageMap);
66
+ // Resolve both class IDs
123
67
  const childId = symbolTable.lookupExact(file.path, className) ||
124
- resolveSymbol(className, file.path, symbolTable, importMap, packageMap)?.nodeId ||
68
+ symbolTable.lookupFuzzy(className)[0]?.nodeId ||
125
69
  generateId('Class', `${file.path}:${className}`);
126
- const parentId = resolveSymbol(parentClassName, file.path, symbolTable, importMap, packageMap)?.nodeId ||
127
- generateId(idPrefix, `${parentClassName}`);
70
+ const parentId = symbolTable.lookupFuzzy(parentClassName)[0]?.nodeId ||
71
+ generateId('Class', `${parentClassName}`);
128
72
  if (childId && parentId && childId !== parentId) {
73
+ const relId = generateId('EXTENDS', `${childId}->${parentId}`);
129
74
  graph.addRelationship({
130
- id: generateId(relType, `${childId}->${parentId}`),
75
+ id: relId,
131
76
  sourceId: childId,
132
77
  targetId: parentId,
133
- type: relType,
78
+ type: 'EXTENDS',
134
79
  confidence: 1.0,
135
80
  reason: '',
136
81
  });
@@ -142,9 +87,9 @@ export const processHeritage = async (graph, files, astCache, symbolTable, impor
142
87
  const interfaceName = captureMap['heritage.implements'].text;
143
88
  // Resolve class and interface IDs
144
89
  const classId = symbolTable.lookupExact(file.path, className) ||
145
- resolveSymbol(className, file.path, symbolTable, importMap, packageMap)?.nodeId ||
90
+ symbolTable.lookupFuzzy(className)[0]?.nodeId ||
146
91
  generateId('Class', `${file.path}:${className}`);
147
- const interfaceId = resolveSymbol(interfaceName, file.path, symbolTable, importMap, packageMap)?.nodeId ||
92
+ const interfaceId = symbolTable.lookupFuzzy(interfaceName)[0]?.nodeId ||
148
93
  generateId('Interface', `${interfaceName}`);
149
94
  if (classId && interfaceId) {
150
95
  const relId = generateId('IMPLEMENTS', `${classId}->${interfaceId}`);
@@ -164,9 +109,9 @@ export const processHeritage = async (graph, files, astCache, symbolTable, impor
164
109
  const traitName = captureMap['heritage.trait'].text;
165
110
  // Resolve struct and trait IDs
166
111
  const structId = symbolTable.lookupExact(file.path, structName) ||
167
- resolveSymbol(structName, file.path, symbolTable, importMap, packageMap)?.nodeId ||
112
+ symbolTable.lookupFuzzy(structName)[0]?.nodeId ||
168
113
  generateId('Struct', `${file.path}:${structName}`);
169
- const traitId = resolveSymbol(traitName, file.path, symbolTable, importMap, packageMap)?.nodeId ||
114
+ const traitId = symbolTable.lookupFuzzy(traitName)[0]?.nodeId ||
170
115
  generateId('Trait', `${traitName}`);
171
116
  if (structId && traitId) {
172
117
  const relId = generateId('IMPLEMENTS', `${structId}->${traitId}`);
@@ -183,17 +128,12 @@ export const processHeritage = async (graph, files, astCache, symbolTable, impor
183
128
  });
184
129
  // Tree is now owned by the LRU cache — no manual delete needed
185
130
  }
186
- if (skippedByLang && skippedByLang.size > 0) {
187
- for (const [lang, count] of skippedByLang.entries()) {
188
- console.warn(`[ingestion] Skipped ${count} ${lang} file(s) in heritage processing — ${lang} parser not available.`);
189
- }
190
- }
191
131
  };
192
132
  /**
193
133
  * Fast path: resolve pre-extracted heritage from workers.
194
134
  * No AST parsing — workers already extracted className + parentName + kind.
195
135
  */
196
- export const processHeritageFromExtracted = async (graph, extractedHeritage, symbolTable, importMap, packageMap, onProgress) => {
136
+ export const processHeritageFromExtracted = async (graph, extractedHeritage, symbolTable, onProgress) => {
197
137
  const total = extractedHeritage.length;
198
138
  for (let i = 0; i < extractedHeritage.length; i++) {
199
139
  if (i % 500 === 0) {
@@ -202,21 +142,17 @@ export const processHeritageFromExtracted = async (graph, extractedHeritage, sym
202
142
  }
203
143
  const h = extractedHeritage[i];
204
144
  if (h.kind === 'extends') {
205
- const fileLanguage = getLanguageFromFilename(h.filePath);
206
- if (!fileLanguage)
207
- continue;
208
- const { type: relType, idPrefix } = resolveExtendsType(h.parentName, h.filePath, symbolTable, importMap, fileLanguage, packageMap);
209
145
  const childId = symbolTable.lookupExact(h.filePath, h.className) ||
210
- resolveSymbol(h.className, h.filePath, symbolTable, importMap, packageMap)?.nodeId ||
146
+ symbolTable.lookupFuzzy(h.className)[0]?.nodeId ||
211
147
  generateId('Class', `${h.filePath}:${h.className}`);
212
- const parentId = resolveSymbol(h.parentName, h.filePath, symbolTable, importMap, packageMap)?.nodeId ||
213
- generateId(idPrefix, `${h.parentName}`);
148
+ const parentId = symbolTable.lookupFuzzy(h.parentName)[0]?.nodeId ||
149
+ generateId('Class', `${h.parentName}`);
214
150
  if (childId && parentId && childId !== parentId) {
215
151
  graph.addRelationship({
216
- id: generateId(relType, `${childId}->${parentId}`),
152
+ id: generateId('EXTENDS', `${childId}->${parentId}`),
217
153
  sourceId: childId,
218
154
  targetId: parentId,
219
- type: relType,
155
+ type: 'EXTENDS',
220
156
  confidence: 1.0,
221
157
  reason: '',
222
158
  });
@@ -224,9 +160,9 @@ export const processHeritageFromExtracted = async (graph, extractedHeritage, sym
224
160
  }
225
161
  else if (h.kind === 'implements') {
226
162
  const classId = symbolTable.lookupExact(h.filePath, h.className) ||
227
- resolveSymbol(h.className, h.filePath, symbolTable, importMap, packageMap)?.nodeId ||
163
+ symbolTable.lookupFuzzy(h.className)[0]?.nodeId ||
228
164
  generateId('Class', `${h.filePath}:${h.className}`);
229
- const interfaceId = resolveSymbol(h.parentName, h.filePath, symbolTable, importMap, packageMap)?.nodeId ||
165
+ const interfaceId = symbolTable.lookupFuzzy(h.parentName)[0]?.nodeId ||
230
166
  generateId('Interface', `${h.parentName}`);
231
167
  if (classId && interfaceId) {
232
168
  graph.addRelationship({
@@ -241,9 +177,9 @@ export const processHeritageFromExtracted = async (graph, extractedHeritage, sym
241
177
  }
242
178
  else if (h.kind === 'trait-impl') {
243
179
  const structId = symbolTable.lookupExact(h.filePath, h.className) ||
244
- resolveSymbol(h.className, h.filePath, symbolTable, importMap, packageMap)?.nodeId ||
180
+ symbolTable.lookupFuzzy(h.className)[0]?.nodeId ||
245
181
  generateId('Struct', `${h.filePath}:${h.className}`);
246
- const traitId = resolveSymbol(h.parentName, h.filePath, symbolTable, importMap, packageMap)?.nodeId ||
182
+ const traitId = symbolTable.lookupFuzzy(h.parentName)[0]?.nodeId ||
247
183
  generateId('Trait', `${h.parentName}`);
248
184
  if (structId && traitId) {
249
185
  graph.addRelationship({
@@ -1,23 +1,8 @@
1
1
  import { KnowledgeGraph } from '../graph/types.js';
2
2
  import { ASTCache } from './ast-cache.js';
3
3
  import type { ExtractedImport } from './workers/parse-worker.js';
4
- import type { SuffixIndex } from './resolvers/index.js';
5
- export type { SuffixIndex, TsconfigPaths, GoModuleConfig, CSharpProjectConfig, ComposerConfig } from './resolvers/index.js';
6
4
  export type ImportMap = Map<string, Set<string>>;
7
5
  export declare const createImportMap: () => ImportMap;
8
- export type PackageMap = Map<string, Set<string>>;
9
- export declare const createPackageMap: () => PackageMap;
10
- export interface NamedImportBinding {
11
- sourcePath: string;
12
- exportedName: string;
13
- }
14
- export type NamedImportMap = Map<string, Map<string, NamedImportBinding>>;
15
- export declare const createNamedImportMap: () => NamedImportMap;
16
- /**
17
- * Check if a file path is directly inside a package directory identified by its suffix.
18
- * Used by the symbol resolver for Go and C# directory-level import matching.
19
- */
20
- export declare function isFileInPackageDir(filePath: string, dirSuffix: string): boolean;
21
6
  /** Pre-built lookup structures for import resolution. Build once, reuse across chunks. */
22
7
  export interface ImportResolutionContext {
23
8
  allFilePaths: Set<string>;
@@ -27,10 +12,27 @@ export interface ImportResolutionContext {
27
12
  resolveCache: Map<string, string | null>;
28
13
  }
29
14
  export declare function buildImportResolutionContext(allPaths: string[]): ImportResolutionContext;
15
+ /**
16
+ * Build a suffix index for O(1) endsWith lookups.
17
+ * Maps every possible path suffix to its original file path.
18
+ * e.g. for "src/com/example/Foo.java":
19
+ * "Foo.java" -> "src/com/example/Foo.java"
20
+ * "example/Foo.java" -> "src/com/example/Foo.java"
21
+ * "com/example/Foo.java" -> "src/com/example/Foo.java"
22
+ * etc.
23
+ */
24
+ export interface SuffixIndex {
25
+ /** Exact suffix lookup (case-sensitive) */
26
+ get(suffix: string): string | undefined;
27
+ /** Case-insensitive suffix lookup */
28
+ getInsensitive(suffix: string): string | undefined;
29
+ /** Get all files in a directory suffix */
30
+ getFilesInDir(dirSuffix: string, extension: string): string[];
31
+ }
30
32
  export declare const processImports: (graph: KnowledgeGraph, files: {
31
33
  path: string;
32
34
  content: string;
33
- }[], astCache: ASTCache, importMap: ImportMap, onProgress?: (current: number, total: number) => void, repoRoot?: string, allPaths?: string[], packageMap?: PackageMap, namedImportMap?: NamedImportMap) => Promise<void>;
35
+ }[], astCache: ASTCache, importMap: ImportMap, onProgress?: (current: number, total: number) => void, repoRoot?: string, allPaths?: string[]) => Promise<void>;
34
36
  export declare const processImportsFromExtracted: (graph: KnowledgeGraph, files: {
35
37
  path: string;
36
- }[], extractedImports: ExtractedImport[], importMap: ImportMap, onProgress?: (current: number, total: number) => void, repoRoot?: string, prebuiltCtx?: ImportResolutionContext, packageMap?: PackageMap, namedImportMap?: NamedImportMap) => Promise<void>;
38
+ }[], extractedImports: ExtractedImport[], importMap: ImportMap, onProgress?: (current: number, total: number) => void, repoRoot?: string, prebuiltCtx?: ImportResolutionContext) => Promise<void>;