gitnexus 1.6.6-rc.99 → 1.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -68
- package/dist/_shared/graph/types.d.ts +17 -1
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/index.d.ts +3 -5
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js +2 -4
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/scope-resolution/module-scope-index.d.ts +1 -2
- package/dist/_shared/scope-resolution/module-scope-index.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/module-scope-index.js +1 -2
- package/dist/_shared/scope-resolution/module-scope-index.js.map +1 -1
- package/dist/_shared/scope-resolution/parsed-file.d.ts +24 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts +13 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/registries/context.d.ts +1 -0
- package/dist/_shared/scope-resolution/registries/context.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/registries/context.js +6 -0
- package/dist/_shared/scope-resolution/registries/context.js.map +1 -1
- package/dist/_shared/scope-resolution/registries/evidence.d.ts +2 -3
- package/dist/_shared/scope-resolution/registries/evidence.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/registries/evidence.js +2 -3
- package/dist/_shared/scope-resolution/registries/evidence.js.map +1 -1
- package/dist/_shared/scope-resolution/registries/macro-registry.d.ts +29 -0
- package/dist/_shared/scope-resolution/registries/macro-registry.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/registries/macro-registry.js +32 -0
- package/dist/_shared/scope-resolution/registries/macro-registry.js.map +1 -0
- package/dist/_shared/scope-resolution/symbol-definition.d.ts +9 -0
- package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/types.d.ts +1 -1
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +35 -1
- package/dist/cli/ai-context.js +111 -12
- package/dist/cli/analyze-config.d.ts +92 -0
- package/dist/cli/analyze-config.js +364 -0
- package/dist/cli/analyze.d.ts +17 -1
- package/dist/cli/analyze.js +224 -71
- package/dist/cli/cli-message.d.ts +1 -1
- package/dist/cli/doctor.d.ts +18 -0
- package/dist/cli/doctor.js +32 -0
- package/dist/cli/i18n/en.d.ts +2 -2
- package/dist/cli/i18n/en.js +2 -2
- package/dist/cli/i18n/resources.d.ts +2 -2
- package/dist/cli/i18n/zh-CN.js +2 -2
- package/dist/cli/index.js +4 -2
- package/dist/cli/resolve-invocation.d.ts +21 -0
- package/dist/cli/resolve-invocation.js +68 -0
- package/dist/cli/setup.d.ts +33 -0
- package/dist/cli/setup.js +96 -35
- package/dist/cli/skill-gen.js +2 -2
- package/dist/cli/wiki.js +20 -4
- package/dist/core/embeddings/embedder.d.ts +1 -1
- package/dist/core/embeddings/embedder.js +14 -1
- package/dist/core/embeddings/runtime-support.d.ts +41 -0
- package/dist/core/embeddings/runtime-support.js +65 -0
- package/dist/core/group/extractors/grpc-patterns/proto.js +2 -1
- package/dist/core/group/extractors/http-patterns/java.js +15 -1
- package/dist/core/ingestion/call-processor.d.ts +57 -227
- package/dist/core/ingestion/call-processor.js +172 -2595
- package/dist/core/ingestion/call-routing.d.ts +6 -5
- package/dist/core/ingestion/call-routing.js +6 -6
- package/dist/core/ingestion/call-types.d.ts +0 -75
- package/dist/core/ingestion/class-extractors/configs/c-cpp.js +26 -1
- package/dist/core/ingestion/class-extractors/configs/ruby.js +3 -0
- package/dist/core/ingestion/class-extractors/generic.js +9 -11
- package/dist/core/ingestion/class-types.d.ts +23 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +11 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.js +227 -73
- package/dist/core/ingestion/cobol-processor.d.ts +1 -0
- package/dist/core/ingestion/cobol-processor.js +51 -2
- package/dist/core/ingestion/emit-references.js +8 -2
- package/dist/core/ingestion/export-detection.d.ts +2 -1
- package/dist/core/ingestion/export-detection.js +2 -6
- package/dist/core/ingestion/field-extractors/configs/dart.d.ts +0 -6
- package/dist/core/ingestion/field-extractors/configs/dart.js +62 -44
- package/dist/core/ingestion/field-extractors/configs/go.d.ts +0 -9
- package/dist/core/ingestion/field-extractors/configs/go.js +40 -1
- package/dist/core/ingestion/field-extractors/configs/jvm.js +43 -4
- package/dist/core/ingestion/field-extractors/configs/php.js +1 -2
- package/dist/core/ingestion/field-extractors/configs/swift.d.ts +12 -1
- package/dist/core/ingestion/field-extractors/configs/swift.js +31 -6
- package/dist/core/ingestion/field-extractors/generic.d.ts +6 -0
- package/dist/core/ingestion/field-extractors/generic.js +5 -4
- package/dist/core/ingestion/field-extractors/typescript.js +0 -29
- package/dist/core/ingestion/filesystem-walker.d.ts +0 -9
- package/dist/core/ingestion/filesystem-walker.js +0 -11
- package/dist/core/ingestion/finalize-orchestrator.js +14 -2
- package/dist/core/ingestion/import-resolvers/configs/swift.d.ts +21 -0
- package/dist/core/ingestion/import-resolvers/configs/swift.js +72 -11
- package/dist/core/ingestion/import-resolvers/python.d.ts +1 -1
- package/dist/core/ingestion/import-resolvers/standard.d.ts +2 -2
- package/dist/core/ingestion/import-resolvers/standard.js +6 -5
- package/dist/core/ingestion/import-resolvers/utils.d.ts +2 -5
- package/dist/core/ingestion/import-resolvers/utils.js +1 -9
- package/dist/core/ingestion/language-provider.d.ts +39 -119
- package/dist/core/ingestion/language-provider.js +0 -2
- package/dist/core/ingestion/languages/c/capture-side-channel.d.ts +62 -0
- package/dist/core/ingestion/languages/c/capture-side-channel.js +65 -0
- package/dist/core/ingestion/languages/c/captures.js +41 -23
- package/dist/core/ingestion/languages/c/import-decomposer.d.ts +9 -0
- package/dist/core/ingestion/languages/c/import-decomposer.js +15 -0
- package/dist/core/ingestion/languages/c/import-target.js +52 -9
- package/dist/core/ingestion/languages/c/index.d.ts +2 -1
- package/dist/core/ingestion/languages/c/index.js +2 -1
- package/dist/core/ingestion/languages/c/query.js +15 -0
- package/dist/core/ingestion/languages/c/scope-resolver.js +47 -4
- package/dist/core/ingestion/languages/c/static-linkage.d.ts +8 -0
- package/dist/core/ingestion/languages/c/static-linkage.js +46 -1
- package/dist/core/ingestion/languages/c-cpp.js +16 -7
- package/dist/core/ingestion/languages/cobol/captures.js +25 -2
- package/dist/core/ingestion/languages/cpp/adl.d.ts +88 -4
- package/dist/core/ingestion/languages/cpp/adl.js +380 -160
- package/dist/core/ingestion/languages/cpp/arity-metadata.js +2 -8
- package/dist/core/ingestion/languages/cpp/capture-side-channel.d.ts +65 -0
- package/dist/core/ingestion/languages/cpp/capture-side-channel.js +78 -0
- package/dist/core/ingestion/languages/cpp/captures.js +162 -54
- package/dist/core/ingestion/languages/cpp/file-local-linkage.d.ts +18 -52
- package/dist/core/ingestion/languages/cpp/file-local-linkage.js +49 -1
- package/dist/core/ingestion/languages/cpp/import-decomposer.d.ts +7 -0
- package/dist/core/ingestion/languages/cpp/import-decomposer.js +12 -0
- package/dist/core/ingestion/languages/cpp/index.d.ts +1 -0
- package/dist/core/ingestion/languages/cpp/index.js +1 -0
- package/dist/core/ingestion/languages/cpp/inline-namespaces.d.ts +8 -0
- package/dist/core/ingestion/languages/cpp/inline-namespaces.js +21 -0
- package/dist/core/ingestion/languages/cpp/query.js +21 -0
- package/dist/core/ingestion/languages/cpp/range-bindings.js +20 -5
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +52 -5
- package/dist/core/ingestion/languages/cpp/two-phase-lookup.d.ts +20 -0
- package/dist/core/ingestion/languages/cpp/two-phase-lookup.js +83 -3
- package/dist/core/ingestion/languages/csharp/captures.js +205 -41
- package/dist/core/ingestion/languages/csharp/index.d.ts +3 -4
- package/dist/core/ingestion/languages/csharp/index.js +3 -4
- package/dist/core/ingestion/languages/csharp/interpret.js +17 -3
- package/dist/core/ingestion/languages/csharp/namespace-siblings.d.ts +17 -7
- package/dist/core/ingestion/languages/csharp/namespace-siblings.js +129 -124
- package/dist/core/ingestion/languages/csharp/qualified-type-names.d.ts +14 -0
- package/dist/core/ingestion/languages/csharp/qualified-type-names.js +59 -0
- package/dist/core/ingestion/languages/csharp/query.js +13 -0
- package/dist/core/ingestion/languages/csharp/receiver-binding.js +10 -6
- package/dist/core/ingestion/languages/csharp/scope-resolver.js +8 -1
- package/dist/core/ingestion/languages/csharp.js +0 -5
- package/dist/core/ingestion/languages/dart/arity-metadata.d.ts +25 -0
- package/dist/core/ingestion/languages/dart/arity-metadata.js +35 -0
- package/dist/core/ingestion/languages/dart/arity.d.ts +19 -0
- package/dist/core/ingestion/languages/dart/arity.js +31 -0
- package/dist/core/ingestion/languages/dart/built-ins.d.ts +11 -0
- package/dist/core/ingestion/languages/dart/built-ins.js +34 -0
- package/dist/core/ingestion/languages/dart/cache-stats.d.ts +13 -0
- package/dist/core/ingestion/languages/dart/cache-stats.js +24 -0
- package/dist/core/ingestion/languages/dart/captures.d.ts +29 -0
- package/dist/core/ingestion/languages/dart/captures.js +445 -0
- package/dist/core/ingestion/languages/dart/expand-wildcards.d.ts +13 -0
- package/dist/core/ingestion/languages/dart/expand-wildcards.js +31 -0
- package/dist/core/ingestion/languages/dart/import-target.d.ts +15 -0
- package/dist/core/ingestion/languages/dart/import-target.js +65 -0
- package/dist/core/ingestion/languages/dart/index.d.ts +28 -0
- package/dist/core/ingestion/languages/dart/index.js +28 -0
- package/dist/core/ingestion/languages/dart/interpret.d.ts +24 -0
- package/dist/core/ingestion/languages/dart/interpret.js +95 -0
- package/dist/core/ingestion/languages/dart/merge-bindings.d.ts +10 -0
- package/dist/core/ingestion/languages/dart/merge-bindings.js +39 -0
- package/dist/core/ingestion/languages/dart/query.d.ts +26 -0
- package/dist/core/ingestion/languages/dart/query.js +142 -0
- package/dist/core/ingestion/languages/dart/receiver-binding.d.ts +24 -0
- package/dist/core/ingestion/languages/dart/receiver-binding.js +87 -0
- package/dist/core/ingestion/languages/dart/scope-resolver.d.ts +29 -0
- package/dist/core/ingestion/languages/dart/scope-resolver.js +194 -0
- package/dist/core/ingestion/languages/dart/signature-bindings.d.ts +23 -0
- package/dist/core/ingestion/languages/dart/signature-bindings.js +51 -0
- package/dist/core/ingestion/languages/dart/simple-hooks.d.ts +20 -0
- package/dist/core/ingestion/languages/dart/simple-hooks.js +47 -0
- package/dist/core/ingestion/languages/dart.d.ts +0 -1
- package/dist/core/ingestion/languages/dart.js +15 -29
- package/dist/core/ingestion/languages/go/arity-metadata.d.ts +1 -0
- package/dist/core/ingestion/languages/go/arity-metadata.js +31 -1
- package/dist/core/ingestion/languages/go/captures.js +162 -3
- package/dist/core/ingestion/languages/go/interface-impls.js +476 -50
- package/dist/core/ingestion/languages/go/interpret.js +21 -11
- package/dist/core/ingestion/languages/go/method-owners.js +20 -8
- package/dist/core/ingestion/languages/go/query.js +15 -7
- package/dist/core/ingestion/languages/go/range-binding.js +24 -9
- package/dist/core/ingestion/languages/go/receiver-binding.js +1 -1
- package/dist/core/ingestion/languages/go/scope-resolver.js +2 -2
- package/dist/core/ingestion/languages/go/simple-hooks.js +10 -5
- package/dist/core/ingestion/languages/go/type-binding.d.ts +1 -0
- package/dist/core/ingestion/languages/go/type-binding.js +40 -2
- package/dist/core/ingestion/languages/go.d.ts +0 -1
- package/dist/core/ingestion/languages/go.js +0 -5
- package/dist/core/ingestion/languages/index.d.ts +0 -5
- package/dist/core/ingestion/languages/index.js +0 -3
- package/dist/core/ingestion/languages/java/captures.js +252 -23
- package/dist/core/ingestion/languages/java/interpret.js +12 -6
- package/dist/core/ingestion/languages/java/package-siblings.js +18 -5
- package/dist/core/ingestion/languages/java/query.js +16 -1
- package/dist/core/ingestion/languages/java/scope-resolver.d.ts +2 -8
- package/dist/core/ingestion/languages/java/scope-resolver.js +2 -8
- package/dist/core/ingestion/languages/java.js +0 -5
- package/dist/core/ingestion/languages/javascript/captures.js +185 -11
- package/dist/core/ingestion/languages/javascript/query.js +107 -1
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +57 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +60 -0
- package/dist/core/ingestion/languages/kotlin/captures.js +213 -22
- package/dist/core/ingestion/languages/kotlin/companion-scopes.d.ts +7 -0
- package/dist/core/ingestion/languages/kotlin/companion-scopes.js +10 -0
- package/dist/core/ingestion/languages/kotlin/index.d.ts +1 -0
- package/dist/core/ingestion/languages/kotlin/index.js +1 -0
- package/dist/core/ingestion/languages/kotlin/query.js +30 -0
- package/dist/core/ingestion/languages/kotlin/scope-resolver.d.ts +5 -7
- package/dist/core/ingestion/languages/kotlin/scope-resolver.js +22 -7
- package/dist/core/ingestion/languages/kotlin.js +8 -5
- package/dist/core/ingestion/languages/php/captures.js +135 -19
- package/dist/core/ingestion/languages/php/import-decomposer.js +21 -63
- package/dist/core/ingestion/languages/php/index.d.ts +3 -4
- package/dist/core/ingestion/languages/php/index.js +3 -4
- package/dist/core/ingestion/languages/php/query.js +5 -0
- package/dist/core/ingestion/languages/php/receiver-binding.js +8 -4
- package/dist/core/ingestion/languages/php.js +0 -4
- package/dist/core/ingestion/languages/python/captures.js +128 -13
- package/dist/core/ingestion/languages/python/depends-references.js +1 -1
- package/dist/core/ingestion/languages/python/import-target.d.ts +4 -5
- package/dist/core/ingestion/languages/python/import-target.js +108 -16
- package/dist/core/ingestion/languages/python/index-stats.d.ts +18 -0
- package/dist/core/ingestion/languages/python/index-stats.js +25 -0
- package/dist/core/ingestion/languages/python/index.d.ts +3 -4
- package/dist/core/ingestion/languages/python/index.js +3 -4
- package/dist/core/ingestion/languages/python/query.js +17 -0
- package/dist/core/ingestion/languages/python/scope-resolver.js +7 -6
- package/dist/core/ingestion/languages/python.d.ts +0 -2
- package/dist/core/ingestion/languages/python.js +0 -7
- package/dist/core/ingestion/languages/ruby/captures.js +174 -31
- package/dist/core/ingestion/languages/ruby/import-target.js +2 -1
- package/dist/core/ingestion/languages/ruby/interpret.js +2 -1
- package/dist/core/ingestion/languages/ruby/query.js +10 -0
- package/dist/core/ingestion/languages/ruby/scope-resolver.js +61 -11
- package/dist/core/ingestion/languages/ruby.js +4 -53
- package/dist/core/ingestion/languages/rust/captures.js +95 -13
- package/dist/core/ingestion/languages/rust/query.js +64 -1
- package/dist/core/ingestion/languages/rust/range-binding.js +40 -12
- package/dist/core/ingestion/languages/rust/receiver-binding.js +9 -0
- package/dist/core/ingestion/languages/rust/scope-resolver.js +75 -1
- package/dist/core/ingestion/languages/rust.d.ts +0 -2
- package/dist/core/ingestion/languages/rust.js +0 -6
- package/dist/core/ingestion/languages/swift/arity-metadata.d.ts +24 -0
- package/dist/core/ingestion/languages/swift/arity-metadata.js +41 -0
- package/dist/core/ingestion/languages/swift/arity.d.ts +29 -0
- package/dist/core/ingestion/languages/swift/arity.js +42 -0
- package/dist/core/ingestion/languages/swift/base-type.d.ts +20 -0
- package/dist/core/ingestion/languages/swift/base-type.js +27 -0
- package/dist/core/ingestion/languages/swift/cache-stats.d.ts +15 -0
- package/dist/core/ingestion/languages/swift/cache-stats.js +26 -0
- package/dist/core/ingestion/languages/swift/captures.d.ts +35 -0
- package/dist/core/ingestion/languages/swift/captures.js +495 -0
- package/dist/core/ingestion/languages/swift/implicit-imports.d.ts +34 -0
- package/dist/core/ingestion/languages/swift/implicit-imports.js +57 -0
- package/dist/core/ingestion/languages/swift/import-decomposer.d.ts +24 -0
- package/dist/core/ingestion/languages/swift/import-decomposer.js +84 -0
- package/dist/core/ingestion/languages/swift/import-target.d.ts +33 -0
- package/dist/core/ingestion/languages/swift/import-target.js +81 -0
- package/dist/core/ingestion/languages/swift/index.d.ts +37 -0
- package/dist/core/ingestion/languages/swift/index.js +37 -0
- package/dist/core/ingestion/languages/swift/interpret.d.ts +15 -0
- package/dist/core/ingestion/languages/swift/interpret.js +89 -0
- package/dist/core/ingestion/languages/swift/merge-bindings.d.ts +20 -0
- package/dist/core/ingestion/languages/swift/merge-bindings.js +48 -0
- package/dist/core/ingestion/languages/swift/query.d.ts +46 -0
- package/dist/core/ingestion/languages/swift/query.js +194 -0
- package/dist/core/ingestion/languages/swift/receiver-binding.d.ts +40 -0
- package/dist/core/ingestion/languages/swift/receiver-binding.js +161 -0
- package/dist/core/ingestion/languages/swift/scope-resolver.d.ts +50 -0
- package/dist/core/ingestion/languages/swift/scope-resolver.js +189 -0
- package/dist/core/ingestion/languages/swift/sibling-type-bindings.d.ts +34 -0
- package/dist/core/ingestion/languages/swift/sibling-type-bindings.js +65 -0
- package/dist/core/ingestion/languages/swift/signature-bindings.d.ts +25 -0
- package/dist/core/ingestion/languages/swift/signature-bindings.js +66 -0
- package/dist/core/ingestion/languages/swift/simple-hooks.d.ts +37 -0
- package/dist/core/ingestion/languages/swift/simple-hooks.js +60 -0
- package/dist/core/ingestion/languages/swift/target-grouping.d.ts +51 -0
- package/dist/core/ingestion/languages/swift/target-grouping.js +93 -0
- package/dist/core/ingestion/languages/swift/target-siblings.d.ts +30 -0
- package/dist/core/ingestion/languages/swift/target-siblings.js +71 -0
- package/dist/core/ingestion/languages/swift.d.ts +0 -5
- package/dist/core/ingestion/languages/swift.js +11 -87
- package/dist/core/ingestion/languages/typescript/array-callback.d.ts +3 -29
- package/dist/core/ingestion/languages/typescript/array-callback.js +4 -43
- package/dist/core/ingestion/languages/typescript/captures.js +147 -17
- package/dist/core/ingestion/languages/typescript/index.d.ts +3 -4
- package/dist/core/ingestion/languages/typescript/index.js +3 -4
- package/dist/core/ingestion/languages/typescript/query.d.ts +2 -3
- package/dist/core/ingestion/languages/typescript/query.js +125 -4
- package/dist/core/ingestion/languages/typescript/receiver-binding.js +0 -1
- package/dist/core/ingestion/languages/typescript.d.ts +2 -3
- package/dist/core/ingestion/languages/typescript.js +46 -23
- package/dist/core/ingestion/languages/vue/captures.d.ts +46 -0
- package/dist/core/ingestion/languages/vue/captures.js +67 -0
- package/dist/core/ingestion/languages/vue/import-target.d.ts +27 -0
- package/dist/core/ingestion/languages/vue/import-target.js +58 -0
- package/dist/core/ingestion/languages/vue/index.d.ts +49 -0
- package/dist/core/ingestion/languages/vue/index.js +49 -0
- package/dist/core/ingestion/languages/vue/scope-resolver.d.ts +55 -0
- package/dist/core/ingestion/languages/vue/scope-resolver.js +292 -0
- package/dist/core/ingestion/languages/vue.js +12 -4
- package/dist/core/ingestion/local-symbol-pruner.d.ts +11 -0
- package/dist/core/ingestion/local-symbol-pruner.js +63 -0
- package/dist/core/ingestion/method-extractors/configs/dart.js +14 -1
- package/dist/core/ingestion/method-extractors/configs/jvm.js +37 -20
- package/dist/core/ingestion/method-extractors/configs/php.js +0 -1
- package/dist/core/ingestion/method-extractors/configs/swift.js +11 -4
- package/dist/core/ingestion/method-types.d.ts +2 -2
- package/dist/core/ingestion/model/index.d.ts +0 -3
- package/dist/core/ingestion/model/index.js +0 -8
- package/dist/core/ingestion/model/resolve.d.ts +7 -43
- package/dist/core/ingestion/model/resolve.js +7 -226
- package/dist/core/ingestion/model/scope-resolution-indexes.d.ts +46 -1
- package/dist/core/ingestion/model/semantic-model.d.ts +4 -6
- package/dist/core/ingestion/model/semantic-model.js +1 -1
- package/dist/core/ingestion/model/symbol-table.d.ts +3 -4
- package/dist/core/ingestion/model/symbol-table.js +3 -4
- package/dist/core/ingestion/parsing-processor.d.ts +30 -24
- package/dist/core/ingestion/parsing-processor.js +76 -640
- package/dist/core/ingestion/pipeline-phases/communities.d.ts +1 -1
- package/dist/core/ingestion/pipeline-phases/communities.js +5 -2
- package/dist/core/ingestion/pipeline-phases/cross-file.d.ts +9 -8
- package/dist/core/ingestion/pipeline-phases/cross-file.js +16 -12
- package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
- package/dist/core/ingestion/pipeline-phases/index.js +1 -0
- package/dist/core/ingestion/pipeline-phases/mro.d.ts +1 -1
- package/dist/core/ingestion/pipeline-phases/mro.js +2 -2
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +44 -22
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +426 -565
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +13 -33
- package/dist/core/ingestion/pipeline-phases/parse.js +2 -2
- package/dist/core/ingestion/pipeline-phases/processes.d.ts +1 -1
- package/dist/core/ingestion/pipeline-phases/processes.js +5 -3
- package/dist/core/ingestion/pipeline-phases/prune-local-symbols.d.ts +14 -0
- package/dist/core/ingestion/pipeline-phases/prune-local-symbols.js +26 -0
- package/dist/core/ingestion/pipeline.d.ts +27 -19
- package/dist/core/ingestion/pipeline.js +4 -2
- package/dist/core/ingestion/resolve-references.js +15 -3
- package/dist/core/ingestion/route-extractors/laravel.d.ts +10 -0
- package/dist/core/ingestion/route-extractors/laravel.js +88 -9
- package/dist/core/ingestion/scope-extractor-bridge.d.ts +2 -1
- package/dist/core/ingestion/scope-extractor-bridge.js +2 -2
- package/dist/core/ingestion/scope-extractor.js +13 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +181 -15
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +21 -10
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +10 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +7 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +58 -6
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +24 -5
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +68 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +189 -29
- package/dist/core/ingestion/scope-resolution/passes/imported-return-types.js +21 -1
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +1 -1
- package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +8 -11
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +171 -50
- package/dist/core/ingestion/scope-resolution/pipeline/registry.d.ts +3 -4
- package/dist/core/ingestion/scope-resolution/pipeline/registry.js +9 -4
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +28 -5
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +191 -24
- package/dist/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.js +31 -0
- package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +72 -0
- package/dist/core/ingestion/scope-resolution/scope/walkers.js +440 -39
- package/dist/core/ingestion/scope-resolution/workspace-index.d.ts +18 -2
- package/dist/core/ingestion/scope-resolution/workspace-index.js +94 -7
- package/dist/core/ingestion/tree-sitter-queries.d.ts +14 -14
- package/dist/core/ingestion/tree-sitter-queries.js +380 -158
- package/dist/core/ingestion/ts-js-hoc-utils.d.ts +12 -0
- package/dist/core/ingestion/ts-js-hoc-utils.js +105 -0
- package/dist/core/ingestion/type-env.d.ts +2 -1
- package/dist/core/ingestion/type-env.js +6 -8
- package/dist/core/ingestion/type-extractors/c-cpp.js +8 -10
- package/dist/core/ingestion/type-extractors/csharp.js +18 -34
- package/dist/core/ingestion/type-extractors/go.js +2 -10
- package/dist/core/ingestion/type-extractors/jvm.js +6 -5
- package/dist/core/ingestion/type-extractors/php.js +1 -1
- package/dist/core/ingestion/type-extractors/python.js +1 -1
- package/dist/core/ingestion/type-extractors/ruby.js +2 -2
- package/dist/core/ingestion/type-extractors/rust.js +0 -16
- package/dist/core/ingestion/type-extractors/shared.d.ts +2 -2
- package/dist/core/ingestion/type-extractors/shared.js +25 -11
- package/dist/core/ingestion/type-extractors/swift.js +5 -5
- package/dist/core/ingestion/type-extractors/types.d.ts +1 -1
- package/dist/core/ingestion/type-extractors/typescript.js +1 -1
- package/dist/core/ingestion/utils/ast-helpers.d.ts +119 -1
- package/dist/core/ingestion/utils/ast-helpers.js +260 -13
- package/dist/core/ingestion/utils/callable-labels.d.ts +13 -0
- package/dist/core/ingestion/utils/callable-labels.js +14 -0
- package/dist/core/ingestion/utils/deferred-resolution-profile.d.ts +10 -0
- package/dist/core/ingestion/utils/deferred-resolution-profile.js +30 -0
- package/dist/core/ingestion/utils/heap-probe.d.ts +20 -0
- package/dist/core/ingestion/utils/heap-probe.js +39 -0
- package/dist/core/ingestion/utils/heritage-marker.d.ts +33 -0
- package/dist/core/ingestion/utils/heritage-marker.js +41 -0
- package/dist/core/ingestion/utils/qualified-name.d.ts +37 -0
- package/dist/core/ingestion/utils/qualified-name.js +67 -0
- package/dist/core/ingestion/variable-extractors/configs/c-cpp.js +49 -0
- package/dist/core/ingestion/variable-extractors/configs/dart.js +76 -62
- package/dist/core/ingestion/variable-extractors/configs/go.js +74 -7
- package/dist/core/ingestion/variable-extractors/configs/jvm.js +35 -8
- package/dist/core/ingestion/variable-extractors/generic.js +40 -12
- package/dist/core/ingestion/variable-types.d.ts +9 -0
- package/dist/core/ingestion/vue-sfc-extractor.d.ts +97 -7
- package/dist/core/ingestion/vue-sfc-extractor.js +433 -11
- package/dist/core/ingestion/workers/parse-worker.d.ts +0 -11
- package/dist/core/ingestion/workers/parse-worker.js +358 -187
- package/dist/core/ingestion/workers/worker-pool.d.ts +78 -9
- package/dist/core/ingestion/workers/worker-pool.js +346 -49
- package/dist/core/lbug/csv-generator.js +20 -2
- package/dist/core/lbug/lbug-adapter.js +29 -10
- package/dist/core/lbug/native-check.js +17 -5
- package/dist/core/lbug/pool-adapter.d.ts +0 -19
- package/dist/core/lbug/pool-adapter.js +40 -77
- package/dist/core/lbug/query-result-utils.d.ts +19 -0
- package/dist/core/lbug/query-result-utils.js +28 -0
- package/dist/core/run-analyze.d.ts +9 -2
- package/dist/core/run-analyze.js +24 -3
- package/dist/core/tree-sitter/parser-loader.d.ts +13 -0
- package/dist/core/tree-sitter/parser-loader.js +4 -0
- package/dist/core/tree-sitter/safe-parse.d.ts +70 -3
- package/dist/core/tree-sitter/safe-parse.js +214 -11
- package/dist/core/wiki/generator.js +13 -5
- package/dist/core/wiki/graph-queries.d.ts +3 -0
- package/dist/core/wiki/graph-queries.js +9 -1
- package/dist/core/wiki/llm-client.d.ts +1 -1
- package/dist/core/wiki/llm-client.js +7 -2
- package/dist/core/wiki/local-cli-client.d.ts +2 -1
- package/dist/core/wiki/local-cli-client.js +62 -4
- package/dist/mcp/compatible-stdio-transport.d.ts +3 -0
- package/dist/mcp/compatible-stdio-transport.js +22 -0
- package/dist/mcp/core/embedder.d.ts +1 -1
- package/dist/mcp/core/embedder.js +13 -1
- package/dist/mcp/local/local-backend.d.ts +37 -5
- package/dist/mcp/local/local-backend.js +227 -129
- package/dist/mcp/resources.js +3 -3
- package/dist/mcp/server.js +9 -1
- package/dist/storage/git.d.ts +11 -0
- package/dist/storage/git.js +30 -0
- package/dist/storage/parse-cache.d.ts +23 -1
- package/dist/storage/parse-cache.js +138 -32
- package/dist/storage/parsedfile-store.d.ts +142 -0
- package/dist/storage/parsedfile-store.js +367 -0
- package/dist/storage/repo-manager.d.ts +2 -1
- package/dist/storage/scope-index-store.d.ts +114 -0
- package/dist/storage/scope-index-store.js +236 -0
- package/dist/types/pipeline.d.ts +6 -3
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +2 -1
- package/hooks/claude/gitnexus-hook.cjs +2 -1
- package/hooks/claude/resolve-analyze-cmd.cjs +323 -0
- package/package.json +4 -5
- package/scripts/bench-scope-resolution.ts +1 -3
- package/scripts/cross-platform-tests.ts +4 -1
- package/skills/gitnexus-cli.md +8 -6
- package/skills/gitnexus-debugging.md +15 -15
- package/skills/gitnexus-exploring.md +11 -11
- package/skills/gitnexus-guide.md +1 -1
- package/skills/gitnexus-impact-analysis.md +10 -10
- package/skills/gitnexus-pr-review.md +19 -19
- package/skills/gitnexus-refactoring.md +25 -25
- package/web/assets/{agent-BRX-afm3.js → agent-EkX7webX.js} +156 -131
- package/web/assets/{architectureDiagram-UL44E2DR-B1oYB8-c.js → architectureDiagram-UL44E2DR-BoczH8cv.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-SPC6pgWI.js → chunk-LCXTWHL2-By5HB3b-.js} +1 -1
- package/web/assets/{chunk-RG4AUYOV-DZXr4Yv3.js → chunk-RG4AUYOV-BQE_DkpL.js} +1 -1
- package/web/assets/{classDiagram-KGZ6W3CR-BqpOj8L9.js → classDiagram-KGZ6W3CR-Dj_02GUH.js} +1 -1
- package/web/assets/{classDiagram-v2-72OJOZXJ-FmElywK2.js → classDiagram-v2-72OJOZXJ-D-NArMpf.js} +1 -1
- package/web/assets/{diagram-3NCE3AQN-BWtJXMDq.js → diagram-3NCE3AQN-VXtXDO95.js} +1 -1
- package/web/assets/{diagram-GF46GFSD-Hh-fChxU.js → diagram-GF46GFSD-B1qab2Ah.js} +1 -1
- package/web/assets/{diagram-QXG6HAR7-DYeQHxGU.js → diagram-QXG6HAR7-BSCHGzzT.js} +1 -1
- package/web/assets/{diagram-WEQXMOUZ-DYGU4T0y.js → diagram-WEQXMOUZ-DHtknmNT.js} +1 -1
- package/web/assets/{erDiagram-L5TCEMPS-bN3wlP2A.js → erDiagram-L5TCEMPS-Db-IYTmm.js} +1 -1
- package/web/assets/{flowDiagram-H6V6AXG4-YACVtF3-.js → flowDiagram-H6V6AXG4-BHDoyVoW.js} +1 -1
- package/web/assets/{index-BhnAdWTt.js → index-BR0IhgbR.js} +10 -10
- package/web/assets/{infoDiagram-3YFTVSEB-BWBzD28-.js → infoDiagram-3YFTVSEB-6h8wbWEe.js} +1 -1
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-B8qYT-j9.js → ishikawaDiagram-BNXS4ZKH-Dx2OkPk1.js} +1 -1
- package/web/assets/{kanban-definition-75IXJCU3-BeoPr5Tl.js → kanban-definition-75IXJCU3-CIIEZfqV.js} +1 -1
- package/web/assets/{mindmap-definition-2TDM6QVE-CdLLN_so.js → mindmap-definition-2TDM6QVE-DUAqydRq.js} +1 -1
- package/web/assets/{pieDiagram-CU6KROY3-DEd2a_k_.js → pieDiagram-CU6KROY3-BntYuYZa.js} +1 -1
- package/web/assets/{requirementDiagram-JXO7QTGE-QNeTo5C_.js → requirementDiagram-JXO7QTGE-QCD6I29n.js} +1 -1
- package/web/assets/{sequenceDiagram-VS2MUI6T-BHC7q7yJ.js → sequenceDiagram-VS2MUI6T-DScFwLz2.js} +1 -1
- package/web/assets/{stateDiagram-7D4R322I-KONnc2Px.js → stateDiagram-7D4R322I-AkRAm6Hl.js} +1 -1
- package/web/assets/{stateDiagram-v2-36443NZ5-C2QfuMlu.js → stateDiagram-v2-36443NZ5-BCK1vigR.js} +1 -1
- package/web/assets/{timeline-definition-O6YCAMPW-D4t4NJx1.js → timeline-definition-O6YCAMPW-BvpIVXjX.js} +1 -1
- package/web/assets/{vennDiagram-MWXL3ELB-6bctC9Yg.js → vennDiagram-MWXL3ELB-BYGWk6dK.js} +1 -1
- package/web/assets/{wardleyDiagram-CUQ6CDDI-BPZYNTvC.js → wardleyDiagram-CUQ6CDDI-Dk1z7H2T.js} +1 -1
- package/web/assets/{xychartDiagram-N2JHSOCM-lBI9O6DW.js → xychartDiagram-N2JHSOCM-2N6NCSWN.js} +1 -1
- package/web/index.html +1 -1
- package/dist/_shared/scope-resolution/shadow/aggregate.d.ts +0 -63
- package/dist/_shared/scope-resolution/shadow/aggregate.d.ts.map +0 -1
- package/dist/_shared/scope-resolution/shadow/aggregate.js +0 -122
- package/dist/_shared/scope-resolution/shadow/aggregate.js.map +0 -1
- package/dist/_shared/scope-resolution/shadow/diff.d.ts +0 -59
- package/dist/_shared/scope-resolution/shadow/diff.d.ts.map +0 -1
- package/dist/_shared/scope-resolution/shadow/diff.js +0 -79
- package/dist/_shared/scope-resolution/shadow/diff.js.map +0 -1
- package/dist/core/ingestion/ast-cache.d.ts +0 -26
- package/dist/core/ingestion/ast-cache.js +0 -48
- package/dist/core/ingestion/heritage-extractors/configs/go.d.ts +0 -13
- package/dist/core/ingestion/heritage-extractors/configs/go.js +0 -20
- package/dist/core/ingestion/heritage-extractors/configs/ruby.d.ts +0 -18
- package/dist/core/ingestion/heritage-extractors/configs/ruby.js +0 -65
- package/dist/core/ingestion/heritage-extractors/generic.d.ts +0 -23
- package/dist/core/ingestion/heritage-extractors/generic.js +0 -47
- package/dist/core/ingestion/heritage-processor.d.ts +0 -54
- package/dist/core/ingestion/heritage-processor.js +0 -367
- package/dist/core/ingestion/heritage-types.d.ts +0 -73
- package/dist/core/ingestion/heritage-types.js +0 -2
- package/dist/core/ingestion/import-processor.d.ts +0 -23
- package/dist/core/ingestion/import-processor.js +0 -377
- package/dist/core/ingestion/model/heritage-map.d.ts +0 -105
- package/dist/core/ingestion/model/heritage-map.js +0 -294
- package/dist/core/ingestion/model/resolution-context.d.ts +0 -93
- package/dist/core/ingestion/model/resolution-context.js +0 -337
- package/dist/core/ingestion/named-bindings/csharp.d.ts +0 -3
- package/dist/core/ingestion/named-bindings/csharp.js +0 -37
- package/dist/core/ingestion/named-bindings/java.d.ts +0 -3
- package/dist/core/ingestion/named-bindings/java.js +0 -29
- package/dist/core/ingestion/named-bindings/kotlin.d.ts +0 -3
- package/dist/core/ingestion/named-bindings/kotlin.js +0 -36
- package/dist/core/ingestion/named-bindings/php.d.ts +0 -3
- package/dist/core/ingestion/named-bindings/php.js +0 -61
- package/dist/core/ingestion/named-bindings/python.d.ts +0 -3
- package/dist/core/ingestion/named-bindings/python.js +0 -49
- package/dist/core/ingestion/named-bindings/rust.d.ts +0 -3
- package/dist/core/ingestion/named-bindings/rust.js +0 -66
- package/dist/core/ingestion/named-bindings/types.d.ts +0 -16
- package/dist/core/ingestion/named-bindings/types.js +0 -6
- package/dist/core/ingestion/named-bindings/typescript.d.ts +0 -3
- package/dist/core/ingestion/named-bindings/typescript.js +0 -58
- package/dist/core/ingestion/pipeline-phases/cross-file-impl.d.ts +0 -17
- package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +0 -209
- package/dist/core/ingestion/pipeline-phases/orm-extraction.d.ts +0 -22
- package/dist/core/ingestion/pipeline-phases/orm-extraction.js +0 -92
- package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.d.ts +0 -70
- package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.js +0 -312
- package/dist/core/ingestion/registry-primary-flag.d.ts +0 -89
- package/dist/core/ingestion/registry-primary-flag.js +0 -122
- package/dist/core/ingestion/shadow-harness.d.ts +0 -113
- package/dist/core/ingestion/shadow-harness.js +0 -148
- package/dist/core/ingestion/utils/ruby-self-call.d.ts +0 -52
- package/dist/core/ingestion/utils/ruby-self-call.js +0 -59
- package/scripts/ci-list-migrated-languages.ts +0 -24
- package/scripts/run-parity.ts +0 -128
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import fs from 'fs/promises';
|
|
9
9
|
import path from 'path';
|
|
10
|
+
import { createHash } from 'crypto';
|
|
10
11
|
import { initLbug, executeQuery, executeParameterized, closeLbug, isLbugReady, } from '../../core/lbug/pool-adapter.js';
|
|
11
12
|
import { isValidQueryParams } from '../../core/lbug/query-params.js';
|
|
12
13
|
import { isWalCorruptionError, WAL_RECOVERY_SUGGESTION } from '../../core/lbug/lbug-config.js';
|
|
@@ -142,7 +143,20 @@ function logQueryError(context, err) {
|
|
|
142
143
|
const msg = err instanceof Error ? err.message : String(err);
|
|
143
144
|
logger.error({ context, err: msg }, 'GitNexus query failed');
|
|
144
145
|
}
|
|
145
|
-
const isReadOnlyDbError = (err) =>
|
|
146
|
+
const isReadOnlyDbError = (err) => {
|
|
147
|
+
// Walk the `cause` chain (bounded) so a wrapped read-only error (e.g. the
|
|
148
|
+
// pool adapter's `{ cause }` wrapper) is still detected here — this is the
|
|
149
|
+
// copy the MCP cypher handler uses to surface its curated read-only message
|
|
150
|
+
// (#2068 follow-up). Mirrors lbug-adapter's isReadOnlyDbError.
|
|
151
|
+
let cur = err;
|
|
152
|
+
for (let depth = 0; depth < 5 && cur != null; depth++) {
|
|
153
|
+
const msg = cur instanceof Error ? cur.message : String(cur);
|
|
154
|
+
if (/read-only database/i.test(msg))
|
|
155
|
+
return true;
|
|
156
|
+
cur = cur instanceof Error ? cur.cause : undefined;
|
|
157
|
+
}
|
|
158
|
+
return false;
|
|
159
|
+
};
|
|
146
160
|
/**
|
|
147
161
|
* Per-query latency telemetry for production aggregation (#553).
|
|
148
162
|
*
|
|
@@ -234,9 +248,16 @@ export function resolveWorktreeCwd(repoPath, launchCwd) {
|
|
|
234
248
|
return repoPath;
|
|
235
249
|
}
|
|
236
250
|
/**
|
|
237
|
-
* Length of the
|
|
251
|
+
* Length of the path-derived suffix appended to a colliding repo id.
|
|
238
252
|
* Exported so tests can pin the suffix shape without re-deriving the
|
|
239
|
-
* literal; see `
|
|
253
|
+
* literal; see `assignRepoId()` and the hashed-id resolution tier (#1658).
|
|
254
|
+
*
|
|
255
|
+
* Note: base64url is an *encoding*, not a hash — it preserves byte order, so
|
|
256
|
+
* two paths that share a long common prefix (sibling clones under one parent)
|
|
257
|
+
* collapse to the same sliced suffix. `assignRepoId()` keeps the legacy
|
|
258
|
+
* base64url suffix only for the first colliding duplicate (id compatibility)
|
|
259
|
+
* and falls back to a content hash of the resolved path on a real collision
|
|
260
|
+
* (#2054).
|
|
240
261
|
*/
|
|
241
262
|
export const REPO_ID_HASH_LENGTH = 6;
|
|
242
263
|
export class LocalBackend {
|
|
@@ -296,10 +317,32 @@ export class LocalBackend {
|
|
|
296
317
|
*/
|
|
297
318
|
async refreshRepos() {
|
|
298
319
|
const entries = await listRegisteredRepos({ validate: true });
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
320
|
+
// Build the next map from scratch and swap it in atomically. Mutating the
|
|
321
|
+
// live map in place let stale entries influence fresh id assignment: a
|
|
322
|
+
// bare-name id, once handed to the first registry entry, stuck to it across
|
|
323
|
+
// refreshes and reorders, and colliding path suffixes silently overwrote
|
|
324
|
+
// each other so sibling clones disappeared from `list_repos` (#2054).
|
|
325
|
+
const nextRepos = new Map();
|
|
326
|
+
const nextContext = new Map();
|
|
327
|
+
const assigned = new Map(); // id -> resolved repo path
|
|
328
|
+
// Assign ids over a path-sorted view so a registered clone always gets the
|
|
329
|
+
// same id regardless of the registry's on-disk order: the bare name and
|
|
330
|
+
// each path-derived suffix become a pure function of the resolved-path set,
|
|
331
|
+
// not of iteration order, so a memorized id can't drift to a different
|
|
332
|
+
// clone after a registry reorder (#2067 follow-up).
|
|
333
|
+
const ordered = [...entries].sort((a, b) => {
|
|
334
|
+
const ra = path.resolve(a.path);
|
|
335
|
+
const rb = path.resolve(b.path);
|
|
336
|
+
return ra < rb ? -1 : ra > rb ? 1 : 0;
|
|
337
|
+
});
|
|
338
|
+
for (const entry of ordered) {
|
|
339
|
+
// path.resolve (not canonicalizePath) matches the pre-#2054 collision
|
|
340
|
+
// check and keeps refreshRepos free of mockable deps on the hot init
|
|
341
|
+
// path. registerRepo writes path.resolve'd paths (not realpath), and
|
|
342
|
+
// resolveRepoFromCache canonicalizes both sides when matching by path, so
|
|
343
|
+
// keying id assignment on path.resolve here is consistent and correct.
|
|
344
|
+
const resolved = path.resolve(entry.path);
|
|
345
|
+
const id = this.assignRepoId(entry.name, entry.path, resolved, assigned);
|
|
303
346
|
const storagePath = entry.storagePath;
|
|
304
347
|
const lbugPath = path.join(storagePath, 'lbug');
|
|
305
348
|
// Clean up any leftover KuzuDB files from before the LadybugDB migration.
|
|
@@ -319,10 +362,10 @@ export class LocalBackend {
|
|
|
319
362
|
remoteUrl: entry.remoteUrl,
|
|
320
363
|
stats: entry.stats,
|
|
321
364
|
};
|
|
322
|
-
|
|
365
|
+
nextRepos.set(id, handle);
|
|
323
366
|
// Build lightweight context (no LadybugDB needed)
|
|
324
367
|
const s = entry.stats || {};
|
|
325
|
-
|
|
368
|
+
nextContext.set(id, {
|
|
326
369
|
projectName: entry.name,
|
|
327
370
|
stats: {
|
|
328
371
|
fileCount: s.files || 0,
|
|
@@ -332,36 +375,78 @@ export class LocalBackend {
|
|
|
332
375
|
},
|
|
333
376
|
});
|
|
334
377
|
}
|
|
335
|
-
// Prune
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
378
|
+
// Prune per-clone pool state for databases that are no longer registered.
|
|
379
|
+
// The LadybugDB pool and the init/staleness/reinit maps are keyed by the
|
|
380
|
+
// immutable lbugPath (see ensureInitialized), so a repo id that merely
|
|
381
|
+
// moves to a different clone needs NO eviction — distinct clones have
|
|
382
|
+
// distinct lbugPaths and can never share a pool entry, which is what closes
|
|
383
|
+
// the resolve→query wrong-clone window for good (#2067). Only a path that
|
|
384
|
+
// dropped out of the registry must release its pooled connection + state.
|
|
385
|
+
const liveLbugPaths = new Set([...nextRepos.values()].map((h) => h.lbugPath));
|
|
386
|
+
for (const prev of this.repos.values()) {
|
|
387
|
+
if (liveLbugPaths.has(prev.lbugPath))
|
|
388
|
+
continue;
|
|
389
|
+
this.initializedRepos.delete(prev.lbugPath);
|
|
390
|
+
this.lastStalenessCheck.delete(prev.lbugPath);
|
|
391
|
+
this.reinitPromises.delete(prev.lbugPath);
|
|
392
|
+
closeLbug(prev.lbugPath).catch(() => { });
|
|
342
393
|
}
|
|
394
|
+
this.repos = nextRepos;
|
|
395
|
+
this.contextCache = nextContext;
|
|
343
396
|
}
|
|
344
397
|
/**
|
|
345
|
-
*
|
|
346
|
-
*
|
|
398
|
+
* Assign a collision-free in-memory id for a registered repo.
|
|
399
|
+
*
|
|
400
|
+
* - Unique name → the bare lowercased name.
|
|
401
|
+
* - Duplicate name → a path-derived suffix. The *first* colliding clone keeps
|
|
402
|
+
* the legacy `base64url(path)` suffix so ids generated before #2054 still
|
|
403
|
+
* resolve (the #1658 hashed-id tier). base64url is an encoding, not a hash:
|
|
404
|
+
* it preserves byte order, so sibling clones under one parent (e.g.
|
|
405
|
+
* `.../REPO_2` and `.../REPO_3`) yield identical leading characters and thus
|
|
406
|
+
* the same sliced suffix. Any further collision therefore falls back to a
|
|
407
|
+
* content hash of the *resolved* path (order-insensitive), extended
|
|
408
|
+
* deterministically until unique.
|
|
409
|
+
*
|
|
410
|
+
* `assigned` maps every id handed out in this refresh to its resolved path,
|
|
411
|
+
* so a candidate is "free" when it is unused or already owned by this exact
|
|
412
|
+
* path. This method records its own assignment into `assigned` before
|
|
413
|
+
* returning, so the map-update is the function's invariant, not a caller
|
|
414
|
+
* obligation. A returned id never overwrites a different path's handle (#2054).
|
|
347
415
|
*/
|
|
348
|
-
|
|
416
|
+
assignRepoId(name, repoPath, resolved, assigned) {
|
|
349
417
|
const base = name.toLowerCase();
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
418
|
+
const free = (id) => {
|
|
419
|
+
const owner = assigned.get(id);
|
|
420
|
+
return owner === undefined || owner === resolved;
|
|
421
|
+
};
|
|
422
|
+
// Record the assignment so subsequent entries in the same refresh see this
|
|
423
|
+
// id as taken (the function owns its own invariant).
|
|
424
|
+
const claim = (id) => {
|
|
425
|
+
assigned.set(id, resolved);
|
|
426
|
+
return id;
|
|
427
|
+
};
|
|
428
|
+
if (free(base))
|
|
429
|
+
return claim(base);
|
|
430
|
+
// Legacy suffix from the *raw* path — kept byte-for-byte so the first
|
|
431
|
+
// colliding duplicate keeps the id it had before #2054 (#1658 tier).
|
|
432
|
+
const legacy = `${base}-${Buffer.from(repoPath)
|
|
433
|
+
.toString('base64url')
|
|
434
|
+
.slice(0, REPO_ID_HASH_LENGTH)
|
|
435
|
+
.toLowerCase()}`;
|
|
436
|
+
if (free(legacy))
|
|
437
|
+
return claim(legacy);
|
|
438
|
+
// Real collision — hash the resolved path. Lowercase hex survives the
|
|
439
|
+
// `paramLower` lookup in resolveRepoFromCache.
|
|
440
|
+
const digest = createHash('sha256').update(resolved).digest('hex');
|
|
441
|
+
for (let len = REPO_ID_HASH_LENGTH; len <= digest.length; len++) {
|
|
442
|
+
const candidate = `${base}-${digest.slice(0, len)}`;
|
|
443
|
+
if (free(candidate))
|
|
444
|
+
return claim(candidate);
|
|
445
|
+
}
|
|
446
|
+
// Two distinct resolved paths sharing a full SHA-256 digest is a hash
|
|
447
|
+
// break, not a runtime condition — fail loudly rather than silently
|
|
448
|
+
// overwrite a different repo's handle (#2054 invariant).
|
|
449
|
+
throw new Error(`GitNexus internal: unable to assign a unique repo id for "${name}" at ${repoPath}`);
|
|
365
450
|
}
|
|
366
451
|
// ─── Repo Resolution ─────────────────────────────────────────────
|
|
367
452
|
/**
|
|
@@ -521,44 +606,52 @@ export class LocalBackend {
|
|
|
521
606
|
};
|
|
522
607
|
}
|
|
523
608
|
// ─── Lazy LadybugDB Init ────────────────────────────────────────────
|
|
524
|
-
|
|
609
|
+
/**
|
|
610
|
+
* Ensure the LadybugDB pool is open for the *resolved* repo.
|
|
611
|
+
*
|
|
612
|
+
* Takes the `RepoHandle` the caller resolved — NOT a bare id — and keys the
|
|
613
|
+
* pool (and the init/staleness/reinit maps) by the immutable `lbugPath`. Two
|
|
614
|
+
* things matter for multi-clone correctness: (1) the handle is the one the
|
|
615
|
+
* caller resolved, so a concurrent `refreshRepos` can't substitute a different
|
|
616
|
+
* clone; (2) the pool key is the database path, so distinct clones never share
|
|
617
|
+
* a pool entry even when their name-derived id transiently collides (#2067).
|
|
618
|
+
*/
|
|
619
|
+
async ensureInitialized(repo) {
|
|
620
|
+
const poolKey = repo.lbugPath;
|
|
525
621
|
// If a reinit is already in progress for this repo, wait for it
|
|
526
|
-
const pending = this.reinitPromises.get(
|
|
622
|
+
const pending = this.reinitPromises.get(poolKey);
|
|
527
623
|
if (pending)
|
|
528
624
|
return pending;
|
|
529
|
-
const handle = this.repos.get(repoId);
|
|
530
|
-
if (!handle)
|
|
531
|
-
throw new Error(`Unknown repo: ${repoId}`);
|
|
532
625
|
// Check if the index was rebuilt since we opened the connection (#297).
|
|
533
626
|
// Throttle staleness checks to at most once per 5 seconds per repo to
|
|
534
627
|
// avoid an fs.readFile round-trip on every tool invocation.
|
|
535
|
-
if (this.initializedRepos.has(
|
|
628
|
+
if (this.initializedRepos.has(poolKey) && isLbugReady(poolKey)) {
|
|
536
629
|
const now = Date.now();
|
|
537
|
-
const lastCheck = this.lastStalenessCheck.get(
|
|
630
|
+
const lastCheck = this.lastStalenessCheck.get(poolKey) ?? 0;
|
|
538
631
|
if (now - lastCheck < 5000)
|
|
539
632
|
return; // Checked recently — skip
|
|
540
|
-
this.lastStalenessCheck.set(
|
|
633
|
+
this.lastStalenessCheck.set(poolKey, now);
|
|
541
634
|
try {
|
|
542
|
-
const metaPath = path.join(
|
|
635
|
+
const metaPath = path.join(repo.storagePath, 'meta.json');
|
|
543
636
|
const metaRaw = await fs.readFile(metaPath, 'utf-8');
|
|
544
637
|
const meta = JSON.parse(metaRaw);
|
|
545
|
-
if (meta.indexedAt && meta.indexedAt !==
|
|
638
|
+
if (meta.indexedAt && meta.indexedAt !== repo.indexedAt) {
|
|
546
639
|
// Index was rebuilt — close stale connection and re-init.
|
|
547
640
|
// Wrap in reinitPromises to prevent TOCTOU race where concurrent
|
|
548
641
|
// callers both detect staleness and double-close the pool.
|
|
549
642
|
const reinit = (async () => {
|
|
550
643
|
try {
|
|
551
|
-
await closeLbug(
|
|
552
|
-
this.initializedRepos.delete(
|
|
553
|
-
|
|
554
|
-
await initLbug(
|
|
555
|
-
this.initializedRepos.add(
|
|
644
|
+
await closeLbug(poolKey);
|
|
645
|
+
this.initializedRepos.delete(poolKey);
|
|
646
|
+
repo.indexedAt = meta.indexedAt;
|
|
647
|
+
await initLbug(poolKey, repo.lbugPath);
|
|
648
|
+
this.initializedRepos.add(poolKey);
|
|
556
649
|
}
|
|
557
650
|
finally {
|
|
558
|
-
this.reinitPromises.delete(
|
|
651
|
+
this.reinitPromises.delete(poolKey);
|
|
559
652
|
}
|
|
560
653
|
})();
|
|
561
|
-
this.reinitPromises.set(
|
|
654
|
+
this.reinitPromises.set(poolKey, reinit);
|
|
562
655
|
return reinit;
|
|
563
656
|
}
|
|
564
657
|
else {
|
|
@@ -570,12 +663,12 @@ export class LocalBackend {
|
|
|
570
663
|
}
|
|
571
664
|
}
|
|
572
665
|
try {
|
|
573
|
-
await initLbug(
|
|
574
|
-
this.initializedRepos.add(
|
|
666
|
+
await initLbug(poolKey, repo.lbugPath);
|
|
667
|
+
this.initializedRepos.add(poolKey);
|
|
575
668
|
}
|
|
576
669
|
catch (err) {
|
|
577
670
|
// If lock error, mark as not initialized so next call retries
|
|
578
|
-
this.initializedRepos.delete(
|
|
671
|
+
this.initializedRepos.delete(poolKey);
|
|
579
672
|
throw err;
|
|
580
673
|
}
|
|
581
674
|
}
|
|
@@ -771,7 +864,7 @@ export class LocalBackend {
|
|
|
771
864
|
if (!params.query?.trim()) {
|
|
772
865
|
return { error: 'query parameter is required and cannot be empty.' };
|
|
773
866
|
}
|
|
774
|
-
await this.ensureInitialized(repo
|
|
867
|
+
await this.ensureInitialized(repo);
|
|
775
868
|
const processLimit = params.limit || 5;
|
|
776
869
|
const maxSymbolsPerProcess = params.max_symbols || 10;
|
|
777
870
|
const includeContent = params.include_content ?? false;
|
|
@@ -846,7 +939,7 @@ export class LocalBackend {
|
|
|
846
939
|
// Find processes this symbol participates in
|
|
847
940
|
let processRows = [];
|
|
848
941
|
try {
|
|
849
|
-
processRows = await executeParameterized(repo.
|
|
942
|
+
processRows = await executeParameterized(repo.lbugPath, `
|
|
850
943
|
MATCH (n {id: $nodeId})-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
|
|
851
944
|
RETURN p.id AS pid, p.label AS label, p.heuristicLabel AS heuristicLabel, p.processType AS processType, p.stepCount AS stepCount, r.step AS step
|
|
852
945
|
`, { nodeId: sym.nodeId });
|
|
@@ -858,7 +951,7 @@ export class LocalBackend {
|
|
|
858
951
|
let cohesion = 0;
|
|
859
952
|
let module;
|
|
860
953
|
try {
|
|
861
|
-
const cohesionRows = await executeParameterized(repo.
|
|
954
|
+
const cohesionRows = await executeParameterized(repo.lbugPath, `
|
|
862
955
|
MATCH (n {id: $nodeId})-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
|
|
863
956
|
RETURN c.cohesion AS cohesion, c.heuristicLabel AS module
|
|
864
957
|
LIMIT 1
|
|
@@ -875,7 +968,7 @@ export class LocalBackend {
|
|
|
875
968
|
let content;
|
|
876
969
|
if (includeContent) {
|
|
877
970
|
try {
|
|
878
|
-
const contentRows = await executeParameterized(repo.
|
|
971
|
+
const contentRows = await executeParameterized(repo.lbugPath, `
|
|
879
972
|
MATCH (n {id: $nodeId})
|
|
880
973
|
RETURN n.content AS content
|
|
881
974
|
`, { nodeId: sym.nodeId });
|
|
@@ -998,7 +1091,7 @@ export class LocalBackend {
|
|
|
998
1091
|
}
|
|
999
1092
|
let ftsResponse;
|
|
1000
1093
|
try {
|
|
1001
|
-
ftsResponse = await searchFTSFromLbug(query, limit, repo.
|
|
1094
|
+
ftsResponse = await searchFTSFromLbug(query, limit, repo.lbugPath);
|
|
1002
1095
|
}
|
|
1003
1096
|
catch (err) {
|
|
1004
1097
|
logger.error({ err: err.message }, 'GitNexus: BM25/FTS search failed (FTS indexes may not exist) -');
|
|
@@ -1017,12 +1110,12 @@ export class LocalBackend {
|
|
|
1017
1110
|
// the nodes that actually scored highest in the BM25 index.
|
|
1018
1111
|
const nodeIds = bm25Result.nodeIds?.length ? bm25Result.nodeIds : null;
|
|
1019
1112
|
const symbols = nodeIds
|
|
1020
|
-
? await executeParameterized(repo.
|
|
1113
|
+
? await executeParameterized(repo.lbugPath, `
|
|
1021
1114
|
MATCH (n)
|
|
1022
1115
|
WHERE n.id IN $nodeIds
|
|
1023
1116
|
RETURN n.id AS id, n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine
|
|
1024
1117
|
`, { nodeIds })
|
|
1025
|
-
: await executeParameterized(repo.
|
|
1118
|
+
: await executeParameterized(repo.lbugPath, `
|
|
1026
1119
|
MATCH (n)
|
|
1027
1120
|
WHERE n.filePath = $filePath
|
|
1028
1121
|
RETURN n.id AS id, n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine
|
|
@@ -1069,7 +1162,7 @@ export class LocalBackend {
|
|
|
1069
1162
|
async semanticSearch(repo, query, limit) {
|
|
1070
1163
|
try {
|
|
1071
1164
|
// Check if embedding table exists before loading the model (avoids heavy model init when embeddings are off)
|
|
1072
|
-
const tableCheck = await executeQuery(repo.
|
|
1165
|
+
const tableCheck = await executeQuery(repo.lbugPath, `MATCH (e:${EMBEDDING_TABLE_NAME}) RETURN COUNT(*) AS cnt LIMIT 1`);
|
|
1073
1166
|
if (!tableCheck.length || (tableCheck[0].cnt ?? tableCheck[0][0]) === 0)
|
|
1074
1167
|
return [];
|
|
1075
1168
|
const { embedQuery, getEmbeddingDims } = await import('../core/embedder.js');
|
|
@@ -1090,7 +1183,7 @@ export class LocalBackend {
|
|
|
1090
1183
|
emb.startLine AS startLine, emb.endLine AS endLine, distance
|
|
1091
1184
|
ORDER BY distance
|
|
1092
1185
|
`;
|
|
1093
|
-
const embResults = await executeQuery(repo.
|
|
1186
|
+
const embResults = await executeQuery(repo.lbugPath, vectorQuery);
|
|
1094
1187
|
return embResults.map((row) => ({
|
|
1095
1188
|
nodeId: row.nodeId ?? row[0],
|
|
1096
1189
|
chunkIndex: row.chunkIndex ?? row[1] ?? 0,
|
|
@@ -1117,7 +1210,7 @@ export class LocalBackend {
|
|
|
1117
1210
|
const exactLimit = getExactScanLimit();
|
|
1118
1211
|
if (embeddingCount > exactLimit)
|
|
1119
1212
|
return [];
|
|
1120
|
-
const rows = await executeQuery(repo.
|
|
1213
|
+
const rows = await executeQuery(repo.lbugPath, `
|
|
1121
1214
|
MATCH (e:${EMBEDDING_TABLE_NAME})
|
|
1122
1215
|
RETURN e.nodeId AS nodeId, e.chunkIndex AS chunkIndex,
|
|
1123
1216
|
e.startLine AS startLine, e.endLine AS endLine, e.embedding AS embedding
|
|
@@ -1152,7 +1245,7 @@ export class LocalBackend {
|
|
|
1152
1245
|
const nodeQuery = label === 'File'
|
|
1153
1246
|
? `MATCH (n:File {id: $nodeId}) RETURN n.name AS name, n.filePath AS filePath`
|
|
1154
1247
|
: `MATCH (n:\`${label}\` {id: $nodeId}) RETURN n.name AS name, n.filePath AS filePath`;
|
|
1155
|
-
const nodeRows = await executeParameterized(repo.
|
|
1248
|
+
const nodeRows = await executeParameterized(repo.lbugPath, nodeQuery, { nodeId });
|
|
1156
1249
|
if (nodeRows.length > 0) {
|
|
1157
1250
|
const nodeRow = nodeRows[0];
|
|
1158
1251
|
results.push({
|
|
@@ -1180,8 +1273,8 @@ export class LocalBackend {
|
|
|
1180
1273
|
return this.cypher(repo, { query, params });
|
|
1181
1274
|
}
|
|
1182
1275
|
async cypher(repo, request) {
|
|
1183
|
-
await this.ensureInitialized(repo
|
|
1184
|
-
if (!isLbugReady(repo.
|
|
1276
|
+
await this.ensureInitialized(repo);
|
|
1277
|
+
if (!isLbugReady(repo.lbugPath)) {
|
|
1185
1278
|
return { error: 'LadybugDB not ready. Index may be corrupted.' };
|
|
1186
1279
|
}
|
|
1187
1280
|
if (request.params !== undefined && !isValidQueryParams(request.params)) {
|
|
@@ -1190,7 +1283,7 @@ export class LocalBackend {
|
|
|
1190
1283
|
};
|
|
1191
1284
|
}
|
|
1192
1285
|
try {
|
|
1193
|
-
const result = await executeParameterized(repo.
|
|
1286
|
+
const result = await executeParameterized(repo.lbugPath, request.query, request.params ?? {});
|
|
1194
1287
|
return result;
|
|
1195
1288
|
}
|
|
1196
1289
|
catch (err) {
|
|
@@ -1283,7 +1376,7 @@ export class LocalBackend {
|
|
|
1283
1376
|
.sort((a, b) => b.symbolCount - a.symbolCount);
|
|
1284
1377
|
}
|
|
1285
1378
|
async overview(repo, params) {
|
|
1286
|
-
await this.ensureInitialized(repo
|
|
1379
|
+
await this.ensureInitialized(repo);
|
|
1287
1380
|
const limit = params.limit || 20;
|
|
1288
1381
|
const result = {
|
|
1289
1382
|
repo: repo.name,
|
|
@@ -1296,7 +1389,7 @@ export class LocalBackend {
|
|
|
1296
1389
|
try {
|
|
1297
1390
|
// Fetch more raw communities than the display limit so aggregation has enough data
|
|
1298
1391
|
const rawLimit = Math.max(limit * 5, 200);
|
|
1299
|
-
const clusters = await executeQuery(repo.
|
|
1392
|
+
const clusters = await executeQuery(repo.lbugPath, `
|
|
1300
1393
|
MATCH (c:Community)
|
|
1301
1394
|
RETURN c.id AS id, c.label AS label, c.heuristicLabel AS heuristicLabel, c.cohesion AS cohesion, c.symbolCount AS symbolCount
|
|
1302
1395
|
ORDER BY c.symbolCount DESC
|
|
@@ -1317,7 +1410,7 @@ export class LocalBackend {
|
|
|
1317
1410
|
}
|
|
1318
1411
|
if (params.showProcesses !== false) {
|
|
1319
1412
|
try {
|
|
1320
|
-
const processes = await executeQuery(repo.
|
|
1413
|
+
const processes = await executeQuery(repo.lbugPath, `
|
|
1321
1414
|
MATCH (p:Process)
|
|
1322
1415
|
RETURN p.id AS id, p.label AS label, p.heuristicLabel AS heuristicLabel, p.processType AS processType, p.stepCount AS stepCount
|
|
1323
1416
|
ORDER BY p.stepCount DESC
|
|
@@ -1355,7 +1448,7 @@ export class LocalBackend {
|
|
|
1355
1448
|
if (ids.length === 0)
|
|
1356
1449
|
return;
|
|
1357
1450
|
try {
|
|
1358
|
-
const rows = await executeParameterized(repo.
|
|
1451
|
+
const rows = await executeParameterized(repo.lbugPath, `
|
|
1359
1452
|
MATCH (n:\`Class\`) WHERE n.id IN $ids RETURN n.id AS id, 'Class' AS label
|
|
1360
1453
|
UNION ALL
|
|
1361
1454
|
MATCH (n:\`Interface\`) WHERE n.id IN $ids RETURN n.id AS id, 'Interface' AS label
|
|
@@ -1440,7 +1533,7 @@ export class LocalBackend {
|
|
|
1440
1533
|
const selectClause = `n.id AS id, n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine${include_content ? ', n.content AS content' : ''}`;
|
|
1441
1534
|
// Direct UID — zero-ambiguity path.
|
|
1442
1535
|
if (uid) {
|
|
1443
|
-
const rows = await executeParameterized(repo.
|
|
1536
|
+
const rows = await executeParameterized(repo.lbugPath, `MATCH (n {id: $uid}) RETURN ${selectClause} LIMIT 1`, { uid });
|
|
1444
1537
|
if (rows.length === 0)
|
|
1445
1538
|
return { kind: 'not_found' };
|
|
1446
1539
|
const r = rows[0];
|
|
@@ -1476,7 +1569,7 @@ export class LocalBackend {
|
|
|
1476
1569
|
}
|
|
1477
1570
|
// LIMIT 20 (was 10) — scoring is the point now, so give the ranker
|
|
1478
1571
|
// headroom instead of arbitrary truncation.
|
|
1479
|
-
const rows = await executeParameterized(repo.
|
|
1572
|
+
const rows = await executeParameterized(repo.lbugPath, `MATCH (n) ${whereClause} RETURN ${selectClause} LIMIT 20`, queryParams);
|
|
1480
1573
|
if (rows.length === 0)
|
|
1481
1574
|
return { kind: 'not_found' };
|
|
1482
1575
|
// Normalise row shape across object / tuple returns from LadybugDB.
|
|
@@ -1509,7 +1602,7 @@ export class LocalBackend {
|
|
|
1509
1602
|
if (ambiguousType) {
|
|
1510
1603
|
const candidateIds = normalized.map((s) => s.id).filter(Boolean);
|
|
1511
1604
|
for (const label of ['Class', 'Interface']) {
|
|
1512
|
-
const labelRows = await executeParameterized(repo.
|
|
1605
|
+
const labelRows = await executeParameterized(repo.lbugPath, `MATCH (n:\`${label}\`) WHERE n.id IN $candidateIds RETURN n.id AS id LIMIT 1`, { candidateIds }).catch(() => []);
|
|
1513
1606
|
if (labelRows.length > 0) {
|
|
1514
1607
|
const preferredId = labelRows[0].id ?? labelRows[0][0];
|
|
1515
1608
|
const preferred = normalized.find((s) => s.id === preferredId);
|
|
@@ -1588,7 +1681,7 @@ export class LocalBackend {
|
|
|
1588
1681
|
}
|
|
1589
1682
|
}
|
|
1590
1683
|
async _contextImpl(repo, params) {
|
|
1591
|
-
await this.ensureInitialized(repo
|
|
1684
|
+
await this.ensureInitialized(repo);
|
|
1592
1685
|
const { name, uid, file_path, kind, include_content } = params;
|
|
1593
1686
|
if (!name && !uid) {
|
|
1594
1687
|
return { error: 'Either "name" or "uid" parameter is required.' };
|
|
@@ -1616,7 +1709,7 @@ export class LocalBackend {
|
|
|
1616
1709
|
const resolvedLabel = outcome.resolvedLabel;
|
|
1617
1710
|
const symId = sym.id;
|
|
1618
1711
|
// Categorized incoming refs
|
|
1619
|
-
const incomingRows = await executeParameterized(repo.
|
|
1712
|
+
const incomingRows = await executeParameterized(repo.lbugPath, `
|
|
1620
1713
|
MATCH (caller)-[r:CodeRelation]->(n {id: $symId})
|
|
1621
1714
|
WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'USES', 'HAS_METHOD', 'HAS_PROPERTY', 'METHOD_OVERRIDES', 'OVERRIDES', 'METHOD_IMPLEMENTS', 'ACCESSES']
|
|
1622
1715
|
RETURN r.type AS relType, caller.id AS uid, caller.name AS name, caller.filePath AS filePath, labels(caller)[0] AS kind
|
|
@@ -1636,7 +1729,7 @@ export class LocalBackend {
|
|
|
1636
1729
|
if (!isClassLike && symRawType === '') {
|
|
1637
1730
|
try {
|
|
1638
1731
|
// Single UNION query instead of two serial round-trips.
|
|
1639
|
-
const typeCheck = await executeParameterized(repo.
|
|
1732
|
+
const typeCheck = await executeParameterized(repo.lbugPath, `
|
|
1640
1733
|
MATCH (n:Class) WHERE n.id = $symId RETURN 'Class' AS label LIMIT 1
|
|
1641
1734
|
UNION ALL
|
|
1642
1735
|
MATCH (n:Interface) WHERE n.id = $symId RETURN 'Interface' AS label LIMIT 1
|
|
@@ -1654,7 +1747,7 @@ export class LocalBackend {
|
|
|
1654
1747
|
try {
|
|
1655
1748
|
// Run incoming-ref queries in parallel — they are independent.
|
|
1656
1749
|
const [ctorIncoming, fileIncoming, typedPropertyIncoming, typedProperties] = await Promise.all([
|
|
1657
|
-
executeParameterized(repo.
|
|
1750
|
+
executeParameterized(repo.lbugPath, `
|
|
1658
1751
|
MATCH (n)-[hm:CodeRelation]->(ctor:Constructor)
|
|
1659
1752
|
WHERE n.id = $symId AND hm.type = 'HAS_METHOD'
|
|
1660
1753
|
MATCH (caller)-[r:CodeRelation]->(ctor)
|
|
@@ -1662,7 +1755,7 @@ export class LocalBackend {
|
|
|
1662
1755
|
RETURN r.type AS relType, caller.id AS uid, caller.name AS name, caller.filePath AS filePath, labels(caller)[0] AS kind
|
|
1663
1756
|
LIMIT 30
|
|
1664
1757
|
`, { symId }),
|
|
1665
|
-
executeParameterized(repo.
|
|
1758
|
+
executeParameterized(repo.lbugPath, `
|
|
1666
1759
|
MATCH (f:File)-[rel:CodeRelation]->(n)
|
|
1667
1760
|
WHERE n.id = $symId AND rel.type = 'DEFINES'
|
|
1668
1761
|
MATCH (caller)-[r:CodeRelation]->(f)
|
|
@@ -1670,7 +1763,7 @@ export class LocalBackend {
|
|
|
1670
1763
|
RETURN r.type AS relType, caller.id AS uid, caller.name AS name, caller.filePath AS filePath, labels(caller)[0] AS kind
|
|
1671
1764
|
LIMIT 30
|
|
1672
1765
|
`, { symId }),
|
|
1673
|
-
executeParameterized(repo.
|
|
1766
|
+
executeParameterized(repo.lbugPath, `
|
|
1674
1767
|
MATCH (p:\`Property\`)
|
|
1675
1768
|
WHERE p.declaredType = $name
|
|
1676
1769
|
OR p.declaredType STARTS WITH $genericPrefix
|
|
@@ -1684,7 +1777,7 @@ export class LocalBackend {
|
|
|
1684
1777
|
genericPrefix: `${sym.name}<`,
|
|
1685
1778
|
genericArg: `<${sym.name}>`,
|
|
1686
1779
|
}),
|
|
1687
|
-
executeParameterized(repo.
|
|
1780
|
+
executeParameterized(repo.lbugPath, `
|
|
1688
1781
|
MATCH (p:\`Property\`)
|
|
1689
1782
|
WHERE p.declaredType = $name
|
|
1690
1783
|
OR p.declaredType STARTS WITH $genericPrefix
|
|
@@ -1716,7 +1809,7 @@ export class LocalBackend {
|
|
|
1716
1809
|
}
|
|
1717
1810
|
}
|
|
1718
1811
|
// Categorized outgoing refs
|
|
1719
|
-
const outgoingRows = await executeParameterized(repo.
|
|
1812
|
+
const outgoingRows = await executeParameterized(repo.lbugPath, `
|
|
1720
1813
|
MATCH (n {id: $symId})-[r:CodeRelation]->(target)
|
|
1721
1814
|
WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'USES', 'HAS_METHOD', 'HAS_PROPERTY', 'METHOD_OVERRIDES', 'OVERRIDES', 'METHOD_IMPLEMENTS', 'ACCESSES']
|
|
1722
1815
|
RETURN r.type AS relType, target.id AS uid, target.name AS name, target.filePath AS filePath, labels(target)[0] AS kind
|
|
@@ -1725,7 +1818,7 @@ export class LocalBackend {
|
|
|
1725
1818
|
// Process participation
|
|
1726
1819
|
let processRows = [];
|
|
1727
1820
|
try {
|
|
1728
|
-
processRows = await executeParameterized(repo.
|
|
1821
|
+
processRows = await executeParameterized(repo.lbugPath, `
|
|
1729
1822
|
MATCH (n {id: $symId})-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
|
|
1730
1823
|
RETURN p.id AS pid, p.heuristicLabel AS label, r.step AS step, p.stepCount AS stepCount
|
|
1731
1824
|
`, { symId });
|
|
@@ -1756,7 +1849,7 @@ export class LocalBackend {
|
|
|
1756
1849
|
let methodMetadata;
|
|
1757
1850
|
if (isMethodLike) {
|
|
1758
1851
|
try {
|
|
1759
|
-
const metaRows = await executeParameterized(repo.
|
|
1852
|
+
const metaRows = await executeParameterized(repo.lbugPath, `
|
|
1760
1853
|
MATCH (n {id: $symId})
|
|
1761
1854
|
RETURN n.visibility AS visibility, n.isStatic AS isStatic, n.isAbstract AS isAbstract,
|
|
1762
1855
|
n.isFinal AS isFinal, n.isVirtual AS isVirtual, n.isOverride AS isOverride,
|
|
@@ -1821,13 +1914,13 @@ export class LocalBackend {
|
|
|
1821
1914
|
* Routes cluster/process types to direct graph queries.
|
|
1822
1915
|
*/
|
|
1823
1916
|
async explore(repo, params) {
|
|
1824
|
-
await this.ensureInitialized(repo
|
|
1917
|
+
await this.ensureInitialized(repo);
|
|
1825
1918
|
const { name, type } = params;
|
|
1826
1919
|
if (type === 'symbol') {
|
|
1827
1920
|
return this.context(repo, { name });
|
|
1828
1921
|
}
|
|
1829
1922
|
if (type === 'cluster') {
|
|
1830
|
-
const clusters = await executeParameterized(repo.
|
|
1923
|
+
const clusters = await executeParameterized(repo.lbugPath, `
|
|
1831
1924
|
MATCH (c:Community)
|
|
1832
1925
|
WHERE c.label = $clusterName OR c.heuristicLabel = $clusterName
|
|
1833
1926
|
RETURN c.id AS id, c.label AS label, c.heuristicLabel AS heuristicLabel, c.cohesion AS cohesion, c.symbolCount AS symbolCount
|
|
@@ -1847,7 +1940,7 @@ export class LocalBackend {
|
|
|
1847
1940
|
totalSymbols += s;
|
|
1848
1941
|
weightedCohesion += (c.cohesion || 0) * s;
|
|
1849
1942
|
}
|
|
1850
|
-
const members = await executeParameterized(repo.
|
|
1943
|
+
const members = await executeParameterized(repo.lbugPath, `
|
|
1851
1944
|
MATCH (n)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
|
|
1852
1945
|
WHERE c.label = $clusterName OR c.heuristicLabel = $clusterName
|
|
1853
1946
|
RETURN DISTINCT n.name AS name, labels(n)[0] AS type, n.filePath AS filePath
|
|
@@ -1870,7 +1963,7 @@ export class LocalBackend {
|
|
|
1870
1963
|
};
|
|
1871
1964
|
}
|
|
1872
1965
|
if (type === 'process') {
|
|
1873
|
-
const processes = await executeParameterized(repo.
|
|
1966
|
+
const processes = await executeParameterized(repo.lbugPath, `
|
|
1874
1967
|
MATCH (p:Process)
|
|
1875
1968
|
WHERE p.label = $processName OR p.heuristicLabel = $processName
|
|
1876
1969
|
RETURN p.id AS id, p.label AS label, p.heuristicLabel AS heuristicLabel, p.processType AS processType, p.stepCount AS stepCount
|
|
@@ -1880,7 +1973,7 @@ export class LocalBackend {
|
|
|
1880
1973
|
return { error: `Process '${name}' not found` };
|
|
1881
1974
|
const proc = processes[0];
|
|
1882
1975
|
const procId = proc.id || proc[0];
|
|
1883
|
-
const steps = await executeParameterized(repo.
|
|
1976
|
+
const steps = await executeParameterized(repo.lbugPath, `
|
|
1884
1977
|
MATCH (n)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p {id: $procId})
|
|
1885
1978
|
RETURN n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, r.step AS step
|
|
1886
1979
|
ORDER BY r.step
|
|
@@ -1908,7 +2001,7 @@ export class LocalBackend {
|
|
|
1908
2001
|
* Maps changed lines to indexed symbols, then finds affected processes.
|
|
1909
2002
|
*/
|
|
1910
2003
|
async detectChanges(repo, params) {
|
|
1911
|
-
await this.ensureInitialized(repo
|
|
2004
|
+
await this.ensureInitialized(repo);
|
|
1912
2005
|
const scope = params.scope || 'unstaged';
|
|
1913
2006
|
const { execFileSync } = await import('child_process');
|
|
1914
2007
|
// Build git diff args based on scope (using execFileSync to avoid shell injection)
|
|
@@ -2019,7 +2112,7 @@ export class LocalBackend {
|
|
|
2019
2112
|
n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine
|
|
2020
2113
|
`;
|
|
2021
2114
|
try {
|
|
2022
|
-
const rows = await executeParameterized(repo.
|
|
2115
|
+
const rows = await executeParameterized(repo.lbugPath, symbolQuery, queryParams);
|
|
2023
2116
|
for (const sym of rows) {
|
|
2024
2117
|
changedSymbols.push({
|
|
2025
2118
|
id: sym.id || sym[0],
|
|
@@ -2040,7 +2133,7 @@ export class LocalBackend {
|
|
|
2040
2133
|
const symIds = changedSymbols.map((s) => s.id);
|
|
2041
2134
|
const symNameById = new Map(changedSymbols.map((s) => [s.id, s.name]));
|
|
2042
2135
|
try {
|
|
2043
|
-
const procs = await executeParameterized(repo.
|
|
2136
|
+
const procs = await executeParameterized(repo.lbugPath, `
|
|
2044
2137
|
MATCH (n)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
|
|
2045
2138
|
WHERE n.id IN $ids
|
|
2046
2139
|
RETURN n.id AS nodeId, p.id AS pid, p.heuristicLabel AS label,
|
|
@@ -2093,7 +2186,7 @@ export class LocalBackend {
|
|
|
2093
2186
|
* Additional refs found via text search are tagged "text_search" (lower confidence).
|
|
2094
2187
|
*/
|
|
2095
2188
|
async rename(repo, params) {
|
|
2096
|
-
await this.ensureInitialized(repo
|
|
2189
|
+
await this.ensureInitialized(repo);
|
|
2097
2190
|
const { new_name, file_path } = params;
|
|
2098
2191
|
const dry_run = params.dry_run ?? true;
|
|
2099
2192
|
if (!params.symbol_name && !params.symbol_uid) {
|
|
@@ -2275,7 +2368,7 @@ export class LocalBackend {
|
|
|
2275
2368
|
}
|
|
2276
2369
|
}
|
|
2277
2370
|
async _impactImpl(repo, params) {
|
|
2278
|
-
await this.ensureInitialized(repo
|
|
2371
|
+
await this.ensureInitialized(repo);
|
|
2279
2372
|
const { target, direction } = params;
|
|
2280
2373
|
const maxDepth = params.maxDepth || 3;
|
|
2281
2374
|
// Map legacy relation type names before filtering (backward compat for OVERRIDES → METHOD_OVERRIDES)
|
|
@@ -2403,14 +2496,14 @@ export class LocalBackend {
|
|
|
2403
2496
|
try {
|
|
2404
2497
|
// Run both seed queries in parallel — they are independent.
|
|
2405
2498
|
const [ctorRows, fileRows] = await Promise.all([
|
|
2406
|
-
executeParameterized(repo.
|
|
2499
|
+
executeParameterized(repo.lbugPath, `
|
|
2407
2500
|
MATCH (n)-[hm:CodeRelation]->(c:Constructor)
|
|
2408
2501
|
WHERE n.id = $symId AND hm.type = 'HAS_METHOD'
|
|
2409
2502
|
RETURN c.id AS id, c.name AS name, labels(c)[0] AS type, c.filePath AS filePath
|
|
2410
2503
|
`, { symId }),
|
|
2411
2504
|
// Restrict to DEFINES edges only — other File->Class edge types (if
|
|
2412
2505
|
// any) should not be treated as the owning file relationship.
|
|
2413
|
-
executeParameterized(repo.
|
|
2506
|
+
executeParameterized(repo.lbugPath, `
|
|
2414
2507
|
MATCH (f:File)-[rel:CodeRelation]->(n)
|
|
2415
2508
|
WHERE n.id = $symId AND rel.type = 'DEFINES'
|
|
2416
2509
|
RETURN f.id AS id, f.name AS name, labels(f)[0] AS type, f.filePath AS filePath
|
|
@@ -2430,7 +2523,7 @@ export class LocalBackend {
|
|
|
2430
2523
|
frontier.push(rid);
|
|
2431
2524
|
}
|
|
2432
2525
|
}
|
|
2433
|
-
const typedPropertyRows = await executeParameterized(repo.
|
|
2526
|
+
const typedPropertyRows = await executeParameterized(repo.lbugPath, `
|
|
2434
2527
|
MATCH (p:\`Property\`)
|
|
2435
2528
|
WHERE p.declaredType = $name
|
|
2436
2529
|
OR p.declaredType STARTS WITH $genericPrefix
|
|
@@ -2461,7 +2554,7 @@ export class LocalBackend {
|
|
|
2461
2554
|
? `MATCH (caller)-[r:CodeRelation]->(n) WHERE n.id IN $frontierIds AND r.type IN $relTypes${confidenceFilter} RETURN n.id AS sourceId, caller.id AS id, caller.name AS name, labels(caller)[0] AS type, caller.filePath AS filePath, r.type AS relType, r.confidence AS confidence`
|
|
2462
2555
|
: `MATCH (n)-[r:CodeRelation]->(callee) WHERE n.id IN $frontierIds AND r.type IN $relTypes${confidenceFilter} RETURN n.id AS sourceId, callee.id AS id, callee.name AS name, labels(callee)[0] AS type, callee.filePath AS filePath, r.type AS relType, r.confidence AS confidence`;
|
|
2463
2556
|
try {
|
|
2464
|
-
const related = await executeParameterized(repo.
|
|
2557
|
+
const related = await executeParameterized(repo.lbugPath, query, {
|
|
2465
2558
|
frontierIds: frontier,
|
|
2466
2559
|
relTypes: relationTypes,
|
|
2467
2560
|
...(safeMinConfidence > 0 ? { minConfidence: safeMinConfidence } : {}),
|
|
@@ -2541,7 +2634,7 @@ export class LocalBackend {
|
|
|
2541
2634
|
const ids = chunk.map((item) => String(item.id ?? ''));
|
|
2542
2635
|
try {
|
|
2543
2636
|
// Use parameterized list to avoid building long query strings
|
|
2544
|
-
const rows = await executeParameterized(repo.
|
|
2637
|
+
const rows = await executeParameterized(repo.lbugPath, `
|
|
2545
2638
|
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
|
|
2546
2639
|
WHERE s.id IN $ids
|
|
2547
2640
|
WITH p, COUNT(DISTINCT s.id) AS hits, MIN(r.step) AS minStep
|
|
@@ -2607,7 +2700,7 @@ export class LocalBackend {
|
|
|
2607
2700
|
try {
|
|
2608
2701
|
const pIds = Array.from(processesMissingMinStep);
|
|
2609
2702
|
const allImpactedIds = impacted.map((it) => String(it.id ?? ''));
|
|
2610
|
-
const missingRows = await executeParameterized(repo.
|
|
2703
|
+
const missingRows = await executeParameterized(repo.lbugPath, `
|
|
2611
2704
|
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
|
|
2612
2705
|
WHERE p.id IN $pIds AND s.id IN $ids
|
|
2613
2706
|
RETURN p.id AS pid, MIN(r.step) AS minStep
|
|
@@ -2659,7 +2752,7 @@ export class LocalBackend {
|
|
|
2659
2752
|
if (!idsChunk || idsChunk.length === 0)
|
|
2660
2753
|
return;
|
|
2661
2754
|
try {
|
|
2662
|
-
const rows = await executeParameterized(repo.
|
|
2755
|
+
const rows = await executeParameterized(repo.lbugPath, `
|
|
2663
2756
|
MATCH (s)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
|
|
2664
2757
|
WHERE s.id IN $ids
|
|
2665
2758
|
RETURN c.heuristicLabel AS name, COUNT(DISTINCT s.id) AS hits
|
|
@@ -2688,7 +2781,7 @@ export class LocalBackend {
|
|
|
2688
2781
|
if (!idsChunk || idsChunk.length === 0)
|
|
2689
2782
|
return;
|
|
2690
2783
|
try {
|
|
2691
|
-
const rows = await executeParameterized(repo.
|
|
2784
|
+
const rows = await executeParameterized(repo.lbugPath, `
|
|
2692
2785
|
MATCH (s)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
|
|
2693
2786
|
WHERE s.id IN $ids
|
|
2694
2787
|
RETURN DISTINCT c.heuristicLabel AS name
|
|
@@ -2815,7 +2908,7 @@ export class LocalBackend {
|
|
|
2815
2908
|
for (let i = 0; i < pageIdArr.length; i += CHUNK_SIZE) {
|
|
2816
2909
|
const chunkIds = pageIdArr.slice(i, i + CHUNK_SIZE);
|
|
2817
2910
|
try {
|
|
2818
|
-
const rows = await executeParameterized(repo.
|
|
2911
|
+
const rows = await executeParameterized(repo.lbugPath, `
|
|
2819
2912
|
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
|
|
2820
2913
|
WHERE s.id IN $ids
|
|
2821
2914
|
RETURN s.id AS sid, p.id AS pid, p.heuristicLabel AS pName,
|
|
@@ -2876,20 +2969,25 @@ export class LocalBackend {
|
|
|
2876
2969
|
// resolves the await regardless of how long this body runs.
|
|
2877
2970
|
if (opts.signal?.aborted)
|
|
2878
2971
|
return null;
|
|
2972
|
+
let repo;
|
|
2879
2973
|
try {
|
|
2880
2974
|
await this.refreshRepos();
|
|
2881
|
-
|
|
2975
|
+
// Fetch the resolved handle BEFORE init and pass it through, so a
|
|
2976
|
+
// concurrent refresh can't remap the id to a different clone (#2067).
|
|
2977
|
+
repo = this.repos.get(repoId);
|
|
2978
|
+
if (repo)
|
|
2979
|
+
await this.ensureInitialized(repo);
|
|
2882
2980
|
}
|
|
2883
2981
|
catch {
|
|
2884
2982
|
return null;
|
|
2885
2983
|
}
|
|
2886
|
-
const repo = this.repos.get(repoId);
|
|
2887
2984
|
if (!repo)
|
|
2888
|
-
return null;
|
|
2985
|
+
return null; // unknown repo → null (preserves contract)
|
|
2889
2986
|
const dir = direction === 'downstream' ? 'downstream' : 'upstream';
|
|
2890
2987
|
let rows;
|
|
2891
2988
|
try {
|
|
2892
|
-
rows = await executeParameterized(
|
|
2989
|
+
rows = await executeParameterized(repo.lbugPath, // pool keyed by the resolved clone's path, not the id
|
|
2990
|
+
`MATCH (n) WHERE n.id = $uid
|
|
2893
2991
|
RETURN n.id AS id, n.name AS name, n.filePath AS filePath, labels(n)[0] AS type
|
|
2894
2992
|
LIMIT 1`, { uid });
|
|
2895
2993
|
}
|
|
@@ -3199,10 +3297,10 @@ export class LocalBackend {
|
|
|
3199
3297
|
return result;
|
|
3200
3298
|
}
|
|
3201
3299
|
async routeMap(repo, params) {
|
|
3202
|
-
await this.ensureInitialized(repo
|
|
3300
|
+
await this.ensureInitialized(repo);
|
|
3203
3301
|
const routeFilter = params.route ? `AND n.name CONTAINS $route` : '';
|
|
3204
3302
|
const queryParams = params.route ? { route: params.route } : {};
|
|
3205
|
-
const routes = await this.fetchRoutesWithConsumers(repo.
|
|
3303
|
+
const routes = await this.fetchRoutesWithConsumers(repo.lbugPath, routeFilter, queryParams);
|
|
3206
3304
|
if (routes.length === 0) {
|
|
3207
3305
|
return {
|
|
3208
3306
|
routes: [],
|
|
@@ -3212,7 +3310,7 @@ export class LocalBackend {
|
|
|
3212
3310
|
: 'No routes found in this project.',
|
|
3213
3311
|
};
|
|
3214
3312
|
}
|
|
3215
|
-
const flowMap = await this.fetchLinkedFlowsBatch(repo.
|
|
3313
|
+
const flowMap = await this.fetchLinkedFlowsBatch(repo.lbugPath, routes.map((r) => r.id));
|
|
3216
3314
|
return {
|
|
3217
3315
|
routes: routes.map((r) => ({
|
|
3218
3316
|
route: r.name,
|
|
@@ -3225,10 +3323,10 @@ export class LocalBackend {
|
|
|
3225
3323
|
};
|
|
3226
3324
|
}
|
|
3227
3325
|
async shapeCheck(repo, params) {
|
|
3228
|
-
await this.ensureInitialized(repo
|
|
3326
|
+
await this.ensureInitialized(repo);
|
|
3229
3327
|
const routeFilter = params.route ? `AND n.name CONTAINS $route` : '';
|
|
3230
3328
|
const queryParams = params.route ? { route: params.route } : {};
|
|
3231
|
-
const allRoutes = await this.fetchRoutesWithConsumers(repo.
|
|
3329
|
+
const allRoutes = await this.fetchRoutesWithConsumers(repo.lbugPath, routeFilter, queryParams);
|
|
3232
3330
|
const results = allRoutes
|
|
3233
3331
|
.filter((r) => ((r.responseKeys && r.responseKeys.length > 0) ||
|
|
3234
3332
|
(r.errorKeys && r.errorKeys.length > 0)) &&
|
|
@@ -3291,10 +3389,10 @@ export class LocalBackend {
|
|
|
3291
3389
|
};
|
|
3292
3390
|
}
|
|
3293
3391
|
async toolMap(repo, params) {
|
|
3294
|
-
await this.ensureInitialized(repo
|
|
3392
|
+
await this.ensureInitialized(repo);
|
|
3295
3393
|
const toolFilter = params.tool ? `AND n.name CONTAINS $tool` : '';
|
|
3296
3394
|
const queryParams = params.tool ? { tool: params.tool } : {};
|
|
3297
|
-
const rows = await executeParameterized(repo.
|
|
3395
|
+
const rows = await executeParameterized(repo.lbugPath, `
|
|
3298
3396
|
MATCH (n:Tool)
|
|
3299
3397
|
WHERE n.id STARTS WITH 'Tool:' ${toolFilter}
|
|
3300
3398
|
RETURN n.id AS id, n.name AS name, n.filePath AS filePath, n.description AS description
|
|
@@ -3307,7 +3405,7 @@ export class LocalBackend {
|
|
|
3307
3405
|
};
|
|
3308
3406
|
}
|
|
3309
3407
|
const toolIds = rows.map((r) => r.id ?? r[0]);
|
|
3310
|
-
const flowMap = await this.fetchLinkedFlowsBatch(repo.
|
|
3408
|
+
const flowMap = await this.fetchLinkedFlowsBatch(repo.lbugPath, toolIds);
|
|
3311
3409
|
return {
|
|
3312
3410
|
tools: rows.map((r) => {
|
|
3313
3411
|
const id = r.id ?? r[0];
|
|
@@ -3322,7 +3420,7 @@ export class LocalBackend {
|
|
|
3322
3420
|
};
|
|
3323
3421
|
}
|
|
3324
3422
|
async apiImpact(repo, params) {
|
|
3325
|
-
await this.ensureInitialized(repo
|
|
3423
|
+
await this.ensureInitialized(repo);
|
|
3326
3424
|
if (!params.route && !params.file) {
|
|
3327
3425
|
return { error: 'Either "route" or "file" parameter is required.' };
|
|
3328
3426
|
}
|
|
@@ -3337,12 +3435,12 @@ export class LocalBackend {
|
|
|
3337
3435
|
routeFilter = `AND n.filePath CONTAINS $file`;
|
|
3338
3436
|
queryParams.file = params.file;
|
|
3339
3437
|
}
|
|
3340
|
-
const routes = await this.fetchRoutesWithConsumers(repo.
|
|
3438
|
+
const routes = await this.fetchRoutesWithConsumers(repo.lbugPath, routeFilter, queryParams);
|
|
3341
3439
|
if (routes.length === 0) {
|
|
3342
3440
|
const target = params.route || params.file;
|
|
3343
3441
|
return { error: `No routes found matching "${target}".` };
|
|
3344
3442
|
}
|
|
3345
|
-
const flowMap = await this.fetchLinkedFlowsBatch(repo.
|
|
3443
|
+
const flowMap = await this.fetchLinkedFlowsBatch(repo.lbugPath, routes.map((r) => r.id));
|
|
3346
3444
|
// Count how many routes share the same handler file (for middleware partial detection)
|
|
3347
3445
|
const routeCountByHandler = new Map();
|
|
3348
3446
|
for (const r of routes) {
|
|
@@ -3451,10 +3549,10 @@ export class LocalBackend {
|
|
|
3451
3549
|
*/
|
|
3452
3550
|
async queryClusters(repoName, limit = 100) {
|
|
3453
3551
|
const repo = await this.resolveRepo(repoName);
|
|
3454
|
-
await this.ensureInitialized(repo
|
|
3552
|
+
await this.ensureInitialized(repo);
|
|
3455
3553
|
try {
|
|
3456
3554
|
const rawLimit = Math.max(limit * 5, 200);
|
|
3457
|
-
const clusters = await executeQuery(repo.
|
|
3555
|
+
const clusters = await executeQuery(repo.lbugPath, `
|
|
3458
3556
|
MATCH (c:Community)
|
|
3459
3557
|
RETURN c.id AS id, c.label AS label, c.heuristicLabel AS heuristicLabel, c.cohesion AS cohesion, c.symbolCount AS symbolCount
|
|
3460
3558
|
ORDER BY c.symbolCount DESC
|
|
@@ -3479,9 +3577,9 @@ export class LocalBackend {
|
|
|
3479
3577
|
*/
|
|
3480
3578
|
async queryProcesses(repoName, limit = 50) {
|
|
3481
3579
|
const repo = await this.resolveRepo(repoName);
|
|
3482
|
-
await this.ensureInitialized(repo
|
|
3580
|
+
await this.ensureInitialized(repo);
|
|
3483
3581
|
try {
|
|
3484
|
-
const processes = await executeQuery(repo.
|
|
3582
|
+
const processes = await executeQuery(repo.lbugPath, `
|
|
3485
3583
|
MATCH (p:Process)
|
|
3486
3584
|
RETURN p.id AS id, p.label AS label, p.heuristicLabel AS heuristicLabel, p.processType AS processType, p.stepCount AS stepCount
|
|
3487
3585
|
ORDER BY p.stepCount DESC
|
|
@@ -3507,8 +3605,8 @@ export class LocalBackend {
|
|
|
3507
3605
|
*/
|
|
3508
3606
|
async queryClusterDetail(name, repoName) {
|
|
3509
3607
|
const repo = await this.resolveRepo(repoName);
|
|
3510
|
-
await this.ensureInitialized(repo
|
|
3511
|
-
const clusters = await executeParameterized(repo.
|
|
3608
|
+
await this.ensureInitialized(repo);
|
|
3609
|
+
const clusters = await executeParameterized(repo.lbugPath, `
|
|
3512
3610
|
MATCH (c:Community)
|
|
3513
3611
|
WHERE c.label = $clusterName OR c.heuristicLabel = $clusterName
|
|
3514
3612
|
RETURN c.id AS id, c.label AS label, c.heuristicLabel AS heuristicLabel, c.cohesion AS cohesion, c.symbolCount AS symbolCount
|
|
@@ -3528,7 +3626,7 @@ export class LocalBackend {
|
|
|
3528
3626
|
totalSymbols += s;
|
|
3529
3627
|
weightedCohesion += (c.cohesion || 0) * s;
|
|
3530
3628
|
}
|
|
3531
|
-
const members = await executeParameterized(repo.
|
|
3629
|
+
const members = await executeParameterized(repo.lbugPath, `
|
|
3532
3630
|
MATCH (n)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
|
|
3533
3631
|
WHERE c.label = $clusterName OR c.heuristicLabel = $clusterName
|
|
3534
3632
|
RETURN DISTINCT n.name AS name, labels(n)[0] AS type, n.filePath AS filePath
|
|
@@ -3556,8 +3654,8 @@ export class LocalBackend {
|
|
|
3556
3654
|
*/
|
|
3557
3655
|
async queryProcessDetail(name, repoName) {
|
|
3558
3656
|
const repo = await this.resolveRepo(repoName);
|
|
3559
|
-
await this.ensureInitialized(repo
|
|
3560
|
-
const processes = await executeParameterized(repo.
|
|
3657
|
+
await this.ensureInitialized(repo);
|
|
3658
|
+
const processes = await executeParameterized(repo.lbugPath, `
|
|
3561
3659
|
MATCH (p:Process)
|
|
3562
3660
|
WHERE p.label = $processName OR p.heuristicLabel = $processName
|
|
3563
3661
|
RETURN p.id AS id, p.label AS label, p.heuristicLabel AS heuristicLabel, p.processType AS processType, p.stepCount AS stepCount
|
|
@@ -3567,7 +3665,7 @@ export class LocalBackend {
|
|
|
3567
3665
|
return { error: `Process '${name}' not found` };
|
|
3568
3666
|
const proc = processes[0];
|
|
3569
3667
|
const procId = proc.id || proc[0];
|
|
3570
|
-
const steps = await executeParameterized(repo.
|
|
3668
|
+
const steps = await executeParameterized(repo.lbugPath, `
|
|
3571
3669
|
MATCH (n)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p {id: $procId})
|
|
3572
3670
|
RETURN n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, r.step AS step
|
|
3573
3671
|
ORDER BY r.step
|