gitnexus 1.6.11-rc.8 → 1.6.11
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 +95 -26
- package/dist/_shared/graph/types.d.ts +81 -2
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/integrations/circuit-breaker.d.ts.map +1 -1
- package/dist/_shared/integrations/circuit-breaker.js.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
- 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 -1
- package/dist/_shared/languages.d.ts.map +1 -1
- package/dist/_shared/languages.js +1 -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 +4 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/scope-resolution/evidence-weights.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.js +1 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.d.ts +3 -0
- package/dist/_shared/scope-resolution/language-classification.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.js +4 -0
- package/dist/_shared/scope-resolution/language-classification.js.map +1 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts +10 -0
- package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/registries/field-registry.js.map +1 -1
- package/dist/_shared/scope-resolution/registries/method-registry.js.map +1 -1
- package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
- package/dist/_shared/scope-resolution/types.d.ts +15 -0
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +4 -0
- package/dist/cli/ai-context.js +90 -14
- package/dist/cli/analyze-config.js +14 -0
- package/dist/cli/analyze-options.d.ts +14 -0
- package/dist/cli/analyze-watch.d.ts +20 -0
- package/dist/cli/analyze-watch.js +434 -0
- package/dist/cli/analyze.js +27 -9
- package/dist/cli/auto-sync.d.ts +1 -0
- package/dist/cli/auto-sync.js +107 -0
- package/dist/cli/command-banner.d.ts +15 -0
- package/dist/cli/command-banner.js +42 -0
- package/dist/cli/detect-changes-format.js +21 -0
- package/dist/cli/doctor.d.ts +7 -0
- package/dist/cli/doctor.js +14 -0
- package/dist/cli/group.js +7 -1
- package/dist/cli/help-i18n.js +4 -0
- package/dist/cli/i18n/en.d.ts +18 -3
- package/dist/cli/i18n/en.js +18 -3
- package/dist/cli/i18n/resources.d.ts +33 -3
- package/dist/cli/i18n/zh-CN.d.ts +15 -0
- package/dist/cli/i18n/zh-CN.js +18 -3
- package/dist/cli/index.js +34 -7
- package/dist/cli/mcp.d.ts +15 -0
- package/dist/cli/mcp.js +44 -0
- package/dist/cli/optional-grammars.d.ts +3 -2
- package/dist/cli/optional-grammars.js +19 -3
- package/dist/cli/setup.js +41 -15
- package/dist/cli/update-notice.d.ts +34 -0
- package/dist/cli/update-notice.js +91 -0
- package/dist/cli/update.d.ts +21 -0
- package/dist/cli/update.js +93 -0
- package/dist/cli/watch.d.ts +1 -20
- package/dist/cli/watch.js +5 -371
- package/dist/core/analysis-feature-registry.d.ts +2 -0
- package/dist/core/analysis-feature-registry.js +15 -0
- package/dist/core/analyzer-identity.js +21 -3
- package/dist/core/auto-sync/analysis-worker-launch.d.ts +30 -0
- package/dist/core/auto-sync/analysis-worker-launch.js +166 -0
- package/dist/core/auto-sync/config.d.ts +33 -0
- package/dist/core/auto-sync/config.js +320 -0
- package/dist/core/auto-sync/index.d.ts +6 -0
- package/dist/core/auto-sync/index.js +6 -0
- package/dist/core/auto-sync/path-security.d.ts +9 -0
- package/dist/core/auto-sync/path-security.js +251 -0
- package/dist/core/auto-sync/repo.d.ts +1 -0
- package/dist/core/auto-sync/repo.js +6 -0
- package/dist/core/auto-sync/runner.d.ts +44 -0
- package/dist/core/auto-sync/runner.js +428 -0
- package/dist/core/auto-sync/starter.d.ts +50 -0
- package/dist/core/auto-sync/starter.js +497 -0
- package/dist/core/auto-sync/state.d.ts +37 -0
- package/dist/core/auto-sync/state.js +119 -0
- package/dist/core/group/config-parser.js +8 -1
- package/dist/core/group/cross-impact.d.ts +3 -0
- package/dist/core/group/cross-impact.js +36 -4
- package/dist/core/group/extractors/http-patterns/java.js +22 -8
- package/dist/core/group/extractors/http-patterns/kotlin.js +86 -31
- package/dist/core/group/extractors/http-patterns/node.js +145 -8
- package/dist/core/group/extractors/http-patterns/python.js +11 -7
- package/dist/core/group/extractors/http-route-extractor.js +63 -17
- package/dist/core/group/extractors/java-workspace-extractor.js +244 -31
- package/dist/core/group/group-lock.js +5 -6
- package/dist/core/group/normalization.d.ts +38 -1
- package/dist/core/group/normalization.js +59 -3
- package/dist/core/group/service.d.ts +11 -0
- package/dist/core/group/service.js +13 -1
- package/dist/core/group/storage.js +2 -2
- package/dist/core/group/sync.d.ts +24 -1
- package/dist/core/group/sync.js +46 -8
- package/dist/core/group/types.d.ts +13 -0
- package/dist/core/incremental/derived-writeback.d.ts +36 -0
- package/dist/core/incremental/derived-writeback.js +68 -0
- package/dist/core/incremental/spring-config-drift.d.ts +12 -0
- package/dist/core/incremental/spring-config-drift.js +46 -0
- package/dist/core/incremental/subgraph-extract.d.ts +7 -4
- package/dist/core/incremental/subgraph-extract.js +30 -5
- package/dist/core/ingestion/asyncapi/document.d.ts +226 -0
- package/dist/core/ingestion/asyncapi/document.js +758 -0
- package/dist/core/ingestion/asyncapi/protocol.d.ts +79 -0
- package/dist/core/ingestion/asyncapi/protocol.js +203 -0
- package/dist/core/ingestion/call-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/call-extractors/configs/zig.js +4 -0
- package/dist/core/ingestion/call-extractors/zig-static-gating.d.ts +100 -0
- package/dist/core/ingestion/call-extractors/zig-static-gating.js +319 -0
- package/dist/core/ingestion/call-processor.js +3 -1
- package/dist/core/ingestion/class-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/class-extractors/configs/zig.js +32 -0
- package/dist/core/ingestion/class-extractors/generic.js +4 -1
- package/dist/core/ingestion/class-types.d.ts +6 -2
- package/dist/core/ingestion/destination-key.d.ts +59 -0
- package/dist/core/ingestion/destination-key.js +61 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +6 -2
- package/dist/core/ingestion/entry-point-scoring.js +8 -44
- package/dist/core/ingestion/export-detection.d.ts +37 -0
- package/dist/core/ingestion/export-detection.js +60 -0
- package/dist/core/ingestion/field-extractors/configs/zig.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/zig.js +49 -0
- package/dist/core/ingestion/field-extractors/generic.d.ts +1 -1
- package/dist/core/ingestion/field-extractors/generic.js +12 -1
- package/dist/core/ingestion/frameworks/spring/actuator-runtime.d.ts +26 -0
- package/dist/core/ingestion/frameworks/spring/actuator-runtime.js +843 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +5 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.js +9 -0
- package/dist/core/ingestion/frameworks/spring/annotation-arguments.js +8 -1
- package/dist/core/ingestion/frameworks/spring/argument-facts.d.ts +80 -0
- package/dist/core/ingestion/frameworks/spring/argument-facts.js +85 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.d.ts +1 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.js +2 -1
- package/dist/core/ingestion/frameworks/spring/destinations.d.ts +539 -0
- package/dist/core/ingestion/frameworks/spring/destinations.js +840 -0
- package/dist/core/ingestion/frameworks/spring/dynamic-lookups.d.ts +22 -0
- package/dist/core/ingestion/frameworks/spring/dynamic-lookups.js +124 -0
- package/dist/core/ingestion/frameworks/spring/message-producers.d.ts +78 -0
- package/dist/core/ingestion/frameworks/spring/message-producers.js +90 -0
- package/dist/core/ingestion/frameworks/spring/non-http-handlers.d.ts +29 -0
- package/dist/core/ingestion/frameworks/spring/vendor-prefixes.d.ts +7 -0
- package/dist/core/ingestion/frameworks/spring/vendor-prefixes.js +22 -0
- package/dist/core/ingestion/import-resolvers/configs/zig.d.ts +13 -0
- package/dist/core/ingestion/import-resolvers/configs/zig.js +26 -0
- package/dist/core/ingestion/import-resolvers/zig.d.ts +34 -0
- package/dist/core/ingestion/import-resolvers/zig.js +193 -0
- package/dist/core/ingestion/language-config.d.ts +177 -0
- package/dist/core/ingestion/language-config.js +719 -0
- package/dist/core/ingestion/language-provider.d.ts +178 -1
- package/dist/core/ingestion/language-provider.js +22 -0
- package/dist/core/ingestion/languages/csharp/razor-view-components.d.ts +62 -0
- package/dist/core/ingestion/languages/csharp/razor-view-components.js +954 -0
- package/dist/core/ingestion/languages/csharp/resolution-config.d.ts +3 -0
- package/dist/core/ingestion/languages/csharp/resolution-config.js +6 -1
- package/dist/core/ingestion/languages/csharp/scope-resolver.js +8 -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 +1 -1
- package/dist/core/ingestion/languages/java/analysis-features.js +14 -6
- package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +8 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.js +34 -0
- package/dist/core/ingestion/languages/java/captures.js +22 -1
- package/dist/core/ingestion/languages/java/lombok-synthesizer.d.ts +42 -0
- package/dist/core/ingestion/languages/java/lombok-synthesizer.js +439 -0
- package/dist/core/ingestion/languages/java/scope-resolver.js +2 -0
- package/dist/core/ingestion/languages/java/spring-actuator.d.ts +2 -0
- package/dist/core/ingestion/languages/java/spring-actuator.js +62 -0
- package/dist/core/ingestion/languages/java/spring-di.d.ts +17 -1
- package/dist/core/ingestion/languages/java/spring-di.js +44 -2
- package/dist/core/ingestion/languages/java/spring-dynamic-lookup.d.ts +8 -0
- package/dist/core/ingestion/languages/java/spring-dynamic-lookup.js +62 -0
- package/dist/core/ingestion/languages/java/spring-message-producers.d.ts +20 -0
- package/dist/core/ingestion/languages/java/spring-message-producers.js +83 -0
- package/dist/core/ingestion/languages/java/spring-non-http-handlers.d.ts +11 -1
- package/dist/core/ingestion/languages/java/spring-non-http-handlers.js +13 -3
- package/dist/core/ingestion/languages/java.js +18 -8
- package/dist/core/ingestion/languages/jvm/accessor-synthesis.d.ts +99 -0
- package/dist/core/ingestion/languages/jvm/accessor-synthesis.js +173 -0
- package/dist/core/ingestion/languages/jvm/beanspec.d.ts +17 -0
- package/dist/core/ingestion/languages/jvm/beanspec.js +42 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +15 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +50 -0
- package/dist/core/ingestion/languages/kotlin/captures.js +24 -1
- package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.d.ts +26 -0
- package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.js +417 -0
- package/dist/core/ingestion/languages/kotlin/scope-resolver.js +4 -0
- package/dist/core/ingestion/languages/kotlin/spring-actuator.d.ts +4 -0
- package/dist/core/ingestion/languages/kotlin/spring-actuator.js +172 -0
- package/dist/core/ingestion/languages/kotlin/spring-config-bindings.d.ts +18 -0
- package/dist/core/ingestion/languages/kotlin/spring-config-bindings.js +411 -0
- package/dist/core/ingestion/languages/kotlin/spring-di.d.ts +51 -1
- package/dist/core/ingestion/languages/kotlin/spring-di.js +86 -6
- package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.d.ts +8 -0
- package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.js +77 -0
- package/dist/core/ingestion/languages/kotlin/spring-message-producers.d.ts +17 -0
- package/dist/core/ingestion/languages/kotlin/spring-message-producers.js +119 -0
- package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.d.ts +16 -0
- package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.js +77 -2
- package/dist/core/ingestion/languages/kotlin.js +24 -0
- package/dist/core/ingestion/languages/python.js +2 -0
- package/dist/core/ingestion/languages/rust/query.js +8 -8
- package/dist/core/ingestion/languages/zig/captures.d.ts +260 -0
- package/dist/core/ingestion/languages/zig/captures.js +2070 -0
- package/dist/core/ingestion/languages/zig/index.d.ts +4 -0
- package/dist/core/ingestion/languages/zig/index.js +4 -0
- package/dist/core/ingestion/languages/zig/interpret.d.ts +36 -0
- package/dist/core/ingestion/languages/zig/interpret.js +176 -0
- package/dist/core/ingestion/languages/zig/query.d.ts +3 -0
- package/dist/core/ingestion/languages/zig/query.js +426 -0
- package/dist/core/ingestion/languages/zig/range-binding.d.ts +37 -0
- package/dist/core/ingestion/languages/zig/range-binding.js +373 -0
- package/dist/core/ingestion/languages/zig/scope-resolver.d.ts +12 -0
- package/dist/core/ingestion/languages/zig/scope-resolver.js +58 -0
- package/dist/core/ingestion/languages/zig/simple-hooks.d.ts +25 -0
- package/dist/core/ingestion/languages/zig/simple-hooks.js +143 -0
- package/dist/core/ingestion/languages/zig.d.ts +32 -0
- package/dist/core/ingestion/languages/zig.js +130 -0
- package/dist/core/ingestion/method-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/zig.js +120 -0
- package/dist/core/ingestion/method-extractors/generic.js +16 -4
- package/dist/core/ingestion/method-types.d.ts +10 -4
- package/dist/core/ingestion/model/field-registry.d.ts +3 -3
- package/dist/core/ingestion/model/field-registry.js +11 -7
- package/dist/core/ingestion/model/method-registry.d.ts +3 -3
- package/dist/core/ingestion/model/method-registry.js +13 -8
- package/dist/core/ingestion/model/registration-table.js +3 -0
- package/dist/core/ingestion/model/type-registry.js +8 -4
- package/dist/core/ingestion/pipeline-phases/di.js +47 -14
- package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
- package/dist/core/ingestion/pipeline-phases/index.js +1 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +7 -1
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +79 -91
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +17 -0
- package/dist/core/ingestion/pipeline-phases/processes.d.ts +2 -1
- package/dist/core/ingestion/pipeline-phases/processes.js +39 -4
- package/dist/core/ingestion/pipeline-phases/routes.js +27 -18
- package/dist/core/ingestion/pipeline-phases/runner.d.ts +4 -1
- package/dist/core/ingestion/pipeline-phases/runner.js +34 -14
- package/dist/core/ingestion/pipeline-phases/scan.js +82 -1
- package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.d.ts +2 -0
- package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.js +8 -0
- package/dist/core/ingestion/pipeline-phases/spring-destinations.d.ts +123 -0
- package/dist/core/ingestion/pipeline-phases/spring-destinations.js +688 -0
- package/dist/core/ingestion/pipeline.d.ts +30 -1
- package/dist/core/ingestion/pipeline.js +52 -14
- package/dist/core/ingestion/resolve-references.js +5 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +16 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.js +10 -0
- package/dist/core/ingestion/route-extractors/java-const-resolver.d.ts +27 -1
- package/dist/core/ingestion/route-extractors/java-const-resolver.js +161 -13
- package/dist/core/ingestion/route-extractors/kotlin-const-resolver.d.ts +12 -18
- package/dist/core/ingestion/route-extractors/kotlin-const-resolver.js +214 -33
- package/dist/core/ingestion/route-extractors/kotlin-spring.d.ts +13 -0
- package/dist/core/ingestion/route-extractors/kotlin-spring.js +259 -0
- package/dist/core/ingestion/route-extractors/python-decorator-handler.d.ts +6 -0
- package/dist/core/ingestion/route-extractors/python-decorator-handler.js +16 -0
- package/dist/core/ingestion/route-extractors/spring-shared.d.ts +30 -1
- package/dist/core/ingestion/route-extractors/spring-shared.js +77 -9
- package/dist/core/ingestion/route-extractors/spring.js +9 -5
- package/dist/core/ingestion/scope-extractor.js +8 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +62 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +4 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +2 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +28 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +11 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +23 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +24 -3
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +11 -1
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +26 -6
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +11 -0
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +29 -3
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +8 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +35 -9
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +1 -4
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +277 -9
- package/dist/core/ingestion/scope-resolution/pipeline/registry.js +2 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +7 -3
- package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +43 -9
- package/dist/core/ingestion/scope-resolution/scope/walkers.js +71 -10
- package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -0
- package/dist/core/ingestion/tree-sitter-queries.js +161 -0
- package/dist/core/ingestion/type-extractors/zig.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/zig.js +17 -0
- package/dist/core/ingestion/utils/ast-helpers.d.ts +40 -1
- package/dist/core/ingestion/utils/ast-helpers.js +124 -6
- package/dist/core/ingestion/utils/callable-flow-captures.d.ts +9 -0
- package/dist/core/ingestion/utils/callable-flow-captures.js +75 -14
- package/dist/core/ingestion/utils/test-file-path.d.ts +28 -0
- package/dist/core/ingestion/utils/test-file-path.js +87 -0
- package/dist/core/ingestion/variable-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/variable-extractors/configs/zig.js +71 -0
- package/dist/core/ingestion/workers/parse-worker.js +85 -14
- package/dist/core/install-context.d.ts +4 -0
- package/dist/core/install-context.js +152 -0
- package/dist/core/lbug/csv-generator.d.ts +10 -1
- package/dist/core/lbug/csv-generator.js +92 -22
- package/dist/core/lbug/graph-emit-sink.d.ts +3 -2
- package/dist/core/lbug/graph-emit-sink.js +4 -2
- package/dist/core/lbug/lbug-adapter.d.ts +100 -5
- package/dist/core/lbug/lbug-adapter.js +236 -24
- package/dist/core/lbug/schema.d.ts +6 -5
- package/dist/core/lbug/schema.js +84 -22
- package/dist/core/net/url-guard.d.ts +6 -0
- package/dist/core/net/url-guard.js +147 -0
- package/dist/core/package-version.d.ts +5 -0
- package/dist/core/package-version.js +10 -0
- package/dist/core/run-analyze.d.ts +21 -4
- package/dist/core/run-analyze.js +426 -117
- package/dist/core/search/fts-indexes.d.ts +19 -1
- package/dist/core/search/fts-indexes.js +28 -1
- package/dist/core/tree-sitter/parser-loader.js +16 -0
- package/dist/core/update-cache.d.ts +39 -0
- package/dist/core/update-cache.js +141 -0
- package/dist/core/update-check.d.ts +31 -0
- package/dist/core/update-check.js +274 -0
- package/dist/mcp/local/local-backend.d.ts +27 -13
- package/dist/mcp/local/local-backend.js +148 -60
- package/dist/mcp/repository-policy.d.ts +5 -1
- package/dist/mcp/repository-policy.js +48 -4
- package/dist/mcp/resources.js +10 -1
- package/dist/mcp/server.js +8 -9
- package/dist/mcp/tools.js +32 -22
- package/dist/server/analyze-launch.d.ts +2 -0
- package/dist/server/analyze-launch.js +2 -0
- package/dist/server/analyze-worker-protocol.d.ts +6 -1
- package/dist/server/analyze-worker.d.ts +1 -0
- package/dist/server/analyze-worker.js +38 -20
- package/dist/server/api.d.ts +5 -1
- package/dist/server/api.js +105 -88
- package/dist/server/git-clone.d.ts +40 -16
- package/dist/server/git-clone.js +253 -199
- package/dist/server/grep-params.d.ts +18 -0
- package/dist/server/grep-params.js +83 -0
- package/dist/server/grep-scan.d.ts +23 -0
- package/dist/server/grep-scan.js +107 -0
- package/dist/server/grep-worker.d.ts +1 -0
- package/dist/server/grep-worker.js +12 -0
- package/dist/server/mcp-http.d.ts +8 -0
- package/dist/server/mcp-http.js +16 -1
- package/dist/server/update-controller.d.ts +29 -0
- package/dist/server/update-controller.js +82 -0
- package/dist/storage/file-lock.d.ts +15 -0
- package/dist/storage/file-lock.js +155 -0
- package/dist/storage/fs-atomic.d.ts +24 -0
- package/dist/storage/fs-atomic.js +86 -2
- package/dist/storage/global-dir.d.ts +2 -0
- package/dist/storage/global-dir.js +6 -0
- package/dist/storage/parse-cache.d.ts +45 -7
- package/dist/storage/parse-cache.js +189 -42
- package/dist/storage/parsedfile-store.d.ts +41 -60
- package/dist/storage/parsedfile-store.js +247 -171
- package/dist/storage/repo-manager.d.ts +10 -4
- package/dist/storage/repo-manager.js +35 -25
- package/dist/storage/repo-meta.d.ts +34 -0
- package/dist/storage/v8-sidecar.d.ts +48 -0
- package/dist/storage/v8-sidecar.js +347 -0
- package/dist/types/pipeline.d.ts +14 -0
- package/dist/utils/process-identity.d.ts +2 -0
- package/dist/utils/process-identity.js +35 -0
- package/package.json +10 -4
- package/scripts/assert-web-assets.mjs +35 -0
- package/scripts/build-web.js +72 -0
- package/scripts/build.js +31 -28
- package/scripts/cross-platform-tests.ts +5 -0
- package/skills/gitnexus-cli.md +5 -1
- package/web/assets/ProcessFlowModal-DAeX2BHW.js +24 -0
- package/web/assets/{abnfDiagram-QNN2D4NM-Cq2djWWe.js → abnfDiagram-PAR5IXJI-J3OdeHLl.js} +1 -1
- package/web/assets/{agent-BWAXPjC5.js → agent-BMRqXorA.js} +6 -4
- package/web/assets/architecture-7GRP2DOG-M7G3SWCO-G3sWyX6M.js +1 -0
- package/web/assets/architectureDiagram-2PNWDENW-ysKcRlGT.js +36 -0
- package/web/assets/blockDiagram-PUWGUBOA-oLXTa1lY.js +129 -0
- package/web/assets/c4Diagram-3NLNHZP5-D3iu4eC0.js +38 -0
- package/web/assets/{chunk-2SREHG4O-Dip42xOq.js → chunk-2NMSUPJH-B24w-wng.js} +1 -1
- package/web/assets/{chunk-VJFVEZTB-CX66F2ep.js → chunk-32MCUW2P-ByUyt0Sa.js} +3 -3
- package/web/assets/{chunk-4RFN2BYJ-DHHWuC-n.js → chunk-3NPNU5GP-DocZ07Sg.js} +1 -1
- package/web/assets/{chunk-XNMVGMAZ-Cg_LnPtj.js → chunk-3SMGFRGC-CAu4JRLv.js} +1 -1
- package/web/assets/{chunk-W44A43WB-BN8EQc_u.js → chunk-4CAJECRU-DRYMwG9z.js} +1 -1
- package/web/assets/chunk-4OADUZ5Q-CxrSvOwZ.js +10 -0
- package/web/assets/{chunk-DMV4VAQV-Bn6WXDSX.js → chunk-5IQCK5RY-CCMhl4so.js} +2 -2
- package/web/assets/{chunk-RRFMTAIC-CMN0wcYA.js → chunk-5MVFYWFU-Db9KvrYO.js} +1 -1
- package/web/assets/chunk-CLS4B6BI-Uvx5QNsu.js +168 -0
- package/web/assets/chunk-DZP67EKU-B3Mt380j.js +70 -0
- package/web/assets/{chunk-6L755F7B-CMhLBxi2.js → chunk-EICP7K5X-CqwE9hui.js} +1 -1
- package/web/assets/{chunk-BI6VK774-D0oaWk8V.js → chunk-GDY2UAB4-CtQQR0a8.js} +1 -1
- package/web/assets/chunk-H7VHZCWX-CE1nAmt6.js +1 -0
- package/web/assets/chunk-IJBDOHL6-BUKtY6oF.js +1 -0
- package/web/assets/{chunk-OIYT25JQ-CQ6KOZGX.js → chunk-JFFVMJIA-0fJenqia.js} +1 -1
- package/web/assets/{chunk-HNC4WDU7-DoU3KnA7.js → chunk-JZGDI5JK-BeTMSSkJ.js} +1 -1
- package/web/assets/{chunk-EQFTRU2I-1ix7TzW9.js → chunk-KD6SPIPN-Qp1Pflah.js} +1 -1
- package/web/assets/chunk-NF366YI6-CpSpya3n.js +231 -0
- package/web/assets/chunk-NUDPKBEF-CU1-BQIW.js +34 -0
- package/web/assets/{chunk-SATU7PGQ-B1zhgOvc.js → chunk-OJINMHTS-zOCQe4eI.js} +1 -1
- package/web/assets/{chunk-E5QJAATJ-dh-5CtIV.js → chunk-Q6NGPIAH-yyBomb63.js} +1 -1
- package/web/assets/chunk-QJSWEUOL-D_rf9gPD.js +128 -0
- package/web/assets/chunk-R7JDMUKV-CRoqKpD6.js +1 -0
- package/web/assets/{chunk-VE5CLXGZ-C1vB7wpY.js → chunk-RCXAM2GK-CUqrWQDV.js} +1 -1
- package/web/assets/{chunk-66DQ2XMT-CM0xjFAN.js → chunk-RT4MAWR3-zXy9-Lvt.js} +1 -1
- package/web/assets/{chunk-TZUXEDM2-B7p9AcTw.js → chunk-SFMINX4W-J2UrvMpD.js} +1 -1
- package/web/assets/{chunk-LORZLZWG-B57uGw2N.js → chunk-SLDQ463B-CHY6e_bQ.js} +2 -2
- package/web/assets/{chunk-FWYVLQTC-BgDItRzJ.js → chunk-TCEHX7R3-CXPDEVbm.js} +1 -1
- package/web/assets/{chunk-224SPVON-B8gxtXpy.js → chunk-VQC2EELJ-Dc8fIy4R.js} +1 -1
- package/web/assets/chunk-VRZKL3EH-DB3KixTQ.js +1 -0
- package/web/assets/{chunk-A7VWPJGB-B4O3oQdQ.js → chunk-VTHDQ7BV-b7FsPQZO.js} +1 -1
- package/web/assets/chunk-VY2OSTJR-Dkgc3Brg.js +2 -0
- package/web/assets/chunk-WUBWJARI-7FwILJ3k.js +2 -0
- package/web/assets/{chunk-D6VWDJW2-BxcBdZ9c.js → chunk-YBMQ5JGJ-BSnyWZmd.js} +1 -1
- package/web/assets/chunk-YDMLL4PJ-IHhMngTz.js +2 -0
- package/web/assets/chunk-Z6V44ARX-BjCEsF0Q.js +62 -0
- package/web/assets/chunk-ZJJ7VQJP-Dz089b-K.js +321 -0
- package/web/assets/chunk-ZNLK7HRR-B0iFpmW4.js +1 -0
- package/web/assets/chunk-ZQN7UHIL-Cy7KAjQt.js +1 -0
- package/web/assets/{chunk-L5GCOVLC-CE2w8Nm_.js → chunk-ZS6VBONO-DBjJO0w9.js} +2 -2
- package/web/assets/{chunk-NV3KIAZN-5yvcpMiu.js → chunk-ZUNWM646-DNRJyNPe.js} +1 -1
- package/web/assets/classDiagram-FGAMPOII-C5Ibyode.js +1 -0
- package/web/assets/classDiagram-v2-AI5RJEK4-C5Ibyode.js +1 -0
- package/web/assets/{cose-bilkent-RZA4XIPR-BHpK4Crp.js → cose-bilkent-Q72C2OJ3-DMeFXnK8.js} +1 -1
- package/web/assets/cynefin-OW5HDTMX-6OCTWOGG-vlqakYcO.js +1 -0
- package/web/assets/{cynefinDiagram-TR7LZUCG-C3Iar9lZ.js → cynefinDiagram-2OOWUY4M-BY6DZkTt.js} +1 -1
- package/web/assets/dagre-MPVFI544-DWO70fy_.js +4 -0
- package/web/assets/diagram-AE4NWXFW-f7JRVRUL.js +24 -0
- package/web/assets/{diagram-L7DVE3PN-GIRyVUtt.js → diagram-BUJID5UG-BXZv1rCS.js} +2 -2
- package/web/assets/{diagram-JCD7PQ7C-DC5-9FRr.js → diagram-C44CZ5NI-CRNfvjCq.js} +1 -1
- package/web/assets/diagram-EYOLEXXS-DZOjKQVE.js +30 -0
- package/web/assets/diagram-P7B6PWOJ-D3SQmw3_.js +3 -0
- package/web/assets/{ebnfDiagram-DRHRQJWO-D8_CI4ZF.js → ebnfDiagram-FTPZ3PV6-jKWpIDN2.js} +1 -1
- package/web/assets/erDiagram-H3ERR26V-BqJntEuJ.js +99 -0
- package/web/assets/eventmodeling-NTZA5JFV-WKSWQHFS-Bq4FqtBL.js +1 -0
- package/web/assets/flowDiagram-YHGXBVSY-Dnlk2bEu.js +1 -0
- package/web/assets/ganttDiagram-RWFTB7ED-Bl6Y1K5T.js +292 -0
- package/web/assets/gitGraph-4MIJSDKK-JH2HKYUO-B3yc4GkH.js +1 -0
- package/web/assets/gitGraphDiagram-MAR6GKOP-CkNvsrdw.js +106 -0
- package/web/assets/{index-CJDpyH-n.css → index-C2_aej58.css} +1 -1
- package/web/assets/{index-DDRie6_8.js → index-Dj3vQOHK.js} +51 -51
- package/web/assets/info-A6RAGUB7-3TX3OFWW-BM3N5_Dv.js +1 -0
- package/web/assets/infoDiagram-LV547AFH-COkFutAf.js +2 -0
- package/web/assets/{ishikawaDiagram-4JDSWWDM-DmqWtjkl.js → ishikawaDiagram-PUJQGNDS-Bb8FylSR.js} +2 -2
- package/web/assets/{journeyDiagram-QUS3FAKT-XAzVzrQW.js → journeyDiagram-EW5QJT4W-BzoHUBhM.js} +4 -4
- package/web/assets/{kanban-definition-D4L7SQKK-YurRnmYn.js → kanban-definition-JSQERAZB-Uy2Pi0yQ.js} +4 -4
- package/web/assets/katex-CZ4GXH2S-C0Fcou7U.js +257 -0
- package/web/assets/{mindmap-definition-66QP5TD6-ChrWWnil.js → mindmap-definition-VBJCLQLM-B-CnOnt_.js} +3 -3
- package/web/assets/packet-AYTQ26CC-MKII6P3Y-Bd52ZE3V.js +1 -0
- package/web/assets/{pegDiagram-YKIO5C6U-QGeQLEq2.js → pegDiagram-7WILOQTJ-D9sneKXg.js} +1 -1
- package/web/assets/pie-WAS4IAKB-6B4OPMJ5-DW5Xy69Z.js +1 -0
- package/web/assets/pieDiagram-EFA7CBSB-Dx2NQofL.js +39 -0
- package/web/assets/{quadrantDiagram-VO5QLCXA-B7098wSc.js → quadrantDiagram-WARVYA7P-DPKL9_0A.js} +3 -3
- package/web/assets/radar-RG4KPBEZ-UPTR3XUL-CkzibT2h.js +1 -0
- package/web/assets/railroad-74A4TZTK-MEFUPFMS-D9zF-mDN.js +1 -0
- package/web/assets/railroad-abnf-HS5TGJTU-R5YG2S5D-ruacjUbX.js +1 -0
- package/web/assets/railroad-ebnf-LZEXJU2U-G5QEX2L6-S1zc5OiO.js +1 -0
- package/web/assets/railroad-peg-WCYAUIDC-H5I2ZRY2-Cbcr0XzY.js +1 -0
- package/web/assets/{railroadDiagram-M77LTMSB-AXu4vxk_.js → railroadDiagram-5NIQVNLQ-DsweTo14.js} +1 -1
- package/web/assets/{requirementDiagram-RASO5HTO-B-l8InpK.js → requirementDiagram-SXREGOKZ-CXwdNSVR.js} +4 -4
- package/web/assets/{sankeyDiagram-F32LOJ6L-Kd7zjJgX.js → sankeyDiagram-VV74M2VP-CA6jtP9P.js} +3 -3
- package/web/assets/{sequenceDiagram-URATNSBD-BlcdY9DS.js → sequenceDiagram-52ZFIFDL-k_5rEbzm.js} +15 -15
- package/web/assets/src-Df5C1Nz4.js +1 -0
- package/web/assets/stateDiagram-3QAKPIVI-BejHTf31.js +1 -0
- package/web/assets/stateDiagram-v2-HN2P4RDZ-BrfoRuOc.js +1 -0
- package/web/assets/swimlanes-QLVP42QD-CQSVO5D6.js +1 -0
- package/web/assets/swimlanesDiagram-JKPDBFCN-DrWB9kcD.js +8 -0
- package/web/assets/{timeline-definition-WJXWRH4I-DUfp1R3E.js → timeline-definition-GS45XAXW-C0Ks8rPP.js} +4 -4
- package/web/assets/treeView-Q6P3EWNA-ZRJGANNQ-DmKOCo6L.js +1 -0
- package/web/assets/treemap-WGGIJYW6-K64VN5AS-DO3xY92U.js +1 -0
- package/web/assets/{vennDiagram-K3VCMQLI-Bj-FN-XS.js → vennDiagram-QIQU2ZRJ-rgPiS837.js} +3 -3
- package/web/assets/wardley-WFR3VGLG-D67OWCCH-DiDPBNft.js +1 -0
- package/web/assets/wardleyDiagram-U6YNM66N-DRVr7SPi.js +78 -0
- package/web/assets/{xychartDiagram-5VRUVLCW-CK_rbSWE.js → xychartDiagram-XJAZEDNM-COtlZzYb.js} +3 -3
- package/web/index.html +19 -17
- package/web/assets/ProcessFlowModal-Badh2Pbg.js +0 -24
- package/web/assets/architecture-TIHT7OUA-V6N4J3SY-fTePvLoe.js +0 -1
- package/web/assets/architectureDiagram-OT7VKSJ7-mKEXxkeF.js +0 -36
- package/web/assets/blockDiagram-54WLDVWM-Dg_hrRWE.js +0 -132
- package/web/assets/c4Diagram-X2LASM7V-CnhoT4aV.js +0 -10
- package/web/assets/chunk-2AEHWXPW-CV4r6-1I.js +0 -127
- package/web/assets/chunk-5VCL7Z4A-CQ-2dYWj.js +0 -1
- package/web/assets/chunk-6BELYETK-ChsYtfHW.js +0 -1
- package/web/assets/chunk-7CWYLC5S-DRgGkkpF.js +0 -2
- package/web/assets/chunk-7FYTHRHK-CsmYIswB.js +0 -32
- package/web/assets/chunk-KRXBNO2N-C-UNuKKf.js +0 -1
- package/web/assets/chunk-LAHSG3N2-Bz4hcn0N.js +0 -321
- package/web/assets/chunk-LIEV3EAG-pyKGssV3.js +0 -1
- package/web/assets/chunk-NLANEA3F-XpH_NPA5.js +0 -62
- package/web/assets/chunk-PE7DX7ZZ-CCvRVj43.js +0 -10
- package/web/assets/chunk-Q67WD55A-BWCH2SVz.js +0 -156
- package/web/assets/chunk-SZD42YQK-ijyKKVr1.js +0 -70
- package/web/assets/chunk-TFPGFQPA-Dj6a-0pC.js +0 -231
- package/web/assets/chunk-TGVD4F4B-BMc31Gj2.js +0 -2
- package/web/assets/chunk-UAT7B5JY-DW-A_fpI.js +0 -1
- package/web/assets/chunk-VY5UBI4V-yxPQAWxw.js +0 -1
- package/web/assets/chunk-WJBAP47W-BckNkuEN.js +0 -1
- package/web/assets/classDiagram-VPOSVPXH-BjOiXA_C.js +0 -1
- package/web/assets/classDiagram-v2-5VFNUXQA-BjOiXA_C.js +0 -1
- package/web/assets/cynefin-VYW2F7L2-2VAHYKR6-DAsF6GZv.js +0 -1
- package/web/assets/dagre-K64A6Z3X-CUwi79mA.js +0 -4
- package/web/assets/diagram-2TLGJV2N-C2F5Nfym.js +0 -30
- package/web/assets/diagram-KFBZAVDW-Dfmf_4ti.js +0 -3
- package/web/assets/diagram-YP3FGXHI-CyNFYtkd.js +0 -24
- package/web/assets/erDiagram-SZLJLQMB-CohQjznC.js +0 -85
- package/web/assets/eventmodeling-45OFAUF4-AOUJWSLX-BvTc6iQi.js +0 -1
- package/web/assets/flowDiagram-BWE6NHOH-B6RnEvD9.js +0 -1
- package/web/assets/ganttDiagram-2QTCJSNI-Cks_mEcF.js +0 -292
- package/web/assets/gitGraph-TEB2WS4Q-U5VWYIBC-Dy7CCSZ5.js +0 -1
- package/web/assets/gitGraphDiagram-VVZAVV5G-CG41cIVc.js +0 -106
- package/web/assets/info-DKCQHKI2-DX6KST54-BLJg1ikX.js +0 -1
- package/web/assets/infoDiagram-FY4PZKRE-BJ3vPVwW.js +0 -2
- package/web/assets/katex-C5OPUE3Q-Bnbavtmu.js +0 -257
- package/web/assets/packet-7NZHBO7P-5WG45QPS-KUxcuvaA.js +0 -1
- package/web/assets/pie-RZYD4A2V-2OCZ2VTD-DPs08kJY.js +0 -1
- package/web/assets/pieDiagram-YPY3TKG5-BuT3MYzm.js +0 -39
- package/web/assets/radar-I7S5WNFK-EPLSA35B-w5F0K3a7.js +0 -1
- package/web/assets/railroad-3IZDKUUU-PWFQV6Y6-Bu668yqY.js +0 -1
- package/web/assets/railroad-abnf-AHOZXSZD-JYYJX3BS-B6ghpETS.js +0 -1
- package/web/assets/railroad-ebnf-EBAXGLYW-RBZ4ONAP-D-XmHh3M.js +0 -1
- package/web/assets/railroad-peg-LSFZ7HO6-KHNPXGPG-mhkrhzEn.js +0 -1
- package/web/assets/src-C5sx_gMp.js +0 -1
- package/web/assets/stateDiagram-DODFXNG5-DTdHc-fF.js +0 -1
- package/web/assets/stateDiagram-v2-JNMM5JRA-DioNLDDo.js +0 -1
- package/web/assets/swimlanes-OSWOYLSK-CA0ofdwY.js +0 -2
- package/web/assets/swimlanesDiagram-RHGX2RDE-PkwUdckC.js +0 -8
- package/web/assets/treeView-QDETBFTQ-EHYTSQNO-C5lpBgPm.js +0 -1
- package/web/assets/treemap-6X3UGDF4-CCWCF7EK-BB0ZyO-B.js +0 -1
- package/web/assets/wardley-OPB4EBWU-6OWERDVT-CEA3Nq0j.js +0 -1
- package/web/assets/wardleyDiagram-XK6FUAWV-CVV0dHFr.js +0 -78
- /package/web/assets/{sizeCapture-5GORAGP4-BEqQzsxs.js → sizeCapture-FGA5AGYP-BEqQzsxs.js} +0 -0
package/dist/core/run-analyze.js
CHANGED
|
@@ -21,11 +21,11 @@ import { logUnresolvedReceiverFiles, summarizeUnresolvedReceivers, } from './ing
|
|
|
21
21
|
import { summarizeUndecidedSatisfaction } from './ingestion/scope-resolution/undecided-satisfaction.js';
|
|
22
22
|
import { summarizeScopeExtractionFailures } from './ingestion/scope-resolution/scope-extraction-failures.js';
|
|
23
23
|
import { resetDegradedParseCounter } from './tree-sitter/safe-parse.js';
|
|
24
|
-
import { initLbug, loadGraphToLbug, getLbugStats, executeQuery, executeWithReusedStatement, closeLbug, closeLbugBeforeExit, loadCachedEmbeddings, deleteNodesForFiles, ensureEmbeddingRowDmlSafe, ensureFtsRowDmlSafe, readIndexCatalogSnapshot, INDEX_CATALOG_UNREADABLE, deleteAllCommunitiesAndProcesses, deleteAllInterprocTaintPaths, deleteAllCallSummaries, deleteAllInjects, deleteAllAdvisedBy, deleteSpringAopEvidenceNodes, deleteSpringAutoConfigurationDeclarations, deleteSpringAutoConfigurationSyntheticClasses, queryImportersBatch, loadFTSExtension, wipeLbugDbFiles, LbugWipeError, DELETE_FILES_CHUNK_SIZE, } from './lbug/lbug-adapter.js';
|
|
24
|
+
import { initLbug, loadGraphToLbug, getLbugStats, executeQuery, executeWithReusedStatement, closeLbug, closeLbugBeforeExit, loadCachedEmbeddings, deleteNodesForFiles, nodeTablesWithRowsForFiles, snapshotDerivedRelsForFiles, restoreDerivedRels, ensureEmbeddingRowDmlSafe, ensureFtsRowDmlSafe, readIndexCatalogSnapshot, INDEX_CATALOG_UNREADABLE, deleteAllCommunitiesAndProcesses, deleteAllInterprocTaintPaths, deleteAllCallSummaries, deleteAllInjects, deleteAllAdvisedBy, deleteAllDestinations, deleteSpringAopEvidenceNodes, deleteSpringAutoConfigurationDeclarations, deleteSpringAutoConfigurationSyntheticClasses, queryImportersBatch, loadFTSExtension, wipeLbugDbFiles, LbugWipeError, DELETE_FILES_CHUNK_SIZE, } from './lbug/lbug-adapter.js';
|
|
25
25
|
import { estimateBufferPool, setBufferPoolSizeHint, resolveNativeSafeStorageDir, } from './lbug/lbug-config.js';
|
|
26
26
|
import { escapeCypherString } from './lbug/cypher-escape.js';
|
|
27
27
|
import { chunk } from '../lib/utils.js';
|
|
28
|
-
import { buildSearchIndexesOrDegrade, ftsFailureIsFatal, createSearchFTSIndexes, summarizeFtsIndexBuildFailures, dropSearchFTSIndexes, initialiseSearchFTSStemmer, verifySearchFTSIndexes, } from './search/fts-indexes.js';
|
|
28
|
+
import { buildSearchIndexesOrDegrade, ftsFailureIsFatal, createSearchFTSIndexes, summarizeFtsIndexBuildFailures, dropSearchFTSIndexes, missingSearchFTSIndexTables, initialiseSearchFTSStemmer, verifySearchFTSIndexes, } from './search/fts-indexes.js';
|
|
29
29
|
import { cjkSegmentationModeMismatch, getSearchFTSCjkSegmentation, initialiseSearchFTSCjkSegmentation, } from './search/cjk-segmentation.js';
|
|
30
30
|
import { getExtensionCapability, getExtensionCapabilities, getFtsCapability, resolveAnalyzeInstallPolicy, } from './lbug/extension-loader.js';
|
|
31
31
|
import { diagnoseExtensionLoad } from './lbug/extension-load-error.js';
|
|
@@ -41,10 +41,13 @@ import { taintModelVersion } from './ingestion/taint/typescript-model.js';
|
|
|
41
41
|
import { parseTruthyEnv, parsePositiveIntEnv } from './ingestion/utils/env.js';
|
|
42
42
|
import { computeFileHashes, diffFileHashes } from '../storage/file-hash.js';
|
|
43
43
|
import { extractChangedSubgraph, computeEffectiveWriteSet, } from './incremental/subgraph-extract.js';
|
|
44
|
+
import { collectSpringConfigConsumerDriftFiles, } from './incremental/spring-config-drift.js';
|
|
44
45
|
import { shadowCandidatesFor } from './incremental/shadow-candidates.js';
|
|
45
46
|
import { shouldEscalateIncrementalWrite } from './incremental/escalation-gate.js';
|
|
46
|
-
import {
|
|
47
|
-
import {
|
|
47
|
+
import { ftsTablesAmong, incrementalFtsTablesFromGraph, nodeTablesForIncrementalDelete, shouldPreservePersistedDerivedGraph, } from './incremental/derived-writeback.js';
|
|
48
|
+
import { NODE_TABLES } from './lbug/schema.js';
|
|
49
|
+
import { loadParseCache, saveParseCache, pruneCache, PARSE_CACHE_VERSION, createColdParseRebuildDir, emptyParseCache, forgetCreatedParseCacheDir, } from '../storage/parse-cache.js';
|
|
50
|
+
import { mergeStagedDurableParsedFileStore } from '../storage/parsedfile-store.js';
|
|
48
51
|
import { getCurrentCommit, getCurrentBranch, getRemoteUrl, hasGitDir, getInferredRepoName, isWorkingTreeDirty, listWorkingTreeDirtyPaths, resolveRepoIdentityRoot, } from '../storage/git.js';
|
|
49
52
|
import { isGitNexusManagedPath } from '../storage/gitnexus-managed-paths.js';
|
|
50
53
|
import { getMaxFileSizeBytes } from './ingestion/utils/max-file-size.js';
|
|
@@ -53,9 +56,12 @@ import { sanitizeDetectedBranch } from '../cli/analyze-config.js';
|
|
|
53
56
|
import { EMBEDDING_TABLE_NAME, EMBEDDING_DIMS, STALE_HASH_SENTINEL, SCHEMA_FINGERPRINT, schemaFingerprintMismatch, isSchemaFingerprintShaped, embeddingDimsMismatch, } from './lbug/schema.js';
|
|
54
57
|
import { isSpringBeanCandidateSourceFile } from './ingestion/frameworks/spring/bean-catalog.js';
|
|
55
58
|
import { isSpringBeanFactoryDeclaration } from './ingestion/frameworks/spring/bean-factories.js';
|
|
56
|
-
import {
|
|
57
|
-
import {
|
|
58
|
-
import {
|
|
59
|
+
import { SPRING_CONFIG_UNRESOLVED_PREFIX } from './ingestion/frameworks/spring/config-bindings.js';
|
|
60
|
+
import { classifySpringConfigFile } from './ingestion/pipeline-phases/spring-config.js';
|
|
61
|
+
import { SPRING_ROUTE_BINDINGS_FEATURE } from './ingestion/frameworks/spring/analysis-features.js';
|
|
62
|
+
import { springVendorPrefixesKey } from './ingestion/frameworks/spring/vendor-prefixes.js';
|
|
63
|
+
import { findAnalysisFeatureMismatches, resolveAnalysisFeatureVersions, } from './analysis-features.js';
|
|
64
|
+
import { ANALYSIS_FEATURES } from './analysis-feature-registry.js';
|
|
59
65
|
import { analyzerRunnerIdentitiesEqual, finalizeAnalyzerRunnerIdentity, resolveAnalyzerRunnerIdentity, } from './analyzer-identity.js';
|
|
60
66
|
// Static, and deliberately so: `embedding-count.ts` and `embedding-checkpoint.ts`
|
|
61
67
|
// live outside `core/embeddings/` precisely because the lazy-embeddings
|
|
@@ -79,16 +85,6 @@ import { EMBEDDING_RESUME_MAX_ATTEMPTS, decideEmbeddingResume, mintInterruptedCh
|
|
|
79
85
|
* Newline and tab are preserved — multi-line notices are intentional.
|
|
80
86
|
*/
|
|
81
87
|
const stripControlCharacters = (msg) => msg.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g, '');
|
|
82
|
-
const ANALYSIS_FEATURES = [
|
|
83
|
-
CLASS_FRAMEWORK_ANNOTATIONS_FEATURE,
|
|
84
|
-
SPRING_AOP_FEATURE,
|
|
85
|
-
SPRING_BEAN_INVENTORY_FEATURE,
|
|
86
|
-
SPRING_CONDITIONALS_FEATURE,
|
|
87
|
-
SPRING_NON_HTTP_HANDLERS_FEATURE,
|
|
88
|
-
SPRING_CONFIG_BINDINGS_FEATURE,
|
|
89
|
-
JAVA_ENUM_INTERFACE_HERITAGE_FEATURE,
|
|
90
|
-
JAVA_RECORD_COMPONENT_ACCESSORS_FEATURE,
|
|
91
|
-
];
|
|
92
88
|
function stringList(value) {
|
|
93
89
|
return Array.isArray(value)
|
|
94
90
|
? value.filter((item) => typeof item === 'string')
|
|
@@ -557,6 +553,17 @@ async function resolveWriteTarget(repoPath, options) {
|
|
|
557
553
|
metaDir: path.dirname(metaPath),
|
|
558
554
|
};
|
|
559
555
|
}
|
|
556
|
+
async function removeColdParseRebuildDir(dir, ignoreErrors) {
|
|
557
|
+
if (!dir)
|
|
558
|
+
return;
|
|
559
|
+
try {
|
|
560
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
561
|
+
}
|
|
562
|
+
catch (err) {
|
|
563
|
+
if (!ignoreErrors)
|
|
564
|
+
throw err;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
560
567
|
/**
|
|
561
568
|
* Run the full analysis under an exclusive, index-directory-scoped write lock
|
|
562
569
|
* (#2658). A second concurrent `analyze` on the same slot waits here for the
|
|
@@ -634,6 +641,7 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
634
641
|
// selects a `branches/<slug>/` sub-slot only for an explicit `--branch` that
|
|
635
642
|
// does not own the flat slot. See resolveWriteTarget for the full contract.
|
|
636
643
|
const { storagePath, repoHasGit, currentCommit, branchLabel, placement, lbugPath, metaDir } = writeTarget;
|
|
644
|
+
let coldParseRebuildDir;
|
|
637
645
|
// Start each analyze with a clean buffer-pool hint: any pre-pipeline DB open
|
|
638
646
|
// (e.g. the embeddings-cache open) falls back to the default until the hint is
|
|
639
647
|
// set from the built graph below, so a prior run's size can't leak in.
|
|
@@ -798,6 +806,13 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
798
806
|
}
|
|
799
807
|
progress('fts', 90, 'Search indexes ready');
|
|
800
808
|
progress('done', 100, 'Done');
|
|
809
|
+
if (options.registryName) {
|
|
810
|
+
await registerRepo(repoPath, existingMeta, {
|
|
811
|
+
name: options.registryName,
|
|
812
|
+
allowDuplicateName: options.allowDuplicateName,
|
|
813
|
+
branch: placement.branch,
|
|
814
|
+
});
|
|
815
|
+
}
|
|
801
816
|
return {
|
|
802
817
|
repoName: options.registryName ??
|
|
803
818
|
getInferredRepoName(repoPath) ??
|
|
@@ -1029,6 +1044,15 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
1029
1044
|
options = { ...options, force: true };
|
|
1030
1045
|
analysisFeatureMismatchLogged = true;
|
|
1031
1046
|
}
|
|
1047
|
+
const currentSpringVendorPrefixes = springVendorPrefixesKey();
|
|
1048
|
+
const persistedRouteBindings = existingMeta?.analysisFeatures?.[SPRING_ROUTE_BINDINGS_FEATURE.id];
|
|
1049
|
+
if (existingMeta &&
|
|
1050
|
+
persistedRouteBindings === SPRING_ROUTE_BINDINGS_FEATURE.version &&
|
|
1051
|
+
existingMeta.springVendorPrefixes !== currentSpringVendorPrefixes) {
|
|
1052
|
+
log('Spring vendor mapping prefixes changed; forcing a full rebuild so persisted Route ' +
|
|
1053
|
+
'evidence matches the configured aliases.');
|
|
1054
|
+
options = { ...options, force: true };
|
|
1055
|
+
}
|
|
1032
1056
|
// Analyzer provenance is part of freshness, not merely diagnostics. A
|
|
1033
1057
|
// same-commit fast path must not preserve metadata produced by an older,
|
|
1034
1058
|
// malformed, or dependency/native-different runner. Force a real rebuild so
|
|
@@ -1083,6 +1107,82 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
1083
1107
|
`new width. Tip: set GITNEXUS_EMBEDDING_DIMS (or --embedding-dims) to pin it across runs.`);
|
|
1084
1108
|
options = { ...options, force: true };
|
|
1085
1109
|
}
|
|
1110
|
+
// Actuator snapshots are external runtime inputs and are intentionally not
|
|
1111
|
+
// hashed or persisted. Rebuild on every enabled run so updated snapshots
|
|
1112
|
+
// cannot hit the git freshness fast path; rebuild once when the option is
|
|
1113
|
+
// removed so stale runtime-only evidence is cleared from the index.
|
|
1114
|
+
const springActuatorRequested = options.springActuatorPath !== undefined;
|
|
1115
|
+
const springActuatorPreviouslyEnabled = existingMeta?.springActuator?.enabled === true;
|
|
1116
|
+
const previousActuatorInputs = existingMeta?.springActuator?.repoRelativeInputs;
|
|
1117
|
+
const retainedActuatorInputs = Array.isArray(previousActuatorInputs)
|
|
1118
|
+
? previousActuatorInputs.filter((input) => typeof input === 'string')
|
|
1119
|
+
: [];
|
|
1120
|
+
if (springActuatorRequested) {
|
|
1121
|
+
const resolvedRepo = path.resolve(repoPath);
|
|
1122
|
+
const resolvedInput = path.resolve(repoPath, options.springActuatorPath);
|
|
1123
|
+
const relativeInput = path.relative(resolvedRepo, resolvedInput);
|
|
1124
|
+
const springActuatorRepoRelativeInput = relativeInput === ''
|
|
1125
|
+
? '.'
|
|
1126
|
+
: relativeInput === '..' ||
|
|
1127
|
+
relativeInput.startsWith(`..${path.sep}`) ||
|
|
1128
|
+
path.isAbsolute(relativeInput)
|
|
1129
|
+
? null
|
|
1130
|
+
: relativeInput.split(path.sep).join('/');
|
|
1131
|
+
if (springActuatorRepoRelativeInput !== null &&
|
|
1132
|
+
!retainedActuatorInputs.includes(springActuatorRepoRelativeInput)) {
|
|
1133
|
+
retainedActuatorInputs.push(springActuatorRepoRelativeInput);
|
|
1134
|
+
}
|
|
1135
|
+
if (!options.force) {
|
|
1136
|
+
log('Spring Actuator runtime enrichment requested; forcing a full rebuild.');
|
|
1137
|
+
}
|
|
1138
|
+
options = { ...options, force: true };
|
|
1139
|
+
}
|
|
1140
|
+
else if (springActuatorPreviouslyEnabled) {
|
|
1141
|
+
if (!Array.isArray(previousActuatorInputs) ||
|
|
1142
|
+
previousActuatorInputs.some((input) => typeof input !== 'string')) {
|
|
1143
|
+
throw new Error('Cannot safely disable Spring Actuator runtime enrichment because the previous ' +
|
|
1144
|
+
'index did not record whether its snapshot was inside the repository. Re-run once ' +
|
|
1145
|
+
'with the previous --spring-actuator path, then run again without it.');
|
|
1146
|
+
}
|
|
1147
|
+
log('Spring Actuator runtime enrichment disabled; rebuilding to remove runtime evidence.');
|
|
1148
|
+
options = { ...options, force: true };
|
|
1149
|
+
}
|
|
1150
|
+
const springActuatorScanExclusions = retainedActuatorInputs.length === 0 ? undefined : retainedActuatorInputs;
|
|
1151
|
+
// AsyncAPI documents are the same class of input as Actuator snapshots and
|
|
1152
|
+
// need the same treatment, for a reason git cannot see: the documents live
|
|
1153
|
+
// outside the tree as often as in it, and NOTHING about replacing one moves
|
|
1154
|
+
// the commit or dirties the working tree. Without this, the second run of an
|
|
1155
|
+
// out-of-band cache — the workflow the option exists for — takes the
|
|
1156
|
+
// already-up-to-date fast path below, never opens a document, and serves the
|
|
1157
|
+
// previous run's addresses while reporting success. Measured, not reasoned:
|
|
1158
|
+
// editing a document and re-running printed "Already up to date" and left the
|
|
1159
|
+
// old address in the graph.
|
|
1160
|
+
//
|
|
1161
|
+
// Forcing the rebuild also settles a second defect for free. A synthetic
|
|
1162
|
+
// `File` node for an out-of-tree document (`asyncapi:<label>`) carries a path
|
|
1163
|
+
// that is in no write set and is not covered by `isGraphWideNode`, so on an
|
|
1164
|
+
// incremental writeback the node is dropped while its edges — anchored to a
|
|
1165
|
+
// graph-wide `Destination` — are kept, and the edges then COPY against a row
|
|
1166
|
+
// that was never written. A full rebuild has no incremental subgraph to get
|
|
1167
|
+
// that wrong, so the pair cannot come apart.
|
|
1168
|
+
const asyncApiSpecRequested = options.asyncApiSpecPath !== undefined;
|
|
1169
|
+
const asyncApiSpecPreviouslyEnabled = existingMeta?.asyncApiSpec?.enabled === true;
|
|
1170
|
+
if (asyncApiSpecRequested) {
|
|
1171
|
+
if (!options.force) {
|
|
1172
|
+
log('AsyncAPI document reading requested; forcing a full rebuild.');
|
|
1173
|
+
}
|
|
1174
|
+
options = { ...options, force: true };
|
|
1175
|
+
}
|
|
1176
|
+
else if (asyncApiSpecPreviouslyEnabled) {
|
|
1177
|
+
log('AsyncAPI document reading disabled; rebuilding to remove document-derived evidence.');
|
|
1178
|
+
options = { ...options, force: true };
|
|
1179
|
+
}
|
|
1180
|
+
// Programmatic `useParseCache: false` must set force or the up-to-date
|
|
1181
|
+
// guard returns before the empty-cache construction below.
|
|
1182
|
+
if (options.useParseCache === false && !options.force) {
|
|
1183
|
+
log('Parser cache bypass requested; forcing a full rebuild so unchanged files are re-parsed.');
|
|
1184
|
+
options = { ...options, force: true };
|
|
1185
|
+
}
|
|
1086
1186
|
// ── Early-return: already up to date ──────────────────────────────
|
|
1087
1187
|
if (existingMeta &&
|
|
1088
1188
|
!existingMeta.embeddingCheckpoint &&
|
|
@@ -1132,6 +1232,30 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
1132
1232
|
// later read on a host where it loads — which is a legitimate, common
|
|
1133
1233
|
// state, and the invariant `analyzer-identity-cli.test.ts` pins.
|
|
1134
1234
|
if (!dirty && !healUnregistered) {
|
|
1235
|
+
if (options.registryName) {
|
|
1236
|
+
await registerRepo(repoPath, existingMeta, {
|
|
1237
|
+
name: options.registryName,
|
|
1238
|
+
allowDuplicateName: options.allowDuplicateName,
|
|
1239
|
+
branch: placement.branch,
|
|
1240
|
+
});
|
|
1241
|
+
if (!placement.branch) {
|
|
1242
|
+
try {
|
|
1243
|
+
await generateAIContextFiles(repoPath, storagePath, options.registryName, existingMeta.stats ?? {}, undefined, {
|
|
1244
|
+
skipAgentsMd: options.skipAgentsMd,
|
|
1245
|
+
skipSkills: options.skipSkills,
|
|
1246
|
+
noStats: options.noStats,
|
|
1247
|
+
defaultBranch: options.defaultBranch,
|
|
1248
|
+
// Fast path does not re-run PDG. Using `options.pdg` would
|
|
1249
|
+
// strip PDG bullets from AGENTS.md on a rename-only analyze.
|
|
1250
|
+
hasPdg: existingMeta.pdg != null,
|
|
1251
|
+
hasSpringActuator: existingMeta.springActuator?.enabled === true,
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
catch {
|
|
1255
|
+
/* best-effort — never fail the fast path over a context refresh */
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1135
1259
|
// ── #2354: restamp the workspace label on a same-commit branch flip ──
|
|
1136
1260
|
// The flat slot follows the checked-out working tree; a branch switch
|
|
1137
1261
|
// at the SAME commit with a clean tree changes nothing the pipeline
|
|
@@ -1256,11 +1380,17 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
1256
1380
|
}
|
|
1257
1381
|
}
|
|
1258
1382
|
// ── Load incremental parse cache ──────────────────────────────────
|
|
1259
|
-
// Content-addressed:
|
|
1260
|
-
//
|
|
1261
|
-
//
|
|
1262
|
-
//
|
|
1263
|
-
|
|
1383
|
+
// Content-addressed: `--force` reuses parser shards; `useParseCache: false`
|
|
1384
|
+
// stages a new generation under a run-unique parse-rebuild.* dir and publishes
|
|
1385
|
+
// after success. Unique because index locks are per branch slot while this
|
|
1386
|
+
// cache root is shared across branches.
|
|
1387
|
+
if (options.useParseCache === false) {
|
|
1388
|
+
coldParseRebuildDir = await createColdParseRebuildDir(storagePath);
|
|
1389
|
+
forgetCreatedParseCacheDir(coldParseRebuildDir);
|
|
1390
|
+
}
|
|
1391
|
+
const parseCache = options.useParseCache === false
|
|
1392
|
+
? emptyParseCache(coldParseRebuildDir)
|
|
1393
|
+
: await loadParseCache(storagePath);
|
|
1264
1394
|
// Streamed structural emit (#2680). Resolved ONCE, so the pipeline flag and
|
|
1265
1395
|
// the CSV-dir resolution below cannot disagree — and resolved HERE, not at
|
|
1266
1396
|
// function entry, because the POSITION is load-bearing: the gate is
|
|
@@ -1276,46 +1406,81 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
1276
1406
|
// pipeline has already run by then; that run emits non-streamed, precisely as
|
|
1277
1407
|
// `resolveStreamPdgEmit` — read fresh at the same point — behaves.)
|
|
1278
1408
|
const streamGraphEmitActive = resolveStreamGraphEmit(options);
|
|
1409
|
+
// #3016: hold back Leiden and flow extraction when the persisted metadata
|
|
1410
|
+
// says this run is a candidate for a surgical incremental write, whose
|
|
1411
|
+
// derived layer is reused rather than recomputed. Deliberately the same
|
|
1412
|
+
// conditions as the `isIncremental` decision below MINUS the two that only
|
|
1413
|
+
// the pipeline can answer (the analysis-feature re-check and a non-empty
|
|
1414
|
+
// file list), so this is a superset: every run that turns out incremental
|
|
1415
|
+
// had the phases skipped, and the runs that do not are caught by
|
|
1416
|
+
// `runDeferredDerivedPhases` once the write plan is known. Excluded on the
|
|
1417
|
+
// streaming path because that is a full rebuild by construction, and the
|
|
1418
|
+
// deferred phases must not write into a finalized emit sink.
|
|
1419
|
+
const skipDerivedGraphPhases = !streamGraphEmitActive &&
|
|
1420
|
+
!options.force &&
|
|
1421
|
+
!!existingMeta &&
|
|
1422
|
+
!!existingMeta.fileHashes &&
|
|
1423
|
+
Object.keys(existingMeta.fileHashes).length > 0 &&
|
|
1424
|
+
repoHasGit &&
|
|
1425
|
+
!schemaFingerprintMismatch(existingMeta.schemaFingerprint);
|
|
1279
1426
|
// ── Phase 1: Full Pipeline (0–60%) ────────────────────────────────
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
:
|
|
1317
|
-
|
|
1318
|
-
|
|
1427
|
+
let pipelineResult;
|
|
1428
|
+
try {
|
|
1429
|
+
pipelineResult = await runPipelineFromRepo(repoPath, (p) => {
|
|
1430
|
+
const phaseLabel = PHASE_LABELS[p.phase] || p.phase;
|
|
1431
|
+
const scaled = Math.round(p.percent * 0.6);
|
|
1432
|
+
const message = p.detail
|
|
1433
|
+
? `${p.message || phaseLabel} (${p.detail})`
|
|
1434
|
+
: p.message || phaseLabel;
|
|
1435
|
+
progress(p.phase, scaled, message);
|
|
1436
|
+
}, {
|
|
1437
|
+
parseCache,
|
|
1438
|
+
workerPoolSize: options.workerPoolSize,
|
|
1439
|
+
// CFG/PDG opt-in (#2081 M1). PipelineOptions.pdg fans out to the worker
|
|
1440
|
+
// build gate (workerData.pdg) and the scope-resolution emit gate.
|
|
1441
|
+
pdg: options.pdg === true,
|
|
1442
|
+
pdgMaxFunctionLines: options.pdgMaxFunctionLines,
|
|
1443
|
+
pdgMaxEdgesPerFunction: options.pdgMaxEdgesPerFunction,
|
|
1444
|
+
pdgMaxReachingDefEdgesPerFunction: options.pdgMaxReachingDefEdgesPerFunction,
|
|
1445
|
+
pdgMaxCdgEdgesPerFunction: options.pdgMaxCdgEdgesPerFunction,
|
|
1446
|
+
pdgMaxTaintFindingsPerFunction: options.pdgMaxTaintFindingsPerFunction,
|
|
1447
|
+
pdgMaxTaintHops: options.pdgMaxTaintHops,
|
|
1448
|
+
pdgMaxInterprocFindings: options.pdgMaxInterprocFindings,
|
|
1449
|
+
pdgMaxInterprocHops: options.pdgMaxInterprocHops,
|
|
1450
|
+
pdgMaxInterprocEdges: options.pdgMaxInterprocEdges,
|
|
1451
|
+
// Streaming/chunked PDG emit (#2202) — gated to full-rebuild runs
|
|
1452
|
+
// (force === true) so the incremental writeback never reads back an
|
|
1453
|
+
// offloaded BasicBlock layer. Memory-only; byte-identical output.
|
|
1454
|
+
streamPdgEmit: resolveStreamPdgEmit(options),
|
|
1455
|
+
pdgEmitChunkSize: resolvePdgEmitChunkSize(options),
|
|
1456
|
+
// Streamed structural emit (#2680) — same full-rebuild gate as the PDG
|
|
1457
|
+
// toggle above, for the same incremental-writeback reason.
|
|
1458
|
+
streamGraphEmit: streamGraphEmitActive,
|
|
1459
|
+
// Resolved ONLY when streaming is active: on a Windows non-ASCII storage
|
|
1460
|
+
// path this helper mkdtempSyncs a real directory, so evaluating it
|
|
1461
|
+
// unconditionally would leak one temp dir per analyze even with the flag
|
|
1462
|
+
// off. The PDG sibling resolves inside its guard for the same reason.
|
|
1463
|
+
graphEmitCsvDir: streamGraphEmitActive
|
|
1464
|
+
? resolveNativeSafeStorageDir(storagePath, 'graph-csv')
|
|
1465
|
+
: undefined,
|
|
1466
|
+
fetchWrappers: options.fetchWrappers,
|
|
1467
|
+
skipDerivedGraphPhases,
|
|
1468
|
+
springActuatorPath: options.springActuatorPath,
|
|
1469
|
+
asyncApiSpecPath: options.asyncApiSpecPath,
|
|
1470
|
+
springActuatorScanExclusions,
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
catch (err) {
|
|
1474
|
+
await removeColdParseRebuildDir(coldParseRebuildDir, true);
|
|
1475
|
+
throw err;
|
|
1476
|
+
}
|
|
1477
|
+
if (options.force && (pipelineResult.parseCacheHitFileCount ?? 0) > 0) {
|
|
1478
|
+
log(`Rebuilt the graph and FTS while reusing cached parser output for ` +
|
|
1479
|
+
`${pipelineResult.parseCacheHitFileCount} file(s) ` +
|
|
1480
|
+
`(parse cache ${PARSE_CACHE_VERSION}). ` +
|
|
1481
|
+
`For same-version capture/query development changes, increment SCHEMA_BUMP in ` +
|
|
1482
|
+
`src/storage/parse-cache.ts to invalidate parser output.`);
|
|
1483
|
+
}
|
|
1319
1484
|
// ── Phase 2: LadybugDB (60–85%) ──────────────────────────────────
|
|
1320
1485
|
progress('lbug', 60, 'Loading into LadybugDB...');
|
|
1321
1486
|
// Compute current per-file content hashes from the pipeline's File nodes.
|
|
@@ -1364,6 +1529,26 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
1364
1529
|
const hashDiff = isIncremental
|
|
1365
1530
|
? diffFileHashes(newFileHashes, existingMeta.fileHashes)
|
|
1366
1531
|
: undefined;
|
|
1532
|
+
// #3016: `skipDerivedGraphPhases` was decided BEFORE the pipeline, from the
|
|
1533
|
+
// persisted metadata alone, so it can only ever be a bet that this run stays
|
|
1534
|
+
// surgical. Settle the bet here, where `isIncremental` and the deletion set
|
|
1535
|
+
// are both known, and pay it off by running the held-back phases whenever the
|
|
1536
|
+
// write plan needs a freshly derived layer:
|
|
1537
|
+
// - not incremental → full rebuild writes the whole graph, and a graph
|
|
1538
|
+
// with no Community/Process nodes would publish an
|
|
1539
|
+
// index with no communities and no flows;
|
|
1540
|
+
// - added/changed/deleted files → the persisted derived layer can miss new
|
|
1541
|
+
// symbols, keep stale memberships, or reference
|
|
1542
|
+
// removed ids. Only an empty file-hash diff is a
|
|
1543
|
+
// proof that Leiden/flows still match.
|
|
1544
|
+
const preserveDerivedLayer = skipDerivedGraphPhases &&
|
|
1545
|
+
isIncremental &&
|
|
1546
|
+
!!hashDiff &&
|
|
1547
|
+
shouldPreservePersistedDerivedGraph(hashDiff);
|
|
1548
|
+
if (skipDerivedGraphPhases && !preserveDerivedLayer) {
|
|
1549
|
+
progress('communities', 58, 'Detecting code communities and flows...');
|
|
1550
|
+
await pipelineResult.runDeferredDerivedPhases?.();
|
|
1551
|
+
}
|
|
1367
1552
|
// #2 atomic index publish: on a full rebuild, build the fresh DB at a temp
|
|
1368
1553
|
// path and swap it over the live index in one rename at the very end, so a
|
|
1369
1554
|
// concurrent MCP reader opening mid-build only ever sees the previous
|
|
@@ -1562,6 +1747,7 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
1562
1747
|
// collapse check compares the whole in-memory graph against the whole DB,
|
|
1563
1748
|
// which is only a like-for-like comparison on a full rebuild.
|
|
1564
1749
|
let wroteChangedSubgraphOnly = false;
|
|
1750
|
+
let incrementalFtsRebuildTables;
|
|
1565
1751
|
if (isIncremental && hashDiff) {
|
|
1566
1752
|
// ── Incremental DB writeback ───────────────────────────────────
|
|
1567
1753
|
// 0. Expand the writable set with transitive importers of
|
|
@@ -1697,6 +1883,29 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
1697
1883
|
// and extractChangedSubgraph — asymmetry between the two would
|
|
1698
1884
|
// leave stale rows or PK-conflict at COPY time.
|
|
1699
1885
|
const effectiveWriteSet = computeEffectiveWriteSet(pipelineResult.graph, writableFiles);
|
|
1886
|
+
const springConfigChanged = hashDiff.toWrite.some((filePath) => classifySpringConfigFile(filePath) !== null) ||
|
|
1887
|
+
hashDiff.deleted.some((filePath) => classifySpringConfigFile(filePath) !== null);
|
|
1888
|
+
if (springConfigChanged) {
|
|
1889
|
+
const unresolvedPrefix = escapeCypherString(SPRING_CONFIG_UNRESOLVED_PREFIX);
|
|
1890
|
+
const persistedSpringConfigConsumers = (await executeQuery('MATCH (n:Property) ' +
|
|
1891
|
+
`WHERE n.description CONTAINS '${unresolvedPrefix}' ` +
|
|
1892
|
+
'RETURN n.id AS id, n.description AS description ' +
|
|
1893
|
+
'UNION ALL ' +
|
|
1894
|
+
'MATCH (n:Class) ' +
|
|
1895
|
+
`WHERE n.description CONTAINS '${unresolvedPrefix}' ` +
|
|
1896
|
+
'RETURN n.id AS id, n.description AS description ' +
|
|
1897
|
+
'UNION ALL ' +
|
|
1898
|
+
'MATCH (n:Record) ' +
|
|
1899
|
+
`WHERE n.description CONTAINS '${unresolvedPrefix}' ` +
|
|
1900
|
+
'RETURN n.id AS id, n.description AS description'));
|
|
1901
|
+
const springConfigConsumerDriftFiles = collectSpringConfigConsumerDriftFiles(pipelineResult.graph, persistedSpringConfigConsumers);
|
|
1902
|
+
for (const filePath of springConfigConsumerDriftFiles)
|
|
1903
|
+
effectiveWriteSet.add(filePath);
|
|
1904
|
+
if (springConfigConsumerDriftFiles.size > 0) {
|
|
1905
|
+
log(`Incremental: +${springConfigConsumerDriftFiles.size} file(s) added for ` +
|
|
1906
|
+
'Spring config consumer property drift');
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1700
1909
|
// `frameworkAnnotations` is derived from cross-file JVM visibility, so
|
|
1701
1910
|
// an unchanged Class row can change when a same-package declaration is
|
|
1702
1911
|
// added or removed without producing an IMPORTS edge. Compare the fresh
|
|
@@ -1824,6 +2033,14 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
1824
2033
|
const sizeForcedRebuild = shouldEscalateIncrementalWrite(filesToDelete.length, effectiveWriteSet.size, allFilePaths.length);
|
|
1825
2034
|
if (extensionForcedRebuild || sizeForcedRebuild) {
|
|
1826
2035
|
escalatedFullWrite = true;
|
|
2036
|
+
// #3016: escalation converts this run into a wipe + full bulk COPY of
|
|
2037
|
+
// the in-memory graph, so the derived layer the skip was betting on
|
|
2038
|
+
// preserving has to exist in that graph after all. Same reasoning as
|
|
2039
|
+
// the not-incremental branch above, just discovered later.
|
|
2040
|
+
if (preserveDerivedLayer) {
|
|
2041
|
+
progress('communities', 63, 'Detecting code communities and flows...');
|
|
2042
|
+
await pipelineResult.runDeferredDerivedPhases?.();
|
|
2043
|
+
}
|
|
1827
2044
|
// Every live cause is named, not just the first: a DB can carry BOTH a
|
|
1828
2045
|
// vector index and FTS indexes, and reporting one cause while the other
|
|
1829
2046
|
// is equally fatal is how #2841 stayed mis-diagnosed for so long. §5.D:
|
|
@@ -2024,7 +2241,53 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2024
2241
|
// the snapshot type exists to enforce.
|
|
2025
2242
|
if (buildPath === lbugPath)
|
|
2026
2243
|
liveIndexMutationStarted = true;
|
|
2027
|
-
|
|
2244
|
+
// FTS narrowing is independent of Leiden/flow reuse: even when this
|
|
2245
|
+
// run re-derives communities, Ladybug still cannot DML a live FTS
|
|
2246
|
+
// index (#2589), so only the tables this write set touches should
|
|
2247
|
+
// lose their index. The probe is a question about the DB rather than
|
|
2248
|
+
// the fresh graph — a symbol the edit DELETED is in no fresh graph
|
|
2249
|
+
// but is still a row that has to go.
|
|
2250
|
+
const tablesWithRows = await nodeTablesWithRowsForFiles(filesToDelete, NODE_TABLES);
|
|
2251
|
+
// Narrowing 1 — the FTS sweep, from "every configured index" to "the
|
|
2252
|
+
// indexes this run must touch". Three sources, and dropping any one of
|
|
2253
|
+
// them strands something:
|
|
2254
|
+
// - what the writeback DELETES (the probe above), because a symbol
|
|
2255
|
+
// the edit removed is in no fresh graph but is still a row;
|
|
2256
|
+
// - what it INSERTS (the fresh graph), because inserting under a live
|
|
2257
|
+
// FTS index is the same #2589 hazard as deleting under one;
|
|
2258
|
+
// - what is MISSING right now, because narrowing to the written
|
|
2259
|
+
// tables would otherwise leave keyword search degraded forever on
|
|
2260
|
+
// tables whose index a previous escalation dropped — the next full
|
|
2261
|
+
// rebuild would be the only thing that ever restored them.
|
|
2262
|
+
// An unreadable catalog proves nothing about that third set, so it
|
|
2263
|
+
// withdraws the narrowing entirely rather than guess.
|
|
2264
|
+
const missingFts = await missingSearchFTSIndexTables(indexCatalogRows);
|
|
2265
|
+
const touchedFts = missingFts
|
|
2266
|
+
? new Set([
|
|
2267
|
+
...ftsTablesAmong(tablesWithRows),
|
|
2268
|
+
...incrementalFtsTablesFromGraph(pipelineResult.graph, new Set(filesToDelete)),
|
|
2269
|
+
...missingFts,
|
|
2270
|
+
])
|
|
2271
|
+
: undefined;
|
|
2272
|
+
// Graph-wide Spring synthetic Class nodes are DETACH DELETEd on this
|
|
2273
|
+
// branch even when Class is not in the write set
|
|
2274
|
+
// (`deleteSpringAutoConfigurationSyntheticClasses`). Always include
|
|
2275
|
+
// Class so class_fts is not live across that DML (#2589), including
|
|
2276
|
+
// when the fresh graph no longer materializes the synthetics but the
|
|
2277
|
+
// DB still holds them.
|
|
2278
|
+
if (touchedFts) {
|
|
2279
|
+
touchedFts.add('Class');
|
|
2280
|
+
}
|
|
2281
|
+
incrementalFtsRebuildTables = touchedFts;
|
|
2282
|
+
// MEMBER_OF / STEP_IN_PROCESS / ENTRY_POINT_OF edges hang off the nodes
|
|
2283
|
+
// the DETACH DELETE below removes, so preserving the Community/Process
|
|
2284
|
+
// nodes preserves only half the layer unless these are reattached after
|
|
2285
|
+
// the subgraph write puts the member nodes back. Only the probed tables
|
|
2286
|
+
// can own such an edge, so they are the only ones worth scanning.
|
|
2287
|
+
const derivedSnapshot = preserveDerivedLayer
|
|
2288
|
+
? await snapshotDerivedRelsForFiles(filesToDelete, [...tablesWithRows])
|
|
2289
|
+
: [];
|
|
2290
|
+
await dropSearchFTSIndexes(indexCatalogRows, incrementalFtsRebuildTables);
|
|
2028
2291
|
// 1b. Remove the write set's existing rows — batched (#2409): one
|
|
2029
2292
|
// DETACH DELETE per table per 200-file chunk. The former per-file
|
|
2030
2293
|
// loop issued a count + delete per table per FILE — ~13k
|
|
@@ -2038,6 +2301,9 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2038
2301
|
progress('lbug', 62, `Removing rows for changed files (0/${filesToDelete.length})...`);
|
|
2039
2302
|
await deleteNodesForFiles(filesToDelete, {
|
|
2040
2303
|
onChunk: (done, total) => progress('lbug', 62, `Removing rows for changed files (${done}/${total})...`),
|
|
2304
|
+
nodeTables: incrementalFtsRebuildTables
|
|
2305
|
+
? nodeTablesForIncrementalDelete(NODE_TABLES, incrementalFtsRebuildTables)
|
|
2306
|
+
: undefined,
|
|
2041
2307
|
});
|
|
2042
2308
|
// Surgical path: Phase 3.5 restores exactly these files' embedding
|
|
2043
2309
|
// rows (FIX 3). Sound because deleteNodesForFiles propagates errors
|
|
@@ -2045,10 +2311,12 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2045
2311
|
// deterministically — and this process holds the exclusive DB lock,
|
|
2046
2312
|
// so no concurrent writer can disturb the derivation.
|
|
2047
2313
|
deletedFilePathsForRestore = new Set(filesToDelete);
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2314
|
+
if (!preserveDerivedLayer) {
|
|
2315
|
+
// 2. Drop graph-wide nodes (Community, Process). They'll be re-inserted
|
|
2316
|
+
// from the fresh pipeline output below. Required for the
|
|
2317
|
+
// "Leiden runs on the FULL graph" correctness invariant.
|
|
2318
|
+
await deleteAllCommunitiesAndProcesses();
|
|
2319
|
+
}
|
|
2052
2320
|
// 2a. Drop INJECTS edges (DI collection injection, #2200) — their
|
|
2053
2321
|
// validity is a whole-program property (a third-file change to the
|
|
2054
2322
|
// interface or an implementer creates/invalidates edges between two
|
|
@@ -2067,6 +2335,18 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2067
2335
|
// Rebuild the complete ADVISED_BY set on every incremental writeback.
|
|
2068
2336
|
await deleteAllAdvisedBy();
|
|
2069
2337
|
await deleteSpringAopEvidenceNodes();
|
|
2338
|
+
// 2b-bis. Drop the whole async messaging overlay. A RESOLVED
|
|
2339
|
+
// Destination deliberately stores no filePath (so the per-file
|
|
2340
|
+
// DETACH DELETE cannot cut a node shared across files), which also
|
|
2341
|
+
// means the per-file delete can never REMOVE one that is now
|
|
2342
|
+
// orphaned, and the endpoint-writability extract can never ADD one
|
|
2343
|
+
// introduced by a new file. Delete-all here plus the graph-wide
|
|
2344
|
+
// re-include in extractChangedSubgraph rebuilds the layer whole;
|
|
2345
|
+
// the springDestinations phase recomputes it from the full file
|
|
2346
|
+
// list on every persisting analyze, so nothing is lost. Both halves
|
|
2347
|
+
// must move together — deleting without the re-include drops the
|
|
2348
|
+
// layer, re-including without the delete duplicates its edges.
|
|
2349
|
+
await deleteAllDestinations();
|
|
2070
2350
|
// 2c. Drop Spring-owned DECLARES edges (#2415). The
|
|
2071
2351
|
// auto-configuration phase scans every metadata file and recomputes
|
|
2072
2352
|
// the full set each run; exact reason filtering leaves declarations
|
|
@@ -2095,7 +2375,9 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2095
2375
|
// only that. Unchanged-file rows in the DB stay untouched. Pass
|
|
2096
2376
|
// the SAME effectiveWriteSet so the subgraph and the deletes
|
|
2097
2377
|
// cover identical files (asymmetry would silently corrupt).
|
|
2098
|
-
const subgraph = extractChangedSubgraph(pipelineResult.graph, effectiveWriteSet
|
|
2378
|
+
const subgraph = extractChangedSubgraph(pipelineResult.graph, effectiveWriteSet, {
|
|
2379
|
+
includeDerivedGraphWide: !preserveDerivedLayer,
|
|
2380
|
+
});
|
|
2099
2381
|
wroteChangedSubgraphOnly = true;
|
|
2100
2382
|
await saveIncrementalDirtyState('load-graph', {
|
|
2101
2383
|
importerExpansion,
|
|
@@ -2108,6 +2390,9 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2108
2390
|
const pct = Math.min(84, 65 + Math.round((lbugMsgCount / (lbugMsgCount + 10)) * 19));
|
|
2109
2391
|
progress('lbug', pct, msg);
|
|
2110
2392
|
});
|
|
2393
|
+
if (preserveDerivedLayer && derivedSnapshot.length > 0) {
|
|
2394
|
+
await restoreDerivedRels(derivedSnapshot);
|
|
2395
|
+
}
|
|
2111
2396
|
}
|
|
2112
2397
|
// Boundary drain (#2409): checkpoint at the end of the incremental
|
|
2113
2398
|
// writeback so the WAL it accumulated never lingers into the FTS and
|
|
@@ -2159,6 +2444,7 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2159
2444
|
// pre-existing row (#2544/#2546) must not discard this run's otherwise-
|
|
2160
2445
|
// successful graph/embeddings work — only keyword search degrades.
|
|
2161
2446
|
const ftsResult = await buildSearchIndexesOrDegrade(executeQuery, {
|
|
2447
|
+
tables: incrementalFtsRebuildTables,
|
|
2162
2448
|
onIndexStart: options.verbose
|
|
2163
2449
|
? (table, indexName) => log(`FTS: creating ${table}.${indexName}`)
|
|
2164
2450
|
: undefined,
|
|
@@ -2771,6 +3057,22 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2771
3057
|
lastCommit: currentCommit,
|
|
2772
3058
|
indexedAt: new Date().toISOString(),
|
|
2773
3059
|
runnerIdentity,
|
|
3060
|
+
// Persist only normalized repo-relative exclusions, never absolute paths
|
|
3061
|
+
// or payloads. Keep them after runtime enrichment is disabled so a later
|
|
3062
|
+
// ordinary scan cannot rediscover an unchanged snapshot as source/FTS.
|
|
3063
|
+
...(springActuatorRequested || retainedActuatorInputs.length > 0
|
|
3064
|
+
? {
|
|
3065
|
+
springActuator: {
|
|
3066
|
+
enabled: springActuatorRequested,
|
|
3067
|
+
repoRelativeInputs: retainedActuatorInputs,
|
|
3068
|
+
},
|
|
3069
|
+
}
|
|
3070
|
+
: {}),
|
|
3071
|
+
// Written only while enabled. Once the option is dropped, the disable
|
|
3072
|
+
// transition above has already forced the cleanup rebuild, so carrying a
|
|
3073
|
+
// `{ enabled: false }` stamp forward would only make every subsequent run
|
|
3074
|
+
// re-decide a question that is already settled.
|
|
3075
|
+
...(asyncApiSpecRequested ? { asyncApiSpec: { enabled: true } } : {}),
|
|
2774
3076
|
// Branch identity this index represents (#2106). Recorded for the flat
|
|
2775
3077
|
// slot too (so resolveBranchPlacement knows which branch owns it). When
|
|
2776
3078
|
// the label is null (detached HEAD / non-git re-analyze) we PRESERVE an
|
|
@@ -2803,8 +3105,9 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2803
3105
|
files: pipelineResult.totalFileCount,
|
|
2804
3106
|
nodes: stats.nodes,
|
|
2805
3107
|
edges: stats.edges,
|
|
2806
|
-
communities: pipelineResult.communityResult?.stats.totalCommunities
|
|
2807
|
-
|
|
3108
|
+
communities: pipelineResult.communityResult?.stats.totalCommunities ??
|
|
3109
|
+
existingMeta?.stats?.communities,
|
|
3110
|
+
processes: pipelineResult.processResult?.stats.totalProcesses ?? existingMeta?.stats?.processes,
|
|
2808
3111
|
embeddings: persistedEmbeddingCount,
|
|
2809
3112
|
},
|
|
2810
3113
|
capabilities: {
|
|
@@ -2870,6 +3173,7 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2870
3173
|
? existingMeta?.undecidedInterfaceSatisfaction
|
|
2871
3174
|
: summarizeUndecidedSatisfaction(pipelineResult.undecidedSatisfaction),
|
|
2872
3175
|
analysisFeatures: currentAnalysisFeatures,
|
|
3176
|
+
springVendorPrefixes: currentSpringVendorPrefixes,
|
|
2873
3177
|
// Always stamped with the live resolved mode (#2331/#2339) — unlike
|
|
2874
3178
|
// `pdg` below, 'none' is a meaningful value to compare, not an
|
|
2875
3179
|
// absence, so this is never conditionally omitted.
|
|
@@ -2914,50 +3218,8 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2914
3218
|
// meta.indexedAt = T_new while lbugPath still resolves to the pre-swap
|
|
2915
3219
|
// inode (which latched the reader on the stale index permanently). The meta
|
|
2916
3220
|
// object is fully computed at this point; only its write is deferred.
|
|
2917
|
-
//
|
|
2918
|
-
//
|
|
2919
|
-
// successful indexing run. Prune stale chunk-hash entries first so
|
|
2920
|
-
// the cache file size stays bounded across runs (chunks whose
|
|
2921
|
-
// composition no longer matches anything in the current scan are
|
|
2922
|
-
// dead weight; the parse phase populates `usedKeys` as it processes
|
|
2923
|
-
// chunks).
|
|
2924
|
-
try {
|
|
2925
|
-
// #2106 R6: the parse cache + durable store are shared across branches.
|
|
2926
|
-
// Before pruning to this run's keys, fold in the OTHER branches' recorded
|
|
2927
|
-
// chunk keys so a branch switch doesn't evict their still-live shards.
|
|
2928
|
-
// Adding to usedKeys makes them survive pruneCache AND land in the saved
|
|
2929
|
-
// index (saveParseCache builds the index from usedKeys). Excludes this
|
|
2930
|
-
// run's own meta dir, so a single-branch repo folds in nothing → prune
|
|
2931
|
-
// set byte-identical to today.
|
|
2932
|
-
const { keys: siblingKeys, complete } = await collectBranchCacheKeys(storagePath, metaDir);
|
|
2933
|
-
if (complete) {
|
|
2934
|
-
for (const k of siblingKeys)
|
|
2935
|
-
parseCache.usedKeys.add(k);
|
|
2936
|
-
}
|
|
2937
|
-
else {
|
|
2938
|
-
// Fail-safe toward retention: a sibling meta was unreadable, so keep
|
|
2939
|
-
// everything currently loaded rather than evict on incomplete info.
|
|
2940
|
-
log('Parse cache: a branch meta was unreadable — retaining all cached chunks (#2106).');
|
|
2941
|
-
for (const k of parseCache.entries.keys())
|
|
2942
|
-
parseCache.usedKeys.add(k);
|
|
2943
|
-
}
|
|
2944
|
-
const pruned = pruneCache(parseCache, parseCache.usedKeys);
|
|
2945
|
-
if (pruned > 0) {
|
|
2946
|
-
log(`Parse cache: pruned ${pruned} stale chunk entries`);
|
|
2947
|
-
}
|
|
2948
|
-
const savedKeys = await saveParseCache(storagePath, parseCache);
|
|
2949
|
-
// Prune the durable ParsedFile store to EXACTLY the parse cache's
|
|
2950
|
-
// surviving keys (#2038 warm-cache coverage), so the two content-addressed
|
|
2951
|
-
// stores stay coherent: a chunk is "cached" iff both its parse-cache shard
|
|
2952
|
-
// and its durable shards exist. A quarantined chunk (in usedKeys but with
|
|
2953
|
-
// no parse-cache shard) drops its durable subdir here and re-dispatches
|
|
2954
|
-
// next run. Same try/catch — a durable-store write failure must never
|
|
2955
|
-
// break an otherwise successful run (next run treats it as a miss).
|
|
2956
|
-
await pruneAndSaveDurableParsedFileStore(getDurableParsedFileDir(storagePath), PARSE_CACHE_VERSION, new Set(savedKeys));
|
|
2957
|
-
}
|
|
2958
|
-
catch (e) {
|
|
2959
|
-
log(`Warning: could not save parse cache (${e.message}); continuing.`);
|
|
2960
|
-
}
|
|
3221
|
+
// Parse-cache publish waits until after that swap + saveMeta so a failed
|
|
3222
|
+
// registerRepo / close / swap cannot replace live shards (#3153).
|
|
2961
3223
|
// Forward the --name alias and the registry-collision bypass bit.
|
|
2962
3224
|
// `allowDuplicateName` is its own concern — independent from the
|
|
2963
3225
|
// pipeline `force` above. The CLI maps it from
|
|
@@ -2978,8 +3240,8 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
2978
3240
|
// ── #2354: the flat workspace slot has adopted this run's branch ──────
|
|
2979
3241
|
// Drop a now-shadowed `branches/<slug>/` sub-index for the same label
|
|
2980
3242
|
// (unreachable once the flat slot serves it) and align the registry's
|
|
2981
|
-
// top-level branch label. Best-effort
|
|
2982
|
-
//
|
|
3243
|
+
// top-level branch label. Best-effort (#2364 review F5): the index is
|
|
3244
|
+
// complete and registered, and a failure
|
|
2983
3245
|
// here leaves only a stale registry label / undeleted shadowed dir —
|
|
2984
3246
|
// never wrong routing, because the flat meta this run already stamped is
|
|
2985
3247
|
// what applyBranchScope trusts. Retried by the next content-changing run
|
|
@@ -3014,15 +3276,17 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
3014
3276
|
files: pipelineResult.totalFileCount,
|
|
3015
3277
|
nodes: stats.nodes,
|
|
3016
3278
|
edges: stats.edges,
|
|
3017
|
-
communities: pipelineResult.communityResult?.stats.totalCommunities
|
|
3279
|
+
communities: pipelineResult.communityResult?.stats.totalCommunities ??
|
|
3280
|
+
existingMeta?.stats?.communities,
|
|
3018
3281
|
clusters: aggregatedClusterCount,
|
|
3019
|
-
processes: pipelineResult.processResult?.stats.totalProcesses,
|
|
3282
|
+
processes: pipelineResult.processResult?.stats.totalProcesses ?? existingMeta?.stats?.processes,
|
|
3020
3283
|
}, undefined, {
|
|
3021
3284
|
skipAgentsMd: options.skipAgentsMd,
|
|
3022
3285
|
skipSkills: options.skipSkills,
|
|
3023
3286
|
noStats: options.noStats,
|
|
3024
3287
|
defaultBranch: options.defaultBranch,
|
|
3025
3288
|
hasPdg: options.pdg === true,
|
|
3289
|
+
hasSpringActuator: options.springActuatorPath !== undefined,
|
|
3026
3290
|
});
|
|
3027
3291
|
}
|
|
3028
3292
|
catch {
|
|
@@ -3086,7 +3350,51 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
3086
3350
|
// is a crash-safety improvement: a failed swap leaves the previous index
|
|
3087
3351
|
// live and the next run recovers via the full-rebuild path.
|
|
3088
3352
|
await saveMeta(metaDir, meta);
|
|
3353
|
+
// Persist the incremental parse cache only after a successful graph
|
|
3354
|
+
// publish (#3153). try/catch so a cache-write failure never breaks an
|
|
3355
|
+
// otherwise successful indexing run. Prune stale chunk-hash entries first
|
|
3356
|
+
// so the cache file size stays bounded across runs (chunks whose
|
|
3357
|
+
// composition no longer matches anything in the current scan are dead
|
|
3358
|
+
// weight; the parse phase populates `usedKeys` as it processes chunks).
|
|
3359
|
+
try {
|
|
3360
|
+
// #2106 R6: the parse cache + durable store are shared across branches.
|
|
3361
|
+
// Before pruning to this run's keys, fold in the OTHER branches' recorded
|
|
3362
|
+
// chunk keys so a branch switch doesn't evict their still-live shards.
|
|
3363
|
+
// Adding to usedKeys makes them survive pruneCache AND land in the saved
|
|
3364
|
+
// index (saveParseCache builds the index from usedKeys). Excludes this
|
|
3365
|
+
// run's own meta dir, so a single-branch repo folds in nothing → prune
|
|
3366
|
+
// set byte-identical to today.
|
|
3367
|
+
const { keys: siblingKeys, complete } = await collectBranchCacheKeys(storagePath, metaDir);
|
|
3368
|
+
if (complete) {
|
|
3369
|
+
for (const k of siblingKeys)
|
|
3370
|
+
parseCache.usedKeys.add(k);
|
|
3371
|
+
}
|
|
3372
|
+
else {
|
|
3373
|
+
// Fail-safe toward retention: a sibling meta was unreadable, so keep
|
|
3374
|
+
// everything currently loaded rather than evict on incomplete info.
|
|
3375
|
+
log('Parse cache: a branch meta was unreadable — retaining all cached chunks (#2106).');
|
|
3376
|
+
for (const k of parseCache.entries.keys())
|
|
3377
|
+
parseCache.usedKeys.add(k);
|
|
3378
|
+
}
|
|
3379
|
+
const pruned = pruneCache(parseCache, parseCache.usedKeys);
|
|
3380
|
+
if (pruned > 0) {
|
|
3381
|
+
log(`Parse cache: pruned ${pruned} stale chunk entries`);
|
|
3382
|
+
}
|
|
3383
|
+
const savedKeys = await saveParseCache(storagePath, parseCache);
|
|
3384
|
+
// Prune the durable ParsedFile store to EXACTLY the parse cache's
|
|
3385
|
+
// surviving keys (#2038 warm-cache coverage), so the two content-addressed
|
|
3386
|
+
// stores stay coherent: a chunk is "cached" iff both its parse-cache shard
|
|
3387
|
+
// and its durable shards exist. A quarantined chunk (in usedKeys but with
|
|
3388
|
+
// no parse-cache shard) drops its durable subdir here and re-dispatches
|
|
3389
|
+
// next run. Same try/catch — a durable-store write failure must never
|
|
3390
|
+
// break an otherwise successful run (next run treats it as a miss).
|
|
3391
|
+
await mergeStagedDurableParsedFileStore(storagePath, parseCache.storagePath ?? storagePath, PARSE_CACHE_VERSION, new Set(savedKeys));
|
|
3392
|
+
}
|
|
3393
|
+
catch (e) {
|
|
3394
|
+
log(`Warning: could not save parse cache (${e.message}); continuing.`);
|
|
3395
|
+
}
|
|
3089
3396
|
progress('done', 100, 'Done');
|
|
3397
|
+
await removeColdParseRebuildDir(coldParseRebuildDir, true);
|
|
3090
3398
|
return {
|
|
3091
3399
|
repoName: projectName,
|
|
3092
3400
|
repoPath,
|
|
@@ -3144,6 +3452,7 @@ async function runFullAnalysisInner(repoPath, options, callbacks, writeTarget, r
|
|
|
3144
3452
|
/* swallow — orphan reclamation must never mask the real failure */
|
|
3145
3453
|
}
|
|
3146
3454
|
}
|
|
3455
|
+
await removeColdParseRebuildDir(coldParseRebuildDir, true);
|
|
3147
3456
|
if (liveIndexMutationStarted) {
|
|
3148
3457
|
// Preserve the original error identity/prototype: callers distinguish
|
|
3149
3458
|
// IndexLockTimeoutError and other domain failures with `instanceof`.
|