cgraphx 2.0.2 → 2.0.6

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 (754) hide show
  1. package/dist/.claude-template/FLOW-MAP.md +13 -3
  2. package/dist/.claude-template/agents/task-history.md +186 -0
  3. package/dist/.claude-template/commands/end.md +1 -0
  4. package/dist/.claude-template/skills/cgraphx-guide/SKILL.md +5 -3
  5. package/dist/.claude-template/skills/cgraphx-guide/how-to-use.html +8 -8
  6. package/dist/.claude-template/skills/cgraphx-guide/how-to-use.md +8 -8
  7. package/dist/.claude-template/skills/clarify-requirements/SKILL.md +13 -9
  8. package/dist/.claude-template/skills/db-query/SKILL.md +19 -2
  9. package/dist/.claude-template/skills/iboc-check/SKILL.md +51 -23
  10. package/dist/.claude-template/skills/iboc-check/filler-prompt.md +3 -4
  11. package/dist/.claude-template/skills/run-api-test/SKILL.md +15 -15
  12. package/dist/.claude-template/skills/run-api-test/assets/{template-test-report.md → template-/346/216/245/345/217/243/346/265/213/350/257/225/346/212/245/345/221/212.md} +4 -4
  13. package/dist/.claude-template/skills/run-api-test/references/bru-run.md +1 -1
  14. package/dist/.claude-template/skills/run-api-test/references/db-verification.md +2 -2
  15. package/dist/.claude-template/skills/run-api-test/references/report-format.md +6 -6
  16. package/dist/.claude-template/skills/run-api-test/references/service-readiness.md +1 -1
  17. package/dist/.claude-template/skills/run-api-test/references/test-scope.md +6 -6
  18. package/dist/.claude-template/skills/run-ui-test/SKILL.md +186 -0
  19. package/dist/.claude-template/skills/run-ui-test/references/report-format.md +77 -0
  20. package/dist/.claude-template/skills/subagent-implement/SKILL.md +3 -2
  21. package/dist/.claude-template/skills/write-api/SKILL.md +18 -18
  22. package/dist/.claude-template/skills/write-api/assets/{template-api-spec.md → template-/346/216/245/345/217/243/346/265/213/350/257/225-spec.md} +1 -1
  23. package/dist/.claude-template/skills/write-api/references/{api-spec-format.md → /346/216/245/345/217/243/346/265/213/350/257/225-spec-format.md} +3 -3
  24. package/dist/.claude-template/skills/write-plan/SKILL.md +4 -2
  25. package/dist/.claude-template/skills/write-ui-test/SKILL.md +125 -0
  26. package/dist/.claude-template/skills/write-ui-test/references//347/224/250/344/276/213/350/247/204/346/240/274-format.md +94 -0
  27. package/dist/core/code/engine/cli/analyze-config.js +320 -0
  28. package/dist/core/code/engine/cli/analyze.js +1086 -0
  29. package/dist/core/code/engine/cli/cli-message.js +83 -0
  30. package/dist/core/code/engine/cli/detect-changes-format.js +58 -0
  31. package/dist/core/code/engine/cli/embedding-dims.js +43 -0
  32. package/dist/core/code/engine/cli/format-elapsed.js +12 -0
  33. package/dist/core/code/engine/cli/help-i18n.js +144 -0
  34. package/dist/core/code/engine/cli/i18n/en.js +110 -0
  35. package/dist/core/code/engine/cli/i18n/index.js +47 -0
  36. package/dist/core/code/engine/cli/i18n/resources.js +9 -0
  37. package/dist/core/code/engine/cli/i18n/zh-CN.js +110 -0
  38. package/dist/core/code/engine/cli/lazy-action.js +67 -0
  39. package/dist/core/code/engine/cli/optional-grammars.js +136 -0
  40. package/dist/core/code/engine/cli/resolve-invocation.js +76 -0
  41. package/dist/core/code/engine/cli/status.js +156 -0
  42. package/dist/core/code/engine/cli/tool.js +384 -0
  43. package/dist/core/code/engine/config/ignore-service.js +511 -0
  44. package/dist/core/code/engine/config/supported-languages.js +17 -0
  45. package/dist/core/code/engine/core/analysis-features.js +64 -0
  46. package/dist/core/code/engine/core/analyzer-identity.js +2171 -0
  47. package/dist/core/code/engine/core/git-staleness.js +180 -0
  48. package/dist/core/code/engine/core/graph/graph.js +180 -0
  49. package/dist/core/code/engine/core/graph/import-cycles.js +106 -0
  50. package/dist/core/code/engine/core/graph/types.js +2 -0
  51. package/dist/core/code/engine/core/index-freshness.js +12 -0
  52. package/dist/core/code/engine/core/ingestion/binding-accumulator.js +341 -0
  53. package/dist/core/code/engine/core/ingestion/call-extractors/configs/c-cpp.js +168 -0
  54. package/dist/core/code/engine/core/ingestion/call-extractors/configs/csharp.js +9 -0
  55. package/dist/core/code/engine/core/ingestion/call-extractors/configs/dart.js +8 -0
  56. package/dist/core/code/engine/core/ingestion/call-extractors/configs/go.js +8 -0
  57. package/dist/core/code/engine/core/ingestion/call-extractors/configs/jvm.js +54 -0
  58. package/dist/core/code/engine/core/ingestion/call-extractors/configs/php.js +8 -0
  59. package/dist/core/code/engine/core/ingestion/call-extractors/configs/python.js +8 -0
  60. package/dist/core/code/engine/core/ingestion/call-extractors/configs/ruby.js +8 -0
  61. package/dist/core/code/engine/core/ingestion/call-extractors/configs/rust.js +8 -0
  62. package/dist/core/code/engine/core/ingestion/call-extractors/configs/swift.js +8 -0
  63. package/dist/core/code/engine/core/ingestion/call-extractors/configs/typescript-javascript.js +11 -0
  64. package/dist/core/code/engine/core/ingestion/call-extractors/generic.js +62 -0
  65. package/dist/core/code/engine/core/ingestion/call-processor.js +503 -0
  66. package/dist/core/code/engine/core/ingestion/call-routing.js +98 -0
  67. package/dist/core/code/engine/core/ingestion/call-types.js +3 -0
  68. package/dist/core/code/engine/core/ingestion/cfg/callee-cell-format.js +45 -0
  69. package/dist/core/code/engine/core/ingestion/cfg/cfg-builder.js +202 -0
  70. package/dist/core/code/engine/core/ingestion/cfg/collect.js +81 -0
  71. package/dist/core/code/engine/core/ingestion/cfg/control-dependence.js +185 -0
  72. package/dist/core/code/engine/core/ingestion/cfg/control-flow-context.js +130 -0
  73. package/dist/core/code/engine/core/ingestion/cfg/emit.js +646 -0
  74. package/dist/core/code/engine/core/ingestion/cfg/post-dominators.js +182 -0
  75. package/dist/core/code/engine/core/ingestion/cfg/reaching-def-reason-codec.js +139 -0
  76. package/dist/core/code/engine/core/ingestion/cfg/reaching-defs-graph.js +322 -0
  77. package/dist/core/code/engine/core/ingestion/cfg/reaching-defs.js +792 -0
  78. package/dist/core/code/engine/core/ingestion/cfg/synthetic-escape.js +305 -0
  79. package/dist/core/code/engine/core/ingestion/cfg/traversal-result.js +6 -0
  80. package/dist/core/code/engine/core/ingestion/cfg/types.js +14 -0
  81. package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp-harvest.js +545 -0
  82. package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp.js +590 -0
  83. package/dist/core/code/engine/core/ingestion/cfg/visitors/call-site-harvest.js +356 -0
  84. package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp-harvest.js +593 -0
  85. package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp.js +871 -0
  86. package/dist/core/code/engine/core/ingestion/cfg/visitors/dart-harvest.js +874 -0
  87. package/dist/core/code/engine/core/ingestion/cfg/visitors/dart.js +840 -0
  88. package/dist/core/code/engine/core/ingestion/cfg/visitors/go-harvest.js +625 -0
  89. package/dist/core/code/engine/core/ingestion/cfg/visitors/go.js +642 -0
  90. package/dist/core/code/engine/core/ingestion/cfg/visitors/java-harvest.js +517 -0
  91. package/dist/core/code/engine/core/ingestion/cfg/visitors/java.js +816 -0
  92. package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin-harvest.js +723 -0
  93. package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin.js +813 -0
  94. package/dist/core/code/engine/core/ingestion/cfg/visitors/php-harvest.js +630 -0
  95. package/dist/core/code/engine/core/ingestion/cfg/visitors/php.js +725 -0
  96. package/dist/core/code/engine/core/ingestion/cfg/visitors/python-harvest.js +776 -0
  97. package/dist/core/code/engine/core/ingestion/cfg/visitors/python.js +562 -0
  98. package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby-harvest.js +591 -0
  99. package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby.js +760 -0
  100. package/dist/core/code/engine/core/ingestion/cfg/visitors/rust-harvest.js +877 -0
  101. package/dist/core/code/engine/core/ingestion/cfg/visitors/rust.js +562 -0
  102. package/dist/core/code/engine/core/ingestion/cfg/visitors/scope-tree-harvest.js +120 -0
  103. package/dist/core/code/engine/core/ingestion/cfg/visitors/swift-harvest.js +683 -0
  104. package/dist/core/code/engine/core/ingestion/cfg/visitors/swift.js +791 -0
  105. package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript-harvest.js +1060 -0
  106. package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript.js +587 -0
  107. package/dist/core/code/engine/core/ingestion/class-extractors/configs/c-cpp.js +77 -0
  108. package/dist/core/code/engine/core/ingestion/class-extractors/configs/csharp.js +24 -0
  109. package/dist/core/code/engine/core/ingestion/class-extractors/configs/dart.js +10 -0
  110. package/dist/core/code/engine/core/ingestion/class-extractors/configs/go.js +28 -0
  111. package/dist/core/code/engine/core/ingestion/class-extractors/configs/jvm.js +67 -0
  112. package/dist/core/code/engine/core/ingestion/class-extractors/configs/php.js +10 -0
  113. package/dist/core/code/engine/core/ingestion/class-extractors/configs/python.js +10 -0
  114. package/dist/core/code/engine/core/ingestion/class-extractors/configs/ruby.js +13 -0
  115. package/dist/core/code/engine/core/ingestion/class-extractors/configs/rust.js +10 -0
  116. package/dist/core/code/engine/core/ingestion/class-extractors/configs/swift.js +21 -0
  117. package/dist/core/code/engine/core/ingestion/class-extractors/configs/typescript-javascript.js +31 -0
  118. package/dist/core/code/engine/core/ingestion/class-extractors/generic.js +144 -0
  119. package/dist/core/code/engine/core/ingestion/class-types.js +2 -0
  120. package/dist/core/code/engine/core/ingestion/cluster-enricher.js +174 -0
  121. package/dist/core/code/engine/core/ingestion/community-processor.js +604 -0
  122. package/dist/core/code/engine/core/ingestion/constants.js +26 -0
  123. package/dist/core/code/engine/core/ingestion/cpp-ue-preprocessor.js +263 -0
  124. package/dist/core/code/engine/core/ingestion/csharp-namespace-gate.js +133 -0
  125. package/dist/core/code/engine/core/ingestion/di-extractors/index.js +38 -0
  126. package/dist/core/code/engine/core/ingestion/di-extractors/spring.js +310 -0
  127. package/dist/core/code/engine/core/ingestion/emit-references.js +244 -0
  128. package/dist/core/code/engine/core/ingestion/entry-point-scoring.js +201 -0
  129. package/dist/core/code/engine/core/ingestion/export-detection.js +244 -0
  130. package/dist/core/code/engine/core/ingestion/field-extractor.js +29 -0
  131. package/dist/core/code/engine/core/ingestion/field-extractors/configs/c-cpp.js +107 -0
  132. package/dist/core/code/engine/core/ingestion/field-extractors/configs/csharp.js +124 -0
  133. package/dist/core/code/engine/core/ingestion/field-extractors/configs/dart.js +99 -0
  134. package/dist/core/code/engine/core/ingestion/field-extractors/configs/go.js +102 -0
  135. package/dist/core/code/engine/core/ingestion/field-extractors/configs/helpers.js +198 -0
  136. package/dist/core/code/engine/core/ingestion/field-extractors/configs/jvm.js +172 -0
  137. package/dist/core/code/engine/core/ingestion/field-extractors/configs/php.js +67 -0
  138. package/dist/core/code/engine/core/ingestion/field-extractors/configs/python.js +94 -0
  139. package/dist/core/code/engine/core/ingestion/field-extractors/configs/ruby.js +79 -0
  140. package/dist/core/code/engine/core/ingestion/field-extractors/configs/rust.js +55 -0
  141. package/dist/core/code/engine/core/ingestion/field-extractors/configs/swift.js +93 -0
  142. package/dist/core/code/engine/core/ingestion/field-extractors/configs/typescript-javascript.js +59 -0
  143. package/dist/core/code/engine/core/ingestion/field-extractors/generic.js +147 -0
  144. package/dist/core/code/engine/core/ingestion/field-extractors/typescript.js +266 -0
  145. package/dist/core/code/engine/core/ingestion/field-types.js +3 -0
  146. package/dist/core/code/engine/core/ingestion/filesystem-walker.js +136 -0
  147. package/dist/core/code/engine/core/ingestion/finalize-orchestrator.js +159 -0
  148. package/dist/core/code/engine/core/ingestion/framework-detection.js +432 -0
  149. package/dist/core/code/engine/core/ingestion/frameworks/spring/analysis-features.js +38 -0
  150. package/dist/core/code/engine/core/ingestion/frameworks/spring/annotation-arguments.js +234 -0
  151. package/dist/core/code/engine/core/ingestion/frameworks/spring/aop-candidates.js +88 -0
  152. package/dist/core/code/engine/core/ingestion/frameworks/spring/aop.js +487 -0
  153. package/dist/core/code/engine/core/ingestion/frameworks/spring/auto-configuration.js +21 -0
  154. package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-candidates.js +189 -0
  155. package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-catalog.js +32 -0
  156. package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-factories.js +73 -0
  157. package/dist/core/code/engine/core/ingestion/frameworks/spring/conditionals.js +323 -0
  158. package/dist/core/code/engine/core/ingestion/frameworks/spring/config-bindings.js +119 -0
  159. package/dist/core/code/engine/core/ingestion/frameworks/spring/di-metadata.js +385 -0
  160. package/dist/core/code/engine/core/ingestion/frameworks/spring/resource-injection.js +96 -0
  161. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/c-cpp.js +17 -0
  162. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/csharp.js +46 -0
  163. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/dart.js +59 -0
  164. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/go.js +30 -0
  165. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/jvm.js +73 -0
  166. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/php.js +19 -0
  167. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/python.js +45 -0
  168. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/ruby.js +20 -0
  169. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/rust.js +58 -0
  170. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/swift.js +94 -0
  171. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/typescript-javascript.js +26 -0
  172. package/dist/core/code/engine/core/ingestion/import-resolvers/csharp.js +128 -0
  173. package/dist/core/code/engine/core/ingestion/import-resolvers/go.js +50 -0
  174. package/dist/core/code/engine/core/ingestion/import-resolvers/jvm.js +112 -0
  175. package/dist/core/code/engine/core/ingestion/import-resolvers/php.js +80 -0
  176. package/dist/core/code/engine/core/ingestion/import-resolvers/python.js +75 -0
  177. package/dist/core/code/engine/core/ingestion/import-resolvers/resolver-factory.js +36 -0
  178. package/dist/core/code/engine/core/ingestion/import-resolvers/ruby.js +20 -0
  179. package/dist/core/code/engine/core/ingestion/import-resolvers/rust.js +79 -0
  180. package/dist/core/code/engine/core/ingestion/import-resolvers/standard.js +180 -0
  181. package/dist/core/code/engine/core/ingestion/import-resolvers/types.js +7 -0
  182. package/dist/core/code/engine/core/ingestion/import-resolvers/utils.js +153 -0
  183. package/dist/core/code/engine/core/ingestion/import-target-adapter.js +99 -0
  184. package/dist/core/code/engine/core/ingestion/language-config.js +391 -0
  185. package/dist/core/code/engine/core/ingestion/language-provider.js +25 -0
  186. package/dist/core/code/engine/core/ingestion/languages/c/arity-metadata.js +98 -0
  187. package/dist/core/code/engine/core/ingestion/languages/c/arity.js +21 -0
  188. package/dist/core/code/engine/core/ingestion/languages/c/capture-side-channel.js +69 -0
  189. package/dist/core/code/engine/core/ingestion/languages/c/captures.js +189 -0
  190. package/dist/core/code/engine/core/ingestion/languages/c/header-scan.js +58 -0
  191. package/dist/core/code/engine/core/ingestion/languages/c/import-decomposer.js +68 -0
  192. package/dist/core/code/engine/core/ingestion/languages/c/import-target.js +103 -0
  193. package/dist/core/code/engine/core/ingestion/languages/c/index.js +33 -0
  194. package/dist/core/code/engine/core/ingestion/languages/c/interpret.js +53 -0
  195. package/dist/core/code/engine/core/ingestion/languages/c/merge-bindings.js +26 -0
  196. package/dist/core/code/engine/core/ingestion/languages/c/query.js +210 -0
  197. package/dist/core/code/engine/core/ingestion/languages/c/scope-resolver.js +112 -0
  198. package/dist/core/code/engine/core/ingestion/languages/c/simple-hooks.js +24 -0
  199. package/dist/core/code/engine/core/ingestion/languages/c/static-linkage.js +109 -0
  200. package/dist/core/code/engine/core/ingestion/languages/c-cpp.js +506 -0
  201. package/dist/core/code/engine/core/ingestion/languages/cpp/adl.js +804 -0
  202. package/dist/core/code/engine/core/ingestion/languages/cpp/arity-metadata.js +258 -0
  203. package/dist/core/code/engine/core/ingestion/languages/cpp/arity.js +37 -0
  204. package/dist/core/code/engine/core/ingestion/languages/cpp/capture-side-channel.js +89 -0
  205. package/dist/core/code/engine/core/ingestion/languages/cpp/captures.js +1975 -0
  206. package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-extractor.js +311 -0
  207. package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-filter.js +210 -0
  208. package/dist/core/code/engine/core/ingestion/languages/cpp/conversion-rank.js +163 -0
  209. package/dist/core/code/engine/core/ingestion/languages/cpp/file-local-linkage.js +327 -0
  210. package/dist/core/code/engine/core/ingestion/languages/cpp/header-scan.js +53 -0
  211. package/dist/core/code/engine/core/ingestion/languages/cpp/import-decomposer.js +134 -0
  212. package/dist/core/code/engine/core/ingestion/languages/cpp/import-target.js +16 -0
  213. package/dist/core/code/engine/core/ingestion/languages/cpp/index.js +33 -0
  214. package/dist/core/code/engine/core/ingestion/languages/cpp/inline-namespaces.js +379 -0
  215. package/dist/core/code/engine/core/ingestion/languages/cpp/interpret.js +239 -0
  216. package/dist/core/code/engine/core/ingestion/languages/cpp/member-lookup.js +470 -0
  217. package/dist/core/code/engine/core/ingestion/languages/cpp/merge-bindings.js +32 -0
  218. package/dist/core/code/engine/core/ingestion/languages/cpp/query.js +763 -0
  219. package/dist/core/code/engine/core/ingestion/languages/cpp/range-bindings.js +230 -0
  220. package/dist/core/code/engine/core/ingestion/languages/cpp/scope-resolver.js +354 -0
  221. package/dist/core/code/engine/core/ingestion/languages/cpp/simple-hooks.js +67 -0
  222. package/dist/core/code/engine/core/ingestion/languages/cpp/two-phase-lookup.js +348 -0
  223. package/dist/core/code/engine/core/ingestion/languages/cpp/type-classifier.js +56 -0
  224. package/dist/core/code/engine/core/ingestion/languages/cpp/user-defined-conversions.js +128 -0
  225. package/dist/core/code/engine/core/ingestion/languages/csharp/accessor-unwrap.js +67 -0
  226. package/dist/core/code/engine/core/ingestion/languages/csharp/arity-metadata.js +49 -0
  227. package/dist/core/code/engine/core/ingestion/languages/csharp/arity.js +40 -0
  228. package/dist/core/code/engine/core/ingestion/languages/csharp/cache-stats.js +32 -0
  229. package/dist/core/code/engine/core/ingestion/languages/csharp/captures.js +557 -0
  230. package/dist/core/code/engine/core/ingestion/languages/csharp/import-decomposer.js +96 -0
  231. package/dist/core/code/engine/core/ingestion/languages/csharp/import-target.js +176 -0
  232. package/dist/core/code/engine/core/ingestion/languages/csharp/index.js +95 -0
  233. package/dist/core/code/engine/core/ingestion/languages/csharp/interpret.js +150 -0
  234. package/dist/core/code/engine/core/ingestion/languages/csharp/merge-bindings.js +58 -0
  235. package/dist/core/code/engine/core/ingestion/languages/csharp/namespace-siblings.js +708 -0
  236. package/dist/core/code/engine/core/ingestion/languages/csharp/qualified-type-names.js +62 -0
  237. package/dist/core/code/engine/core/ingestion/languages/csharp/query.js +578 -0
  238. package/dist/core/code/engine/core/ingestion/languages/csharp/receiver-binding.js +142 -0
  239. package/dist/core/code/engine/core/ingestion/languages/csharp/resolution-config.js +18 -0
  240. package/dist/core/code/engine/core/ingestion/languages/csharp/scope-resolver.js +84 -0
  241. package/dist/core/code/engine/core/ingestion/languages/csharp/simple-hooks.js +81 -0
  242. package/dist/core/code/engine/core/ingestion/languages/csharp.js +204 -0
  243. package/dist/core/code/engine/core/ingestion/languages/dart/arity-metadata.js +38 -0
  244. package/dist/core/code/engine/core/ingestion/languages/dart/arity.js +34 -0
  245. package/dist/core/code/engine/core/ingestion/languages/dart/built-ins.js +37 -0
  246. package/dist/core/code/engine/core/ingestion/languages/dart/cache-stats.js +30 -0
  247. package/dist/core/code/engine/core/ingestion/languages/dart/captures.js +1096 -0
  248. package/dist/core/code/engine/core/ingestion/languages/dart/expand-wildcards.js +34 -0
  249. package/dist/core/code/engine/core/ingestion/languages/dart/extension-type-preprocess.js +33 -0
  250. package/dist/core/code/engine/core/ingestion/languages/dart/import-target.js +68 -0
  251. package/dist/core/code/engine/core/ingestion/languages/dart/index.js +45 -0
  252. package/dist/core/code/engine/core/ingestion/languages/dart/interpret.js +101 -0
  253. package/dist/core/code/engine/core/ingestion/languages/dart/merge-bindings.js +42 -0
  254. package/dist/core/code/engine/core/ingestion/languages/dart/query.js +246 -0
  255. package/dist/core/code/engine/core/ingestion/languages/dart/receiver-binding.js +90 -0
  256. package/dist/core/code/engine/core/ingestion/languages/dart/scope-resolver.js +197 -0
  257. package/dist/core/code/engine/core/ingestion/languages/dart/signature-bindings.js +54 -0
  258. package/dist/core/code/engine/core/ingestion/languages/dart/simple-hooks.js +61 -0
  259. package/dist/core/code/engine/core/ingestion/languages/dart.js +138 -0
  260. package/dist/core/code/engine/core/ingestion/languages/go/arity-metadata.js +71 -0
  261. package/dist/core/code/engine/core/ingestion/languages/go/arity.js +17 -0
  262. package/dist/core/code/engine/core/ingestion/languages/go/cache-stats.js +21 -0
  263. package/dist/core/code/engine/core/ingestion/languages/go/captures.js +492 -0
  264. package/dist/core/code/engine/core/ingestion/languages/go/expand-wildcards.js +97 -0
  265. package/dist/core/code/engine/core/ingestion/languages/go/generic-type-parameters.js +146 -0
  266. package/dist/core/code/engine/core/ingestion/languages/go/import-decomposer.js +47 -0
  267. package/dist/core/code/engine/core/ingestion/languages/go/import-target.js +70 -0
  268. package/dist/core/code/engine/core/ingestion/languages/go/index.js +39 -0
  269. package/dist/core/code/engine/core/ingestion/languages/go/interface-impls.js +955 -0
  270. package/dist/core/code/engine/core/ingestion/languages/go/interpret.js +177 -0
  271. package/dist/core/code/engine/core/ingestion/languages/go/merge-bindings.js +21 -0
  272. package/dist/core/code/engine/core/ingestion/languages/go/method-owners.js +131 -0
  273. package/dist/core/code/engine/core/ingestion/languages/go/namespace-mirror.js +56 -0
  274. package/dist/core/code/engine/core/ingestion/languages/go/package-clause.js +79 -0
  275. package/dist/core/code/engine/core/ingestion/languages/go/package-siblings.js +83 -0
  276. package/dist/core/code/engine/core/ingestion/languages/go/query.js +298 -0
  277. package/dist/core/code/engine/core/ingestion/languages/go/range-binding.js +127 -0
  278. package/dist/core/code/engine/core/ingestion/languages/go/receiver-binding.js +24 -0
  279. package/dist/core/code/engine/core/ingestion/languages/go/scope-resolver.js +75 -0
  280. package/dist/core/code/engine/core/ingestion/languages/go/simple-hooks.js +31 -0
  281. package/dist/core/code/engine/core/ingestion/languages/go/type-binding.js +279 -0
  282. package/dist/core/code/engine/core/ingestion/languages/go.js +160 -0
  283. package/dist/core/code/engine/core/ingestion/languages/index.js +66 -0
  284. package/dist/core/code/engine/core/ingestion/languages/java/analysis-features.js +16 -0
  285. package/dist/core/code/engine/core/ingestion/languages/java/arity-metadata.js +43 -0
  286. package/dist/core/code/engine/core/ingestion/languages/java/arity.js +27 -0
  287. package/dist/core/code/engine/core/ingestion/languages/java/cache-stats.js +32 -0
  288. package/dist/core/code/engine/core/ingestion/languages/java/capture-side-channel.js +123 -0
  289. package/dist/core/code/engine/core/ingestion/languages/java/captures.js +791 -0
  290. package/dist/core/code/engine/core/ingestion/languages/java/import-decomposer.js +88 -0
  291. package/dist/core/code/engine/core/ingestion/languages/java/import-target.js +103 -0
  292. package/dist/core/code/engine/core/ingestion/languages/java/index.js +43 -0
  293. package/dist/core/code/engine/core/ingestion/languages/java/interpret.js +146 -0
  294. package/dist/core/code/engine/core/ingestion/languages/java/merge-bindings.js +43 -0
  295. package/dist/core/code/engine/core/ingestion/languages/java/package-facts.js +16 -0
  296. package/dist/core/code/engine/core/ingestion/languages/java/package-siblings.js +11 -0
  297. package/dist/core/code/engine/core/ingestion/languages/java/query.js +319 -0
  298. package/dist/core/code/engine/core/ingestion/languages/java/receiver-binding.js +98 -0
  299. package/dist/core/code/engine/core/ingestion/languages/java/scope-resolver.js +213 -0
  300. package/dist/core/code/engine/core/ingestion/languages/java/simple-hooks.js +39 -0
  301. package/dist/core/code/engine/core/ingestion/languages/java/spring-aop.js +53 -0
  302. package/dist/core/code/engine/core/ingestion/languages/java/spring-bean-metadata.js +11 -0
  303. package/dist/core/code/engine/core/ingestion/languages/java/spring-conditionals.js +52 -0
  304. package/dist/core/code/engine/core/ingestion/languages/java/spring-config-bindings.js +222 -0
  305. package/dist/core/code/engine/core/ingestion/languages/java/spring-di.js +165 -0
  306. package/dist/core/code/engine/core/ingestion/languages/java.js +192 -0
  307. package/dist/core/code/engine/core/ingestion/languages/javascript/arity.js +15 -0
  308. package/dist/core/code/engine/core/ingestion/languages/javascript/captures.js +1122 -0
  309. package/dist/core/code/engine/core/ingestion/languages/javascript/import-target.js +56 -0
  310. package/dist/core/code/engine/core/ingestion/languages/javascript/index.js +109 -0
  311. package/dist/core/code/engine/core/ingestion/languages/javascript/interpret.js +45 -0
  312. package/dist/core/code/engine/core/ingestion/languages/javascript/merge-bindings.js +21 -0
  313. package/dist/core/code/engine/core/ingestion/languages/javascript/query.js +659 -0
  314. package/dist/core/code/engine/core/ingestion/languages/javascript/scope-resolver.js +78 -0
  315. package/dist/core/code/engine/core/ingestion/languages/javascript/simple-hooks.js +44 -0
  316. package/dist/core/code/engine/core/ingestion/languages/jvm/package-facts.js +46 -0
  317. package/dist/core/code/engine/core/ingestion/languages/jvm/package-siblings.js +200 -0
  318. package/dist/core/code/engine/core/ingestion/languages/kotlin/arity-metadata.js +23 -0
  319. package/dist/core/code/engine/core/ingestion/languages/kotlin/arity.js +18 -0
  320. package/dist/core/code/engine/core/ingestion/languages/kotlin/cache-stats.js +21 -0
  321. package/dist/core/code/engine/core/ingestion/languages/kotlin/capture-side-channel.js +160 -0
  322. package/dist/core/code/engine/core/ingestion/languages/kotlin/captures.js +1262 -0
  323. package/dist/core/code/engine/core/ingestion/languages/kotlin/companion-scopes.js +72 -0
  324. package/dist/core/code/engine/core/ingestion/languages/kotlin/import-decomposer.js +40 -0
  325. package/dist/core/code/engine/core/ingestion/languages/kotlin/import-target.js +135 -0
  326. package/dist/core/code/engine/core/ingestion/languages/kotlin/index.js +26 -0
  327. package/dist/core/code/engine/core/ingestion/languages/kotlin/interpret.js +75 -0
  328. package/dist/core/code/engine/core/ingestion/languages/kotlin/merge-bindings.js +28 -0
  329. package/dist/core/code/engine/core/ingestion/languages/kotlin/owners.js +134 -0
  330. package/dist/core/code/engine/core/ingestion/languages/kotlin/package-facts.js +16 -0
  331. package/dist/core/code/engine/core/ingestion/languages/kotlin/package-siblings.js +11 -0
  332. package/dist/core/code/engine/core/ingestion/languages/kotlin/query.js +243 -0
  333. package/dist/core/code/engine/core/ingestion/languages/kotlin/receiver-binding.js +103 -0
  334. package/dist/core/code/engine/core/ingestion/languages/kotlin/scope-resolver.js +207 -0
  335. package/dist/core/code/engine/core/ingestion/languages/kotlin/simple-hooks.js +42 -0
  336. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-aop.js +68 -0
  337. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-bean-metadata.js +11 -0
  338. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-conditionals.js +53 -0
  339. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-di.js +304 -0
  340. package/dist/core/code/engine/core/ingestion/languages/kotlin.js +189 -0
  341. package/dist/core/code/engine/core/ingestion/languages/php/arity-metadata.js +66 -0
  342. package/dist/core/code/engine/core/ingestion/languages/php/arity.js +43 -0
  343. package/dist/core/code/engine/core/ingestion/languages/php/cache-stats.js +32 -0
  344. package/dist/core/code/engine/core/ingestion/languages/php/captures.js +1166 -0
  345. package/dist/core/code/engine/core/ingestion/languages/php/import-decomposer.js +238 -0
  346. package/dist/core/code/engine/core/ingestion/languages/php/import-target.js +213 -0
  347. package/dist/core/code/engine/core/ingestion/languages/php/index.js +85 -0
  348. package/dist/core/code/engine/core/ingestion/languages/php/interpret.js +256 -0
  349. package/dist/core/code/engine/core/ingestion/languages/php/merge-bindings.js +50 -0
  350. package/dist/core/code/engine/core/ingestion/languages/php/namespace-siblings.js +353 -0
  351. package/dist/core/code/engine/core/ingestion/languages/php/query.js +391 -0
  352. package/dist/core/code/engine/core/ingestion/languages/php/receiver-binding.js +135 -0
  353. package/dist/core/code/engine/core/ingestion/languages/php/scope-resolver.js +361 -0
  354. package/dist/core/code/engine/core/ingestion/languages/php/simple-hooks.js +116 -0
  355. package/dist/core/code/engine/core/ingestion/languages/php.js +302 -0
  356. package/dist/core/code/engine/core/ingestion/languages/python/arity-metadata.js +49 -0
  357. package/dist/core/code/engine/core/ingestion/languages/python/arity.js +41 -0
  358. package/dist/core/code/engine/core/ingestion/languages/python/cache-stats.js +34 -0
  359. package/dist/core/code/engine/core/ingestion/languages/python/captures.js +299 -0
  360. package/dist/core/code/engine/core/ingestion/languages/python/depends-references.js +68 -0
  361. package/dist/core/code/engine/core/ingestion/languages/python/import-decomposer.js +115 -0
  362. package/dist/core/code/engine/core/ingestion/languages/python/import-target.js +440 -0
  363. package/dist/core/code/engine/core/ingestion/languages/python/index-stats.js +30 -0
  364. package/dist/core/code/engine/core/ingestion/languages/python/index.js +96 -0
  365. package/dist/core/code/engine/core/ingestion/languages/python/interpret.js +430 -0
  366. package/dist/core/code/engine/core/ingestion/languages/python/merge-bindings.js +47 -0
  367. package/dist/core/code/engine/core/ingestion/languages/python/query.js +323 -0
  368. package/dist/core/code/engine/core/ingestion/languages/python/receiver-binding.js +310 -0
  369. package/dist/core/code/engine/core/ingestion/languages/python/scope-resolver.js +80 -0
  370. package/dist/core/code/engine/core/ingestion/languages/python/simple-hooks.js +53 -0
  371. package/dist/core/code/engine/core/ingestion/languages/python.js +140 -0
  372. package/dist/core/code/engine/core/ingestion/languages/ruby/arity.js +41 -0
  373. package/dist/core/code/engine/core/ingestion/languages/ruby/cache-stats.js +21 -0
  374. package/dist/core/code/engine/core/ingestion/languages/ruby/captures.js +864 -0
  375. package/dist/core/code/engine/core/ingestion/languages/ruby/import-target.js +88 -0
  376. package/dist/core/code/engine/core/ingestion/languages/ruby/index.js +29 -0
  377. package/dist/core/code/engine/core/ingestion/languages/ruby/interpret.js +115 -0
  378. package/dist/core/code/engine/core/ingestion/languages/ruby/merge-bindings.js +21 -0
  379. package/dist/core/code/engine/core/ingestion/languages/ruby/query.js +349 -0
  380. package/dist/core/code/engine/core/ingestion/languages/ruby/receiver-binding.js +70 -0
  381. package/dist/core/code/engine/core/ingestion/languages/ruby/scope-resolver.js +263 -0
  382. package/dist/core/code/engine/core/ingestion/languages/ruby/simple-hooks.js +68 -0
  383. package/dist/core/code/engine/core/ingestion/languages/ruby.js +215 -0
  384. package/dist/core/code/engine/core/ingestion/languages/rust/arity.js +16 -0
  385. package/dist/core/code/engine/core/ingestion/languages/rust/cache-stats.js +21 -0
  386. package/dist/core/code/engine/core/ingestion/languages/rust/captures.js +304 -0
  387. package/dist/core/code/engine/core/ingestion/languages/rust/import-decomposer.js +167 -0
  388. package/dist/core/code/engine/core/ingestion/languages/rust/import-target.js +108 -0
  389. package/dist/core/code/engine/core/ingestion/languages/rust/index.js +29 -0
  390. package/dist/core/code/engine/core/ingestion/languages/rust/interpret.js +201 -0
  391. package/dist/core/code/engine/core/ingestion/languages/rust/merge-bindings.js +21 -0
  392. package/dist/core/code/engine/core/ingestion/languages/rust/method-owners.js +76 -0
  393. package/dist/core/code/engine/core/ingestion/languages/rust/module-path.js +222 -0
  394. package/dist/core/code/engine/core/ingestion/languages/rust/qualified-call.js +482 -0
  395. package/dist/core/code/engine/core/ingestion/languages/rust/query.js +280 -0
  396. package/dist/core/code/engine/core/ingestion/languages/rust/range-binding.js +687 -0
  397. package/dist/core/code/engine/core/ingestion/languages/rust/receiver-binding.js +148 -0
  398. package/dist/core/code/engine/core/ingestion/languages/rust/scope-resolver.js +151 -0
  399. package/dist/core/code/engine/core/ingestion/languages/rust/simple-hooks.js +32 -0
  400. package/dist/core/code/engine/core/ingestion/languages/rust.js +183 -0
  401. package/dist/core/code/engine/core/ingestion/languages/swift/arity-metadata.js +44 -0
  402. package/dist/core/code/engine/core/ingestion/languages/swift/arity.js +45 -0
  403. package/dist/core/code/engine/core/ingestion/languages/swift/base-type.js +30 -0
  404. package/dist/core/code/engine/core/ingestion/languages/swift/cache-stats.js +32 -0
  405. package/dist/core/code/engine/core/ingestion/languages/swift/captures.js +594 -0
  406. package/dist/core/code/engine/core/ingestion/languages/swift/conditional-directive-preprocess.js +256 -0
  407. package/dist/core/code/engine/core/ingestion/languages/swift/implicit-imports.js +60 -0
  408. package/dist/core/code/engine/core/ingestion/languages/swift/import-decomposer.js +87 -0
  409. package/dist/core/code/engine/core/ingestion/languages/swift/import-target.js +84 -0
  410. package/dist/core/code/engine/core/ingestion/languages/swift/index.js +56 -0
  411. package/dist/core/code/engine/core/ingestion/languages/swift/interpret.js +93 -0
  412. package/dist/core/code/engine/core/ingestion/languages/swift/merge-bindings.js +51 -0
  413. package/dist/core/code/engine/core/ingestion/languages/swift/query.js +226 -0
  414. package/dist/core/code/engine/core/ingestion/languages/swift/receiver-binding.js +169 -0
  415. package/dist/core/code/engine/core/ingestion/languages/swift/scope-resolver.js +192 -0
  416. package/dist/core/code/engine/core/ingestion/languages/swift/sibling-type-bindings.js +68 -0
  417. package/dist/core/code/engine/core/ingestion/languages/swift/signature-bindings.js +69 -0
  418. package/dist/core/code/engine/core/ingestion/languages/swift/simple-hooks.js +65 -0
  419. package/dist/core/code/engine/core/ingestion/languages/swift/target-grouping.js +97 -0
  420. package/dist/core/code/engine/core/ingestion/languages/swift/target-siblings.js +74 -0
  421. package/dist/core/code/engine/core/ingestion/languages/swift.js +246 -0
  422. package/dist/core/code/engine/core/ingestion/languages/typescript/arity-metadata.js +106 -0
  423. package/dist/core/code/engine/core/ingestion/languages/typescript/arity.js +57 -0
  424. package/dist/core/code/engine/core/ingestion/languages/typescript/array-callback.js +58 -0
  425. package/dist/core/code/engine/core/ingestion/languages/typescript/cache-stats.js +34 -0
  426. package/dist/core/code/engine/core/ingestion/languages/typescript/captures.js +956 -0
  427. package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-export-assignment.js +535 -0
  428. package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-module-exports.js +196 -0
  429. package/dist/core/code/engine/core/ingestion/languages/typescript/import-decomposer.js +374 -0
  430. package/dist/core/code/engine/core/ingestion/languages/typescript/import-target.js +65 -0
  431. package/dist/core/code/engine/core/ingestion/languages/typescript/index.js +108 -0
  432. package/dist/core/code/engine/core/ingestion/languages/typescript/interpret.js +344 -0
  433. package/dist/core/code/engine/core/ingestion/languages/typescript/merge-bindings.js +161 -0
  434. package/dist/core/code/engine/core/ingestion/languages/typescript/nuxt-auto-imports.js +325 -0
  435. package/dist/core/code/engine/core/ingestion/languages/typescript/query.js +1328 -0
  436. package/dist/core/code/engine/core/ingestion/languages/typescript/receiver-binding.js +201 -0
  437. package/dist/core/code/engine/core/ingestion/languages/typescript/scope-resolver.js +293 -0
  438. package/dist/core/code/engine/core/ingestion/languages/typescript/simple-hooks.js +139 -0
  439. package/dist/core/code/engine/core/ingestion/languages/typescript.js +455 -0
  440. package/dist/core/code/engine/core/ingestion/languages/vue/captures.js +70 -0
  441. package/dist/core/code/engine/core/ingestion/languages/vue/import-target.js +61 -0
  442. package/dist/core/code/engine/core/ingestion/languages/vue/index.js +55 -0
  443. package/dist/core/code/engine/core/ingestion/languages/vue/scope-resolver.js +295 -0
  444. package/dist/core/code/engine/core/ingestion/languages/vue.js +96 -0
  445. package/dist/core/code/engine/core/ingestion/local-symbol-pruner.js +68 -0
  446. package/dist/core/code/engine/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
  447. package/dist/core/code/engine/core/ingestion/method-extractors/configs/csharp.js +290 -0
  448. package/dist/core/code/engine/core/ingestion/method-extractors/configs/dart.js +392 -0
  449. package/dist/core/code/engine/core/ingestion/method-extractors/configs/go.js +179 -0
  450. package/dist/core/code/engine/core/ingestion/method-extractors/configs/jvm.js +350 -0
  451. package/dist/core/code/engine/core/ingestion/method-extractors/configs/php.js +306 -0
  452. package/dist/core/code/engine/core/ingestion/method-extractors/configs/python.js +312 -0
  453. package/dist/core/code/engine/core/ingestion/method-extractors/configs/ruby.js +289 -0
  454. package/dist/core/code/engine/core/ingestion/method-extractors/configs/rust.js +198 -0
  455. package/dist/core/code/engine/core/ingestion/method-extractors/configs/swift.js +286 -0
  456. package/dist/core/code/engine/core/ingestion/method-extractors/configs/typescript-javascript.js +341 -0
  457. package/dist/core/code/engine/core/ingestion/method-extractors/generic.js +209 -0
  458. package/dist/core/code/engine/core/ingestion/method-types.js +3 -0
  459. package/dist/core/code/engine/core/ingestion/model/field-registry.js +41 -0
  460. package/dist/core/code/engine/core/ingestion/model/index.js +52 -0
  461. package/dist/core/code/engine/core/ingestion/model/method-registry.js +138 -0
  462. package/dist/core/code/engine/core/ingestion/model/owned-members-lookup.js +46 -0
  463. package/dist/core/code/engine/core/ingestion/model/registration-table.js +234 -0
  464. package/dist/core/code/engine/core/ingestion/model/resolve.js +183 -0
  465. package/dist/core/code/engine/core/ingestion/model/scope-resolution-indexes.js +43 -0
  466. package/dist/core/code/engine/core/ingestion/model/semantic-model.js +179 -0
  467. package/dist/core/code/engine/core/ingestion/model/symbol-table.js +216 -0
  468. package/dist/core/code/engine/core/ingestion/model/type-registry.js +84 -0
  469. package/dist/core/code/engine/core/ingestion/mro-processor.js +709 -0
  470. package/dist/core/code/engine/core/ingestion/parsing-processor.js +312 -0
  471. package/dist/core/code/engine/core/ingestion/pipeline-phases/communities.js +69 -0
  472. package/dist/core/code/engine/core/ingestion/pipeline-phases/cross-file.js +71 -0
  473. package/dist/core/code/engine/core/ingestion/pipeline-phases/di.js +338 -0
  474. package/dist/core/code/engine/core/ingestion/pipeline-phases/http-api-calls.js +312 -0
  475. package/dist/core/code/engine/core/ingestion/pipeline-phases/index.js +54 -0
  476. package/dist/core/code/engine/core/ingestion/pipeline-phases/mro.js +40 -0
  477. package/dist/core/code/engine/core/ingestion/pipeline-phases/orm.js +78 -0
  478. package/dist/core/code/engine/core/ingestion/pipeline-phases/parse-impl.js +1286 -0
  479. package/dist/core/code/engine/core/ingestion/pipeline-phases/parse.js +41 -0
  480. package/dist/core/code/engine/core/ingestion/pipeline-phases/processes.js +193 -0
  481. package/dist/core/code/engine/core/ingestion/pipeline-phases/prune-local-symbols.js +29 -0
  482. package/dist/core/code/engine/core/ingestion/pipeline-phases/registry.js +52 -0
  483. package/dist/core/code/engine/core/ingestion/pipeline-phases/routes.js +409 -0
  484. package/dist/core/code/engine/core/ingestion/pipeline-phases/rpc-edges.js +301 -0
  485. package/dist/core/code/engine/core/ingestion/pipeline-phases/runner.js +207 -0
  486. package/dist/core/code/engine/core/ingestion/pipeline-phases/scan.js +49 -0
  487. package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-aop.js +442 -0
  488. package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-auto-configuration.js +264 -0
  489. package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-config.js +440 -0
  490. package/dist/core/code/engine/core/ingestion/pipeline-phases/structure.js +38 -0
  491. package/dist/core/code/engine/core/ingestion/pipeline-phases/tools.js +89 -0
  492. package/dist/core/code/engine/core/ingestion/pipeline-phases/types.js +40 -0
  493. package/dist/core/code/engine/core/ingestion/pipeline.js +152 -0
  494. package/dist/core/code/engine/core/ingestion/process-processor.js +325 -0
  495. package/dist/core/code/engine/core/ingestion/resolve-references.js +205 -0
  496. package/dist/core/code/engine/core/ingestion/route-extractors/constant-resolver.js +135 -0
  497. package/dist/core/code/engine/core/ingestion/route-extractors/django-root-discovery.js +221 -0
  498. package/dist/core/code/engine/core/ingestion/route-extractors/django.js +428 -0
  499. package/dist/core/code/engine/core/ingestion/route-extractors/expo.js +39 -0
  500. package/dist/core/code/engine/core/ingestion/route-extractors/fastapi-router-bindings.js +264 -0
  501. package/dist/core/code/engine/core/ingestion/route-extractors/laravel.js +501 -0
  502. package/dist/core/code/engine/core/ingestion/route-extractors/middleware.js +175 -0
  503. package/dist/core/code/engine/core/ingestion/route-extractors/nextjs.js +81 -0
  504. package/dist/core/code/engine/core/ingestion/route-extractors/php.js +25 -0
  505. package/dist/core/code/engine/core/ingestion/route-extractors/python-const-resolver.js +307 -0
  506. package/dist/core/code/engine/core/ingestion/route-extractors/response-shapes.js +299 -0
  507. package/dist/core/code/engine/core/ingestion/route-extractors/route-path.js +71 -0
  508. package/dist/core/code/engine/core/ingestion/route-extractors/spring-shared.js +310 -0
  509. package/dist/core/code/engine/core/ingestion/route-extractors/spring.js +441 -0
  510. package/dist/core/code/engine/core/ingestion/scope-extractor-bridge.js +60 -0
  511. package/dist/core/code/engine/core/ingestion/scope-extractor.js +1373 -0
  512. package/dist/core/code/engine/core/ingestion/scope-resolution/contract/scope-resolver.js +282 -0
  513. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +72 -0
  514. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/edges.js +194 -0
  515. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/ids.js +472 -0
  516. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +49 -0
  517. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +43 -0
  518. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +274 -0
  519. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +93 -0
  520. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/callable-value-flow.js +1240 -0
  521. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/compound-receiver.js +1174 -0
  522. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/free-call-fallback.js +873 -0
  523. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/imported-return-types.js +226 -0
  524. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/mro.js +107 -0
  525. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/overload-narrowing.js +441 -0
  526. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/property-dispatch.js +122 -0
  527. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +1720 -0
  528. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/phase.js +395 -0
  529. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +208 -0
  530. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/registry.js +49 -0
  531. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/run.js +632 -0
  532. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.js +112 -0
  533. package/dist/core/code/engine/core/ingestion/scope-resolution/resolution-outcome.js +41 -0
  534. package/dist/core/code/engine/core/ingestion/scope-resolution/scope/namespace-targets.js +81 -0
  535. package/dist/core/code/engine/core/ingestion/scope-resolution/scope/walkers.js +1835 -0
  536. package/dist/core/code/engine/core/ingestion/scope-resolution/unresolved-receivers.js +242 -0
  537. package/dist/core/code/engine/core/ingestion/scope-resolution/utils/definition-id.js +22 -0
  538. package/dist/core/code/engine/core/ingestion/scope-resolution/workspace-index.js +151 -0
  539. package/dist/core/code/engine/core/ingestion/structure-processor.js +40 -0
  540. package/dist/core/code/engine/core/ingestion/tree-sitter-queries.js +2244 -0
  541. package/dist/core/code/engine/core/ingestion/ts-js-hoc-utils.js +115 -0
  542. package/dist/core/code/engine/core/ingestion/type-env.js +1136 -0
  543. package/dist/core/code/engine/core/ingestion/type-extractors/c-cpp.js +555 -0
  544. package/dist/core/code/engine/core/ingestion/type-extractors/csharp.js +570 -0
  545. package/dist/core/code/engine/core/ingestion/type-extractors/dart.js +372 -0
  546. package/dist/core/code/engine/core/ingestion/type-extractors/go.js +508 -0
  547. package/dist/core/code/engine/core/ingestion/type-extractors/jvm.js +875 -0
  548. package/dist/core/code/engine/core/ingestion/type-extractors/php.js +537 -0
  549. package/dist/core/code/engine/core/ingestion/type-extractors/python.js +477 -0
  550. package/dist/core/code/engine/core/ingestion/type-extractors/ruby.js +380 -0
  551. package/dist/core/code/engine/core/ingestion/type-extractors/rust.js +502 -0
  552. package/dist/core/code/engine/core/ingestion/type-extractors/shared.js +843 -0
  553. package/dist/core/code/engine/core/ingestion/type-extractors/swift.js +490 -0
  554. package/dist/core/code/engine/core/ingestion/type-extractors/types.js +2 -0
  555. package/dist/core/code/engine/core/ingestion/type-extractors/typescript.js +690 -0
  556. package/dist/core/code/engine/core/ingestion/utils/ast-helpers.js +1693 -0
  557. package/dist/core/code/engine/core/ingestion/utils/call-analysis.js +779 -0
  558. package/dist/core/code/engine/core/ingestion/utils/callable-flow-captures.js +932 -0
  559. package/dist/core/code/engine/core/ingestion/utils/callable-labels.js +49 -0
  560. package/dist/core/code/engine/core/ingestion/utils/deferred-resolution-profile.js +151 -0
  561. package/dist/core/code/engine/core/ingestion/utils/effective-ram.js +67 -0
  562. package/dist/core/code/engine/core/ingestion/utils/env.js +60 -0
  563. package/dist/core/code/engine/core/ingestion/utils/event-loop.js +9 -0
  564. package/dist/core/code/engine/core/ingestion/utils/graph-sort.js +103 -0
  565. package/dist/core/code/engine/core/ingestion/utils/heap-probe.js +45 -0
  566. package/dist/core/code/engine/core/ingestion/utils/heritage-marker.js +47 -0
  567. package/dist/core/code/engine/core/ingestion/utils/line-base.js +24 -0
  568. package/dist/core/code/engine/core/ingestion/utils/max-file-size.js +59 -0
  569. package/dist/core/code/engine/core/ingestion/utils/method-props.js +198 -0
  570. package/dist/core/code/engine/core/ingestion/utils/qualified-name.js +73 -0
  571. package/dist/core/code/engine/core/ingestion/utils/receiver-chain-captures.js +60 -0
  572. package/dist/core/code/engine/core/ingestion/utils/receiver-chain-codec.js +188 -0
  573. package/dist/core/code/engine/core/ingestion/utils/scope-tree-walk.js +36 -0
  574. package/dist/core/code/engine/core/ingestion/utils/symbol-labels.js +48 -0
  575. package/dist/core/code/engine/core/ingestion/utils/template-arguments.js +187 -0
  576. package/dist/core/code/engine/core/ingestion/utils/type-parameters.js +209 -0
  577. package/dist/core/code/engine/core/ingestion/utils/verbose.js +6 -0
  578. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/c-cpp.js +133 -0
  579. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/csharp.js +66 -0
  580. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/dart.js +111 -0
  581. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/go.js +153 -0
  582. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/jvm.js +145 -0
  583. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/php.js +61 -0
  584. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/python.js +104 -0
  585. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/ruby.js +55 -0
  586. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/rust.js +79 -0
  587. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/swift.js +91 -0
  588. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/typescript-javascript.js +86 -0
  589. package/dist/core/code/engine/core/ingestion/variable-extractors/generic.js +111 -0
  590. package/dist/core/code/engine/core/ingestion/variable-types.js +3 -0
  591. package/dist/core/code/engine/core/ingestion/vue-sfc-extractor.js +544 -0
  592. package/dist/core/code/engine/core/ingestion/workers/callable-id.js +122 -0
  593. package/dist/core/code/engine/core/ingestion/workers/clone-safety.js +470 -0
  594. package/dist/core/code/engine/core/ingestion/workers/parse-worker.js +2456 -0
  595. package/dist/core/code/engine/core/ingestion/workers/post-result.js +90 -0
  596. package/dist/core/code/engine/core/ingestion/workers/quarantine.js +41 -0
  597. package/dist/core/code/engine/core/ingestion/workers/result-merge.js +59 -0
  598. package/dist/core/code/engine/core/ingestion/workers/worker-pool.js +1725 -0
  599. package/dist/core/code/engine/core/ingestion/workspace-config.js +139 -0
  600. package/dist/core/code/engine/core/lbug/conn-lock.js +72 -0
  601. package/dist/core/code/engine/core/lbug/csv-generator.js +710 -0
  602. package/dist/core/code/engine/core/lbug/cypher-escape.js +24 -0
  603. package/dist/core/code/engine/core/lbug/extension-load-error.js +339 -0
  604. package/dist/core/code/engine/core/lbug/extension-loader.js +261 -0
  605. package/dist/core/code/engine/core/lbug/graph-emit-sink.js +584 -0
  606. package/dist/core/code/engine/core/lbug/lbug-adapter.js +2703 -0
  607. package/dist/core/code/engine/core/lbug/lbug-config.js +1029 -0
  608. package/dist/core/code/engine/core/lbug/native-check.js +435 -0
  609. package/dist/core/code/engine/core/lbug/pool-adapter.js +973 -0
  610. package/dist/core/code/engine/core/lbug/query-params.js +25 -0
  611. package/dist/core/code/engine/core/lbug/query-result-utils.js +31 -0
  612. package/dist/core/code/engine/core/lbug/rel-pair-routing.js +373 -0
  613. package/dist/core/code/engine/core/lbug/schema.js +771 -0
  614. package/dist/core/code/engine/core/lbug/shutdown-helpers.js +40 -0
  615. package/dist/core/code/engine/core/lbug/sidecar-recovery.js +716 -0
  616. package/dist/core/code/engine/core/lbug/stdio-capture.js +49 -0
  617. package/dist/core/code/engine/core/lbug/sync-csv-writer.js +115 -0
  618. package/dist/core/code/engine/core/lbug/wal-checkpoint-driver.js +215 -0
  619. package/dist/core/code/engine/core/lbug/wal-driver-state.js +28 -0
  620. package/dist/core/code/engine/core/logger.js +339 -0
  621. package/dist/core/code/engine/core/platform/capabilities.js +91 -0
  622. package/dist/core/code/engine/core/run-analyze.js +1098 -0
  623. package/dist/core/code/engine/core/tree-sitter/parser-loader.js +281 -0
  624. package/dist/core/code/engine/core/tree-sitter/safe-parse.js +258 -0
  625. package/dist/core/code/engine/core/tree-sitter/vendored-grammars.js +64 -0
  626. package/dist/core/code/engine/lib/utils.js +121 -0
  627. package/dist/core/code/engine/mcp/core/lbug-adapter.js +27 -0
  628. package/dist/core/code/engine/mcp/local/aop-metadata.js +230 -0
  629. package/dist/core/code/engine/mcp/local/bean-metadata.js +49 -0
  630. package/dist/core/code/engine/mcp/local/limits.js +15 -0
  631. package/dist/core/code/engine/mcp/local/line-display.js +6 -0
  632. package/dist/core/code/engine/mcp/local/local-backend.js +4142 -0
  633. package/dist/core/code/engine/storage/branch-index.js +72 -0
  634. package/dist/core/code/engine/storage/file-hash.js +95 -0
  635. package/dist/core/code/engine/storage/fs-atomic.js +34 -0
  636. package/dist/core/code/engine/storage/git.js +555 -0
  637. package/dist/core/code/engine/storage/index-lock.js +664 -0
  638. package/dist/core/code/engine/storage/parse-cache.js +650 -0
  639. package/dist/core/code/engine/storage/parsedfile-store.js +620 -0
  640. package/dist/core/code/engine/storage/repo-manager.js +1061 -0
  641. package/dist/core/code/engine/storage/scope-index-store.js +247 -0
  642. package/dist/core/code/engine/types/pipeline.js +2 -0
  643. package/dist/core/code/scripts/install-duckdb-extension.mjs +125 -0
  644. package/dist/core/code/scripts/resolve-analyze-cmd.cjs +346 -0
  645. package/dist/core/code/shared/graph/types.js +8 -0
  646. package/dist/core/code/shared/index.js +105 -0
  647. package/dist/core/code/shared/integrations/circuit-breaker.js +242 -0
  648. package/dist/core/code/shared/integrations/resilient-fetch.js +224 -0
  649. package/dist/core/code/shared/integrations/retry.js +70 -0
  650. package/dist/core/code/shared/integrations/understand-quickly.js +145 -0
  651. package/dist/core/code/shared/language-detection.js +162 -0
  652. package/dist/core/code/shared/languages.js +27 -0
  653. package/dist/core/code/shared/lbug/schema-constants.js +98 -0
  654. package/dist/core/code/shared/mro-strategy.js +2 -0
  655. package/dist/core/code/shared/pipeline.js +5 -0
  656. package/dist/core/code/shared/scope-resolution/callable-flow-site.js +11 -0
  657. package/dist/core/code/shared/scope-resolution/def-index.js +53 -0
  658. package/dist/core/code/shared/scope-resolution/evidence-weights.js +87 -0
  659. package/dist/core/code/shared/scope-resolution/finalize-algorithm.js +807 -0
  660. package/dist/core/code/shared/scope-resolution/language-classification.js +46 -0
  661. package/dist/core/code/shared/scope-resolution/method-dispatch-index.js +100 -0
  662. package/dist/core/code/shared/scope-resolution/module-scope-index.js +59 -0
  663. package/dist/core/code/shared/scope-resolution/origin-priority.js +23 -0
  664. package/dist/core/code/shared/scope-resolution/parsed-file.js +54 -0
  665. package/dist/core/code/shared/scope-resolution/position-index.js +136 -0
  666. package/dist/core/code/shared/scope-resolution/qualified-name-index.js +77 -0
  667. package/dist/core/code/shared/scope-resolution/reference-site.js +24 -0
  668. package/dist/core/code/shared/scope-resolution/registries/class-registry.js +32 -0
  669. package/dist/core/code/shared/scope-resolution/registries/context.js +52 -0
  670. package/dist/core/code/shared/scope-resolution/registries/evidence.js +152 -0
  671. package/dist/core/code/shared/scope-resolution/registries/field-registry.js +33 -0
  672. package/dist/core/code/shared/scope-resolution/registries/lookup-core.js +392 -0
  673. package/dist/core/code/shared/scope-resolution/registries/lookup-qualified.js +58 -0
  674. package/dist/core/code/shared/scope-resolution/registries/macro-registry.js +34 -0
  675. package/dist/core/code/shared/scope-resolution/registries/method-registry.js +34 -0
  676. package/dist/core/code/shared/scope-resolution/registries/tie-breaks.js +63 -0
  677. package/dist/core/code/shared/scope-resolution/resolve-type-ref.js +128 -0
  678. package/dist/core/code/shared/scope-resolution/scope-id.js +49 -0
  679. package/dist/core/code/shared/scope-resolution/scope-tree.js +225 -0
  680. package/dist/core/code/shared/scope-resolution/symbol-definition.js +12 -0
  681. package/dist/core/code/shared/scope-resolution/types.js +25 -0
  682. package/dist/core/code/shared/test-helpers.js +17 -0
  683. package/dist/core/code/vendor/leiden/index.cjs +355 -0
  684. package/dist/core/code/vendor/leiden/utils.cjs +419 -0
  685. package/dist/core/dbquery/cli.d.ts.map +1 -1
  686. package/dist/core/dbquery/cli.js +5 -4
  687. package/dist/core/dbquery/cli.js.map +1 -1
  688. package/dist/core/dbquery/config.d.ts.map +1 -1
  689. package/dist/core/dbquery/config.js +39 -3
  690. package/dist/core/dbquery/config.js.map +1 -1
  691. package/dist/core/dbquery/drivers/http.d.ts +23 -0
  692. package/dist/core/dbquery/drivers/http.d.ts.map +1 -0
  693. package/dist/core/dbquery/drivers/http.js +125 -0
  694. package/dist/core/dbquery/drivers/http.js.map +1 -0
  695. package/dist/core/dbquery/drivers/mysql.js +1 -1
  696. package/dist/core/dbquery/drivers/mysql.js.map +1 -1
  697. package/dist/core/dbquery/drivers/postgres.js +1 -1
  698. package/dist/core/dbquery/drivers/postgres.js.map +1 -1
  699. package/dist/core/dbquery/executor.d.ts.map +1 -1
  700. package/dist/core/dbquery/executor.js +46 -12
  701. package/dist/core/dbquery/executor.js.map +1 -1
  702. package/dist/core/dbquery/format.d.ts.map +1 -1
  703. package/dist/core/dbquery/format.js +2 -1
  704. package/dist/core/dbquery/format.js.map +1 -1
  705. package/dist/core/dbquery/init.d.ts.map +1 -1
  706. package/dist/core/dbquery/init.js +7 -0
  707. package/dist/core/dbquery/init.js.map +1 -1
  708. package/dist/core/dbquery/types.d.ts +55 -7
  709. package/dist/core/dbquery/types.d.ts.map +1 -1
  710. package/dist/core/directory.d.ts +17 -0
  711. package/dist/core/directory.d.ts.map +1 -1
  712. package/dist/core/directory.js +37 -0
  713. package/dist/core/directory.js.map +1 -1
  714. package/dist/core/features/cli.d.ts.map +1 -1
  715. package/dist/core/features/cli.js +3 -2
  716. package/dist/core/features/cli.js.map +1 -1
  717. package/dist/core/features/scanner.d.ts +1 -1
  718. package/dist/core/features/scanner.d.ts.map +1 -1
  719. package/dist/core/features/scanner.js +20 -4
  720. package/dist/core/features/scanner.js.map +1 -1
  721. package/dist/core/markdown/cli.d.ts.map +1 -1
  722. package/dist/core/markdown/cli.js +9 -8
  723. package/dist/core/markdown/cli.js.map +1 -1
  724. package/dist/core/timeline/cli.d.ts.map +1 -1
  725. package/dist/core/timeline/cli.js +13 -6
  726. package/dist/core/timeline/cli.js.map +1 -1
  727. package/dist/core/timeline/debris.d.ts +20 -0
  728. package/dist/core/timeline/debris.d.ts.map +1 -0
  729. package/dist/core/timeline/debris.js +124 -0
  730. package/dist/core/timeline/debris.js.map +1 -0
  731. package/dist/core/timeline/hook-runner.d.ts.map +1 -1
  732. package/dist/core/timeline/hook-runner.js +3 -1
  733. package/dist/core/timeline/hook-runner.js.map +1 -1
  734. package/dist/core/timeline/hooks.d.ts.map +1 -1
  735. package/dist/core/timeline/hooks.js +13 -5
  736. package/dist/core/timeline/hooks.js.map +1 -1
  737. package/dist/core/timeline/installer.d.ts +2 -0
  738. package/dist/core/timeline/installer.d.ts.map +1 -1
  739. package/dist/core/timeline/installer.js +12 -0
  740. package/dist/core/timeline/installer.js.map +1 -1
  741. package/dist/core/timeline/project-root.d.ts +21 -0
  742. package/dist/core/timeline/project-root.d.ts.map +1 -0
  743. package/dist/core/timeline/project-root.js +83 -0
  744. package/dist/core/timeline/project-root.js.map +1 -0
  745. package/dist/web/register.d.ts.map +1 -1
  746. package/dist/web/register.js +2 -1
  747. package/dist/web/register.js.map +1 -1
  748. package/package.json +1 -1
  749. package/dist/.claude-template/.cgraphx/timeline-current-turn.json +0 -1
  750. package/dist/.claude-template/skills/.cgraphx/timeline-current-turn.json +0 -1
  751. package/dist/.claude-template/skills/handdrawn-deck/.cgraphx/timeline-current-turn.json +0 -1
  752. package/dist/.claude-template/skills/handdrawn-deck/references/.cgraphx/timeline-current-turn.json +0 -1
  753. package/dist/.claude-template/skills/handdrawn-sketch-engine/.cgraphx/timeline-current-turn.json +0 -1
  754. /package/dist/.claude-template/skills/run-api-test/assets/{template-test-verify.jsonl → template-/346/216/245/345/217/243/346/265/213/350/257/225/351/252/214/350/257/201.jsonl"} +0 -0
@@ -0,0 +1,1061 @@
1
+ "use strict";
2
+ /**
3
+ * Repository Manager
4
+ *
5
+ * Manages GitNexus index storage:
6
+ * - Per-repo metadata file (cgraph.json) under .cgraphx/code/, dual-written to a
7
+ * legacy meta.json mirror for backward compatibility (see MIGRATION.md)
8
+ * - .cgraphx/code/ directory for local metadata and caches (parse-cache, parsedfile-store)
9
+ *
10
+ * cgraph.json is simply a filename distinct from the generic meta.json — it
11
+ * has no bearing on git worktree behavior. .cgraphx/code/ remains fully git-ignored
12
+ * in every case; each worktree already has its own independent .cgraphx/code/ by
13
+ * construction (getStoragePath is per-checkout), regardless of which filename
14
+ * the metadata inside it uses.
15
+ */
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.findSiblingClones = exports.saveCLIConfig = exports.loadCLIConfig = exports.getGlobalConfigPath = exports.listRegisteredRepos = exports.resolveRegistryEntry = exports.assertSafeStoragePath = exports.UnsafeStoragePathError = exports.assertAnalysisFinalized = exports.isRepoRegistered = exports.AnalysisNotFinalizedError = exports.RegistryAmbiguousTargetError = exports.RegistryNotFoundError = exports.adoptFlatBranchLabel = exports.removeBranchIndex = exports.unregisterRepo = exports.registerRepo = exports.RegistryNameCollisionError = exports.readRegistry = exports.resolveProjectRoot = exports.getGlobalDir = exports.ensureGitNexusIgnored = exports.findRepo = exports.reconcileMetadataFiles = exports.loadRepo = exports.hasIndex = exports.saveMeta = exports.loadMeta = exports.cleanupOldKuzuFiles = exports.hasKuzuIndex = exports.getStoragePaths = exports.getStoragePath = exports.INDEX_METADATA_FILE = exports.cloneDirBelongsToEntry = exports.registryPathEquals = exports.canonicalizePath = exports.resolveBranchPlacement = exports.branchSlug = void 0;
21
+ exports.isReadOnlyFilesystemError = isReadOnlyFilesystemError;
22
+ exports.isMissingFilesystemError = isMissingFilesystemError;
23
+ const promises_1 = __importDefault(require("fs/promises"));
24
+ const fs_1 = require("fs");
25
+ const path_1 = __importDefault(require("path"));
26
+ const os_1 = __importDefault(require("os"));
27
+ const crypto_1 = require("crypto");
28
+ const git_js_1 = require("./git.js");
29
+ const utils_js_1 = require("../lib/utils.js");
30
+ const fs_atomic_js_1 = require("./fs-atomic.js");
31
+ const logger_js_1 = require("../core/logger.js");
32
+ const branch_index_js_1 = require("./branch-index.js");
33
+ Object.defineProperty(exports, "branchSlug", { enumerable: true, get: function () { return branch_index_js_1.branchSlug; } });
34
+ Object.defineProperty(exports, "resolveBranchPlacement", { enumerable: true, get: function () { return branch_index_js_1.resolveBranchPlacement; } });
35
+ /**
36
+ * Normalise a repo path for registry comparison across platforms
37
+ * (#664 review feedback from @evander-wang).
38
+ *
39
+ * Why this exists: `path.resolve` alone is NOT enough for
40
+ * cross-platform registry stability.
41
+ * - **macOS**: tmpdirs and `/var` are symlinks to `/private/var`.
42
+ * A child process that stored `/private/var/folders/.../repo` in
43
+ * the registry cannot later be matched by an outer caller that
44
+ * supplies the symlink form `/var/folders/.../repo`. `path.resolve`
45
+ * does not follow symlinks; `realpathSync.native` does.
46
+ * - **Windows**: GitHub runners surface tmpdirs in 8.3 short-name
47
+ * form (`RUNNERA~1\...`), but `process.cwd()` often returns the
48
+ * long form (`runneradmin\...`). `realpathSync.native` normalises
49
+ * both sides to the long-name canonical path.
50
+ * - **Windows, extended-length paths** (#2667): a caller can supply a
51
+ * `\\?\`-prefixed path — the usual MAX_PATH workaround — and
52
+ * `path.resolve` preserves the prefix, so the string compare below
53
+ * never matches the un-prefixed entry the registry stores. The
54
+ * realpath branch already dropped it (libuv strips the prefix inside
55
+ * `fs__realpath`), but the fallback branch did not, which is exactly
56
+ * the branch a missing path takes. `stripWindowsLongPathPrefix` is
57
+ * applied to both so the two branches agree.
58
+ *
59
+ * This normalisation is safe here precisely because the result is only ever
60
+ * compared, never opened: Node does NOT re-add `\\?\` for over-MAX_PATH
61
+ * paths, so an fs-facing path must keep whatever form the caller gave it.
62
+ * See the `registerRepo` comment on applying canonicalisation at COMPARE
63
+ * points only.
64
+ *
65
+ * Fallback behaviour: if the path does not exist on disk (e.g. a user
66
+ * passed `gitnexus remove some-alias` and the alias misses every
67
+ * registry entry, or the caller is resolving a path that was deleted
68
+ * after registration), we return `path.resolve(p)` rather than
69
+ * throwing. This preserves the idempotent-on-missing semantics of
70
+ * `resolveRegistryEntry` / `remove`.
71
+ *
72
+ * Backwards compatibility: this function is applied to BOTH the
73
+ * caller-supplied input AND each stored `entry.path` at compare time
74
+ * inside `resolveRegistryEntry`, so registries written by older
75
+ * versions still match correctly. Entries are NOT canonicalised at
76
+ * write time — `registerRepo` stores `path.resolve(repoPath)` — which
77
+ * is what makes the compare-only rule above hold.
78
+ */
79
+ const canonicalizePath = (p) => {
80
+ const resolved = path_1.default.resolve(p);
81
+ try {
82
+ return (0, utils_js_1.stripWindowsLongPathPrefix)(fs_1.realpathSync.native(resolved));
83
+ }
84
+ catch {
85
+ return (0, utils_js_1.stripWindowsLongPathPrefix)(resolved);
86
+ }
87
+ };
88
+ exports.canonicalizePath = canonicalizePath;
89
+ /**
90
+ * Compare two already-canonicalised registry paths. Case-insensitive on Windows
91
+ * (its filesystem is), case-sensitive elsewhere. Both arguments must already be
92
+ * run through {@link canonicalizePath}; this is the single comparison the registry
93
+ * lookups/dedup/finalize checks all share so they answer identically.
94
+ */
95
+ const registryPathEquals = (a, b) => process.platform === 'win32' ? a.toLowerCase() === b.toLowerCase() : a === b;
96
+ exports.registryPathEquals = registryPathEquals;
97
+ /**
98
+ * Does the clone dir derived from an entry's *name* actually belong to that
99
+ * entry? Registry names are not unique across storage locations: a cloned
100
+ * repo under `~/.cgraphx/code/repos/<name>` and a local repo registered under the
101
+ * same name share a `getCloneDir(entry.name)` result. The server's delete
102
+ * handler must therefore never remove the clone dir based on the name alone —
103
+ * only when the entry's own `path` resolves to that dir (mirroring its step-2b
104
+ * rule that cleanup is driven off `entry.path`, so a same-named sibling's
105
+ * clone is never removed). Both sides are canonicalised so symlinked or
106
+ * differently-spelled forms of the same dir still match.
107
+ */
108
+ const cloneDirBelongsToEntry = (cloneDir, entryPath) => (0, exports.registryPathEquals)((0, exports.canonicalizePath)(cloneDir), (0, exports.canonicalizePath)(entryPath));
109
+ exports.cloneDirBelongsToEntry = cloneDirBelongsToEntry;
110
+ // Index directory: `<projectRoot>/.cgraphx/code` (cgraphx code 子系统,spec §4.4).
111
+ // Kept as two segments so path joins and the string-based git-exclude checks
112
+ // below share one source of truth.
113
+ const CGRAPHX_DIR = '.cgraphx';
114
+ const CGRAPHX_CODE_DIR_PARTS = [CGRAPHX_DIR, 'code'];
115
+ // git exclude entry covers the whole `.cgraphx/` tree (index + any sibling
116
+ // cgraphx state), not just the `code/` subdirectory.
117
+ const CGRAPHX_EXCLUDE_ENTRY = `${CGRAPHX_DIR}/`;
118
+ exports.INDEX_METADATA_FILE = 'cgraph.json';
119
+ // Dual-written mirror of INDEX_METADATA_FILE, kept for backward compatibility
120
+ // with consumers that only know the pre-rename filename (see MIGRATION.md).
121
+ const LEGACY_METADATA_FILE = 'meta.json';
122
+ // ─── Local Storage Helpers ─────────────────────────────────────────────
123
+ /**
124
+ * Get the .cgraphx/code storage path for a repository.
125
+ * Used for local metadata and caches that are not committed.
126
+ */
127
+ const getStoragePath = (repoPath) => {
128
+ return path_1.default.join(path_1.default.resolve(repoPath), ...CGRAPHX_CODE_DIR_PARTS);
129
+ };
130
+ exports.getStoragePath = getStoragePath;
131
+ /**
132
+ * Get paths to key storage files.
133
+ *
134
+ * `storagePath` is ALWAYS the flat `<repo>/.cgraphx/code` — content-addressed
135
+ * caches (`parse-cache/`, `parsedfile-store/`) live there and are shared
136
+ * across branches (#2106 KTD7). When `branch` is provided, both `lbugPath`
137
+ * and `metaPath` are scoped under `branches/<slug>/`. For the flat call
138
+ * (no `branch`), `storagePath` and `lbugPath` remain byte-identical to the
139
+ * pre-multi-branch behavior (#2106); `metaPath`'s FILENAME changed from
140
+ * `meta.json` to `cgraph.json` (PR #2363) — `saveMeta` keeps a `meta.json`
141
+ * mirror in sync for consumers that still read the legacy name.
142
+ *
143
+ * Each branch slot has its own metadata file:
144
+ * - Primary/flat: <repo>/.cgraphx/code/cgraph.json
145
+ * - Feature branches: <repo>/.cgraphx/code/branches/<slug>/cgraph.json
146
+ *
147
+ * Callers should use `loadMeta(metaDir)` and `saveMeta(metaDir, meta)` where
148
+ * metaDir is the directory containing the metadata file — both handle the
149
+ * legacy mirror automatically.
150
+ */
151
+ const getStoragePaths = (repoPath, branch) => {
152
+ const storagePath = (0, exports.getStoragePath)(repoPath);
153
+ const baseDir = branch ? path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR, (0, branch_index_js_1.branchSlug)(branch)) : storagePath;
154
+ return {
155
+ storagePath,
156
+ lbugPath: path_1.default.join(baseDir, 'lbug'),
157
+ metaPath: path_1.default.join(baseDir, exports.INDEX_METADATA_FILE), // Branch-specific metadata file
158
+ };
159
+ };
160
+ exports.getStoragePaths = getStoragePaths;
161
+ /**
162
+ * Check whether a KuzuDB index exists in the given storage path.
163
+ * Non-destructive — safe to call from status commands.
164
+ */
165
+ const hasKuzuIndex = async (storagePath) => {
166
+ try {
167
+ await promises_1.default.stat(path_1.default.join(storagePath, 'kuzu'));
168
+ return true;
169
+ }
170
+ catch {
171
+ return false;
172
+ }
173
+ };
174
+ exports.hasKuzuIndex = hasKuzuIndex;
175
+ /**
176
+ * Clean up stale KuzuDB files after migration to LadybugDB.
177
+ *
178
+ * Returns:
179
+ * found — true if .cgraphx/code/kuzu existed and was deleted
180
+ * needsReindex — true if kuzu existed but lbug does not (re-analyze required)
181
+ *
182
+ * Callers own the user-facing messaging; this function only deletes files.
183
+ */
184
+ const cleanupOldKuzuFiles = async (storagePath) => {
185
+ const oldPath = path_1.default.join(storagePath, 'kuzu');
186
+ const newPath = path_1.default.join(storagePath, 'lbug');
187
+ try {
188
+ await promises_1.default.stat(oldPath);
189
+ // Old kuzu file/dir exists — determine if lbug is already present
190
+ let needsReindex = false;
191
+ try {
192
+ await promises_1.default.stat(newPath);
193
+ }
194
+ catch {
195
+ needsReindex = true;
196
+ }
197
+ // Delete kuzu database file and its sidecars (.wal, .lock)
198
+ for (const suffix of ['', '.wal', '.lock']) {
199
+ try {
200
+ await promises_1.default.unlink(oldPath + suffix);
201
+ }
202
+ catch { }
203
+ }
204
+ // Also handle the case where kuzu was stored as a directory
205
+ try {
206
+ await promises_1.default.rm(oldPath, { recursive: true, force: true });
207
+ }
208
+ catch { }
209
+ return { found: true, needsReindex };
210
+ }
211
+ catch {
212
+ // Old path doesn't exist — nothing to do
213
+ return { found: false, needsReindex: false };
214
+ }
215
+ };
216
+ exports.cleanupOldKuzuFiles = cleanupOldKuzuFiles;
217
+ /**
218
+ * Load metadata from the legacy `meta.json` mirror in the given directory.
219
+ * Returns null when the file is absent, unreadable, or unparseable — a
220
+ * corrupt legacy file is treated the same as a missing one (safe rebuild).
221
+ */
222
+ const loadMetaLegacy = async (metaDir) => tryReadMetaFile(metaDir, LEGACY_METADATA_FILE);
223
+ /**
224
+ * Load metadata from a directory containing the metadata file (cgraph.json).
225
+ * For primary/flat: metaDir = <repo>/.cgraphx/code
226
+ * For feature branches: metaDir = <repo>/.cgraphx/code/branches/<slug>
227
+ *
228
+ * Falls back to the legacy `meta.json` mirror ONLY when `cgraph.json` is
229
+ * provably absent (ENOENT/ENOTDIR). Any other failure — a parse error, EACCES,
230
+ * EIO — returns null instead of silently resurrecting possibly-stale legacy
231
+ * content: a corrupt primary file must trigger the same safe full-rebuild path
232
+ * a missing index would (the fail-safe `saveMeta`'s docstring relies on), not
233
+ * an incremental run over a stale legacy baseline.
234
+ */
235
+ const loadMeta = async (metaDir) => {
236
+ let raw;
237
+ try {
238
+ raw = await promises_1.default.readFile(path_1.default.join(metaDir, exports.INDEX_METADATA_FILE), 'utf-8');
239
+ }
240
+ catch (err) {
241
+ // Provably absent → the legacy mirror is the source of truth (pre-rename
242
+ // repo, or a mirror-only state). Anything else → fail safe with null.
243
+ return isMissingFilesystemError(err) ? loadMetaLegacy(metaDir) : null;
244
+ }
245
+ try {
246
+ return JSON.parse(raw);
247
+ }
248
+ catch {
249
+ // Corrupt primary file — do NOT mask it with legacy content.
250
+ return null;
251
+ }
252
+ };
253
+ exports.loadMeta = loadMeta;
254
+ /**
255
+ * Atomically write `meta` to `<dir>/<filename>`. Tmp name includes a random
256
+ * suffix (not a fixed `.tmp`) so two concurrent writers targeting the same
257
+ * directory never collide on the same tmp path — mirrors the pattern in
258
+ * core/group/bridge-db.ts's `writeBridgeMeta` (`'wx'` + `0o600` closes the
259
+ * symlink-race/permissions holes CodeQL flags as `js/insecure-temporary-file`;
260
+ * `retryRename` absorbs a transient EBUSY/EPERM/EACCES on the rename itself).
261
+ */
262
+ async function writeMetaFile(dir, filename, meta) {
263
+ const targetPath = path_1.default.join(dir, filename);
264
+ const tmpPath = `${targetPath}.tmp.${(0, crypto_1.randomBytes)(8).toString('hex')}`;
265
+ const handle = await promises_1.default.open(tmpPath, 'wx', 0o600);
266
+ try {
267
+ await handle.writeFile(JSON.stringify(meta, null, 2), 'utf-8');
268
+ }
269
+ finally {
270
+ await handle.close();
271
+ }
272
+ await (0, fs_atomic_js_1.retryRename)(tmpPath, targetPath);
273
+ }
274
+ /**
275
+ * Save metadata to the metadata file (cgraph.json) in the given directory,
276
+ * dual-writing the legacy `meta.json` mirror for backward compatibility.
277
+ *
278
+ * Atomic via tmp-file + rename (matches `saveParseCache`'s pattern). The
279
+ * `incrementalInProgress` dirty flag travels through this file — a crash
280
+ * mid-write would leave a corrupt `cgraph.json` that the next run's
281
+ * `loadMeta` would silently treat as "no prior index", losing the dirty
282
+ * flag and skipping the recovery full-rebuild. Write-and-rename rules
283
+ * that out: the rename is atomic on POSIX and on Windows (`fs.rename`
284
+ * on `node:fs/promises` uses `MoveFileEx(REPLACE_EXISTING)`), so either
285
+ * the old or the new file is observed at every moment.
286
+ *
287
+ * `cgraph.json` is the primary write and must succeed. `meta.json` is a
288
+ * best-effort mirror kept for consumers that only know the legacy filename
289
+ * (see MIGRATION.md) — its write failure is logged, not thrown, so a
290
+ * mirror-write hiccup never fails the caller's analyze run.
291
+ */
292
+ const saveMeta = async (metaDir, meta) => {
293
+ await promises_1.default.mkdir(metaDir, { recursive: true });
294
+ await writeMetaFile(metaDir, exports.INDEX_METADATA_FILE, meta);
295
+ try {
296
+ await writeMetaFile(metaDir, LEGACY_METADATA_FILE, meta);
297
+ }
298
+ catch (err) {
299
+ logger_js_1.logger.warn({ err, metaDir }, 'Failed to write legacy meta.json mirror (non-critical)');
300
+ }
301
+ };
302
+ exports.saveMeta = saveMeta;
303
+ /**
304
+ * Check if a path has a GitNexus index (metadata file or legacy location)
305
+ */
306
+ const hasIndex = async (repoPath) => {
307
+ const paths = (0, exports.getStoragePaths)(repoPath);
308
+ // Check new metadata file first
309
+ try {
310
+ await promises_1.default.access(paths.metaPath);
311
+ return true;
312
+ }
313
+ catch {
314
+ // Fall back to legacy location
315
+ try {
316
+ await promises_1.default.access(path_1.default.join(paths.storagePath, LEGACY_METADATA_FILE));
317
+ return true;
318
+ }
319
+ catch {
320
+ return false;
321
+ }
322
+ }
323
+ };
324
+ exports.hasIndex = hasIndex;
325
+ /**
326
+ * Load an indexed repo from a path (checks metadata file first, then legacy)
327
+ */
328
+ const loadRepo = async (repoPath) => {
329
+ const paths = (0, exports.getStoragePaths)(repoPath);
330
+ const meta = await (0, exports.loadMeta)(paths.storagePath);
331
+ if (!meta)
332
+ return null;
333
+ return {
334
+ repoPath: path_1.default.resolve(repoPath),
335
+ ...paths,
336
+ meta,
337
+ };
338
+ };
339
+ exports.loadRepo = loadRepo;
340
+ /**
341
+ * Best-effort read of one specific metadata filename — no fallback, null on
342
+ * any failure (absent, unreadable, or unparseable).
343
+ */
344
+ const tryReadMetaFile = async (dir, filename) => {
345
+ try {
346
+ const raw = await promises_1.default.readFile(path_1.default.join(dir, filename), 'utf-8');
347
+ return JSON.parse(raw);
348
+ }
349
+ catch {
350
+ return null;
351
+ }
352
+ };
353
+ /** `indexedAt` as epoch millis; 0 when absent/unparseable (i.e. oldest). */
354
+ const metaTimestamp = (meta) => {
355
+ const t = Date.parse(meta.indexedAt ?? '');
356
+ return Number.isFinite(t) ? t : 0;
357
+ };
358
+ /**
359
+ * Reconcile `cgraph.json` and the legacy `meta.json` mirror in one
360
+ * directory: whichever parses and is fresher (by `indexedAt`) wins and is
361
+ * re-written to BOTH files via `saveMeta`. Never deletes anything.
362
+ * Returns true when a write occurred.
363
+ */
364
+ const reconcileMetaDir = async (dir) => {
365
+ const primary = await tryReadMetaFile(dir, exports.INDEX_METADATA_FILE);
366
+ const legacy = await tryReadMetaFile(dir, LEGACY_METADATA_FILE);
367
+ if (!primary && !legacy) {
368
+ // Fresh directory (neither file) is a silent no-op; a file that exists
369
+ // but doesn't parse deserves a warning — loadMeta will treat it as "no
370
+ // prior index" and the next successful saveMeta self-heals it.
371
+ for (const filename of [exports.INDEX_METADATA_FILE, LEGACY_METADATA_FILE]) {
372
+ try {
373
+ await promises_1.default.access(path_1.default.join(dir, filename));
374
+ logger_js_1.logger.warn({ dir, filename }, 'Metadata file exists but is unreadable/corrupt; leaving as-is (next successful analyze rewrites it)');
375
+ }
376
+ catch {
377
+ // absent — expected for a fresh directory
378
+ }
379
+ }
380
+ return false;
381
+ }
382
+ if (primary && legacy) {
383
+ if (JSON.stringify(primary) === JSON.stringify(legacy))
384
+ return false; // converged
385
+ // Both parse but differ — the fresher one wins (an older binary may have
386
+ // re-analyzed and written only meta.json AFTER cgraph.json was created;
387
+ // blind-preferring the primary would permanently shadow that fresher
388
+ // state, silently certifying a stale index as up to date).
389
+ const winner = metaTimestamp(legacy) > metaTimestamp(primary) ? legacy : primary;
390
+ await (0, exports.saveMeta)(dir, winner);
391
+ logger_js_1.logger.info({ dir, winner: winner === legacy ? LEGACY_METADATA_FILE : exports.INDEX_METADATA_FILE }, 'Reconciled diverged metadata files (fresher indexedAt wins, written to both)');
392
+ return true;
393
+ }
394
+ // Exactly one parses — establish/repair the other so both stay in sync.
395
+ const survivor = (primary ?? legacy);
396
+ await (0, exports.saveMeta)(dir, survivor);
397
+ return true;
398
+ };
399
+ /**
400
+ * Reconcile the metadata files for a repo's flat slot and every
401
+ * `branches/<slug>/` slot. Runs once per `analyze` (see run-analyze.ts).
402
+ *
403
+ * This is a best-effort compatibility sync, NOT a one-way migration: the
404
+ * legacy `meta.json` mirror is kept in sync indefinitely (removal happens at
405
+ * a future major version — see MIGRATION.md), so older binaries, still-running
406
+ * MCP servers, and the shipped editor hooks keep working, and a rollback to a
407
+ * pre-rename version sees current metadata instead of "no prior index".
408
+ * Returns true when any file was written.
409
+ */
410
+ const reconcileMetadataFiles = async (repoPath) => {
411
+ const storagePath = (0, exports.getStoragePath)(repoPath);
412
+ let changed = await reconcileMetaDir(storagePath);
413
+ const branchesDir = path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR);
414
+ let branchDirs;
415
+ try {
416
+ branchDirs = await promises_1.default.readdir(branchesDir);
417
+ }
418
+ catch {
419
+ // branchesDir may not exist (not a multi-branch repo) — expected, silent.
420
+ return changed;
421
+ }
422
+ for (const branchDir of branchDirs) {
423
+ const branchPath = path_1.default.join(branchesDir, branchDir);
424
+ // Per-branch isolation: one bad branch dir (dangling symlink, EACCES)
425
+ // must not silently abort reconciliation for every branch after it —
426
+ // readdir order is stable, so an unguarded throw here would permanently
427
+ // starve the same trailing branches on every run.
428
+ try {
429
+ const stat = await promises_1.default.stat(branchPath);
430
+ if (!stat.isDirectory())
431
+ continue;
432
+ if (await reconcileMetaDir(branchPath))
433
+ changed = true;
434
+ }
435
+ catch (err) {
436
+ logger_js_1.logger.warn({ branchDir, err }, 'Skipping branch directory during metadata reconciliation (non-critical)');
437
+ }
438
+ }
439
+ return changed;
440
+ };
441
+ exports.reconcileMetadataFiles = reconcileMetadataFiles;
442
+ /**
443
+ * Find the .cgraphx/code index by walking up from a starting path
444
+ */
445
+ const findRepo = async (startPath) => {
446
+ let current = path_1.default.resolve(startPath);
447
+ const root = path_1.default.parse(current).root;
448
+ while (current !== root) {
449
+ const repo = await (0, exports.loadRepo)(current);
450
+ if (repo)
451
+ return repo;
452
+ current = path_1.default.dirname(current);
453
+ }
454
+ return null;
455
+ };
456
+ exports.findRepo = findRepo;
457
+ function isReadOnlyFilesystemError(err) {
458
+ const code = err?.code;
459
+ return code === 'EROFS' || code === 'EACCES' || code === 'EPERM';
460
+ }
461
+ /**
462
+ * True for errors that prove a path is absent (ENOENT/ENOTDIR) — as opposed
463
+ * to transient/permission failures (EIO/EACCES/EBUSY…) where the file may
464
+ * well still exist. Exported for consumers that need the same "provably
465
+ * missing vs not provably absent" distinction (e.g. collectBranchCacheKeys).
466
+ */
467
+ function isMissingFilesystemError(err) {
468
+ const code = err?.code;
469
+ return code === 'ENOENT' || code === 'ENOTDIR';
470
+ }
471
+ /**
472
+ * Keep .cgraphx/code/ ignored. It contains local index state and caches.
473
+ */
474
+ const ensureGitNexusIgnored = async (repoPath) => {
475
+ const gitignorePath = path_1.default.join((0, exports.getStoragePath)(repoPath), '.gitignore');
476
+ const desired = '*\n';
477
+ // Idempotent fast path: skip the write entirely when the file already has
478
+ // the expected content. Lets this run cleanly on read-only mounts (e.g.
479
+ // the documented Docker workflow with WORKSPACE_DIR bound :ro) when an
480
+ // earlier `analyze` already created the file. See issue #1549.
481
+ try {
482
+ if ((await promises_1.default.readFile(gitignorePath, 'utf-8')) === desired) {
483
+ await ensureGitInfoExclude(repoPath);
484
+ return;
485
+ }
486
+ }
487
+ catch (err) {
488
+ if (err?.code !== 'ENOENT')
489
+ throw err;
490
+ }
491
+ try {
492
+ await promises_1.default.mkdir(path_1.default.dirname(gitignorePath), { recursive: true });
493
+ await promises_1.default.writeFile(gitignorePath, desired, 'utf-8');
494
+ }
495
+ catch (err) {
496
+ if (isReadOnlyFilesystemError(err)) {
497
+ logger_js_1.logger.warn({ path: gitignorePath, code: err.code }, 'GitNexus storage filesystem is not writable; skipping .cgraphx/code/.gitignore. Cache files may appear as untracked in this repo locally.');
498
+ }
499
+ else {
500
+ throw err;
501
+ }
502
+ }
503
+ await ensureGitInfoExclude(repoPath);
504
+ };
505
+ exports.ensureGitNexusIgnored = ensureGitNexusIgnored;
506
+ const ensureGitInfoExclude = async (repoPath) => {
507
+ const gitDirPath = path_1.default.join(path_1.default.resolve(repoPath), '.git');
508
+ const excludePath = path_1.default.join(gitDirPath, 'info', 'exclude');
509
+ try {
510
+ const gitDir = await promises_1.default.stat(gitDirPath);
511
+ if (!gitDir.isDirectory())
512
+ return;
513
+ }
514
+ catch {
515
+ return;
516
+ }
517
+ let content = '';
518
+ try {
519
+ content = await promises_1.default.readFile(excludePath, 'utf-8');
520
+ }
521
+ catch (err) {
522
+ if (err?.code !== 'ENOENT')
523
+ throw err;
524
+ }
525
+ const excludes = content
526
+ .split(/\r?\n/)
527
+ .map((line) => line.trim())
528
+ .filter((line) => line && !line.startsWith('#'));
529
+ if (excludes.includes(CGRAPHX_DIR) || excludes.includes(CGRAPHX_EXCLUDE_ENTRY))
530
+ return;
531
+ const separator = content.length === 0 || content.endsWith('\n') ? '' : '\n';
532
+ try {
533
+ await promises_1.default.mkdir(path_1.default.dirname(excludePath), { recursive: true });
534
+ await promises_1.default.writeFile(excludePath, `${content}${separator}${CGRAPHX_EXCLUDE_ENTRY}\n`, 'utf-8');
535
+ }
536
+ catch (err) {
537
+ if (isReadOnlyFilesystemError(err)) {
538
+ logger_js_1.logger.warn({ path: excludePath, code: err.code }, 'GitNexus storage filesystem is not writable; skipping .git/info/exclude update. .cgraphx/ cache directory may appear as untracked in `git status` locally.');
539
+ }
540
+ else {
541
+ throw err;
542
+ }
543
+ }
544
+ };
545
+ // ─── Global Directory (~/.cgraphx/code/) ───────────────────────────────
546
+ /**
547
+ * Get the path to the global GitNexus directory (used for CLI config only).
548
+ */
549
+ const getGlobalDir = () => {
550
+ return process.env.CGRAPH_HOME || path_1.default.join(os_1.default.homedir(), '.cgraphx', 'code');
551
+ };
552
+ exports.getGlobalDir = getGlobalDir;
553
+ // ─── Project-root discovery (cwd-based; global registry removed) ────────
554
+ //
555
+ // The global registry was removed per spec §8 ("无全局状态"): index data lives
556
+ // ONLY in `<projectRoot>/.cgraphx/code/`, and the CLI operates on "当前目录或显式
557
+ // 路径的项目根索引". These functions replace the old registry I/O with cwd-
558
+ // based discovery so every former registry consumer (LocalBackend.refreshRepos,
559
+ // git-staleness.checkCwdMatch, findSiblingClones) resolves the same single
560
+ // project-root index without any `~/.cgraphx/code/registry.json`.
561
+ /**
562
+ * Best-effort `process.cwd()` that never throws — some sandboxed runtimes
563
+ * (deleted cwd, container teardown) make `process.cwd()` throw EBADF/ENOENT.
564
+ * Falling back to the current module directory keeps discovery alive instead
565
+ * of crashing the CLI entrypoint.
566
+ */
567
+ const safeCwd = () => {
568
+ try {
569
+ return process.cwd();
570
+ }
571
+ catch {
572
+ return __dirname;
573
+ }
574
+ };
575
+ /**
576
+ * Resolve the project root whose `.cgraphx/code/` index the CLI should operate on
577
+ * (spec §8). Discovery precedence:
578
+ *
579
+ * 1. `opts.explicitPath` — a caller-provided `--path` project root.
580
+ * 2. `CGRAPH_REPO` env var — an ambient override for scripted/CI contexts.
581
+ * 3. upward walk from `opts.startCwd` (default `process.cwd()`) for the
582
+ * nearest ancestor (or self) directory containing a readable `.cgraphx/code/`
583
+ * index metadata file.
584
+ *
585
+ * Returns the discovered {@link IndexedRepo} (meta + paths), or `null` when no
586
+ * index is found — callers surface a "run `cgraph analyze`" error in that case.
587
+ *
588
+ * Reuses {@link findRepo} / {@link loadRepo} so the walk, the cgraph.json↔
589
+ * meta.json fallback, and the storage-path derivation stay identical to the
590
+ * `status` / `analyze` commands.
591
+ */
592
+ const resolveProjectRoot = async (opts) => {
593
+ const explicit = opts?.explicitPath ?? process.env.CGRAPH_REPO;
594
+ const start = opts?.startCwd ?? (explicit ? path_1.default.resolve(explicit) : safeCwd());
595
+ return (0, exports.findRepo)(start);
596
+ };
597
+ exports.resolveProjectRoot = resolveProjectRoot;
598
+ /**
599
+ * Scan the `branches/<slug>/` sub-indexes of a project root and return their
600
+ * summaries (#2106). Non-primary branch indexes live under
601
+ * `<storagePath>/branches/<slug>/cgraph.json`; each readable meta becomes one
602
+ * {@link BranchSummary}. Absent dir, unreadable entries, or a fresh repo yield
603
+ * `[]`. Used by discovery so `--branch` scoping in LocalBackend still resolves
604
+ * pinned sub-indexes without a global registry.
605
+ */
606
+ const readBranchSummaries = async (repoPath) => {
607
+ const { storagePath } = (0, exports.getStoragePaths)(repoPath);
608
+ const branchesDir = path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR);
609
+ let entries;
610
+ try {
611
+ entries = await promises_1.default.readdir(branchesDir);
612
+ }
613
+ catch {
614
+ return []; // no branches dir → single-branch/legacy repo, expected.
615
+ }
616
+ const summaries = [];
617
+ for (const slug of entries) {
618
+ const slugDir = path_1.default.join(branchesDir, slug);
619
+ try {
620
+ const stat = await promises_1.default.stat(slugDir);
621
+ if (!stat.isDirectory())
622
+ continue;
623
+ }
624
+ catch {
625
+ continue; // dangling symlink / EACCES — skip one branch, not the whole scan.
626
+ }
627
+ const meta = await (0, exports.loadMeta)(slugDir);
628
+ if (meta?.branch) {
629
+ summaries.push({
630
+ branch: meta.branch,
631
+ indexedAt: meta.indexedAt ?? '',
632
+ lastCommit: meta.lastCommit ?? '',
633
+ stats: meta.stats,
634
+ });
635
+ }
636
+ }
637
+ return summaries;
638
+ };
639
+ /**
640
+ * Convert a discovered {@link IndexedRepo} into the {@link RegistryEntry} shape
641
+ * that former registry consumers (LocalBackend, git-staleness) expect. The
642
+ * `name` is derived the same way {@link registerRepo} derives it (explicit
643
+ * alias → inferred git remote name → basename), so the displayed label matches
644
+ * what `cgraph analyze` would report.
645
+ */
646
+ const indexedRepoToRegistryEntry = async (repo) => ({
647
+ name: (0, git_js_1.getInferredRepoName)(repo.repoPath) ?? path_1.default.basename(repo.repoPath),
648
+ path: repo.repoPath,
649
+ storagePath: repo.storagePath,
650
+ indexedAt: repo.meta.indexedAt ?? '',
651
+ lastCommit: repo.meta.lastCommit ?? '',
652
+ remoteUrl: repo.meta.remoteUrl,
653
+ stats: repo.meta.stats,
654
+ branch: repo.meta.branch,
655
+ branches: await readBranchSummaries(repo.repoPath),
656
+ });
657
+ /**
658
+ * Read the set of indexed repos discoverable from the given context. With the
659
+ * global registry removed (spec §8), this is cwd-based discovery that returns
660
+ * at most ONE entry — the project root whose `.cgraphx/code/` index is nearest the
661
+ * starting directory (or the explicit `--path` / `CGRAPH_REPO` override).
662
+ *
663
+ * Formerly read `~/.cgraphx/code/registry.json`; now delegates to
664
+ * {@link resolveProjectRoot}. Accepts optional discovery context so callers
665
+ * like `checkCwdMatch(cwd)` can pin the start directory instead of implicitly
666
+ * using `process.cwd()`.
667
+ */
668
+ const readRegistry = async (opts) => {
669
+ const repo = await (0, exports.resolveProjectRoot)(opts);
670
+ return repo ? [await indexedRepoToRegistryEntry(repo)] : [];
671
+ };
672
+ exports.readRegistry = readRegistry;
673
+ /**
674
+ * Thrown by {@link registerRepo} when a requested name is already in
675
+ * use by a DIFFERENT path. The CLI layer surfaces this as an actionable
676
+ * error instead of relying on `.message` string-matching.
677
+ *
678
+ * The colliding alias is exposed as `err.registryName` (not `err.name`).
679
+ * `err.name` keeps its inherited `Error.prototype.name` semantics (the
680
+ * class name) so downstream code can do the usual `err.name ===
681
+ * 'RegistryNameCollisionError'` checks; use the `kind` discriminant or
682
+ * `instanceof RegistryNameCollisionError` for type-safe narrowing.
683
+ */
684
+ class RegistryNameCollisionError extends Error {
685
+ registryName;
686
+ existingPath;
687
+ requestedPath;
688
+ kind = 'RegistryNameCollisionError';
689
+ constructor(registryName, existingPath, requestedPath) {
690
+ super(`Registry name "${registryName}" is already used by "${existingPath}".\n` +
691
+ `Pass --name <alias> to register "${requestedPath}" under a different name, ` +
692
+ `or --allow-duplicate-name to allow both paths under the same name (leaves -r <name> ambiguous for these two).`);
693
+ this.registryName = registryName;
694
+ this.existingPath = existingPath;
695
+ this.requestedPath = requestedPath;
696
+ this.name = 'RegistryNameCollisionError';
697
+ }
698
+ }
699
+ exports.RegistryNameCollisionError = RegistryNameCollisionError;
700
+ /**
701
+ * Register a repo. With the global registry removed (spec §8), this is a
702
+ * minimal stub: it derives and returns a project name from the repo path
703
+ * or the provided `opts.name`, performing no disk I/O. Called after
704
+ * `cgraph analyze` completes.
705
+ *
706
+ * Name resolution precedence:
707
+ * 1. explicit `opts.name` (from `analyze --name <alias>`)
708
+ * 2. `git config --get remote.origin.url` repo name
709
+ * 3. `path.basename(repoPath)` (the original default)
710
+ */
711
+ const registerRepo = async (repoPath, _meta, opts) => {
712
+ if (opts?.name)
713
+ return opts.name;
714
+ const resolved = path_1.default.resolve(repoPath);
715
+ return (0, git_js_1.getInferredRepoName)(resolved) ?? path_1.default.basename((0, git_js_1.resolveRepoIdentityRoot)(resolved));
716
+ };
717
+ exports.registerRepo = registerRepo;
718
+ /**
719
+ * No-op unregister — the global registry no longer exists.
720
+ */
721
+ const unregisterRepo = async (_repoPath) => { };
722
+ exports.unregisterRepo = unregisterRepo;
723
+ /**
724
+ * No-op branch-index removal — the global registry no longer exists.
725
+ * Returns `false` (no matching entry found) unconditionally.
726
+ */
727
+ const removeBranchIndex = async (_repoPath, _branch) => false;
728
+ exports.removeBranchIndex = removeBranchIndex;
729
+ /**
730
+ * Remove a shadowed `branches/<slug>/` sub-index directory when the flat slot
731
+ * adopts this run's branch label (#2354).
732
+ *
733
+ * The flat index follows the checked-out working tree, so when a plain analyze
734
+ * lands on a branch that also has a pinned `branches/<slug>/` sub-index, that
735
+ * sub-index becomes permanently shadowed — explicit `--branch` runs re-resolve
736
+ * to the flat slot and query-side branch scoping serves the flat handle first.
737
+ * This deletes the shadowed directory to avoid stranding un-cleanable disk
738
+ * bloat. The registry-summary bookkeeping half was removed along with the
739
+ * global registry (spec §8).
740
+ */
741
+ const adoptFlatBranchLabel = async (repoPath, branch) => {
742
+ const resolved = path_1.default.resolve(repoPath);
743
+ const { storagePath } = (0, exports.getStoragePaths)(resolved);
744
+ // Remove a shadowed sub-index directory, mirroring `clean --branch`'s
745
+ // containment guard: the target MUST live under .cgraphx/code/branches/.
746
+ const branchDir = path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR, (0, branch_index_js_1.branchSlug)(branch));
747
+ const branchesRoot = path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR) + path_1.default.sep;
748
+ if (!branchDir.startsWith(branchesRoot))
749
+ return;
750
+ let rmError;
751
+ await promises_1.default.rm(branchDir, { recursive: true, force: true }).catch((err) => {
752
+ rmError = err;
753
+ });
754
+ let dirGone = false;
755
+ if (!rmError) {
756
+ dirGone = true;
757
+ }
758
+ else {
759
+ // On failure, probe the disk and treat only provably-absent errno as gone
760
+ // — EACCES/EIO are "not provably absent" (same polarity as the old
761
+ // listRegisteredRepos validate path).
762
+ const probeCode = await promises_1.default.access(branchDir).then(() => null, (e) => e?.code ?? 'UNKNOWN');
763
+ dirGone = probeCode === 'ENOENT' || probeCode === 'ENOTDIR';
764
+ }
765
+ if (dirGone) {
766
+ // Non-recursive by design: only removes the parent when no other pinned
767
+ // sub-index remains, so an empty branches/ dir doesn't read as "pinned".
768
+ await promises_1.default.rmdir(path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR)).catch(() => { });
769
+ }
770
+ else {
771
+ logger_js_1.logger.warn({ path: branchDir, code: rmError?.code }, 'Could not remove the shadowed branch sub-index.');
772
+ }
773
+ };
774
+ exports.adoptFlatBranchLabel = adoptFlatBranchLabel;
775
+ /**
776
+ * Thrown by {@link resolveRegistryEntry} when no registered repo matches
777
+ * the caller's target string (by alias, basename, remote-inferred name,
778
+ * or resolved path). CLI callers that want idempotent "remove" semantics
779
+ * should catch this and exit 0 with a warning; non-idempotent callers
780
+ * (e.g. MCP tools) can surface the error directly.
781
+ */
782
+ class RegistryNotFoundError extends Error {
783
+ target;
784
+ availableNames;
785
+ kind = 'RegistryNotFoundError';
786
+ constructor(target, availableNames) {
787
+ const hint = availableNames.length > 0
788
+ ? ` Available: ${availableNames.join(', ')}.`
789
+ : ' No repositories are currently registered.';
790
+ super(`No registered repo matches "${target}".${hint}`);
791
+ this.target = target;
792
+ this.availableNames = availableNames;
793
+ this.name = 'RegistryNotFoundError';
794
+ }
795
+ }
796
+ exports.RegistryNotFoundError = RegistryNotFoundError;
797
+ /**
798
+ * Thrown by {@link resolveRegistryEntry} when the target string matches
799
+ * the `name` of two or more entries — only possible when the user
800
+ * previously registered duplicates via `analyze --name X
801
+ * --allow-duplicate-name` (#829). The error carries enough information
802
+ * for the caller to render an actionable disambiguation hint without
803
+ * string-matching on `.message`.
804
+ *
805
+ * `kind` is a string literal discriminant (same pattern as
806
+ * {@link RegistryNameCollisionError}) so callers can narrow via
807
+ * `err.kind === 'RegistryAmbiguousTargetError'` without importing the
808
+ * class.
809
+ */
810
+ class RegistryAmbiguousTargetError extends Error {
811
+ target;
812
+ matches;
813
+ kind = 'RegistryAmbiguousTargetError';
814
+ constructor(target, matches) {
815
+ const listing = matches.map((m) => ` - ${m.name} (${m.path})`).join('\n');
816
+ super(`Multiple registered repos match "${target}":\n${listing}\n` +
817
+ `Pass the absolute path instead to disambiguate.`);
818
+ this.target = target;
819
+ this.matches = matches;
820
+ this.name = 'RegistryAmbiguousTargetError';
821
+ }
822
+ }
823
+ exports.RegistryAmbiguousTargetError = RegistryAmbiguousTargetError;
824
+ /**
825
+ * Thrown by {@link assertAnalysisFinalized} when a successful `analyze` run
826
+ * did not actually persist the index metadata file (#1169).
827
+ *
828
+ * Why this exists: on Windows, `cgraph analyze` has been observed to exit
829
+ * cleanly (code 0) with `lbug.wal` written but no metadata file, leaving the
830
+ * repo invisible to `cgraph list`/`status`. This invariant fails loudly so
831
+ * the silent-finalize bug surfaces with a non-zero exit code regardless of
832
+ * the upstream root cause.
833
+ */
834
+ class AnalysisNotFinalizedError extends Error {
835
+ repoPath;
836
+ storagePath;
837
+ kind = 'AnalysisNotFinalizedError';
838
+ constructor(repoPath, storagePath) {
839
+ super(`Analysis did not finalize for ${repoPath}: ` +
840
+ `${exports.INDEX_METADATA_FILE} was not written to ${path_1.default.join(storagePath, exports.INDEX_METADATA_FILE)}. ` +
841
+ `The on-disk index is incomplete. ` +
842
+ `Re-run "cgraph analyze" — if the problem persists, inspect ` +
843
+ `${storagePath} for a stale lbug.wal that signals an aborted write.`);
844
+ this.repoPath = repoPath;
845
+ this.storagePath = storagePath;
846
+ this.name = 'AnalysisNotFinalizedError';
847
+ }
848
+ }
849
+ exports.AnalysisNotFinalizedError = AnalysisNotFinalizedError;
850
+ /**
851
+ * Always returns false — the global registry no longer exists, so no repo is
852
+ * ever "registered" in that sense.
853
+ */
854
+ const isRepoRegistered = async (_repoPath) => false;
855
+ exports.isRepoRegistered = isRepoRegistered;
856
+ /**
857
+ * Verify that a successful `analyze` call actually produced the index
858
+ * metadata file on disk:
859
+ * - `cgraph.json` must exist at `<repoPath>/.cgraphx/code/cgraph.json`.
860
+ *
861
+ * Throws {@link AnalysisNotFinalizedError} on failure. Pure read — does not
862
+ * mutate disk state.
863
+ *
864
+ * Callers must skip this assertion on the `alreadyUpToDate` early-return
865
+ * path, where the rebuild was deliberately not run.
866
+ */
867
+ const assertAnalysisFinalized = async (repoPath) => {
868
+ const resolved = path_1.default.resolve(repoPath);
869
+ const { storagePath, metaPath } = (0, exports.getStoragePaths)(resolved);
870
+ try {
871
+ await promises_1.default.access(metaPath);
872
+ }
873
+ catch {
874
+ throw new AnalysisNotFinalizedError(resolved, storagePath);
875
+ }
876
+ };
877
+ exports.assertAnalysisFinalized = assertAnalysisFinalized;
878
+ /**
879
+ * Thrown by {@link assertSafeStoragePath} when an entry's `storagePath` does
880
+ * NOT point at the expected `<entry.path>/.cgraphx/code` subfolder. CLI destructive
881
+ * commands (`remove`, `clean --all`) should catch this and exit non-zero
882
+ * without deleting anything — proceeding would mean `fs.rm(recursive: true)`
883
+ * on whatever odd path the entry is pointing at.
884
+ */
885
+ class UnsafeStoragePathError extends Error {
886
+ entry;
887
+ expectedStoragePath;
888
+ actualStoragePath;
889
+ kind = 'UnsafeStoragePathError';
890
+ constructor(entry, expectedStoragePath, actualStoragePath) {
891
+ super(`Refusing to remove storage path for safety: expected ` +
892
+ `"${expectedStoragePath}" under the repo's .cgraphx/code subfolder, ` +
893
+ `but the entry has "${actualStoragePath}".`);
894
+ this.entry = entry;
895
+ this.expectedStoragePath = expectedStoragePath;
896
+ this.actualStoragePath = actualStoragePath;
897
+ this.name = 'UnsafeStoragePathError';
898
+ }
899
+ }
900
+ exports.UnsafeStoragePathError = UnsafeStoragePathError;
901
+ /**
902
+ * Guard rail for destructive CLI paths: verify that an entry's `storagePath`
903
+ * is the canonical `<repo>/.cgraphx/code` subfolder of its `path`. If not, throw
904
+ * {@link UnsafeStoragePathError} so the caller exits without touching disk.
905
+ *
906
+ * Pure string check — does NOT require the paths to exist on disk.
907
+ * Windows: case-insensitive; POSIX: case-sensitive.
908
+ */
909
+ const assertSafeStoragePath = (entry) => {
910
+ const expected = path_1.default.join(path_1.default.resolve(entry.path), ...CGRAPHX_CODE_DIR_PARTS);
911
+ const actual = path_1.default.resolve(entry.storagePath);
912
+ const matches = process.platform === 'win32'
913
+ ? expected.toLowerCase() === actual.toLowerCase()
914
+ : expected === actual;
915
+ if (!matches) {
916
+ throw new UnsafeStoragePathError(entry, expected, actual);
917
+ }
918
+ };
919
+ exports.assertSafeStoragePath = assertSafeStoragePath;
920
+ /**
921
+ * Resolve a user-supplied target string (from `gitnexus remove <target>`
922
+ * or equivalent MCP tool argument) to a single registry entry.
923
+ *
924
+ * Match precedence (first hit wins, subsequent tiers are only tried if
925
+ * the prior tier produces zero matches):
926
+ * 1. Exact resolved-path match (Windows: case-insensitive).
927
+ * Paths are unique by registry construction, so a path match can
928
+ * never be ambiguous.
929
+ * 2. Exact `name` match (case-insensitive). If ≥ 2 entries share the
930
+ * name — only possible via `--allow-duplicate-name` (#829) —
931
+ * throws {@link RegistryAmbiguousTargetError}.
932
+ *
933
+ * No fuzzy / partial matching — unambiguous, scriptable behaviour is
934
+ * more important than convenience for destructive commands.
935
+ *
936
+ * Throws {@link RegistryNotFoundError} if no entry matches.
937
+ *
938
+ * `entries` is passed in (rather than re-read) so callers that already
939
+ * hold the registry snapshot (e.g. to print a "before" state) can avoid
940
+ * a second disk read, and so tests can inject fixtures without touching
941
+ * `CGRAPH_HOME`.
942
+ */
943
+ const resolveRegistryEntry = (entries, target) => {
944
+ // Tier 1: path match. Canonicalise BOTH sides so symlink and
945
+ // Windows-8.3 quirks don't cause a false miss — e.g. the caller
946
+ // passes `/var/folders/.../repo` while the registry has
947
+ // `/private/var/folders/.../repo` (both resolve to the same
948
+ // `realpath.native`). See `canonicalizePath` for the rationale.
949
+ //
950
+ // Canonicalising the STORED entry (not just the input) is what gives
951
+ // us backward-compat for registries written by versions that only
952
+ // ran `path.resolve` — both get canonicalised here at compare time.
953
+ const canonicalTarget = (0, exports.canonicalizePath)(target);
954
+ const pathMatch = entries.find((e) => {
955
+ const a = (0, exports.canonicalizePath)(e.path);
956
+ const b = canonicalTarget;
957
+ return (0, exports.registryPathEquals)(a, b);
958
+ });
959
+ if (pathMatch)
960
+ return pathMatch;
961
+ // Tier 2: name match. Case-insensitive on all platforms — registry
962
+ // name collisions are already filtered case-insensitively in
963
+ // `registerRepo`, so "APP" vs "app" are considered the same key.
964
+ const targetLower = target.toLowerCase();
965
+ const nameMatches = entries.filter((e) => e.name.toLowerCase() === targetLower);
966
+ if (nameMatches.length === 1)
967
+ return nameMatches[0];
968
+ if (nameMatches.length > 1) {
969
+ throw new RegistryAmbiguousTargetError(target, nameMatches);
970
+ }
971
+ // Tier 3: miss. Build the available-names hint ONCE; resolveRepo-style
972
+ // disambiguated labels (`app (/path)`) are applied when the same name
973
+ // appears in multiple entries so the user sees the same hint shape as
974
+ // `-r <name>` errors.
975
+ const nameCounts = new Map();
976
+ for (const e of entries) {
977
+ const key = e.name.toLowerCase();
978
+ nameCounts.set(key, (nameCounts.get(key) ?? 0) + 1);
979
+ }
980
+ const availableNames = entries.map((e) => (nameCounts.get(e.name.toLowerCase()) ?? 0) > 1 ? `${e.name} (${e.path})` : e.name);
981
+ throw new RegistryNotFoundError(target, availableNames);
982
+ };
983
+ exports.resolveRegistryEntry = resolveRegistryEntry;
984
+ /**
985
+ * List the indexed repos available to CLI tool operations. With the global
986
+ * registry removed (spec §8), this is cwd-based discovery ({@link readRegistry})
987
+ * returning at most ONE entry — the project root whose `.cgraphx/code/` index is
988
+ * nearest `startCwd` (or the `explicitPath` / `CGRAPH_REPO` override).
989
+ *
990
+ * The legacy `validate` flag is now implicit: discovery reads the index meta,
991
+ * so an absent or unreadable `.cgraphx/code/` naturally yields `[]` (the "no index"
992
+ * path) — there is no separate on-disk validation step to skip.
993
+ */
994
+ const listRegisteredRepos = async (opts) => (0, exports.readRegistry)(opts);
995
+ exports.listRegisteredRepos = listRegisteredRepos;
996
+ /**
997
+ * Get the path to the global CLI config file
998
+ */
999
+ const getGlobalConfigPath = () => {
1000
+ return path_1.default.join((0, exports.getGlobalDir)(), 'config.json');
1001
+ };
1002
+ exports.getGlobalConfigPath = getGlobalConfigPath;
1003
+ /**
1004
+ * Load CLI config from ~/.cgraphx/code/config.json
1005
+ */
1006
+ const loadCLIConfig = async () => {
1007
+ try {
1008
+ const raw = await promises_1.default.readFile((0, exports.getGlobalConfigPath)(), 'utf-8');
1009
+ return JSON.parse(raw);
1010
+ }
1011
+ catch {
1012
+ return {};
1013
+ }
1014
+ };
1015
+ exports.loadCLIConfig = loadCLIConfig;
1016
+ /**
1017
+ * Save CLI config to ~/.cgraphx/code/config.json
1018
+ */
1019
+ const saveCLIConfig = async (config) => {
1020
+ const dir = (0, exports.getGlobalDir)();
1021
+ await promises_1.default.mkdir(dir, { recursive: true });
1022
+ const configPath = (0, exports.getGlobalConfigPath)();
1023
+ await promises_1.default.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
1024
+ // Restrict file permissions on Unix (config may contain API keys)
1025
+ if (process.platform !== 'win32') {
1026
+ try {
1027
+ await promises_1.default.chmod(configPath, 0o600);
1028
+ }
1029
+ catch {
1030
+ /* best-effort */
1031
+ }
1032
+ }
1033
+ };
1034
+ exports.saveCLIConfig = saveCLIConfig;
1035
+ // ─── Sibling-clone detection ─────────────────────────────────────────────
1036
+ //
1037
+ // A "sibling clone" is a different on-disk path that points at the same
1038
+ // logical repository (same `origin` remote URL) as an indexed project root.
1039
+ // With the global registry removed (spec §8), detection is limited to the
1040
+ // one project root discoverable from the caller's context ({@link readRegistry}
1041
+ // → cwd / `--path` / `CGRAPH_REPO`): it can surface a sibling only when the
1042
+ // discovered index's `remoteUrl` matches and its path differs from the
1043
+ // caller's `selfPath`. Cross-clone discovery that walks every registered path
1044
+ // is gone with the registry; the realistic shape this still catches is a
1045
+ // query whose cwd resolves to one clone while the indexed root lives at
1046
+ // another path sharing the same origin.
1047
+ /**
1048
+ * Find a discovered project root whose `remoteUrl` matches the given one,
1049
+ * excluding `selfPath` (case-insensitive on Windows). Entries without a
1050
+ * `remoteUrl` are ignored — we cannot prove sibling-ness without a fingerprint.
1051
+ */
1052
+ const findSiblingClones = async (remoteUrl, selfPath) => {
1053
+ if (!remoteUrl)
1054
+ return [];
1055
+ const entries = await (0, exports.readRegistry)();
1056
+ const isWin = process.platform === 'win32';
1057
+ const norm = (p) => (isWin ? path_1.default.resolve(p).toLowerCase() : path_1.default.resolve(p));
1058
+ const self = norm(selfPath);
1059
+ return entries.filter((e) => e.remoteUrl === remoteUrl && norm(e.path) !== self);
1060
+ };
1061
+ exports.findSiblingClones = findSiblingClones;