gitnexus 1.6.4 → 1.6.5-rc.10

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 (72) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/ai-context.d.ts +1 -0
  3. package/dist/cli/ai-context.js +30 -12
  4. package/dist/cli/analyze.d.ts +18 -0
  5. package/dist/cli/analyze.js +33 -4
  6. package/dist/cli/augment.d.ts +1 -1
  7. package/dist/cli/augment.js +1 -1
  8. package/dist/cli/index.js +6 -1
  9. package/dist/core/augmentation/engine.d.ts +2 -2
  10. package/dist/core/augmentation/engine.js +2 -2
  11. package/dist/core/embeddings/ast-utils.js +2 -1
  12. package/dist/core/embeddings/http-client.js +22 -6
  13. package/dist/core/group/extractors/grpc-extractor.js +2 -1
  14. package/dist/core/group/extractors/http-patterns/python.js +175 -0
  15. package/dist/core/group/extractors/http-route-extractor.js +2 -1
  16. package/dist/core/group/extractors/include-extractor.js +2 -1
  17. package/dist/core/group/extractors/thrift-extractor.js +2 -1
  18. package/dist/core/group/extractors/tree-sitter-scanner.js +2 -1
  19. package/dist/core/ingestion/call-processor.js +3 -2
  20. package/dist/core/ingestion/heritage-processor.js +3 -2
  21. package/dist/core/ingestion/import-processor.js +2 -1
  22. package/dist/core/ingestion/languages/c/arity-metadata.d.ts +14 -0
  23. package/dist/core/ingestion/languages/c/arity-metadata.js +94 -0
  24. package/dist/core/ingestion/languages/c/arity.d.ts +6 -0
  25. package/dist/core/ingestion/languages/c/arity.js +18 -0
  26. package/dist/core/ingestion/languages/c/captures.d.ts +2 -0
  27. package/dist/core/ingestion/languages/c/captures.js +105 -0
  28. package/dist/core/ingestion/languages/c/header-scan.d.ts +7 -0
  29. package/dist/core/ingestion/languages/c/header-scan.js +55 -0
  30. package/dist/core/ingestion/languages/c/import-decomposer.d.ts +8 -0
  31. package/dist/core/ingestion/languages/c/import-decomposer.js +50 -0
  32. package/dist/core/ingestion/languages/c/import-target.d.ts +14 -0
  33. package/dist/core/ingestion/languages/c/import-target.js +57 -0
  34. package/dist/core/ingestion/languages/c/index.d.ts +11 -0
  35. package/dist/core/ingestion/languages/c/index.js +11 -0
  36. package/dist/core/ingestion/languages/c/interpret.d.ts +14 -0
  37. package/dist/core/ingestion/languages/c/interpret.js +48 -0
  38. package/dist/core/ingestion/languages/c/merge-bindings.d.ts +7 -0
  39. package/dist/core/ingestion/languages/c/merge-bindings.js +23 -0
  40. package/dist/core/ingestion/languages/c/query.d.ts +3 -0
  41. package/dist/core/ingestion/languages/c/query.js +161 -0
  42. package/dist/core/ingestion/languages/c/scope-resolver.d.ts +13 -0
  43. package/dist/core/ingestion/languages/c/scope-resolver.js +60 -0
  44. package/dist/core/ingestion/languages/c/simple-hooks.d.ts +14 -0
  45. package/dist/core/ingestion/languages/c/simple-hooks.js +19 -0
  46. package/dist/core/ingestion/languages/c/static-linkage.d.ts +13 -0
  47. package/dist/core/ingestion/languages/c/static-linkage.js +57 -0
  48. package/dist/core/ingestion/languages/c-cpp.js +10 -0
  49. package/dist/core/ingestion/languages/csharp/captures.js +2 -1
  50. package/dist/core/ingestion/languages/csharp/namespace-siblings.js +3 -2
  51. package/dist/core/ingestion/languages/go/captures.js +2 -1
  52. package/dist/core/ingestion/languages/go/range-binding.js +2 -1
  53. package/dist/core/ingestion/languages/python/captures.js +2 -1
  54. package/dist/core/ingestion/languages/typescript/captures.js +2 -1
  55. package/dist/core/ingestion/parsing-processor.js +2 -1
  56. package/dist/core/ingestion/registry-primary-flag.js +1 -0
  57. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +11 -0
  58. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +2 -1
  59. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +13 -2
  60. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +2 -0
  61. package/dist/core/ingestion/scope-resolution/pipeline/run.js +4 -1
  62. package/dist/core/ingestion/workers/parse-worker.js +2 -1
  63. package/dist/core/lbug/lbug-adapter.js +8 -0
  64. package/dist/core/lbug/pool-adapter.js +19 -2
  65. package/dist/core/run-analyze.d.ts +2 -0
  66. package/dist/core/run-analyze.js +5 -1
  67. package/dist/core/tree-sitter/safe-parse.d.ts +6 -0
  68. package/dist/core/tree-sitter/safe-parse.js +32 -0
  69. package/dist/server/git-clone.js +10 -13
  70. package/dist/storage/git.d.ts +17 -6
  71. package/dist/storage/git.js +46 -12
  72. package/package.json +1 -1
@@ -0,0 +1,161 @@
1
+ import Parser from 'tree-sitter';
2
+ import C from 'tree-sitter-c';
3
+ const C_SCOPE_QUERY = `
4
+ ;; Scopes
5
+ (translation_unit) @scope.module
6
+ (struct_specifier) @scope.class
7
+ (union_specifier) @scope.class
8
+ (function_definition) @scope.function
9
+ (compound_statement) @scope.block
10
+ (if_statement) @scope.block
11
+ (for_statement) @scope.block
12
+ (while_statement) @scope.block
13
+ (do_statement) @scope.block
14
+ (switch_statement) @scope.block
15
+ (case_statement) @scope.block
16
+
17
+ ;; Declarations — struct (named)
18
+ (struct_specifier
19
+ name: (type_identifier) @declaration.name
20
+ body: (field_declaration_list)) @declaration.struct
21
+
22
+ ;; Declarations — struct (typedef struct { ... } Name)
23
+ (type_definition
24
+ type: (struct_specifier
25
+ body: (field_declaration_list))
26
+ declarator: (type_identifier) @declaration.name) @declaration.struct
27
+
28
+ ;; Declarations — union (named)
29
+ (union_specifier
30
+ name: (type_identifier) @declaration.name
31
+ body: (field_declaration_list)) @declaration.union
32
+
33
+ ;; Declarations — union (typedef union { ... } Name)
34
+ (type_definition
35
+ type: (union_specifier
36
+ body: (field_declaration_list))
37
+ declarator: (type_identifier) @declaration.name) @declaration.union
38
+
39
+ ;; Declarations — enum
40
+ (enum_specifier
41
+ name: (type_identifier) @declaration.name) @declaration.enum
42
+
43
+ ;; Declarations — function definition
44
+ (function_definition
45
+ declarator: (function_declarator
46
+ declarator: (identifier) @declaration.name)) @declaration.function
47
+
48
+ ;; Declarations — function definition with pointer return
49
+ (function_definition
50
+ declarator: (pointer_declarator
51
+ declarator: (function_declarator
52
+ declarator: (identifier) @declaration.name))) @declaration.function
53
+
54
+ ;; Declarations — function declaration (prototype)
55
+ ;; Note: Both prototypes and definitions are captured as @declaration.function.
56
+ ;; This may produce duplicate Function nodes in the knowledge graph when a
57
+ ;; function is declared in a header and defined in a .c file. CALLS edges
58
+ ;; resolve correctly through scope-based wildcard import chains; the
59
+ ;; duplication is a graph-quality concern only (no false edges).
60
+ (declaration
61
+ declarator: (function_declarator
62
+ declarator: (identifier) @declaration.name)) @declaration.function
63
+
64
+ ;; Declarations — function declaration with pointer return (prototype)
65
+ (declaration
66
+ declarator: (pointer_declarator
67
+ declarator: (function_declarator
68
+ declarator: (identifier) @declaration.name))) @declaration.function
69
+
70
+ ;; Declarations — typedef
71
+ (type_definition
72
+ declarator: (type_identifier) @declaration.name) @declaration.typedef
73
+
74
+ ;; Declarations — typedef for function pointers: typedef void (*callback)(int, int)
75
+ (type_definition
76
+ declarator: (function_declarator
77
+ declarator: (parenthesized_declarator
78
+ (pointer_declarator
79
+ declarator: (type_identifier) @declaration.name)))) @declaration.typedef
80
+
81
+ ;; Declarations — struct fields
82
+ (field_declaration
83
+ declarator: (field_identifier) @declaration.name) @declaration.field
84
+
85
+ ;; Declarations — struct fields (pointer)
86
+ (field_declaration
87
+ declarator: (pointer_declarator
88
+ declarator: (field_identifier) @declaration.name)) @declaration.field
89
+
90
+ ;; Declarations — variables (with initializer)
91
+ (declaration
92
+ declarator: (init_declarator
93
+ declarator: (identifier) @declaration.name)) @declaration.variable
94
+
95
+ ;; Declarations — macro definitions
96
+ (preproc_def
97
+ name: (identifier) @declaration.name) @declaration.macro
98
+
99
+ (preproc_function_def
100
+ name: (identifier) @declaration.name) @declaration.macro
101
+
102
+ ;; Declarations — enum constants
103
+ (enumerator
104
+ name: (identifier) @declaration.name) @declaration.const
105
+
106
+ ;; Imports
107
+ (preproc_include) @import.statement
108
+
109
+ ;; Type bindings — parameter annotations
110
+ (parameter_declaration
111
+ type: (_) @type-binding.type
112
+ declarator: (identifier) @type-binding.name) @type-binding.parameter
113
+
114
+ ;; Type bindings — variable with type (init_declarator)
115
+ (declaration
116
+ type: (_) @type-binding.type
117
+ declarator: (init_declarator
118
+ declarator: (identifier) @type-binding.name)) @type-binding.assignment
119
+
120
+ ;; References — free calls
121
+ ;; Note: This also captures calls through function pointer variables (e.g. fp(x))
122
+ ;; since tree-sitter-c produces structurally identical AST nodes for both direct
123
+ ;; function calls and function-pointer-variable calls. A type-based guard to
124
+ ;; distinguish variable-calls from function-calls is not implemented — this is a
125
+ ;; known architectural trade-off shared with the Go resolver. The uniqueness
126
+ ;; constraint in pickUniqueGlobalCallable limits false edge exposure.
127
+ (call_expression
128
+ function: (identifier) @reference.name) @reference.call.free
129
+
130
+ ;; References — member calls via pointer (ptr->func())
131
+ (call_expression
132
+ function: (field_expression
133
+ argument: (_) @reference.receiver
134
+ field: (field_identifier) @reference.name)) @reference.call.member
135
+
136
+ ;; References — field reads
137
+ (field_expression
138
+ argument: (_) @reference.receiver
139
+ field: (field_identifier) @reference.name) @reference.read
140
+
141
+ ;; References — field writes (assignment)
142
+ (assignment_expression
143
+ left: (field_expression
144
+ argument: (_) @reference.receiver
145
+ field: (field_identifier) @reference.name)) @reference.write
146
+ `;
147
+ let _parser = null;
148
+ let _query = null;
149
+ export function getCParser() {
150
+ if (_parser === null) {
151
+ _parser = new Parser();
152
+ _parser.setLanguage(C);
153
+ }
154
+ return _parser;
155
+ }
156
+ export function getCScopeQuery() {
157
+ if (_query === null) {
158
+ _query = new Parser.Query(C, C_SCOPE_QUERY);
159
+ }
160
+ return _query;
161
+ }
@@ -0,0 +1,13 @@
1
+ import type { ScopeResolver } from '../../scope-resolution/contract/scope-resolver.js';
2
+ /**
3
+ * C `ScopeResolver` registered in `SCOPE_RESOLVERS` and consumed by
4
+ * the generic `runScopeResolution` orchestrator (RFC #909 Ring 3).
5
+ *
6
+ * C is a structurally simple language for scope resolution:
7
+ * - No classes (structs are value types, no method dispatch)
8
+ * - No inheritance (no MRO needed beyond the shared first-wins default)
9
+ * - No overloading (arity check is simple: variadic detection only)
10
+ * - `#include` is wildcard import (all symbols from header are visible)
11
+ * - `static` functions are file-local (not exported)
12
+ */
13
+ export declare const cScopeResolver: ScopeResolver;
@@ -0,0 +1,60 @@
1
+ import { SupportedLanguages } from '../../../../_shared/index.js';
2
+ import { buildMro, defaultLinearize } from '../../scope-resolution/passes/mro.js';
3
+ import { populateClassOwnedMembers } from '../../scope-resolution/scope/walkers.js';
4
+ import { cProvider } from '../c-cpp.js';
5
+ import { cArityCompatibility, cMergeBindings, resolveCImportTarget } from './index.js';
6
+ import { scanHeaderFiles } from './header-scan.js';
7
+ import { expandCWildcardNames, isStaticName, clearStaticNames } from './static-linkage.js';
8
+ /**
9
+ * C `ScopeResolver` registered in `SCOPE_RESOLVERS` and consumed by
10
+ * the generic `runScopeResolution` orchestrator (RFC #909 Ring 3).
11
+ *
12
+ * C is a structurally simple language for scope resolution:
13
+ * - No classes (structs are value types, no method dispatch)
14
+ * - No inheritance (no MRO needed beyond the shared first-wins default)
15
+ * - No overloading (arity check is simple: variadic detection only)
16
+ * - `#include` is wildcard import (all symbols from header are visible)
17
+ * - `static` functions are file-local (not exported)
18
+ */
19
+ export const cScopeResolver = {
20
+ language: SupportedLanguages.C,
21
+ languageProvider: cProvider,
22
+ importEdgeReason: 'c-scope: include',
23
+ loadResolutionConfig: (repoPath) => {
24
+ // Clear stale static-linkage data from any previous invocation to
25
+ // prevent cross-repo contamination in server-mode scenarios.
26
+ clearStaticNames();
27
+ return scanHeaderFiles(repoPath);
28
+ },
29
+ resolveImportTarget: (targetRaw, fromFile, allFilePaths, resolutionConfig) => {
30
+ // Augment allFilePaths with .h files discovered via loadResolutionConfig
31
+ // since the phase only passes .c files to the C resolver but #include
32
+ // targets .h files classified as C++ in language detection.
33
+ const headerPaths = resolutionConfig;
34
+ if (headerPaths !== undefined && headerPaths.size > 0) {
35
+ const augmented = new Set(allFilePaths);
36
+ for (const h of headerPaths)
37
+ augmented.add(h);
38
+ return resolveCImportTarget(targetRaw, fromFile, augmented);
39
+ }
40
+ return resolveCImportTarget(targetRaw, fromFile, allFilePaths);
41
+ },
42
+ expandsWildcardTo: (targetModuleScope, parsedFiles) => expandCWildcardNames(targetModuleScope, parsedFiles),
43
+ mergeBindings: (existing, incoming, scopeId) => cMergeBindings(existing, incoming, scopeId),
44
+ arityCompatibility: (callsite, def) => cArityCompatibility(def, callsite),
45
+ buildMro: (graph, parsedFiles, nodeLookup) => buildMro(graph, parsedFiles, nodeLookup, defaultLinearize),
46
+ populateOwners: (parsed) => populateClassOwnedMembers(parsed),
47
+ isSuperReceiver: () => false,
48
+ // C is statically typed — disable field fallback heuristic
49
+ fieldFallbackOnMethodLookup: false,
50
+ // C has no method return types to propagate
51
+ propagatesReturnTypesAcrossImports: false,
52
+ // C #include brings in all symbols — enable global free call fallback
53
+ allowGlobalFreeCallFallback: true,
54
+ // C `static` functions have file-local (translation-unit) linkage —
55
+ // exclude them from global free-call fallback cross-file resolution.
56
+ isFileLocalDef: (def) => {
57
+ const simple = def.qualifiedName?.split('.').pop() ?? def.qualifiedName ?? '';
58
+ return isStaticName(def.filePath, simple);
59
+ },
60
+ };
@@ -0,0 +1,14 @@
1
+ import type { CaptureMatch, ParsedImport, Scope, ScopeId, ScopeTree, TypeRef } from '../../../../_shared/index.js';
2
+ /**
3
+ * C binding scope: always use default auto-hoist (null).
4
+ * C has no self/receiver bindings that need special scoping.
5
+ */
6
+ export declare function cBindingScopeFor(_decl: CaptureMatch, _innermost: Scope, _tree: ScopeTree): ScopeId | null;
7
+ /**
8
+ * C import owning scope: always use default (null).
9
+ */
10
+ export declare function cImportOwningScope(_imp: ParsedImport, _innermost: Scope, _tree: ScopeTree): ScopeId | null;
11
+ /**
12
+ * C receiver binding: always null. C has no methods or receivers.
13
+ */
14
+ export declare function cReceiverBinding(_functionScope: Scope): TypeRef | null;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * C binding scope: always use default auto-hoist (null).
3
+ * C has no self/receiver bindings that need special scoping.
4
+ */
5
+ export function cBindingScopeFor(_decl, _innermost, _tree) {
6
+ return null;
7
+ }
8
+ /**
9
+ * C import owning scope: always use default (null).
10
+ */
11
+ export function cImportOwningScope(_imp, _innermost, _tree) {
12
+ return null;
13
+ }
14
+ /**
15
+ * C receiver binding: always null. C has no methods or receivers.
16
+ */
17
+ export function cReceiverBinding(_functionScope) {
18
+ return null;
19
+ }
@@ -0,0 +1,13 @@
1
+ import type { ParsedFile, ScopeId } from '../../../../_shared/index.js';
2
+ /** Record a symbol name as `static` (file-local linkage) for the given file. */
3
+ export declare function markStaticName(filePath: string, name: string): void;
4
+ /** Check whether a symbol name has `static` linkage in the given file. */
5
+ export declare function isStaticName(filePath: string, name: string): boolean;
6
+ /** Clear tracked static names (for testing). */
7
+ export declare function clearStaticNames(): void;
8
+ /**
9
+ * Return the names visible through a C wildcard import (`#include`).
10
+ * All module-scope defs from the target file are visible EXCEPT those
11
+ * declared with `static` storage class (file-local linkage in C).
12
+ */
13
+ export declare function expandCWildcardNames(targetModuleScope: ScopeId, parsedFiles: readonly ParsedFile[]): readonly string[];
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Per-file set of function names declared with `static` storage class.
3
+ * Populated during `emitCScopeCaptures` and consumed by `expandCWildcardNames`
4
+ * to exclude file-local symbols from cross-file wildcard import visibility.
5
+ *
6
+ * NOTE: module-level state, single-process-single-repo use only.
7
+ * For server-mode or multi-repo-in-one-process use cases, call
8
+ * `clearStaticNames()` at the start of each resolution pass to avoid
9
+ * stale static-linkage data from a previous invocation.
10
+ *
11
+ * Key: filePath, Value: Set of static function names.
12
+ */
13
+ const staticNames = new Map();
14
+ /** Record a symbol name as `static` (file-local linkage) for the given file. */
15
+ export function markStaticName(filePath, name) {
16
+ let names = staticNames.get(filePath);
17
+ if (names === undefined) {
18
+ names = new Set();
19
+ staticNames.set(filePath, names);
20
+ }
21
+ names.add(name);
22
+ }
23
+ /** Check whether a symbol name has `static` linkage in the given file. */
24
+ export function isStaticName(filePath, name) {
25
+ return staticNames.get(filePath)?.has(name) ?? false;
26
+ }
27
+ /** Clear tracked static names (for testing). */
28
+ export function clearStaticNames() {
29
+ staticNames.clear();
30
+ }
31
+ /**
32
+ * Return the names visible through a C wildcard import (`#include`).
33
+ * All module-scope defs from the target file are visible EXCEPT those
34
+ * declared with `static` storage class (file-local linkage in C).
35
+ */
36
+ export function expandCWildcardNames(targetModuleScope, parsedFiles) {
37
+ const target = parsedFiles.find((p) => p.moduleScope === targetModuleScope);
38
+ if (target === undefined)
39
+ return [];
40
+ const seen = new Set();
41
+ const names = [];
42
+ for (const def of target.localDefs) {
43
+ const name = simpleName(def);
44
+ if (name === '')
45
+ continue;
46
+ if (isStaticName(target.filePath, name))
47
+ continue;
48
+ if (seen.has(name))
49
+ continue;
50
+ seen.add(name);
51
+ names.push(name);
52
+ }
53
+ return names;
54
+ }
55
+ function simpleName(def) {
56
+ return def.qualifiedName?.split('.').pop() ?? def.qualifiedName ?? '';
57
+ }
@@ -37,6 +37,7 @@ import { createCallExtractor } from '../call-extractors/generic.js';
37
37
  import { cCallConfig, cppCallConfig } from '../call-extractors/configs/c-cpp.js';
38
38
  import { createHeritageExtractor } from '../heritage-extractors/generic.js';
39
39
  import { stripUeMacros } from '../cpp-ue-preprocessor.js';
40
+ import { emitCScopeCaptures, interpretCImport, interpretCTypeBinding, cArityCompatibility, cBindingScopeFor, cImportOwningScope, cReceiverBinding, } from './c/index.js';
40
41
  const C_BUILT_INS = new Set([
41
42
  'printf',
42
43
  'fprintf',
@@ -338,6 +339,15 @@ export const cProvider = defineLanguage({
338
339
  heritageExtractor: createHeritageExtractor(SupportedLanguages.C),
339
340
  labelOverride: cppLabelOverride,
340
341
  builtInNames: C_BUILT_INS,
342
+ // ── RFC #909 Ring 3: scope-based resolution hooks (RFC §5) ──────────
343
+ emitScopeCaptures: emitCScopeCaptures,
344
+ interpretImport: interpretCImport,
345
+ interpretTypeBinding: interpretCTypeBinding,
346
+ bindingScopeFor: cBindingScopeFor,
347
+ importOwningScope: cImportOwningScope,
348
+ receiverBinding: cReceiverBinding,
349
+ arityCompatibility: cArityCompatibility,
350
+ // mergeBindings + resolveImportTarget live on ScopeResolver (see c/scope-resolver.ts).
341
351
  });
342
352
  export const cppProvider = defineLanguage({
343
353
  id: SupportedLanguages.CPlusPlus,
@@ -22,6 +22,7 @@ import { synthesizeCsharpReceiverBinding } from './receiver-binding.js';
22
22
  import { getCsharpParser, getCsharpScopeQuery } from './query.js';
23
23
  import { recordCacheHit, recordCacheMiss } from './cache-stats.js';
24
24
  import { getTreeSitterBufferSize } from '../../constants.js';
25
+ import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
25
26
  /** Declaration anchors that carry function-like arity metadata. */
26
27
  const FUNCTION_DECL_TAGS = [
27
28
  '@declaration.method',
@@ -75,7 +76,7 @@ export function emitCsharpScopeCaptures(sourceText, _filePath, cachedTree) {
75
76
  // the LanguageProvider contract layer; cast here at the use site.
76
77
  let tree = cachedTree;
77
78
  if (tree === undefined) {
78
- tree = getCsharpParser().parse(sourceText, undefined, {
79
+ tree = parseSourceSafe(getCsharpParser(), sourceText, undefined, {
79
80
  bufferSize: getTreeSitterBufferSize(sourceText),
80
81
  });
81
82
  recordCacheMiss();
@@ -32,6 +32,7 @@
32
32
  */
33
33
  import { getCsharpParser } from './query.js';
34
34
  import { getTreeSitterBufferSize } from '../../constants.js';
35
+ import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
35
36
  /** Build a structural view of a C# file by walking the tree-sitter
36
37
  * AST. Prefers `cachedTree` (handed in via `treeCache`) so we don't
37
38
  * re-parse files the orchestrator already parsed for `extractParsedFile`;
@@ -39,7 +40,7 @@ import { getTreeSitterBufferSize } from '../../constants.js';
39
40
  * shared across calls. */
40
41
  function extractFileStructure(content, cachedTree) {
41
42
  const tree = cachedTree ??
42
- getCsharpParser().parse(content, undefined, {
43
+ parseSourceSafe(getCsharpParser(), content, undefined, {
43
44
  bufferSize: getTreeSitterBufferSize(content),
44
45
  });
45
46
  const namespaces = [];
@@ -332,7 +333,7 @@ export function populateCsharpNamespaceSiblings(parsedFiles, indexes, inputs) {
332
333
  const key = q.includes('.') ? q.slice(q.lastIndexOf('.') + 1) : q;
333
334
  if (key === '')
334
335
  continue;
335
- const arr = defsByName.get(key) ?? [];
336
+ const arr = [...(defsByName.get(key) ?? [])];
336
337
  arr.push(def);
337
338
  defsByName.set(key, arr);
338
339
  }
@@ -6,10 +6,11 @@ import { splitGoImportStatement } from './import-decomposer.js';
6
6
  import { synthesizeGoReceiverBinding } from './receiver-binding.js';
7
7
  import { synthesizeGoTypeBindings } from './type-binding.js';
8
8
  import { getTreeSitterBufferSize } from '../../constants.js';
9
+ import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
9
10
  export function emitGoScopeCaptures(sourceText, _filePath, cachedTree) {
10
11
  let tree = cachedTree;
11
12
  if (tree === undefined) {
12
- tree = getGoParser().parse(sourceText, undefined, {
13
+ tree = parseSourceSafe(getGoParser(), sourceText, undefined, {
13
14
  bufferSize: getTreeSitterBufferSize(sourceText),
14
15
  });
15
16
  recordGoCacheMiss();
@@ -1,5 +1,6 @@
1
1
  import { getGoParser } from './query.js';
2
2
  import { getTreeSitterBufferSize } from '../../constants.js';
3
+ import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
3
4
  export function populateGoRangeBindings(parsedFiles, _indexes, ctx) {
4
5
  const parser = getGoParser();
5
6
  for (const parsed of parsedFiles) {
@@ -8,7 +9,7 @@ export function populateGoRangeBindings(parsedFiles, _indexes, ctx) {
8
9
  continue;
9
10
  const cachedTree = ctx.treeCache?.get(parsed.filePath);
10
11
  const tree = cachedTree ??
11
- parser.parse(sourceText, undefined, {
12
+ parseSourceSafe(parser, sourceText, undefined, {
12
13
  bufferSize: getTreeSitterBufferSize(sourceText),
13
14
  });
14
15
  const moduleScope = parsed.scopes.find((s) => s.kind === 'Module');
@@ -22,6 +22,7 @@ import { synthesizeReceiverTypeBinding } from './receiver-binding.js';
22
22
  import { computePythonArityMetadata } from './arity-metadata.js';
23
23
  import { recordCacheHit, recordCacheMiss } from './cache-stats.js';
24
24
  import { getTreeSitterBufferSize } from '../../constants.js';
25
+ import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
25
26
  import { pythonFunctionDefinitionLabel } from './simple-hooks.js';
26
27
  export function emitPythonScopeCaptures(sourceText, _filePath, cachedTree) {
27
28
  // Skip the parse when the caller (parse phase's ASTCache) already
@@ -32,7 +33,7 @@ export function emitPythonScopeCaptures(sourceText, _filePath, cachedTree) {
32
33
  let tree = cachedTree;
33
34
  if (tree === undefined) {
34
35
  try {
35
- tree = getPythonParser().parse(sourceText, undefined, {
36
+ tree = parseSourceSafe(getPythonParser(), sourceText, undefined, {
36
37
  bufferSize: getTreeSitterBufferSize(sourceText),
37
38
  });
38
39
  }
@@ -31,6 +31,7 @@ import { recordCacheHit, recordCacheMiss } from './cache-stats.js';
31
31
  import { synthesizeTsReceiverBinding } from './receiver-binding.js';
32
32
  import { computeTsArityMetadata } from './arity-metadata.js';
33
33
  import { getTreeSitterBufferSize } from '../../constants.js';
34
+ import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
34
35
  /** tree-sitter-typescript node types for function-like scopes that may
35
36
  * carry a synthesized `this` binding. Kept in sync with the
36
37
  * `@scope.function` patterns in `query.ts`. */
@@ -119,7 +120,7 @@ export function emitTsScopeCaptures(sourceText, filePath, cachedTree) {
119
120
  tree = undefined;
120
121
  }
121
122
  if (tree === undefined) {
122
- tree = getTsParser(filePath).parse(sourceText, undefined, {
123
+ tree = parseSourceSafe(getTsParser(filePath), sourceText, undefined, {
123
124
  bufferSize: getTreeSitterBufferSize(sourceText),
124
125
  });
125
126
  recordCacheMiss();
@@ -5,6 +5,7 @@ import { generateId } from '../../lib/utils.js';
5
5
  import { getLanguageFromFilename, SupportedLanguages } from '../../_shared/index.js';
6
6
  import { extractVueScript, isVueSetupTopLevel } from './vue-sfc-extractor.js';
7
7
  import { yieldToEventLoop } from './utils/event-loop.js';
8
+ import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
8
9
  import { isVerboseIngestionEnabled } from './utils/verbose.js';
9
10
  import { getDefinitionNodeFromCaptures, findEnclosingClassInfo, getLabelFromCaptures, CLASS_CONTAINER_TYPES, } from './utils/ast-helpers.js';
10
11
  import { detectFrameworkFromAST } from './framework-detection.js';
@@ -274,7 +275,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, sco
274
275
  }
275
276
  let tree;
276
277
  try {
277
- tree = parser.parse(parseContent, undefined, {
278
+ tree = parseSourceSafe(parser, parseContent, undefined, {
278
279
  bufferSize: getTreeSitterBufferSize(parseContent),
279
280
  });
280
281
  }
@@ -69,6 +69,7 @@ export const MIGRATED_LANGUAGES = new Set([
69
69
  SupportedLanguages.CSharp,
70
70
  SupportedLanguages.TypeScript,
71
71
  SupportedLanguages.Go,
72
+ SupportedLanguages.C,
72
73
  ]);
73
74
  /**
74
75
  * Return the env-var name that controls a given language's registry-
@@ -414,6 +414,17 @@ export interface ScopeResolver {
414
414
  * but is too loose as a default for strict module systems.
415
415
  */
416
416
  readonly allowGlobalFreeCallFallback?: boolean;
417
+ /**
418
+ * Optional predicate to identify definitions with file-local linkage
419
+ * (e.g. C `static` functions). When provided, `pickUniqueGlobalCallable`
420
+ * excludes defs where `isFileLocalDef(def) === true` and the def lives
421
+ * in a different file from the caller. This prevents the global free-call
422
+ * fallback from creating CALLS edges to file-local symbols that are
423
+ * logically invisible from the caller's translation unit.
424
+ *
425
+ * Languages without file-local linkage semantics leave this undefined.
426
+ */
427
+ readonly isFileLocalDef?: (def: SymbolDefinition) => boolean;
417
428
  /**
418
429
  * Optional post-finalize hook to inject cross-file bindings that
419
430
  * aren't modeled via explicit imports. Runs after
@@ -16,7 +16,7 @@
16
16
  * Generic; promoted from `languages/python/scope-resolver.ts` per the scope-resolution
17
17
  * generalization plan.
18
18
  */
19
- import type { ParsedFile, Reference, ScopeId } from '../../../../_shared/index.js';
19
+ import type { ParsedFile, Reference, ScopeId, SymbolDefinition } from '../../../../_shared/index.js';
20
20
  import type { KnowledgeGraph } from '../../../graph/types.js';
21
21
  import type { ScopeResolutionIndexes } from '../../model/scope-resolution-indexes.js';
22
22
  import type { SemanticModel } from '../../model/semantic-model.js';
@@ -26,4 +26,5 @@ export declare function emitFreeCallFallback(graph: KnowledgeGraph, scopes: Scop
26
26
  readonly bySourceScope: ReadonlyMap<ScopeId, readonly Reference[]>;
27
27
  }, handledSites: Set<string>, model: SemanticModel, workspaceIndex: WorkspaceResolutionIndex, options?: {
28
28
  readonly allowGlobalFallback?: boolean;
29
+ readonly isFileLocalDef?: (def: SymbolDefinition) => boolean;
29
30
  }): number;
@@ -55,7 +55,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
55
55
  // the caller does not import the target package. Same-package calls are
56
56
  // caught by findCallableBindingInScope above before reaching here.
57
57
  if (fnDef === undefined && options.allowGlobalFallback === true) {
58
- fnDef = pickUniqueGlobalCallable(site.name, model, scopes);
58
+ fnDef = pickUniqueGlobalCallable(site.name, model, scopes, parsed.filePath, options.isFileLocalDef);
59
59
  }
60
60
  if (fnDef === undefined)
61
61
  continue;
@@ -88,7 +88,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
88
88
  }
89
89
  return emitted;
90
90
  }
91
- function pickUniqueGlobalCallable(name, model, scopes) {
91
+ function pickUniqueGlobalCallable(name, model, scopes, callerFilePath, isFileLocalDef) {
92
92
  const scopeDefs = [];
93
93
  const scopeSeen = new Set();
94
94
  for (const def of scopes.defs.byId.values()) {
@@ -97,6 +97,11 @@ function pickUniqueGlobalCallable(name, model, scopes) {
97
97
  continue;
98
98
  if (def.type !== 'Function' && def.type !== 'Method' && def.type !== 'Constructor')
99
99
  continue;
100
+ // Skip file-local defs (e.g. C `static` functions) that live in a
101
+ // different file from the caller — they are logically invisible.
102
+ if (isFileLocalDef !== undefined && def.filePath !== callerFilePath && isFileLocalDef(def)) {
103
+ continue;
104
+ }
100
105
  const key = logicalCallableKey(def);
101
106
  if (scopeSeen.has(key))
102
107
  continue;
@@ -109,6 +114,12 @@ function pickUniqueGlobalCallable(name, model, scopes) {
109
114
  const seen = new Set();
110
115
  const push = (pool) => {
111
116
  for (const def of pool) {
117
+ // Apply the same file-local linkage filter as Phase 1 —
118
+ // cross-file static defs must never leak through the
119
+ // SemanticModel fallback path.
120
+ if (isFileLocalDef !== undefined && def.filePath !== callerFilePath && isFileLocalDef(def)) {
121
+ continue;
122
+ }
112
123
  const key = logicalCallableKey(def);
113
124
  if (seen.has(key))
114
125
  continue;
@@ -13,6 +13,7 @@ import { pythonScopeResolver } from '../../languages/python/scope-resolver.js';
13
13
  import { csharpScopeResolver } from '../../languages/csharp/scope-resolver.js';
14
14
  import { typescriptScopeResolver } from '../../languages/typescript/scope-resolver.js';
15
15
  import { goScopeResolver } from '../../languages/go/scope-resolver.js';
16
+ import { cScopeResolver } from '../../languages/c/scope-resolver.js';
16
17
  /** Map of `SupportedLanguages` → `ScopeResolver`. The phase iterates
17
18
  * this map intersected with `MIGRATED_LANGUAGES` (the per-language
18
19
  * flag set) so adding a resolver here without flipping the flag is
@@ -22,4 +23,5 @@ export const SCOPE_RESOLVERS = new Map([
22
23
  [SupportedLanguages.CSharp, csharpScopeResolver],
23
24
  [SupportedLanguages.TypeScript, typescriptScopeResolver],
24
25
  [SupportedLanguages.Go, goScopeResolver],
26
+ [SupportedLanguages.C, cScopeResolver],
25
27
  ]);
@@ -169,7 +169,10 @@ export function runScopeResolution(input, provider) {
169
169
  // ── Phase 4: emit graph edges (LOAD-BEARING ORDER — see I1) ────────────
170
170
  const handledSites = new Set();
171
171
  const receiverExtras = emitReceiverBoundCalls(graph, indexes, parsedFiles, nodeLookup, handledSites, provider, workspaceIndex, readonlyModel);
172
- const freeCallExtras = emitFreeCallFallback(graph, indexes, parsedFiles, nodeLookup, referenceIndex, handledSites, readonlyModel, workspaceIndex, { allowGlobalFallback: provider.allowGlobalFreeCallFallback === true });
172
+ const freeCallExtras = emitFreeCallFallback(graph, indexes, parsedFiles, nodeLookup, referenceIndex, handledSites, readonlyModel, workspaceIndex, {
173
+ allowGlobalFallback: provider.allowGlobalFreeCallFallback === true,
174
+ isFileLocalDef: provider.isFileLocalDef,
175
+ });
173
176
  const { emitted, skipped } = emitReferencesViaLookup(graph, indexes, referenceIndex, nodeLookup, handledSites);
174
177
  const importsEmitted = emitImportEdges(graph, indexes.imports, indexes.scopeTree, provider.importEdgeReason);
175
178
  if (PROF) {
@@ -16,6 +16,7 @@ import { createRequire } from 'node:module';
16
16
  import { SupportedLanguages } from '../../../_shared/index.js';
17
17
  import { getProvider } from '../languages/index.js';
18
18
  import { getTreeSitterBufferSize, getTreeSitterContentByteLength, TREE_SITTER_MAX_BUFFER, } from '../constants.js';
19
+ import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
19
20
  // tree-sitter-swift is an optionalDependency — may not be installed
20
21
  const _require = createRequire(import.meta.url);
21
22
  let Swift = null;
@@ -1026,7 +1027,7 @@ const processFileGroup = (files, language, queryString, result, onFileProcessed)
1026
1027
  clearCaches(); // Reset memoization before each new file
1027
1028
  let tree;
1028
1029
  try {
1029
- tree = parser.parse(parseContent, undefined, {
1030
+ tree = parseSourceSafe(parser, parseContent, undefined, {
1030
1031
  bufferSize: getTreeSitterBufferSize(parseContent),
1031
1032
  });
1032
1033
  }
@@ -1102,6 +1102,14 @@ export const loadVectorExtension = async (targetConn, opts = {}) => {
1102
1102
  const useModuleState = targetConn === undefined;
1103
1103
  if (useModuleState && vectorExtensionLoaded)
1104
1104
  return true;
1105
+ // INSTALL VECTOR crashes with SIGSEGV on Windows: the KuzuDB native extension
1106
+ // installer has an unhandled error path on Windows that raises a fatal signal
1107
+ // that JS try/catch cannot intercept. Skip loading — vector/embedding search
1108
+ // is unavailable but all graph index queries still work. Do NOT set
1109
+ // vectorExtensionLoaded here: the flag means "successfully loaded", and a
1110
+ // subsequent call would otherwise short-circuit to `return true` at the top.
1111
+ if (process.platform === 'win32')
1112
+ return false;
1105
1113
  if (!isVectorExtensionSupportedByPlatform())
1106
1114
  return false;
1107
1115
  const c = targetConn ?? conn;