cgraphx 2.0.1 → 2.0.3

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 (701) hide show
  1. package/dist/.claude-template/FLOW-MAP.md +7 -5
  2. package/dist/.claude-template/commands/end.md +1 -1
  3. package/dist/.claude-template/skills/cgraphx-guide/SKILL.md +2 -1
  4. package/dist/.claude-template/skills/cgraphx-guide/how-to-use.html +4 -2
  5. package/dist/.claude-template/skills/cgraphx-guide/how-to-use.md +5 -2
  6. package/dist/.claude-template/skills/iboc-check/SKILL.md +116 -0
  7. package/dist/.claude-template/skills/iboc-check/filler-prompt.md +75 -0
  8. package/dist/.claude-template/skills/implementation/SKILL.md +7 -0
  9. package/dist/.claude-template/skills/init-project-guides/SKILL.md +1 -1
  10. package/dist/.claude-template/skills/run-api-test/references/db-verification.md +2 -2
  11. package/dist/.claude-template/skills/subagent-implement/SKILL.md +3 -2
  12. package/dist/.claude-template/skills/write-api/assets/template-request.bru +3 -3
  13. package/dist/.claude-template/skills/write-api/references/bru-format.md +6 -6
  14. package/dist/.claude-template/skills/write-delivery-guide/SKILL.md +97 -0
  15. package/dist/.claude-template/skills/write-delivery-guide/template-change-type.md +120 -0
  16. package/dist/.claude-template/skills/write-delivery-guide/template-multi-role-flow.md +148 -0
  17. package/dist/.claude-template/skills/write-unit-test-code/SKILL.md +23 -6
  18. package/dist/core/code/engine/cli/analyze-config.js +320 -0
  19. package/dist/core/code/engine/cli/analyze.js +1086 -0
  20. package/dist/core/code/engine/cli/cli-message.js +83 -0
  21. package/dist/core/code/engine/cli/detect-changes-format.js +58 -0
  22. package/dist/core/code/engine/cli/embedding-dims.js +43 -0
  23. package/dist/core/code/engine/cli/format-elapsed.js +12 -0
  24. package/dist/core/code/engine/cli/help-i18n.js +144 -0
  25. package/dist/core/code/engine/cli/i18n/en.js +110 -0
  26. package/dist/core/code/engine/cli/i18n/index.js +47 -0
  27. package/dist/core/code/engine/cli/i18n/resources.js +9 -0
  28. package/dist/core/code/engine/cli/i18n/zh-CN.js +110 -0
  29. package/dist/core/code/engine/cli/lazy-action.js +67 -0
  30. package/dist/core/code/engine/cli/optional-grammars.js +136 -0
  31. package/dist/core/code/engine/cli/resolve-invocation.js +76 -0
  32. package/dist/core/code/engine/cli/status.js +156 -0
  33. package/dist/core/code/engine/cli/tool.js +384 -0
  34. package/dist/core/code/engine/config/ignore-service.js +511 -0
  35. package/dist/core/code/engine/config/supported-languages.js +17 -0
  36. package/dist/core/code/engine/core/analysis-features.js +64 -0
  37. package/dist/core/code/engine/core/analyzer-identity.js +2171 -0
  38. package/dist/core/code/engine/core/git-staleness.js +180 -0
  39. package/dist/core/code/engine/core/graph/graph.js +180 -0
  40. package/dist/core/code/engine/core/graph/import-cycles.js +106 -0
  41. package/dist/core/code/engine/core/graph/types.js +2 -0
  42. package/dist/core/code/engine/core/index-freshness.js +12 -0
  43. package/dist/core/code/engine/core/ingestion/binding-accumulator.js +341 -0
  44. package/dist/core/code/engine/core/ingestion/call-extractors/configs/c-cpp.js +168 -0
  45. package/dist/core/code/engine/core/ingestion/call-extractors/configs/csharp.js +9 -0
  46. package/dist/core/code/engine/core/ingestion/call-extractors/configs/dart.js +8 -0
  47. package/dist/core/code/engine/core/ingestion/call-extractors/configs/go.js +8 -0
  48. package/dist/core/code/engine/core/ingestion/call-extractors/configs/jvm.js +54 -0
  49. package/dist/core/code/engine/core/ingestion/call-extractors/configs/php.js +8 -0
  50. package/dist/core/code/engine/core/ingestion/call-extractors/configs/python.js +8 -0
  51. package/dist/core/code/engine/core/ingestion/call-extractors/configs/ruby.js +8 -0
  52. package/dist/core/code/engine/core/ingestion/call-extractors/configs/rust.js +8 -0
  53. package/dist/core/code/engine/core/ingestion/call-extractors/configs/swift.js +8 -0
  54. package/dist/core/code/engine/core/ingestion/call-extractors/configs/typescript-javascript.js +11 -0
  55. package/dist/core/code/engine/core/ingestion/call-extractors/generic.js +62 -0
  56. package/dist/core/code/engine/core/ingestion/call-processor.js +503 -0
  57. package/dist/core/code/engine/core/ingestion/call-routing.js +98 -0
  58. package/dist/core/code/engine/core/ingestion/call-types.js +3 -0
  59. package/dist/core/code/engine/core/ingestion/cfg/callee-cell-format.js +45 -0
  60. package/dist/core/code/engine/core/ingestion/cfg/cfg-builder.js +202 -0
  61. package/dist/core/code/engine/core/ingestion/cfg/collect.js +81 -0
  62. package/dist/core/code/engine/core/ingestion/cfg/control-dependence.js +185 -0
  63. package/dist/core/code/engine/core/ingestion/cfg/control-flow-context.js +130 -0
  64. package/dist/core/code/engine/core/ingestion/cfg/emit.js +646 -0
  65. package/dist/core/code/engine/core/ingestion/cfg/post-dominators.js +182 -0
  66. package/dist/core/code/engine/core/ingestion/cfg/reaching-def-reason-codec.js +139 -0
  67. package/dist/core/code/engine/core/ingestion/cfg/reaching-defs-graph.js +322 -0
  68. package/dist/core/code/engine/core/ingestion/cfg/reaching-defs.js +792 -0
  69. package/dist/core/code/engine/core/ingestion/cfg/synthetic-escape.js +305 -0
  70. package/dist/core/code/engine/core/ingestion/cfg/traversal-result.js +6 -0
  71. package/dist/core/code/engine/core/ingestion/cfg/types.js +14 -0
  72. package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp-harvest.js +545 -0
  73. package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp.js +590 -0
  74. package/dist/core/code/engine/core/ingestion/cfg/visitors/call-site-harvest.js +356 -0
  75. package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp-harvest.js +593 -0
  76. package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp.js +871 -0
  77. package/dist/core/code/engine/core/ingestion/cfg/visitors/dart-harvest.js +874 -0
  78. package/dist/core/code/engine/core/ingestion/cfg/visitors/dart.js +840 -0
  79. package/dist/core/code/engine/core/ingestion/cfg/visitors/go-harvest.js +625 -0
  80. package/dist/core/code/engine/core/ingestion/cfg/visitors/go.js +642 -0
  81. package/dist/core/code/engine/core/ingestion/cfg/visitors/java-harvest.js +517 -0
  82. package/dist/core/code/engine/core/ingestion/cfg/visitors/java.js +816 -0
  83. package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin-harvest.js +723 -0
  84. package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin.js +813 -0
  85. package/dist/core/code/engine/core/ingestion/cfg/visitors/php-harvest.js +630 -0
  86. package/dist/core/code/engine/core/ingestion/cfg/visitors/php.js +725 -0
  87. package/dist/core/code/engine/core/ingestion/cfg/visitors/python-harvest.js +776 -0
  88. package/dist/core/code/engine/core/ingestion/cfg/visitors/python.js +562 -0
  89. package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby-harvest.js +591 -0
  90. package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby.js +760 -0
  91. package/dist/core/code/engine/core/ingestion/cfg/visitors/rust-harvest.js +877 -0
  92. package/dist/core/code/engine/core/ingestion/cfg/visitors/rust.js +562 -0
  93. package/dist/core/code/engine/core/ingestion/cfg/visitors/scope-tree-harvest.js +120 -0
  94. package/dist/core/code/engine/core/ingestion/cfg/visitors/swift-harvest.js +683 -0
  95. package/dist/core/code/engine/core/ingestion/cfg/visitors/swift.js +791 -0
  96. package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript-harvest.js +1060 -0
  97. package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript.js +587 -0
  98. package/dist/core/code/engine/core/ingestion/class-extractors/configs/c-cpp.js +77 -0
  99. package/dist/core/code/engine/core/ingestion/class-extractors/configs/csharp.js +24 -0
  100. package/dist/core/code/engine/core/ingestion/class-extractors/configs/dart.js +10 -0
  101. package/dist/core/code/engine/core/ingestion/class-extractors/configs/go.js +28 -0
  102. package/dist/core/code/engine/core/ingestion/class-extractors/configs/jvm.js +67 -0
  103. package/dist/core/code/engine/core/ingestion/class-extractors/configs/php.js +10 -0
  104. package/dist/core/code/engine/core/ingestion/class-extractors/configs/python.js +10 -0
  105. package/dist/core/code/engine/core/ingestion/class-extractors/configs/ruby.js +13 -0
  106. package/dist/core/code/engine/core/ingestion/class-extractors/configs/rust.js +10 -0
  107. package/dist/core/code/engine/core/ingestion/class-extractors/configs/swift.js +21 -0
  108. package/dist/core/code/engine/core/ingestion/class-extractors/configs/typescript-javascript.js +31 -0
  109. package/dist/core/code/engine/core/ingestion/class-extractors/generic.js +144 -0
  110. package/dist/core/code/engine/core/ingestion/class-types.js +2 -0
  111. package/dist/core/code/engine/core/ingestion/cluster-enricher.js +174 -0
  112. package/dist/core/code/engine/core/ingestion/community-processor.js +604 -0
  113. package/dist/core/code/engine/core/ingestion/constants.js +26 -0
  114. package/dist/core/code/engine/core/ingestion/cpp-ue-preprocessor.js +263 -0
  115. package/dist/core/code/engine/core/ingestion/csharp-namespace-gate.js +133 -0
  116. package/dist/core/code/engine/core/ingestion/di-extractors/index.js +38 -0
  117. package/dist/core/code/engine/core/ingestion/di-extractors/spring.js +310 -0
  118. package/dist/core/code/engine/core/ingestion/emit-references.js +244 -0
  119. package/dist/core/code/engine/core/ingestion/entry-point-scoring.js +201 -0
  120. package/dist/core/code/engine/core/ingestion/export-detection.js +244 -0
  121. package/dist/core/code/engine/core/ingestion/field-extractor.js +29 -0
  122. package/dist/core/code/engine/core/ingestion/field-extractors/configs/c-cpp.js +107 -0
  123. package/dist/core/code/engine/core/ingestion/field-extractors/configs/csharp.js +124 -0
  124. package/dist/core/code/engine/core/ingestion/field-extractors/configs/dart.js +99 -0
  125. package/dist/core/code/engine/core/ingestion/field-extractors/configs/go.js +102 -0
  126. package/dist/core/code/engine/core/ingestion/field-extractors/configs/helpers.js +198 -0
  127. package/dist/core/code/engine/core/ingestion/field-extractors/configs/jvm.js +172 -0
  128. package/dist/core/code/engine/core/ingestion/field-extractors/configs/php.js +67 -0
  129. package/dist/core/code/engine/core/ingestion/field-extractors/configs/python.js +94 -0
  130. package/dist/core/code/engine/core/ingestion/field-extractors/configs/ruby.js +79 -0
  131. package/dist/core/code/engine/core/ingestion/field-extractors/configs/rust.js +55 -0
  132. package/dist/core/code/engine/core/ingestion/field-extractors/configs/swift.js +93 -0
  133. package/dist/core/code/engine/core/ingestion/field-extractors/configs/typescript-javascript.js +59 -0
  134. package/dist/core/code/engine/core/ingestion/field-extractors/generic.js +147 -0
  135. package/dist/core/code/engine/core/ingestion/field-extractors/typescript.js +266 -0
  136. package/dist/core/code/engine/core/ingestion/field-types.js +3 -0
  137. package/dist/core/code/engine/core/ingestion/filesystem-walker.js +136 -0
  138. package/dist/core/code/engine/core/ingestion/finalize-orchestrator.js +159 -0
  139. package/dist/core/code/engine/core/ingestion/framework-detection.js +432 -0
  140. package/dist/core/code/engine/core/ingestion/frameworks/spring/analysis-features.js +38 -0
  141. package/dist/core/code/engine/core/ingestion/frameworks/spring/annotation-arguments.js +234 -0
  142. package/dist/core/code/engine/core/ingestion/frameworks/spring/aop-candidates.js +88 -0
  143. package/dist/core/code/engine/core/ingestion/frameworks/spring/aop.js +487 -0
  144. package/dist/core/code/engine/core/ingestion/frameworks/spring/auto-configuration.js +21 -0
  145. package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-candidates.js +189 -0
  146. package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-catalog.js +32 -0
  147. package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-factories.js +73 -0
  148. package/dist/core/code/engine/core/ingestion/frameworks/spring/conditionals.js +323 -0
  149. package/dist/core/code/engine/core/ingestion/frameworks/spring/config-bindings.js +119 -0
  150. package/dist/core/code/engine/core/ingestion/frameworks/spring/di-metadata.js +385 -0
  151. package/dist/core/code/engine/core/ingestion/frameworks/spring/resource-injection.js +96 -0
  152. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/c-cpp.js +17 -0
  153. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/csharp.js +46 -0
  154. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/dart.js +59 -0
  155. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/go.js +30 -0
  156. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/jvm.js +73 -0
  157. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/php.js +19 -0
  158. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/python.js +45 -0
  159. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/ruby.js +20 -0
  160. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/rust.js +58 -0
  161. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/swift.js +94 -0
  162. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/typescript-javascript.js +26 -0
  163. package/dist/core/code/engine/core/ingestion/import-resolvers/csharp.js +128 -0
  164. package/dist/core/code/engine/core/ingestion/import-resolvers/go.js +50 -0
  165. package/dist/core/code/engine/core/ingestion/import-resolvers/jvm.js +112 -0
  166. package/dist/core/code/engine/core/ingestion/import-resolvers/php.js +80 -0
  167. package/dist/core/code/engine/core/ingestion/import-resolvers/python.js +75 -0
  168. package/dist/core/code/engine/core/ingestion/import-resolvers/resolver-factory.js +36 -0
  169. package/dist/core/code/engine/core/ingestion/import-resolvers/ruby.js +20 -0
  170. package/dist/core/code/engine/core/ingestion/import-resolvers/rust.js +79 -0
  171. package/dist/core/code/engine/core/ingestion/import-resolvers/standard.js +180 -0
  172. package/dist/core/code/engine/core/ingestion/import-resolvers/types.js +7 -0
  173. package/dist/core/code/engine/core/ingestion/import-resolvers/utils.js +153 -0
  174. package/dist/core/code/engine/core/ingestion/import-target-adapter.js +99 -0
  175. package/dist/core/code/engine/core/ingestion/language-config.js +391 -0
  176. package/dist/core/code/engine/core/ingestion/language-provider.js +25 -0
  177. package/dist/core/code/engine/core/ingestion/languages/c/arity-metadata.js +98 -0
  178. package/dist/core/code/engine/core/ingestion/languages/c/arity.js +21 -0
  179. package/dist/core/code/engine/core/ingestion/languages/c/capture-side-channel.js +69 -0
  180. package/dist/core/code/engine/core/ingestion/languages/c/captures.js +189 -0
  181. package/dist/core/code/engine/core/ingestion/languages/c/header-scan.js +58 -0
  182. package/dist/core/code/engine/core/ingestion/languages/c/import-decomposer.js +68 -0
  183. package/dist/core/code/engine/core/ingestion/languages/c/import-target.js +103 -0
  184. package/dist/core/code/engine/core/ingestion/languages/c/index.js +33 -0
  185. package/dist/core/code/engine/core/ingestion/languages/c/interpret.js +53 -0
  186. package/dist/core/code/engine/core/ingestion/languages/c/merge-bindings.js +26 -0
  187. package/dist/core/code/engine/core/ingestion/languages/c/query.js +210 -0
  188. package/dist/core/code/engine/core/ingestion/languages/c/scope-resolver.js +112 -0
  189. package/dist/core/code/engine/core/ingestion/languages/c/simple-hooks.js +24 -0
  190. package/dist/core/code/engine/core/ingestion/languages/c/static-linkage.js +109 -0
  191. package/dist/core/code/engine/core/ingestion/languages/c-cpp.js +506 -0
  192. package/dist/core/code/engine/core/ingestion/languages/cpp/adl.js +804 -0
  193. package/dist/core/code/engine/core/ingestion/languages/cpp/arity-metadata.js +258 -0
  194. package/dist/core/code/engine/core/ingestion/languages/cpp/arity.js +37 -0
  195. package/dist/core/code/engine/core/ingestion/languages/cpp/capture-side-channel.js +89 -0
  196. package/dist/core/code/engine/core/ingestion/languages/cpp/captures.js +1975 -0
  197. package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-extractor.js +311 -0
  198. package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-filter.js +210 -0
  199. package/dist/core/code/engine/core/ingestion/languages/cpp/conversion-rank.js +163 -0
  200. package/dist/core/code/engine/core/ingestion/languages/cpp/file-local-linkage.js +327 -0
  201. package/dist/core/code/engine/core/ingestion/languages/cpp/header-scan.js +53 -0
  202. package/dist/core/code/engine/core/ingestion/languages/cpp/import-decomposer.js +134 -0
  203. package/dist/core/code/engine/core/ingestion/languages/cpp/import-target.js +16 -0
  204. package/dist/core/code/engine/core/ingestion/languages/cpp/index.js +33 -0
  205. package/dist/core/code/engine/core/ingestion/languages/cpp/inline-namespaces.js +379 -0
  206. package/dist/core/code/engine/core/ingestion/languages/cpp/interpret.js +239 -0
  207. package/dist/core/code/engine/core/ingestion/languages/cpp/member-lookup.js +470 -0
  208. package/dist/core/code/engine/core/ingestion/languages/cpp/merge-bindings.js +32 -0
  209. package/dist/core/code/engine/core/ingestion/languages/cpp/query.js +763 -0
  210. package/dist/core/code/engine/core/ingestion/languages/cpp/range-bindings.js +230 -0
  211. package/dist/core/code/engine/core/ingestion/languages/cpp/scope-resolver.js +354 -0
  212. package/dist/core/code/engine/core/ingestion/languages/cpp/simple-hooks.js +67 -0
  213. package/dist/core/code/engine/core/ingestion/languages/cpp/two-phase-lookup.js +348 -0
  214. package/dist/core/code/engine/core/ingestion/languages/cpp/type-classifier.js +56 -0
  215. package/dist/core/code/engine/core/ingestion/languages/cpp/user-defined-conversions.js +128 -0
  216. package/dist/core/code/engine/core/ingestion/languages/csharp/accessor-unwrap.js +67 -0
  217. package/dist/core/code/engine/core/ingestion/languages/csharp/arity-metadata.js +49 -0
  218. package/dist/core/code/engine/core/ingestion/languages/csharp/arity.js +40 -0
  219. package/dist/core/code/engine/core/ingestion/languages/csharp/cache-stats.js +32 -0
  220. package/dist/core/code/engine/core/ingestion/languages/csharp/captures.js +557 -0
  221. package/dist/core/code/engine/core/ingestion/languages/csharp/import-decomposer.js +96 -0
  222. package/dist/core/code/engine/core/ingestion/languages/csharp/import-target.js +176 -0
  223. package/dist/core/code/engine/core/ingestion/languages/csharp/index.js +95 -0
  224. package/dist/core/code/engine/core/ingestion/languages/csharp/interpret.js +150 -0
  225. package/dist/core/code/engine/core/ingestion/languages/csharp/merge-bindings.js +58 -0
  226. package/dist/core/code/engine/core/ingestion/languages/csharp/namespace-siblings.js +708 -0
  227. package/dist/core/code/engine/core/ingestion/languages/csharp/qualified-type-names.js +62 -0
  228. package/dist/core/code/engine/core/ingestion/languages/csharp/query.js +578 -0
  229. package/dist/core/code/engine/core/ingestion/languages/csharp/receiver-binding.js +142 -0
  230. package/dist/core/code/engine/core/ingestion/languages/csharp/resolution-config.js +18 -0
  231. package/dist/core/code/engine/core/ingestion/languages/csharp/scope-resolver.js +84 -0
  232. package/dist/core/code/engine/core/ingestion/languages/csharp/simple-hooks.js +81 -0
  233. package/dist/core/code/engine/core/ingestion/languages/csharp.js +204 -0
  234. package/dist/core/code/engine/core/ingestion/languages/dart/arity-metadata.js +38 -0
  235. package/dist/core/code/engine/core/ingestion/languages/dart/arity.js +34 -0
  236. package/dist/core/code/engine/core/ingestion/languages/dart/built-ins.js +37 -0
  237. package/dist/core/code/engine/core/ingestion/languages/dart/cache-stats.js +30 -0
  238. package/dist/core/code/engine/core/ingestion/languages/dart/captures.js +1096 -0
  239. package/dist/core/code/engine/core/ingestion/languages/dart/expand-wildcards.js +34 -0
  240. package/dist/core/code/engine/core/ingestion/languages/dart/extension-type-preprocess.js +33 -0
  241. package/dist/core/code/engine/core/ingestion/languages/dart/import-target.js +68 -0
  242. package/dist/core/code/engine/core/ingestion/languages/dart/index.js +45 -0
  243. package/dist/core/code/engine/core/ingestion/languages/dart/interpret.js +101 -0
  244. package/dist/core/code/engine/core/ingestion/languages/dart/merge-bindings.js +42 -0
  245. package/dist/core/code/engine/core/ingestion/languages/dart/query.js +246 -0
  246. package/dist/core/code/engine/core/ingestion/languages/dart/receiver-binding.js +90 -0
  247. package/dist/core/code/engine/core/ingestion/languages/dart/scope-resolver.js +197 -0
  248. package/dist/core/code/engine/core/ingestion/languages/dart/signature-bindings.js +54 -0
  249. package/dist/core/code/engine/core/ingestion/languages/dart/simple-hooks.js +61 -0
  250. package/dist/core/code/engine/core/ingestion/languages/dart.js +138 -0
  251. package/dist/core/code/engine/core/ingestion/languages/go/arity-metadata.js +71 -0
  252. package/dist/core/code/engine/core/ingestion/languages/go/arity.js +17 -0
  253. package/dist/core/code/engine/core/ingestion/languages/go/cache-stats.js +21 -0
  254. package/dist/core/code/engine/core/ingestion/languages/go/captures.js +492 -0
  255. package/dist/core/code/engine/core/ingestion/languages/go/expand-wildcards.js +97 -0
  256. package/dist/core/code/engine/core/ingestion/languages/go/generic-type-parameters.js +146 -0
  257. package/dist/core/code/engine/core/ingestion/languages/go/import-decomposer.js +47 -0
  258. package/dist/core/code/engine/core/ingestion/languages/go/import-target.js +70 -0
  259. package/dist/core/code/engine/core/ingestion/languages/go/index.js +39 -0
  260. package/dist/core/code/engine/core/ingestion/languages/go/interface-impls.js +955 -0
  261. package/dist/core/code/engine/core/ingestion/languages/go/interpret.js +177 -0
  262. package/dist/core/code/engine/core/ingestion/languages/go/merge-bindings.js +21 -0
  263. package/dist/core/code/engine/core/ingestion/languages/go/method-owners.js +131 -0
  264. package/dist/core/code/engine/core/ingestion/languages/go/namespace-mirror.js +56 -0
  265. package/dist/core/code/engine/core/ingestion/languages/go/package-clause.js +79 -0
  266. package/dist/core/code/engine/core/ingestion/languages/go/package-siblings.js +83 -0
  267. package/dist/core/code/engine/core/ingestion/languages/go/query.js +298 -0
  268. package/dist/core/code/engine/core/ingestion/languages/go/range-binding.js +127 -0
  269. package/dist/core/code/engine/core/ingestion/languages/go/receiver-binding.js +24 -0
  270. package/dist/core/code/engine/core/ingestion/languages/go/scope-resolver.js +75 -0
  271. package/dist/core/code/engine/core/ingestion/languages/go/simple-hooks.js +31 -0
  272. package/dist/core/code/engine/core/ingestion/languages/go/type-binding.js +279 -0
  273. package/dist/core/code/engine/core/ingestion/languages/go.js +160 -0
  274. package/dist/core/code/engine/core/ingestion/languages/index.js +66 -0
  275. package/dist/core/code/engine/core/ingestion/languages/java/analysis-features.js +16 -0
  276. package/dist/core/code/engine/core/ingestion/languages/java/arity-metadata.js +43 -0
  277. package/dist/core/code/engine/core/ingestion/languages/java/arity.js +27 -0
  278. package/dist/core/code/engine/core/ingestion/languages/java/cache-stats.js +32 -0
  279. package/dist/core/code/engine/core/ingestion/languages/java/capture-side-channel.js +123 -0
  280. package/dist/core/code/engine/core/ingestion/languages/java/captures.js +791 -0
  281. package/dist/core/code/engine/core/ingestion/languages/java/import-decomposer.js +88 -0
  282. package/dist/core/code/engine/core/ingestion/languages/java/import-target.js +103 -0
  283. package/dist/core/code/engine/core/ingestion/languages/java/index.js +43 -0
  284. package/dist/core/code/engine/core/ingestion/languages/java/interpret.js +146 -0
  285. package/dist/core/code/engine/core/ingestion/languages/java/merge-bindings.js +43 -0
  286. package/dist/core/code/engine/core/ingestion/languages/java/package-facts.js +16 -0
  287. package/dist/core/code/engine/core/ingestion/languages/java/package-siblings.js +11 -0
  288. package/dist/core/code/engine/core/ingestion/languages/java/query.js +319 -0
  289. package/dist/core/code/engine/core/ingestion/languages/java/receiver-binding.js +98 -0
  290. package/dist/core/code/engine/core/ingestion/languages/java/scope-resolver.js +213 -0
  291. package/dist/core/code/engine/core/ingestion/languages/java/simple-hooks.js +39 -0
  292. package/dist/core/code/engine/core/ingestion/languages/java/spring-aop.js +53 -0
  293. package/dist/core/code/engine/core/ingestion/languages/java/spring-bean-metadata.js +11 -0
  294. package/dist/core/code/engine/core/ingestion/languages/java/spring-conditionals.js +52 -0
  295. package/dist/core/code/engine/core/ingestion/languages/java/spring-config-bindings.js +222 -0
  296. package/dist/core/code/engine/core/ingestion/languages/java/spring-di.js +165 -0
  297. package/dist/core/code/engine/core/ingestion/languages/java.js +192 -0
  298. package/dist/core/code/engine/core/ingestion/languages/javascript/arity.js +15 -0
  299. package/dist/core/code/engine/core/ingestion/languages/javascript/captures.js +1122 -0
  300. package/dist/core/code/engine/core/ingestion/languages/javascript/import-target.js +56 -0
  301. package/dist/core/code/engine/core/ingestion/languages/javascript/index.js +109 -0
  302. package/dist/core/code/engine/core/ingestion/languages/javascript/interpret.js +45 -0
  303. package/dist/core/code/engine/core/ingestion/languages/javascript/merge-bindings.js +21 -0
  304. package/dist/core/code/engine/core/ingestion/languages/javascript/query.js +659 -0
  305. package/dist/core/code/engine/core/ingestion/languages/javascript/scope-resolver.js +78 -0
  306. package/dist/core/code/engine/core/ingestion/languages/javascript/simple-hooks.js +44 -0
  307. package/dist/core/code/engine/core/ingestion/languages/jvm/package-facts.js +46 -0
  308. package/dist/core/code/engine/core/ingestion/languages/jvm/package-siblings.js +200 -0
  309. package/dist/core/code/engine/core/ingestion/languages/kotlin/arity-metadata.js +23 -0
  310. package/dist/core/code/engine/core/ingestion/languages/kotlin/arity.js +18 -0
  311. package/dist/core/code/engine/core/ingestion/languages/kotlin/cache-stats.js +21 -0
  312. package/dist/core/code/engine/core/ingestion/languages/kotlin/capture-side-channel.js +160 -0
  313. package/dist/core/code/engine/core/ingestion/languages/kotlin/captures.js +1262 -0
  314. package/dist/core/code/engine/core/ingestion/languages/kotlin/companion-scopes.js +72 -0
  315. package/dist/core/code/engine/core/ingestion/languages/kotlin/import-decomposer.js +40 -0
  316. package/dist/core/code/engine/core/ingestion/languages/kotlin/import-target.js +135 -0
  317. package/dist/core/code/engine/core/ingestion/languages/kotlin/index.js +26 -0
  318. package/dist/core/code/engine/core/ingestion/languages/kotlin/interpret.js +75 -0
  319. package/dist/core/code/engine/core/ingestion/languages/kotlin/merge-bindings.js +28 -0
  320. package/dist/core/code/engine/core/ingestion/languages/kotlin/owners.js +134 -0
  321. package/dist/core/code/engine/core/ingestion/languages/kotlin/package-facts.js +16 -0
  322. package/dist/core/code/engine/core/ingestion/languages/kotlin/package-siblings.js +11 -0
  323. package/dist/core/code/engine/core/ingestion/languages/kotlin/query.js +243 -0
  324. package/dist/core/code/engine/core/ingestion/languages/kotlin/receiver-binding.js +103 -0
  325. package/dist/core/code/engine/core/ingestion/languages/kotlin/scope-resolver.js +207 -0
  326. package/dist/core/code/engine/core/ingestion/languages/kotlin/simple-hooks.js +42 -0
  327. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-aop.js +68 -0
  328. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-bean-metadata.js +11 -0
  329. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-conditionals.js +53 -0
  330. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-di.js +304 -0
  331. package/dist/core/code/engine/core/ingestion/languages/kotlin.js +189 -0
  332. package/dist/core/code/engine/core/ingestion/languages/php/arity-metadata.js +66 -0
  333. package/dist/core/code/engine/core/ingestion/languages/php/arity.js +43 -0
  334. package/dist/core/code/engine/core/ingestion/languages/php/cache-stats.js +32 -0
  335. package/dist/core/code/engine/core/ingestion/languages/php/captures.js +1166 -0
  336. package/dist/core/code/engine/core/ingestion/languages/php/import-decomposer.js +238 -0
  337. package/dist/core/code/engine/core/ingestion/languages/php/import-target.js +213 -0
  338. package/dist/core/code/engine/core/ingestion/languages/php/index.js +85 -0
  339. package/dist/core/code/engine/core/ingestion/languages/php/interpret.js +256 -0
  340. package/dist/core/code/engine/core/ingestion/languages/php/merge-bindings.js +50 -0
  341. package/dist/core/code/engine/core/ingestion/languages/php/namespace-siblings.js +353 -0
  342. package/dist/core/code/engine/core/ingestion/languages/php/query.js +391 -0
  343. package/dist/core/code/engine/core/ingestion/languages/php/receiver-binding.js +135 -0
  344. package/dist/core/code/engine/core/ingestion/languages/php/scope-resolver.js +361 -0
  345. package/dist/core/code/engine/core/ingestion/languages/php/simple-hooks.js +116 -0
  346. package/dist/core/code/engine/core/ingestion/languages/php.js +302 -0
  347. package/dist/core/code/engine/core/ingestion/languages/python/arity-metadata.js +49 -0
  348. package/dist/core/code/engine/core/ingestion/languages/python/arity.js +41 -0
  349. package/dist/core/code/engine/core/ingestion/languages/python/cache-stats.js +34 -0
  350. package/dist/core/code/engine/core/ingestion/languages/python/captures.js +299 -0
  351. package/dist/core/code/engine/core/ingestion/languages/python/depends-references.js +68 -0
  352. package/dist/core/code/engine/core/ingestion/languages/python/import-decomposer.js +115 -0
  353. package/dist/core/code/engine/core/ingestion/languages/python/import-target.js +440 -0
  354. package/dist/core/code/engine/core/ingestion/languages/python/index-stats.js +30 -0
  355. package/dist/core/code/engine/core/ingestion/languages/python/index.js +96 -0
  356. package/dist/core/code/engine/core/ingestion/languages/python/interpret.js +430 -0
  357. package/dist/core/code/engine/core/ingestion/languages/python/merge-bindings.js +47 -0
  358. package/dist/core/code/engine/core/ingestion/languages/python/query.js +323 -0
  359. package/dist/core/code/engine/core/ingestion/languages/python/receiver-binding.js +310 -0
  360. package/dist/core/code/engine/core/ingestion/languages/python/scope-resolver.js +80 -0
  361. package/dist/core/code/engine/core/ingestion/languages/python/simple-hooks.js +53 -0
  362. package/dist/core/code/engine/core/ingestion/languages/python.js +140 -0
  363. package/dist/core/code/engine/core/ingestion/languages/ruby/arity.js +41 -0
  364. package/dist/core/code/engine/core/ingestion/languages/ruby/cache-stats.js +21 -0
  365. package/dist/core/code/engine/core/ingestion/languages/ruby/captures.js +864 -0
  366. package/dist/core/code/engine/core/ingestion/languages/ruby/import-target.js +88 -0
  367. package/dist/core/code/engine/core/ingestion/languages/ruby/index.js +29 -0
  368. package/dist/core/code/engine/core/ingestion/languages/ruby/interpret.js +115 -0
  369. package/dist/core/code/engine/core/ingestion/languages/ruby/merge-bindings.js +21 -0
  370. package/dist/core/code/engine/core/ingestion/languages/ruby/query.js +349 -0
  371. package/dist/core/code/engine/core/ingestion/languages/ruby/receiver-binding.js +70 -0
  372. package/dist/core/code/engine/core/ingestion/languages/ruby/scope-resolver.js +263 -0
  373. package/dist/core/code/engine/core/ingestion/languages/ruby/simple-hooks.js +68 -0
  374. package/dist/core/code/engine/core/ingestion/languages/ruby.js +215 -0
  375. package/dist/core/code/engine/core/ingestion/languages/rust/arity.js +16 -0
  376. package/dist/core/code/engine/core/ingestion/languages/rust/cache-stats.js +21 -0
  377. package/dist/core/code/engine/core/ingestion/languages/rust/captures.js +304 -0
  378. package/dist/core/code/engine/core/ingestion/languages/rust/import-decomposer.js +167 -0
  379. package/dist/core/code/engine/core/ingestion/languages/rust/import-target.js +108 -0
  380. package/dist/core/code/engine/core/ingestion/languages/rust/index.js +29 -0
  381. package/dist/core/code/engine/core/ingestion/languages/rust/interpret.js +201 -0
  382. package/dist/core/code/engine/core/ingestion/languages/rust/merge-bindings.js +21 -0
  383. package/dist/core/code/engine/core/ingestion/languages/rust/method-owners.js +76 -0
  384. package/dist/core/code/engine/core/ingestion/languages/rust/module-path.js +222 -0
  385. package/dist/core/code/engine/core/ingestion/languages/rust/qualified-call.js +482 -0
  386. package/dist/core/code/engine/core/ingestion/languages/rust/query.js +280 -0
  387. package/dist/core/code/engine/core/ingestion/languages/rust/range-binding.js +687 -0
  388. package/dist/core/code/engine/core/ingestion/languages/rust/receiver-binding.js +148 -0
  389. package/dist/core/code/engine/core/ingestion/languages/rust/scope-resolver.js +151 -0
  390. package/dist/core/code/engine/core/ingestion/languages/rust/simple-hooks.js +32 -0
  391. package/dist/core/code/engine/core/ingestion/languages/rust.js +183 -0
  392. package/dist/core/code/engine/core/ingestion/languages/swift/arity-metadata.js +44 -0
  393. package/dist/core/code/engine/core/ingestion/languages/swift/arity.js +45 -0
  394. package/dist/core/code/engine/core/ingestion/languages/swift/base-type.js +30 -0
  395. package/dist/core/code/engine/core/ingestion/languages/swift/cache-stats.js +32 -0
  396. package/dist/core/code/engine/core/ingestion/languages/swift/captures.js +594 -0
  397. package/dist/core/code/engine/core/ingestion/languages/swift/conditional-directive-preprocess.js +256 -0
  398. package/dist/core/code/engine/core/ingestion/languages/swift/implicit-imports.js +60 -0
  399. package/dist/core/code/engine/core/ingestion/languages/swift/import-decomposer.js +87 -0
  400. package/dist/core/code/engine/core/ingestion/languages/swift/import-target.js +84 -0
  401. package/dist/core/code/engine/core/ingestion/languages/swift/index.js +56 -0
  402. package/dist/core/code/engine/core/ingestion/languages/swift/interpret.js +93 -0
  403. package/dist/core/code/engine/core/ingestion/languages/swift/merge-bindings.js +51 -0
  404. package/dist/core/code/engine/core/ingestion/languages/swift/query.js +226 -0
  405. package/dist/core/code/engine/core/ingestion/languages/swift/receiver-binding.js +169 -0
  406. package/dist/core/code/engine/core/ingestion/languages/swift/scope-resolver.js +192 -0
  407. package/dist/core/code/engine/core/ingestion/languages/swift/sibling-type-bindings.js +68 -0
  408. package/dist/core/code/engine/core/ingestion/languages/swift/signature-bindings.js +69 -0
  409. package/dist/core/code/engine/core/ingestion/languages/swift/simple-hooks.js +65 -0
  410. package/dist/core/code/engine/core/ingestion/languages/swift/target-grouping.js +97 -0
  411. package/dist/core/code/engine/core/ingestion/languages/swift/target-siblings.js +74 -0
  412. package/dist/core/code/engine/core/ingestion/languages/swift.js +246 -0
  413. package/dist/core/code/engine/core/ingestion/languages/typescript/arity-metadata.js +106 -0
  414. package/dist/core/code/engine/core/ingestion/languages/typescript/arity.js +57 -0
  415. package/dist/core/code/engine/core/ingestion/languages/typescript/array-callback.js +58 -0
  416. package/dist/core/code/engine/core/ingestion/languages/typescript/cache-stats.js +34 -0
  417. package/dist/core/code/engine/core/ingestion/languages/typescript/captures.js +956 -0
  418. package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-export-assignment.js +535 -0
  419. package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-module-exports.js +196 -0
  420. package/dist/core/code/engine/core/ingestion/languages/typescript/import-decomposer.js +374 -0
  421. package/dist/core/code/engine/core/ingestion/languages/typescript/import-target.js +65 -0
  422. package/dist/core/code/engine/core/ingestion/languages/typescript/index.js +108 -0
  423. package/dist/core/code/engine/core/ingestion/languages/typescript/interpret.js +344 -0
  424. package/dist/core/code/engine/core/ingestion/languages/typescript/merge-bindings.js +161 -0
  425. package/dist/core/code/engine/core/ingestion/languages/typescript/nuxt-auto-imports.js +325 -0
  426. package/dist/core/code/engine/core/ingestion/languages/typescript/query.js +1328 -0
  427. package/dist/core/code/engine/core/ingestion/languages/typescript/receiver-binding.js +201 -0
  428. package/dist/core/code/engine/core/ingestion/languages/typescript/scope-resolver.js +293 -0
  429. package/dist/core/code/engine/core/ingestion/languages/typescript/simple-hooks.js +139 -0
  430. package/dist/core/code/engine/core/ingestion/languages/typescript.js +455 -0
  431. package/dist/core/code/engine/core/ingestion/languages/vue/captures.js +70 -0
  432. package/dist/core/code/engine/core/ingestion/languages/vue/import-target.js +61 -0
  433. package/dist/core/code/engine/core/ingestion/languages/vue/index.js +55 -0
  434. package/dist/core/code/engine/core/ingestion/languages/vue/scope-resolver.js +295 -0
  435. package/dist/core/code/engine/core/ingestion/languages/vue.js +96 -0
  436. package/dist/core/code/engine/core/ingestion/local-symbol-pruner.js +68 -0
  437. package/dist/core/code/engine/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
  438. package/dist/core/code/engine/core/ingestion/method-extractors/configs/csharp.js +290 -0
  439. package/dist/core/code/engine/core/ingestion/method-extractors/configs/dart.js +392 -0
  440. package/dist/core/code/engine/core/ingestion/method-extractors/configs/go.js +179 -0
  441. package/dist/core/code/engine/core/ingestion/method-extractors/configs/jvm.js +350 -0
  442. package/dist/core/code/engine/core/ingestion/method-extractors/configs/php.js +306 -0
  443. package/dist/core/code/engine/core/ingestion/method-extractors/configs/python.js +312 -0
  444. package/dist/core/code/engine/core/ingestion/method-extractors/configs/ruby.js +289 -0
  445. package/dist/core/code/engine/core/ingestion/method-extractors/configs/rust.js +198 -0
  446. package/dist/core/code/engine/core/ingestion/method-extractors/configs/swift.js +286 -0
  447. package/dist/core/code/engine/core/ingestion/method-extractors/configs/typescript-javascript.js +341 -0
  448. package/dist/core/code/engine/core/ingestion/method-extractors/generic.js +209 -0
  449. package/dist/core/code/engine/core/ingestion/method-types.js +3 -0
  450. package/dist/core/code/engine/core/ingestion/model/field-registry.js +41 -0
  451. package/dist/core/code/engine/core/ingestion/model/index.js +52 -0
  452. package/dist/core/code/engine/core/ingestion/model/method-registry.js +138 -0
  453. package/dist/core/code/engine/core/ingestion/model/owned-members-lookup.js +46 -0
  454. package/dist/core/code/engine/core/ingestion/model/registration-table.js +234 -0
  455. package/dist/core/code/engine/core/ingestion/model/resolve.js +183 -0
  456. package/dist/core/code/engine/core/ingestion/model/scope-resolution-indexes.js +43 -0
  457. package/dist/core/code/engine/core/ingestion/model/semantic-model.js +179 -0
  458. package/dist/core/code/engine/core/ingestion/model/symbol-table.js +216 -0
  459. package/dist/core/code/engine/core/ingestion/model/type-registry.js +84 -0
  460. package/dist/core/code/engine/core/ingestion/mro-processor.js +709 -0
  461. package/dist/core/code/engine/core/ingestion/parsing-processor.js +312 -0
  462. package/dist/core/code/engine/core/ingestion/pipeline-phases/communities.js +69 -0
  463. package/dist/core/code/engine/core/ingestion/pipeline-phases/cross-file.js +71 -0
  464. package/dist/core/code/engine/core/ingestion/pipeline-phases/di.js +338 -0
  465. package/dist/core/code/engine/core/ingestion/pipeline-phases/http-api-calls.js +312 -0
  466. package/dist/core/code/engine/core/ingestion/pipeline-phases/index.js +54 -0
  467. package/dist/core/code/engine/core/ingestion/pipeline-phases/mro.js +40 -0
  468. package/dist/core/code/engine/core/ingestion/pipeline-phases/orm.js +78 -0
  469. package/dist/core/code/engine/core/ingestion/pipeline-phases/parse-impl.js +1286 -0
  470. package/dist/core/code/engine/core/ingestion/pipeline-phases/parse.js +41 -0
  471. package/dist/core/code/engine/core/ingestion/pipeline-phases/processes.js +193 -0
  472. package/dist/core/code/engine/core/ingestion/pipeline-phases/prune-local-symbols.js +29 -0
  473. package/dist/core/code/engine/core/ingestion/pipeline-phases/registry.js +52 -0
  474. package/dist/core/code/engine/core/ingestion/pipeline-phases/routes.js +409 -0
  475. package/dist/core/code/engine/core/ingestion/pipeline-phases/rpc-edges.js +301 -0
  476. package/dist/core/code/engine/core/ingestion/pipeline-phases/runner.js +207 -0
  477. package/dist/core/code/engine/core/ingestion/pipeline-phases/scan.js +49 -0
  478. package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-aop.js +442 -0
  479. package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-auto-configuration.js +264 -0
  480. package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-config.js +440 -0
  481. package/dist/core/code/engine/core/ingestion/pipeline-phases/structure.js +38 -0
  482. package/dist/core/code/engine/core/ingestion/pipeline-phases/tools.js +89 -0
  483. package/dist/core/code/engine/core/ingestion/pipeline-phases/types.js +40 -0
  484. package/dist/core/code/engine/core/ingestion/pipeline.js +152 -0
  485. package/dist/core/code/engine/core/ingestion/process-processor.js +325 -0
  486. package/dist/core/code/engine/core/ingestion/resolve-references.js +205 -0
  487. package/dist/core/code/engine/core/ingestion/route-extractors/constant-resolver.js +135 -0
  488. package/dist/core/code/engine/core/ingestion/route-extractors/django-root-discovery.js +221 -0
  489. package/dist/core/code/engine/core/ingestion/route-extractors/django.js +428 -0
  490. package/dist/core/code/engine/core/ingestion/route-extractors/expo.js +39 -0
  491. package/dist/core/code/engine/core/ingestion/route-extractors/fastapi-router-bindings.js +264 -0
  492. package/dist/core/code/engine/core/ingestion/route-extractors/laravel.js +501 -0
  493. package/dist/core/code/engine/core/ingestion/route-extractors/middleware.js +175 -0
  494. package/dist/core/code/engine/core/ingestion/route-extractors/nextjs.js +81 -0
  495. package/dist/core/code/engine/core/ingestion/route-extractors/php.js +25 -0
  496. package/dist/core/code/engine/core/ingestion/route-extractors/python-const-resolver.js +307 -0
  497. package/dist/core/code/engine/core/ingestion/route-extractors/response-shapes.js +299 -0
  498. package/dist/core/code/engine/core/ingestion/route-extractors/route-path.js +71 -0
  499. package/dist/core/code/engine/core/ingestion/route-extractors/spring-shared.js +310 -0
  500. package/dist/core/code/engine/core/ingestion/route-extractors/spring.js +441 -0
  501. package/dist/core/code/engine/core/ingestion/scope-extractor-bridge.js +60 -0
  502. package/dist/core/code/engine/core/ingestion/scope-extractor.js +1373 -0
  503. package/dist/core/code/engine/core/ingestion/scope-resolution/contract/scope-resolver.js +282 -0
  504. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +72 -0
  505. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/edges.js +194 -0
  506. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/ids.js +472 -0
  507. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +49 -0
  508. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +43 -0
  509. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +274 -0
  510. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +93 -0
  511. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/callable-value-flow.js +1240 -0
  512. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/compound-receiver.js +1174 -0
  513. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/free-call-fallback.js +873 -0
  514. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/imported-return-types.js +226 -0
  515. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/mro.js +107 -0
  516. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/overload-narrowing.js +441 -0
  517. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/property-dispatch.js +122 -0
  518. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +1720 -0
  519. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/phase.js +395 -0
  520. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +208 -0
  521. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/registry.js +49 -0
  522. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/run.js +632 -0
  523. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.js +112 -0
  524. package/dist/core/code/engine/core/ingestion/scope-resolution/resolution-outcome.js +41 -0
  525. package/dist/core/code/engine/core/ingestion/scope-resolution/scope/namespace-targets.js +81 -0
  526. package/dist/core/code/engine/core/ingestion/scope-resolution/scope/walkers.js +1835 -0
  527. package/dist/core/code/engine/core/ingestion/scope-resolution/unresolved-receivers.js +242 -0
  528. package/dist/core/code/engine/core/ingestion/scope-resolution/utils/definition-id.js +22 -0
  529. package/dist/core/code/engine/core/ingestion/scope-resolution/workspace-index.js +151 -0
  530. package/dist/core/code/engine/core/ingestion/structure-processor.js +40 -0
  531. package/dist/core/code/engine/core/ingestion/tree-sitter-queries.js +2244 -0
  532. package/dist/core/code/engine/core/ingestion/ts-js-hoc-utils.js +115 -0
  533. package/dist/core/code/engine/core/ingestion/type-env.js +1136 -0
  534. package/dist/core/code/engine/core/ingestion/type-extractors/c-cpp.js +555 -0
  535. package/dist/core/code/engine/core/ingestion/type-extractors/csharp.js +570 -0
  536. package/dist/core/code/engine/core/ingestion/type-extractors/dart.js +372 -0
  537. package/dist/core/code/engine/core/ingestion/type-extractors/go.js +508 -0
  538. package/dist/core/code/engine/core/ingestion/type-extractors/jvm.js +875 -0
  539. package/dist/core/code/engine/core/ingestion/type-extractors/php.js +537 -0
  540. package/dist/core/code/engine/core/ingestion/type-extractors/python.js +477 -0
  541. package/dist/core/code/engine/core/ingestion/type-extractors/ruby.js +380 -0
  542. package/dist/core/code/engine/core/ingestion/type-extractors/rust.js +502 -0
  543. package/dist/core/code/engine/core/ingestion/type-extractors/shared.js +843 -0
  544. package/dist/core/code/engine/core/ingestion/type-extractors/swift.js +490 -0
  545. package/dist/core/code/engine/core/ingestion/type-extractors/types.js +2 -0
  546. package/dist/core/code/engine/core/ingestion/type-extractors/typescript.js +690 -0
  547. package/dist/core/code/engine/core/ingestion/utils/ast-helpers.js +1693 -0
  548. package/dist/core/code/engine/core/ingestion/utils/call-analysis.js +779 -0
  549. package/dist/core/code/engine/core/ingestion/utils/callable-flow-captures.js +932 -0
  550. package/dist/core/code/engine/core/ingestion/utils/callable-labels.js +49 -0
  551. package/dist/core/code/engine/core/ingestion/utils/deferred-resolution-profile.js +151 -0
  552. package/dist/core/code/engine/core/ingestion/utils/effective-ram.js +67 -0
  553. package/dist/core/code/engine/core/ingestion/utils/env.js +60 -0
  554. package/dist/core/code/engine/core/ingestion/utils/event-loop.js +9 -0
  555. package/dist/core/code/engine/core/ingestion/utils/graph-sort.js +103 -0
  556. package/dist/core/code/engine/core/ingestion/utils/heap-probe.js +45 -0
  557. package/dist/core/code/engine/core/ingestion/utils/heritage-marker.js +47 -0
  558. package/dist/core/code/engine/core/ingestion/utils/line-base.js +24 -0
  559. package/dist/core/code/engine/core/ingestion/utils/max-file-size.js +59 -0
  560. package/dist/core/code/engine/core/ingestion/utils/method-props.js +198 -0
  561. package/dist/core/code/engine/core/ingestion/utils/qualified-name.js +73 -0
  562. package/dist/core/code/engine/core/ingestion/utils/receiver-chain-captures.js +60 -0
  563. package/dist/core/code/engine/core/ingestion/utils/receiver-chain-codec.js +188 -0
  564. package/dist/core/code/engine/core/ingestion/utils/scope-tree-walk.js +36 -0
  565. package/dist/core/code/engine/core/ingestion/utils/symbol-labels.js +48 -0
  566. package/dist/core/code/engine/core/ingestion/utils/template-arguments.js +187 -0
  567. package/dist/core/code/engine/core/ingestion/utils/type-parameters.js +209 -0
  568. package/dist/core/code/engine/core/ingestion/utils/verbose.js +6 -0
  569. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/c-cpp.js +133 -0
  570. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/csharp.js +66 -0
  571. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/dart.js +111 -0
  572. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/go.js +153 -0
  573. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/jvm.js +145 -0
  574. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/php.js +61 -0
  575. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/python.js +104 -0
  576. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/ruby.js +55 -0
  577. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/rust.js +79 -0
  578. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/swift.js +91 -0
  579. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/typescript-javascript.js +86 -0
  580. package/dist/core/code/engine/core/ingestion/variable-extractors/generic.js +111 -0
  581. package/dist/core/code/engine/core/ingestion/variable-types.js +3 -0
  582. package/dist/core/code/engine/core/ingestion/vue-sfc-extractor.js +544 -0
  583. package/dist/core/code/engine/core/ingestion/workers/callable-id.js +122 -0
  584. package/dist/core/code/engine/core/ingestion/workers/clone-safety.js +470 -0
  585. package/dist/core/code/engine/core/ingestion/workers/parse-worker.js +2456 -0
  586. package/dist/core/code/engine/core/ingestion/workers/post-result.js +90 -0
  587. package/dist/core/code/engine/core/ingestion/workers/quarantine.js +41 -0
  588. package/dist/core/code/engine/core/ingestion/workers/result-merge.js +59 -0
  589. package/dist/core/code/engine/core/ingestion/workers/worker-pool.js +1725 -0
  590. package/dist/core/code/engine/core/ingestion/workspace-config.js +139 -0
  591. package/dist/core/code/engine/core/lbug/conn-lock.js +72 -0
  592. package/dist/core/code/engine/core/lbug/csv-generator.js +710 -0
  593. package/dist/core/code/engine/core/lbug/cypher-escape.js +24 -0
  594. package/dist/core/code/engine/core/lbug/extension-load-error.js +339 -0
  595. package/dist/core/code/engine/core/lbug/extension-loader.js +261 -0
  596. package/dist/core/code/engine/core/lbug/graph-emit-sink.js +584 -0
  597. package/dist/core/code/engine/core/lbug/lbug-adapter.js +2703 -0
  598. package/dist/core/code/engine/core/lbug/lbug-config.js +1029 -0
  599. package/dist/core/code/engine/core/lbug/native-check.js +435 -0
  600. package/dist/core/code/engine/core/lbug/pool-adapter.js +973 -0
  601. package/dist/core/code/engine/core/lbug/query-params.js +25 -0
  602. package/dist/core/code/engine/core/lbug/query-result-utils.js +31 -0
  603. package/dist/core/code/engine/core/lbug/rel-pair-routing.js +373 -0
  604. package/dist/core/code/engine/core/lbug/schema.js +771 -0
  605. package/dist/core/code/engine/core/lbug/shutdown-helpers.js +40 -0
  606. package/dist/core/code/engine/core/lbug/sidecar-recovery.js +716 -0
  607. package/dist/core/code/engine/core/lbug/stdio-capture.js +49 -0
  608. package/dist/core/code/engine/core/lbug/sync-csv-writer.js +115 -0
  609. package/dist/core/code/engine/core/lbug/wal-checkpoint-driver.js +215 -0
  610. package/dist/core/code/engine/core/lbug/wal-driver-state.js +28 -0
  611. package/dist/core/code/engine/core/logger.js +339 -0
  612. package/dist/core/code/engine/core/platform/capabilities.js +91 -0
  613. package/dist/core/code/engine/core/run-analyze.js +1098 -0
  614. package/dist/core/code/engine/core/tree-sitter/parser-loader.js +281 -0
  615. package/dist/core/code/engine/core/tree-sitter/safe-parse.js +258 -0
  616. package/dist/core/code/engine/core/tree-sitter/vendored-grammars.js +64 -0
  617. package/dist/core/code/engine/lib/utils.js +121 -0
  618. package/dist/core/code/engine/mcp/core/lbug-adapter.js +27 -0
  619. package/dist/core/code/engine/mcp/local/aop-metadata.js +230 -0
  620. package/dist/core/code/engine/mcp/local/bean-metadata.js +49 -0
  621. package/dist/core/code/engine/mcp/local/limits.js +15 -0
  622. package/dist/core/code/engine/mcp/local/line-display.js +6 -0
  623. package/dist/core/code/engine/mcp/local/local-backend.js +4142 -0
  624. package/dist/core/code/engine/storage/branch-index.js +72 -0
  625. package/dist/core/code/engine/storage/file-hash.js +95 -0
  626. package/dist/core/code/engine/storage/fs-atomic.js +34 -0
  627. package/dist/core/code/engine/storage/git.js +555 -0
  628. package/dist/core/code/engine/storage/index-lock.js +664 -0
  629. package/dist/core/code/engine/storage/parse-cache.js +650 -0
  630. package/dist/core/code/engine/storage/parsedfile-store.js +620 -0
  631. package/dist/core/code/engine/storage/repo-manager.js +1061 -0
  632. package/dist/core/code/engine/storage/scope-index-store.js +247 -0
  633. package/dist/core/code/engine/types/pipeline.js +2 -0
  634. package/dist/core/code/scripts/install-duckdb-extension.mjs +125 -0
  635. package/dist/core/code/scripts/resolve-analyze-cmd.cjs +346 -0
  636. package/dist/core/code/shared/graph/types.js +8 -0
  637. package/dist/core/code/shared/index.js +105 -0
  638. package/dist/core/code/shared/integrations/circuit-breaker.js +242 -0
  639. package/dist/core/code/shared/integrations/resilient-fetch.js +224 -0
  640. package/dist/core/code/shared/integrations/retry.js +70 -0
  641. package/dist/core/code/shared/integrations/understand-quickly.js +145 -0
  642. package/dist/core/code/shared/language-detection.js +162 -0
  643. package/dist/core/code/shared/languages.js +27 -0
  644. package/dist/core/code/shared/lbug/schema-constants.js +98 -0
  645. package/dist/core/code/shared/mro-strategy.js +2 -0
  646. package/dist/core/code/shared/pipeline.js +5 -0
  647. package/dist/core/code/shared/scope-resolution/callable-flow-site.js +11 -0
  648. package/dist/core/code/shared/scope-resolution/def-index.js +53 -0
  649. package/dist/core/code/shared/scope-resolution/evidence-weights.js +87 -0
  650. package/dist/core/code/shared/scope-resolution/finalize-algorithm.js +807 -0
  651. package/dist/core/code/shared/scope-resolution/language-classification.js +46 -0
  652. package/dist/core/code/shared/scope-resolution/method-dispatch-index.js +100 -0
  653. package/dist/core/code/shared/scope-resolution/module-scope-index.js +59 -0
  654. package/dist/core/code/shared/scope-resolution/origin-priority.js +23 -0
  655. package/dist/core/code/shared/scope-resolution/parsed-file.js +54 -0
  656. package/dist/core/code/shared/scope-resolution/position-index.js +136 -0
  657. package/dist/core/code/shared/scope-resolution/qualified-name-index.js +77 -0
  658. package/dist/core/code/shared/scope-resolution/reference-site.js +24 -0
  659. package/dist/core/code/shared/scope-resolution/registries/class-registry.js +32 -0
  660. package/dist/core/code/shared/scope-resolution/registries/context.js +52 -0
  661. package/dist/core/code/shared/scope-resolution/registries/evidence.js +152 -0
  662. package/dist/core/code/shared/scope-resolution/registries/field-registry.js +33 -0
  663. package/dist/core/code/shared/scope-resolution/registries/lookup-core.js +392 -0
  664. package/dist/core/code/shared/scope-resolution/registries/lookup-qualified.js +58 -0
  665. package/dist/core/code/shared/scope-resolution/registries/macro-registry.js +34 -0
  666. package/dist/core/code/shared/scope-resolution/registries/method-registry.js +34 -0
  667. package/dist/core/code/shared/scope-resolution/registries/tie-breaks.js +63 -0
  668. package/dist/core/code/shared/scope-resolution/resolve-type-ref.js +128 -0
  669. package/dist/core/code/shared/scope-resolution/scope-id.js +49 -0
  670. package/dist/core/code/shared/scope-resolution/scope-tree.js +225 -0
  671. package/dist/core/code/shared/scope-resolution/symbol-definition.js +12 -0
  672. package/dist/core/code/shared/scope-resolution/types.js +25 -0
  673. package/dist/core/code/shared/test-helpers.js +17 -0
  674. package/dist/core/code/vendor/leiden/index.cjs +355 -0
  675. package/dist/core/code/vendor/leiden/utils.cjs +419 -0
  676. package/dist/core/features/scanner.d.ts +2 -0
  677. package/dist/core/features/scanner.d.ts.map +1 -1
  678. package/dist/core/features/scanner.js +27 -6
  679. package/dist/core/features/scanner.js.map +1 -1
  680. package/dist/core/timeline/cli.d.ts.map +1 -1
  681. package/dist/core/timeline/cli.js +13 -6
  682. package/dist/core/timeline/cli.js.map +1 -1
  683. package/dist/core/timeline/debris.d.ts +20 -0
  684. package/dist/core/timeline/debris.d.ts.map +1 -0
  685. package/dist/core/timeline/debris.js +124 -0
  686. package/dist/core/timeline/debris.js.map +1 -0
  687. package/dist/core/timeline/hook-runner.d.ts.map +1 -1
  688. package/dist/core/timeline/hook-runner.js +3 -1
  689. package/dist/core/timeline/hook-runner.js.map +1 -1
  690. package/dist/core/timeline/hooks.d.ts.map +1 -1
  691. package/dist/core/timeline/hooks.js +13 -5
  692. package/dist/core/timeline/hooks.js.map +1 -1
  693. package/dist/core/timeline/installer.d.ts +2 -0
  694. package/dist/core/timeline/installer.d.ts.map +1 -1
  695. package/dist/core/timeline/installer.js +12 -0
  696. package/dist/core/timeline/installer.js.map +1 -1
  697. package/dist/core/timeline/project-root.d.ts +21 -0
  698. package/dist/core/timeline/project-root.d.ts.map +1 -0
  699. package/dist/core/timeline/project-root.js +83 -0
  700. package/dist/core/timeline/project-root.js.map +1 -0
  701. package/package.json +1 -1
@@ -0,0 +1,1098 @@
1
+ "use strict";
2
+ /**
3
+ * Shared Analysis Orchestrator
4
+ *
5
+ * Extracts the core analysis pipeline from the CLI analyze command into a
6
+ * reusable function that can be called from both the CLI and a server-side
7
+ * worker process.
8
+ *
9
+ * IMPORTANT: This module must NEVER call process.exit(). The caller (CLI
10
+ * wrapper or server worker) is responsible for process lifecycle.
11
+ */
12
+ var __importDefault = (this && this.__importDefault) || function (mod) {
13
+ return (mod && mod.__esModule) ? mod : { "default": mod };
14
+ };
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.resolveStreamGraphEmit = exports.collectBranchCacheKeys = exports.PHASE_LABELS = void 0;
17
+ exports.runFullAnalysis = runFullAnalysis;
18
+ const path_1 = __importDefault(require("path"));
19
+ const promises_1 = __importDefault(require("fs/promises"));
20
+ const node_crypto_1 = require("node:crypto");
21
+ const node_url_1 = require("node:url");
22
+ const fs_atomic_js_1 = require("../storage/fs-atomic.js");
23
+ const index_lock_js_1 = require("../storage/index-lock.js");
24
+ const pipeline_js_1 = require("./ingestion/pipeline.js");
25
+ const workspace_config_js_1 = require("./ingestion/workspace-config.js");
26
+ const unresolved_receivers_js_1 = require("./ingestion/scope-resolution/unresolved-receivers.js");
27
+ const safe_parse_js_1 = require("./tree-sitter/safe-parse.js");
28
+ const lbug_adapter_js_1 = require("./lbug/lbug-adapter.js");
29
+ const lbug_config_js_1 = require("./lbug/lbug-config.js");
30
+ const wal_checkpoint_driver_js_1 = require("./lbug/wal-checkpoint-driver.js");
31
+ const sidecar_recovery_js_1 = require("./lbug/sidecar-recovery.js");
32
+ const repo_manager_js_1 = require("../storage/repo-manager.js");
33
+ const env_js_1 = require("./ingestion/utils/env.js");
34
+ const file_hash_js_1 = require("../storage/file-hash.js");
35
+ const parse_cache_js_1 = require("../storage/parse-cache.js");
36
+ const parsedfile_store_js_1 = require("../storage/parsedfile-store.js");
37
+ const git_js_1 = require("../storage/git.js");
38
+ const analyze_config_js_1 = require("../cli/analyze-config.js");
39
+ const schema_js_1 = require("./lbug/schema.js");
40
+ const bean_factories_js_1 = require("./ingestion/frameworks/spring/bean-factories.js");
41
+ const analysis_features_js_1 = require("./ingestion/frameworks/spring/analysis-features.js");
42
+ const analysis_features_js_2 = require("./ingestion/languages/java/analysis-features.js");
43
+ const analysis_features_js_3 = require("./analysis-features.js");
44
+ const analyzer_identity_js_1 = require("./analyzer-identity.js");
45
+ /**
46
+ * Strip C0/C1 control characters from a progress/diagnostic message.
47
+ *
48
+ * Several guard notices below interpolate values read straight out of
49
+ * `.cgraphx/code/cgraph.json`, which is parsed with no runtime shape validation
50
+ * (`loadMeta` does a bare `JSON.parse(...) as RepoMeta`) — the stamped schema
51
+ * fingerprint, the runner-identity schema, the CJK mode. On the CLI path these
52
+ * reach `console.log` and therefore the user's terminal, so a crafted value
53
+ * carrying ANSI escapes (`\x1b[2J`, `\x1b]0;…`) would be replayed verbatim.
54
+ *
55
+ * Sanitizing at the funnel rather than per field: every message that ever
56
+ * interpolates untrusted metadata is covered, including ones not written yet.
57
+ * Newline and tab are preserved — multi-line notices are intentional.
58
+ */
59
+ const stripControlCharacters = (msg) => msg.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g, '');
60
+ const ANALYSIS_FEATURES = [
61
+ analysis_features_js_3.CLASS_FRAMEWORK_ANNOTATIONS_FEATURE,
62
+ analysis_features_js_1.SPRING_AOP_FEATURE,
63
+ analysis_features_js_1.SPRING_BEAN_INVENTORY_FEATURE,
64
+ analysis_features_js_1.SPRING_CONDITIONALS_FEATURE,
65
+ analysis_features_js_2.SPRING_CONFIG_BINDINGS_FEATURE,
66
+ ];
67
+ function stringList(value) {
68
+ return Array.isArray(value)
69
+ ? value.filter((item) => typeof item === 'string')
70
+ : [];
71
+ }
72
+ function collectFrameworkAnnotationDriftFiles(graph, persistedRows) {
73
+ const persistedById = new Map();
74
+ for (const row of persistedRows) {
75
+ if (typeof row.id === 'string') {
76
+ persistedById.set(row.id, stringList(row.frameworkAnnotations));
77
+ }
78
+ }
79
+ const driftFiles = new Set();
80
+ graph.forEachNode((node) => {
81
+ if (node.label !== 'Class')
82
+ return;
83
+ const current = stringList(node.properties.frameworkAnnotations);
84
+ const persisted = persistedById.get(node.id) ?? [];
85
+ if (current.length !== persisted.length ||
86
+ current.some((annotation, index) => annotation !== persisted[index])) {
87
+ const filePath = node.properties.filePath;
88
+ if (typeof filePath === 'string')
89
+ driftFiles.add(filePath);
90
+ }
91
+ });
92
+ return driftFiles;
93
+ }
94
+ function collectSpringBeanDeclarationDriftFiles(graph, persistedRows) {
95
+ const persisted = new Map();
96
+ for (const row of persistedRows) {
97
+ if (typeof row.id === 'string' &&
98
+ typeof row.filePath === 'string' &&
99
+ typeof row.reason === 'string' &&
100
+ (0, bean_factories_js_1.isSpringBeanFactoryDeclaration)({ type: 'DECLARES', reason: row.reason })) {
101
+ persisted.set(row.id, { filePath: row.filePath, reason: row.reason });
102
+ }
103
+ }
104
+ const current = new Map();
105
+ for (const relationship of graph.relationships) {
106
+ if (relationship.type !== 'DECLARES')
107
+ continue;
108
+ if (!(0, bean_factories_js_1.isSpringBeanFactoryDeclaration)(relationship))
109
+ continue;
110
+ const declaration = graph.getNode(relationship.targetId);
111
+ if (declaration === undefined || typeof declaration.properties.filePath !== 'string')
112
+ continue;
113
+ current.set(declaration.id, {
114
+ filePath: declaration.properties.filePath,
115
+ reason: relationship.reason,
116
+ });
117
+ }
118
+ const driftFiles = new Set();
119
+ for (const [id, value] of current) {
120
+ const prior = persisted.get(id);
121
+ if (prior === undefined || prior.reason !== value.reason)
122
+ driftFiles.add(value.filePath);
123
+ }
124
+ for (const [id, value] of persisted) {
125
+ if (!current.has(id))
126
+ driftFiles.add(value.filePath);
127
+ }
128
+ return driftFiles;
129
+ }
130
+ exports.PHASE_LABELS = {
131
+ extracting: 'Scanning files',
132
+ structure: 'Building structure',
133
+ parsing: 'Parsing code',
134
+ imports: 'Resolving imports',
135
+ calls: 'Tracing calls',
136
+ heritage: 'Extracting inheritance',
137
+ scopeResolution: 'Resolving types',
138
+ communities: 'Detecting communities',
139
+ processes: 'Detecting processes',
140
+ complete: 'Pipeline complete',
141
+ lbug: 'Loading into LadybugDB',
142
+ embeddings: 'Generating embeddings',
143
+ done: 'Done',
144
+ };
145
+ // ---------------------------------------------------------------------------
146
+ // Main orchestrator
147
+ // ---------------------------------------------------------------------------
148
+ /**
149
+ * Run the full GitNexus analysis pipeline.
150
+ *
151
+ * This is the shared core extracted from the CLI `analyze` command. It
152
+ * handles: pipeline execution, LadybugDB loading, embedding generation,
153
+ * metadata persistence, and AI context file generation.
154
+ *
155
+ * The function communicates progress and log messages exclusively through
156
+ * the {@link AnalyzeCallbacks} interface — it never writes to stdout/stderr
157
+ * directly and never calls `process.exit()`.
158
+ */
159
+ /**
160
+ * Collect the recorded parse-cache chunk keys across the flat + every branch
161
+ * metadata directory under a flat `.cgraphx/code` storage, EXCLUDING `excludeDir`
162
+ * (the current run's own meta dir) so a single-branch repo collects nothing and
163
+ * its prune stays byte-identical to today (#2106 R6 — the byte-identity claim
164
+ * is about the PRUNE result; the metadata FILENAME read here changed with
165
+ * PR #2363's rename, checking `cgraph.json` first then the legacy
166
+ * `meta.json` mirror). `complete` is false when a sibling metadata file exists
167
+ * but fails to read or parse — callers then retain the whole shared cache
168
+ * rather than over-evict another branch's still-live shards. Exported for
169
+ * testing.
170
+ */
171
+ const collectBranchCacheKeys = async (storagePath, excludeDir) => {
172
+ const keys = new Set();
173
+ let complete = true;
174
+ const metaDirs = [storagePath];
175
+ const branchesDir = path_1.default.join(storagePath, 'branches');
176
+ const slugs = await promises_1.default.readdir(branchesDir).catch(() => []);
177
+ for (const slug of slugs)
178
+ metaDirs.push(path_1.default.join(branchesDir, slug));
179
+ for (const dir of metaDirs) {
180
+ if (excludeDir && path_1.default.resolve(dir) === path_1.default.resolve(excludeDir))
181
+ continue;
182
+ let raw;
183
+ try {
184
+ raw = await promises_1.default.readFile(path_1.default.join(dir, repo_manager_js_1.INDEX_METADATA_FILE), 'utf-8');
185
+ }
186
+ catch (newErr) {
187
+ if (!(0, repo_manager_js_1.isMissingFilesystemError)(newErr)) {
188
+ complete = false;
189
+ continue;
190
+ }
191
+ try {
192
+ raw = await promises_1.default.readFile(path_1.default.join(dir, 'meta.json'), 'utf-8');
193
+ }
194
+ catch (legacyErr) {
195
+ if (!(0, repo_manager_js_1.isMissingFilesystemError)(legacyErr))
196
+ complete = false;
197
+ continue; // no metadata here — not a branch index, not a failure
198
+ }
199
+ }
200
+ try {
201
+ const parsed = JSON.parse(raw);
202
+ if (Array.isArray(parsed.cacheKeys)) {
203
+ for (const k of parsed.cacheKeys)
204
+ if (typeof k === 'string')
205
+ keys.add(k);
206
+ }
207
+ }
208
+ catch {
209
+ complete = false; // present but corrupt → fail-safe toward retention
210
+ }
211
+ }
212
+ return { keys, complete };
213
+ };
214
+ exports.collectBranchCacheKeys = collectBranchCacheKeys;
215
+ /**
216
+ * Resolve whether streamed structural graph emit is on for this run (#2680).
217
+ *
218
+ * **On by default.** It costs nothing observable: the sink answers a complete
219
+ * relationship read, so community detection, process extraction and the
220
+ * local-symbol pruner all behave exactly as they do without it — the edges
221
+ * simply live in columns and on disk instead of as objects. There is no reason
222
+ * to make a user opt in to using less memory.
223
+ *
224
+ * Two conditions still bound it:
225
+ *
226
+ * - `force === true`. Sound only on a full rebuild (analyze is always a full
227
+ * rebuild now, so every run qualifies once the freshness guards rebind
228
+ * `options.force`).
229
+ * - `CGRAPH_STREAM_GRAPH_EMIT=0` (or an explicit `streamGraphEmit: false`)
230
+ * turns it off. The escape hatch exists for bisecting a suspected
231
+ * streaming-related fault, not as a routine choice.
232
+ *
233
+ * Read every call (not memoized) so `vi.stubEnv` works.
234
+ */
235
+ const resolveStreamGraphEmit = (options) => {
236
+ if (options.force !== true)
237
+ return false;
238
+ if (options.streamGraphEmit !== undefined)
239
+ return options.streamGraphEmit;
240
+ // Unset ⇒ on. Set ⇒ honour it, so `=0` / `=false` is the escape hatch.
241
+ const raw = process.env.CGRAPH_STREAM_GRAPH_EMIT;
242
+ return raw === undefined || raw === '' ? true : (0, env_js_1.parseTruthyEnv)(raw);
243
+ };
244
+ exports.resolveStreamGraphEmit = resolveStreamGraphEmit;
245
+ /**
246
+ * Resolve which storage slot this analyze writes to, including branch
247
+ * placement (#2106/#2354). Extracted from the top of the pipeline so the lock
248
+ * scope (`metaDir`) is known before the lock is acquired. Throws the same
249
+ * `--branch` / checked-out mismatch error the pipeline used to throw inline, so
250
+ * that failure still surfaces before any lock is taken.
251
+ */
252
+ async function resolveWriteTarget(repoPath, options) {
253
+ // `storagePath` is ALWAYS the flat `.cgraphx/code` — content-addressed caches
254
+ // (parse-cache, parsedfile-store) and kuzu-migration cleanup live there and
255
+ // are shared across branches (#2106 KTD7).
256
+ const { storagePath } = (0, repo_manager_js_1.getStoragePaths)(repoPath);
257
+ const repoHasGit = (0, git_js_1.hasGitDir)(repoPath);
258
+ const currentCommit = repoHasGit ? (0, git_js_1.getCurrentCommit)(repoPath) : '';
259
+ // Normalize the auto-detected branch the same way an explicit `--branch` is
260
+ // validated (#2106 R1): a git ref the branch-name rules forbid becomes `null`
261
+ // → the flat slot, matching that a later `--branch <that-ref>` query would
262
+ // also be rejected. A normal ref round-trips index-time/query-time labels.
263
+ const checkedOutBranch = repoHasGit
264
+ ? ((0, analyze_config_js_1.sanitizeDetectedBranch)((0, git_js_1.getCurrentBranch)(repoPath)) ?? null)
265
+ : null;
266
+ // Analyze indexes the working tree, not an arbitrary ref. An explicit
267
+ // `--branch X` while a DIFFERENT branch Y is checked out would write Y's
268
+ // content into X's slot, corrupting X (#2106). Refuse the mismatch. Detached
269
+ // HEAD / non-git (checkedOutBranch === null) still allow an explicit label.
270
+ if (options.branch && checkedOutBranch && options.branch !== checkedOutBranch) {
271
+ throw new Error(`--branch "${options.branch}" does not match the checked-out branch "${checkedOutBranch}". ` +
272
+ `Check out "${options.branch}" before indexing it, or omit --branch to index the current branch.`);
273
+ }
274
+ const branchLabel = options.branch ?? checkedOutBranch;
275
+ const placement = options.branch ? await (0, repo_manager_js_1.resolveBranchPlacement)(repoPath, branchLabel) : {};
276
+ const { lbugPath, metaPath } = (0, repo_manager_js_1.getStoragePaths)(repoPath, placement.branch);
277
+ return {
278
+ storagePath,
279
+ repoHasGit,
280
+ currentCommit,
281
+ checkedOutBranch,
282
+ branchLabel,
283
+ placement,
284
+ lbugPath,
285
+ metaPath,
286
+ metaDir: path_1.default.dirname(metaPath),
287
+ };
288
+ }
289
+ /**
290
+ * Run the full analysis under an exclusive, index-directory-scoped write lock
291
+ * (#2658). A second concurrent `analyze` on the same slot waits here for the
292
+ * first to finish, then falls through to the normal freshness check inside —
293
+ * so a run whose work the holder already did returns `alreadyUpToDate` in
294
+ * seconds instead of rebuilding (single-flight coalescing), while a run for a
295
+ * genuinely-changed tree does one follow-up incremental. No new flag: waiting
296
+ * is the default, which is what hook-driven re-index wants.
297
+ *
298
+ * The lock is held by whichever process runs the pipeline (the heap-respawn
299
+ * child, or the original) — see index-lock.ts for why ownership lives with the
300
+ * writer, not a supervising parent. Released as soon as the write completes or
301
+ * throws; the post-analysis steps in the CLI (registry) run lock-free.
302
+ */
303
+ async function runFullAnalysis(repoPath, options, callbacks, runnerIdentityAtBootstrap) {
304
+ // Scope the degraded-parse log throttle to this run (module-level counter
305
+ // would otherwise stay saturated on a reused process).
306
+ (0, safe_parse_js_1.resetDegradedParseCounter)();
307
+ // 早期加载 workspace 配置(spec §5.2 / §9):在触碰任何索引目录之前校验,
308
+ // 配置文件缺失 → 契约阶段跳过(返回 null);配置存在但解析/结构非法 → 抛
309
+ // WorkspaceConfigError 中止本次 analyze,不产出半索引。解析结果经进程缓存
310
+ // 供后续 rpc-edges / http-api-calls 阶段与 walker 复用(T-11 / T-12 接入消费)。
311
+ (0, workspace_config_js_1.loadWorkspaceConfig)(repoPath);
312
+ const log = (msg) => callbacks.onLog?.(stripControlCharacters(msg));
313
+ const acquireOpts = {
314
+ log,
315
+ onWaitStart: () => callbacks.onProgress('lock', 0, 'Waiting for another analyze to finish on this index…'),
316
+ };
317
+ let writeTarget = await resolveWriteTarget(repoPath, options);
318
+ let lock = await (0, index_lock_js_1.acquireIndexLock)(writeTarget.metaDir, acquireOpts);
319
+ try {
320
+ // #2658 review H2: acquireIndexLock can wait up to the timeout ceiling,
321
+ // during which git HEAD/branch — and thus the resolved write slot — may
322
+ // change (a commit lands, a branch is switched, or another writer adopts the
323
+ // flat slot). The pre-wait snapshot must NOT be reused: re-resolve UNDER the
324
+ // lock so the freshness check (`existingMeta.lastCommit === currentCommit`)
325
+ // and the meta stamps see current git state, honoring the module's "re-check
326
+ // freshness after acquiring" contract. If the slot itself moved we hold the
327
+ // WRONG lock — release and re-acquire the correct one. Bounded so a
328
+ // pathologically churning checkout can't loop forever; after the cap we
329
+ // proceed on the current lock. The loop is INSIDE the try so a re-resolve
330
+ // that throws (e.g. a `--branch` that stopped matching the now-switched
331
+ // checkout) still releases the held lock via `finally` (no leak).
332
+ const MAX_RELOCK = 3;
333
+ for (let attempt = 0; attempt < MAX_RELOCK; attempt++) {
334
+ const fresh = await resolveWriteTarget(repoPath, options);
335
+ if (fresh.metaDir === writeTarget.metaDir) {
336
+ writeTarget = fresh; // same slot — adopt the freshly-read commit/branch/placement
337
+ break;
338
+ }
339
+ log(`Index write target moved while waiting for the lock ` +
340
+ `(${writeTarget.metaDir} → ${fresh.metaDir}); re-acquiring the correct slot.`);
341
+ lock.release();
342
+ writeTarget = fresh;
343
+ lock = await (0, index_lock_js_1.acquireIndexLock)(fresh.metaDir, acquireOpts);
344
+ if (attempt === MAX_RELOCK - 1) {
345
+ log('Index write target still moving after repeated re-acquire; proceeding on this lock.');
346
+ }
347
+ }
348
+ return await runFullAnalysisInner(repoPath, options, callbacks, writeTarget, runnerIdentityAtBootstrap);
349
+ }
350
+ finally {
351
+ lock.release();
352
+ }
353
+ }
354
+ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, runnerIdentityAtBootstrap) {
355
+ const log = (msg) => callbacks.onLog?.(stripControlCharacters(msg));
356
+ const progress = (phase, percent, message) => callbacks.onProgress(phase, percent, message);
357
+ // The degraded-parse counter reset happens in the `runFullAnalysis` wrapper
358
+ // (before the lock is taken).
359
+ // Write target (storage paths + resolved branch placement) was computed by
360
+ // the `runFullAnalysis` wrapper — which needs `metaDir` up front to acquire
361
+ // the exclusive index lock BEFORE any of the freshness/write work below
362
+ // (#2658). `storagePath` is ALWAYS the flat `.cgraphx/code`; `placement.branch`
363
+ // selects a `branches/<slug>/` sub-slot only for an explicit `--branch` that
364
+ // does not own the flat slot. See resolveWriteTarget for the full contract.
365
+ const { storagePath, repoHasGit, currentCommit, branchLabel, placement, lbugPath, metaDir } = writeTarget;
366
+ // Start each analyze with a clean buffer-pool hint: any pre-pipeline DB open
367
+ // (e.g. the embeddings-cache open) falls back to the default until the hint is
368
+ // set from the built graph below, so a prior run's size can't leak in.
369
+ (0, lbug_config_js_1.setBufferPoolSizeHint)(undefined);
370
+ // Clean up stale KuzuDB files from before the LadybugDB migration.
371
+ const kuzuResult = await (0, repo_manager_js_1.cleanupOldKuzuFiles)(storagePath);
372
+ if (kuzuResult.found && kuzuResult.needsReindex) {
373
+ log('Migrating from KuzuDB to LadybugDB — rebuilding index...');
374
+ }
375
+ // Keep cgraph.json and the legacy meta.json mirror in sync (fresher
376
+ // indexedAt wins; nothing is deleted). Best-effort: loadMeta has its own
377
+ // legacy fallback, so a reconciliation failure (read-only mount, full disk)
378
+ // must never abort the analyze run — a repo that indexed fine read-only
379
+ // before the rename must keep doing so.
380
+ try {
381
+ await (0, repo_manager_js_1.reconcileMetadataFiles)(repoPath);
382
+ }
383
+ catch (err) {
384
+ const code = err?.code;
385
+ log(`Metadata reconciliation failed (non-critical${code ? `, ${code}` : ''}); continuing.`);
386
+ }
387
+ const existingMeta = await (0, repo_manager_js_1.loadMeta)(metaDir);
388
+ // Resolve once per real analysis run so every successful metadata write
389
+ // carries one coherent receipt.
390
+ const runnerIdentity = runnerIdentityAtBootstrap ?? (0, analyzer_identity_js_1.resolveAnalyzerRunnerIdentity)((0, node_url_1.pathToFileURL)(__filename).href);
391
+ if (!(0, analyzer_identity_js_1.analyzerRunnerIdentitiesEqual)(runnerIdentity, runnerIdentity)) {
392
+ throw new Error('Analyzer bootstrap supplied a malformed runner identity receipt');
393
+ }
394
+ // ── Crash recovery: dirty flag forces full rebuild ────────────────
395
+ // If the previous incremental run set incrementalInProgress and didn't
396
+ // clear it, the on-disk index may be in a half-state. Cheapest path
397
+ // back to a known-good index is to wipe + rebuild from scratch.
398
+ if (existingMeta?.incrementalInProgress) {
399
+ const dirty = existingMeta.incrementalInProgress;
400
+ const dirtyDetails = typeof dirty === 'object'
401
+ ? [
402
+ dirty.phase ? `phase=${dirty.phase}` : undefined,
403
+ `toWrite=${dirty.toWriteCount}`,
404
+ dirty.importerExpansion !== undefined
405
+ ? `importerExpansion=${dirty.importerExpansion}`
406
+ : undefined,
407
+ dirty.effectiveWriteCount !== undefined
408
+ ? `effectiveWrite=${dirty.effectiveWriteCount}`
409
+ : undefined,
410
+ dirty.deleteCount !== undefined ? `deleteCount=${dirty.deleteCount}` : undefined,
411
+ // Only stamped when > 0 (tri-review 4669518496 P2-5): its
412
+ // presence means the crashed run's importer expansion was
413
+ // already degraded — the write set may have been under-expanded
414
+ // before the crash.
415
+ dirty.droppedImporterChunks !== undefined
416
+ ? `droppedImporterChunks=${dirty.droppedImporterChunks}`
417
+ : undefined,
418
+ ]
419
+ .filter(Boolean)
420
+ .join(', ')
421
+ : 'legacy dirty flag';
422
+ log(
423
+ // "analyze run", not "incremental run" — since #2099 F1 the flag is a
424
+ // generic dirty marker written by BOTH writeback branches.
425
+ 'Previous analyze run did not complete cleanly (incrementalInProgress flag set); ' +
426
+ `last dirty state: ${dirtyDetails}; ` +
427
+ 'forcing full rebuild to restore a known-good index.');
428
+ options = { ...options, force: true };
429
+ // Reload meta after clearing the flag in-memory; we still want fileHashes
430
+ // for the post-rebuild meta carry-over, but force=true ensures the
431
+ // rebuild path executes.
432
+ //
433
+ // #2409 defect 2: the crashed writeback's WAL can be poisoned — replaying
434
+ // it kills the process natively, and the first DB open of this recovery
435
+ // run (the embedding-cache preservation open below) happens BEFORE the
436
+ // rebuild wipe that would discard it. Park the WAL/shadow sidecars aside
437
+ // now, while nothing is open, so every open in this run is replay-free.
438
+ // The rebuild wipes the DB regardless, so no committed data is at stake.
439
+ const { removed, failed } = await (0, sidecar_recovery_js_1.quarantineSidecarsForDirtyRecovery)(lbugPath, log);
440
+ if (removed.length > 0) {
441
+ log(`Dirty-state recovery discarded ${removed.map((p) => path_1.default.basename(p)).join(', ')} ` +
442
+ 'from the interrupted run (the file could not be moved aside, so its bytes were ' +
443
+ 'removed — post-mortem forensics lost). Recovery proceeds with full embedding ' +
444
+ 'preservation.');
445
+ }
446
+ if (failed.length > 0) {
447
+ // FIX 1 (this shipping review, replacing the tri-review 4669518496
448
+ // P2-3 drop-shape design): under a persistent lock the old drop-shape
449
+ // run derived its embedding mode as "drop", ran the WHOLE pipeline,
450
+ // and then died at the rebuild wipe on the very same handle — wasting
451
+ // minutes and zeroing embeddings on the way. A possibly-poisoned
452
+ // sidecar still sits next to the DB (any pre-wipe open would replay it
453
+ // and die), so failing here, in seconds, with the same actionable
454
+ // typed error the wipe would eventually throw is strictly better —
455
+ // and the CLI's LbugWipeError handler already renders it
456
+ // (recoveryHint 'lbug-wipe-failed'). The message is self-contained
457
+ // (headline + paths + lock guidance) because serve forwards only
458
+ // err.message over worker IPC.
459
+ throw new lbug_adapter_js_1.LbugWipeError(failed, {
460
+ headline: "Cannot start dirty-state recovery — the interrupted run's LadybugDB sidecars " +
461
+ 'could neither be moved aside nor removed:',
462
+ });
463
+ }
464
+ }
465
+ // ── schema mismatch forces full rebuild (#2289 P1, #2798) ─────────
466
+ // An index whose tables were created from a different DDL cannot be reconciled
467
+ // without a full rebuild — a same-commit re-analyze would strand stale rows
468
+ // next to new-schema writes, and LadybugDB fixes a relation table's endpoint
469
+ // pairs at CREATE time, so edges the old shape cannot hold are simply dropped.
470
+ // MUST sit before the alreadyUpToDate fast path below: an unchanged-commit
471
+ // clean tree would otherwise early-return without forcing the rebuild.
472
+ //
473
+ // Forcing here is what recreates the schema: `force` makes the run a full
474
+ // rebuild, which wipes the database file and re-runs the DDL against an
475
+ // empty one. Re-running `CREATE … TABLE` over the EXISTING database would
476
+ // not help — runSchemaCreationQueries suppresses "already exists", so the
477
+ // new shape would never be applied.
478
+ //
479
+ // ABSENT covers two cases and forces in both: an index from a GitNexus
480
+ // older than this field (the backward-compatibility path — one rebuild, then
481
+ // it is stamped), and a non-git repo, which never stamps it (see the meta
482
+ // literal below) and takes the `currentCommit === ''` rebuild branch below
483
+ // regardless.
484
+ //
485
+ // The two cases must not be told the same story. Blaming "an older GitNexus
486
+ // version" is FALSE for a non-git repo — the field is absent by design there,
487
+ // so this build would keep saying it about an index this exact build just
488
+ // wrote, on every run, forever. A stamp is only named when it has the shape
489
+ // SCHEMA_FINGERPRINT produces; anything else degrades to a neutral
490
+ // placeholder, and a non-git repo is additionally told WHY it has no stamp.
491
+ if (existingMeta && (0, schema_js_1.schemaFingerprintMismatch)(existingMeta.schemaFingerprint)) {
492
+ const stamped = existingMeta.schemaFingerprint;
493
+ const origin = (0, schema_js_1.isSchemaFingerprintShaped)(stamped) ? stamped : 'an unidentified GitNexus build';
494
+ const nonGitNote = stamped === undefined && !repoHasGit
495
+ ? ' Non-git repositories never record a schema fingerprint, so this run rebuilds regardless.'
496
+ : '';
497
+ log(`index schema changed (built by ${origin}, this build is ${schema_js_1.SCHEMA_FINGERPRINT}); forcing a ` +
498
+ `full re-analyze so the database is recreated from the current schema.${nonGitNote}`);
499
+ options = { ...options, force: true };
500
+ }
501
+ // ── independently-versioned analysis capabilities ────────────────
502
+ // `schemaFingerprint` is reserved for graph-wide incremental invariants. Some
503
+ // persisted semantics apply only to repositories containing relevant source
504
+ // files, so they carry exact feature versions instead. This guard must also
505
+ // run before alreadyUpToDate: a feature can change what is EXTRACTED without
506
+ // changing the DDL, so an index whose `schemaFingerprint` matches this build
507
+ // can still be missing that feature's evidence (e.g. the Class
508
+ // frameworkAnnotations values, or Java/Kotlin Bean evidence) — the fingerprint
509
+ // guard above would wave it through.
510
+ const persistedFilePaths = Object.keys(existingMeta?.fileHashes ?? {});
511
+ const expectedPersistedAnalysisFeatures = (0, analysis_features_js_3.resolveAnalysisFeatureVersions)(ANALYSIS_FEATURES, persistedFilePaths);
512
+ const persistedAnalysisFeatureMismatches = existingMeta
513
+ ? (0, analysis_features_js_3.findAnalysisFeatureMismatches)(existingMeta.analysisFeatures, expectedPersistedAnalysisFeatures)
514
+ : [];
515
+ let analysisFeatureMismatchLogged = false;
516
+ if (existingMeta && persistedAnalysisFeatureMismatches.length > 0) {
517
+ log(`analysis capabilities changed (${persistedAnalysisFeatureMismatches.join(', ')}); ` +
518
+ `forcing a full rebuild so persisted feature evidence is complete.`);
519
+ options = { ...options, force: true };
520
+ analysisFeatureMismatchLogged = true;
521
+ }
522
+ // Analyzer provenance is part of freshness, not merely diagnostics. A
523
+ // same-commit fast path must not preserve metadata produced by an older,
524
+ // malformed, or dependency/native-different runner. Force a real rebuild so
525
+ // the graph and its schema-v4 receipt are finalized atomically together.
526
+ if (existingMeta && !(0, analyzer_identity_js_1.analyzerRunnerIdentitiesEqual)(existingMeta.runnerIdentity, runnerIdentity)) {
527
+ const stampedRunnerSchema = existingMeta.runnerIdentity?.schemaVersion;
528
+ log(`analyzer runner identity changed (stamped schema ${String(stampedRunnerSchema ?? 'missing')}, ` +
529
+ `this build uses schema ${runnerIdentity.schemaVersion}); forcing a full rebuild so the ` +
530
+ 'index provenance matches the analyzer and dependency/native runtime that produced it.');
531
+ options = { ...options, force: true };
532
+ }
533
+ // ── embedding width mismatch forces full rebuild (#2798) ──────────
534
+ // The half of the schema `SCHEMA_FINGERPRINT` deliberately cannot cover:
535
+ // `CodeEmbedding.embedding` is declared `FLOAT[EMBEDDING_DIMS]`, and that
536
+ // width comes from `CGRAPH_EMBEDDING_DIMS` at module load, so folding it
537
+ // into a digest of CODE would make the same build disagree with itself under
538
+ // two envs. Without this block a dims flip on a same-commit clean tree fired
539
+ // NO guard: the fast path below returned over a FLOAT[384] table while this
540
+ // process embedded at 768. The one older reaction (in the embedding-restore
541
+ // block further down) discards the CACHE and re-embeds — into a column whose
542
+ // width it never revisits.
543
+ //
544
+ // Forcing is again what repairs it, and for the same reason as the
545
+ // fingerprint guard: only a full rebuild wipes the database and re-runs the
546
+ // DDL, and `runSchemaCreationQueries` suppresses "already exists", so
547
+ // re-running CREATE over the existing DB would silently keep the old width.
548
+ // Not conditioned on the index actually holding vectors — the table is
549
+ // created for every index either way, and nothing but a rebuild can retype it.
550
+ //
551
+ // ABSENT is NOT a mismatch here (see embeddingDimsMismatch for the argument):
552
+ // it means an index predating the field, whose width is unknown but was
553
+ // consistent with the env that wrote it, and which the fingerprint guard
554
+ // above already rebuilds — that rebuild is where the stamp lands.
555
+ if (existingMeta && (0, schema_js_1.embeddingDimsMismatch)(existingMeta.embeddingDims, schema_js_1.EMBEDDING_DIMS)) {
556
+ // Only NAME a recorded width that could be one, for the reason the
557
+ // fingerprint guard gates its stamp on `isSchemaFingerprintShaped`:
558
+ // meta.json is a schema-less JSON.parse of on-disk state, so a value that
559
+ // is not a positive integer is not worth quoting back at the user.
560
+ const recordedDims = existingMeta.embeddingDims;
561
+ const built = typeof recordedDims === 'number' && Number.isInteger(recordedDims) && recordedDims > 0
562
+ ? `FLOAT[${recordedDims}]`
563
+ : 'an unrecognized width';
564
+ log(`embedding dimensions changed (index built with ${built}, this run embeds at ` +
565
+ `${schema_js_1.EMBEDDING_DIMS}); forcing a full rebuild so the vector column is recreated at the ` +
566
+ `new width. Tip: set CGRAPH_EMBEDDING_DIMS (or --embedding-dims) to pin it across runs.`);
567
+ options = { ...options, force: true };
568
+ }
569
+ // ── Early-return: already up to date ──────────────────────────────
570
+ if (existingMeta &&
571
+ !existingMeta.embeddingCheckpoint &&
572
+ !options.force &&
573
+ existingMeta.lastCommit === currentCommit) {
574
+ // Non-git folders have currentCommit = '' — always rebuild since we can't detect changes
575
+ if (currentCommit !== '') {
576
+ // For git repos, even if HEAD matches lastCommit, the working tree
577
+ // may have uncommitted changes. Only short-circuit when the working
578
+ // tree is also clean — otherwise fall through to the incremental
579
+ // path which will hash-diff and update only changed files.
580
+ //
581
+ // We exclude paths GitNexus writes during analyze plus the common
582
+ // AI-agent tooling artifacts (which analyze historically also wrote):
583
+ // .cgraphx/ — index storage (db / parse cache / meta.json under code/)
584
+ // .claude/, .cursor/, .agents/ — agent tooling artifacts
585
+ // AGENTS.md, CLAUDE.md — agent instruction files
586
+ // Counting them as dirty would perpetually defeat the up-to-date
587
+ // fast path whenever agent tooling touches them
588
+ // (regression vs PR #1233 behavior).
589
+ const dirty = (0, git_js_1.isWorkingTreeDirty)(repoPath);
590
+ // Registration wrinkle around the fast path (#2264). A prior
591
+ // `analyze --name X` that hit a name collision writes meta.json (meta-save
592
+ // runs before registerRepo) then fails before registering, leaving the
593
+ // index up-to-date but UNREGISTERED. When the user re-runs with
594
+ // --allow-duplicate-name they explicitly want it registered, so fall
595
+ // through to the pipeline (which registers it, honoring the flag) instead
596
+ // of early-returning an unregistered repo the flag could never heal.
597
+ // For a PLAIN analyze we deliberately do NOT self-heal: an up-to-date but
598
+ // unregistered repo early-returns here and the CLI's assertAnalysisFinalized
599
+ // surfaces it as a hard failure (#1169) rather than silently registering a
600
+ // possibly half-finalized index. `isRepoRegistered` is only read on the
601
+ // opt-in branch so the common fast path keeps its single-stat cost.
602
+ const healUnregistered = options.allowDuplicateName === true && !(await (0, repo_manager_js_1.isRepoRegistered)(repoPath));
603
+ // Capability degradation is deliberately NOT self-healed here: an
604
+ // auto-heal probe would open the live index on the millisecond fast path
605
+ // and could turn this early return into a full re-analysis whenever an
606
+ // index authored under one capability set was later read on a host with
607
+ // another — a legitimate, common state, and the invariant
608
+ // `analyzer-identity-cli.test.ts` pins.
609
+ if (!dirty && !healUnregistered) {
610
+ // ── #2354: restamp the workspace label on a same-commit branch flip ──
611
+ // The flat slot follows the checked-out working tree; a branch switch
612
+ // at the SAME commit with a clean tree changes nothing the pipeline
613
+ // must rebuild, but the slot's informational `branch` label (and the
614
+ // registry copy that query-side branch scoping reads) would go stale.
615
+ // Detached HEAD / non-git (branchLabel === null) keeps the existing
616
+ // stamp, mirroring the end-of-run meta write.
617
+ if (!placement.branch && branchLabel && existingMeta.branch !== branchLabel) {
618
+ // Adopt first, stamp last (#2364 review F3): this block's retry
619
+ // guard is `existingMeta.branch !== branchLabel`, so stamping the
620
+ // meta before the registry/shadow cleanup would flip the guard and
621
+ // lock in any partial failure — with saveMeta last, a failed adopt
622
+ // leaves the guard true and the next same-commit run self-heals
623
+ // (adopt is idempotent). The whole sync is best-effort: the label
624
+ // is informational and the flat DB content is byte-valid for both
625
+ // labels here (same commit, clean tree), so an "Already up to
626
+ // date" run must not fail over it; read-only storage — the
627
+ // documented Docker :ro workflow (#1549) — degrades to a warning.
628
+ try {
629
+ await (0, repo_manager_js_1.adoptFlatBranchLabel)(repoPath, branchLabel);
630
+ await (0, repo_manager_js_1.saveMeta)(metaDir, { ...existingMeta, branch: branchLabel });
631
+ }
632
+ catch (err) {
633
+ // EACCES/EPERM also arise from ownership problems and transient
634
+ // Windows locks, so keep the real error visible alongside the
635
+ // #1549 read-only hint instead of replacing it.
636
+ const reason = (0, repo_manager_js_1.isReadOnlyFilesystemError)(err)
637
+ ? `${err.message} — storage may be read-only (#1549)`
638
+ : err.message;
639
+ log(`Warning: could not restamp the workspace branch label (${reason}); will retry on the next run.`);
640
+ }
641
+ }
642
+ await (0, repo_manager_js_1.ensureGitNexusIgnored)(repoPath);
643
+ return {
644
+ // `resolveRepoIdentityRoot` collapses worktree roots to the
645
+ // canonical repo basename (#1259) but leaves arbitrary subdirs
646
+ // and plain-folder roots unchanged.
647
+ repoName: options.registryName ??
648
+ (0, git_js_1.getInferredRepoName)(repoPath) ??
649
+ path_1.default.basename((0, git_js_1.resolveRepoIdentityRoot)(repoPath)),
650
+ repoPath,
651
+ stats: existingMeta.stats ?? {},
652
+ alreadyUpToDate: true,
653
+ isPrimaryBranch: !placement.branch,
654
+ };
655
+ }
656
+ }
657
+ }
658
+ // ── Load incremental parse cache ──────────────────────────────────
659
+ // Content-addressed: safe to reuse across `--force` runs (chunks whose
660
+ // file contents haven't changed produce identical worker output).
661
+ // Loaded into a single ParseCache object that the pipeline mutates
662
+ // in-place (cache hits leave entries unchanged; misses add new ones).
663
+ const parseCache = await (0, parse_cache_js_1.loadParseCache)(storagePath);
664
+ // Streamed structural emit (#2680). Resolved ONCE, so the pipeline flag and
665
+ // the CSV-dir resolution below cannot disagree — and resolved HERE, not at
666
+ // function entry, because the POSITION is load-bearing: the gate is
667
+ // `options.force`, and every freshness guard above REBINDS `options` with
668
+ // `force: true` (dirty-flag recovery, schema-fingerprint change, analysis-
669
+ // feature drift, runner-identity change, CJK-mode change). Resolving before
670
+ // them froze the answer at `false` for every rebuild they trigger — including
671
+ // the whole-fleet rebuild a schema-fingerprint change forces on every existing
672
+ // index at once, which is exactly when the #2649 memory relief matters most.
673
+ // So this MUST stay below the last guard that can set `force` and above its
674
+ // first use.
675
+ const streamGraphEmitActive = (0, exports.resolveStreamGraphEmit)(options);
676
+ // ── Phase 1: Full Pipeline (0–60%) ────────────────────────────────
677
+ const pipelineResult = await (0, pipeline_js_1.runPipelineFromRepo)(repoPath, (p) => {
678
+ const phaseLabel = exports.PHASE_LABELS[p.phase] || p.phase;
679
+ const scaled = Math.round(p.percent * 0.6);
680
+ const message = p.detail
681
+ ? `${p.message || phaseLabel} (${p.detail})`
682
+ : p.message || phaseLabel;
683
+ progress(p.phase, scaled, message);
684
+ }, {
685
+ parsedFileStorePath: storagePath,
686
+ parseCache,
687
+ workerPoolSize: options.workerPoolSize,
688
+ // Streamed structural emit (#2680) — gated to full-rebuild runs.
689
+ streamGraphEmit: streamGraphEmitActive,
690
+ graphEmitCsvDir: streamGraphEmitActive
691
+ ? (0, lbug_config_js_1.resolveNativeSafeStorageDir)(storagePath, 'graph-csv')
692
+ : undefined,
693
+ fetchWrappers: options.fetchWrappers,
694
+ });
695
+ // ── Phase 2: LadybugDB (60–85%) ──────────────────────────────────
696
+ progress('lbug', 60, 'Loading into LadybugDB...');
697
+ // Compute current per-file content hashes from the pipeline's File nodes.
698
+ // Used both to drive the incremental DB writeback (when eligible) and to
699
+ // populate meta.json.fileHashes for the next run.
700
+ const allFilePaths = [];
701
+ pipelineResult.graph.forEachNode((n) => {
702
+ if (n.label === 'File') {
703
+ const fp = n.properties?.filePath;
704
+ if (fp)
705
+ allFilePaths.push(fp);
706
+ }
707
+ });
708
+ const newFileHashes = await (0, file_hash_js_1.computeFileHashes)(repoPath, allFilePaths);
709
+ const currentAnalysisFeatures = (0, analysis_features_js_3.resolveAnalysisFeatureVersions)(ANALYSIS_FEATURES, allFilePaths);
710
+ const currentAnalysisFeatureMismatches = existingMeta
711
+ ? (0, analysis_features_js_3.findAnalysisFeatureMismatches)(existingMeta.analysisFeatures, currentAnalysisFeatures)
712
+ : [];
713
+ if (existingMeta &&
714
+ currentAnalysisFeatureMismatches.length > 0 &&
715
+ !analysisFeatureMismatchLogged) {
716
+ // Covers a repository gaining or losing its first applicable source file:
717
+ // the persisted file list cannot predict that transition before the
718
+ // pipeline, but an incremental top-up would leave unchanged rows incomplete.
719
+ log(`analysis capabilities changed (${currentAnalysisFeatureMismatches.join(', ')}); ` +
720
+ `forcing a full rebuild so persisted feature evidence is complete.`);
721
+ options = { ...options, force: true };
722
+ }
723
+ // #2 atomic index publish: on a full rebuild, build the fresh DB at a temp
724
+ // path and swap it over the live index in one rename at the very end, so a
725
+ // concurrent MCP reader opening mid-build only ever sees the previous
726
+ // complete index (never a wiped/half-built file) and a crash leaves the old
727
+ // index intact. The whole build flows through the singleton connection, so
728
+ // only initLbug/wipeLbugDbFiles below take the temp target.
729
+ //
730
+ // POSIX only: the common CLI/serve-worker analyze paths skip the native close
731
+ // (closeLbugBeforeExit, #2264) and leave the build handle open at swap time.
732
+ // POSIX renames an open file cleanly; a same-process open handle blocks the
733
+ // rename on Windows. Windows keeps the current in-place behavior
734
+ // (buildPath === lbugPath, no swap) until that is resolved (see §12/follow-up).
735
+ //
736
+ // Analyze is always a full rebuild now (incremental writeback was removed),
737
+ // so every run qualifies for the swap where the platform allows.
738
+ // Where the swap is allowed:
739
+ // - POSIX renames an open file, so the usual skip-native-close (#2264) is
740
+ // fine and the swap always applies.
741
+ // - Windows can swap only when a real close is safe to release the build
742
+ // handle before the rename. Unverified on Windows CI; falls back to
743
+ // in-place otherwise. Keep it opt-in (CGRAPH_ATOMIC_WINDOWS_SWAP=1) so the
744
+ // default Windows analyze stays on the proven in-place path.
745
+ const posixSwap = process.platform !== 'win32';
746
+ const windowsSwapOk = process.platform === 'win32' && process.env.CGRAPH_ATOMIC_WINDOWS_SWAP === '1';
747
+ const useAtomicSwap = posixSwap || windowsSwapOk;
748
+ // #2658: a per-run staging name (was the fixed `lbug.new`). Even under the
749
+ // single-writer lock, a unique name means a crashed run's half-built staging
750
+ // file can never be mistaken for — or clobber — a live run's; the lock's
751
+ // orphan sweep (sweepStagingArtifacts) reclaims stragglers on the next
752
+ // acquire. The `.staging.` prefix is what that sweep matches.
753
+ const buildPath = useAtomicSwap ? `${lbugPath}.staging.${(0, node_crypto_1.randomUUID)()}` : lbugPath;
754
+ // Full rebuild path: wipe DB files first.
755
+ // Set the dirty flag BEFORE the wipe whenever a prior meta exists. Without it
756
+ // a full rebuild crashing between the wipe and the end-of-run saveMeta leaves
757
+ // a meta that vouches for a DB it no longer matches — the next clean-tree
758
+ // run's fast path would certify a destroyed DB. toWriteCount: 0 is the
759
+ // full-path sentinel.
760
+ if (existingMeta) {
761
+ const now = Date.now();
762
+ await (0, repo_manager_js_1.saveMeta)(metaDir, {
763
+ ...existingMeta,
764
+ incrementalInProgress: {
765
+ startedAt: now,
766
+ updatedAt: now,
767
+ phase: 'full-rebuild',
768
+ toWriteCount: 0,
769
+ },
770
+ });
771
+ }
772
+ await (0, lbug_adapter_js_1.closeLbug)();
773
+ // Shared loud wipe (#2409 + tri-review 4669518496 P2-4). The 4-file
774
+ // family list — `.shadow` included, because a checkpoint-in-flight crash
775
+ // leaves a shadow sidecar that is replay poison next to a freshly created
776
+ // DB file — lives in wipeLbugDbFiles so this site can never drift. Failures
777
+ // now throw a typed LbugWipeError (ENOENT-verified removal) instead of
778
+ // silently letting initLbug reopen a still-populated DB this run believes it
779
+ // wiped.
780
+ //
781
+ // With the atomic swap (POSIX), this wipes the TEMP build target
782
+ // (`buildPath` = `<lbugPath>.new`, clearing any stragglers from a crashed
783
+ // run) and leaves the live index untouched until the end-of-run swap. On
784
+ // Windows buildPath === lbugPath, so this is the original in-place wipe.
785
+ await (0, lbug_adapter_js_1.wipeLbugDbFiles)(buildPath);
786
+ // Size the buffer pool to the graph just built by the pipeline (a page cache
787
+ // over the on-disk index, which scales with node/edge count) instead of the
788
+ // fixed 2 GiB default, whose eager commit dominates large-repo analyze. The
789
+ // size is clamped to [COPY-safety floor, default], so it only ever shrinks
790
+ // the pool; env override / no-hint paths are unchanged. See
791
+ // resolveBufferManagerSize / estimateBufferPool.
792
+ (0, lbug_config_js_1.setBufferPoolSizeHint)((0, lbug_config_js_1.estimateBufferPool)(pipelineResult.graph.nodeCount +
793
+ pipelineResult.graph.relationshipCount +
794
+ // Streamed edges left the heap but still get COPYed, so they are part of
795
+ // the real load volume (#2680). The hint only ever SHRINKS the pool, so
796
+ // omitting them would starve the COPY at exactly the scale streaming
797
+ // exists to serve.
798
+ (pipelineResult.graphEmitManifest?.totalRows ?? 0)));
799
+ // Full rebuild (POSIX) builds into the temp `buildPath`; Windows uses
800
+ // `buildPath === lbugPath` in place.
801
+ await (0, lbug_adapter_js_1.initLbug)(buildPath);
802
+ // Manual WAL checkpoint driver (#1741): periodically drain the WAL
803
+ // from JS so the un-retriable native auto-checkpoint almost never
804
+ // has work left to do. Failures of the manual CHECKPOINT are absorbed
805
+ // by the driver's bounded retry; the final un-recoverable error still
806
+ // surfaces via the surrounding write that follows the failed flush.
807
+ // Opt-out via `CGRAPH_WAL_MANUAL_CHECKPOINT=0` (the driver itself
808
+ // returns a no-op handle when disabled). Analyze-only: MCP and serve
809
+ // paths continue to rely on the close-time CHECKPOINT in `safeClose`.
810
+ const walCheckpointDriver = (0, wal_checkpoint_driver_js_1.startWalCheckpointDriver)();
811
+ try {
812
+ // All work after initLbug is wrapped in try/finally to ensure closeLbug()
813
+ // is called even if an error occurs — the module-level singleton DB handle
814
+ // must be released to avoid blocking subsequent invocations.
815
+ let lbugMsgCount = 0;
816
+ // ── Full rebuild ───────────────────────────────────────────────
817
+ // Pass the streamed structural graph emit (#2680) so the rows flushed
818
+ // to CSV during the emit loop are COPY'd alongside the rest.
819
+ await (0, lbug_adapter_js_1.loadGraphToLbug)(pipelineResult.graph, pipelineResult.repoPath, storagePath, (msg) => {
820
+ lbugMsgCount++;
821
+ const pct = Math.min(84, 60 + Math.round((lbugMsgCount / (lbugMsgCount + 10)) * 24));
822
+ progress('lbug', pct, msg);
823
+ }, pipelineResult.graphEmitManifest);
824
+ const stats = await (0, lbug_adapter_js_1.getLbugStats)();
825
+ // ── Phase 5: Finalize (98–100%) ───────────────────────────────────
826
+ progress('done', 98, 'Saving metadata...');
827
+ const { getRuntimeCapabilities } = await import('./platform/capabilities.js');
828
+ const runtimeCapabilities = getRuntimeCapabilities();
829
+ // Convert the post-run file-hash map to the on-disk Record<string,string>
830
+ // shape consumed by RepoMeta.fileHashes.
831
+ const newFileHashesRecord = {};
832
+ for (const [k, v] of newFileHashes)
833
+ newFileHashesRecord[k] = v;
834
+ const resolutionOutcomes = pipelineResult.resolutionOutcomes ?? [];
835
+ (0, unresolved_receivers_js_1.logUnresolvedReceiverFiles)(resolutionOutcomes);
836
+ // Annotated so the capabilities stamp below is compile-checked against
837
+ // RepoMeta's status unions (tri-review 4669518496 P1/U3) — an unannotated
838
+ // literal widens the vectorSearch.status ternary to `string` and the
839
+ // honesty contract silently decays to "whatever interpolates".
840
+ const meta = {
841
+ repoPath,
842
+ lastCommit: currentCommit,
843
+ indexedAt: new Date().toISOString(),
844
+ runnerIdentity,
845
+ // Branch identity this index represents (#2106). Recorded for the flat
846
+ // slot too (so resolveBranchPlacement knows which branch owns it). When
847
+ // the label is null (detached HEAD / non-git re-analyze) we PRESERVE an
848
+ // existing stamp rather than stripping it — otherwise a detached re-index
849
+ // of the primary (e.g. CI's `actions/checkout` default) would un-claim the
850
+ // flat slot and let the next branch analyze overwrite the primary index.
851
+ // Stays absent only when never stamped (fresh detached/non-git repo).
852
+ branch: branchLabel ?? existingMeta?.branch,
853
+ // Captured here (not at registration) so it travels with the
854
+ // on-disk meta.json — sibling-clone fingerprinting works for
855
+ // out-of-tree consumers (group-status, future tooling) without
856
+ // a second git shellout. `undefined` when the repo has no
857
+ // origin remote, which is fine: paths-only repos behave as
858
+ // before.
859
+ remoteUrl: (0, git_js_1.hasGitDir)(repoPath) ? (0, git_js_1.getRemoteUrl)(repoPath) : undefined,
860
+ stats: {
861
+ files: pipelineResult.totalFileCount,
862
+ nodes: stats.nodes,
863
+ edges: stats.edges,
864
+ communities: pipelineResult.communityResult?.stats.totalCommunities,
865
+ processes: pipelineResult.processResult?.stats.totalProcesses,
866
+ embeddings: 0,
867
+ },
868
+ capabilities: {
869
+ graph: { provider: 'ladybugdb', status: runtimeCapabilities.graph },
870
+ vectorSearch: {
871
+ // Embeddings were removed from this build, so the vector lane is
872
+ // never populated.
873
+ provider: 'exact-scan',
874
+ status: 'unavailable',
875
+ exactScanLimit: runtimeCapabilities.exactScanLimit,
876
+ reason: runtimeCapabilities.reason,
877
+ },
878
+ },
879
+ // Derived digest of the DDL this run created the tables from (#2798).
880
+ // Git-only: non-git repos never take the incremental path.
881
+ schemaFingerprint: (0, git_js_1.hasGitDir)(repoPath) ? schema_js_1.SCHEMA_FINGERPRINT : undefined,
882
+ unresolvedReceiverMembers: (0, unresolved_receivers_js_1.summarizeUnresolvedReceivers)(resolutionOutcomes),
883
+ analysisFeatures: currentAnalysisFeatures,
884
+ // The FLOAT[N] width this run created the vector column at (#2798).
885
+ // Always stamped, unlike `schemaFingerprint`: the CodeEmbedding table is
886
+ // created for every index, git or not, so absence has exactly one
887
+ // meaning — an index older than the field.
888
+ embeddingDims: schema_js_1.EMBEDDING_DIMS,
889
+ fileHashes: (0, git_js_1.hasGitDir)(repoPath) ? newFileHashesRecord : undefined,
890
+ // This branch's full live chunk-key set (#2106 R6). `usedKeys` is every
891
+ // chunk hash touched in this scan — cache HITS included (see parse-impl
892
+ // usedKeys.add) — so it's complete even on an incremental run. Persisted
893
+ // so a sibling branch's prune can union it and not evict our shards.
894
+ cacheKeys: [...parseCache.usedKeys],
895
+ // Setting incrementalInProgress to undefined explicitly clears any prior
896
+ // dirty flag set during this run's full-rebuild wipe.
897
+ incrementalInProgress: undefined,
898
+ // Embeddings checkpoint is always cleared on a clean run (embeddings are
899
+ // no longer generated by this build).
900
+ embeddingCheckpoint: undefined,
901
+ };
902
+ // Re-resolve at the commit boundary. Long analyses can overlap an npm
903
+ // upgrade, rebuilt dist tree, or native dependency replacement; stamping
904
+ // the start-of-run receipt after such a mutation would falsely certify a
905
+ // graph produced by two analyzer identities. Stable-read validation lives
906
+ // inside the resolver, and a mismatch leaves the dirty flag intact so the
907
+ // next run takes the established full-recovery path.
908
+ meta.runnerIdentity = (0, analyzer_identity_js_1.finalizeAnalyzerRunnerIdentity)((0, node_url_1.pathToFileURL)(__filename).href, runnerIdentity);
909
+ // #2614 F1: the freshness stamp (saveMeta) is written AFTER the atomic swap
910
+ // below — never here — so a concurrent MCP reader can't observe
911
+ // meta.indexedAt = T_new while lbugPath still resolves to the pre-swap
912
+ // inode (which latched the reader on the stale index permanently). The meta
913
+ // object is fully computed at this point; only its write is deferred.
914
+ // Persist the incremental parse cache for the next run. Wraps in
915
+ // try/catch so a cache-write failure never breaks an otherwise
916
+ // successful indexing run. Prune stale chunk-hash entries first so
917
+ // the cache file size stays bounded across runs (chunks whose
918
+ // composition no longer matches anything in the current scan are
919
+ // dead weight; the parse phase populates `usedKeys` as it processes
920
+ // chunks).
921
+ try {
922
+ // #2106 R6: the parse cache + durable store are shared across branches.
923
+ // Before pruning to this run's keys, fold in the OTHER branches' recorded
924
+ // chunk keys so a branch switch doesn't evict their still-live shards.
925
+ // Adding to usedKeys makes them survive pruneCache AND land in the saved
926
+ // index (saveParseCache builds the index from usedKeys). Excludes this
927
+ // run's own meta dir, so a single-branch repo folds in nothing → prune
928
+ // set byte-identical to today.
929
+ const { keys: siblingKeys, complete } = await (0, exports.collectBranchCacheKeys)(storagePath, metaDir);
930
+ if (complete) {
931
+ for (const k of siblingKeys)
932
+ parseCache.usedKeys.add(k);
933
+ }
934
+ else {
935
+ // Fail-safe toward retention: a sibling meta was unreadable, so keep
936
+ // everything currently loaded rather than evict on incomplete info.
937
+ log('Parse cache: a branch meta was unreadable — retaining all cached chunks (#2106).');
938
+ for (const k of parseCache.entries.keys())
939
+ parseCache.usedKeys.add(k);
940
+ }
941
+ const pruned = (0, parse_cache_js_1.pruneCache)(parseCache, parseCache.usedKeys);
942
+ if (pruned > 0) {
943
+ log(`Parse cache: pruned ${pruned} stale chunk entries`);
944
+ }
945
+ const savedKeys = await (0, parse_cache_js_1.saveParseCache)(storagePath, parseCache);
946
+ // Prune the durable ParsedFile store to EXACTLY the parse cache's
947
+ // surviving keys (#2038 warm-cache coverage), so the two content-addressed
948
+ // stores stay coherent: a chunk is "cached" iff both its parse-cache shard
949
+ // and its durable shards exist. A quarantined chunk (in usedKeys but with
950
+ // no parse-cache shard) drops its durable subdir here and re-dispatches
951
+ // next run. Same try/catch — a durable-store write failure must never
952
+ // break an otherwise successful run (next run treats it as a miss).
953
+ await (0, parsedfile_store_js_1.pruneAndSaveDurableParsedFileStore)((0, parsedfile_store_js_1.getDurableParsedFileDir)(storagePath), parse_cache_js_1.PARSE_CACHE_VERSION, new Set(savedKeys));
954
+ }
955
+ catch (e) {
956
+ log(`Warning: could not save parse cache (${e.message}); continuing.`);
957
+ }
958
+ // Forward the --name alias and the registry-collision bypass bit.
959
+ // `allowDuplicateName` is its own concern — independent from the
960
+ // pipeline `force` above. The CLI maps it from
961
+ // `--allow-duplicate-name` only; `--force` triggers a pipeline re-run
962
+ // but never bypasses the registry guard. The returned name is the one
963
+ // actually written to the registry (after applying the precedence chain
964
+ // in registerRepo) (#979).
965
+ const projectName = await (0, repo_manager_js_1.registerRepo)(repoPath, meta, {
966
+ name: options.registryName,
967
+ allowDuplicateName: options.allowDuplicateName,
968
+ // Non-primary branch runs upsert into the entry's branches[]; the
969
+ // primary/flat run (placement.branch === undefined) refreshes the
970
+ // top-level fields (#2106).
971
+ branch: placement.branch,
972
+ });
973
+ // ── #2354: the flat workspace slot has adopted this run's branch ──────
974
+ // Drop a now-shadowed `branches/<slug>/` sub-index for the same label
975
+ // (unreachable once the flat slot serves it) and align the registry's
976
+ // top-level branch label. Best-effort like the parse-cache save above
977
+ // (#2364 review F5): the index is complete and registered, and a failure
978
+ // here leaves only a stale registry label / undeleted shadowed dir —
979
+ // never wrong routing, because the flat meta this run already stamped is
980
+ // what applyBranchScope trusts. Retried by the next content-changing run
981
+ // (same-commit fast-path runs skip it: their guard compares the
982
+ // already-stamped meta label).
983
+ if (!placement.branch && branchLabel) {
984
+ try {
985
+ await (0, repo_manager_js_1.adoptFlatBranchLabel)(repoPath, branchLabel);
986
+ }
987
+ catch (e) {
988
+ log(`Warning: could not sync the workspace branch label (${e.message}); continuing.`);
989
+ }
990
+ }
991
+ // Keep generated .cgraphx/code contents ignored without editing the user's root .gitignore.
992
+ await (0, repo_manager_js_1.ensureGitNexusIgnored)(repoPath);
993
+ // ── Close LadybugDB ──────────────────────────────────────────────
994
+ // Stop the manual checkpoint driver before closeLbug so its
995
+ // in-flight CHECKPOINT cannot race the `safeClose` CHECKPOINT.
996
+ await walCheckpointDriver.stop();
997
+ // CLI callers (about to process.exit) skip the native close —
998
+ // closeLbugBeforeExit CHECKPOINTs for durability then leaves the handles for
999
+ // process exit to reclaim (#2264). Long-lived callers close for real.
1000
+ //
1001
+ // On Windows a swap must release the build handle before the rename (a
1002
+ // same-process open file can't be renamed), so it forces a real close.
1003
+ // POSIX renames an open file, so it keeps the skip-native-close there.
1004
+ const forceRealCloseForSwap = useAtomicSwap && process.platform === 'win32';
1005
+ await (options.skipNativeCloseOnExit && !forceRealCloseForSwap
1006
+ ? (0, lbug_adapter_js_1.closeLbugBeforeExit)()
1007
+ : (0, lbug_adapter_js_1.closeLbug)());
1008
+ // #2 atomic publish: the fresh index was built at buildPath (always a full
1009
+ // rebuild now). Swap it over the live lbugPath in one rename so an MCP
1010
+ // reader that opened mid-build only ever saw the previous complete index —
1011
+ // never a wiped/half-built file. The close above checkpoint-consolidated
1012
+ // buildPath to a single file (no .wal), so the rename publishes a complete
1013
+ // index; a reader holding the old inode keeps a consistent stale snapshot
1014
+ // until the pool re-opens onto the new one (the pool staleness
1015
+ // invalidation). Runs only on success — a thrown error skips this, leaving
1016
+ // the live index intact and the temp build to be cleared by the next run's
1017
+ // wipe.
1018
+ // Only publish if the build actually produced a DB at buildPath. A
1019
+ // degenerate run (empty repo, or a mocked pipeline that never opened the
1020
+ // store) leaves nothing to swap — skip rather than throw ENOENT.
1021
+ const builtDbExists = useAtomicSwap
1022
+ ? await promises_1.default.stat(buildPath).then(() => true, () => false)
1023
+ : false;
1024
+ if (useAtomicSwap && builtDbExists) {
1025
+ await (0, fs_atomic_js_1.retryRename)(buildPath, lbugPath);
1026
+ // Clear any sidecars orphaned beside the replaced file. A cleanly-closed
1027
+ // prior index has none; a crashed one could, and it would be replay
1028
+ // poison next to the freshly published index. Best-effort.
1029
+ for (const suffix of ['.wal', '.shadow', '.wal.checkpoint']) {
1030
+ await promises_1.default.rm(`${lbugPath}${suffix}`, { force: true }).catch(() => { });
1031
+ }
1032
+ // #2614 F4: if the final checkpoint silently failed, the build may still
1033
+ // carry a residual .wal/.shadow under the temp name. MOVE it beside the
1034
+ // published index (not orphan/delete it) so the next open replays the
1035
+ // delta, rather than leaving it under a name LadybugDB never reconciles.
1036
+ for (const suffix of ['.wal', '.shadow']) {
1037
+ await promises_1.default.rename(`${buildPath}${suffix}`, `${lbugPath}${suffix}`).catch(() => { });
1038
+ }
1039
+ }
1040
+ // #2614 F1: stamp the freshness metadata now that the index is published.
1041
+ // When meta.indexedAt becomes visible, lbugPath already resolves to the new
1042
+ // inode, so a reader reiniting on the stamp opens the fresh graph rather
1043
+ // than latching on the old one. Leaving the dirty flag set across the swap
1044
+ // is a crash-safety improvement: a failed swap leaves the previous index
1045
+ // live and the next run recovers via the full-rebuild path.
1046
+ await (0, repo_manager_js_1.saveMeta)(metaDir, meta);
1047
+ progress('done', 100, 'Done');
1048
+ return {
1049
+ repoName: projectName,
1050
+ repoPath,
1051
+ stats: meta.stats,
1052
+ pipelineResult,
1053
+ isPrimaryBranch: !placement.branch,
1054
+ };
1055
+ }
1056
+ catch (err) {
1057
+ // Ensure LadybugDB is closed even on error. Stop the driver first
1058
+ // so its retry loop cannot extend an already-failing analyze.
1059
+ try {
1060
+ await walCheckpointDriver.stop();
1061
+ }
1062
+ catch {
1063
+ /* swallow — surface path is the rethrow below */
1064
+ }
1065
+ try {
1066
+ // Skip the native close on the error path too: a real conn.close() after
1067
+ // large --pdg writes can itself abort in LadybugDB's ClientContext
1068
+ // destructor (#2264 review P2), turning an actionable exit-1 into a raw
1069
+ // SIGABRT. closeLbugBeforeExit leaves the handles open, but the CLI catch
1070
+ // now force-exits when isLbugReady() (analyze.ts, #2264 review P1), so the
1071
+ // process still terminates — no hang, no abort. flushWAL keeps the partial
1072
+ // index durable; process exit reclaims the handles. Long-lived callers
1073
+ // (skipNativeCloseOnExit unset) close for real.
1074
+ await (options.skipNativeCloseOnExit ? (0, lbug_adapter_js_1.closeLbugBeforeExit)() : (0, lbug_adapter_js_1.closeLbug)());
1075
+ }
1076
+ catch {
1077
+ /* swallow */
1078
+ }
1079
+ // Reclaim the staging index this run created (#2841 cleanup). Without this
1080
+ // a failed staged build orphans a FULL copy of the index — hundreds of MB on
1081
+ // a large repo — until the next `acquireIndexLock` sweeps `lbug.staging.`
1082
+ // artifacts, and the failure most likely to leave one (a machine whose
1083
+ // extension cannot load) is also the one least likely to be followed by
1084
+ // another analyze. Only ever removes a path this run minted: `buildPath`
1085
+ // differs from `lbugPath` exactly when the atomic-swap plan is in effect,
1086
+ // and the live index is never that path. Best-effort by construction — the
1087
+ // rethrow below is the surface, and the lock's sweep remains the backstop.
1088
+ if (useAtomicSwap && buildPath !== lbugPath) {
1089
+ try {
1090
+ await (0, lbug_adapter_js_1.wipeLbugDbFiles)(buildPath);
1091
+ }
1092
+ catch {
1093
+ /* swallow — orphan reclamation must never mask the real failure */
1094
+ }
1095
+ }
1096
+ throw err;
1097
+ }
1098
+ }