gitnexus 1.4.10 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +6 -5
  2. package/dist/cli/ai-context.d.ts +4 -1
  3. package/dist/cli/ai-context.js +19 -11
  4. package/dist/cli/analyze.d.ts +6 -0
  5. package/dist/cli/analyze.js +105 -251
  6. package/dist/cli/eval-server.js +20 -11
  7. package/dist/cli/index-repo.js +20 -22
  8. package/dist/cli/index.js +8 -7
  9. package/dist/cli/mcp.js +1 -1
  10. package/dist/cli/serve.js +29 -1
  11. package/dist/cli/setup.js +9 -9
  12. package/dist/cli/skill-gen.js +15 -9
  13. package/dist/cli/wiki.d.ts +2 -0
  14. package/dist/cli/wiki.js +141 -26
  15. package/dist/config/ignore-service.js +102 -22
  16. package/dist/config/supported-languages.d.ts +8 -42
  17. package/dist/config/supported-languages.js +8 -43
  18. package/dist/core/augmentation/engine.js +19 -7
  19. package/dist/core/embeddings/embedder.js +19 -15
  20. package/dist/core/embeddings/embedding-pipeline.js +6 -6
  21. package/dist/core/embeddings/http-client.js +3 -3
  22. package/dist/core/embeddings/text-generator.js +9 -24
  23. package/dist/core/embeddings/types.d.ts +1 -1
  24. package/dist/core/embeddings/types.js +1 -7
  25. package/dist/core/graph/graph.js +6 -2
  26. package/dist/core/graph/types.d.ts +9 -59
  27. package/dist/core/ingestion/ast-cache.js +3 -3
  28. package/dist/core/ingestion/call-processor.d.ts +20 -2
  29. package/dist/core/ingestion/call-processor.js +347 -144
  30. package/dist/core/ingestion/call-routing.js +10 -4
  31. package/dist/core/ingestion/call-sites/extract-language-call-site.d.ts +10 -0
  32. package/dist/core/ingestion/call-sites/extract-language-call-site.js +22 -0
  33. package/dist/core/ingestion/call-sites/java.d.ts +9 -0
  34. package/dist/core/ingestion/call-sites/java.js +30 -0
  35. package/dist/core/ingestion/cluster-enricher.js +6 -8
  36. package/dist/core/ingestion/cobol/cobol-copy-expander.js +10 -3
  37. package/dist/core/ingestion/cobol/cobol-preprocessor.js +287 -81
  38. package/dist/core/ingestion/cobol/jcl-parser.js +1 -1
  39. package/dist/core/ingestion/cobol/jcl-processor.js +1 -1
  40. package/dist/core/ingestion/cobol-processor.js +102 -56
  41. package/dist/core/ingestion/community-processor.js +21 -15
  42. package/dist/core/ingestion/entry-point-scoring.d.ts +1 -1
  43. package/dist/core/ingestion/entry-point-scoring.js +5 -6
  44. package/dist/core/ingestion/export-detection.js +32 -9
  45. package/dist/core/ingestion/field-extractor.d.ts +1 -1
  46. package/dist/core/ingestion/field-extractors/configs/c-cpp.js +8 -12
  47. package/dist/core/ingestion/field-extractors/configs/csharp.js +45 -2
  48. package/dist/core/ingestion/field-extractors/configs/dart.js +5 -3
  49. package/dist/core/ingestion/field-extractors/configs/go.js +3 -7
  50. package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +5 -0
  51. package/dist/core/ingestion/field-extractors/configs/helpers.js +14 -0
  52. package/dist/core/ingestion/field-extractors/configs/jvm.js +7 -7
  53. package/dist/core/ingestion/field-extractors/configs/php.js +9 -11
  54. package/dist/core/ingestion/field-extractors/configs/python.js +1 -1
  55. package/dist/core/ingestion/field-extractors/configs/ruby.js +4 -3
  56. package/dist/core/ingestion/field-extractors/configs/rust.js +2 -5
  57. package/dist/core/ingestion/field-extractors/configs/swift.js +9 -7
  58. package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +2 -6
  59. package/dist/core/ingestion/field-extractors/generic.d.ts +5 -2
  60. package/dist/core/ingestion/field-extractors/generic.js +6 -0
  61. package/dist/core/ingestion/field-extractors/typescript.d.ts +1 -1
  62. package/dist/core/ingestion/field-extractors/typescript.js +1 -1
  63. package/dist/core/ingestion/field-types.d.ts +4 -2
  64. package/dist/core/ingestion/filesystem-walker.js +3 -3
  65. package/dist/core/ingestion/framework-detection.d.ts +1 -1
  66. package/dist/core/ingestion/framework-detection.js +355 -85
  67. package/dist/core/ingestion/heritage-processor.d.ts +24 -0
  68. package/dist/core/ingestion/heritage-processor.js +99 -8
  69. package/dist/core/ingestion/import-processor.js +44 -15
  70. package/dist/core/ingestion/import-resolvers/csharp.js +7 -3
  71. package/dist/core/ingestion/import-resolvers/dart.js +1 -1
  72. package/dist/core/ingestion/import-resolvers/go.js +4 -2
  73. package/dist/core/ingestion/import-resolvers/jvm.js +4 -4
  74. package/dist/core/ingestion/import-resolvers/php.js +4 -4
  75. package/dist/core/ingestion/import-resolvers/python.js +1 -1
  76. package/dist/core/ingestion/import-resolvers/rust.js +9 -3
  77. package/dist/core/ingestion/import-resolvers/standard.d.ts +1 -1
  78. package/dist/core/ingestion/import-resolvers/standard.js +6 -5
  79. package/dist/core/ingestion/import-resolvers/swift.js +2 -1
  80. package/dist/core/ingestion/import-resolvers/utils.js +26 -7
  81. package/dist/core/ingestion/language-config.js +5 -4
  82. package/dist/core/ingestion/language-provider.d.ts +7 -2
  83. package/dist/core/ingestion/languages/c-cpp.js +106 -21
  84. package/dist/core/ingestion/languages/cobol.js +1 -1
  85. package/dist/core/ingestion/languages/csharp.js +96 -19
  86. package/dist/core/ingestion/languages/dart.js +23 -7
  87. package/dist/core/ingestion/languages/go.js +1 -1
  88. package/dist/core/ingestion/languages/index.d.ts +1 -1
  89. package/dist/core/ingestion/languages/index.js +2 -3
  90. package/dist/core/ingestion/languages/java.js +4 -1
  91. package/dist/core/ingestion/languages/kotlin.js +60 -13
  92. package/dist/core/ingestion/languages/php.js +102 -25
  93. package/dist/core/ingestion/languages/python.js +28 -5
  94. package/dist/core/ingestion/languages/ruby.js +56 -14
  95. package/dist/core/ingestion/languages/rust.js +55 -11
  96. package/dist/core/ingestion/languages/swift.js +112 -27
  97. package/dist/core/ingestion/languages/typescript.js +95 -19
  98. package/dist/core/ingestion/markdown-processor.js +5 -5
  99. package/dist/core/ingestion/method-extractors/configs/csharp.d.ts +2 -0
  100. package/dist/core/ingestion/method-extractors/configs/csharp.js +283 -0
  101. package/dist/core/ingestion/method-extractors/configs/jvm.d.ts +3 -0
  102. package/dist/core/ingestion/method-extractors/configs/jvm.js +326 -0
  103. package/dist/core/ingestion/method-extractors/generic.d.ts +5 -0
  104. package/dist/core/ingestion/method-extractors/generic.js +137 -0
  105. package/dist/core/ingestion/method-types.d.ts +61 -0
  106. package/dist/core/ingestion/method-types.js +2 -0
  107. package/dist/core/ingestion/mro-processor.d.ts +1 -1
  108. package/dist/core/ingestion/mro-processor.js +12 -8
  109. package/dist/core/ingestion/named-binding-processor.js +2 -2
  110. package/dist/core/ingestion/named-bindings/rust.js +3 -1
  111. package/dist/core/ingestion/parsing-processor.js +74 -24
  112. package/dist/core/ingestion/pipeline.d.ts +2 -1
  113. package/dist/core/ingestion/pipeline.js +208 -102
  114. package/dist/core/ingestion/process-processor.js +12 -10
  115. package/dist/core/ingestion/resolution-context.js +3 -3
  116. package/dist/core/ingestion/route-extractors/middleware.js +31 -7
  117. package/dist/core/ingestion/route-extractors/php.js +2 -1
  118. package/dist/core/ingestion/route-extractors/response-shapes.js +8 -4
  119. package/dist/core/ingestion/structure-processor.d.ts +1 -1
  120. package/dist/core/ingestion/structure-processor.js +4 -4
  121. package/dist/core/ingestion/symbol-table.d.ts +1 -1
  122. package/dist/core/ingestion/symbol-table.js +22 -6
  123. package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -1
  124. package/dist/core/ingestion/tree-sitter-queries.js +1 -1
  125. package/dist/core/ingestion/type-env.d.ts +2 -2
  126. package/dist/core/ingestion/type-env.js +75 -50
  127. package/dist/core/ingestion/type-extractors/c-cpp.js +33 -30
  128. package/dist/core/ingestion/type-extractors/csharp.js +24 -14
  129. package/dist/core/ingestion/type-extractors/dart.js +6 -8
  130. package/dist/core/ingestion/type-extractors/go.js +7 -6
  131. package/dist/core/ingestion/type-extractors/jvm.js +10 -21
  132. package/dist/core/ingestion/type-extractors/php.js +26 -13
  133. package/dist/core/ingestion/type-extractors/python.js +11 -15
  134. package/dist/core/ingestion/type-extractors/ruby.js +8 -3
  135. package/dist/core/ingestion/type-extractors/rust.js +6 -8
  136. package/dist/core/ingestion/type-extractors/shared.js +134 -50
  137. package/dist/core/ingestion/type-extractors/swift.js +16 -13
  138. package/dist/core/ingestion/type-extractors/typescript.js +23 -15
  139. package/dist/core/ingestion/utils/ast-helpers.d.ts +8 -8
  140. package/dist/core/ingestion/utils/ast-helpers.js +72 -35
  141. package/dist/core/ingestion/utils/call-analysis.d.ts +2 -0
  142. package/dist/core/ingestion/utils/call-analysis.js +96 -49
  143. package/dist/core/ingestion/utils/event-loop.js +1 -1
  144. package/dist/core/ingestion/workers/parse-worker.d.ts +7 -2
  145. package/dist/core/ingestion/workers/parse-worker.js +364 -84
  146. package/dist/core/ingestion/workers/worker-pool.js +5 -10
  147. package/dist/core/lbug/csv-generator.js +54 -15
  148. package/dist/core/lbug/lbug-adapter.d.ts +5 -0
  149. package/dist/core/lbug/lbug-adapter.js +86 -23
  150. package/dist/core/lbug/schema.d.ts +3 -6
  151. package/dist/core/lbug/schema.js +6 -30
  152. package/dist/core/run-analyze.d.ts +49 -0
  153. package/dist/core/run-analyze.js +257 -0
  154. package/dist/core/tree-sitter/parser-loader.d.ts +1 -1
  155. package/dist/core/tree-sitter/parser-loader.js +1 -1
  156. package/dist/core/wiki/cursor-client.js +2 -7
  157. package/dist/core/wiki/generator.js +38 -23
  158. package/dist/core/wiki/graph-queries.js +10 -10
  159. package/dist/core/wiki/html-viewer.js +7 -3
  160. package/dist/core/wiki/llm-client.d.ts +23 -2
  161. package/dist/core/wiki/llm-client.js +96 -26
  162. package/dist/core/wiki/prompts.js +7 -6
  163. package/dist/mcp/core/embedder.js +1 -1
  164. package/dist/mcp/core/lbug-adapter.d.ts +4 -1
  165. package/dist/mcp/core/lbug-adapter.js +17 -7
  166. package/dist/mcp/local/local-backend.js +247 -95
  167. package/dist/mcp/resources.js +14 -6
  168. package/dist/mcp/server.js +13 -5
  169. package/dist/mcp/staleness.js +5 -1
  170. package/dist/mcp/tools.js +100 -23
  171. package/dist/server/analyze-job.d.ts +53 -0
  172. package/dist/server/analyze-job.js +146 -0
  173. package/dist/server/analyze-worker.d.ts +13 -0
  174. package/dist/server/analyze-worker.js +59 -0
  175. package/dist/server/api.js +795 -44
  176. package/dist/server/git-clone.d.ts +25 -0
  177. package/dist/server/git-clone.js +91 -0
  178. package/dist/storage/git.js +1 -3
  179. package/dist/storage/repo-manager.d.ts +5 -2
  180. package/dist/storage/repo-manager.js +4 -4
  181. package/dist/types/pipeline.d.ts +1 -21
  182. package/dist/types/pipeline.js +1 -18
  183. package/hooks/claude/gitnexus-hook.cjs +52 -22
  184. package/package.json +3 -2
  185. package/dist/core/ingestion/utils/language-detection.d.ts +0 -9
  186. package/dist/core/ingestion/utils/language-detection.js +0 -70
@@ -1,6 +1,6 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/csharp.ts
2
- import { SupportedLanguages } from '../../../../config/supported-languages.js';
3
- import { findVisibility, hasKeyword, hasModifier } from './helpers.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
+ import { findVisibility, hasKeyword, hasModifier, collectModifierTexts } from './helpers.js';
4
4
  import { extractSimpleTypeName } from '../../type-extractors/shared.js';
5
5
  const CSHARP_VIS = new Set(['public', 'private', 'protected', 'internal']);
6
6
  /**
@@ -62,6 +62,12 @@ export const csharpConfig = {
62
62
  return undefined;
63
63
  },
64
64
  extractVisibility(node) {
65
+ // Detect compound C# visibilities: protected internal, private protected
66
+ const mods = collectModifierTexts(node);
67
+ if (mods.has('protected') && mods.has('internal'))
68
+ return 'protected internal';
69
+ if (mods.has('private') && mods.has('protected'))
70
+ return 'private protected';
65
71
  return findVisibility(node, CSHARP_VIS, 'private', 'modifier');
66
72
  },
67
73
  isStatic(node) {
@@ -70,4 +76,41 @@ export const csharpConfig = {
70
76
  isReadonly(node) {
71
77
  return hasKeyword(node, 'readonly') || hasModifier(node, 'modifier', 'readonly');
72
78
  },
79
+ extractPrimaryFields(ownerNode, context) {
80
+ // C# record positional parameters become public init-only properties.
81
+ // C# 12 class primary constructor parameters are captured as private fields.
82
+ // The parameter_list has no field name — find it by type.
83
+ let paramList = null;
84
+ for (let i = 0; i < ownerNode.namedChildCount; i++) {
85
+ const child = ownerNode.namedChild(i);
86
+ if (child?.type === 'parameter_list') {
87
+ paramList = child;
88
+ break;
89
+ }
90
+ }
91
+ if (!paramList)
92
+ return [];
93
+ const isRecord = ownerNode.type === 'record_declaration';
94
+ const fields = [];
95
+ for (let i = 0; i < paramList.namedChildCount; i++) {
96
+ const param = paramList.namedChild(i);
97
+ if (!param || param.type !== 'parameter')
98
+ continue;
99
+ const nameNode = param.childForFieldName('name');
100
+ const typeNode = param.childForFieldName('type');
101
+ if (!nameNode)
102
+ continue;
103
+ fields.push({
104
+ name: nameNode.text,
105
+ type: typeNode ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null) : null,
106
+ // Record params are public init-only properties; class params are private captured fields
107
+ visibility: isRecord ? 'public' : 'private',
108
+ isStatic: false,
109
+ isReadonly: isRecord, // record properties are init-only (readonly)
110
+ sourceFile: context.filePath,
111
+ line: param.startPosition.row + 1,
112
+ });
113
+ }
114
+ return fields;
115
+ },
73
116
  };
@@ -1,5 +1,5 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/dart.ts
2
- import { SupportedLanguages } from '../../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  import { hasKeyword } from './helpers.js';
4
4
  import { extractSimpleTypeName } from '../../type-extractors/shared.js';
5
5
  /**
@@ -42,8 +42,10 @@ export const dartConfig = {
42
42
  // declaration > type_identifier (first named child usually)
43
43
  for (let i = 0; i < node.namedChildCount; i++) {
44
44
  const child = node.namedChild(i);
45
- if (child && (child.type === 'type_identifier' || child.type === 'generic_type'
46
- || child.type === 'function_type')) {
45
+ if (child &&
46
+ (child.type === 'type_identifier' ||
47
+ child.type === 'generic_type' ||
48
+ child.type === 'function_type')) {
47
49
  return extractSimpleTypeName(child) ?? child.text?.trim();
48
50
  }
49
51
  }
@@ -1,5 +1,5 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/go.ts
2
- import { SupportedLanguages } from '../../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  import { extractSimpleTypeName } from '../../type-extractors/shared.js';
4
4
  /**
5
5
  * Go field extraction config.
@@ -12,9 +12,7 @@ import { extractSimpleTypeName } from '../../type-extractors/shared.js';
12
12
  */
13
13
  export const goConfig = {
14
14
  language: SupportedLanguages.Go,
15
- typeDeclarationNodes: [
16
- 'type_declaration',
17
- ],
15
+ typeDeclarationNodes: ['type_declaration'],
18
16
  fieldNodeTypes: ['field_declaration'],
19
17
  bodyNodeTypes: ['field_declaration_list'],
20
18
  defaultVisibility: 'package',
@@ -49,9 +47,7 @@ export const goConfig = {
49
47
  const text = name?.text;
50
48
  if (text && text.length > 0) {
51
49
  const first = text.charAt(0);
52
- return first === first.toUpperCase() && first !== first.toLowerCase()
53
- ? 'public'
54
- : 'package';
50
+ return first === first.toUpperCase() && first !== first.toLowerCase() ? 'public' : 'package';
55
51
  }
56
52
  return 'package';
57
53
  },
@@ -42,3 +42,8 @@ export declare function typeFromAnnotation(node: SyntaxNode): string | undefined
42
42
  * and return its text via extractSimpleTypeName.
43
43
  */
44
44
  export declare function typeFromDescendant(node: SyntaxNode, types: ReadonlySet<string>): string | undefined;
45
+ /**
46
+ * Collect all modifier keyword texts from a declaration node's named `modifier` children.
47
+ * Used by C# configs to detect compound visibilities (protected internal, private protected).
48
+ */
49
+ export declare function collectModifierTexts(node: SyntaxNode): Set<string>;
@@ -132,3 +132,17 @@ export function typeFromDescendant(node, types) {
132
132
  }
133
133
  return undefined;
134
134
  }
135
+ /**
136
+ * Collect all modifier keyword texts from a declaration node's named `modifier` children.
137
+ * Used by C# configs to detect compound visibilities (protected internal, private protected).
138
+ */
139
+ export function collectModifierTexts(node) {
140
+ const result = new Set();
141
+ for (let i = 0; i < node.namedChildCount; i++) {
142
+ const child = node.namedChild(i);
143
+ if (child && child.type === 'modifier') {
144
+ result.add(child.text.trim());
145
+ }
146
+ }
147
+ return result;
148
+ }
@@ -1,5 +1,5 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/jvm.ts
2
- import { SupportedLanguages } from '../../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  import { findVisibility, hasKeyword, hasModifier, typeFromField } from './helpers.js';
4
4
  import { extractSimpleTypeName } from '../../type-extractors/shared.js';
5
5
  // ---------------------------------------------------------------------------
@@ -62,10 +62,7 @@ export const javaConfig = {
62
62
  const KOTLIN_VIS = new Set(['public', 'private', 'protected', 'internal']);
63
63
  export const kotlinConfig = {
64
64
  language: SupportedLanguages.Kotlin,
65
- typeDeclarationNodes: [
66
- 'class_declaration',
67
- 'object_declaration',
68
- ],
65
+ typeDeclarationNodes: ['class_declaration', 'object_declaration'],
69
66
  fieldNodeTypes: ['property_declaration'],
70
67
  bodyNodeTypes: ['class_body'],
71
68
  defaultVisibility: 'public',
@@ -92,8 +89,11 @@ export const kotlinConfig = {
92
89
  if (child?.type === 'variable_declaration') {
93
90
  for (let j = 0; j < child.namedChildCount; j++) {
94
91
  const t = child.namedChild(j);
95
- if (t && (t.type === 'user_type' || t.type === 'type_identifier'
96
- || t.type === 'nullable_type' || t.type === 'generic_type')) {
92
+ if (t &&
93
+ (t.type === 'user_type' ||
94
+ t.type === 'type_identifier' ||
95
+ t.type === 'nullable_type' ||
96
+ t.type === 'generic_type')) {
97
97
  return extractSimpleTypeName(t) ?? t.text?.trim();
98
98
  }
99
99
  }
@@ -1,5 +1,5 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/php.ts
2
- import { SupportedLanguages } from '../../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  import { findVisibility, hasKeyword } from './helpers.js';
4
4
  import { extractSimpleTypeName } from '../../type-extractors/shared.js';
5
5
  const PHP_VIS = new Set(['public', 'private', 'protected']);
@@ -11,11 +11,7 @@ const PHP_VIS = new Set(['public', 'private', 'protected']);
11
11
  */
12
12
  export const phpConfig = {
13
13
  language: SupportedLanguages.PHP,
14
- typeDeclarationNodes: [
15
- 'class_declaration',
16
- 'interface_declaration',
17
- 'trait_declaration',
18
- ],
14
+ typeDeclarationNodes: ['class_declaration', 'interface_declaration', 'trait_declaration'],
19
15
  fieldNodeTypes: ['property_declaration'],
20
16
  bodyNodeTypes: ['declaration_list'],
21
17
  defaultVisibility: 'public',
@@ -24,8 +20,7 @@ export const phpConfig = {
24
20
  for (let i = 0; i < node.namedChildCount; i++) {
25
21
  const child = node.namedChild(i);
26
22
  if (child?.type === 'property_element') {
27
- const varName = child.childForFieldName('name')
28
- ?? child.firstNamedChild;
23
+ const varName = child.childForFieldName('name') ?? child.firstNamedChild;
29
24
  if (varName) {
30
25
  // strip leading $ from PHP variable names
31
26
  const text = varName.text;
@@ -47,9 +42,12 @@ export const phpConfig = {
47
42
  const child = node.namedChild(i);
48
43
  if (!child)
49
44
  continue;
50
- if (child.type === 'union_type' || child.type === 'named_type'
51
- || child.type === 'optional_type' || child.type === 'primitive_type'
52
- || child.type === 'intersection_type' || child.type === 'nullable_type') {
45
+ if (child.type === 'union_type' ||
46
+ child.type === 'named_type' ||
47
+ child.type === 'optional_type' ||
48
+ child.type === 'primitive_type' ||
49
+ child.type === 'intersection_type' ||
50
+ child.type === 'nullable_type') {
53
51
  return extractSimpleTypeName(child) ?? child.text?.trim();
54
52
  }
55
53
  }
@@ -1,5 +1,5 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/python.ts
2
- import { SupportedLanguages } from '../../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  import { extractSimpleTypeName } from '../../type-extractors/shared.js';
4
4
  /**
5
5
  * Python field extraction config.
@@ -1,5 +1,5 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/ruby.ts
2
- import { SupportedLanguages } from '../../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  /**
4
4
  * Collect all field names declared by an `attr_accessor`, `attr_reader`, or
5
5
  * `attr_writer` call node. A single call may list multiple symbols:
@@ -10,8 +10,9 @@ function extractAttrNames(node) {
10
10
  if (!method)
11
11
  return [];
12
12
  const methodName = method.text;
13
- if (methodName !== 'attr_accessor' && methodName !== 'attr_reader'
14
- && methodName !== 'attr_writer') {
13
+ if (methodName !== 'attr_accessor' &&
14
+ methodName !== 'attr_reader' &&
15
+ methodName !== 'attr_writer') {
15
16
  return [];
16
17
  }
17
18
  const args = node.childForFieldName('arguments');
@@ -1,5 +1,5 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/rust.ts
2
- import { SupportedLanguages } from '../../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  import { extractSimpleTypeName } from '../../type-extractors/shared.js';
4
4
  import { hasKeyword } from './helpers.js';
5
5
  /**
@@ -11,10 +11,7 @@ import { hasKeyword } from './helpers.js';
11
11
  */
12
12
  export const rustConfig = {
13
13
  language: SupportedLanguages.Rust,
14
- typeDeclarationNodes: [
15
- 'struct_item',
16
- 'enum_item',
17
- ],
14
+ typeDeclarationNodes: ['struct_item', 'enum_item'],
18
15
  fieldNodeTypes: ['field_declaration'],
19
16
  bodyNodeTypes: ['field_declaration_list'],
20
17
  defaultVisibility: 'private',
@@ -1,8 +1,14 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/swift.ts
2
- import { SupportedLanguages } from '../../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  import { hasKeyword, findVisibility } from './helpers.js';
4
4
  import { extractSimpleTypeName } from '../../type-extractors/shared.js';
5
- const SWIFT_VIS = new Set(['public', 'private', 'fileprivate', 'internal', 'open']);
5
+ const SWIFT_VIS = new Set([
6
+ 'public',
7
+ 'private',
8
+ 'fileprivate',
9
+ 'internal',
10
+ 'open',
11
+ ]);
6
12
  /**
7
13
  * Swift field extraction config.
8
14
  *
@@ -11,11 +17,7 @@ const SWIFT_VIS = new Set(['public', 'private', 'fileprivate', 'internal', 'open
11
17
  */
12
18
  export const swiftConfig = {
13
19
  language: SupportedLanguages.Swift,
14
- typeDeclarationNodes: [
15
- 'class_declaration',
16
- 'struct_declaration',
17
- 'protocol_declaration',
18
- ],
20
+ typeDeclarationNodes: ['class_declaration', 'struct_declaration', 'protocol_declaration'],
19
21
  fieldNodeTypes: ['property_declaration'],
20
22
  bodyNodeTypes: ['class_body', 'protocol_body'],
21
23
  defaultVisibility: 'internal',
@@ -1,5 +1,5 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/typescript-javascript.ts
2
- import { SupportedLanguages } from '../../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  import { hasKeyword, findVisibility, typeFromAnnotation } from './helpers.js';
4
4
  const VISIBILITY_KEYWORDS = new Set(['public', 'private', 'protected']);
5
5
  const shared = {
@@ -8,11 +8,7 @@ const shared = {
8
8
  'abstract_class_declaration',
9
9
  'interface_declaration',
10
10
  ],
11
- fieldNodeTypes: [
12
- 'public_field_definition',
13
- 'property_signature',
14
- 'field_definition',
15
- ],
11
+ fieldNodeTypes: ['public_field_definition', 'property_signature', 'field_definition'],
16
12
  bodyNodeTypes: ['class_body', 'interface_body', 'object_type'],
17
13
  defaultVisibility: 'public',
18
14
  extractName(node) {
@@ -6,9 +6,9 @@
6
6
  * BaseFieldExtractor whose behaviour is entirely driven by FieldExtractionConfig.
7
7
  */
8
8
  import type { SyntaxNode } from '../utils/ast-helpers.js';
9
- import { SupportedLanguages } from '../../../config/supported-languages.js';
9
+ import { SupportedLanguages } from 'gitnexus-shared';
10
10
  import type { FieldExtractor } from '../field-extractor.js';
11
- import type { FieldVisibility } from '../field-types.js';
11
+ import type { FieldExtractorContext, FieldInfo, FieldVisibility } from '../field-types.js';
12
12
  export interface FieldExtractionConfig {
13
13
  language: SupportedLanguages;
14
14
  /** AST node types that are class/struct/interface declarations */
@@ -39,6 +39,9 @@ export interface FieldExtractionConfig {
39
39
  isStatic: (node: SyntaxNode) => boolean;
40
40
  /** Check if a field is readonly/final/const */
41
41
  isReadonly: (node: SyntaxNode) => boolean;
42
+ /** Extract fields from primary constructor parameters on the owner node itself
43
+ * (e.g. C# record positional parameters, C# 12 class primary constructors). */
44
+ extractPrimaryFields?: (ownerNode: SyntaxNode, context: FieldExtractorContext) => FieldInfo[];
42
45
  }
43
46
  /**
44
47
  * Create a FieldExtractor from a declarative config.
@@ -31,6 +31,12 @@ export function createFieldExtractor(config) {
31
31
  for (const body of bodies) {
32
32
  this.extractFieldsFromBody(body, context, fields);
33
33
  }
34
+ // Extract fields from primary constructor parameters (e.g. C# records)
35
+ if (config.extractPrimaryFields) {
36
+ const primaryFields = config.extractPrimaryFields(node, context);
37
+ for (const f of primaryFields)
38
+ fields.push(f);
39
+ }
34
40
  return { ownerFqn, fields, nestedTypes: [] };
35
41
  }
36
42
  // ------------------------------------------------------------------
@@ -1,5 +1,5 @@
1
1
  import type { SyntaxNode } from '../utils/ast-helpers.js';
2
- import { SupportedLanguages } from '../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  import { BaseFieldExtractor } from '../field-extractor.js';
4
4
  import type { FieldExtractorContext, ExtractedFields, FieldVisibility } from '../field-types.js';
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/typescript.ts
2
- import { SupportedLanguages } from '../../../config/supported-languages.js';
2
+ import { SupportedLanguages } from 'gitnexus-shared';
3
3
  import { BaseFieldExtractor } from '../field-extractor.js';
4
4
  /**
5
5
  * Hand-written TypeScript field extractor.
@@ -1,15 +1,17 @@
1
1
  import type { TypeEnvironment } from './type-env.js';
2
2
  import type { SymbolTable } from './symbol-table.js';
3
- import { SupportedLanguages } from '../../config/supported-languages.js';
3
+ import { SupportedLanguages } from 'gitnexus-shared';
4
4
  /**
5
5
  * Visibility levels used across all supported languages.
6
6
  * - public / private / protected: universal modifiers
7
7
  * - internal: C#, Kotlin (assembly/module scope)
8
+ * - protected internal: C# (accessible by same assembly OR derived classes)
9
+ * - private protected: C# (accessible by derived classes within same assembly)
8
10
  * - package: Java (package-private, no keyword)
9
11
  * - fileprivate: Swift (file scope)
10
12
  * - open: Swift (subclassable across modules)
11
13
  */
12
- export type FieldVisibility = 'public' | 'private' | 'protected' | 'internal' | 'package' | 'fileprivate' | 'open';
14
+ export type FieldVisibility = 'public' | 'private' | 'protected' | 'internal' | 'protected internal' | 'private protected' | 'package' | 'fileprivate' | 'open';
13
15
  /**
14
16
  * Represents a field or property within a class/struct/interface
15
17
  */
@@ -74,8 +74,8 @@ export const readFileContents = async (repoPath, relativePaths) => {
74
74
  */
75
75
  export const walkRepository = async (repoPath, onProgress) => {
76
76
  const scanned = await walkRepositoryPaths(repoPath, onProgress);
77
- const contents = await readFileContents(repoPath, scanned.map(f => f.path));
77
+ const contents = await readFileContents(repoPath, scanned.map((f) => f.path));
78
78
  return scanned
79
- .filter(f => contents.has(f.path))
80
- .map(f => ({ path: f.path, content: contents.get(f.path) }));
79
+ .filter((f) => contents.has(f.path))
80
+ .map((f) => ({ path: f.path, content: contents.get(f.path) }));
81
81
  };
@@ -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
  export interface FrameworkHint {
14
14
  framework: string;
15
15
  entryPointMultiplier: number;