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
package/dist/server/api.d.ts
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* CORS is restricted to localhost, private/LAN networks, and the deployed site.
|
|
9
9
|
*/
|
|
10
10
|
import express from 'express';
|
|
11
|
+
import { type RegistryEntry } from '../storage/repo-manager.js';
|
|
11
12
|
import { type GraphNode, type GraphRelationship } from '../_shared/index.js';
|
|
13
|
+
import { JobManager } from './analyze-job.js';
|
|
12
14
|
/**
|
|
13
15
|
* Determine whether an HTTP Origin header value is allowed by CORS policy.
|
|
14
16
|
*
|
|
@@ -49,6 +51,34 @@ export declare const registerWebUI: (app: express.Express, staticDir: string | n
|
|
|
49
51
|
export declare const writeNdjsonRecord: (res: express.Response, record: GraphStreamRecord, signal?: AbortSignal) => Promise<void>;
|
|
50
52
|
export declare const getNodeQuery: (table: string, includeContent: boolean) => string;
|
|
51
53
|
export declare const streamGraphNdjson: (res: express.Response, includeContent?: boolean, signal?: AbortSignal) => Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Mount an SSE progress endpoint for a JobManager.
|
|
56
|
+
* Handles: initial state, terminal events, heartbeat, event IDs, client disconnect.
|
|
57
|
+
*
|
|
58
|
+
* Terminal payloads carry `repoPath` (the analyzed path) alongside the display
|
|
59
|
+
* `repoName` so clients can reconnect by path identity — with duplicate
|
|
60
|
+
* basenames, a name-only reconnect resolves to the first same-named sibling.
|
|
61
|
+
* Exported for unit tests that lock the wire payload shape.
|
|
62
|
+
*/
|
|
63
|
+
export declare const mountSSEProgress: (app: express.Express, routePath: string, jm: JobManager) => void;
|
|
64
|
+
/**
|
|
65
|
+
* Resolve a `?repo=` request param against the registry in two tiers:
|
|
66
|
+
*
|
|
67
|
+
* 1. Path claim — any input containing a separator ('/' or '\\', which
|
|
68
|
+
* cover path.sep on every platform) is treated as a path claim and
|
|
69
|
+
* resolved by canonical registry path ONLY. A miss fails closed
|
|
70
|
+
* (null, never a basename fallback) so a stale or wrong path can
|
|
71
|
+
* never silently retarget a same-named sibling repo (#2419).
|
|
72
|
+
* Within this tier, only absolute or Windows-shaped ('\\') claims
|
|
73
|
+
* are worth canonicalizing; relative claims like 'org/name' or
|
|
74
|
+
* './repo' are rejected immediately WITHOUT touching the filesystem
|
|
75
|
+
* — canonicalizing them would run an attacker-influenced
|
|
76
|
+
* CWD-relative realpathSync probe on un-rate-limited GET routes,
|
|
77
|
+
* and no legitimate caller sends relative paths.
|
|
78
|
+
* 2. Name fallback — bare names (no separators) keep the legacy
|
|
79
|
+
* basename/name match for older callers.
|
|
80
|
+
*/
|
|
81
|
+
export declare const resolveRegisteredRepoEntry: (repos: RegistryEntry[], repoName?: string) => RegistryEntry | null;
|
|
52
82
|
/**
|
|
53
83
|
* Handle a GET /api/file request body. Extracted from createServer's route
|
|
54
84
|
* registration so it can be unit-tested without spinning up an HTTP server
|
package/dist/server/api.js
CHANGED
|
@@ -12,12 +12,13 @@ import cors from 'cors';
|
|
|
12
12
|
import path from 'path';
|
|
13
13
|
import fs from 'fs/promises';
|
|
14
14
|
import { createRequire } from 'node:module';
|
|
15
|
-
import { loadMeta, listRegisteredRepos, getStoragePath } from '../storage/repo-manager.js';
|
|
15
|
+
import { canonicalizePath, cloneDirBelongsToEntry, loadMeta, saveMeta, listRegisteredRepos, getStoragePath, registryPathEquals, } from '../storage/repo-manager.js';
|
|
16
16
|
import { executeQuery, executePrepared, executeWithReusedStatement, streamQuery, flushWAL, closeLbug, withLbugDb, isReadOnlyDbError, } from '../core/lbug/lbug-adapter.js';
|
|
17
17
|
import { isValidQueryParams } from '../core/lbug/query-params.js';
|
|
18
18
|
import { NODE_TABLES } from '../_shared/index.js';
|
|
19
19
|
import { searchFTSFromLbug } from '../core/search/bm25-index.js';
|
|
20
20
|
import { hybridSearch } from '../core/search/hybrid-search.js';
|
|
21
|
+
import { ftsDegradedWarning } from '../core/search/fts-indexes.js';
|
|
21
22
|
import { LocalBackend } from '../mcp/local/local-backend.js';
|
|
22
23
|
import { mountMCPEndpoints } from './mcp-http.js';
|
|
23
24
|
import { fileURLToPath } from 'url';
|
|
@@ -380,8 +381,13 @@ export const streamGraphNdjson = async (res, includeContent = false, signal) =>
|
|
|
380
381
|
/**
|
|
381
382
|
* Mount an SSE progress endpoint for a JobManager.
|
|
382
383
|
* Handles: initial state, terminal events, heartbeat, event IDs, client disconnect.
|
|
384
|
+
*
|
|
385
|
+
* Terminal payloads carry `repoPath` (the analyzed path) alongside the display
|
|
386
|
+
* `repoName` so clients can reconnect by path identity — with duplicate
|
|
387
|
+
* basenames, a name-only reconnect resolves to the first same-named sibling.
|
|
388
|
+
* Exported for unit tests that lock the wire payload shape.
|
|
383
389
|
*/
|
|
384
|
-
const mountSSEProgress = (app, routePath, jm) => {
|
|
390
|
+
export const mountSSEProgress = (app, routePath, jm) => {
|
|
385
391
|
app.get(routePath, (req, res) => {
|
|
386
392
|
let jobId;
|
|
387
393
|
try {
|
|
@@ -411,6 +417,7 @@ const mountSSEProgress = (app, routePath, jm) => {
|
|
|
411
417
|
eventId++;
|
|
412
418
|
res.write(`id: ${eventId}\nevent: ${job.status}\ndata: ${JSON.stringify({
|
|
413
419
|
repoName: job.repoName,
|
|
420
|
+
repoPath: job.repoPath,
|
|
414
421
|
error: job.error,
|
|
415
422
|
})}\n\n`);
|
|
416
423
|
res.end();
|
|
@@ -434,6 +441,7 @@ const mountSSEProgress = (app, routePath, jm) => {
|
|
|
434
441
|
const eventJob = jm.getJob(jobId);
|
|
435
442
|
res.write(`id: ${eventId}\nevent: ${progress.phase}\ndata: ${JSON.stringify({
|
|
436
443
|
repoName: eventJob?.repoName,
|
|
444
|
+
repoPath: eventJob?.repoPath,
|
|
437
445
|
error: eventJob?.error,
|
|
438
446
|
})}\n\n`);
|
|
439
447
|
clearInterval(heartbeat);
|
|
@@ -476,6 +484,43 @@ const requestedRepo = (req) => {
|
|
|
476
484
|
}
|
|
477
485
|
return undefined;
|
|
478
486
|
};
|
|
487
|
+
const repoParamBasename = (repoName) => repoName.replace(/\\/g, '/').split('/').filter(Boolean).pop() ?? repoName;
|
|
488
|
+
/**
|
|
489
|
+
* Resolve a `?repo=` request param against the registry in two tiers:
|
|
490
|
+
*
|
|
491
|
+
* 1. Path claim — any input containing a separator ('/' or '\\', which
|
|
492
|
+
* cover path.sep on every platform) is treated as a path claim and
|
|
493
|
+
* resolved by canonical registry path ONLY. A miss fails closed
|
|
494
|
+
* (null, never a basename fallback) so a stale or wrong path can
|
|
495
|
+
* never silently retarget a same-named sibling repo (#2419).
|
|
496
|
+
* Within this tier, only absolute or Windows-shaped ('\\') claims
|
|
497
|
+
* are worth canonicalizing; relative claims like 'org/name' or
|
|
498
|
+
* './repo' are rejected immediately WITHOUT touching the filesystem
|
|
499
|
+
* — canonicalizing them would run an attacker-influenced
|
|
500
|
+
* CWD-relative realpathSync probe on un-rate-limited GET routes,
|
|
501
|
+
* and no legitimate caller sends relative paths.
|
|
502
|
+
* 2. Name fallback — bare names (no separators) keep the legacy
|
|
503
|
+
* basename/name match for older callers.
|
|
504
|
+
*/
|
|
505
|
+
export const resolveRegisteredRepoEntry = (repos, repoName) => {
|
|
506
|
+
if (!repoName)
|
|
507
|
+
return repos[0] ?? null;
|
|
508
|
+
const looksLikePath = path.isAbsolute(repoName) || repoName.includes('/') || repoName.includes('\\');
|
|
509
|
+
if (looksLikePath) {
|
|
510
|
+
// Relative path claims fail closed with zero filesystem probes.
|
|
511
|
+
if (!path.isAbsolute(repoName) && !repoName.includes('\\'))
|
|
512
|
+
return null;
|
|
513
|
+
const requestedPath = canonicalizePath(repoName);
|
|
514
|
+
const pathMatch = repos.find((r) => registryPathEquals(canonicalizePath(r.path), requestedPath));
|
|
515
|
+
if (pathMatch)
|
|
516
|
+
return pathMatch;
|
|
517
|
+
return null;
|
|
518
|
+
}
|
|
519
|
+
const normalizedName = repoParamBasename(repoName);
|
|
520
|
+
return (repos.find((r) => r.name === normalizedName) ||
|
|
521
|
+
repos.find((r) => r.name.toLowerCase() === normalizedName.toLowerCase()) ||
|
|
522
|
+
null);
|
|
523
|
+
};
|
|
479
524
|
/**
|
|
480
525
|
* Handle a GET /api/file request body. Extracted from createServer's route
|
|
481
526
|
* registration so it can be unit-tested without spinning up an HTTP server
|
|
@@ -678,7 +723,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
678
723
|
// Initialize MCP backend (multi-repo, shared across all MCP sessions)
|
|
679
724
|
const backend = new LocalBackend();
|
|
680
725
|
await backend.init();
|
|
681
|
-
const cleanupMcp = mountMCPEndpoints(app, backend);
|
|
726
|
+
const cleanupMcp = await mountMCPEndpoints(app, backend);
|
|
682
727
|
const jobManager = new JobManager();
|
|
683
728
|
// Backstop: remove any upload staging dirs orphaned by a previous crash.
|
|
684
729
|
void sweepStaleUploads().catch(() => { });
|
|
@@ -702,6 +747,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
702
747
|
backend,
|
|
703
748
|
acquireRepoLock,
|
|
704
749
|
releaseRepoLock,
|
|
750
|
+
closeDbHandle: closeLbug,
|
|
705
751
|
});
|
|
706
752
|
/**
|
|
707
753
|
* Maximum time the hold-queue will wait for an active analysis job to complete.
|
|
@@ -712,19 +758,8 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
712
758
|
// Pass `req` to enable early exit if the client disconnects during the hold-queue wait.
|
|
713
759
|
const resolveRepo = async (repoName, isRetry = false, req) => {
|
|
714
760
|
const repos = await listRegisteredRepos();
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
// e.g. "C:\Users\LENOVO\.gitnexus\repos\todo.txt-cli" -> "todo.txt-cli"
|
|
718
|
-
const normalizedName = repoName ? path.basename(repoName) : undefined;
|
|
719
|
-
if (normalizedName) {
|
|
720
|
-
found =
|
|
721
|
-
repos.find((r) => r.name === normalizedName) ||
|
|
722
|
-
repos.find((r) => r.name.toLowerCase() === normalizedName.toLowerCase()) ||
|
|
723
|
-
null;
|
|
724
|
-
}
|
|
725
|
-
else if (repos.length > 0) {
|
|
726
|
-
found = repos[0]; // default to first repo
|
|
727
|
-
}
|
|
761
|
+
const found = resolveRegisteredRepoEntry(repos, repoName);
|
|
762
|
+
const normalizedName = repoName ? repoParamBasename(repoName) : undefined;
|
|
728
763
|
// If not yet in the registry, check whether a background job is actively cloning or
|
|
729
764
|
// analyzing this repo. Hold the connection open (up to 5 minutes) until it completes.
|
|
730
765
|
// We only wait for in-progress jobs ('queued'|'cloning'|'analyzing') — a 'complete' job
|
|
@@ -757,7 +792,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
757
792
|
if (currentJob.status === 'complete') {
|
|
758
793
|
await backend.init();
|
|
759
794
|
const freshRepos = await listRegisteredRepos();
|
|
760
|
-
return freshRepos
|
|
795
|
+
return resolveRegisteredRepoEntry(freshRepos, repoName);
|
|
761
796
|
}
|
|
762
797
|
await new Promise((r) => setTimeout(r, 1000));
|
|
763
798
|
}
|
|
@@ -774,7 +809,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
774
809
|
logger.debug({ repoName: String(normalizedName).replace(/[\r\n]/g, ' ') }, '[debug] resolveRepo 404, triggering deep init');
|
|
775
810
|
}
|
|
776
811
|
await backend.init();
|
|
777
|
-
return await resolveRepo(
|
|
812
|
+
return await resolveRepo(repoName, true, req);
|
|
778
813
|
}
|
|
779
814
|
return found;
|
|
780
815
|
};
|
|
@@ -826,6 +861,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
826
861
|
res.json(repos.map((r) => ({
|
|
827
862
|
name: r.name,
|
|
828
863
|
path: r.path,
|
|
864
|
+
repoPath: r.path,
|
|
829
865
|
indexedAt: r.indexedAt,
|
|
830
866
|
lastCommit: r.lastCommit,
|
|
831
867
|
stats: r.stats,
|
|
@@ -836,7 +872,11 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
836
872
|
}
|
|
837
873
|
});
|
|
838
874
|
// Get repo info
|
|
839
|
-
|
|
875
|
+
// Rate-limited (CodeQL js/missing-rate-limiting): resolveRepo canonicalizes
|
|
876
|
+
// the attacker-supplied ?repo= param (realpathSync probe for absolute /
|
|
877
|
+
// Windows-shaped claims). Default 60 rpm/IP — web callers hit this route
|
|
878
|
+
// only on connect/switch, never in a polling loop.
|
|
879
|
+
app.get('/api/repo', createRouteLimiter(), async (req, res) => {
|
|
840
880
|
try {
|
|
841
881
|
const entry = await resolveRepo(requestedRepo(req), false, req);
|
|
842
882
|
if (!entry) {
|
|
@@ -906,7 +946,10 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
906
946
|
catch {
|
|
907
947
|
/* repo name not eligible for a clone dir (local repo) */
|
|
908
948
|
}
|
|
909
|
-
|
|
949
|
+
// Only remove the clone dir when it is *this* entry's path — a local
|
|
950
|
+
// repo registered under the same name would otherwise take a cloned
|
|
951
|
+
// sibling's checkout down with it (see cloneDirBelongsToEntry).
|
|
952
|
+
if (cloneDir && cloneDirBelongsToEntry(cloneDir, entry.path)) {
|
|
910
953
|
try {
|
|
911
954
|
const stat = await fs.stat(cloneDir);
|
|
912
955
|
if (stat.isDirectory()) {
|
|
@@ -921,7 +964,10 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
921
964
|
// UPLOAD_ROOT. Drive this off entry.path (not a name-rederived dir) so
|
|
922
965
|
// a same-named clone is never affected.
|
|
923
966
|
const resolvedEntry = path.resolve(entry.path);
|
|
924
|
-
|
|
967
|
+
const safeUploadRoot = UPLOAD_ROOT.endsWith(path.sep)
|
|
968
|
+
? UPLOAD_ROOT
|
|
969
|
+
: UPLOAD_ROOT + path.sep;
|
|
970
|
+
if (resolvedEntry === UPLOAD_ROOT || resolvedEntry.startsWith(safeUploadRoot)) {
|
|
925
971
|
await fs.rm(resolvedEntry, { recursive: true, force: true }).catch(() => { });
|
|
926
972
|
}
|
|
927
973
|
// 3. Unregister from the global registry
|
|
@@ -1140,8 +1186,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1140
1186
|
}, { readOnly: true });
|
|
1141
1187
|
const response = { results: results.searchResults ?? results };
|
|
1142
1188
|
if (results.ftsAvailable === false) {
|
|
1143
|
-
response.warning =
|
|
1144
|
-
'FTS indexes missing — keyword search degraded. Run: gitnexus analyze --repair-fts (or gitnexus analyze --force) to rebuild indexes.';
|
|
1189
|
+
response.warning = ftsDegradedWarning();
|
|
1145
1190
|
}
|
|
1146
1191
|
res.json(response);
|
|
1147
1192
|
}
|
|
@@ -1219,7 +1264,8 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1219
1264
|
const filePath = row.filePath || '';
|
|
1220
1265
|
const fullPath = path.resolve(repoRoot, filePath);
|
|
1221
1266
|
// Path traversal guard
|
|
1222
|
-
|
|
1267
|
+
const safeRepoRoot = repoRoot.endsWith(path.sep) ? repoRoot : repoRoot + path.sep;
|
|
1268
|
+
if (!fullPath.startsWith(safeRepoRoot) && fullPath !== repoRoot)
|
|
1223
1269
|
continue;
|
|
1224
1270
|
let content;
|
|
1225
1271
|
try {
|
|
@@ -1477,16 +1523,14 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1477
1523
|
status: 'analyzing',
|
|
1478
1524
|
progress: { phase: 'analyzing', percent: 0, message: 'Starting embedding generation...' },
|
|
1479
1525
|
});
|
|
1526
|
+
const embedController = new AbortController();
|
|
1527
|
+
embedJobManager.registerAbortController(job.id, embedController);
|
|
1480
1528
|
// 30-minute timeout for embedding jobs (same as analyze jobs)
|
|
1481
1529
|
const EMBED_TIMEOUT_MS = 30 * 60 * 1000;
|
|
1482
1530
|
const embedTimeout = setTimeout(() => {
|
|
1483
1531
|
const current = embedJobManager.getJob(job.id);
|
|
1484
1532
|
if (current && current.status !== 'complete' && current.status !== 'failed') {
|
|
1485
|
-
|
|
1486
|
-
embedJobManager.updateJob(job.id, {
|
|
1487
|
-
status: 'failed',
|
|
1488
|
-
error: 'Embedding timed out (30 minute limit)',
|
|
1489
|
-
});
|
|
1533
|
+
embedJobManager.cancelJob(job.id, 'Embedding timed out (30 minute limit)');
|
|
1490
1534
|
}
|
|
1491
1535
|
}, EMBED_TIMEOUT_MS);
|
|
1492
1536
|
// Run embedding pipeline asynchronously
|
|
@@ -1495,6 +1539,36 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1495
1539
|
const lbugPath = path.join(entry.storagePath, 'lbug');
|
|
1496
1540
|
await withLbugDb(lbugPath, async () => {
|
|
1497
1541
|
const { runEmbeddingPipeline } = await import('../core/embeddings/embedding-pipeline.js');
|
|
1542
|
+
const { resolveEmbeddingIdentity } = await import('../core/embeddings/embedding-identity.js');
|
|
1543
|
+
const embeddingIdentity = resolveEmbeddingIdentity();
|
|
1544
|
+
let embeddingMeta = await loadMeta(entry.storagePath);
|
|
1545
|
+
if (!embeddingMeta) {
|
|
1546
|
+
throw new Error('Repository metadata is missing; run gitnexus analyze first');
|
|
1547
|
+
}
|
|
1548
|
+
const priorCheckpoint = embeddingMeta.embeddingCheckpoint;
|
|
1549
|
+
if (priorCheckpoint && priorCheckpoint.provider !== embeddingIdentity.provider) {
|
|
1550
|
+
throw new Error('Cannot resume embedding checkpoint: the embedding provider configuration differs.');
|
|
1551
|
+
}
|
|
1552
|
+
if (priorCheckpoint &&
|
|
1553
|
+
(priorCheckpoint.model !== embeddingIdentity.model ||
|
|
1554
|
+
priorCheckpoint.dimensions !== embeddingIdentity.dimensions)) {
|
|
1555
|
+
throw new Error(`Cannot resume embedding checkpoint: it uses ${priorCheckpoint.model} at ` +
|
|
1556
|
+
`${priorCheckpoint.dimensions} dimensions, but this run resolves ` +
|
|
1557
|
+
`${embeddingIdentity.model} at ${embeddingIdentity.dimensions}.`);
|
|
1558
|
+
}
|
|
1559
|
+
const forceReembedNodeIds = new Set(priorCheckpoint?.pendingNodeIds ?? []);
|
|
1560
|
+
const saveEmbeddingCheckpoint = async (checkpoint, pendingNodeIds) => {
|
|
1561
|
+
embeddingMeta = {
|
|
1562
|
+
...embeddingMeta,
|
|
1563
|
+
embeddingCheckpoint: {
|
|
1564
|
+
at: new Date().toISOString(),
|
|
1565
|
+
...checkpoint,
|
|
1566
|
+
...embeddingIdentity,
|
|
1567
|
+
pendingNodeIds,
|
|
1568
|
+
},
|
|
1569
|
+
};
|
|
1570
|
+
await saveMeta(entry.storagePath, embeddingMeta);
|
|
1571
|
+
};
|
|
1498
1572
|
// Fetch existing content hashes for incremental embedding.
|
|
1499
1573
|
// Delegated to lbug-adapter which owns the DB query logic and legacy-fallback handling.
|
|
1500
1574
|
const { fetchExistingEmbeddingHashes } = await import('../core/lbug/lbug-adapter.js');
|
|
@@ -1520,15 +1594,25 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1520
1594
|
});
|
|
1521
1595
|
}, {}, // config: use defaults
|
|
1522
1596
|
undefined, // skipNodeIds
|
|
1523
|
-
existingEmbeddings
|
|
1597
|
+
existingEmbeddings, {
|
|
1598
|
+
signal: embedController.signal,
|
|
1599
|
+
forceReembedNodeIds,
|
|
1600
|
+
onCheckpointWindowStart: async ({ nodeIds, ...checkpoint }) => {
|
|
1601
|
+
await saveEmbeddingCheckpoint(checkpoint, nodeIds);
|
|
1602
|
+
},
|
|
1603
|
+
onCheckpoint: async (checkpoint) => {
|
|
1604
|
+
await flushWAL();
|
|
1605
|
+
await saveEmbeddingCheckpoint(checkpoint, []);
|
|
1606
|
+
},
|
|
1607
|
+
});
|
|
1524
1608
|
// Flush WAL so subsequent /api/search requests see the new
|
|
1525
1609
|
// embeddings immediately (#1149). In the CLI path closeLbug()
|
|
1526
1610
|
// handles this during process exit, but the server keeps the
|
|
1527
1611
|
// connection open for other routes — a CHECKPOINT is enough.
|
|
1528
1612
|
await flushWAL();
|
|
1613
|
+
embeddingMeta = { ...embeddingMeta, embeddingCheckpoint: undefined };
|
|
1614
|
+
await saveMeta(entry.storagePath, embeddingMeta);
|
|
1529
1615
|
});
|
|
1530
|
-
clearTimeout(embedTimeout);
|
|
1531
|
-
releaseRepoLock(repoLockPath);
|
|
1532
1616
|
// Don't overwrite 'failed' if the job was cancelled while the pipeline was running
|
|
1533
1617
|
const current = embedJobManager.getJob(job.id);
|
|
1534
1618
|
if (!current || current.status !== 'failed') {
|
|
@@ -1536,8 +1620,6 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1536
1620
|
}
|
|
1537
1621
|
}
|
|
1538
1622
|
catch (err) {
|
|
1539
|
-
clearTimeout(embedTimeout);
|
|
1540
|
-
releaseRepoLock(repoLockPath);
|
|
1541
1623
|
const current = embedJobManager.getJob(job.id);
|
|
1542
1624
|
if (!current || current.status !== 'failed') {
|
|
1543
1625
|
embedJobManager.updateJob(job.id, {
|
|
@@ -1546,6 +1628,10 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1546
1628
|
});
|
|
1547
1629
|
}
|
|
1548
1630
|
}
|
|
1631
|
+
finally {
|
|
1632
|
+
clearTimeout(embedTimeout);
|
|
1633
|
+
releaseRepoLock(repoLockPath);
|
|
1634
|
+
}
|
|
1549
1635
|
})();
|
|
1550
1636
|
res.status(202).json({ jobId: job.id, status: 'analyzing' });
|
|
1551
1637
|
}
|
|
@@ -9,4 +9,4 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { Express } from 'express';
|
|
11
11
|
import type { LocalBackend } from '../mcp/local/local-backend.js';
|
|
12
|
-
export declare function mountMCPEndpoints(app: Express, backend: LocalBackend): () => Promise<void
|
|
12
|
+
export declare function mountMCPEndpoints(app: Express, backend: LocalBackend): Promise<() => Promise<void>>;
|
package/dist/server/mcp-http.js
CHANGED
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
* Used by server/api.ts to wire up the full web server.
|
|
9
9
|
*/
|
|
10
10
|
import { createStreamableHttpHandler } from '../mcp/http-transport.js';
|
|
11
|
+
import { createMcpRepositoryPolicy } from '../mcp/repository-policy.js';
|
|
11
12
|
import { logger } from '../core/logger.js';
|
|
12
|
-
export function mountMCPEndpoints(app, backend) {
|
|
13
|
-
const
|
|
13
|
+
export async function mountMCPEndpoints(app, backend) {
|
|
14
|
+
const repositoryPolicy = await createMcpRepositoryPolicy(backend);
|
|
15
|
+
const { handler, cleanup } = createStreamableHttpHandler(backend, { repositoryPolicy });
|
|
14
16
|
app.all('/api/mcp', (req, res) => {
|
|
15
17
|
void handler(req, res).catch((err) => {
|
|
16
18
|
logger.error({ err }, 'MCP HTTP request failed:');
|
|
@@ -65,7 +65,8 @@ export function resolveContainedDest(stageRoot, rel) {
|
|
|
65
65
|
}
|
|
66
66
|
const dest = path.resolve(stageRoot, segments.join(path.sep));
|
|
67
67
|
// Suffix path.sep so a sibling prefix (/sandbox-evil vs /sandbox) can't pass.
|
|
68
|
-
|
|
68
|
+
const safePrefix = stageRoot.endsWith(path.sep) ? stageRoot : stageRoot + path.sep;
|
|
69
|
+
if (dest !== stageRoot && !dest.startsWith(safePrefix)) {
|
|
69
70
|
throw new BadRequestError('Upload path escapes the sandbox');
|
|
70
71
|
}
|
|
71
72
|
return dest;
|
|
@@ -77,7 +77,8 @@ export function assertSafePath(rawPath, root) {
|
|
|
77
77
|
}
|
|
78
78
|
const resolvedRoot = path.resolve(root);
|
|
79
79
|
const fullPath = path.resolve(resolvedRoot, rawPath);
|
|
80
|
-
|
|
80
|
+
const safePrefix = resolvedRoot.endsWith(path.sep) ? resolvedRoot : resolvedRoot + path.sep;
|
|
81
|
+
if (fullPath !== resolvedRoot && !fullPath.startsWith(safePrefix)) {
|
|
81
82
|
throw new ForbiddenError('Path traversal denied');
|
|
82
83
|
}
|
|
83
84
|
return fullPath;
|
package/dist/storage/git.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when the working tree has uncommitted changes that analyze would
|
|
3
|
+
* re-index, even at a matching HEAD. Excludes the paths GitNexus writes during
|
|
4
|
+
* analyze (.gitnexus/, .claude/, .cursor/, AGENTS.md, CLAUDE.md) so its own
|
|
5
|
+
* output never counts as dirty (regression vs PR #1233 behavior). Conservative
|
|
6
|
+
* on any git failure. Shared so `analyze`'s fast-path gate and `status`'s
|
|
7
|
+
* freshness report agree on what "dirty" means.
|
|
8
|
+
*/
|
|
9
|
+
export declare const isWorkingTreeDirty: (repoPath: string) => boolean;
|
|
1
10
|
export declare const isGitRepo: (repoPath: string) => boolean;
|
|
2
11
|
export declare const getCurrentCommit: (repoPath: string) => string;
|
|
3
12
|
/**
|
|
@@ -56,6 +65,28 @@ export declare const getGitRoot: (fromPath: string) => string | null;
|
|
|
56
65
|
* path if the caller later resolved it from a different directory.
|
|
57
66
|
*/
|
|
58
67
|
export declare const getCanonicalRepoRoot: (fromPath: string) => string | null;
|
|
68
|
+
/**
|
|
69
|
+
* Path to the repo's `$GIT_COMMON_DIR/info/exclude` file — git's own
|
|
70
|
+
* per-repo, untracked exclude list (same tier as `.gitignore` in
|
|
71
|
+
* precedence, but never committed, so it works even when the caller has
|
|
72
|
+
* no write access to the repo's tracked content). Shared across every
|
|
73
|
+
* linked worktree of a repo, matching git's own resolution (#2606).
|
|
74
|
+
*
|
|
75
|
+
* Returns `null` when `fromPath` is not inside a git repository or `git`
|
|
76
|
+
* is unavailable; callers should treat that the same as "no file".
|
|
77
|
+
*/
|
|
78
|
+
export declare const getGitInfoExcludePath: (fromPath: string) => string | null;
|
|
79
|
+
/**
|
|
80
|
+
* Path to git's own global, all-repos ignore file: the value of
|
|
81
|
+
* `core.excludesFile` (any config scope — system/global/local, resolved
|
|
82
|
+
* the same way `git` itself would from `fromPath`), or git's documented
|
|
83
|
+
* default of `$XDG_CONFIG_HOME/git/ignore` when unset (gitignore(5)).
|
|
84
|
+
* Lowest-precedence source, mirroring git's own behavior (#2606).
|
|
85
|
+
*
|
|
86
|
+
* Never throws: an unset key or unavailable `git` falls through to the
|
|
87
|
+
* default path, which is always computable without `git`.
|
|
88
|
+
*/
|
|
89
|
+
export declare const getCoreExcludesFilePath: (fromPath: string) => string;
|
|
59
90
|
/**
|
|
60
91
|
* Resolve `fromPath` to the directory whose basename should drive the
|
|
61
92
|
* registry name (#1259) — the *identity root*. Three outcomes:
|
package/dist/storage/git.js
CHANGED
|
@@ -1,8 +1,44 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
1
|
+
import { execFileSync, execSync } from 'child_process';
|
|
2
2
|
import { statSync } from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
4
5
|
// Git utilities for repository detection, commit tracking, and diff analysis
|
|
5
6
|
const chompGitOutput = (value) => value.toString().replace(/\r?\n$/, '');
|
|
7
|
+
/**
|
|
8
|
+
* True when the working tree has uncommitted changes that analyze would
|
|
9
|
+
* re-index, even at a matching HEAD. Excludes the paths GitNexus writes during
|
|
10
|
+
* analyze (.gitnexus/, .claude/, .cursor/, AGENTS.md, CLAUDE.md) so its own
|
|
11
|
+
* output never counts as dirty (regression vs PR #1233 behavior). Conservative
|
|
12
|
+
* on any git failure. Shared so `analyze`'s fast-path gate and `status`'s
|
|
13
|
+
* freshness report agree on what "dirty" means.
|
|
14
|
+
*/
|
|
15
|
+
export const isWorkingTreeDirty = (repoPath) => {
|
|
16
|
+
try {
|
|
17
|
+
const out = execFileSync('git', [
|
|
18
|
+
'status',
|
|
19
|
+
'--porcelain',
|
|
20
|
+
'--',
|
|
21
|
+
'.',
|
|
22
|
+
':(exclude).gitnexus',
|
|
23
|
+
':(exclude).gitnexus/**',
|
|
24
|
+
':(exclude).claude',
|
|
25
|
+
':(exclude).claude/**',
|
|
26
|
+
':(exclude).cursor',
|
|
27
|
+
':(exclude).cursor/**',
|
|
28
|
+
':(exclude)AGENTS.md',
|
|
29
|
+
':(exclude)CLAUDE.md',
|
|
30
|
+
], {
|
|
31
|
+
cwd: repoPath,
|
|
32
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
33
|
+
windowsHide: true,
|
|
34
|
+
encoding: 'utf8',
|
|
35
|
+
});
|
|
36
|
+
return out.trim().length > 0;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return true; // conservative on git failure
|
|
40
|
+
}
|
|
41
|
+
};
|
|
6
42
|
export const isGitRepo = (repoPath) => {
|
|
7
43
|
try {
|
|
8
44
|
execSync('git rev-parse --is-inside-work-tree', {
|
|
@@ -163,6 +199,80 @@ export const getCanonicalRepoRoot = (fromPath) => {
|
|
|
163
199
|
return null;
|
|
164
200
|
}
|
|
165
201
|
};
|
|
202
|
+
// getGitInfoExcludePath/getCoreExcludesFilePath are called once per repo
|
|
203
|
+
// PER language/contract extractor during group sync (#2606) — an N-repo
|
|
204
|
+
// group fans out to 6+ extractors each calling these, so an uncached
|
|
205
|
+
// execSync per call turns into O(extractors × repos) blocking subprocess
|
|
206
|
+
// spawns. Both resolve to the same value for the same fromPath for the
|
|
207
|
+
// life of the process (git config/exclude files don't change mid-run), so
|
|
208
|
+
// memoize by fromPath. ponytail: process-lifetime cache, never invalidated
|
|
209
|
+
// — fine for one-shot CLI runs; the long-lived MCP server would need a
|
|
210
|
+
// TTL or explicit invalidation if a user edits core.excludesFile mid-session.
|
|
211
|
+
const gitInfoExcludePathCache = new Map();
|
|
212
|
+
const coreExcludesFilePathCache = new Map();
|
|
213
|
+
/**
|
|
214
|
+
* Path to the repo's `$GIT_COMMON_DIR/info/exclude` file — git's own
|
|
215
|
+
* per-repo, untracked exclude list (same tier as `.gitignore` in
|
|
216
|
+
* precedence, but never committed, so it works even when the caller has
|
|
217
|
+
* no write access to the repo's tracked content). Shared across every
|
|
218
|
+
* linked worktree of a repo, matching git's own resolution (#2606).
|
|
219
|
+
*
|
|
220
|
+
* Returns `null` when `fromPath` is not inside a git repository or `git`
|
|
221
|
+
* is unavailable; callers should treat that the same as "no file".
|
|
222
|
+
*/
|
|
223
|
+
export const getGitInfoExcludePath = (fromPath) => {
|
|
224
|
+
const cached = gitInfoExcludePathCache.get(fromPath);
|
|
225
|
+
if (cached !== undefined)
|
|
226
|
+
return cached;
|
|
227
|
+
let result;
|
|
228
|
+
try {
|
|
229
|
+
const commonDir = chompGitOutput(execSync('git rev-parse --path-format=absolute --git-common-dir', {
|
|
230
|
+
cwd: fromPath,
|
|
231
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
232
|
+
windowsHide: true,
|
|
233
|
+
}));
|
|
234
|
+
result = commonDir ? path.join(path.resolve(commonDir), 'info', 'exclude') : null;
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
result = null;
|
|
238
|
+
}
|
|
239
|
+
gitInfoExcludePathCache.set(fromPath, result);
|
|
240
|
+
return result;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Path to git's own global, all-repos ignore file: the value of
|
|
244
|
+
* `core.excludesFile` (any config scope — system/global/local, resolved
|
|
245
|
+
* the same way `git` itself would from `fromPath`), or git's documented
|
|
246
|
+
* default of `$XDG_CONFIG_HOME/git/ignore` when unset (gitignore(5)).
|
|
247
|
+
* Lowest-precedence source, mirroring git's own behavior (#2606).
|
|
248
|
+
*
|
|
249
|
+
* Never throws: an unset key or unavailable `git` falls through to the
|
|
250
|
+
* default path, which is always computable without `git`.
|
|
251
|
+
*/
|
|
252
|
+
export const getCoreExcludesFilePath = (fromPath) => {
|
|
253
|
+
const cached = coreExcludesFilePathCache.get(fromPath);
|
|
254
|
+
if (cached !== undefined)
|
|
255
|
+
return cached;
|
|
256
|
+
let result;
|
|
257
|
+
try {
|
|
258
|
+
const configured = chompGitOutput(execSync('git config --get --type=path core.excludesFile', {
|
|
259
|
+
cwd: fromPath,
|
|
260
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
261
|
+
windowsHide: true,
|
|
262
|
+
}));
|
|
263
|
+
if (configured)
|
|
264
|
+
result = configured;
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// Unset, or git unavailable — fall through to git's documented default.
|
|
268
|
+
}
|
|
269
|
+
if (!result) {
|
|
270
|
+
const xdgConfigHome = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config');
|
|
271
|
+
result = path.join(xdgConfigHome, 'git', 'ignore');
|
|
272
|
+
}
|
|
273
|
+
coreExcludesFilePathCache.set(fromPath, result);
|
|
274
|
+
return result;
|
|
275
|
+
};
|
|
166
276
|
/**
|
|
167
277
|
* Resolve `fromPath` to the directory whose basename should drive the
|
|
168
278
|
* registry name (#1259) — the *identity root*. Three outcomes:
|
|
@@ -52,7 +52,13 @@ import { fileURLToPath } from 'url';
|
|
|
52
52
|
// the main thread (the #1983 OOM). Because the two stores share this version,
|
|
53
53
|
// any future change to the `ParsedFile` serialization shape MUST bump
|
|
54
54
|
// SCHEMA_BUMP so both invalidate in lockstep.
|
|
55
|
-
|
|
55
|
+
// v20: Java/Kotlin capture side-channels persist package and class-annotation
|
|
56
|
+
// facts for shared Spring Bean resolution.
|
|
57
|
+
// v19: Java enum constant bodies emit E$N Class nodes; anonymous naming uses
|
|
58
|
+
// JLS 13.1 immediate-host chains (#2555).
|
|
59
|
+
// v18: Worker$N anonymous bodies. v17: callable-value-flow operand identity.
|
|
60
|
+
// v16: direct callee identity.
|
|
61
|
+
const SCHEMA_BUMP = 20;
|
|
56
62
|
const GITNEXUS_PKG_VERSION = (() => {
|
|
57
63
|
try {
|
|
58
64
|
// package.json sits at gitnexus/package.json — two levels up from
|
|
@@ -100,6 +100,14 @@ export declare const persistParsedFileShardSync: (storagePath: string, shardId:
|
|
|
100
100
|
export declare const loadParsedFilesForPaths: (storagePath: string, wantPaths: ReadonlySet<string>) => Promise<Map<string, ParsedFile>>;
|
|
101
101
|
/** Durable store dir — a sibling of `parsedfile-store/`, NEVER cleared per run. */
|
|
102
102
|
export declare const getDurableParsedFileDir: (storagePath: string) => string;
|
|
103
|
+
/**
|
|
104
|
+
* Start a fresh durable generation for one content-addressed parse chunk.
|
|
105
|
+
* The main thread calls this once before dispatching a cache miss, before any
|
|
106
|
+
* worker can write that chunk. Recreating the directory immediately keeps the
|
|
107
|
+
* worker-side mkdir memoization valid while preventing old worker shard names
|
|
108
|
+
* from accumulating across analyses.
|
|
109
|
+
*/
|
|
110
|
+
export declare const prepareDurableParsedFileChunk: (durableDir: string, chunkHash: string) => Promise<void>;
|
|
103
111
|
/**
|
|
104
112
|
* Synchronous durable-shard writer for use INSIDE a parse worker, alongside
|
|
105
113
|
* {@link persistParsedFileShardSync}. Writes the SAME bytes to a content-addressed
|