gitnexus 1.6.9 → 1.6.10-aptos.0
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 +211 -53
- package/dist/_shared/graph/types.d.ts +67 -3
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/index.d.ts +1 -0
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.d.ts +3 -1
- package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.js +4 -3
- package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +2 -0
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/languages.d.ts +2 -0
- package/dist/_shared/languages.d.ts.map +1 -1
- package/dist/_shared/languages.js +2 -0
- package/dist/_shared/languages.js.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +2 -2
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +8 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/pipeline.d.ts +1 -1
- package/dist/_shared/pipeline.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/callable-flow-site.d.ts +110 -0
- package/dist/_shared/scope-resolution/callable-flow-site.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/callable-flow-site.js +11 -0
- package/dist/_shared/scope-resolution/callable-flow-site.js.map +1 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.d.ts +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.js +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.js +1 -0
- package/dist/_shared/scope-resolution/language-classification.js.map +1 -1
- package/dist/_shared/scope-resolution/parsed-file.d.ts +7 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts +9 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/types.d.ts +20 -3
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +1 -1
- package/dist/cli/ai-context.js +25 -44
- package/dist/cli/analyze.d.ts +5 -2
- package/dist/cli/analyze.js +197 -11
- package/dist/cli/clean.js +17 -3
- package/dist/cli/cli-message.d.ts +1 -1
- package/dist/cli/doctor.d.ts +18 -0
- package/dist/cli/doctor.js +96 -5
- package/dist/cli/editor-targets.d.ts +17 -2
- package/dist/cli/editor-targets.js +44 -0
- package/dist/cli/embeddings.d.ts +12 -0
- package/dist/cli/embeddings.js +49 -0
- package/dist/cli/eval-server.d.ts +23 -1
- package/dist/cli/eval-server.js +126 -8
- package/dist/cli/help-i18n.js +6 -0
- package/dist/cli/i18n/en.d.ts +18 -8
- package/dist/cli/i18n/en.js +18 -8
- package/dist/cli/i18n/resources.d.ts +28 -8
- package/dist/cli/i18n/zh-CN.d.ts +10 -0
- package/dist/cli/i18n/zh-CN.js +18 -8
- package/dist/cli/index.js +21 -7
- package/dist/cli/lazy-action.d.ts +7 -0
- package/dist/cli/lazy-action.js +27 -0
- package/dist/cli/mcp.js +6 -3
- package/dist/cli/move-availability.d.ts +5 -0
- package/dist/cli/move-availability.js +11 -0
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.js +230 -32
- package/dist/cli/skill-gen.js +38 -18
- package/dist/cli/standard-skills.d.ts +76 -0
- package/dist/cli/standard-skills.js +45 -0
- package/dist/cli/status.d.ts +4 -1
- package/dist/cli/status.js +57 -4
- package/dist/cli/tool.js +11 -0
- package/dist/cli/uninstall.js +77 -18
- package/dist/cli/wiki.d.ts +1 -0
- package/dist/cli/wiki.js +7 -1
- package/dist/config/ignore-service.d.ts +2 -0
- package/dist/config/ignore-service.js +27 -0
- package/dist/core/analysis-features.d.ts +21 -0
- package/dist/core/analysis-features.js +59 -0
- package/dist/core/analyzer-identity.d.ts +74 -0
- package/dist/core/analyzer-identity.js +1820 -0
- package/dist/core/augmentation/engine.js +13 -8
- package/dist/core/embeddings/embedder.d.ts +3 -2
- package/dist/core/embeddings/embedder.js +24 -7
- package/dist/core/embeddings/embedding-identity.d.ts +11 -0
- package/dist/core/embeddings/embedding-identity.js +24 -0
- package/dist/core/embeddings/embedding-pipeline.d.ts +36 -1
- package/dist/core/embeddings/embedding-pipeline.js +100 -9
- package/dist/core/embeddings/http-client.d.ts +33 -3
- package/dist/core/embeddings/http-client.js +237 -25
- package/dist/core/embeddings/node-module-compat.d.ts +25 -0
- package/dist/core/embeddings/node-module-compat.js +25 -0
- package/dist/core/embeddings/onnxruntime-common-resolver.js +8 -5
- package/dist/core/embeddings/onnxruntime-node-resolver.js +33 -7
- package/dist/core/embeddings/runtime-install.d.ts +119 -0
- package/dist/core/embeddings/runtime-install.js +372 -0
- package/dist/core/embeddings/runtime-support.d.ts +48 -17
- package/dist/core/embeddings/runtime-support.js +96 -0
- package/dist/core/git-staleness.js +1 -1
- package/dist/core/group/bridge-db.js +2 -0
- package/dist/core/group/extractors/http-patterns/python.js +246 -108
- package/dist/core/group/extractors/manifest-extractor.js +4 -0
- package/dist/core/incremental/escalation-gate.d.ts +38 -0
- package/dist/core/incremental/escalation-gate.js +48 -0
- package/dist/core/incremental/shadow-candidates.d.ts +3 -3
- package/dist/core/incremental/shadow-candidates.js +3 -3
- package/dist/core/incremental/subgraph-extract.d.ts +2 -2
- package/dist/core/incremental/subgraph-extract.js +2 -2
- package/dist/core/index-freshness.d.ts +5 -0
- package/dist/core/index-freshness.js +13 -0
- package/dist/core/ingestion/class-extractors/configs/jvm.js +29 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.js +1 -1
- package/dist/core/ingestion/cobol/jcl-processor.js +9 -8
- package/dist/core/ingestion/cobol-processor.js +27 -26
- package/dist/core/ingestion/community-processor.d.ts +51 -1
- package/dist/core/ingestion/community-processor.js +323 -64
- package/dist/core/ingestion/emit-references.js +7 -2
- package/dist/core/ingestion/filesystem-walker.js +4 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +3 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.js +7 -0
- package/dist/core/ingestion/frameworks/spring/bean-candidates.d.ts +30 -0
- package/dist/core/ingestion/frameworks/spring/bean-candidates.js +182 -0
- package/dist/core/ingestion/frameworks/spring/bean-catalog.d.ts +12 -0
- package/dist/core/ingestion/frameworks/spring/bean-catalog.js +26 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.d.ts +24 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.js +115 -0
- package/dist/core/ingestion/languages/c/captures.js +56 -0
- package/dist/core/ingestion/languages/c/query.js +17 -0
- package/dist/core/ingestion/languages/c/scope-resolver.js +6 -0
- package/dist/core/ingestion/languages/cobol/captures.js +93 -0
- package/dist/core/ingestion/languages/cobol/scope-resolver.js +7 -0
- package/dist/core/ingestion/languages/cpp/captures.js +365 -75
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +14 -0
- package/dist/core/ingestion/languages/csharp/captures.js +25 -0
- package/dist/core/ingestion/languages/dart/captures.js +90 -2
- package/dist/core/ingestion/languages/dart/extension-type-preprocess.d.ts +7 -0
- package/dist/core/ingestion/languages/dart/extension-type-preprocess.js +30 -0
- package/dist/core/ingestion/languages/dart.js +2 -0
- package/dist/core/ingestion/languages/go/captures.js +34 -0
- package/dist/core/ingestion/languages/index.d.ts +1 -0
- package/dist/core/ingestion/languages/index.js +2 -0
- package/dist/core/ingestion/languages/java/analysis-features.d.ts +3 -0
- package/dist/core/ingestion/languages/java/analysis-features.js +13 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +22 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.js +58 -0
- package/dist/core/ingestion/languages/java/captures.d.ts +4 -3
- package/dist/core/ingestion/languages/java/captures.js +193 -17
- package/dist/core/ingestion/languages/java/package-facts.d.ts +5 -0
- package/dist/core/ingestion/languages/java/package-facts.js +9 -0
- package/dist/core/ingestion/languages/java/package-siblings.d.ts +3 -16
- package/dist/core/ingestion/languages/java/package-siblings.js +8 -147
- package/dist/core/ingestion/languages/java/query.js +23 -0
- package/dist/core/ingestion/languages/java/scope-resolver.js +23 -0
- package/dist/core/ingestion/languages/java/spring-bean-metadata.d.ts +2 -0
- package/dist/core/ingestion/languages/java/spring-bean-metadata.js +8 -0
- package/dist/core/ingestion/languages/java/spring-config-bindings.d.ts +23 -0
- package/dist/core/ingestion/languages/java/spring-config-bindings.js +215 -0
- package/dist/core/ingestion/languages/java.js +3 -0
- package/dist/core/ingestion/languages/javascript/captures.js +16 -0
- package/dist/core/ingestion/languages/javascript/query.js +21 -0
- package/dist/core/ingestion/languages/jvm/package-facts.d.ts +35 -0
- package/dist/core/ingestion/languages/jvm/package-facts.js +40 -0
- package/dist/core/ingestion/languages/jvm/package-siblings.d.ts +14 -0
- package/dist/core/ingestion/languages/jvm/package-siblings.js +129 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +17 -3
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +42 -8
- package/dist/core/ingestion/languages/kotlin/captures.js +59 -0
- package/dist/core/ingestion/languages/kotlin/package-facts.d.ts +5 -0
- package/dist/core/ingestion/languages/kotlin/package-facts.js +9 -0
- package/dist/core/ingestion/languages/kotlin/package-siblings.d.ts +4 -0
- package/dist/core/ingestion/languages/kotlin/package-siblings.js +8 -0
- package/dist/core/ingestion/languages/kotlin/query.js +19 -0
- package/dist/core/ingestion/languages/kotlin/scope-resolver.js +9 -1
- package/dist/core/ingestion/languages/kotlin/spring-bean-metadata.d.ts +2 -0
- package/dist/core/ingestion/languages/kotlin/spring-bean-metadata.js +8 -0
- package/dist/core/ingestion/languages/kotlin.js +5 -6
- package/dist/core/ingestion/languages/move.d.ts +1 -0
- package/dist/core/ingestion/languages/move.js +27 -0
- package/dist/core/ingestion/languages/php/captures.js +40 -0
- package/dist/core/ingestion/languages/php/import-decomposer.js +12 -0
- package/dist/core/ingestion/languages/php/import-target.d.ts +2 -1
- package/dist/core/ingestion/languages/php/import-target.js +110 -2
- package/dist/core/ingestion/languages/php/interpret.js +10 -0
- package/dist/core/ingestion/languages/php/scope-resolver.js +1 -1
- package/dist/core/ingestion/languages/python/captures.d.ts +3 -4
- package/dist/core/ingestion/languages/python/captures.js +24 -5
- package/dist/core/ingestion/languages/python/interpret.js +4 -0
- package/dist/core/ingestion/languages/python/receiver-binding.d.ts +15 -2
- package/dist/core/ingestion/languages/python/receiver-binding.js +96 -2
- package/dist/core/ingestion/languages/python/simple-hooks.d.ts +5 -5
- package/dist/core/ingestion/languages/python/simple-hooks.js +15 -5
- package/dist/core/ingestion/languages/ruby/captures.js +42 -0
- package/dist/core/ingestion/languages/rust/captures.js +13 -0
- package/dist/core/ingestion/languages/rust/interpret.js +18 -0
- package/dist/core/ingestion/languages/rust/query.js +9 -0
- package/dist/core/ingestion/languages/rust/range-binding.js +6 -2
- package/dist/core/ingestion/languages/swift/captures.js +12 -0
- package/dist/core/ingestion/languages/typescript/captures.js +21 -0
- package/dist/core/ingestion/languages/typescript/nuxt-auto-imports.js +2 -1
- package/dist/core/ingestion/languages/typescript/query.js +37 -0
- package/dist/core/ingestion/markdown-processor.js +3 -2
- package/dist/core/ingestion/model/registration-table.js +1 -0
- package/dist/core/ingestion/parsing-processor.d.ts +3 -1
- package/dist/core/ingestion/parsing-processor.js +36 -1
- package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
- package/dist/core/ingestion/pipeline-phases/index.js +2 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +56 -2
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +0 -2
- package/dist/core/ingestion/pipeline-phases/parse.js +12 -3
- package/dist/core/ingestion/pipeline-phases/processes.d.ts +8 -0
- package/dist/core/ingestion/pipeline-phases/processes.js +11 -1
- package/dist/core/ingestion/pipeline-phases/spring-config.d.ts +37 -0
- package/dist/core/ingestion/pipeline-phases/spring-config.js +433 -0
- package/dist/core/ingestion/pipeline-phases/standalone-ingest.d.ts +10 -0
- package/dist/core/ingestion/pipeline-phases/standalone-ingest.js +6 -0
- package/dist/core/ingestion/pipeline.d.ts +4 -2
- package/dist/core/ingestion/pipeline.js +5 -2
- package/dist/core/ingestion/resolve-references.js +12 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +83 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.js +131 -0
- package/dist/core/ingestion/route-extractors/python-const-resolver.d.ts +75 -0
- package/dist/core/ingestion/route-extractors/python-const-resolver.js +299 -0
- package/dist/core/ingestion/scope-extractor.js +306 -43
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +71 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.d.ts +7 -7
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +8 -7
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +3 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +6 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +1 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +4 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +7 -2
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +47 -0
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +1138 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +16 -4
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +97 -1
- package/dist/core/ingestion/scope-resolution/passes/property-dispatch.d.ts +60 -0
- package/dist/core/ingestion/scope-resolution/passes/property-dispatch.js +111 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +4 -3
- package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +5 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +25 -38
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +6 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +147 -35
- package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
- package/dist/core/ingestion/scope-resolution/scope/walkers.js +73 -44
- package/dist/core/ingestion/taint/typescript-model.js +34 -2
- package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
- package/dist/core/ingestion/tree-sitter-queries.js +23 -2
- package/dist/core/ingestion/type-extractors/jvm.js +17 -2
- package/dist/core/ingestion/utils/ast-helpers.d.ts +1 -0
- package/dist/core/ingestion/utils/ast-helpers.js +153 -2
- package/dist/core/ingestion/utils/callable-flow-captures.d.ts +94 -0
- package/dist/core/ingestion/utils/callable-flow-captures.js +878 -0
- package/dist/core/ingestion/utils/line-base.d.ts +20 -0
- package/dist/core/ingestion/utils/line-base.js +20 -0
- package/dist/core/ingestion/utils/symbol-labels.d.ts +21 -0
- package/dist/core/ingestion/utils/symbol-labels.js +45 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +34 -0
- package/dist/core/ingestion/workers/parse-worker.js +40 -5
- package/dist/core/ingestion/workers/result-merge.js +4 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +28 -0
- package/dist/core/ingestion/workers/worker-pool.js +128 -28
- package/dist/core/lbug/csv-generator.d.ts +15 -0
- package/dist/core/lbug/csv-generator.js +124 -27
- package/dist/core/lbug/cypher-escape.d.ts +20 -0
- package/dist/core/lbug/cypher-escape.js +20 -0
- package/dist/core/lbug/extension-load-error.d.ts +67 -0
- package/dist/core/lbug/extension-load-error.js +326 -0
- package/dist/core/lbug/extension-loader.d.ts +17 -2
- package/dist/core/lbug/extension-loader.js +38 -13
- package/dist/core/lbug/lbug-adapter.d.ts +203 -2
- package/dist/core/lbug/lbug-adapter.js +527 -86
- package/dist/core/lbug/lbug-config.d.ts +56 -2
- package/dist/core/lbug/lbug-config.js +267 -7
- package/dist/core/lbug/move-columns.d.ts +7 -0
- package/dist/core/lbug/move-columns.js +86 -0
- package/dist/core/lbug/native-check.d.ts +40 -0
- package/dist/core/lbug/native-check.js +90 -0
- package/dist/core/lbug/node-table-layout.d.ts +29 -0
- package/dist/core/lbug/node-table-layout.js +119 -0
- package/dist/core/lbug/pool-adapter.d.ts +23 -1
- package/dist/core/lbug/pool-adapter.js +115 -8
- package/dist/core/lbug/schema.d.ts +4 -3
- package/dist/core/lbug/schema.js +16 -16
- package/dist/core/lbug/sidecar-recovery.d.ts +172 -0
- package/dist/core/lbug/sidecar-recovery.js +418 -16
- package/dist/core/lbug/wal-checkpoint-driver.js +3 -0
- package/dist/core/move/artifact-download.d.ts +19 -0
- package/dist/core/move/artifact-download.js +179 -0
- package/dist/core/move/compiler-facts.d.ts +120 -0
- package/dist/core/move/compiler-facts.js +9 -0
- package/dist/core/move/consistency.d.ts +28 -0
- package/dist/core/move/consistency.js +98 -0
- package/dist/core/move/constants.d.ts +98 -0
- package/dist/core/move/constants.js +136 -0
- package/dist/core/move/discovery.d.ts +10 -0
- package/dist/core/move/discovery.js +22 -0
- package/dist/core/move/entry-points.d.ts +14 -0
- package/dist/core/move/entry-points.js +40 -0
- package/dist/core/move/facts-mapper.d.ts +75 -0
- package/dist/core/move/facts-mapper.js +534 -0
- package/dist/core/move/install-lock.d.ts +14 -0
- package/dist/core/move/install-lock.js +102 -0
- package/dist/core/move/install.d.ts +39 -0
- package/dist/core/move/install.js +391 -0
- package/dist/core/move/mcp-client.d.ts +115 -0
- package/dist/core/move/mcp-client.js +436 -0
- package/dist/core/move/move-ingest.d.ts +49 -0
- package/dist/core/move/move-ingest.js +320 -0
- package/dist/core/move/provision.d.ts +19 -0
- package/dist/core/move/provision.js +91 -0
- package/dist/core/move/release.d.ts +6 -0
- package/dist/core/move/release.js +10 -0
- package/dist/core/move/symbol-id.d.ts +35 -0
- package/dist/core/move/symbol-id.js +65 -0
- package/dist/core/move/type-parser.d.ts +11 -0
- package/dist/core/move/type-parser.js +38 -0
- package/dist/core/platform/capabilities.d.ts +0 -1
- package/dist/core/platform/capabilities.js +39 -8
- package/dist/core/run-analyze.d.ts +3 -3
- package/dist/core/run-analyze.js +1001 -184
- package/dist/core/search/fts-indexes.d.ts +31 -0
- package/dist/core/search/fts-indexes.js +73 -0
- package/dist/core/search/fts-schema.js +2 -0
- package/dist/core/tree-sitter/safe-parse.d.ts +8 -3
- package/dist/core/tree-sitter/safe-parse.js +21 -7
- package/dist/core/wiki/graph-queries.js +6 -5
- package/dist/core/wiki/llm-client.d.ts +8 -2
- package/dist/core/wiki/llm-client.js +41 -5
- package/dist/mcp/core/embedder.js +16 -2
- package/dist/mcp/http-transport.d.ts +5 -0
- package/dist/mcp/http-transport.js +19 -5
- package/dist/mcp/local/bean-metadata.d.ts +2 -0
- package/dist/mcp/local/bean-metadata.js +25 -0
- package/dist/mcp/local/line-display.d.ts +22 -0
- package/dist/mcp/local/line-display.js +3 -0
- package/dist/mcp/local/local-backend.d.ts +19 -1
- package/dist/mcp/local/local-backend.js +402 -155
- package/dist/mcp/local/pdg-impact.d.ts +5 -3
- package/dist/mcp/local/pdg-impact.js +5 -2
- package/dist/mcp/output-budget.d.ts +5 -0
- package/dist/mcp/output-budget.js +52 -0
- package/dist/mcp/read-only-policy.d.ts +12 -0
- package/dist/mcp/read-only-policy.js +102 -0
- package/dist/mcp/repository-policy.d.ts +34 -0
- package/dist/mcp/repository-policy.js +328 -0
- package/dist/mcp/resources.js +32 -5
- package/dist/mcp/server.d.ts +5 -2
- package/dist/mcp/server.js +29 -9
- package/dist/mcp/tools.d.ts +0 -8
- package/dist/mcp/tools.js +102 -5
- package/dist/server/analyze-job.d.ts +3 -0
- package/dist/server/analyze-job.js +17 -0
- package/dist/server/analyze-launch.d.ts +6 -0
- package/dist/server/analyze-launch.js +82 -6
- package/dist/server/analyze-worker-core.d.ts +2 -1
- package/dist/server/analyze-worker-core.js +5 -2
- package/dist/server/analyze-worker.js +29 -6
- package/dist/server/api.d.ts +30 -0
- package/dist/server/api.js +120 -34
- package/dist/server/mcp-http.d.ts +1 -1
- package/dist/server/mcp-http.js +4 -2
- package/dist/server/upload-ingest.js +2 -1
- package/dist/server/validation.js +2 -1
- package/dist/storage/git.d.ts +31 -0
- package/dist/storage/git.js +111 -1
- package/dist/storage/parse-cache.js +7 -1
- package/dist/storage/parsedfile-store.d.ts +8 -0
- package/dist/storage/parsedfile-store.js +165 -1
- package/dist/storage/repo-manager.d.ts +194 -2
- package/dist/storage/repo-manager.js +56 -1
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +50 -3
- package/hooks/claude/gitnexus-hook.cjs +59 -9
- package/hooks/claude/pre-tool-use.sh +0 -0
- package/hooks/claude/session-start.sh +0 -0
- package/package.json +21 -15
- package/scripts/cross-platform-tests.ts +56 -0
- package/scripts/ensure-fts.ts +43 -0
- package/scripts/install-duckdb-extension.mjs +85 -24
- package/scripts/run-cross-platform.ts +61 -6
- package/scripts/shard-arg.ts +30 -0
- package/scripts/sync-plugin-manifests.mjs +192 -0
- package/skills/gitnexus-lfg/README.md +55 -0
- package/skills/gitnexus-lfg/SKILL.md +86 -0
- package/skills/gitnexus-plan/README.md +142 -0
- package/skills/gitnexus-plan/SKILL.md +348 -0
- package/skills/gitnexus-plan/references/context-ledger.md +137 -0
- package/skills/gitnexus-plan/references/context-pack.md +126 -0
- package/skills/gitnexus-plan/references/evidence-provenance.md +272 -0
- package/skills/gitnexus-plan/references/pdg-slice.md +109 -0
- package/skills/gitnexus-plan/references/plan-template.md +201 -0
- package/skills/gitnexus-plan/scripts/evidence-provenance.mjs +2084 -0
- package/skills/gitnexus-review/SKILL.md +273 -0
- package/skills/gitnexus-review/ci-personas/ci-adversarial-lens.md +42 -0
- package/skills/gitnexus-review/ci-personas/ci-blast-radius-lens.md +39 -0
- package/skills/gitnexus-review/ci-personas/ci-correctness-lens.md +37 -0
- package/skills/gitnexus-review/ci-personas/ci-coverage-lens.md +40 -0
- package/skills/gitnexus-review/ci-personas/ci-critic-lens.md +42 -0
- package/skills/gitnexus-review/ci-personas/ci-security-lens.md +39 -0
- package/skills/gitnexus-work/README.md +71 -0
- package/skills/gitnexus-work/SKILL.md +269 -0
- package/skills/gitnexus-work/references/evidence-provenance.md +272 -0
- package/skills/gitnexus-work/scripts/evidence-provenance.mjs +2084 -0
- package/web/assets/ProcessFlowModal-B_bfBySy.js +22 -0
- package/web/assets/__vite-browser-external-bMKyYQkO.js +1 -0
- package/web/assets/agent-Bqxn-abU.js +626 -0
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-BVWFvYz2.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-CmG3uPWf.js +36 -0
- package/web/assets/{blockDiagram-7IZFK4PR-BkWhpzWB.js → blockDiagram-7IZFK4PR-DBefcjof.js} +7 -7
- package/web/assets/{c4Diagram-Y2BXMSZH-DtBvpzWD.js → c4Diagram-Y2BXMSZH-EjWnjEJl.js} +6 -6
- package/web/assets/chunk-2T2R6R2M-Bb6Sy3_j.js +4 -0
- package/web/assets/chunk-2UTLFMKG-CXlhF3Pt.js +1 -0
- package/web/assets/chunk-3SSMPTDK-rPsRM1x0.js +321 -0
- package/web/assets/chunk-4R4BOZG6-Be_F0JoX.js +159 -0
- package/web/assets/{chunk-6764PJDD-DpIS7hxD.js → chunk-6764PJDD-C7xxk063.js} +1 -1
- package/web/assets/chunk-67TQ5CYL-CA7OhIEf.js +124 -0
- package/web/assets/chunk-7FYTHRHK-CsmYIswB.js +32 -0
- package/web/assets/chunk-7J6CGLKN-BlKwgXKs.js +10 -0
- package/web/assets/chunk-7W6UQGC5-pyKGssV3.js +1 -0
- package/web/assets/chunk-C62D2QBJ-3gdL8EKc.js +1 -0
- package/web/assets/chunk-CEXFNPSA-CjwtMDkc.js +1 -0
- package/web/assets/{chunk-INKRHTLW-Nu4ri9P-.js → chunk-INKRHTLW-Ckl3_KkO.js} +13 -13
- package/web/assets/chunk-J5EP6P6S-L19oz55R.js +1 -0
- package/web/assets/{chunk-KGFNY3KK-JGMJvKCK.js → chunk-KGFNY3KK-BZeP-55u.js} +17 -17
- package/web/assets/chunk-KGYTTC2M-zm6n242I.js +1 -0
- package/web/assets/{chunk-KRXBNO2N-BW5o0KUN.js → chunk-KRXBNO2N-C-UNuKKf.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-CfLLCywY.js → chunk-LCXTWHL2-C162wE5z.js} +5 -5
- package/web/assets/chunk-LII3EMHJ-BL6lKJ_P.js +1 -0
- package/web/assets/chunk-LRIF4GLE-n59lhprL.js +1 -0
- package/web/assets/chunk-QA3QBVWF-DVXPOIxe.js +2 -0
- package/web/assets/chunk-RERM46MO-B5dAdWpP.js +1 -0
- package/web/assets/chunk-RG4AUYOV-ZNgyLFq6.js +206 -0
- package/web/assets/chunk-RKZBBQEN-MyIQbGgD.js +1 -0
- package/web/assets/chunk-RLI5ZMPA-CkXZ0y0U.js +1 -0
- package/web/assets/chunk-T2UQINTJ-BEyXhZWe.js +1 -0
- package/web/assets/chunk-UP6H54XL-BG-n7qDp.js +1 -0
- package/web/assets/chunk-UXSXWOXI-CW1_r5cS.js +1 -0
- package/web/assets/chunk-UY5QBCOK-ByqTVLvh.js +1 -0
- package/web/assets/chunk-VU6ZFW4Y-BLeasdkU.js +2 -0
- package/web/assets/{chunk-W44A43WB-JqMLIpR0.js → chunk-W44A43WB-BN8EQc_u.js} +1 -1
- package/web/assets/chunk-ZXARS5L4-C3v-4Fsw.js +1 -0
- package/web/assets/classDiagram-KGZ6W3CR-olpO3fMe.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-olpO3fMe.js +1 -0
- package/web/assets/cose-bilkent-UX7MHV2Q-BmnZ7Mvj.js +1 -0
- package/web/assets/dagre-ND4H6XIP-CY4iIF7v.js +4 -0
- package/web/assets/diagram-3NCE3AQN-CO6QpzEE.js +43 -0
- package/web/assets/diagram-GF46GFSD-B2atbzmU.js +24 -0
- package/web/assets/diagram-HNR7UZ2L-DVRltWbL.js +3 -0
- package/web/assets/diagram-QXG6HAR7-DR6AHD2h.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-DkpoMwTL.js +10 -0
- package/web/assets/erDiagram-L5TCEMPS-n8g_90bc.js +85 -0
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-CgFBM7e-.js +1 -0
- package/web/assets/flowDiagram-H6V6AXG4-SGMDiCkB.js +162 -0
- package/web/assets/ganttDiagram-JCBTUEKG-Cb3UBqRS.js +292 -0
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DCJv7SII.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-Bs9CR7tq.js +106 -0
- package/web/assets/index-CX_fADmQ.css +2 -0
- package/web/assets/index-D1Z3dGGz.js +575 -0
- package/web/assets/info-J43DQDTF-KCYPFFUO-BfNy-9Nd.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-T368on4D.js +2 -0
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-DfYpxnE5.js → ishikawaDiagram-BNXS4ZKH-XpjJRU9h.js} +6 -6
- package/web/assets/journeyDiagram-M6C3CM3L-C6wjooas.js +139 -0
- package/web/assets/kanban-definition-75IXJCU3-5_UVY79g.js +89 -0
- package/web/assets/{katex-K3KEBU37-CTc5BslQ.js → katex-K3KEBU37-qRQBy-EZ.js} +2 -2
- package/web/assets/{mindmap-definition-2TDM6QVE-DypvbOMQ.js → mindmap-definition-2TDM6QVE-8xDLzk2e.js} +29 -29
- package/web/assets/node-Ct_zna8U.js +8 -0
- package/web/assets/packet-YPE3B663-LP52Z2RK-D4qkeG9k.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-B_yMKyQa.js +1 -0
- package/web/assets/pieDiagram-CU6KROY3-Bv4LpAbr.js +30 -0
- package/web/assets/preload-helper-Czpn1I53.js +1 -0
- package/web/assets/{quadrantDiagram-VICAPDV7-yXSZ2lLz.js → quadrantDiagram-VICAPDV7-DR54jOeR.js} +6 -6
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DeD6yN_0.js +1 -0
- package/web/assets/requirementDiagram-JXO7QTGE-PEkg7sKC.js +84 -0
- package/web/assets/rolldown-runtime-QTnfLwEv.js +1 -0
- package/web/assets/sankeyDiagram-URQDO5SZ-DDWEtjcs.js +40 -0
- package/web/assets/sdk-CzHHH8tD.js +37 -0
- package/web/assets/sequenceDiagram-VS2MUI6T-Bv-uwANx.js +162 -0
- package/web/assets/src-JV30wyV8.js +1 -0
- package/web/assets/stateDiagram-7D4R322I-DVNjmkEq.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-CyN4Fh7_.js +1 -0
- package/web/assets/timeline-definition-O6YCAMPW-Qmsuo7qS.js +120 -0
- package/web/assets/treeView-BLDUP644-QA4HXRO3-CDuSYnd4.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-imazucyJ.js +1 -0
- package/web/assets/vennDiagram-MWXL3ELB-BD1iK1SX.js +34 -0
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-DqrT9tB8.js +1 -0
- package/web/assets/wardleyDiagram-CUQ6CDDI-D6TzLVob.js +78 -0
- package/web/assets/{xychartDiagram-N2JHSOCM-BOLm0eNm.js → xychartDiagram-N2JHSOCM-CoZ_Tits.js} +6 -6
- package/web/index.html +18 -10
- package/skills/gitnexus-pr-review.md +0 -163
- package/web/assets/agent-Dli_x7bU.js +0 -660
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +0 -1
- package/web/assets/architectureDiagram-UL44E2DR-dEkqUZN9.js +0 -36
- package/web/assets/chunk-3SSMPTDK-B4_etUhr.js +0 -321
- package/web/assets/chunk-67TQ5CYL-4sNPJU1q.js +0 -124
- package/web/assets/chunk-7W6UQGC5-KyEG0HQg.js +0 -1
- package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +0 -161
- package/web/assets/chunk-LII3EMHJ-D-jm-dLa.js +0 -1
- package/web/assets/chunk-QA3QBVWF-BgRW3SXd.js +0 -2
- package/web/assets/chunk-RG4AUYOV-CqWzWsV3.js +0 -206
- package/web/assets/chunk-T2UQINTJ-DSBqkzH7.js +0 -1
- package/web/assets/chunk-UY5QBCOK-DyF0vyGd.js +0 -1
- package/web/assets/chunk-ZXARS5L4-CxN8oiwI.js +0 -1
- package/web/assets/classDiagram-KGZ6W3CR-CMne4tG9.js +0 -1
- package/web/assets/classDiagram-v2-72OJOZXJ-CMne4tG9.js +0 -1
- package/web/assets/cose-bilkent-UX7MHV2Q-D71wNYRJ.js +0 -1
- package/web/assets/dagre-ND4H6XIP-Co5rRx9X.js +0 -4
- package/web/assets/diagram-3NCE3AQN-DBp4O00j.js +0 -43
- package/web/assets/diagram-GF46GFSD-6N_8yS0i.js +0 -24
- package/web/assets/diagram-HNR7UZ2L-DFCfd5LI.js +0 -3
- package/web/assets/diagram-QXG6HAR7-Di093rFg.js +0 -24
- package/web/assets/diagram-WEQXMOUZ-DZWi4SUN.js +0 -10
- package/web/assets/erDiagram-L5TCEMPS-8X1y6R4Y.js +0 -85
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +0 -1
- package/web/assets/flowDiagram-H6V6AXG4-CMpY8Ufn.js +0 -162
- package/web/assets/ganttDiagram-JCBTUEKG-D3iL2Aet.js +0 -292
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +0 -1
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +0 -106
- package/web/assets/index-KctnI3Vq.js +0 -635
- package/web/assets/index-_lgn7hs5.css +0 -2
- package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +0 -1
- package/web/assets/infoDiagram-3YFTVSEB-BaLMZkUg.js +0 -2
- package/web/assets/journeyDiagram-M6C3CM3L-CvArszLo.js +0 -139
- package/web/assets/kanban-definition-75IXJCU3-CpfVLLf9.js +0 -89
- package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +0 -1
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +0 -1
- package/web/assets/pieDiagram-CU6KROY3-s27EFWgP.js +0 -30
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +0 -1
- package/web/assets/requirementDiagram-JXO7QTGE-CWhqInuf.js +0 -84
- package/web/assets/sankeyDiagram-URQDO5SZ-1qEjlFIB.js +0 -40
- package/web/assets/sequenceDiagram-VS2MUI6T-RyTlZ5cR.js +0 -162
- package/web/assets/stateDiagram-7D4R322I-DTjVfX4A.js +0 -1
- package/web/assets/stateDiagram-v2-36443NZ5-xY9_k9_Q.js +0 -1
- package/web/assets/timeline-definition-O6YCAMPW-DrrqLYAf.js +0 -120
- package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +0 -1
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +0 -1
- package/web/assets/vennDiagram-MWXL3ELB-B0RkWAim.js +0 -34
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +0 -1
- package/web/assets/wardleyDiagram-CUQ6CDDI-boUxiQ5F.js +0 -78
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
import fs from 'fs/promises';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import { createHash } from 'crypto';
|
|
11
|
-
import { initLbug, executeQuery, executeParameterized, closeLbug, isLbugReady, } from '../../core/lbug/pool-adapter.js';
|
|
11
|
+
import { initLbug, executeQuery, executeParameterized, closeLbug, isLbugReady, statDbIdentity, dbIdentityChanged, } from '../../core/lbug/pool-adapter.js';
|
|
12
|
+
import { queryClassBeanMetadata } from './bean-metadata.js';
|
|
12
13
|
import { isValidQueryParams } from '../../core/lbug/query-params.js';
|
|
14
|
+
import { toDisplayLine } from './line-display.js';
|
|
13
15
|
import { isWalCorruptionError, WAL_RECOVERY_SUGGESTION } from '../../core/lbug/lbug-config.js';
|
|
14
16
|
// Embedding imports are lazy (dynamic import) to avoid loading onnxruntime-node
|
|
15
17
|
// at MCP server startup — crashes on unsupported Node ABI versions (#89)
|
|
@@ -24,11 +26,13 @@ import { collectBestChunks } from '../../core/embeddings/types.js';
|
|
|
24
26
|
import { DEFAULT_MCP_VECTOR_MAX_DISTANCE, getVectorMaxDistance, } from '../../core/embeddings/config.js';
|
|
25
27
|
import { rankExactEmbeddingRows, } from '../../core/embeddings/exact-search.js';
|
|
26
28
|
import { EMBEDDING_TABLE_NAME, EMBEDDING_INDEX_NAME } from '../../core/lbug/schema.js';
|
|
27
|
-
import { getExactScanLimit
|
|
29
|
+
import { getExactScanLimit } from '../../core/platform/capabilities.js';
|
|
28
30
|
import { PhaseTimer } from '../../core/search/phase-timer.js';
|
|
31
|
+
import { ftsDegradedWarning } from '../../core/search/fts-indexes.js';
|
|
29
32
|
import { cjkSegmentationModeMismatch, containsSegmentableCjkRun, getSearchFTSCjkSegmentation, isSupportedCjkSegmentationMode, MAX_CJK_SEGMENTATION_QUERY_LENGTH, } from '../../core/search/cjk-segmentation.js';
|
|
30
33
|
import { checkStalenessAsync, checkCwdMatch } from '../../core/git-staleness.js';
|
|
31
34
|
import { logger } from '../../core/logger.js';
|
|
35
|
+
import { isLocalEmbeddingRuntimeBlockerMessage, isMissingLocalEmbeddingStackMessage, } from '../../core/embeddings/runtime-support.js';
|
|
32
36
|
import { LIST_REPOS_DEFAULT_LIMIT, LIST_REPOS_MAX_LIMIT, EXPLAIN_DEFAULT_LIMIT, EXPLAIN_MAX_LIMIT, PDG_QUERY_DEFAULT_LIMIT, PDG_QUERY_MAX_LIMIT, } from '../tools.js';
|
|
33
37
|
import { findImportCycles } from '../../core/graph/import-cycles.js';
|
|
34
38
|
import { decodeTaintPath } from '../../core/ingestion/taint/path-codec.js';
|
|
@@ -64,6 +68,51 @@ function resolveAliasString(canonical, legacy) {
|
|
|
64
68
|
}
|
|
65
69
|
return undefined;
|
|
66
70
|
}
|
|
71
|
+
const TOOL_STRING_ALIASES = {
|
|
72
|
+
impact: [{ canonical: 'target', aliases: ['name', 'symbol'] }],
|
|
73
|
+
context: [{ canonical: 'file_path', aliases: ['file'] }],
|
|
74
|
+
};
|
|
75
|
+
function normalizeToolParams(method, params) {
|
|
76
|
+
const input = params && typeof params === 'object' ? params : {};
|
|
77
|
+
const definitions = TOOL_STRING_ALIASES[method];
|
|
78
|
+
if (!definitions)
|
|
79
|
+
return { params: input };
|
|
80
|
+
const normalized = { ...input };
|
|
81
|
+
for (const { canonical, aliases } of definitions) {
|
|
82
|
+
const keys = [canonical, ...aliases];
|
|
83
|
+
const supplied = [];
|
|
84
|
+
for (const key of keys) {
|
|
85
|
+
if (!Object.prototype.hasOwnProperty.call(input, key))
|
|
86
|
+
continue;
|
|
87
|
+
const value = input[key];
|
|
88
|
+
// Internal CLI callers materialize omitted optional flags as undefined.
|
|
89
|
+
if (value === undefined)
|
|
90
|
+
continue;
|
|
91
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
92
|
+
return { error: `MCP parameter ${method}.${key} must be a non-empty string.` };
|
|
93
|
+
}
|
|
94
|
+
supplied.push({ key, value: value.trim() });
|
|
95
|
+
}
|
|
96
|
+
const distinctValues = new Set(supplied.map(({ value }) => value));
|
|
97
|
+
if (distinctValues.size > 1) {
|
|
98
|
+
return {
|
|
99
|
+
error: `Conflicting MCP parameters for ${method}.${canonical}: ${supplied
|
|
100
|
+
.map(({ key }) => key)
|
|
101
|
+
.join(', ')} must agree.`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
for (const alias of aliases)
|
|
105
|
+
delete normalized[alias];
|
|
106
|
+
if (supplied.length > 0)
|
|
107
|
+
normalized[canonical] = supplied[0].value;
|
|
108
|
+
}
|
|
109
|
+
if (method === 'impact' &&
|
|
110
|
+
typeof normalized.target !== 'string' &&
|
|
111
|
+
(typeof normalized.target_uid !== 'string' || !normalized.target_uid.trim())) {
|
|
112
|
+
return { error: 'MCP impact requires target, name, symbol, or target_uid.' };
|
|
113
|
+
}
|
|
114
|
+
return { params: normalized };
|
|
115
|
+
}
|
|
67
116
|
// AI context generation is CLI-only (gitnexus analyze)
|
|
68
117
|
// import { generateAIContextFiles } from '../../cli/ai-context.js';
|
|
69
118
|
/**
|
|
@@ -71,6 +120,8 @@ function resolveAliasString(canonical, legacy) {
|
|
|
71
120
|
* Matches common test file patterns across all supported languages.
|
|
72
121
|
*/
|
|
73
122
|
export function isTestFilePath(filePath) {
|
|
123
|
+
if (!filePath)
|
|
124
|
+
return false;
|
|
74
125
|
const p = filePath.toLowerCase().replace(/\\/g, '/');
|
|
75
126
|
return (p.includes('.test.') ||
|
|
76
127
|
p.includes('.spec.') ||
|
|
@@ -152,6 +203,10 @@ export const VALID_RELATION_TYPES = new Set([
|
|
|
152
203
|
// (WRAPS/FETCHES precedent): the 0.5 unknown-type floor applies there,
|
|
153
204
|
// and the edges carry their own confidence (0.8) in the graph.
|
|
154
205
|
'INJECTS',
|
|
206
|
+
'ACQUIRES',
|
|
207
|
+
'READS_RESOURCE',
|
|
208
|
+
'WRITES_RESOURCE',
|
|
209
|
+
'USES_TYPE',
|
|
155
210
|
]);
|
|
156
211
|
/**
|
|
157
212
|
* Relation types the #1858 epistemic-boundary probe keys on. Kept as
|
|
@@ -419,6 +474,11 @@ export class LocalBackend {
|
|
|
419
474
|
// not persist across calls and the staleness check would reinit forever
|
|
420
475
|
// (#2106).
|
|
421
476
|
lastObservedIndexedAt = new Map();
|
|
477
|
+
// #2614 F1: file identity of the lbug the pool last opened. An atomic swap or
|
|
478
|
+
// an in-place incremental changes the inode; reiniting on that reinit-covers
|
|
479
|
+
// the window where meta.indexedAt hasn't caught up (and the incremental case),
|
|
480
|
+
// so a rebuilt index is never served stale even when the stamp looks current.
|
|
481
|
+
lastObservedDbIdentity = new Map();
|
|
422
482
|
groupToolSvc = null;
|
|
423
483
|
/**
|
|
424
484
|
* One-shot stderr warnings for sibling-clone drift, keyed by
|
|
@@ -434,6 +494,12 @@ export class LocalBackend {
|
|
|
434
494
|
* stderr noisy per DoD §2.8.
|
|
435
495
|
*/
|
|
436
496
|
warnedVectorUnsupported = false;
|
|
497
|
+
/**
|
|
498
|
+
* One-shot warning when a pruned or Node-unloadable optional embedding stack
|
|
499
|
+
* (#2370/#2372) forces semantic search to fall back to BM25 — so the
|
|
500
|
+
* degradation is visible once instead of silent.
|
|
501
|
+
*/
|
|
502
|
+
warnedMissingEmbeddingStack = false;
|
|
437
503
|
/**
|
|
438
504
|
* Cross-repo group tools (CLI). Shares logic with MCP `group_*` handlers.
|
|
439
505
|
*/
|
|
@@ -445,7 +511,7 @@ export class LocalBackend {
|
|
|
445
511
|
query: (r, p) => this.query(r, p),
|
|
446
512
|
impactByUid: (id, uid, d, o) => this.impactByUid(id, uid, d, o),
|
|
447
513
|
context: (r, p) => this.context(r, p),
|
|
448
|
-
trace: (r, p) => this.
|
|
514
|
+
trace: (r, p) => this.traceForGroup(r, p),
|
|
449
515
|
resolveSymbol: (r, q) => this.resolveSymbolForGroup(r, q),
|
|
450
516
|
pdgFlows: (r, anchor, opts) => this.pdgFlowsForGroup(r, anchor, opts),
|
|
451
517
|
};
|
|
@@ -453,6 +519,23 @@ export class LocalBackend {
|
|
|
453
519
|
}
|
|
454
520
|
return this.groupToolSvc;
|
|
455
521
|
}
|
|
522
|
+
/**
|
|
523
|
+
* Adapt local `trace` to the group port. The assembled group/cross-repo trace
|
|
524
|
+
* presents 1-based endpoints (via resolveSymbolForGroup), so convert the hop
|
|
525
|
+
* lines here too — otherwise one response mixes 1-based endpoints with 0-based
|
|
526
|
+
* hops (#2380). Single-repo `trace` dispatches directly (not through this
|
|
527
|
+
* port) and stays 0-based (documented full-parity follow-up).
|
|
528
|
+
*/
|
|
529
|
+
async traceForGroup(repo, params) {
|
|
530
|
+
const result = await this.trace(repo, params);
|
|
531
|
+
const hops = result.hops;
|
|
532
|
+
if (Array.isArray(hops)) {
|
|
533
|
+
for (const hop of hops) {
|
|
534
|
+
hop.startLine = toDisplayLine(hop.startLine);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
return result;
|
|
538
|
+
}
|
|
456
539
|
/**
|
|
457
540
|
* Adapt the shared symbol resolver to the GroupToolPort contract. Used by the
|
|
458
541
|
* cross-repo trace path to locate which member repo an endpoint lives in and
|
|
@@ -470,8 +553,8 @@ export class LocalBackend {
|
|
|
470
553
|
name: s.name,
|
|
471
554
|
type: s.type,
|
|
472
555
|
filePath: s.filePath,
|
|
473
|
-
startLine: s.startLine,
|
|
474
|
-
endLine: s.endLine,
|
|
556
|
+
startLine: toDisplayLine(s.startLine),
|
|
557
|
+
endLine: toDisplayLine(s.endLine),
|
|
475
558
|
},
|
|
476
559
|
};
|
|
477
560
|
}
|
|
@@ -483,7 +566,7 @@ export class LocalBackend {
|
|
|
483
566
|
name: c.name,
|
|
484
567
|
type: c.type,
|
|
485
568
|
filePath: c.filePath,
|
|
486
|
-
startLine: c.startLine,
|
|
569
|
+
startLine: toDisplayLine(c.startLine),
|
|
487
570
|
})),
|
|
488
571
|
};
|
|
489
572
|
}
|
|
@@ -681,6 +764,7 @@ export class LocalBackend {
|
|
|
681
764
|
this.initializedRepos.delete(key);
|
|
682
765
|
this.lastStalenessCheck.delete(key);
|
|
683
766
|
this.lastObservedIndexedAt.delete(key);
|
|
767
|
+
this.lastObservedDbIdentity.delete(key);
|
|
684
768
|
this.reinitPromises.delete(key);
|
|
685
769
|
closeLbug(key).catch(() => { });
|
|
686
770
|
}
|
|
@@ -1040,23 +1124,38 @@ export class LocalBackend {
|
|
|
1040
1124
|
// Reading the flat meta for a branch handle would compare the branch
|
|
1041
1125
|
// index's indexedAt against the primary's and thrash the pool (#2106).
|
|
1042
1126
|
const meta = await loadMeta(path.dirname(repo.lbugPath));
|
|
1043
|
-
if (!meta)
|
|
1044
|
-
return;
|
|
1045
1127
|
// Compare against the last indexedAt OBSERVED for this pool (keyed by
|
|
1046
1128
|
// lbugPath), not the handle's — branch handles are fresh spreads so a
|
|
1047
1129
|
// handle mutation would not persist and would reinit on every check.
|
|
1048
1130
|
const observed = this.lastObservedIndexedAt.get(poolKey) ?? repo.indexedAt;
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1131
|
+
const stampChanged = !!meta?.indexedAt && meta.indexedAt !== observed;
|
|
1132
|
+
// #2614 F1: also reinit on a file-identity change. An atomic swap (or an
|
|
1133
|
+
// in-place incremental) changes the lbug inode; keying only on
|
|
1134
|
+
// meta.indexedAt let a reader that reinited inside the pre-swap window
|
|
1135
|
+
// latch on the old inode forever (its stamp already == meta.indexedAt).
|
|
1136
|
+
const currentIdentity = await statDbIdentity(repo.lbugPath);
|
|
1137
|
+
const identityChanged = dbIdentityChanged(this.lastObservedDbIdentity.get(poolKey) ?? null, currentIdentity);
|
|
1138
|
+
if (stampChanged || identityChanged) {
|
|
1139
|
+
// Index was rebuilt/swapped — DELEGATE the close/reopen to the pool's
|
|
1140
|
+
// initLbug, which refuses to evict (and close the shared Database)
|
|
1141
|
+
// while a query is in flight (its checkedOut>0 guard). Calling
|
|
1142
|
+
// closeLbug directly here bypassed that guard and could close a
|
|
1143
|
+
// Database mid-query — a native use-after-free (#2614). Wrap in
|
|
1144
|
+
// reinitPromises to serialize concurrent detectors.
|
|
1053
1145
|
const reinit = (async () => {
|
|
1054
1146
|
try {
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1147
|
+
// Advance the observed stamp regardless: a stamp change with an
|
|
1148
|
+
// unchanged file must not re-trigger on every check.
|
|
1149
|
+
if (meta?.indexedAt)
|
|
1150
|
+
this.lastObservedIndexedAt.set(poolKey, meta.indexedAt);
|
|
1151
|
+
const reopened = await initLbug(poolKey, repo.lbugPath);
|
|
1152
|
+
// Advance the observed IDENTITY only when the pool actually rolled
|
|
1153
|
+
// over. If a query was in flight, initLbug served the current
|
|
1154
|
+
// handle and returned false; leaving the identity divergent
|
|
1155
|
+
// re-triggers the reopen on a later idle check instead of latching.
|
|
1156
|
+
if (reopened) {
|
|
1157
|
+
this.lastObservedDbIdentity.set(poolKey, await statDbIdentity(repo.lbugPath));
|
|
1158
|
+
}
|
|
1060
1159
|
}
|
|
1061
1160
|
finally {
|
|
1062
1161
|
this.reinitPromises.delete(poolKey);
|
|
@@ -1077,6 +1176,7 @@ export class LocalBackend {
|
|
|
1077
1176
|
await initLbug(poolKey, repo.lbugPath);
|
|
1078
1177
|
this.initializedRepos.add(poolKey);
|
|
1079
1178
|
this.lastObservedIndexedAt.set(poolKey, repo.indexedAt);
|
|
1179
|
+
this.lastObservedDbIdentity.set(poolKey, await statDbIdentity(repo.lbugPath));
|
|
1080
1180
|
}
|
|
1081
1181
|
catch (err) {
|
|
1082
1182
|
// If lock error, mark as not initialized so next call retries
|
|
@@ -1278,7 +1378,10 @@ export class LocalBackend {
|
|
|
1278
1378
|
if (method.startsWith('group_')) {
|
|
1279
1379
|
return this.handleGroupTool(method, params || {});
|
|
1280
1380
|
}
|
|
1281
|
-
const
|
|
1381
|
+
const normalized = normalizeToolParams(method, params);
|
|
1382
|
+
if ('error' in normalized)
|
|
1383
|
+
return { error: normalized.error };
|
|
1384
|
+
const p = normalized.params;
|
|
1282
1385
|
// #2175: Claude Code drops a tool-call argument named exactly "query", so the
|
|
1283
1386
|
// query/cypher tools advertise "search_query"/"statement" while still accepting the
|
|
1284
1387
|
// legacy "query" key for backward compat. The alias is resolved with `?? ` (new name
|
|
@@ -1295,46 +1398,59 @@ export class LocalBackend {
|
|
|
1295
1398
|
}
|
|
1296
1399
|
// Resolve repo from optional param (re-reads registry on miss). An optional
|
|
1297
1400
|
// `branch` param scopes the resolved handle to that branch's index (#2106).
|
|
1298
|
-
const
|
|
1299
|
-
const repo = await this.resolveRepo(repoParams?.repo, repoParams?.branch);
|
|
1401
|
+
const repo = await this.resolveRepo(p.repo, p.branch);
|
|
1300
1402
|
switch (method) {
|
|
1301
1403
|
case 'query':
|
|
1302
|
-
return this.query(repo,
|
|
1404
|
+
return this.query(repo, p);
|
|
1303
1405
|
case 'cypher': {
|
|
1304
|
-
const raw = await this.cypher(repo,
|
|
1406
|
+
const raw = await this.cypher(repo, p);
|
|
1305
1407
|
return this.formatCypherAsMarkdown(raw);
|
|
1306
1408
|
}
|
|
1307
1409
|
case 'context':
|
|
1308
|
-
return this.context(repo,
|
|
1410
|
+
return this.context(repo, p);
|
|
1309
1411
|
case 'explain':
|
|
1310
|
-
return this.explain(repo,
|
|
1412
|
+
return this.explain(repo, p);
|
|
1311
1413
|
case 'pdg_query':
|
|
1312
|
-
return this.pdgQuery(repo,
|
|
1414
|
+
return this.pdgQuery(repo, p);
|
|
1313
1415
|
case 'impact':
|
|
1314
|
-
return this.impact(repo,
|
|
1416
|
+
return this.impact(repo, p);
|
|
1315
1417
|
case 'detect_changes':
|
|
1316
|
-
return this.detectChanges(repo,
|
|
1418
|
+
return this.detectChanges(repo, p);
|
|
1317
1419
|
case 'check':
|
|
1318
|
-
return this.check(repo,
|
|
1420
|
+
return this.check(repo, p);
|
|
1319
1421
|
case 'rename':
|
|
1320
|
-
return this.rename(repo,
|
|
1422
|
+
return this.rename(repo, p);
|
|
1321
1423
|
// Legacy aliases for backwards compatibility
|
|
1322
1424
|
case 'search':
|
|
1323
|
-
return this.query(repo,
|
|
1425
|
+
return this.query(repo, p);
|
|
1324
1426
|
case 'explore':
|
|
1325
|
-
return this.context(repo, {
|
|
1427
|
+
return this.context(repo, {
|
|
1428
|
+
name: typeof p.name === 'string' ? p.name : undefined,
|
|
1429
|
+
...p,
|
|
1430
|
+
});
|
|
1326
1431
|
case 'overview':
|
|
1327
|
-
return this.overview(repo,
|
|
1432
|
+
return this.overview(repo, p);
|
|
1328
1433
|
case 'route_map':
|
|
1329
|
-
return this.routeMap(repo,
|
|
1434
|
+
return this.routeMap(repo, p);
|
|
1330
1435
|
case 'shape_check':
|
|
1331
|
-
return this.shapeCheck(repo,
|
|
1436
|
+
return this.shapeCheck(repo, p);
|
|
1332
1437
|
case 'tool_map':
|
|
1333
|
-
return this.toolMap(repo,
|
|
1438
|
+
return this.toolMap(repo, p);
|
|
1334
1439
|
case 'api_impact':
|
|
1335
|
-
return this.apiImpact(repo,
|
|
1440
|
+
return this.apiImpact(repo, p);
|
|
1441
|
+
// Move/Aptos tools (graph-property/Cypher only — no move-flow shell-out).
|
|
1442
|
+
case 'move_entries':
|
|
1443
|
+
return this.moveEntries(repo, p);
|
|
1444
|
+
case 'move_resources':
|
|
1445
|
+
return this.moveResources(repo, p);
|
|
1446
|
+
case 'move_impact':
|
|
1447
|
+
return this.moveImpact(repo, {
|
|
1448
|
+
target: typeof p.target === 'string' ? p.target : '',
|
|
1449
|
+
direction: p.direction === 'upstream' || p.direction === 'downstream' ? p.direction : undefined,
|
|
1450
|
+
maxDepth: typeof p.maxDepth === 'number' ? p.maxDepth : undefined,
|
|
1451
|
+
});
|
|
1336
1452
|
case 'trace':
|
|
1337
|
-
return this.trace(repo,
|
|
1453
|
+
return this.trace(repo, p);
|
|
1338
1454
|
default:
|
|
1339
1455
|
throw new Error(`Unknown tool: ${method}`);
|
|
1340
1456
|
}
|
|
@@ -1564,8 +1680,8 @@ export class LocalBackend {
|
|
|
1564
1680
|
name: sym.name,
|
|
1565
1681
|
type: sym.type,
|
|
1566
1682
|
filePath: sym.filePath,
|
|
1567
|
-
startLine: sym.startLine,
|
|
1568
|
-
endLine: sym.endLine,
|
|
1683
|
+
startLine: toDisplayLine(sym.startLine),
|
|
1684
|
+
endLine: toDisplayLine(sym.endLine),
|
|
1569
1685
|
...(module ? { module } : {}),
|
|
1570
1686
|
...(includeContent && content ? { content } : {}),
|
|
1571
1687
|
};
|
|
@@ -1652,7 +1768,7 @@ export class LocalBackend {
|
|
|
1652
1768
|
// path, leaving the success-path response shape byte-identical.
|
|
1653
1769
|
const warnings = [];
|
|
1654
1770
|
if (!ftsUsed) {
|
|
1655
|
-
warnings.push(
|
|
1771
|
+
warnings.push(ftsDegradedWarning());
|
|
1656
1772
|
}
|
|
1657
1773
|
// #2331: a CJK query against a server process resolving
|
|
1658
1774
|
// GITNEXUS_FTS_CJK_SEGMENTATION to 'none' silently misses sub-phrase
|
|
@@ -1791,8 +1907,11 @@ export class LocalBackend {
|
|
|
1791
1907
|
name: sym.name || sym[1],
|
|
1792
1908
|
type: sym.type || sym[2],
|
|
1793
1909
|
filePath: sym.filePath || sym[3],
|
|
1794
|
-
|
|
1795
|
-
|
|
1910
|
+
// Raw 0-based here — `bm25Search` is only called from `query()`,
|
|
1911
|
+
// whose aggregation loop applies `toDisplayLine` once (see below).
|
|
1912
|
+
// Converting here too would double-shift BM25-matched lines (#2380).
|
|
1913
|
+
startLine: sym.startLine ?? sym[4],
|
|
1914
|
+
endLine: sym.endLine ?? sym[5],
|
|
1796
1915
|
bm25Score: bm25Result.score,
|
|
1797
1916
|
});
|
|
1798
1917
|
}
|
|
@@ -1834,10 +1953,16 @@ export class LocalBackend {
|
|
|
1834
1953
|
const queryVecStr = `[${queryVec.join(',')}]`;
|
|
1835
1954
|
const maxDistance = getVectorMaxDistance(DEFAULT_MCP_VECTOR_MAX_DISTANCE);
|
|
1836
1955
|
let bestChunks = new Map();
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1956
|
+
// Always TRY the vector lane — no platform gate. LadybugDB ships the
|
|
1957
|
+
// VECTOR extension for every supported platform, Windows included
|
|
1958
|
+
// (#2623 follow-up; the old `platform !== 'win32'` gate was stale), so
|
|
1959
|
+
// whether the index is queryable is a per-machine runtime fact. The
|
|
1960
|
+
// catch below is the fallback: any failure (extension unloadable, index
|
|
1961
|
+
// absent, older DB) degrades to the exact scan with a once-per-backend
|
|
1962
|
+
// diagnostic instead of being silently swallowed.
|
|
1963
|
+
try {
|
|
1964
|
+
bestChunks = await collectBestChunks(limit, async (fetchLimit) => {
|
|
1965
|
+
const vectorQuery = `
|
|
1841
1966
|
CALL QUERY_VECTOR_INDEX('${EMBEDDING_TABLE_NAME}', '${EMBEDDING_INDEX_NAME}',
|
|
1842
1967
|
CAST(${queryVecStr} AS FLOAT[${dims}]), ${fetchLimit})
|
|
1843
1968
|
YIELD node AS emb, distance
|
|
@@ -1847,27 +1972,25 @@ export class LocalBackend {
|
|
|
1847
1972
|
emb.startLine AS startLine, emb.endLine AS endLine, distance
|
|
1848
1973
|
ORDER BY distance
|
|
1849
1974
|
`;
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
}
|
|
1860
|
-
catch {
|
|
1861
|
-
bestChunks = new Map();
|
|
1862
|
-
}
|
|
1975
|
+
const embResults = await executeQuery(repo.lbugPath, vectorQuery);
|
|
1976
|
+
return embResults.map((row) => ({
|
|
1977
|
+
nodeId: row.nodeId ?? row[0],
|
|
1978
|
+
chunkIndex: row.chunkIndex ?? row[1] ?? 0,
|
|
1979
|
+
startLine: row.startLine ?? row[2] ?? 0,
|
|
1980
|
+
endLine: row.endLine ?? row[3] ?? 0,
|
|
1981
|
+
distance: row.distance ?? row[4],
|
|
1982
|
+
}));
|
|
1983
|
+
});
|
|
1863
1984
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1985
|
+
catch (err) {
|
|
1986
|
+
bestChunks = new Map();
|
|
1987
|
+
if (!this.warnedVectorUnsupported) {
|
|
1988
|
+
// Rare diagnostic: surface why semantic search fell back to the
|
|
1989
|
+
// exact scan. Emitted once per `LocalBackend` instance lifetime to
|
|
1990
|
+
// avoid noisy stderr on hot semantic-search paths (DoD §2.8).
|
|
1991
|
+
this.warnedVectorUnsupported = true;
|
|
1992
|
+
logger.warn({ err }, 'GitNexus [query:vector]: vector index query failed; using exact scan fallback');
|
|
1993
|
+
}
|
|
1871
1994
|
}
|
|
1872
1995
|
if (bestChunks.size === 0) {
|
|
1873
1996
|
const embeddingCount = Number(tableCheck[0].cnt ?? tableCheck[0][0] ?? 0);
|
|
@@ -1927,8 +2050,20 @@ export class LocalBackend {
|
|
|
1927
2050
|
}
|
|
1928
2051
|
return results;
|
|
1929
2052
|
}
|
|
1930
|
-
catch {
|
|
1931
|
-
//
|
|
2053
|
+
catch (err) {
|
|
2054
|
+
// Embeddings disabled is the common, silent case. But a pruned or
|
|
2055
|
+
// Node-unloadable optional stack (#2370/#2372) also lands here — surface it
|
|
2056
|
+
// once so semantic search doesn't silently degrade to BM25 with no hint
|
|
2057
|
+
// (the exact silent-degradation mode #2370 exists to fix). Emitted once per
|
|
2058
|
+
// LocalBackend instance to keep stderr quiet on hot paths (like the VECTOR
|
|
2059
|
+
// fallback above). All other errors stay silent, as before.
|
|
2060
|
+
const message = err instanceof Error ? err.message : '';
|
|
2061
|
+
if (!this.warnedMissingEmbeddingStack &&
|
|
2062
|
+
(isMissingLocalEmbeddingStackMessage(message) ||
|
|
2063
|
+
isLocalEmbeddingRuntimeBlockerMessage(message))) {
|
|
2064
|
+
this.warnedMissingEmbeddingStack = true;
|
|
2065
|
+
logger.warn(`GitNexus [query:vector]: ${message}`);
|
|
2066
|
+
}
|
|
1932
2067
|
return [];
|
|
1933
2068
|
}
|
|
1934
2069
|
}
|
|
@@ -2376,7 +2511,7 @@ export class LocalBackend {
|
|
|
2376
2511
|
name: c.name,
|
|
2377
2512
|
kind: c.type,
|
|
2378
2513
|
filePath: c.filePath,
|
|
2379
|
-
line: c.startLine,
|
|
2514
|
+
line: toDisplayLine(c.startLine),
|
|
2380
2515
|
score: Number(c.score.toFixed(2)),
|
|
2381
2516
|
})),
|
|
2382
2517
|
};
|
|
@@ -2540,6 +2675,7 @@ export class LocalBackend {
|
|
|
2540
2675
|
// "fix" enrichment ordering; F3 depends on enrichment-before-early-return.
|
|
2541
2676
|
const epistemicSymType = (resolvedLabel || sym.type || symKind || '');
|
|
2542
2677
|
const epistemicPromise = this.computeEpistemicBoundary(repo, symId, epistemicSymType, (sym.name || sym[1]));
|
|
2678
|
+
const beanMetadataPromise = queryClassBeanMetadata(repo.lbugPath, symId, epistemicSymType);
|
|
2543
2679
|
let methodMetadata;
|
|
2544
2680
|
if (isMethodLike) {
|
|
2545
2681
|
try {
|
|
@@ -2575,7 +2711,7 @@ export class LocalBackend {
|
|
|
2575
2711
|
// dynamic dispatch are not reflected in `incoming`, so the view is a lower
|
|
2576
2712
|
// bound. Additive; never suppresses a field. Resolved from the probe started
|
|
2577
2713
|
// above (concurrent with methodMetadata).
|
|
2578
|
-
const epistemic = await epistemicPromise;
|
|
2714
|
+
const [epistemic, beanMetadata] = await Promise.all([epistemicPromise, beanMetadataPromise]);
|
|
2579
2715
|
return {
|
|
2580
2716
|
status: 'found',
|
|
2581
2717
|
symbol: {
|
|
@@ -2583,10 +2719,11 @@ export class LocalBackend {
|
|
|
2583
2719
|
name: sym.name || sym[1],
|
|
2584
2720
|
kind: symKind,
|
|
2585
2721
|
filePath: sym.filePath || sym[3],
|
|
2586
|
-
startLine: sym.startLine
|
|
2587
|
-
endLine: sym.endLine
|
|
2722
|
+
startLine: toDisplayLine(sym.startLine ?? sym[4]),
|
|
2723
|
+
endLine: toDisplayLine(sym.endLine ?? sym[5]),
|
|
2588
2724
|
...(include_content && (sym.content || sym[6]) ? { content: sym.content || sym[6] } : {}),
|
|
2589
2725
|
...(methodMetadata ? { methodMetadata } : {}),
|
|
2726
|
+
...(beanMetadata ? { bean: beanMetadata } : {}),
|
|
2590
2727
|
},
|
|
2591
2728
|
...epistemic,
|
|
2592
2729
|
incoming: categorize(incomingRows),
|
|
@@ -2660,7 +2797,7 @@ export class LocalBackend {
|
|
|
2660
2797
|
name: c.name,
|
|
2661
2798
|
kind: c.type,
|
|
2662
2799
|
filePath: c.filePath,
|
|
2663
|
-
line: c.startLine,
|
|
2800
|
+
line: toDisplayLine(c.startLine),
|
|
2664
2801
|
score: Number(c.score.toFixed(2)),
|
|
2665
2802
|
})),
|
|
2666
2803
|
},
|
|
@@ -2678,11 +2815,14 @@ export class LocalBackend {
|
|
|
2678
2815
|
return {
|
|
2679
2816
|
anchorClause: 'a.id STARTS WITH $idPrefix AND a.startLine >= $symStart AND a.startLine <= $symEnd',
|
|
2680
2817
|
queryParams: { idPrefix, symStart: sym.startLine + 1, symEnd: sym.endLine + 1 },
|
|
2818
|
+
// Display anchor is 1-based, matching the ambiguous-candidate branch and
|
|
2819
|
+
// the context/query/impact tools (#2380). This is display-only — the
|
|
2820
|
+
// BasicBlock join above uses the raw `sym.startLine + 1` in `symStart`.
|
|
2681
2821
|
anchor: {
|
|
2682
2822
|
file: sym.filePath,
|
|
2683
2823
|
symbol: sym.name,
|
|
2684
|
-
startLine: sym.startLine,
|
|
2685
|
-
endLine: sym.endLine,
|
|
2824
|
+
startLine: toDisplayLine(sym.startLine),
|
|
2825
|
+
endLine: toDisplayLine(sym.endLine),
|
|
2686
2826
|
},
|
|
2687
2827
|
};
|
|
2688
2828
|
}
|
|
@@ -3425,7 +3565,10 @@ export class LocalBackend {
|
|
|
3425
3565
|
/** Guard: ensure a file path resolves within the repo root (prevents path traversal) */
|
|
3426
3566
|
const assertSafePath = (filePath) => {
|
|
3427
3567
|
const full = path.resolve(repo.repoPath, filePath);
|
|
3428
|
-
|
|
3568
|
+
const safePrefix = repo.repoPath.endsWith(path.sep)
|
|
3569
|
+
? repo.repoPath
|
|
3570
|
+
: repo.repoPath + path.sep;
|
|
3571
|
+
if (!full.startsWith(safePrefix) && full !== repo.repoPath) {
|
|
3429
3572
|
throw new Error(`Path traversal blocked: ${filePath}`);
|
|
3430
3573
|
}
|
|
3431
3574
|
return full;
|
|
@@ -3447,28 +3590,13 @@ export class LocalBackend {
|
|
|
3447
3590
|
if (oldName === new_name) {
|
|
3448
3591
|
return { error: 'New name is the same as the current name.' };
|
|
3449
3592
|
}
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
};
|
|
3458
|
-
// The definition itself
|
|
3459
|
-
if (sym.filePath && sym.startLine) {
|
|
3460
|
-
try {
|
|
3461
|
-
const content = await fs.readFile(assertSafePath(sym.filePath), 'utf-8');
|
|
3462
|
-
const lines = content.split('\n');
|
|
3463
|
-
const lineIdx = sym.startLine - 1;
|
|
3464
|
-
if (lineIdx >= 0 && lineIdx < lines.length && lines[lineIdx].includes(oldName)) {
|
|
3465
|
-
const defRegex = new RegExp(`\\b${oldName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'g');
|
|
3466
|
-
addEdit(sym.filePath, sym.startLine, lines[lineIdx].trim(), lines[lineIdx].replace(defRegex, new_name).trim(), 'graph');
|
|
3467
|
-
}
|
|
3468
|
-
}
|
|
3469
|
-
catch (e) {
|
|
3470
|
-
logQueryError('rename:read-definition', e);
|
|
3471
|
-
}
|
|
3593
|
+
const escapedOldName = oldName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
3594
|
+
// Classify each file to rewrite by how it was discovered. Definition and
|
|
3595
|
+
// graph-ref files carry graph confidence; files found only by text search
|
|
3596
|
+
// carry text_search confidence. A graph-classified file is never downgraded.
|
|
3597
|
+
const fileConfidence = new Map();
|
|
3598
|
+
if (sym.filePath) {
|
|
3599
|
+
fileConfidence.set(sym.filePath, 'graph');
|
|
3472
3600
|
}
|
|
3473
3601
|
// All incoming refs from graph (callers, importers, etc.)
|
|
3474
3602
|
const allIncoming = [
|
|
@@ -3477,31 +3605,12 @@ export class LocalBackend {
|
|
|
3477
3605
|
...(lookupResult.incoming.extends || []),
|
|
3478
3606
|
...(lookupResult.incoming.implements || []),
|
|
3479
3607
|
];
|
|
3480
|
-
let graphEdits = changes.size > 0 ? 1 : 0; // count definition edit
|
|
3481
3608
|
for (const ref of allIncoming) {
|
|
3482
|
-
if (
|
|
3483
|
-
|
|
3484
|
-
try {
|
|
3485
|
-
const content = await fs.readFile(assertSafePath(ref.filePath), 'utf-8');
|
|
3486
|
-
const lines = content.split('\n');
|
|
3487
|
-
for (let i = 0; i < lines.length; i++) {
|
|
3488
|
-
if (lines[i].includes(oldName)) {
|
|
3489
|
-
addEdit(ref.filePath, i + 1, lines[i].trim(), lines[i]
|
|
3490
|
-
.replace(new RegExp(`\\b${oldName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'g'), new_name)
|
|
3491
|
-
.trim(), 'graph');
|
|
3492
|
-
graphEdits++;
|
|
3493
|
-
break; // one edit per file from graph refs
|
|
3494
|
-
}
|
|
3495
|
-
}
|
|
3496
|
-
}
|
|
3497
|
-
catch (e) {
|
|
3498
|
-
logQueryError('rename:read-ref', e);
|
|
3609
|
+
if (ref.filePath) {
|
|
3610
|
+
fileConfidence.set(ref.filePath, 'graph');
|
|
3499
3611
|
}
|
|
3500
3612
|
}
|
|
3501
|
-
//
|
|
3502
|
-
let astSearchEdits = 0;
|
|
3503
|
-
const graphFiles = new Set([sym.filePath, ...allIncoming.map((r) => r.filePath)].filter(Boolean));
|
|
3504
|
-
// Simple text search across the repo for the old name (in files not already covered by graph)
|
|
3613
|
+
// Text search for files the graph might have missed entirely.
|
|
3505
3614
|
try {
|
|
3506
3615
|
const { execFileSync } = await import('child_process');
|
|
3507
3616
|
const rgArgs = [
|
|
@@ -3527,65 +3636,199 @@ export class LocalBackend {
|
|
|
3527
3636
|
.filter((f) => f.length > 0);
|
|
3528
3637
|
for (const file of files) {
|
|
3529
3638
|
const normalizedFile = file.replace(/\\/g, '/').replace(/^\.\//, '');
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
const content = await fs.readFile(assertSafePath(normalizedFile), 'utf-8');
|
|
3534
|
-
const lines = content.split('\n');
|
|
3535
|
-
const regex = new RegExp(`\\b${oldName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'g');
|
|
3536
|
-
for (let i = 0; i < lines.length; i++) {
|
|
3537
|
-
regex.lastIndex = 0;
|
|
3538
|
-
if (regex.test(lines[i])) {
|
|
3539
|
-
regex.lastIndex = 0;
|
|
3540
|
-
addEdit(normalizedFile, i + 1, lines[i].trim(), lines[i].replace(regex, new_name).trim(), 'text_search');
|
|
3541
|
-
astSearchEdits++;
|
|
3542
|
-
}
|
|
3543
|
-
}
|
|
3544
|
-
}
|
|
3545
|
-
catch (e) {
|
|
3546
|
-
logQueryError('rename:text-search-read', e);
|
|
3639
|
+
// Never downgrade a graph-classified file to text_search.
|
|
3640
|
+
if (!fileConfidence.has(normalizedFile)) {
|
|
3641
|
+
fileConfidence.set(normalizedFile, 'text_search');
|
|
3547
3642
|
}
|
|
3548
3643
|
}
|
|
3549
3644
|
}
|
|
3550
3645
|
catch (e) {
|
|
3551
3646
|
logQueryError('rename:ripgrep', e);
|
|
3552
3647
|
}
|
|
3553
|
-
//
|
|
3554
|
-
|
|
3555
|
-
|
|
3648
|
+
// Enumerate every `\boldName\b` line in each file to rewrite, so the previewed
|
|
3649
|
+
// file set is exactly the set the apply loop below rewrites. A file with no
|
|
3650
|
+
// matching line is dropped (apply would write nothing to it). `wordTest`
|
|
3651
|
+
// (non-global) probes each line; `wordReplace` (global) rewrites it and is
|
|
3652
|
+
// reused by the apply loop — compiled once each rather than once per line,
|
|
3653
|
+
// and one escaping formula serves both passes.
|
|
3654
|
+
const wordTest = new RegExp(`\\b${escapedOldName}\\b`);
|
|
3655
|
+
const wordReplace = new RegExp(`\\b${escapedOldName}\\b`, 'g');
|
|
3656
|
+
const changes = new Map();
|
|
3657
|
+
for (const [filePath, confidence] of fileConfidence) {
|
|
3658
|
+
try {
|
|
3659
|
+
const content = await fs.readFile(assertSafePath(filePath), 'utf-8');
|
|
3660
|
+
const lines = content.split('\n');
|
|
3661
|
+
const edits = [];
|
|
3662
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3663
|
+
if (!wordTest.test(lines[i])) {
|
|
3664
|
+
continue;
|
|
3665
|
+
}
|
|
3666
|
+
edits.push({
|
|
3667
|
+
line: i + 1,
|
|
3668
|
+
old_text: lines[i].trim(),
|
|
3669
|
+
new_text: lines[i].replace(wordReplace, new_name).trim(),
|
|
3670
|
+
confidence,
|
|
3671
|
+
});
|
|
3672
|
+
}
|
|
3673
|
+
if (edits.length > 0) {
|
|
3674
|
+
changes.set(filePath, { file_path: filePath, edits });
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
catch (e) {
|
|
3678
|
+
logQueryError('rename:enumerate', e);
|
|
3679
|
+
}
|
|
3680
|
+
}
|
|
3681
|
+
// Step 4: Apply or preview.
|
|
3556
3682
|
const failedFiles = [];
|
|
3557
3683
|
if (!dry_run) {
|
|
3558
|
-
|
|
3559
|
-
for (const change of allChanges) {
|
|
3684
|
+
for (const change of changes.values()) {
|
|
3560
3685
|
try {
|
|
3561
3686
|
const fullPath = assertSafePath(change.file_path);
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
content = content.replace(regex, new_name);
|
|
3565
|
-
await fs.writeFile(fullPath, content, 'utf-8');
|
|
3687
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
3688
|
+
await fs.writeFile(fullPath, content.replace(wordReplace, new_name), 'utf-8');
|
|
3566
3689
|
}
|
|
3567
3690
|
catch (e) {
|
|
3568
|
-
// A swallowed write failure must not be reported as
|
|
3569
|
-
//
|
|
3570
|
-
// with the unwritten files listed, rather than masquerading as done.
|
|
3691
|
+
// A swallowed write failure must not be reported as success (#2283):
|
|
3692
|
+
// record the file so the result degrades to 'partial'.
|
|
3571
3693
|
logQueryError('rename:apply-edit', e);
|
|
3572
3694
|
failedFiles.push(change.file_path);
|
|
3573
3695
|
}
|
|
3574
3696
|
}
|
|
3697
|
+
// A file whose write threw did not land, so drop its edits from the
|
|
3698
|
+
// reported result — total_edits/changes must describe what actually
|
|
3699
|
+
// reached disk, not what was attempted (#2605: the report matches reality
|
|
3700
|
+
// even on partial failure). failed_files still names every dropped file.
|
|
3701
|
+
for (const f of failedFiles) {
|
|
3702
|
+
changes.delete(f);
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
// Counts derive from the reported set (dry-run: every enumerated file;
|
|
3706
|
+
// apply: only files that landed), so the graph/text_search split always
|
|
3707
|
+
// sums to total_edits and never overstates a partial apply.
|
|
3708
|
+
const reported = Array.from(changes.values());
|
|
3709
|
+
let graphEdits = 0;
|
|
3710
|
+
let astSearchEdits = 0;
|
|
3711
|
+
for (const change of reported) {
|
|
3712
|
+
for (const edit of change.edits) {
|
|
3713
|
+
if (edit.confidence === 'graph') {
|
|
3714
|
+
graphEdits++;
|
|
3715
|
+
}
|
|
3716
|
+
else {
|
|
3717
|
+
astSearchEdits++;
|
|
3718
|
+
}
|
|
3719
|
+
}
|
|
3575
3720
|
}
|
|
3576
3721
|
return {
|
|
3577
3722
|
status: failedFiles.length > 0 ? 'partial' : 'success',
|
|
3578
3723
|
old_name: oldName,
|
|
3579
3724
|
new_name,
|
|
3580
|
-
files_affected:
|
|
3581
|
-
total_edits:
|
|
3725
|
+
files_affected: reported.length,
|
|
3726
|
+
total_edits: graphEdits + astSearchEdits,
|
|
3582
3727
|
graph_edits: graphEdits,
|
|
3583
3728
|
text_search_edits: astSearchEdits,
|
|
3584
|
-
changes:
|
|
3729
|
+
changes: reported,
|
|
3585
3730
|
applied: !dry_run,
|
|
3586
3731
|
...(failedFiles.length > 0 && { failed_files: failedFiles }),
|
|
3587
3732
|
};
|
|
3588
3733
|
}
|
|
3734
|
+
async moveEntries(repo, params) {
|
|
3735
|
+
await this.ensureInitialized(repo);
|
|
3736
|
+
if (!isLbugReady(repo.lbugPath))
|
|
3737
|
+
return { error: 'LadybugDB not ready. Index may be corrupted.' };
|
|
3738
|
+
const clauses = ["f.language = 'move'"];
|
|
3739
|
+
switch (params?.kind) {
|
|
3740
|
+
case 'entry':
|
|
3741
|
+
clauses.push('f.isEntry = true');
|
|
3742
|
+
break;
|
|
3743
|
+
case 'view':
|
|
3744
|
+
clauses.push('f.isView = true');
|
|
3745
|
+
break;
|
|
3746
|
+
case 'inline':
|
|
3747
|
+
clauses.push('f.isInline = true');
|
|
3748
|
+
break;
|
|
3749
|
+
case 'native':
|
|
3750
|
+
clauses.push('f.isNative = true');
|
|
3751
|
+
break;
|
|
3752
|
+
default:
|
|
3753
|
+
clauses.push('(f.isEntry = true OR f.isView = true)');
|
|
3754
|
+
}
|
|
3755
|
+
const qp = {};
|
|
3756
|
+
if (typeof params?.module === 'string' && params.module) {
|
|
3757
|
+
clauses.push('f.moduleQualifiedName = $module');
|
|
3758
|
+
qp.module = params.module;
|
|
3759
|
+
}
|
|
3760
|
+
const rows = (await executeParameterized(repo.lbugPath, `MATCH (f:Function) WHERE ${clauses.join(' AND ')}
|
|
3761
|
+
RETURN f.name AS name, f.qualifiedName AS qualifiedName, f.filePath AS filePath,
|
|
3762
|
+
f.isEntry AS isEntry, f.isView AS isView,
|
|
3763
|
+
f.isInline AS isInline, f.isNative AS isNative, f.visibility AS visibility,
|
|
3764
|
+
f.acquires AS acquires, f.attributes AS attributes, f.returnType AS returnType
|
|
3765
|
+
ORDER BY f.filePath, f.name`, qp));
|
|
3766
|
+
const attribute = params?.attribute;
|
|
3767
|
+
const filtered = typeof attribute === 'string' && attribute
|
|
3768
|
+
? rows.filter((r) => Array.isArray(r.attributes) && r.attributes.includes(attribute))
|
|
3769
|
+
: rows;
|
|
3770
|
+
return { entries: filtered, count: filtered.length };
|
|
3771
|
+
}
|
|
3772
|
+
async moveResources(repo, params) {
|
|
3773
|
+
await this.ensureInitialized(repo);
|
|
3774
|
+
if (!isLbugReady(repo.lbugPath))
|
|
3775
|
+
return { error: 'LadybugDB not ready. Index may be corrupted.' };
|
|
3776
|
+
const qp = {};
|
|
3777
|
+
let moduleFilter = '';
|
|
3778
|
+
if (typeof params?.module === 'string' && params.module) {
|
|
3779
|
+
moduleFilter = ' AND s.moduleQualifiedName = $module';
|
|
3780
|
+
qp.module = params.module;
|
|
3781
|
+
}
|
|
3782
|
+
const resourceQuery = (label) => `
|
|
3783
|
+
MATCH (s:\`${label}\`) WHERE s.language = 'move' AND s.isResource = true${moduleFilter}
|
|
3784
|
+
RETURN s.name AS name, s.qualifiedName AS qualifiedName, s.filePath AS filePath,
|
|
3785
|
+
s.abilities AS abilities, s.fieldList AS fieldList
|
|
3786
|
+
ORDER BY s.qualifiedName`;
|
|
3787
|
+
const accessorQuery = (label) => `
|
|
3788
|
+
MATCH (f:Function)-[r:CodeRelation]->(s:\`${label}\`)
|
|
3789
|
+
WHERE s.language = 'move' AND s.isResource = true${moduleFilter}
|
|
3790
|
+
AND (r.type = 'READS_RESOURCE' OR r.type = 'WRITES_RESOURCE' OR r.type = 'ACQUIRES')
|
|
3791
|
+
RETURN s.qualifiedName AS resourceQualifiedName, f.qualifiedName AS caller,
|
|
3792
|
+
r.type AS reason, f.isEntry AS isEntry, f.isView AS isView`;
|
|
3793
|
+
const [structs, enums, structAccessors, enumAccessors] = await Promise.all([
|
|
3794
|
+
executeParameterized(repo.lbugPath, resourceQuery('Struct'), qp),
|
|
3795
|
+
executeParameterized(repo.lbugPath, resourceQuery('Enum'), qp),
|
|
3796
|
+
executeParameterized(repo.lbugPath, accessorQuery('Struct'), qp),
|
|
3797
|
+
executeParameterized(repo.lbugPath, accessorQuery('Enum'), qp),
|
|
3798
|
+
]);
|
|
3799
|
+
const rows = [...structs, ...enums].sort((a, b) => String(a.qualifiedName).localeCompare(String(b.qualifiedName)));
|
|
3800
|
+
const accessorsByResource = new Map();
|
|
3801
|
+
for (const row of [...structAccessors, ...enumAccessors]) {
|
|
3802
|
+
const resourceQualifiedName = String(row.resourceQualifiedName ?? '');
|
|
3803
|
+
if (!resourceQualifiedName || !row.caller)
|
|
3804
|
+
continue;
|
|
3805
|
+
const accessors = accessorsByResource.get(resourceQualifiedName) ?? [];
|
|
3806
|
+
accessors.push({
|
|
3807
|
+
caller: row.caller,
|
|
3808
|
+
reason: row.reason,
|
|
3809
|
+
isEntry: row.isEntry,
|
|
3810
|
+
isView: row.isView,
|
|
3811
|
+
});
|
|
3812
|
+
accessorsByResource.set(resourceQualifiedName, accessors);
|
|
3813
|
+
}
|
|
3814
|
+
const resources = rows.map((r) => ({
|
|
3815
|
+
...r,
|
|
3816
|
+
fieldList: Array.isArray(r.fieldList)
|
|
3817
|
+
? r.fieldList.map((v) => String(v).replace(/^['"]|['"]$/g, ''))
|
|
3818
|
+
: r.fieldList,
|
|
3819
|
+
accessors: accessorsByResource.get(String(r.qualifiedName)) ?? [],
|
|
3820
|
+
}));
|
|
3821
|
+
return { resources, count: resources.length };
|
|
3822
|
+
}
|
|
3823
|
+
async moveImpact(repo, params) {
|
|
3824
|
+
const impactParams = {
|
|
3825
|
+
target: params.target,
|
|
3826
|
+
direction: params.direction ?? 'upstream',
|
|
3827
|
+
maxDepth: params.maxDepth,
|
|
3828
|
+
relationTypes: ['CALLS', 'READS_RESOURCE', 'WRITES_RESOURCE', 'ACQUIRES', 'USES_TYPE'],
|
|
3829
|
+
};
|
|
3830
|
+
return this.impact(repo, impactParams);
|
|
3831
|
+
}
|
|
3589
3832
|
async trace(repo, params) {
|
|
3590
3833
|
try {
|
|
3591
3834
|
return await this._traceImpl(repo, params);
|
|
@@ -4016,7 +4259,7 @@ export class LocalBackend {
|
|
|
4016
4259
|
name: c.name,
|
|
4017
4260
|
kind: c.type,
|
|
4018
4261
|
filePath: c.filePath,
|
|
4019
|
-
line: c.startLine,
|
|
4262
|
+
line: toDisplayLine(c.startLine),
|
|
4020
4263
|
score: Number(c.score.toFixed(2)),
|
|
4021
4264
|
})),
|
|
4022
4265
|
};
|
|
@@ -4069,7 +4312,7 @@ export class LocalBackend {
|
|
|
4069
4312
|
name: c.name,
|
|
4070
4313
|
kind: c.type,
|
|
4071
4314
|
filePath: c.filePath,
|
|
4072
|
-
line: c.startLine,
|
|
4315
|
+
line: toDisplayLine(c.startLine),
|
|
4073
4316
|
score: Number(c.score.toFixed(2)),
|
|
4074
4317
|
impactedCount: summary?.impactedCount ?? 0,
|
|
4075
4318
|
risk: summary?.risk ?? 'UNKNOWN',
|
|
@@ -4462,6 +4705,9 @@ export class LocalBackend {
|
|
|
4462
4705
|
const epistemicPromise = opts.skipEpistemic
|
|
4463
4706
|
? Promise.resolve({})
|
|
4464
4707
|
: this.computeEpistemicBoundary(repo, symId, symType, (sym.name || sym[1]));
|
|
4708
|
+
const beanMetadataPromise = opts.skipEpistemic || summaryOnly
|
|
4709
|
+
? Promise.resolve(undefined)
|
|
4710
|
+
: queryClassBeanMetadata(repo.lbugPath, symId, symType);
|
|
4465
4711
|
const impacted = [];
|
|
4466
4712
|
const visited = new Set([symId]);
|
|
4467
4713
|
const pdgBridgeEvidenceById = new Map();
|
|
@@ -4864,13 +5110,14 @@ export class LocalBackend {
|
|
|
4864
5110
|
}
|
|
4865
5111
|
// #1858 — await the epistemic boundary probe kicked off alongside the BFS
|
|
4866
5112
|
// above. Additive: leaves impactedCount and every existing field untouched.
|
|
4867
|
-
const epistemic = await epistemicPromise;
|
|
5113
|
+
const [epistemic, beanMetadata] = await Promise.all([epistemicPromise, beanMetadataPromise]);
|
|
4868
5114
|
const base = {
|
|
4869
5115
|
target: {
|
|
4870
5116
|
id: symId,
|
|
4871
5117
|
name: sym.name || sym[1],
|
|
4872
5118
|
type: symType,
|
|
4873
5119
|
filePath: sym.filePath || sym[2],
|
|
5120
|
+
...(beanMetadata ? { bean: beanMetadata } : {}),
|
|
4874
5121
|
},
|
|
4875
5122
|
direction,
|
|
4876
5123
|
impactedCount: impacted.length,
|