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