gitnexus 1.5.3 → 1.6.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 (304) hide show
  1. package/README.md +10 -0
  2. package/dist/_shared/graph/types.d.ts +1 -1
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +1 -0
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/language-detection.d.ts.map +1 -1
  7. package/dist/_shared/language-detection.js +2 -0
  8. package/dist/_shared/language-detection.js.map +1 -1
  9. package/dist/_shared/languages.d.ts +1 -0
  10. package/dist/_shared/languages.d.ts.map +1 -1
  11. package/dist/_shared/languages.js +1 -0
  12. package/dist/_shared/languages.js.map +1 -1
  13. package/dist/_shared/lbug/schema-constants.d.ts +1 -1
  14. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  15. package/dist/_shared/lbug/schema-constants.js +3 -1
  16. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  17. package/dist/_shared/mro-strategy.d.ts +19 -0
  18. package/dist/_shared/mro-strategy.d.ts.map +1 -0
  19. package/dist/_shared/mro-strategy.js +2 -0
  20. package/dist/_shared/mro-strategy.js.map +1 -0
  21. package/dist/cli/ai-context.d.ts +1 -0
  22. package/dist/cli/ai-context.js +28 -4
  23. package/dist/cli/analyze.d.ts +2 -0
  24. package/dist/cli/analyze.js +30 -4
  25. package/dist/cli/group.d.ts +2 -0
  26. package/dist/cli/group.js +233 -0
  27. package/dist/cli/index.js +3 -0
  28. package/dist/cli/serve.js +4 -1
  29. package/dist/cli/setup.js +34 -3
  30. package/dist/config/ignore-service.js +8 -3
  31. package/dist/core/augmentation/engine.js +1 -1
  32. package/dist/core/git-staleness.d.ts +13 -0
  33. package/dist/core/git-staleness.js +29 -0
  34. package/dist/core/group/bridge-db.d.ts +82 -0
  35. package/dist/core/group/bridge-db.js +460 -0
  36. package/dist/core/group/bridge-schema.d.ts +27 -0
  37. package/dist/core/group/bridge-schema.js +55 -0
  38. package/dist/core/group/config-parser.d.ts +3 -0
  39. package/dist/core/group/config-parser.js +83 -0
  40. package/dist/core/group/contract-extractor.d.ts +7 -0
  41. package/dist/core/group/contract-extractor.js +1 -0
  42. package/dist/core/group/extractors/fs-utils.d.ts +10 -0
  43. package/dist/core/group/extractors/fs-utils.js +24 -0
  44. package/dist/core/group/extractors/grpc-extractor.d.ts +25 -0
  45. package/dist/core/group/extractors/grpc-extractor.js +386 -0
  46. package/dist/core/group/extractors/grpc-patterns/go.d.ts +2 -0
  47. package/dist/core/group/extractors/grpc-patterns/go.js +97 -0
  48. package/dist/core/group/extractors/grpc-patterns/index.d.ts +19 -0
  49. package/dist/core/group/extractors/grpc-patterns/index.js +46 -0
  50. package/dist/core/group/extractors/grpc-patterns/java.d.ts +2 -0
  51. package/dist/core/group/extractors/grpc-patterns/java.js +173 -0
  52. package/dist/core/group/extractors/grpc-patterns/node.d.ts +4 -0
  53. package/dist/core/group/extractors/grpc-patterns/node.js +290 -0
  54. package/dist/core/group/extractors/grpc-patterns/proto.d.ts +9 -0
  55. package/dist/core/group/extractors/grpc-patterns/proto.js +134 -0
  56. package/dist/core/group/extractors/grpc-patterns/python.d.ts +2 -0
  57. package/dist/core/group/extractors/grpc-patterns/python.js +67 -0
  58. package/dist/core/group/extractors/grpc-patterns/types.d.ts +50 -0
  59. package/dist/core/group/extractors/grpc-patterns/types.js +1 -0
  60. package/dist/core/group/extractors/http-patterns/go.d.ts +2 -0
  61. package/dist/core/group/extractors/http-patterns/go.js +215 -0
  62. package/dist/core/group/extractors/http-patterns/index.d.ts +17 -0
  63. package/dist/core/group/extractors/http-patterns/index.js +44 -0
  64. package/dist/core/group/extractors/http-patterns/java.d.ts +2 -0
  65. package/dist/core/group/extractors/http-patterns/java.js +253 -0
  66. package/dist/core/group/extractors/http-patterns/node.d.ts +4 -0
  67. package/dist/core/group/extractors/http-patterns/node.js +354 -0
  68. package/dist/core/group/extractors/http-patterns/php.d.ts +2 -0
  69. package/dist/core/group/extractors/http-patterns/php.js +70 -0
  70. package/dist/core/group/extractors/http-patterns/python.d.ts +2 -0
  71. package/dist/core/group/extractors/http-patterns/python.js +133 -0
  72. package/dist/core/group/extractors/http-patterns/types.d.ts +61 -0
  73. package/dist/core/group/extractors/http-patterns/types.js +1 -0
  74. package/dist/core/group/extractors/http-route-extractor.d.ts +21 -0
  75. package/dist/core/group/extractors/http-route-extractor.js +391 -0
  76. package/dist/core/group/extractors/manifest-extractor.d.ts +54 -0
  77. package/dist/core/group/extractors/manifest-extractor.js +235 -0
  78. package/dist/core/group/extractors/topic-extractor.d.ts +8 -0
  79. package/dist/core/group/extractors/topic-extractor.js +97 -0
  80. package/dist/core/group/extractors/topic-patterns/go.d.ts +2 -0
  81. package/dist/core/group/extractors/topic-patterns/go.js +120 -0
  82. package/dist/core/group/extractors/topic-patterns/index.d.ts +14 -0
  83. package/dist/core/group/extractors/topic-patterns/index.js +38 -0
  84. package/dist/core/group/extractors/topic-patterns/java.d.ts +2 -0
  85. package/dist/core/group/extractors/topic-patterns/java.js +80 -0
  86. package/dist/core/group/extractors/topic-patterns/node.d.ts +4 -0
  87. package/dist/core/group/extractors/topic-patterns/node.js +155 -0
  88. package/dist/core/group/extractors/topic-patterns/python.d.ts +2 -0
  89. package/dist/core/group/extractors/topic-patterns/python.js +116 -0
  90. package/dist/core/group/extractors/topic-patterns/types.d.ts +25 -0
  91. package/dist/core/group/extractors/topic-patterns/types.js +10 -0
  92. package/dist/core/group/extractors/tree-sitter-scanner.d.ts +113 -0
  93. package/dist/core/group/extractors/tree-sitter-scanner.js +94 -0
  94. package/dist/core/group/matching.d.ts +13 -0
  95. package/dist/core/group/matching.js +198 -0
  96. package/dist/core/group/normalization.d.ts +3 -0
  97. package/dist/core/group/normalization.js +115 -0
  98. package/dist/core/group/service-boundary-detector.d.ts +8 -0
  99. package/dist/core/group/service-boundary-detector.js +155 -0
  100. package/dist/core/group/service.d.ts +46 -0
  101. package/dist/core/group/service.js +160 -0
  102. package/dist/core/group/storage.d.ts +9 -0
  103. package/dist/core/group/storage.js +91 -0
  104. package/dist/core/group/sync.d.ts +21 -0
  105. package/dist/core/group/sync.js +148 -0
  106. package/dist/core/group/types.d.ts +130 -0
  107. package/dist/core/group/types.js +1 -0
  108. package/dist/core/ingestion/binding-accumulator.d.ts +212 -0
  109. package/dist/core/ingestion/binding-accumulator.js +336 -0
  110. package/dist/core/ingestion/call-processor.d.ts +155 -24
  111. package/dist/core/ingestion/call-processor.js +1129 -247
  112. package/dist/core/ingestion/class-extractors/generic.d.ts +2 -0
  113. package/dist/core/ingestion/class-extractors/generic.js +135 -0
  114. package/dist/core/ingestion/class-types.d.ts +34 -0
  115. package/dist/core/ingestion/class-types.js +1 -0
  116. package/dist/core/ingestion/cobol-processor.d.ts +1 -1
  117. package/dist/core/ingestion/entry-point-scoring.d.ts +1 -0
  118. package/dist/core/ingestion/entry-point-scoring.js +1 -0
  119. package/dist/core/ingestion/field-types.d.ts +2 -2
  120. package/dist/core/ingestion/filesystem-walker.js +8 -0
  121. package/dist/core/ingestion/framework-detection.d.ts +1 -0
  122. package/dist/core/ingestion/framework-detection.js +1 -0
  123. package/dist/core/ingestion/heritage-processor.d.ts +8 -15
  124. package/dist/core/ingestion/heritage-processor.js +15 -28
  125. package/dist/core/ingestion/import-processor.d.ts +1 -11
  126. package/dist/core/ingestion/import-processor.js +1 -13
  127. package/dist/core/ingestion/import-resolvers/utils.js +1 -0
  128. package/dist/core/ingestion/import-resolvers/vue.d.ts +8 -0
  129. package/dist/core/ingestion/import-resolvers/vue.js +9 -0
  130. package/dist/core/ingestion/language-config.js +1 -1
  131. package/dist/core/ingestion/language-provider.d.ts +14 -3
  132. package/dist/core/ingestion/languages/c-cpp.js +168 -1
  133. package/dist/core/ingestion/languages/csharp.js +20 -0
  134. package/dist/core/ingestion/languages/dart.js +26 -4
  135. package/dist/core/ingestion/languages/go.js +22 -0
  136. package/dist/core/ingestion/languages/index.d.ts +1 -0
  137. package/dist/core/ingestion/languages/index.js +2 -0
  138. package/dist/core/ingestion/languages/java.js +17 -0
  139. package/dist/core/ingestion/languages/kotlin.js +24 -1
  140. package/dist/core/ingestion/languages/php.js +23 -11
  141. package/dist/core/ingestion/languages/python.js +9 -0
  142. package/dist/core/ingestion/languages/ruby.js +43 -0
  143. package/dist/core/ingestion/languages/rust.js +38 -0
  144. package/dist/core/ingestion/languages/swift.js +31 -0
  145. package/dist/core/ingestion/languages/typescript.d.ts +1 -0
  146. package/dist/core/ingestion/languages/typescript.js +52 -3
  147. package/dist/core/ingestion/languages/vue.d.ts +13 -0
  148. package/dist/core/ingestion/languages/vue.js +81 -0
  149. package/dist/core/ingestion/markdown-processor.d.ts +1 -1
  150. package/dist/core/ingestion/method-extractors/configs/c-cpp.d.ts +3 -0
  151. package/dist/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
  152. package/dist/core/ingestion/method-extractors/configs/csharp.js +5 -1
  153. package/dist/core/ingestion/method-extractors/configs/dart.d.ts +2 -0
  154. package/dist/core/ingestion/method-extractors/configs/dart.js +376 -0
  155. package/dist/core/ingestion/method-extractors/configs/go.d.ts +2 -0
  156. package/dist/core/ingestion/method-extractors/configs/go.js +176 -0
  157. package/dist/core/ingestion/method-extractors/configs/jvm.js +14 -4
  158. package/dist/core/ingestion/method-extractors/configs/php.d.ts +2 -0
  159. package/dist/core/ingestion/method-extractors/configs/php.js +304 -0
  160. package/dist/core/ingestion/method-extractors/configs/python.d.ts +2 -0
  161. package/dist/core/ingestion/method-extractors/configs/python.js +309 -0
  162. package/dist/core/ingestion/method-extractors/configs/ruby.d.ts +2 -0
  163. package/dist/core/ingestion/method-extractors/configs/ruby.js +286 -0
  164. package/dist/core/ingestion/method-extractors/configs/rust.d.ts +2 -0
  165. package/dist/core/ingestion/method-extractors/configs/rust.js +195 -0
  166. package/dist/core/ingestion/method-extractors/configs/swift.d.ts +2 -0
  167. package/dist/core/ingestion/method-extractors/configs/swift.js +277 -0
  168. package/dist/core/ingestion/method-extractors/configs/typescript-javascript.js +85 -8
  169. package/dist/core/ingestion/method-extractors/generic.d.ts +6 -0
  170. package/dist/core/ingestion/method-extractors/generic.js +84 -17
  171. package/dist/core/ingestion/method-types.d.ts +29 -0
  172. package/dist/core/ingestion/model/field-registry.d.ts +18 -0
  173. package/dist/core/ingestion/model/field-registry.js +22 -0
  174. package/dist/core/ingestion/model/heritage-map.d.ts +70 -0
  175. package/dist/core/ingestion/model/heritage-map.js +159 -0
  176. package/dist/core/ingestion/model/index.d.ts +20 -0
  177. package/dist/core/ingestion/model/index.js +41 -0
  178. package/dist/core/ingestion/model/method-registry.d.ts +62 -0
  179. package/dist/core/ingestion/model/method-registry.js +130 -0
  180. package/dist/core/ingestion/model/registration-table.d.ts +139 -0
  181. package/dist/core/ingestion/model/registration-table.js +224 -0
  182. package/dist/core/ingestion/model/resolution-context.d.ts +93 -0
  183. package/dist/core/ingestion/model/resolution-context.js +337 -0
  184. package/dist/core/ingestion/model/resolve.d.ts +56 -0
  185. package/dist/core/ingestion/model/resolve.js +297 -0
  186. package/dist/core/ingestion/model/semantic-model.d.ts +86 -0
  187. package/dist/core/ingestion/model/semantic-model.js +120 -0
  188. package/dist/core/ingestion/model/symbol-table.d.ts +222 -0
  189. package/dist/core/ingestion/model/symbol-table.js +206 -0
  190. package/dist/core/ingestion/model/type-registry.d.ts +39 -0
  191. package/dist/core/ingestion/model/type-registry.js +62 -0
  192. package/dist/core/ingestion/mro-processor.d.ts +5 -4
  193. package/dist/core/ingestion/mro-processor.js +311 -107
  194. package/dist/core/ingestion/parsing-processor.d.ts +5 -4
  195. package/dist/core/ingestion/parsing-processor.js +224 -87
  196. package/dist/core/ingestion/pipeline-phases/cobol.d.ts +16 -0
  197. package/dist/core/ingestion/pipeline-phases/cobol.js +45 -0
  198. package/dist/core/ingestion/pipeline-phases/communities.d.ts +16 -0
  199. package/dist/core/ingestion/pipeline-phases/communities.js +62 -0
  200. package/dist/core/ingestion/pipeline-phases/cross-file-impl.d.ts +17 -0
  201. package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +156 -0
  202. package/dist/core/ingestion/pipeline-phases/cross-file.d.ts +37 -0
  203. package/dist/core/ingestion/pipeline-phases/cross-file.js +63 -0
  204. package/dist/core/ingestion/pipeline-phases/index.d.ts +21 -0
  205. package/dist/core/ingestion/pipeline-phases/index.js +22 -0
  206. package/dist/core/ingestion/pipeline-phases/markdown.d.ts +17 -0
  207. package/dist/core/ingestion/pipeline-phases/markdown.js +33 -0
  208. package/dist/core/ingestion/pipeline-phases/mro.d.ts +18 -0
  209. package/dist/core/ingestion/pipeline-phases/mro.js +36 -0
  210. package/dist/core/ingestion/pipeline-phases/orm-extraction.d.ts +22 -0
  211. package/dist/core/ingestion/pipeline-phases/orm-extraction.js +92 -0
  212. package/dist/core/ingestion/pipeline-phases/orm.d.ts +15 -0
  213. package/dist/core/ingestion/pipeline-phases/orm.js +74 -0
  214. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +47 -0
  215. package/dist/core/ingestion/pipeline-phases/parse-impl.js +437 -0
  216. package/dist/core/ingestion/pipeline-phases/parse.d.ts +49 -0
  217. package/dist/core/ingestion/pipeline-phases/parse.js +33 -0
  218. package/dist/core/ingestion/pipeline-phases/processes.d.ts +16 -0
  219. package/dist/core/ingestion/pipeline-phases/processes.js +143 -0
  220. package/dist/core/ingestion/pipeline-phases/routes.d.ts +21 -0
  221. package/dist/core/ingestion/pipeline-phases/routes.js +243 -0
  222. package/dist/core/ingestion/pipeline-phases/runner.d.ts +22 -0
  223. package/dist/core/ingestion/pipeline-phases/runner.js +203 -0
  224. package/dist/core/ingestion/pipeline-phases/scan.d.ts +21 -0
  225. package/dist/core/ingestion/pipeline-phases/scan.js +46 -0
  226. package/dist/core/ingestion/pipeline-phases/structure.d.ts +27 -0
  227. package/dist/core/ingestion/pipeline-phases/structure.js +35 -0
  228. package/dist/core/ingestion/pipeline-phases/tools.d.ts +20 -0
  229. package/dist/core/ingestion/pipeline-phases/tools.js +79 -0
  230. package/dist/core/ingestion/pipeline-phases/types.d.ts +79 -0
  231. package/dist/core/ingestion/pipeline-phases/types.js +37 -0
  232. package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.d.ts +35 -0
  233. package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.js +174 -0
  234. package/dist/core/ingestion/pipeline.d.ts +18 -10
  235. package/dist/core/ingestion/pipeline.js +66 -1410
  236. package/dist/core/ingestion/process-processor.js +1 -1
  237. package/dist/core/ingestion/tree-sitter-queries.d.ts +5 -5
  238. package/dist/core/ingestion/tree-sitter-queries.js +90 -0
  239. package/dist/core/ingestion/type-env.d.ts +15 -2
  240. package/dist/core/ingestion/type-env.js +163 -102
  241. package/dist/core/ingestion/type-extractors/csharp.js +17 -0
  242. package/dist/core/ingestion/type-extractors/jvm.js +11 -0
  243. package/dist/core/ingestion/type-extractors/php.js +0 -55
  244. package/dist/core/ingestion/type-extractors/ruby.js +0 -32
  245. package/dist/core/ingestion/type-extractors/swift.js +13 -0
  246. package/dist/core/ingestion/type-extractors/types.d.ts +8 -8
  247. package/dist/core/ingestion/type-extractors/typescript.js +66 -69
  248. package/dist/core/ingestion/utils/ast-helpers.d.ts +32 -44
  249. package/dist/core/ingestion/utils/ast-helpers.js +157 -573
  250. package/dist/core/ingestion/utils/env.d.ts +10 -0
  251. package/dist/core/ingestion/utils/env.js +10 -0
  252. package/dist/core/ingestion/utils/graph-sort.d.ts +58 -0
  253. package/dist/core/ingestion/utils/graph-sort.js +100 -0
  254. package/dist/core/ingestion/utils/method-props.d.ts +32 -0
  255. package/dist/core/ingestion/utils/method-props.js +147 -0
  256. package/dist/core/ingestion/vue-sfc-extractor.d.ts +44 -0
  257. package/dist/core/ingestion/vue-sfc-extractor.js +94 -0
  258. package/dist/core/ingestion/workers/parse-worker.d.ts +31 -19
  259. package/dist/core/ingestion/workers/parse-worker.js +469 -200
  260. package/dist/core/lbug/lbug-adapter.d.ts +6 -0
  261. package/dist/core/lbug/lbug-adapter.js +134 -27
  262. package/dist/core/lbug/pool-adapter.d.ts +76 -0
  263. package/dist/core/lbug/pool-adapter.js +522 -0
  264. package/dist/core/run-analyze.d.ts +2 -0
  265. package/dist/core/run-analyze.js +1 -1
  266. package/dist/core/search/bm25-index.js +1 -1
  267. package/dist/core/tree-sitter/parser-loader.js +1 -0
  268. package/dist/core/wiki/graph-queries.js +1 -1
  269. package/dist/mcp/core/embedder.js +6 -5
  270. package/dist/mcp/core/lbug-adapter.d.ts +3 -63
  271. package/dist/mcp/core/lbug-adapter.js +3 -484
  272. package/dist/mcp/local/local-backend.d.ts +31 -2
  273. package/dist/mcp/local/local-backend.js +255 -46
  274. package/dist/mcp/resources.js +5 -4
  275. package/dist/mcp/staleness.d.ts +3 -13
  276. package/dist/mcp/staleness.js +2 -31
  277. package/dist/mcp/tools.js +80 -4
  278. package/dist/server/analyze-job.d.ts +2 -0
  279. package/dist/server/analyze-job.js +4 -0
  280. package/dist/server/api.d.ts +20 -1
  281. package/dist/server/api.js +306 -71
  282. package/dist/server/git-clone.d.ts +2 -1
  283. package/dist/server/git-clone.js +98 -5
  284. package/dist/storage/git.d.ts +13 -0
  285. package/dist/storage/git.js +25 -0
  286. package/dist/storage/repo-manager.js +1 -1
  287. package/package.json +9 -3
  288. package/scripts/patch-tree-sitter-swift.cjs +78 -0
  289. package/vendor/tree-sitter-proto/binding.gyp +30 -0
  290. package/vendor/tree-sitter-proto/bindings/node/binding.cc +20 -0
  291. package/vendor/tree-sitter-proto/bindings/node/index.d.ts +28 -0
  292. package/vendor/tree-sitter-proto/bindings/node/index.js +7 -0
  293. package/vendor/tree-sitter-proto/package.json +18 -0
  294. package/vendor/tree-sitter-proto/src/node-types.json +1145 -0
  295. package/vendor/tree-sitter-proto/src/parser.c +10149 -0
  296. package/vendor/tree-sitter-proto/src/tree_sitter/alloc.h +54 -0
  297. package/vendor/tree-sitter-proto/src/tree_sitter/array.h +291 -0
  298. package/vendor/tree-sitter-proto/src/tree_sitter/parser.h +266 -0
  299. package/dist/core/ingestion/named-binding-processor.d.ts +0 -18
  300. package/dist/core/ingestion/named-binding-processor.js +0 -42
  301. package/dist/core/ingestion/resolution-context.d.ts +0 -58
  302. package/dist/core/ingestion/resolution-context.js +0 -135
  303. package/dist/core/ingestion/symbol-table.d.ts +0 -79
  304. package/dist/core/ingestion/symbol-table.js +0 -115
@@ -2,11 +2,13 @@ import Parser from 'tree-sitter';
2
2
  import { loadParser, loadLanguage, isLanguageAvailable } from '../tree-sitter/parser-loader.js';
3
3
  import { getProvider } from './languages/index.js';
4
4
  import { generateId } from '../../lib/utils.js';
5
- import { getLanguageFromFilename } from '../../_shared/index.js';
5
+ import { getLanguageFromFilename, SupportedLanguages } from '../../_shared/index.js';
6
+ import { extractVueScript, isVueSetupTopLevel } from './vue-sfc-extractor.js';
6
7
  import { yieldToEventLoop } from './utils/event-loop.js';
7
- import { getDefinitionNodeFromCaptures, findEnclosingClassId, extractMethodSignature, getLabelFromCaptures, CLASS_CONTAINER_TYPES, } from './utils/ast-helpers.js';
8
+ import { getDefinitionNodeFromCaptures, findEnclosingClassInfo, getLabelFromCaptures, CLASS_CONTAINER_TYPES, } from './utils/ast-helpers.js';
8
9
  import { detectFrameworkFromAST } from './framework-detection.js';
9
10
  import { buildTypeEnv } from './type-env.js';
11
+ import { buildMethodProps, arityForIdFromInfo, typeTagForId, constTagForId, buildCollisionGroups, } from './utils/method-props.js';
10
12
  import { getTreeSitterBufferSize, TREE_SITTER_MAX_BUFFER } from './constants.js';
11
13
  // ============================================================================
12
14
  // Worker-based parallel parsing
@@ -31,7 +33,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
31
33
  toolDefs: [],
32
34
  ormQueries: [],
33
35
  constructorBindings: [],
34
- typeEnvBindings: [],
36
+ fileScopeBindings: [],
35
37
  };
36
38
  const total = files.length;
37
39
  // Dispatch to worker pool — pool handles splitting into chunks and sub-batching
@@ -49,7 +51,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
49
51
  const allToolDefs = [];
50
52
  const allORMQueries = [];
51
53
  const allConstructorBindings = [];
52
- const allTypeEnvBindings = [];
54
+ const fileScopeBindingsByFile = [];
53
55
  for (const result of chunkResults) {
54
56
  for (const node of result.nodes) {
55
57
  graph.addNode({
@@ -69,20 +71,33 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
69
71
  returnType: sym.returnType,
70
72
  declaredType: sym.declaredType,
71
73
  ownerId: sym.ownerId,
74
+ qualifiedName: sym.qualifiedName,
72
75
  });
73
76
  }
74
- allImports.push(...result.imports);
75
- allCalls.push(...result.calls);
76
- allAssignments.push(...result.assignments);
77
- allHeritage.push(...result.heritage);
78
- allRoutes.push(...result.routes);
79
- allFetchCalls.push(...result.fetchCalls);
80
- allDecoratorRoutes.push(...result.decoratorRoutes);
81
- allToolDefs.push(...result.toolDefs);
77
+ for (const item of result.imports)
78
+ allImports.push(item);
79
+ for (const item of result.calls)
80
+ allCalls.push(item);
81
+ for (const item of result.assignments)
82
+ allAssignments.push(item);
83
+ for (const item of result.heritage)
84
+ allHeritage.push(item);
85
+ for (const item of result.routes)
86
+ allRoutes.push(item);
87
+ for (const item of result.fetchCalls)
88
+ allFetchCalls.push(item);
89
+ for (const item of result.decoratorRoutes)
90
+ allDecoratorRoutes.push(item);
91
+ for (const item of result.toolDefs)
92
+ allToolDefs.push(item);
82
93
  if (result.ormQueries)
83
- allORMQueries.push(...result.ormQueries);
84
- allConstructorBindings.push(...result.constructorBindings);
85
- allTypeEnvBindings.push(...result.typeEnvBindings);
94
+ for (const item of result.ormQueries)
95
+ allORMQueries.push(item);
96
+ for (const item of result.constructorBindings)
97
+ allConstructorBindings.push(item);
98
+ if (result.fileScopeBindings)
99
+ for (const item of result.fileScopeBindings)
100
+ fileScopeBindingsByFile.push(item);
86
101
  }
87
102
  // Merge and log skipped languages from workers
88
103
  const skippedLanguages = new Map();
@@ -110,7 +125,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
110
125
  toolDefs: allToolDefs,
111
126
  ormQueries: allORMQueries,
112
127
  constructorBindings: allConstructorBindings,
113
- typeEnvBindings: allTypeEnvBindings,
128
+ fileScopeBindings: fileScopeBindingsByFile,
114
129
  };
115
130
  };
116
131
  // ============================================================================
@@ -118,14 +133,14 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
118
133
  // ============================================================================
119
134
  // Inline caches to avoid repeated parent-walks per node (same pattern as parse-worker.ts).
120
135
  // Keyed by tree-sitter node reference — cleared at the start of each file.
121
- const classIdCache = new Map();
136
+ const classInfoCache = new Map();
122
137
  const exportCache = new Map();
123
- const cachedFindEnclosingClassId = (node, filePath) => {
124
- const cached = classIdCache.get(node);
138
+ const cachedFindEnclosingClassInfo = (node, filePath, resolveEnclosingOwner) => {
139
+ const cached = classInfoCache.get(node);
125
140
  if (cached !== undefined)
126
141
  return cached;
127
- const result = findEnclosingClassId(node, filePath);
128
- classIdCache.set(node, result);
142
+ const result = findEnclosingClassInfo(node, filePath, resolveEnclosingOwner);
143
+ classInfoCache.set(node, result);
129
144
  return result;
130
145
  };
131
146
  const cachedExportCheck = (checker, node, name) => {
@@ -138,21 +153,46 @@ const cachedExportCheck = (checker, node, name) => {
138
153
  };
139
154
  // FieldExtractor cache for sequential path — same pattern as parse-worker.ts
140
155
  const seqFieldInfoCache = new Map();
141
- function seqFindEnclosingClassNode(node) {
156
+ // MethodExtractor cache for sequential path — avoids re-traversing the same class
157
+ // body once per method. Keyed on classNode.id (tree-sitter node identity number).
158
+ const seqMethodExtractCache = new Map();
159
+ // Derived method map + collision groups cache — avoids rebuilding per method.
160
+ const seqMethodMapCache = new Map();
161
+ /** Provider-aware enclosing container lookup.
162
+ * Walks up from `node` until a CLASS_CONTAINER_TYPES node is found.
163
+ * When `resolveEnclosingOwner` is provided, delegates language-specific
164
+ * container remapping (e.g., Ruby singleton_class → enclosing class).
165
+ * Without the hook, returns the first matching container directly (raw lookup). */
166
+ function seqFindEnclosingOwnerNode(node, resolveEnclosingOwner) {
142
167
  let current = node.parent;
143
168
  while (current) {
144
- if (CLASS_CONTAINER_TYPES.has(current.type))
169
+ if (CLASS_CONTAINER_TYPES.has(current.type)) {
170
+ if (resolveEnclosingOwner) {
171
+ const resolved = resolveEnclosingOwner(current);
172
+ if (resolved === null) {
173
+ // Provider says skip this container — keep walking up.
174
+ current = current.parent;
175
+ continue;
176
+ }
177
+ return resolved;
178
+ }
145
179
  return current;
180
+ }
146
181
  current = current.parent;
147
182
  }
148
183
  return null;
149
184
  }
150
- /** Minimal no-op SymbolTable stub for FieldExtractorContext (sequential path has a real
151
- * SymbolTable, but it's incomplete at this stage use the stub for safety). */
185
+ /** Minimal no-op SymbolTable stub for sequential extractor contexts. The real
186
+ * SymbolTable is not fully populated yet at this stage, so use the stub for safety.
187
+ * Implements the full {@link SymbolTableReader} surface so future extractor additions
188
+ * don't silently fall off an `as unknown as` cast. */
152
189
  const NOOP_SYMBOL_TABLE_SEQ = {
153
- lookupExactAll: () => [],
154
190
  lookupExact: () => undefined,
155
191
  lookupExactFull: () => undefined,
192
+ lookupExactAll: () => [],
193
+ lookupCallableByName: () => [],
194
+ getFiles: () => [][Symbol.iterator](),
195
+ getStats: () => ({ fileCount: 0 }),
156
196
  };
157
197
  function seqGetFieldInfo(classNode, provider, context) {
158
198
  if (!provider.fieldExtractor)
@@ -177,9 +217,11 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
177
217
  for (let i = 0; i < files.length; i++) {
178
218
  const file = files[i];
179
219
  // Reset memoization before each new file (node refs are per-tree)
180
- classIdCache.clear();
220
+ classInfoCache.clear();
181
221
  exportCache.clear();
182
222
  seqFieldInfoCache.clear();
223
+ seqMethodExtractCache.clear();
224
+ seqMethodMapCache.clear();
183
225
  onFileProgress?.(i + 1, total, file.path);
184
226
  if (i % 20 === 0)
185
227
  await yieldToEventLoop();
@@ -194,6 +236,18 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
194
236
  // Skip files larger than the max tree-sitter buffer (32 MB)
195
237
  if (file.content.length > TREE_SITTER_MAX_BUFFER)
196
238
  continue;
239
+ // Vue SFC preprocessing: extract <script> block content
240
+ let parseContent = file.content;
241
+ let lineOffset = 0;
242
+ let isVueSetup = false;
243
+ if (language === SupportedLanguages.Vue) {
244
+ const extracted = extractVueScript(file.content);
245
+ if (!extracted)
246
+ continue; // skip .vue files with no script block
247
+ parseContent = extracted.scriptContent;
248
+ lineOffset = extracted.lineOffset;
249
+ isVueSetup = extracted.isSetup;
250
+ }
197
251
  try {
198
252
  await loadLanguage(language, file.path);
199
253
  }
@@ -202,8 +256,8 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
202
256
  }
203
257
  let tree;
204
258
  try {
205
- tree = parser.parse(file.content, undefined, {
206
- bufferSize: getTreeSitterBufferSize(file.content.length),
259
+ tree = parser.parse(parseContent, undefined, {
260
+ bufferSize: getTreeSitterBufferSize(parseContent.length),
207
261
  });
208
262
  }
209
263
  catch (parseError) {
@@ -227,90 +281,172 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
227
281
  console.warn(`Query error for ${file.path}:`, queryError);
228
282
  continue;
229
283
  }
230
- // Build per-file type environment for FieldExtractor context (lightweight — skipped if no fieldExtractor)
284
+ // Build per-file type environment for FieldExtractor context (lightweight — skipped if no fieldExtractor).
285
+ //
286
+ // Note: this TypeEnv is intentionally NOT flushed into the BindingAccumulator.
287
+ // The accumulator feed happens later in `call-processor.ts` via its own
288
+ // `typeEnv.flush(accumulator)` call. Flushing here would double-count
289
+ // file-scope bindings and break the single-use invariant of `flush()`.
290
+ // See the BindingAccumulator class JSDoc for the full accumulator
291
+ // lifecycle and flush-site ownership rules.
231
292
  const typeEnv = provider.fieldExtractor
232
- ? buildTypeEnv(tree, language, { enclosingFunctionFinder: provider.enclosingFunctionFinder })
293
+ ? buildTypeEnv(tree, language, {
294
+ enclosingFunctionFinder: provider.enclosingFunctionFinder,
295
+ extractFunctionName: provider.methodExtractor?.extractFunctionName,
296
+ })
233
297
  : null;
234
298
  matches.forEach((match) => {
235
299
  const captureMap = {};
236
300
  match.captures.forEach((c) => {
237
301
  captureMap[c.name] = c.node;
238
302
  });
239
- const nodeLabel = getLabelFromCaptures(captureMap, provider);
240
- if (!nodeLabel)
303
+ const definitionNodeForRange = getDefinitionNodeFromCaptures(captureMap);
304
+ const definitionNode = getDefinitionNodeFromCaptures(captureMap);
305
+ const defaultNodeLabel = getLabelFromCaptures(captureMap, provider);
306
+ if (!defaultNodeLabel)
241
307
  return;
242
308
  const nameNode = captureMap['name'];
309
+ const extractedClassSymbol = definitionNode && provider.classExtractor?.isTypeDeclaration(definitionNode)
310
+ ? provider.classExtractor.extract(definitionNode, {
311
+ name: nameNode?.text,
312
+ type: defaultNodeLabel,
313
+ })
314
+ : null;
315
+ const nodeLabel = extractedClassSymbol?.type ?? defaultNodeLabel;
243
316
  // Synthesize name for constructors without explicit @name capture (e.g. Swift init)
244
- if (!nameNode && nodeLabel !== 'Constructor')
317
+ if (!nameNode && nodeLabel !== 'Constructor' && !extractedClassSymbol)
245
318
  return;
246
- const nodeName = nameNode ? nameNode.text : 'init';
247
- const definitionNodeForRange = getDefinitionNodeFromCaptures(captureMap);
319
+ const nodeName = extractedClassSymbol?.name ?? (nameNode ? nameNode.text : 'init');
248
320
  const startLine = definitionNodeForRange
249
- ? definitionNodeForRange.startPosition.row
321
+ ? definitionNodeForRange.startPosition.row + lineOffset
250
322
  : nameNode
251
- ? nameNode.startPosition.row
252
- : 0;
253
- const nodeId = generateId(nodeLabel, `${file.path}:${nodeName}`);
254
- const definitionNode = getDefinitionNodeFromCaptures(captureMap);
255
- const frameworkHint = definitionNode
256
- ? detectFrameworkFromAST(language, (definitionNode.text || '').slice(0, 300))
323
+ ? nameNode.startPosition.row + lineOffset
324
+ : lineOffset;
325
+ // Compute enclosing class BEFORE node ID — needed to qualify method IDs
326
+ const needsOwner = nodeLabel === 'Method' ||
327
+ nodeLabel === 'Constructor' ||
328
+ nodeLabel === 'Property' ||
329
+ nodeLabel === 'Function';
330
+ const enclosingClassInfo = needsOwner
331
+ ? cachedFindEnclosingClassInfo(nameNode || definitionNodeForRange, file.path, provider.resolveEnclosingOwner)
257
332
  : null;
258
- // Extract method signature for Method/Constructor nodes
259
- const methodSig = nodeLabel === 'Function' || nodeLabel === 'Method' || nodeLabel === 'Constructor'
260
- ? extractMethodSignature(definitionNode)
261
- : undefined;
262
- // Language-specific return type fallback (e.g. Ruby YARD @return [Type])
263
- // Also upgrades uninformative AST types like PHP `array` with PHPDoc `@return User[]`
264
- if (methodSig &&
265
- (!methodSig.returnType ||
266
- methodSig.returnType === 'array' ||
267
- methodSig.returnType === 'iterable') &&
268
- definitionNode) {
269
- const tc = provider.typeConfig;
270
- if (tc?.extractReturnType) {
271
- const docReturn = tc.extractReturnType(definitionNode);
272
- if (docReturn)
273
- methodSig.returnType = docReturn;
333
+ const enclosingClassId = enclosingClassInfo?.classId ?? null;
334
+ // Qualify method/property IDs with enclosing class name to avoid collisions
335
+ // e.g. "Method:animal.dart:Animal.speak" vs "Method:animal.dart:Dog.speak"
336
+ const qualifiedName = enclosingClassInfo
337
+ ? `${enclosingClassInfo.className}.${nodeName}`
338
+ : nodeName;
339
+ // Extract method metadata for Function/Method/Constructor nodes BEFORE generating
340
+ // the node ID — parameterCount is needed to disambiguate overloaded methods.
341
+ // Use the per-language MethodExtractor for method metadata (isAbstract, isStatic,
342
+ // visibility, annotations, parameterCount, parameterTypes, returnType, etc.).
343
+ const isMethodLike = nodeLabel === 'Function' || nodeLabel === 'Method' || nodeLabel === 'Constructor';
344
+ let methodProps = {};
345
+ let arityForId; // raw param count for ID, even for variadic
346
+ let seqDefMethodInfo;
347
+ let seqDefMethods;
348
+ let seqClassNodeId;
349
+ if (isMethodLike && definitionNode) {
350
+ let enriched = false;
351
+ if (provider.methodExtractor) {
352
+ // Try class-based extraction (method inside a class/struct/trait body).
353
+ // Raw lookup (no resolveEnclosingOwner) so the method extractor sees
354
+ // the actual container node (e.g. singleton_class) for static detection.
355
+ const methodOwnerNode = seqFindEnclosingOwnerNode(definitionNode);
356
+ if (methodOwnerNode) {
357
+ // Cache extract() results per class node to avoid re-traversing the
358
+ // same class body for every method it contains (O(N) -> O(1) per hit).
359
+ let result = seqMethodExtractCache.get(methodOwnerNode.id);
360
+ if (result === undefined) {
361
+ result =
362
+ provider.methodExtractor.extract(methodOwnerNode, {
363
+ filePath: file.path,
364
+ language,
365
+ }) ?? null;
366
+ seqMethodExtractCache.set(methodOwnerNode.id, result);
367
+ }
368
+ if (result?.methods?.length) {
369
+ const defLine = definitionNode.startPosition.row + 1;
370
+ const info = result.methods.find((m) => m.name === nodeName && m.line === defLine);
371
+ if (info) {
372
+ enriched = true;
373
+ arityForId = arityForIdFromInfo(info);
374
+ methodProps = buildMethodProps(info);
375
+ seqDefMethodInfo = info;
376
+ seqDefMethods = result.methods;
377
+ seqClassNodeId = methodOwnerNode.id;
378
+ }
379
+ }
380
+ }
381
+ // For top-level methods (e.g. Go method_declaration), try extractFromNode
382
+ if (!enriched && provider.methodExtractor.extractFromNode) {
383
+ const info = provider.methodExtractor.extractFromNode(definitionNode, {
384
+ filePath: file.path,
385
+ language,
386
+ });
387
+ if (info) {
388
+ enriched = true;
389
+ arityForId = arityForIdFromInfo(info);
390
+ methodProps = buildMethodProps(info);
391
+ }
392
+ }
393
+ }
394
+ }
395
+ // Append #<paramCount> to Method/Constructor IDs to disambiguate overloads.
396
+ // Functions are not suffixed — they don't overload by name in the same scope.
397
+ // When same-arity collisions exist, append ~type1,type2 for further disambiguation.
398
+ const needsAritySuffix = nodeLabel === 'Method' || nodeLabel === 'Constructor';
399
+ let arityTag = needsAritySuffix && arityForId !== undefined ? `#${arityForId}` : '';
400
+ if (arityTag && seqDefMethods && seqDefMethodInfo && seqClassNodeId !== undefined) {
401
+ // Use cached method map + collision groups (built once per class, not per method)
402
+ let cached = seqMethodMapCache.get(seqClassNodeId);
403
+ if (!cached) {
404
+ const tempMap = new Map();
405
+ for (const m of seqDefMethods)
406
+ tempMap.set(`${m.name}:${m.line}`, m);
407
+ cached = { map: tempMap, groups: buildCollisionGroups(tempMap) };
408
+ seqMethodMapCache.set(seqClassNodeId, cached);
274
409
  }
410
+ arityTag += typeTagForId(cached.map, nodeName, arityForId, seqDefMethodInfo, language, cached.groups);
411
+ arityTag += constTagForId(cached.map, nodeName, arityForId, seqDefMethodInfo, cached.groups);
275
412
  }
413
+ const nodeId = generateId(nodeLabel, `${file.path}:${qualifiedName}${arityTag}`);
414
+ const classNodeForSymbol = definitionNodeForRange || definitionNode || nameNode;
415
+ const qualifiedTypeName = extractedClassSymbol?.qualifiedName ??
416
+ (classNodeForSymbol && provider.classExtractor?.isTypeDeclaration(classNodeForSymbol)
417
+ ? (provider.classExtractor.extractQualifiedName(classNodeForSymbol, nodeName) ?? nodeName)
418
+ : undefined);
419
+ const frameworkHint = definitionNode
420
+ ? detectFrameworkFromAST(language, (definitionNode.text || '').slice(0, 300))
421
+ : null;
276
422
  const node = {
277
423
  id: nodeId,
278
424
  label: nodeLabel,
279
425
  properties: {
280
426
  name: nodeName,
281
427
  filePath: file.path,
282
- startLine: definitionNodeForRange ? definitionNodeForRange.startPosition.row : startLine,
283
- endLine: definitionNodeForRange ? definitionNodeForRange.endPosition.row : startLine,
428
+ startLine: definitionNodeForRange
429
+ ? definitionNodeForRange.startPosition.row + lineOffset
430
+ : startLine,
431
+ endLine: definitionNodeForRange
432
+ ? definitionNodeForRange.endPosition.row + lineOffset
433
+ : startLine,
284
434
  language: language,
285
- isExported: cachedExportCheck(provider.exportChecker, nameNode || definitionNodeForRange, nodeName),
435
+ isExported: language === SupportedLanguages.Vue && isVueSetup
436
+ ? isVueSetupTopLevel(nameNode || definitionNodeForRange)
437
+ : cachedExportCheck(provider.exportChecker, nameNode || definitionNodeForRange, nodeName),
438
+ ...(qualifiedTypeName !== undefined ? { qualifiedName: qualifiedTypeName } : {}),
286
439
  ...(frameworkHint
287
440
  ? {
288
441
  astFrameworkMultiplier: frameworkHint.entryPointMultiplier,
289
442
  astFrameworkReason: frameworkHint.reason,
290
443
  }
291
444
  : {}),
292
- ...(methodSig
293
- ? {
294
- parameterCount: methodSig.parameterCount,
295
- ...(methodSig.requiredParameterCount !== undefined
296
- ? { requiredParameterCount: methodSig.requiredParameterCount }
297
- : {}),
298
- ...(methodSig.parameterTypes ? { parameterTypes: methodSig.parameterTypes } : {}),
299
- returnType: methodSig.returnType,
300
- }
301
- : {}),
445
+ ...methodProps,
302
446
  },
303
447
  };
304
448
  graph.addNode(node);
305
- // Compute enclosing class for Method/Constructor/Property/Function used for both ownerId and HAS_METHOD
306
- // Function is included because Kotlin/Rust/Python capture class methods as Function nodes
307
- const needsOwner = nodeLabel === 'Method' ||
308
- nodeLabel === 'Constructor' ||
309
- nodeLabel === 'Property' ||
310
- nodeLabel === 'Function';
311
- const enclosingClassId = needsOwner
312
- ? cachedFindEnclosingClassId(nameNode || definitionNodeForRange, file.path)
313
- : null;
449
+ // enclosingClassId already computed above (before nodeId generation)
314
450
  // Extract declared type and field metadata for Property nodes
315
451
  let declaredType;
316
452
  let seqVisibility;
@@ -319,7 +455,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
319
455
  if (nodeLabel === 'Property' && definitionNode) {
320
456
  // FieldExtractor is the single source of truth when available
321
457
  if (provider.fieldExtractor && typeEnv) {
322
- const classNode = seqFindEnclosingClassNode(definitionNode);
458
+ const classNode = seqFindEnclosingOwnerNode(definitionNode, provider.resolveEnclosingOwner);
323
459
  if (classNode) {
324
460
  const fieldMap = seqGetFieldInfo(classNode, provider, {
325
461
  typeEnv,
@@ -336,7 +472,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
336
472
  }
337
473
  }
338
474
  }
339
- // All 14 languages register a FieldExtractor — no fallback needed.
475
+ // All 15 tree-sitter languages register a FieldExtractor — no fallback needed.
340
476
  }
341
477
  // Apply field metadata to the graph node retroactively
342
478
  if (seqVisibility !== undefined)
@@ -348,12 +484,13 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
348
484
  if (declaredType !== undefined)
349
485
  node.properties.declaredType = declaredType;
350
486
  symbolTable.add(file.path, nodeName, nodeId, nodeLabel, {
351
- parameterCount: methodSig?.parameterCount,
352
- requiredParameterCount: methodSig?.requiredParameterCount,
353
- parameterTypes: methodSig?.parameterTypes,
354
- returnType: methodSig?.returnType,
487
+ parameterCount: methodProps.parameterCount,
488
+ requiredParameterCount: methodProps.requiredParameterCount,
489
+ parameterTypes: methodProps.parameterTypes,
490
+ returnType: methodProps.returnType,
355
491
  declaredType,
356
492
  ownerId: enclosingClassId ?? undefined,
493
+ qualifiedName: qualifiedTypeName,
357
494
  });
358
495
  const fileId = generateId('File', file.path);
359
496
  const relId = generateId('DEFINES', `${fileId}->${nodeId}`);
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Phase: cobol
3
+ *
4
+ * Processes COBOL and JCL files via regex extraction (no tree-sitter).
5
+ *
6
+ * @deps structure
7
+ * @reads scannedFiles, allPaths (from structure phase)
8
+ * @writes graph (COBOL program/paragraph/section nodes, JCL job/step nodes)
9
+ */
10
+ import type { PipelinePhase } from './types.js';
11
+ export interface CobolOutput {
12
+ programs: number;
13
+ paragraphs: number;
14
+ sections: number;
15
+ }
16
+ export declare const cobolPhase: PipelinePhase<CobolOutput>;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Phase: cobol
3
+ *
4
+ * Processes COBOL and JCL files via regex extraction (no tree-sitter).
5
+ *
6
+ * @deps structure
7
+ * @reads scannedFiles, allPaths (from structure phase)
8
+ * @writes graph (COBOL program/paragraph/section nodes, JCL job/step nodes)
9
+ */
10
+ import { getPhaseOutput } from './types.js';
11
+ import { processCobol, isCobolFile, isJclFile } from '../cobol-processor.js';
12
+ import { readFileContents } from '../filesystem-walker.js';
13
+ import { isDev } from '../utils/env.js';
14
+ export const cobolPhase = {
15
+ name: 'cobol',
16
+ deps: ['structure'],
17
+ async execute(ctx, deps) {
18
+ const { scannedFiles, allPathSet } = getPhaseOutput(deps, 'structure');
19
+ const cobolScanned = scannedFiles.filter((f) => isCobolFile(f.path) || isJclFile(f.path));
20
+ if (cobolScanned.length === 0) {
21
+ return { programs: 0, paragraphs: 0, sections: 0 };
22
+ }
23
+ const cobolContents = await readFileContents(ctx.repoPath, cobolScanned.map((f) => f.path));
24
+ const cobolFiles = cobolScanned
25
+ .filter((f) => cobolContents.has(f.path))
26
+ .map((f) => ({ path: f.path, content: cobolContents.get(f.path) }));
27
+ const cobolResult = processCobol(ctx.graph, cobolFiles, allPathSet);
28
+ if (isDev) {
29
+ console.log(` COBOL: ${cobolResult.programs} programs, ${cobolResult.paragraphs} paragraphs, ${cobolResult.sections} sections from ${cobolFiles.length} files`);
30
+ if (cobolResult.execSqlBlocks > 0 ||
31
+ cobolResult.execCicsBlocks > 0 ||
32
+ cobolResult.entryPoints > 0) {
33
+ console.log(` COBOL enriched: ${cobolResult.execSqlBlocks} SQL blocks, ${cobolResult.execCicsBlocks} CICS blocks, ${cobolResult.entryPoints} entry points, ${cobolResult.moves} moves, ${cobolResult.fileDeclarations} file declarations`);
34
+ }
35
+ if (cobolResult.jclJobs > 0) {
36
+ console.log(` JCL: ${cobolResult.jclJobs} jobs, ${cobolResult.jclSteps} steps`);
37
+ }
38
+ }
39
+ return {
40
+ programs: cobolResult.programs,
41
+ paragraphs: cobolResult.paragraphs,
42
+ sections: cobolResult.sections,
43
+ };
44
+ },
45
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Phase: communities
3
+ *
4
+ * Detects code communities via Leiden algorithm and creates
5
+ * Community nodes + MEMBER_OF edges.
6
+ *
7
+ * @deps mro
8
+ * @reads graph (all nodes and relationships)
9
+ * @writes graph (Community nodes, MEMBER_OF edges)
10
+ */
11
+ import type { PipelinePhase } from './types.js';
12
+ import { type CommunityDetectionResult } from '../community-processor.js';
13
+ export interface CommunitiesOutput {
14
+ communityResult: CommunityDetectionResult;
15
+ }
16
+ export declare const communitiesPhase: PipelinePhase<CommunitiesOutput>;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Phase: communities
3
+ *
4
+ * Detects code communities via Leiden algorithm and creates
5
+ * Community nodes + MEMBER_OF edges.
6
+ *
7
+ * @deps mro
8
+ * @reads graph (all nodes and relationships)
9
+ * @writes graph (Community nodes, MEMBER_OF edges)
10
+ */
11
+ import { getPhaseOutput } from './types.js';
12
+ import { processCommunities } from '../community-processor.js';
13
+ import { isDev } from '../utils/env.js';
14
+ export const communitiesPhase = {
15
+ name: 'communities',
16
+ deps: ['mro', 'structure'],
17
+ async execute(ctx, deps) {
18
+ const { totalFiles } = getPhaseOutput(deps, 'structure');
19
+ ctx.onProgress({
20
+ phase: 'communities',
21
+ percent: 84,
22
+ message: 'Detecting code communities...',
23
+ stats: { filesProcessed: totalFiles, totalFiles, nodesCreated: ctx.graph.nodeCount },
24
+ });
25
+ const communityResult = await processCommunities(ctx.graph, (message, progress) => {
26
+ const communityProgress = 84 + progress * 0.09;
27
+ ctx.onProgress({
28
+ phase: 'communities',
29
+ percent: Math.round(communityProgress),
30
+ message,
31
+ stats: { filesProcessed: totalFiles, totalFiles, nodesCreated: ctx.graph.nodeCount },
32
+ });
33
+ });
34
+ if (isDev) {
35
+ console.log(`🏘️ Community detection: ${communityResult.stats.totalCommunities} communities found (modularity: ${communityResult.stats.modularity.toFixed(3)})`);
36
+ }
37
+ communityResult.communities.forEach((comm) => {
38
+ ctx.graph.addNode({
39
+ id: comm.id,
40
+ label: 'Community',
41
+ properties: {
42
+ name: comm.label,
43
+ filePath: '',
44
+ heuristicLabel: comm.heuristicLabel,
45
+ cohesion: comm.cohesion,
46
+ symbolCount: comm.symbolCount,
47
+ },
48
+ });
49
+ });
50
+ communityResult.memberships.forEach((membership) => {
51
+ ctx.graph.addRelationship({
52
+ id: `${membership.nodeId}_member_of_${membership.communityId}`,
53
+ type: 'MEMBER_OF',
54
+ sourceId: membership.nodeId,
55
+ targetId: membership.communityId,
56
+ confidence: 1.0,
57
+ reason: 'leiden-algorithm',
58
+ });
59
+ });
60
+ return { communityResult };
61
+ },
62
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Cross-file binding propagation — extracted from pipeline.ts.
3
+ *
4
+ * Seeds downstream files with resolved type bindings from upstream exports.
5
+ * Files are processed in topological import order so upstream bindings
6
+ * are available when downstream files are re-resolved.
7
+ *
8
+ * @module
9
+ */
10
+ import type { createResolutionContext } from '../model/resolution-context.js';
11
+ import { type PipelineProgress } from '../../../_shared/index.js';
12
+ import type { KnowledgeGraph } from '../../graph/types.js';
13
+ /**
14
+ * Cross-file binding propagation.
15
+ * Returns the number of files re-processed.
16
+ */
17
+ export declare function runCrossFileBindingPropagation(graph: KnowledgeGraph, ctx: ReturnType<typeof createResolutionContext>, parseExportedTypeMap: ReadonlyMap<string, ReadonlyMap<string, string>>, allPathSet: ReadonlySet<string>, totalFiles: number, repoPath: string, pipelineStart: number, onProgress: (progress: PipelineProgress) => void): Promise<number>;