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/mcp/server.d.ts
CHANGED
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
14
14
|
import type { LocalBackend } from './local/local-backend.js';
|
|
15
|
+
import { McpRepositoryPolicy } from './repository-policy.js';
|
|
15
16
|
/**
|
|
16
17
|
* Create a configured MCP Server with all handlers registered.
|
|
17
18
|
* Transport-agnostic — caller connects the desired transport.
|
|
18
19
|
*/
|
|
19
|
-
export declare function createMCPServer(backend: LocalBackend
|
|
20
|
+
export declare function createMCPServer(backend: LocalBackend, options?: {
|
|
21
|
+
repositoryPolicy?: McpRepositoryPolicy;
|
|
22
|
+
}): Server;
|
|
20
23
|
/** Conventional 128 + signal-number exit codes for graceful termination. */
|
|
21
24
|
export declare const SHUTDOWN_EXIT_CODES: {
|
|
22
25
|
readonly SIGINT: 130;
|
|
@@ -34,5 +37,5 @@ type SignalRegistrar = (event: 'SIGINT' | 'SIGTERM', listener: (...args: unknown
|
|
|
34
37
|
* mapping can be unit-tested without touching the real process.
|
|
35
38
|
*/
|
|
36
39
|
export declare function installSignalShutdown(shutdown: (exitCode?: number) => unknown, on?: SignalRegistrar): void;
|
|
37
|
-
export declare function startMCPServer(backend: LocalBackend): Promise<void>;
|
|
40
|
+
export declare function startMCPServer(backend: LocalBackend, repositoryPolicy?: McpRepositoryPolicy): Promise<void>;
|
|
38
41
|
export {};
|
package/dist/mcp/server.js
CHANGED
|
@@ -17,6 +17,9 @@ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSche
|
|
|
17
17
|
import { GITNEXUS_TOOLS } from './tools.js';
|
|
18
18
|
import { installGlobalStdoutSentinel } from './stdio-context.js';
|
|
19
19
|
import { getResourceDefinitions, getResourceTemplates, readResource } from './resources.js';
|
|
20
|
+
import { assertMcpReadOnlyResource, assertMcpReadOnlyToolCall, filterMcpReadOnlyResourceContent, MCP_READ_ONLY_TOOLS, readOnlyResourceTemplateAllowed, resolveMcpReadOnlyMode, toolForReadOnlyMcp, } from './read-only-policy.js';
|
|
21
|
+
import { createMcpRepositoryPolicy, McpRepositoryPolicy, mcpRepositoryPolicyConfigured, } from './repository-policy.js';
|
|
22
|
+
import { applyMcpMaxTokens, resolveMcpMaxTokens, withoutMcpBudgetArg } from './output-budget.js';
|
|
20
23
|
/**
|
|
21
24
|
* Next-step hints appended to tool responses.
|
|
22
25
|
*
|
|
@@ -60,7 +63,13 @@ function getNextStepHint(toolName, args) {
|
|
|
60
63
|
* Create a configured MCP Server with all handlers registered.
|
|
61
64
|
* Transport-agnostic — caller connects the desired transport.
|
|
62
65
|
*/
|
|
63
|
-
export function createMCPServer(backend) {
|
|
66
|
+
export function createMCPServer(backend, options = {}) {
|
|
67
|
+
const readOnly = resolveMcpReadOnlyMode();
|
|
68
|
+
if (!options.repositoryPolicy && mcpRepositoryPolicyConfigured()) {
|
|
69
|
+
throw new Error('Configured MCP repository policy must be validated before server creation.');
|
|
70
|
+
}
|
|
71
|
+
const repositoryPolicy = options.repositoryPolicy ?? McpRepositoryPolicy.unrestricted();
|
|
72
|
+
const scopedBackend = repositoryPolicy.scopeBackend(backend);
|
|
64
73
|
const require = createRequire(import.meta.url);
|
|
65
74
|
const pkgVersion = require('../../package.json').version;
|
|
66
75
|
const server = new Server({
|
|
@@ -87,7 +96,8 @@ export function createMCPServer(backend) {
|
|
|
87
96
|
});
|
|
88
97
|
// Handle list resource templates request (for dynamic resources)
|
|
89
98
|
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
|
|
90
|
-
const templates = getResourceTemplates()
|
|
99
|
+
const templates = getResourceTemplates().filter((template) => readOnlyResourceTemplateAllowed(template.uriTemplate, readOnly) &&
|
|
100
|
+
repositoryPolicy.resourceTemplateAllowed(template.uriTemplate));
|
|
91
101
|
return {
|
|
92
102
|
resourceTemplates: templates.map((t) => ({
|
|
93
103
|
uriTemplate: t.uriTemplate,
|
|
@@ -101,7 +111,9 @@ export function createMCPServer(backend) {
|
|
|
101
111
|
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
102
112
|
const { uri } = request.params;
|
|
103
113
|
try {
|
|
104
|
-
|
|
114
|
+
assertMcpReadOnlyResource(uri, readOnly);
|
|
115
|
+
repositoryPolicy.assertResourceUri(uri);
|
|
116
|
+
const content = filterMcpReadOnlyResourceContent(await readResource(uri, scopedBackend), readOnly);
|
|
105
117
|
return {
|
|
106
118
|
contents: [
|
|
107
119
|
{
|
|
@@ -126,7 +138,10 @@ export function createMCPServer(backend) {
|
|
|
126
138
|
});
|
|
127
139
|
// Handle list tools request
|
|
128
140
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
129
|
-
tools: GITNEXUS_TOOLS.
|
|
141
|
+
tools: GITNEXUS_TOOLS.filter((tool) => (!readOnly || MCP_READ_ONLY_TOOLS.has(tool.name)) &&
|
|
142
|
+
repositoryPolicy.toolAllowed(tool.name))
|
|
143
|
+
.map((tool) => toolForReadOnlyMcp(repositoryPolicy.toolForMcp(tool), readOnly))
|
|
144
|
+
.map((tool) => ({
|
|
130
145
|
name: tool.name,
|
|
131
146
|
description: tool.description,
|
|
132
147
|
inputSchema: tool.inputSchema,
|
|
@@ -136,15 +151,19 @@ export function createMCPServer(backend) {
|
|
|
136
151
|
// Handle tool calls — append next-step hints to guide agent workflow
|
|
137
152
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
138
153
|
const { name, arguments: args } = request.params;
|
|
154
|
+
let maxTokens;
|
|
139
155
|
try {
|
|
140
|
-
const
|
|
156
|
+
const typedArgs = args;
|
|
157
|
+
assertMcpReadOnlyToolCall(name, typedArgs, readOnly);
|
|
158
|
+
maxTokens = resolveMcpMaxTokens(name, typedArgs);
|
|
159
|
+
const result = await scopedBackend.callTool(name, withoutMcpBudgetArg(typedArgs));
|
|
141
160
|
const resultText = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
|
|
142
161
|
const hint = getNextStepHint(name, args);
|
|
143
162
|
return {
|
|
144
163
|
content: [
|
|
145
164
|
{
|
|
146
165
|
type: 'text',
|
|
147
|
-
text: resultText + hint,
|
|
166
|
+
text: applyMcpMaxTokens(resultText + hint, maxTokens),
|
|
148
167
|
},
|
|
149
168
|
],
|
|
150
169
|
};
|
|
@@ -155,7 +174,7 @@ export function createMCPServer(backend) {
|
|
|
155
174
|
content: [
|
|
156
175
|
{
|
|
157
176
|
type: 'text',
|
|
158
|
-
text: `Error: ${message}`,
|
|
177
|
+
text: applyMcpMaxTokens(`Error: ${message}`, maxTokens),
|
|
159
178
|
},
|
|
160
179
|
],
|
|
161
180
|
isError: true,
|
|
@@ -265,8 +284,9 @@ export function installSignalShutdown(shutdown, on = (event, listener) => {
|
|
|
265
284
|
on('SIGINT', () => void shutdown(SHUTDOWN_EXIT_CODES.SIGINT));
|
|
266
285
|
on('SIGTERM', () => void shutdown(SHUTDOWN_EXIT_CODES.SIGTERM));
|
|
267
286
|
}
|
|
268
|
-
export async function startMCPServer(backend) {
|
|
269
|
-
const
|
|
287
|
+
export async function startMCPServer(backend, repositoryPolicy) {
|
|
288
|
+
const validatedRepositoryPolicy = repositoryPolicy ?? (await createMcpRepositoryPolicy(backend));
|
|
289
|
+
const server = createMCPServer(backend, { repositoryPolicy: validatedRepositoryPolicy });
|
|
270
290
|
// Idempotent global sentinel install. cli/mcp.ts calls this first thing
|
|
271
291
|
// (before warnMissingOptionalGrammars / backend.init can emit to stdout);
|
|
272
292
|
// calling again here is a safety net for direct callers of startMCPServer
|
package/dist/mcp/tools.d.ts
CHANGED
|
@@ -24,14 +24,6 @@ export interface ToolDefinition {
|
|
|
24
24
|
minLength?: number;
|
|
25
25
|
}>;
|
|
26
26
|
required: string[];
|
|
27
|
-
/**
|
|
28
|
-
* JSON-Schema `anyOf` for cross-property constraints `required` cannot express
|
|
29
|
-
* — e.g. "at least one of route/file". Forwarded verbatim to clients by the
|
|
30
|
-
* server's ListTools handler, so MCP clients see the constraint.
|
|
31
|
-
*/
|
|
32
|
-
anyOf?: Array<{
|
|
33
|
-
required: string[];
|
|
34
|
-
}>;
|
|
35
27
|
};
|
|
36
28
|
}
|
|
37
29
|
/**
|
package/dist/mcp/tools.js
CHANGED
|
@@ -141,6 +141,11 @@ SERVICE: optional monorepo path prefix (POSIX-style, case-sensitive segments). W
|
|
|
141
141
|
description: 'Include full symbol source code (default: false)',
|
|
142
142
|
default: false,
|
|
143
143
|
},
|
|
144
|
+
maxTokens: {
|
|
145
|
+
type: 'integer',
|
|
146
|
+
minimum: 1,
|
|
147
|
+
description: 'Maximum estimated tokens in the complete formatted MCP response. Explicit request overrides GITNEXUS_MCP_DEFAULT_MAX_TOKENS.',
|
|
148
|
+
},
|
|
144
149
|
repo: {
|
|
145
150
|
type: 'string',
|
|
146
151
|
description: 'Indexed repository name or path, or group mode "@<groupName>" / "@<groupName>/<memberPath>" (member path keys from group.yaml). Omit when only one indexed repo exists.',
|
|
@@ -253,6 +258,10 @@ SERVICE: optional monorepo path prefix (case-sensitive path segments). When "rep
|
|
|
253
258
|
description: 'Direct symbol UID from prior tool results (zero-ambiguity lookup)',
|
|
254
259
|
},
|
|
255
260
|
file_path: { type: 'string', description: 'File path to disambiguate common names' },
|
|
261
|
+
file: {
|
|
262
|
+
type: 'string',
|
|
263
|
+
description: 'Compatibility alias for file_path; values must agree when both are present',
|
|
264
|
+
},
|
|
256
265
|
kind: {
|
|
257
266
|
type: 'string',
|
|
258
267
|
description: "Kind filter to disambiguate common names (e.g. 'Function', 'Class', 'Method', 'Interface', 'Constructor')",
|
|
@@ -262,6 +271,11 @@ SERVICE: optional monorepo path prefix (case-sensitive path segments). When "rep
|
|
|
262
271
|
description: 'Include full symbol source code (default: false)',
|
|
263
272
|
default: false,
|
|
264
273
|
},
|
|
274
|
+
maxTokens: {
|
|
275
|
+
type: 'integer',
|
|
276
|
+
minimum: 1,
|
|
277
|
+
description: 'Maximum estimated tokens in the complete formatted MCP response. Explicit request overrides GITNEXUS_MCP_DEFAULT_MAX_TOKENS.',
|
|
278
|
+
},
|
|
265
279
|
repo: {
|
|
266
280
|
type: 'string',
|
|
267
281
|
description: 'Indexed repository name or path, or group mode "@<groupName>" / "@<groupName>/<memberPath>". Omit if only one repo is indexed.',
|
|
@@ -379,7 +393,7 @@ MODE (opt-in): "callgraph" (default) walks symbol→symbol edges (CALLS/IMPORTS/
|
|
|
379
393
|
|
|
380
394
|
STATEMENT-ANCHORED PDG SLICE: with mode:'pdg', pass "line" (1-based source line within the target symbol) to seed the dependence slice on the statement at that line and return what depends on it in affectedStatements (line + text). Inter-procedural symbols are still reported through interproceduralByDepth/pdgInterprocedural and the compatibility byDepth bucket. Without "line", pdg returns whole-symbol inter-procedural reach plus local whole-symbol PDG diagnostics.
|
|
381
395
|
|
|
382
|
-
PDG OUTPUT CONTRACT: every mode:'pdg' result (success, empty, degraded, or error) carries pdgResultVersion:
|
|
396
|
+
PDG OUTPUT CONTRACT: every mode:'pdg' result (success, empty, degraded, or error) carries pdgResultVersion:2 — a stable discriminator for external consumers that bumps on any breaking change to the PDG result shape (distinct from the DB schema version). Successful PDG results include mode:'pdg', a full target envelope (id/name/type/filePath), affectedStatements, affectedStatementCount, interproceduralByDepth/pdgInterprocedural for cross-function reach, compatibility byDepth/byDepthCounts, risk:'UNKNOWN', and a note describing the unified contract. Degraded PDG results (no-layer, sub-layer-missing, unknown) keep mode:'pdg', pdgResultVersion:2, target metadata when the target resolves, risk:'UNKNOWN', note/remediation, and empty byDepth parity fields — never a false-safe zero. If depth and limit both bound the slice, truncatedByReasons reports both causes while truncatedBy remains scalar.
|
|
383
397
|
|
|
384
398
|
WHEN TO USE: Before making code changes — especially refactoring, renaming, or modifying shared code. Shows what would break.
|
|
385
399
|
AFTER THIS: Review d=1 items (WILL BREAK). Use context() on high-risk symbols.
|
|
@@ -413,6 +427,14 @@ SERVICE: optional monorepo path prefix (case-sensitive path segments). When "rep
|
|
|
413
427
|
type: 'object',
|
|
414
428
|
properties: {
|
|
415
429
|
target: { type: 'string', description: 'Name of function, class, or file to analyze' },
|
|
430
|
+
name: {
|
|
431
|
+
type: 'string',
|
|
432
|
+
description: 'Compatibility alias for target; all supplied target aliases must agree',
|
|
433
|
+
},
|
|
434
|
+
symbol: {
|
|
435
|
+
type: 'string',
|
|
436
|
+
description: 'Compatibility alias for target; all supplied target aliases must agree',
|
|
437
|
+
},
|
|
416
438
|
target_uid: {
|
|
417
439
|
type: 'string',
|
|
418
440
|
description: 'Direct symbol UID from prior tool results (zero-ambiguity lookup, skips target resolution)',
|
|
@@ -503,6 +525,11 @@ SERVICE: optional monorepo path prefix (case-sensitive path segments). When "rep
|
|
|
503
525
|
description: 'When true, returns target, summary, risk, byDepthCounts, affected_processes, and affected_modules — omits byDepth. Single-repo only; ignored in group mode (@groupName). Use for hub symbols to get actionable signal without output explosion.',
|
|
504
526
|
default: false,
|
|
505
527
|
},
|
|
528
|
+
maxTokens: {
|
|
529
|
+
type: 'integer',
|
|
530
|
+
minimum: 1,
|
|
531
|
+
description: 'Maximum estimated tokens in the complete formatted MCP response. Explicit request overrides GITNEXUS_MCP_DEFAULT_MAX_TOKENS.',
|
|
532
|
+
},
|
|
506
533
|
timeoutMs: {
|
|
507
534
|
type: 'number',
|
|
508
535
|
description: 'Wall-clock budget in milliseconds for the Phase-1 local impact leg (default 30000)',
|
|
@@ -516,7 +543,7 @@ SERVICE: optional monorepo path prefix (case-sensitive path segments). When "rep
|
|
|
516
543
|
maximum: 3600000,
|
|
517
544
|
},
|
|
518
545
|
},
|
|
519
|
-
required: ['
|
|
546
|
+
required: ['direction'],
|
|
520
547
|
},
|
|
521
548
|
},
|
|
522
549
|
{
|
|
@@ -699,9 +726,6 @@ Response shape is keyed on how many routes match, not on the data: exactly one m
|
|
|
699
726
|
repo: { type: 'string', description: 'Repository name or path.' },
|
|
700
727
|
},
|
|
701
728
|
required: [],
|
|
702
|
-
// Exactly one lookup key is needed, but either works (route wins if both
|
|
703
|
-
// are passed) — so the structural constraint is "at least one of route/file".
|
|
704
|
-
anyOf: [{ required: ['route'] }, { required: ['file'] }],
|
|
705
729
|
},
|
|
706
730
|
},
|
|
707
731
|
{
|
|
@@ -804,6 +828,76 @@ DESTINATION TRACE (cross-repo): for an "@groupName" trace, OMIT to/to_uid/to_fil
|
|
|
804
828
|
required: [],
|
|
805
829
|
},
|
|
806
830
|
},
|
|
831
|
+
{
|
|
832
|
+
name: 'move_entries',
|
|
833
|
+
description: `List Move/Aptos entry points (compiler-sourced).
|
|
834
|
+
|
|
835
|
+
WHEN TO USE: To enumerate a Move package's external surface - \`entry\` functions (transaction entry points) and \`#[view]\` functions (read-only queries). Filter by module, kind, or attribute.
|
|
836
|
+
|
|
837
|
+
Returns: { entries: [{ name, qualifiedName, filePath, isEntry, isView, visibility, acquires, attributes, returnType }], count }.`,
|
|
838
|
+
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
839
|
+
inputSchema: {
|
|
840
|
+
type: 'object',
|
|
841
|
+
properties: {
|
|
842
|
+
module: {
|
|
843
|
+
type: 'string',
|
|
844
|
+
description: 'Filter to one module (qualified name, e.g. 0xa::coin).',
|
|
845
|
+
},
|
|
846
|
+
kind: {
|
|
847
|
+
type: 'string',
|
|
848
|
+
enum: ['entry', 'view', 'inline', 'native'],
|
|
849
|
+
description: 'Restrict to a single entry kind. Omit for entry+view.',
|
|
850
|
+
},
|
|
851
|
+
attribute: {
|
|
852
|
+
type: 'string',
|
|
853
|
+
description: 'Only functions carrying this attribute (e.g. "view").',
|
|
854
|
+
},
|
|
855
|
+
repo: { type: 'string', description: 'Repository name or path.' },
|
|
856
|
+
},
|
|
857
|
+
required: [],
|
|
858
|
+
},
|
|
859
|
+
},
|
|
860
|
+
{
|
|
861
|
+
name: 'move_resources',
|
|
862
|
+
description: `List Move/Aptos resources (structs/enums with the \`key\` ability) and their accessors.
|
|
863
|
+
|
|
864
|
+
WHEN TO USE: To audit on-chain storage — which resources exist and which functions read/write/acquire them (from READS_RESOURCE / WRITES_RESOURCE / ACQUIRES edges).
|
|
865
|
+
|
|
866
|
+
Returns: { resources: [{ name, qualifiedName, filePath, abilities, fieldList, accessors: [{ caller, reason, isEntry, isView }] }], count }.`,
|
|
867
|
+
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
868
|
+
inputSchema: {
|
|
869
|
+
type: 'object',
|
|
870
|
+
properties: {
|
|
871
|
+
module: { type: 'string', description: 'Filter to one module (qualified name).' },
|
|
872
|
+
repo: { type: 'string', description: 'Repository name or path.' },
|
|
873
|
+
},
|
|
874
|
+
required: [],
|
|
875
|
+
},
|
|
876
|
+
},
|
|
877
|
+
{
|
|
878
|
+
name: 'move_impact',
|
|
879
|
+
description: `Blast radius for a Move/Aptos symbol over Move edges (CALLS / READS_RESOURCE / WRITES_RESOURCE / ACQUIRES / USES_TYPE).
|
|
880
|
+
|
|
881
|
+
WHEN TO USE: BEFORE editing a Move function or resource/type. Reports callers, resource-access dependents, and signature type users. Restricts the generic impact traversal to Move semantic edges.`,
|
|
882
|
+
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
883
|
+
inputSchema: {
|
|
884
|
+
type: 'object',
|
|
885
|
+
properties: {
|
|
886
|
+
target: {
|
|
887
|
+
type: 'string',
|
|
888
|
+
description: 'Move symbol (qualified name preferred, e.g. 0xa::coin::transfer).',
|
|
889
|
+
},
|
|
890
|
+
direction: {
|
|
891
|
+
type: 'string',
|
|
892
|
+
enum: ['upstream', 'downstream'],
|
|
893
|
+
description: 'upstream = who depends on the target (default); downstream = what the target depends on.',
|
|
894
|
+
},
|
|
895
|
+
maxDepth: { type: 'number', description: 'Traversal depth (default 3).' },
|
|
896
|
+
repo: { type: 'string', description: 'Repository name or path.' },
|
|
897
|
+
},
|
|
898
|
+
required: ['target'],
|
|
899
|
+
},
|
|
900
|
+
},
|
|
807
901
|
];
|
|
808
902
|
/**
|
|
809
903
|
* Per-repo tools that accept an optional `branch` scope (#2106). Single source
|
|
@@ -827,6 +921,9 @@ const BRANCH_SCOPED_TOOLS = new Set([
|
|
|
827
921
|
'shape_check',
|
|
828
922
|
'api_impact',
|
|
829
923
|
'trace',
|
|
924
|
+
'move_entries',
|
|
925
|
+
'move_resources',
|
|
926
|
+
'move_impact',
|
|
830
927
|
]);
|
|
831
928
|
for (const tool of GITNEXUS_TOOLS) {
|
|
832
929
|
if (!BRANCH_SCOPED_TOOLS.has(tool.name))
|
|
@@ -30,6 +30,7 @@ export interface AnalyzeJob {
|
|
|
30
30
|
export declare class JobManager {
|
|
31
31
|
private jobs;
|
|
32
32
|
private children;
|
|
33
|
+
private abortControllers;
|
|
33
34
|
private timeouts;
|
|
34
35
|
private emitter;
|
|
35
36
|
private cleanupTimer;
|
|
@@ -45,6 +46,8 @@ export declare class JobManager {
|
|
|
45
46
|
updateJob(id: string, update: Partial<Pick<AnalyzeJob, 'status' | 'progress' | 'error' | 'repoPath' | 'repoName' | 'completedAt'>>): void;
|
|
46
47
|
/** Register a child process for a job — enables cancellation and timeout. */
|
|
47
48
|
registerChild(jobId: string, child: ChildProcess): void;
|
|
49
|
+
/** Register cancellable in-process work for a job. */
|
|
50
|
+
registerAbortController(jobId: string, controller: AbortController): void;
|
|
48
51
|
/** Cancel a running job — sends SIGTERM to child process. */
|
|
49
52
|
cancelJob(jobId: string, reason?: string): boolean;
|
|
50
53
|
/** Subscribe to progress events for a job. Returns unsubscribe function. */
|
|
@@ -16,6 +16,7 @@ const JOB_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
|
|
|
16
16
|
export class JobManager {
|
|
17
17
|
jobs = new Map();
|
|
18
18
|
children = new Map();
|
|
19
|
+
abortControllers = new Map();
|
|
19
20
|
timeouts = new Map();
|
|
20
21
|
emitter = new EventEmitter();
|
|
21
22
|
cleanupTimer;
|
|
@@ -72,6 +73,7 @@ export class JobManager {
|
|
|
72
73
|
Object.assign(job, update);
|
|
73
74
|
if (this.isTerminal(job.status)) {
|
|
74
75
|
job.completedAt = job.completedAt ?? Date.now();
|
|
76
|
+
this.abortControllers.delete(id);
|
|
75
77
|
}
|
|
76
78
|
// Emit exactly one event per updateJob call to prevent SSE double-write
|
|
77
79
|
if (update.status === 'complete' || update.status === 'failed') {
|
|
@@ -107,6 +109,15 @@ export class JobManager {
|
|
|
107
109
|
}
|
|
108
110
|
});
|
|
109
111
|
}
|
|
112
|
+
/** Register cancellable in-process work for a job. */
|
|
113
|
+
registerAbortController(jobId, controller) {
|
|
114
|
+
const job = this.jobs.get(jobId);
|
|
115
|
+
if (!job || this.isTerminal(job.status)) {
|
|
116
|
+
controller.abort();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
this.abortControllers.set(jobId, controller);
|
|
120
|
+
}
|
|
110
121
|
/** Cancel a running job — sends SIGTERM to child process. */
|
|
111
122
|
cancelJob(jobId, reason) {
|
|
112
123
|
const job = this.jobs.get(jobId);
|
|
@@ -116,6 +127,8 @@ export class JobManager {
|
|
|
116
127
|
if (child) {
|
|
117
128
|
child.kill('SIGTERM');
|
|
118
129
|
}
|
|
130
|
+
this.abortControllers.get(jobId)?.abort();
|
|
131
|
+
this.abortControllers.delete(jobId);
|
|
119
132
|
this.updateJob(jobId, {
|
|
120
133
|
status: 'failed',
|
|
121
134
|
error: reason || 'Analysis cancelled',
|
|
@@ -134,6 +147,9 @@ export class JobManager {
|
|
|
134
147
|
child.kill('SIGTERM');
|
|
135
148
|
}
|
|
136
149
|
this.children.clear();
|
|
150
|
+
for (const controller of this.abortControllers.values())
|
|
151
|
+
controller.abort();
|
|
152
|
+
this.abortControllers.clear();
|
|
137
153
|
// Clear all timeouts
|
|
138
154
|
for (const timer of this.timeouts.values()) {
|
|
139
155
|
clearTimeout(timer);
|
|
@@ -150,6 +166,7 @@ export class JobManager {
|
|
|
150
166
|
for (const [id, job] of this.jobs) {
|
|
151
167
|
if (this.isTerminal(job.status) && job.completedAt && now - job.completedAt > JOB_TTL_MS) {
|
|
152
168
|
this.jobs.delete(id);
|
|
169
|
+
this.abortControllers.delete(id);
|
|
153
170
|
}
|
|
154
171
|
}
|
|
155
172
|
}
|
|
@@ -17,6 +17,12 @@ export interface LaunchDeps {
|
|
|
17
17
|
};
|
|
18
18
|
acquireRepoLock: (key: string) => string | null;
|
|
19
19
|
releaseRepoLock: (key: string) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Drops the server's cached LadybugDB handle (closeLbug). The worker
|
|
22
|
+
* process rewrites the repo's DB files on disk, so a connection opened
|
|
23
|
+
* before the rewrite keeps reading the pre-rewrite state until evicted.
|
|
24
|
+
*/
|
|
25
|
+
closeDbHandle: () => Promise<void>;
|
|
20
26
|
}
|
|
21
27
|
export interface LaunchOptions {
|
|
22
28
|
force?: boolean;
|
|
@@ -10,16 +10,83 @@
|
|
|
10
10
|
* path is resolved relative to `import.meta.url`.
|
|
11
11
|
*/
|
|
12
12
|
import path from 'path';
|
|
13
|
+
import { existsSync, statSync } from 'node:fs';
|
|
13
14
|
import { fork } from 'child_process';
|
|
14
15
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
15
16
|
import { createRequire } from 'node:module';
|
|
16
|
-
import { getStoragePath } from '../storage/repo-manager.js';
|
|
17
|
+
import { canonicalizePath, getStoragePath, INDEX_METADATA_FILE, listRegisteredRepos, registryPathEquals, } from '../storage/repo-manager.js';
|
|
17
18
|
import { logger } from '../core/logger.js';
|
|
18
19
|
const _require = createRequire(import.meta.url);
|
|
19
20
|
const MAX_WORKER_RETRIES = 2;
|
|
21
|
+
/**
|
|
22
|
+
* The worker reports `complete` over IPC before its on-disk finalization
|
|
23
|
+
* (LadybugDB checkpoint + native handle release + metadata write) is visible
|
|
24
|
+
* at `getStoragePath(targetPath)` — observed up to ~6.5s behind the IPC
|
|
25
|
+
* message. Opening the database inside that window is what the pre-IPC
|
|
26
|
+
* ordering was meant to prevent and is actively dangerous: reads fail with
|
|
27
|
+
* binder errors or return an empty graph, the open can quarantine the
|
|
28
|
+
* in-flight WAL, and the native layer racing the rewrite has crashed the
|
|
29
|
+
* whole server (SIGSEGV-class exit, no output) on slow CI runners.
|
|
30
|
+
*/
|
|
31
|
+
const FINALIZE_SETTLE_TIMEOUT_MS = 60_000;
|
|
32
|
+
const FINALIZE_SETTLE_POLL_MS = 200;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve once the analyzed repo's index is settled at `storagePath`: the
|
|
35
|
+
* LadybugDB file and metadata both exist AND were (re)written by THIS job
|
|
36
|
+
* (mtime >= jobStartMs — bare existence is not enough, a re-analysis leaves
|
|
37
|
+
* the previous index in place while it works), and no transient WAL/shadow/
|
|
38
|
+
* checkpoint sidecars remain (the worker's native close has finished).
|
|
39
|
+
*
|
|
40
|
+
* Never rejects. Timing out logs and proceeds (pre-gate behavior) rather
|
|
41
|
+
* than failing a job whose analysis genuinely succeeded — e.g. a no-op
|
|
42
|
+
* non-force analyze legitimately rewrites nothing.
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* Look up the analyzed repo's registered storage path. The request's
|
|
46
|
+
* user-provided path is used only as a comparison key; the filesystem probes
|
|
47
|
+
* below run against the registry's own `storagePath` — the server-owned
|
|
48
|
+
* record readers resolve through, and not a user-controlled value
|
|
49
|
+
* (CodeQL js/path-injection).
|
|
50
|
+
*/
|
|
51
|
+
const registeredStoragePath = async (targetPath) => {
|
|
52
|
+
const target = canonicalizePath(path.resolve(targetPath));
|
|
53
|
+
const entries = await listRegisteredRepos();
|
|
54
|
+
const entry = entries.find((e) => registryPathEquals(canonicalizePath(e.path), target));
|
|
55
|
+
return entry?.storagePath ?? null;
|
|
56
|
+
};
|
|
57
|
+
const waitForSettledIndex = async (targetPath, jobStartMs) => {
|
|
58
|
+
const settled = (storagePath) => {
|
|
59
|
+
try {
|
|
60
|
+
const lbugStat = statSync(path.join(storagePath, 'lbug'));
|
|
61
|
+
const metaStat = statSync(path.join(storagePath, INDEX_METADATA_FILE));
|
|
62
|
+
return (lbugStat.mtimeMs >= jobStartMs &&
|
|
63
|
+
metaStat.mtimeMs >= jobStartMs &&
|
|
64
|
+
['lbug.wal', 'lbug.shadow', 'lbug.wal.checkpoint'].every((f) => !existsSync(path.join(storagePath, f))));
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false; // not written yet
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const deadline = Date.now() + FINALIZE_SETTLE_TIMEOUT_MS;
|
|
71
|
+
for (;;) {
|
|
72
|
+
// Re-resolved each round: the worker registers the repo as part of the
|
|
73
|
+
// finalization this gate is waiting out.
|
|
74
|
+
const storagePath = await registeredStoragePath(targetPath);
|
|
75
|
+
if (storagePath && settled(storagePath))
|
|
76
|
+
return;
|
|
77
|
+
if (Date.now() > deadline) {
|
|
78
|
+
logger.warn({ targetPath }, 'analyze finalization not visible after timeout; completing job anyway');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
await new Promise((resolve) => setTimeout(resolve, FINALIZE_SETTLE_POLL_MS));
|
|
82
|
+
}
|
|
83
|
+
};
|
|
20
84
|
export function createLaunchAnalysisWorker(deps) {
|
|
21
|
-
const { jobManager, backend, acquireRepoLock, releaseRepoLock } = deps;
|
|
85
|
+
const { jobManager, backend, acquireRepoLock, releaseRepoLock, closeDbHandle } = deps;
|
|
22
86
|
return function launchAnalysisWorker(job, targetPath, opts) {
|
|
87
|
+
// For waitForSettledIndex: files (re)written by this job have mtimes at or
|
|
88
|
+
// after this instant. Taken before the fork so no worker write predates it.
|
|
89
|
+
const jobStartMs = Date.now();
|
|
23
90
|
// Acquire shared repo lock (keyed on storagePath to match embed handler)
|
|
24
91
|
const analyzeLockKey = getStoragePath(targetPath);
|
|
25
92
|
const lockErr = acquireRepoLock(analyzeLockKey);
|
|
@@ -67,10 +134,17 @@ export function createLaunchAnalysisWorker(deps) {
|
|
|
67
134
|
}
|
|
68
135
|
else if (msg.type === 'complete') {
|
|
69
136
|
releaseRepoLock(analyzeLockKey);
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
137
|
+
// Before marking complete: (1) wait for the worker's on-disk
|
|
138
|
+
// finalization to settle (see waitForSettledIndex), (2) evict the
|
|
139
|
+
// cached DB handle — same invalidation DELETE /api/repo performs, a
|
|
140
|
+
// handle opened before the rewrite reads pre-rewrite state — and
|
|
141
|
+
// only then (3) reinitialize the backend. This makes the ordering
|
|
142
|
+
// comment below true in practice: the repo is actually queryable
|
|
143
|
+
// when the client receives the SSE complete event.
|
|
144
|
+
waitForSettledIndex(targetPath, jobStartMs)
|
|
145
|
+
.then(() => closeDbHandle())
|
|
146
|
+
.catch(() => { }) // best-effort: eviction failure must not fail the job
|
|
147
|
+
.then(() => backend.init())
|
|
74
148
|
.then(() => {
|
|
75
149
|
jobManager.updateJob(job.id, { status: 'complete', repoName: msg.result.repoName });
|
|
76
150
|
})
|
|
@@ -84,6 +158,8 @@ export function createLaunchAnalysisWorker(deps) {
|
|
|
84
158
|
}
|
|
85
159
|
else if (msg.type === 'error') {
|
|
86
160
|
releaseRepoLock(analyzeLockKey);
|
|
161
|
+
// A failed (force) analyze may still have rewritten DB files first.
|
|
162
|
+
void closeDbHandle().catch(() => { });
|
|
87
163
|
jobManager.updateJob(job.id, { status: 'failed', error: msg.message });
|
|
88
164
|
}
|
|
89
165
|
});
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import type { AnalyzeOptions } from '../core/run-analyze.js';
|
|
16
16
|
import type { WorkerMessage } from './analyze-worker.js';
|
|
17
|
+
import type { AnalyzerRunnerIdentity } from '../storage/repo-manager.js';
|
|
17
18
|
export interface WorkerAnalysisDeps {
|
|
18
19
|
runFullAnalysis: typeof import('../core/run-analyze.js').runFullAnalysis;
|
|
19
20
|
assertAnalysisFinalized: typeof import('../storage/repo-manager.js').assertAnalysisFinalized;
|
|
@@ -32,7 +33,7 @@ export interface WorkerAnalysisDeps {
|
|
|
32
33
|
* already claimed the terminal slot — and never throws; the caller schedules
|
|
33
34
|
* `process.exit` after this resolves.
|
|
34
35
|
*/
|
|
35
|
-
export declare function runWorkerAnalysis(repoPath: string, options: AnalyzeOptions, deps: WorkerAnalysisDeps): Promise<void>;
|
|
36
|
+
export declare function runWorkerAnalysis(repoPath: string, options: AnalyzeOptions, deps: WorkerAnalysisDeps, runnerIdentityAtBootstrap?: AnalyzerRunnerIdentity): Promise<void>;
|
|
36
37
|
/**
|
|
37
38
|
* Create the single-use terminal-outcome claim shared by the worker's message
|
|
38
39
|
* handler and its SIGTERM handler. The first call returns `true`; every later
|
|
@@ -5,9 +5,12 @@ import { projectAnalyzeResultForIpc } from './analyze-worker-ipc.js';
|
|
|
5
5
|
* already claimed the terminal slot — and never throws; the caller schedules
|
|
6
6
|
* `process.exit` after this resolves.
|
|
7
7
|
*/
|
|
8
|
-
export async function runWorkerAnalysis(repoPath, options, deps) {
|
|
8
|
+
export async function runWorkerAnalysis(repoPath, options, deps, runnerIdentityAtBootstrap) {
|
|
9
9
|
let terminal;
|
|
10
10
|
try {
|
|
11
|
+
const bootstrapArgs = runnerIdentityAtBootstrap
|
|
12
|
+
? [runnerIdentityAtBootstrap]
|
|
13
|
+
: [];
|
|
11
14
|
const result = await deps.runFullAnalysis(repoPath,
|
|
12
15
|
// This worker force-exits right after reporting, so skip the native close
|
|
13
16
|
// (it can double-free in LadybugDB's ClientContext destructor after --pdg
|
|
@@ -15,7 +18,7 @@ export async function runWorkerAnalysis(repoPath, options, deps) {
|
|
|
15
18
|
{ ...options, skipNativeCloseOnExit: true }, {
|
|
16
19
|
onProgress: (phase, percent, message) => deps.send({ type: 'progress', phase, percent, message }),
|
|
17
20
|
onLog: (message) => deps.send({ type: 'progress', phase: 'log', percent: -1, message }),
|
|
18
|
-
});
|
|
21
|
+
}, ...bootstrapArgs);
|
|
19
22
|
// P2 (#2264): a half-finalized repo — meta.json written but the global
|
|
20
23
|
// registry entry missing (e.g. a prior collision-aborted run, or a wiped
|
|
21
24
|
// registry) — must NOT be reported as a successful analysis. Mirror the CLI's
|
|
@@ -10,10 +10,7 @@
|
|
|
10
10
|
* Child -> Parent: { type: 'complete', result: AnalyzeResult }
|
|
11
11
|
* Child -> Parent: { type: 'error', message: string }
|
|
12
12
|
*/
|
|
13
|
-
import { runFullAnalysis } from '../core/run-analyze.js';
|
|
14
13
|
import { runWorkerAnalysis, createTerminalClaim } from './analyze-worker-core.js';
|
|
15
|
-
import { assertAnalysisFinalized } from '../storage/repo-manager.js';
|
|
16
|
-
import { boundedCheckpointBeforeExit } from '../core/lbug/shutdown-helpers.js';
|
|
17
14
|
function send(msg) {
|
|
18
15
|
// No try/catch: if the IPC channel is gone, process.send throws
|
|
19
16
|
// (ERR_IPC_CHANNEL_CLOSED) and that failure must NOT be swallowed. Every caller
|
|
@@ -26,6 +23,7 @@ function send(msg) {
|
|
|
26
23
|
// terminal send, so a cancel near the finish line can't also report success and a
|
|
27
24
|
// late SIGTERM can't flip an already-reported job (#2264 P3).
|
|
28
25
|
const claimTerminal = createTerminalClaim();
|
|
26
|
+
let boundedCheckpointBeforeExit = null;
|
|
29
27
|
// Catch uncaught exceptions and unhandled rejections — report them to the parent
|
|
30
28
|
// over IPC (the same channel the analysis path uses), then exit. The report runs
|
|
31
29
|
// in `try` and the exit in `finally` so a throw from send() on a closed channel
|
|
@@ -61,6 +59,10 @@ process.on('SIGTERM', () => {
|
|
|
61
59
|
if (claimTerminal()) {
|
|
62
60
|
send({ type: 'error', message: 'Analysis cancelled (worker received SIGTERM)' });
|
|
63
61
|
}
|
|
62
|
+
if (!boundedCheckpointBeforeExit) {
|
|
63
|
+
process.exit(0);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
64
66
|
void boundedCheckpointBeforeExit({
|
|
65
67
|
exitCode: 0,
|
|
66
68
|
onFlushError: (err) => {
|
|
@@ -76,16 +78,37 @@ process.on('message', async (msg) => {
|
|
|
76
78
|
return;
|
|
77
79
|
started = true;
|
|
78
80
|
try {
|
|
81
|
+
// Capture the complete build/dependency receipt before evaluating the
|
|
82
|
+
// analyzer graph or loading LadybugDB. A replacement racing this boundary
|
|
83
|
+
// is compared against this receipt again immediately before metadata commit.
|
|
84
|
+
const identityModule = await import('../core/analyzer-identity.js');
|
|
85
|
+
const prepared = await identityModule.captureAnalyzerIdentityBeforeLoad(import.meta.url, async () => {
|
|
86
|
+
const [analysisModule, repoManager, shutdownHelpers] = await Promise.all([
|
|
87
|
+
import('../core/run-analyze.js'),
|
|
88
|
+
import('../storage/repo-manager.js'),
|
|
89
|
+
import('../core/lbug/shutdown-helpers.js'),
|
|
90
|
+
]);
|
|
91
|
+
return { analysisModule, repoManager, shutdownHelpers };
|
|
92
|
+
});
|
|
93
|
+
boundedCheckpointBeforeExit = prepared.loaded.shutdownHelpers.boundedCheckpointBeforeExit;
|
|
79
94
|
// The run → finalize → report contract lives in the side-effect-free
|
|
80
95
|
// analyze-worker-core seam (unit-testable without this entry module's
|
|
81
96
|
// process.on side effects). It reports exactly one terminal message and
|
|
82
97
|
// never throws.
|
|
83
98
|
await runWorkerAnalysis(msg.repoPath, msg.options, {
|
|
84
|
-
runFullAnalysis,
|
|
85
|
-
assertAnalysisFinalized,
|
|
99
|
+
runFullAnalysis: prepared.loaded.analysisModule.runFullAnalysis,
|
|
100
|
+
assertAnalysisFinalized: prepared.loaded.repoManager.assertAnalysisFinalized,
|
|
86
101
|
send,
|
|
87
102
|
claimTerminal,
|
|
88
|
-
});
|
|
103
|
+
}, prepared.runnerIdentity);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (claimTerminal()) {
|
|
107
|
+
send({
|
|
108
|
+
type: 'error',
|
|
109
|
+
message: error instanceof Error ? error.message : 'Analysis worker bootstrap failed',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
89
112
|
}
|
|
90
113
|
finally {
|
|
91
114
|
// LadybugDB's native module prevents clean exit — force it (same reason the
|