gitnexus 1.6.8-rc.9 → 1.6.8
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 +3 -3
- package/dist/_shared/graph/types.d.ts +31 -1
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +11 -1
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +6 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/scope-resolution/parsed-file.d.ts +21 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/symbol-definition.d.ts +6 -0
- package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +31 -1
- package/dist/cli/ai-context.js +18 -16
- package/dist/cli/analyze-config.js +11 -0
- package/dist/cli/analyze.d.ts +14 -0
- package/dist/cli/analyze.js +98 -0
- package/dist/cli/embedding-dims.d.ts +33 -0
- package/dist/cli/embedding-dims.js +39 -0
- package/dist/cli/eval-server.d.ts +8 -0
- package/dist/cli/eval-server.js +242 -2
- package/dist/cli/help-i18n.js +19 -0
- package/dist/cli/i18n/en.d.ts +15 -1
- package/dist/cli/i18n/en.js +15 -1
- package/dist/cli/i18n/resources.d.ts +29 -1
- package/dist/cli/i18n/zh-CN.d.ts +14 -0
- package/dist/cli/i18n/zh-CN.js +15 -1
- package/dist/cli/index.js +89 -1
- package/dist/cli/mcp.d.ts +6 -1
- package/dist/cli/mcp.js +26 -1
- package/dist/cli/optional-grammars.d.ts +6 -8
- package/dist/cli/optional-grammars.js +8 -11
- package/dist/cli/setup.d.ts +3 -1
- package/dist/cli/setup.js +67 -17
- package/dist/cli/skill-gen.js +2 -1
- package/dist/cli/tool.d.ts +19 -1
- package/dist/cli/tool.js +96 -3
- package/dist/core/embeddings/hf-env.d.ts +0 -66
- package/dist/core/embeddings/http-client.d.ts +7 -0
- package/dist/core/embeddings/http-client.js +5 -3
- package/dist/core/embeddings/server-mapping.d.ts +1 -1
- package/dist/core/embeddings/server-mapping.js +7 -3
- package/dist/core/graph/import-cycles.d.ts +10 -0
- package/dist/core/graph/import-cycles.js +103 -0
- package/dist/core/group/cross-impact.d.ts +2 -1
- package/dist/core/group/cross-impact.js +5 -1
- package/dist/core/group/extractors/grpc-patterns/proto.js +10 -6
- package/dist/core/group/extractors/http-patterns/kotlin.js +7 -7
- package/dist/core/group/extractors/http-route-extractor.d.ts +24 -0
- package/dist/core/group/extractors/http-route-extractor.js +22 -4
- package/dist/core/group/extractors/include-extractor.js +22 -13
- package/dist/core/group/sync.d.ts +27 -1
- package/dist/core/group/sync.js +0 -0
- package/dist/core/incremental/subgraph-extract.js +18 -1
- package/dist/core/ingestion/cfg/cfg-builder.d.ts +114 -0
- package/dist/core/ingestion/cfg/cfg-builder.js +196 -0
- package/dist/core/ingestion/cfg/collect.d.ts +51 -0
- package/dist/core/ingestion/cfg/collect.js +77 -0
- package/dist/core/ingestion/cfg/control-dependence.d.ts +58 -0
- package/dist/core/ingestion/cfg/control-dependence.js +182 -0
- package/dist/core/ingestion/cfg/control-flow-context.d.ts +106 -0
- package/dist/core/ingestion/cfg/control-flow-context.js +124 -0
- package/dist/core/ingestion/cfg/emit.d.ts +293 -0
- package/dist/core/ingestion/cfg/emit.js +646 -0
- package/dist/core/ingestion/cfg/post-dominators.d.ts +79 -0
- package/dist/core/ingestion/cfg/post-dominators.js +176 -0
- package/dist/core/ingestion/cfg/reaching-def-reason-codec.d.ts +106 -0
- package/dist/core/ingestion/cfg/reaching-def-reason-codec.js +133 -0
- package/dist/core/ingestion/cfg/reaching-defs-graph.d.ts +18 -0
- package/dist/core/ingestion/cfg/reaching-defs-graph.js +312 -0
- package/dist/core/ingestion/cfg/reaching-defs.d.ts +162 -0
- package/dist/core/ingestion/cfg/reaching-defs.js +785 -0
- package/dist/core/ingestion/cfg/synthetic-escape.d.ts +124 -0
- package/dist/core/ingestion/cfg/synthetic-escape.js +300 -0
- package/dist/core/ingestion/cfg/traversal-result.d.ts +20 -0
- package/dist/core/ingestion/cfg/traversal-result.js +2 -0
- package/dist/core/ingestion/cfg/types.d.ts +274 -0
- package/dist/core/ingestion/cfg/types.js +13 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.d.ts +111 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.js +541 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp.d.ts +74 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp.js +584 -0
- package/dist/core/ingestion/cfg/visitors/call-site-harvest.d.ts +195 -0
- package/dist/core/ingestion/cfg/visitors/call-site-harvest.js +350 -0
- package/dist/core/ingestion/cfg/visitors/csharp-harvest.d.ts +124 -0
- package/dist/core/ingestion/cfg/visitors/csharp-harvest.js +589 -0
- package/dist/core/ingestion/cfg/visitors/csharp.d.ts +87 -0
- package/dist/core/ingestion/cfg/visitors/csharp.js +867 -0
- package/dist/core/ingestion/cfg/visitors/dart-harvest.d.ts +278 -0
- package/dist/core/ingestion/cfg/visitors/dart-harvest.js +870 -0
- package/dist/core/ingestion/cfg/visitors/dart.d.ts +119 -0
- package/dist/core/ingestion/cfg/visitors/dart.js +836 -0
- package/dist/core/ingestion/cfg/visitors/go-harvest.d.ts +160 -0
- package/dist/core/ingestion/cfg/visitors/go-harvest.js +621 -0
- package/dist/core/ingestion/cfg/visitors/go.d.ts +108 -0
- package/dist/core/ingestion/cfg/visitors/go.js +638 -0
- package/dist/core/ingestion/cfg/visitors/java-harvest.d.ts +108 -0
- package/dist/core/ingestion/cfg/visitors/java-harvest.js +513 -0
- package/dist/core/ingestion/cfg/visitors/java.d.ts +101 -0
- package/dist/core/ingestion/cfg/visitors/java.js +812 -0
- package/dist/core/ingestion/cfg/visitors/kotlin-harvest.d.ts +253 -0
- package/dist/core/ingestion/cfg/visitors/kotlin-harvest.js +719 -0
- package/dist/core/ingestion/cfg/visitors/kotlin.d.ts +121 -0
- package/dist/core/ingestion/cfg/visitors/kotlin.js +809 -0
- package/dist/core/ingestion/cfg/visitors/php-harvest.d.ts +172 -0
- package/dist/core/ingestion/cfg/visitors/php-harvest.js +626 -0
- package/dist/core/ingestion/cfg/visitors/php.d.ts +96 -0
- package/dist/core/ingestion/cfg/visitors/php.js +721 -0
- package/dist/core/ingestion/cfg/visitors/python-harvest.d.ts +212 -0
- package/dist/core/ingestion/cfg/visitors/python-harvest.js +739 -0
- package/dist/core/ingestion/cfg/visitors/python.d.ts +103 -0
- package/dist/core/ingestion/cfg/visitors/python.js +558 -0
- package/dist/core/ingestion/cfg/visitors/ruby-harvest.d.ts +223 -0
- package/dist/core/ingestion/cfg/visitors/ruby-harvest.js +587 -0
- package/dist/core/ingestion/cfg/visitors/ruby.d.ts +112 -0
- package/dist/core/ingestion/cfg/visitors/ruby.js +756 -0
- package/dist/core/ingestion/cfg/visitors/rust-harvest.d.ts +324 -0
- package/dist/core/ingestion/cfg/visitors/rust-harvest.js +873 -0
- package/dist/core/ingestion/cfg/visitors/rust.d.ts +95 -0
- package/dist/core/ingestion/cfg/visitors/rust.js +558 -0
- package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.d.ts +87 -0
- package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.js +116 -0
- package/dist/core/ingestion/cfg/visitors/swift-harvest.d.ts +255 -0
- package/dist/core/ingestion/cfg/visitors/swift-harvest.js +679 -0
- package/dist/core/ingestion/cfg/visitors/swift.d.ts +116 -0
- package/dist/core/ingestion/cfg/visitors/swift.js +787 -0
- package/dist/core/ingestion/cfg/visitors/typescript-harvest.d.ts +149 -0
- package/dist/core/ingestion/cfg/visitors/typescript-harvest.js +1056 -0
- package/dist/core/ingestion/cfg/visitors/typescript.d.ts +66 -0
- package/dist/core/ingestion/cfg/visitors/typescript.js +583 -0
- package/dist/core/ingestion/import-resolvers/utils.js +2 -0
- package/dist/core/ingestion/language-provider.d.ts +11 -0
- package/dist/core/ingestion/languages/c-cpp.js +6 -1
- package/dist/core/ingestion/languages/cobol.js +4 -0
- package/dist/core/ingestion/languages/cpp/arity-metadata.js +41 -2
- package/dist/core/ingestion/languages/cpp/captures.js +50 -1
- package/dist/core/ingestion/languages/cpp/conversion-rank.d.ts +2 -0
- package/dist/core/ingestion/languages/cpp/conversion-rank.js +89 -0
- package/dist/core/ingestion/languages/cpp/header-scan.d.ts +1 -1
- package/dist/core/ingestion/languages/cpp/header-scan.js +2 -2
- package/dist/core/ingestion/languages/cpp/inline-namespaces.js +7 -2
- package/dist/core/ingestion/languages/cpp/member-lookup.js +2 -1
- package/dist/core/ingestion/languages/cpp/query.js +23 -0
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +2 -1
- package/dist/core/ingestion/languages/csharp.js +2 -0
- package/dist/core/ingestion/languages/dart.js +2 -0
- package/dist/core/ingestion/languages/go.js +2 -0
- package/dist/core/ingestion/languages/java.js +3 -0
- package/dist/core/ingestion/languages/kotlin/query.js +3 -2
- package/dist/core/ingestion/languages/kotlin.js +3 -0
- package/dist/core/ingestion/languages/php.js +2 -0
- package/dist/core/ingestion/languages/python.js +2 -0
- package/dist/core/ingestion/languages/ruby.js +2 -0
- package/dist/core/ingestion/languages/rust.js +2 -0
- package/dist/core/ingestion/languages/swift.js +2 -0
- package/dist/core/ingestion/languages/typescript.js +5 -0
- package/dist/core/ingestion/languages/vue.js +6 -0
- package/dist/core/ingestion/method-extractors/configs/c-cpp.js +6 -13
- package/dist/core/ingestion/method-extractors/generic.js +1 -0
- package/dist/core/ingestion/method-types.d.ts +2 -0
- package/dist/core/ingestion/model/symbol-table.d.ts +1 -0
- package/dist/core/ingestion/model/symbol-table.js +1 -0
- package/dist/core/ingestion/mro-processor.js +109 -0
- package/dist/core/ingestion/parsing-processor.js +23 -0
- package/dist/core/ingestion/pipeline-phases/call-summaries.d.ts +26 -0
- package/dist/core/ingestion/pipeline-phases/call-summaries.js +46 -0
- 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.d.ts +0 -21
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +18 -1
- package/dist/core/ingestion/pipeline-phases/routes.d.ts +10 -0
- package/dist/core/ingestion/pipeline-phases/routes.js +30 -1
- package/dist/core/ingestion/pipeline-phases/taint-summaries.d.ts +30 -0
- package/dist/core/ingestion/pipeline-phases/taint-summaries.js +81 -0
- package/dist/core/ingestion/pipeline.d.ts +92 -10
- package/dist/core/ingestion/pipeline.js +11 -2
- package/dist/core/ingestion/scope-extractor.js +12 -2
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +9 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.d.ts +75 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +67 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +12 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +14 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +6 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +13 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +9 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +28 -2
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +4 -0
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +9 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +6 -1
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +174 -40
- package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +24 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +276 -190
- package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +43 -3
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +75 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +349 -1
- package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
- package/dist/core/ingestion/taint/call-summary-codec.d.ts +75 -0
- package/dist/core/ingestion/taint/call-summary-codec.js +128 -0
- package/dist/core/ingestion/taint/call-summary-emit.d.ts +43 -0
- package/dist/core/ingestion/taint/call-summary-emit.js +70 -0
- package/dist/core/ingestion/taint/call-summary-harvest.d.ts +77 -0
- package/dist/core/ingestion/taint/call-summary-harvest.js +179 -0
- package/dist/core/ingestion/taint/call-summary-model.d.ts +47 -0
- package/dist/core/ingestion/taint/call-summary-model.js +25 -0
- package/dist/core/ingestion/taint/emit.d.ts +125 -0
- package/dist/core/ingestion/taint/emit.js +208 -0
- package/dist/core/ingestion/taint/interproc-emit.d.ts +50 -0
- package/dist/core/ingestion/taint/interproc-emit.js +88 -0
- package/dist/core/ingestion/taint/interproc-solver.d.ts +110 -0
- package/dist/core/ingestion/taint/interproc-solver.js +312 -0
- package/dist/core/ingestion/taint/match.d.ts +153 -0
- package/dist/core/ingestion/taint/match.js +278 -0
- package/dist/core/ingestion/taint/path-codec.d.ts +134 -0
- package/dist/core/ingestion/taint/path-codec.js +190 -0
- package/dist/core/ingestion/taint/propagate.d.ts +216 -0
- package/dist/core/ingestion/taint/propagate.js +659 -0
- package/dist/core/ingestion/taint/site-safety.d.ts +29 -0
- package/dist/core/ingestion/taint/site-safety.js +98 -0
- package/dist/core/ingestion/taint/source-sink-config.d.ts +107 -23
- package/dist/core/ingestion/taint/source-sink-config.js +35 -12
- package/dist/core/ingestion/taint/source-sink-registry.d.ts +6 -4
- package/dist/core/ingestion/taint/source-sink-registry.js +6 -4
- package/dist/core/ingestion/taint/summary-harvest-driver.d.ts +80 -0
- package/dist/core/ingestion/taint/summary-harvest-driver.js +179 -0
- package/dist/core/ingestion/taint/summary-harvest.d.ts +89 -0
- package/dist/core/ingestion/taint/summary-harvest.js +537 -0
- package/dist/core/ingestion/taint/summary-model.d.ts +200 -0
- package/dist/core/ingestion/taint/summary-model.js +86 -0
- package/dist/core/ingestion/taint/typescript-model.d.ts +38 -0
- package/dist/core/ingestion/taint/typescript-model.js +102 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +21 -0
- package/dist/core/ingestion/utils/env.d.ts +7 -0
- package/dist/core/ingestion/utils/env.js +12 -0
- package/dist/core/ingestion/utils/method-props.js +1 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +13 -0
- package/dist/core/ingestion/workers/parse-worker.js +76 -17
- package/dist/core/ingestion/workers/worker-pool.d.ts +9 -40
- package/dist/core/ingestion/workers/worker-pool.js +15 -2
- package/dist/core/lbug/csv-generator.d.ts +51 -3
- package/dist/core/lbug/csv-generator.js +369 -255
- package/dist/core/lbug/lbug-adapter.d.ts +58 -18
- package/dist/core/lbug/lbug-adapter.js +346 -84
- package/dist/core/lbug/lbug-config.d.ts +19 -0
- package/dist/core/lbug/lbug-config.js +29 -0
- package/dist/core/lbug/pdg-emit-sink.d.ts +127 -0
- package/dist/core/lbug/pdg-emit-sink.js +358 -0
- package/dist/core/lbug/pool-adapter.d.ts +35 -0
- package/dist/core/lbug/pool-adapter.js +90 -1
- package/dist/core/lbug/rel-pair-routing.d.ts +54 -0
- package/dist/core/lbug/rel-pair-routing.js +140 -0
- package/dist/core/lbug/schema.d.ts +2 -2
- package/dist/core/lbug/schema.js +3 -0
- package/dist/core/logger.d.ts +0 -5
- package/dist/core/run-analyze.d.ts +96 -0
- package/dist/core/run-analyze.js +207 -3
- package/dist/core/tree-sitter/parser-loader.js +5 -4
- package/dist/core/tree-sitter/safe-parse.d.ts +0 -5
- package/dist/core/tree-sitter/vendored-grammars.d.ts +39 -0
- package/dist/core/tree-sitter/vendored-grammars.js +57 -0
- package/dist/core/wiki/generator.js +3 -1
- package/dist/core/wiki/graph-queries.d.ts +6 -0
- package/dist/core/wiki/graph-queries.js +9 -1
- package/dist/mcp/http-transport.d.ts +134 -0
- package/dist/mcp/http-transport.js +503 -0
- package/dist/mcp/local/local-backend.d.ts +110 -24
- package/dist/mcp/local/local-backend.js +1225 -19
- package/dist/mcp/local/pdg-impact.d.ts +384 -0
- package/dist/mcp/local/pdg-impact.js +1972 -0
- package/dist/mcp/resources.js +13 -1
- package/dist/mcp/tools.d.ts +12 -0
- package/dist/mcp/tools.js +214 -7
- package/dist/server/analyze-launch.d.ts +29 -0
- package/dist/server/analyze-launch.js +137 -0
- package/dist/server/analyze-upload.d.ts +33 -0
- package/dist/server/analyze-upload.js +123 -0
- package/dist/server/analyze-worker.d.ts +17 -1
- package/dist/server/api.d.ts +17 -0
- package/dist/server/api.js +132 -168
- package/dist/server/git-clone.d.ts +43 -2
- package/dist/server/git-clone.js +211 -16
- package/dist/server/mcp-http.d.ts +5 -6
- package/dist/server/mcp-http.js +9 -82
- package/dist/server/middleware.d.ts +40 -0
- package/dist/server/middleware.js +92 -0
- package/dist/server/private-ip.d.ts +1 -0
- package/dist/server/private-ip.js +15 -0
- package/dist/server/upload-ingest.d.ts +56 -0
- package/dist/server/upload-ingest.js +276 -0
- package/dist/server/upload-paths.d.ts +37 -0
- package/dist/server/upload-paths.js +57 -0
- package/dist/server/upload-sweep.d.ts +20 -0
- package/dist/server/upload-sweep.js +57 -0
- package/dist/storage/git.js +5 -8
- package/dist/storage/parse-cache.d.ts +22 -1
- package/dist/storage/parse-cache.js +41 -10
- package/dist/storage/repo-manager.d.ts +121 -10
- package/dist/storage/repo-manager.js +43 -5
- package/dist/types/pipeline.d.ts +9 -0
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +110 -10
- package/hooks/claude/gitnexus-hook.cjs +110 -13
- package/hooks/claude/hook-db-lock-probe.cjs +513 -26
- package/package.json +8 -2
- package/scripts/assert-publish-grammar-coverage.cjs +31 -0
- package/scripts/build-tree-sitter-grammars.cjs +16 -10
- package/scripts/cross-platform-tests.ts +1 -0
- package/skills/gitnexus-debugging.md +16 -4
- package/skills/gitnexus-exploring.md +3 -3
- package/skills/gitnexus-guide.md +33 -0
- package/skills/gitnexus-pdg-query.md +89 -0
- package/skills/gitnexus-refactoring.md +1 -1
- package/skills/gitnexus-taint-analysis.md +178 -0
- package/vendor/tree-sitter-c/package.json +1 -1
- package/vendor/tree-sitter-dart/package.json +1 -1
- package/vendor/tree-sitter-kotlin/package.json +1 -1
- package/vendor/tree-sitter-proto/package.json +1 -1
- package/vendor/tree-sitter-swift/package.json +1 -1
- package/web/assets/{agent-CKPMqImC.js → agent-D3Xd7zZE.js} +123 -123
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-ChH9xW-N.js +36 -0
- package/web/assets/{blockDiagram-7IZFK4PR-B4niSLvR.js → blockDiagram-7IZFK4PR-BkWhpzWB.js} +1 -1
- package/web/assets/{c4Diagram-Y2BXMSZH-DIzEXalR.js → c4Diagram-Y2BXMSZH-DtBvpzWD.js} +1 -1
- package/web/assets/{chunk-3SSMPTDK-BzGeeheI.js → chunk-3SSMPTDK-B4_etUhr.js} +2 -2
- package/web/assets/{chunk-5IMINLNL-CnTLsXIV.js → chunk-5IMINLNL-DOdTeQri.js} +1 -1
- package/web/assets/{chunk-5VCL7Z4A-w1BCx98Z.js → chunk-5VCL7Z4A-CQ-2dYWj.js} +1 -1
- package/web/assets/chunk-6764PJDD-DpIS7hxD.js +1 -0
- package/web/assets/{chunk-67TQ5CYL-CChC2cAv.js → chunk-67TQ5CYL-4sNPJU1q.js} +3 -3
- package/web/assets/{chunk-7W6UQGC5-CgFyfZ6k.js → chunk-7W6UQGC5-KyEG0HQg.js} +1 -1
- package/web/assets/{chunk-AZZRMDJM-5E9ARdDQ.js → chunk-AZZRMDJM-y-xJBuMz.js} +1 -1
- package/web/assets/{chunk-INKRHTLW-ELpfuk9h.js → chunk-INKRHTLW-Nu4ri9P-.js} +1 -1
- package/web/assets/{chunk-JQRUD6KW-Dcq_Qnyy.js → chunk-JQRUD6KW-Dbva2Z17.js} +1 -1
- package/web/assets/{chunk-KGFNY3KK-W-VR57xb.js → chunk-KGFNY3KK-JGMJvKCK.js} +1 -1
- package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +161 -0
- package/web/assets/{chunk-KNLZD3CH-BuZBOcso.js → chunk-KNLZD3CH-BGlP6X9R.js} +1 -1
- package/web/assets/{chunk-KRXBNO2N-DH2NPM7I.js → chunk-KRXBNO2N-BW5o0KUN.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-Dfmux4m1.js → chunk-LCXTWHL2-zoomRtWX.js} +1 -1
- package/web/assets/{chunk-LII3EMHJ-3X33tCpU.js → chunk-LII3EMHJ-D-jm-dLa.js} +1 -1
- package/web/assets/{chunk-QA3QBVWF-D5Ha3GgB.js → chunk-QA3QBVWF-BgRW3SXd.js} +1 -1
- package/web/assets/{chunk-RG4AUYOV-CAkzcoRj.js → chunk-RG4AUYOV-DD0B2N2B.js} +1 -1
- package/web/assets/{chunk-T2UQINTJ-kGYG7ppP.js → chunk-T2UQINTJ-DSBqkzH7.js} +1 -1
- package/web/assets/chunk-T5OCTHI4-DdZvN-9i.js +1 -0
- package/web/assets/{chunk-UY5QBCOK-Du-c56gs.js → chunk-UY5QBCOK-DyF0vyGd.js} +1 -1
- package/web/assets/{chunk-W44A43WB-lrCpuupA.js → chunk-W44A43WB-JqMLIpR0.js} +1 -1
- package/web/assets/{chunk-ZXARS5L4-CSZRiyOf.js → chunk-ZXARS5L4-CxN8oiwI.js} +1 -1
- package/web/assets/classDiagram-KGZ6W3CR-DJm9BgF-.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-DJm9BgF-.js +1 -0
- package/web/assets/{context-builder-_HS0v2ma.js → context-builder-BHiFUA8O.js} +10 -2
- package/web/assets/{cose-bilkent-UX7MHV2Q-BHv2bbtl.js → cose-bilkent-UX7MHV2Q-D71wNYRJ.js} +1 -1
- package/web/assets/dagre-ND4H6XIP-BIkxmhcu.js +4 -0
- package/web/assets/diagram-3NCE3AQN-BTa6iH0T.js +43 -0
- package/web/assets/diagram-GF46GFSD-DZDV0vBj.js +24 -0
- package/web/assets/{diagram-HNR7UZ2L-fUWreZzx.js → diagram-HNR7UZ2L-DFCfd5LI.js} +2 -2
- package/web/assets/diagram-QXG6HAR7-BzM--Jj0.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-DFFwz0k4.js +10 -0
- package/web/assets/{erDiagram-L5TCEMPS-QN2eEP1e.js → erDiagram-L5TCEMPS-CfHMJJqo.js} +1 -1
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +1 -0
- package/web/assets/{flowDiagram-H6V6AXG4-CXbXImlN.js → flowDiagram-H6V6AXG4-Be805QiJ.js} +3 -3
- package/web/assets/{ganttDiagram-JCBTUEKG-BHQssTz6.js → ganttDiagram-JCBTUEKG-D3iL2Aet.js} +1 -1
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +106 -0
- package/web/assets/index-BvYev1UJ.js +635 -0
- package/web/assets/index-_lgn7hs5.css +2 -0
- package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-Y7BKSoke.js +2 -0
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-6LKOvBfp.js → ishikawaDiagram-BNXS4ZKH-CT4SHFuI.js} +1 -1
- package/web/assets/{journeyDiagram-M6C3CM3L-DNPYCpvq.js → journeyDiagram-M6C3CM3L-CvArszLo.js} +1 -1
- package/web/assets/{kanban-definition-75IXJCU3-DgDi9oJT.js → kanban-definition-75IXJCU3-C6yDxr7N.js} +3 -3
- package/web/assets/{katex-K3KEBU37-CrVLz8l7.js → katex-K3KEBU37-CTc5BslQ.js} +1 -1
- package/web/assets/{mindmap-definition-2TDM6QVE-CwR5sBB-.js → mindmap-definition-2TDM6QVE-BOc2WEne.js} +1 -1
- package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +1 -0
- package/web/assets/{pieDiagram-CU6KROY3-By8g6f6B.js → pieDiagram-CU6KROY3-Cvc0f_Pd.js} +1 -1
- package/web/assets/{quadrantDiagram-VICAPDV7-bAm6Hi_5.js → quadrantDiagram-VICAPDV7-yXSZ2lLz.js} +1 -1
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +1 -0
- package/web/assets/{requirementDiagram-JXO7QTGE-7oDcJ1_J.js → requirementDiagram-JXO7QTGE-BRcZvHs4.js} +1 -1
- package/web/assets/{sankeyDiagram-URQDO5SZ-LFJz53u5.js → sankeyDiagram-URQDO5SZ-1qEjlFIB.js} +1 -1
- package/web/assets/{sequenceDiagram-VS2MUI6T-FySeKCUy.js → sequenceDiagram-VS2MUI6T-PcSCuvrB.js} +3 -3
- package/web/assets/stateDiagram-7D4R322I-D6qYSV1E.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-Bg-ImOSX.js +1 -0
- package/web/assets/{timeline-definition-O6YCAMPW-Ds2CnVZK.js → timeline-definition-O6YCAMPW-QWkh01xw.js} +1 -1
- package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +1 -0
- package/web/assets/{vennDiagram-MWXL3ELB-DUIEwXWp.js → vennDiagram-MWXL3ELB-ak4DfwuM.js} +3 -3
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +1 -0
- package/web/assets/{wardleyDiagram-CUQ6CDDI-DEiFPQih.js → wardleyDiagram-CUQ6CDDI-CTzR4Loq.js} +1 -1
- package/web/assets/{xychartDiagram-N2JHSOCM-BUbayhST.js → xychartDiagram-N2JHSOCM-DA1BEaQz.js} +1 -1
- package/web/index.html +13 -15
- package/scripts/materialize-vendor-grammars.cjs +0 -97
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-BETj2x4g.js +0 -1
- package/web/assets/architectureDiagram-UL44E2DR-D1EXI0zA.js +0 -36
- package/web/assets/chunk-2T2R6R2M-n6s9JZqv.js +0 -4
- package/web/assets/chunk-2UTLFMKG-CMBB1TMN.js +0 -1
- package/web/assets/chunk-4R4BOZG6-mKhL59ul.js +0 -159
- package/web/assets/chunk-6764PJDD-ChwMM2z4.js +0 -1
- package/web/assets/chunk-7J6CGLKN-DT-b53FT.js +0 -10
- package/web/assets/chunk-C62D2QBJ-CDAWj26E.js +0 -1
- package/web/assets/chunk-CEXFNPSA-D68Tk6ls.js +0 -1
- package/web/assets/chunk-CilyBKbf.js +0 -1
- package/web/assets/chunk-J5EP6P6S-DxWW0yvu.js +0 -1
- package/web/assets/chunk-KGYTTC2M-C6PHeuay.js +0 -1
- package/web/assets/chunk-RERM46MO-DQNbXtfw.js +0 -1
- package/web/assets/chunk-RKZBBQEN-BmTPLSyv.js +0 -1
- package/web/assets/chunk-RLI5ZMPA-DExu2DOK.js +0 -1
- package/web/assets/chunk-T5OCTHI4--9wWpVws.js +0 -1
- package/web/assets/chunk-UP6H54XL-DsKdC6jC.js +0 -1
- package/web/assets/chunk-UXSXWOXI-DR81EqLr.js +0 -1
- package/web/assets/classDiagram-KGZ6W3CR-Bv93af_b.js +0 -1
- package/web/assets/classDiagram-v2-72OJOZXJ-CLfEqHUa.js +0 -1
- package/web/assets/dagre-ND4H6XIP-DsIr9MOv.js +0 -4
- package/web/assets/diagram-3NCE3AQN-BqAtKUpW.js +0 -43
- package/web/assets/diagram-GF46GFSD-CaBG6n6o.js +0 -24
- package/web/assets/diagram-QXG6HAR7-CZ-O3rcV.js +0 -24
- package/web/assets/diagram-WEQXMOUZ-P4lSL4GH.js +0 -10
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-B3myHUst.js +0 -1
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DF3rtf4A.js +0 -1
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CCwVLT__.js +0 -106
- package/web/assets/index-BKWA-m7o.css +0 -2
- package/web/assets/index-CG6q8eTs.js +0 -626
- package/web/assets/info-J43DQDTF-KCYPFFUO-R4XV_akJ.js +0 -1
- package/web/assets/infoDiagram-3YFTVSEB-DmLICZx1.js +0 -2
- package/web/assets/packet-YPE3B663-LP52Z2RK-CgQPdNZa.js +0 -1
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BzWOwc_c.js +0 -1
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-B7KG0FN7.js +0 -1
- package/web/assets/stateDiagram-7D4R322I-CB2nABwH.js +0 -1
- package/web/assets/stateDiagram-v2-36443NZ5-COBGd2RL.js +0 -1
- package/web/assets/treeView-BLDUP644-QA4HXRO3-CRSxEwLO.js +0 -1
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-a0PfKoVn.js +0 -1
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-BKQ6e5mC.js +0 -1
- /package/web/assets/{chunk-AQ6EADP3-CCFje6lL.js → chunk-AQ6EADP3-CZhslHi-.js} +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type WriteStream } from 'fs';
|
|
2
|
+
/** Injectable for tests (backpressure/error simulation), mirroring split. */
|
|
3
|
+
export type WriteStreamFactory = (filePath: string) => WriteStream;
|
|
4
|
+
/**
|
|
5
|
+
* Derive a node's table label from its graph id. Matches the legacy
|
|
6
|
+
* `getNodeLabel` that lived inline in `loadGraphToLbug`:
|
|
7
|
+
* - `comm_*` → Community
|
|
8
|
+
* - `proc_*` → Process
|
|
9
|
+
* - otherwise the prefix before the first `:` (e.g. `Function:…` → Function)
|
|
10
|
+
*/
|
|
11
|
+
export declare const getNodeLabel: (nodeId: string) => string;
|
|
12
|
+
export interface RelPairMeta {
|
|
13
|
+
csvPath: string;
|
|
14
|
+
rows: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Routes already-escaped relationship CSV rows to per-FROM→TO-label-pair
|
|
18
|
+
* files. Filters edges whose endpoint labels are not valid node tables
|
|
19
|
+
* (counted as `skipped`), exactly as the legacy split did.
|
|
20
|
+
*/
|
|
21
|
+
export declare class RelPairRouter {
|
|
22
|
+
private readonly csvDir;
|
|
23
|
+
private readonly header;
|
|
24
|
+
private readonly validTables;
|
|
25
|
+
private readonly wsFactory;
|
|
26
|
+
/** pairKey (`From|To`) → { csvPath, rows } */
|
|
27
|
+
readonly byPair: Map<string, RelPairMeta>;
|
|
28
|
+
private readonly streams;
|
|
29
|
+
skipped: number;
|
|
30
|
+
total: number;
|
|
31
|
+
private streamError;
|
|
32
|
+
private readonly abort;
|
|
33
|
+
constructor(csvDir: string, header: string, validTables: Set<string>, wsFactory?: WriteStreamFactory);
|
|
34
|
+
private markError;
|
|
35
|
+
/**
|
|
36
|
+
* The first stream error observed, if any. Lets the emit caller rethrow the
|
|
37
|
+
* real error (EMFILE / disk-full) instead of the generic `AbortError` that a
|
|
38
|
+
* pending `once(ws,'drain',{signal})` rejects with when the abort fires —
|
|
39
|
+
* mirroring the retained `splitRelCsvByLabelPair`'s `throw streamError ?? err`.
|
|
40
|
+
*/
|
|
41
|
+
get lastError(): Error | null;
|
|
42
|
+
/**
|
|
43
|
+
* Route one already-escaped CSV row (no trailing newline) to its pair file.
|
|
44
|
+
* Returns `void` on the synchronous hot path; a `Promise<void>` only when a
|
|
45
|
+
* stream signals backpressure (or a new pair's header does) — the caller
|
|
46
|
+
* awaits the promise before routing the next edge.
|
|
47
|
+
*/
|
|
48
|
+
route(fromId: string, toId: string, row: string): void | Promise<void>;
|
|
49
|
+
private openAndWrite;
|
|
50
|
+
/** Flush + close every pair stream. Rejects if any stream errored. */
|
|
51
|
+
close(): Promise<void>;
|
|
52
|
+
/** Tear down all streams (no flush) — used on the error path. */
|
|
53
|
+
destroy(): void;
|
|
54
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relationship per-label-pair routing (#2203 U2).
|
|
3
|
+
*
|
|
4
|
+
* LadybugDB's bulk `COPY` into the single `CodeRelation` rel table requires a
|
|
5
|
+
* separate CSV per FROM→TO node-label pair (the `from=`/`to=` COPY params).
|
|
6
|
+
* Historically the emit pass wrote one monolithic `relations.csv`, which
|
|
7
|
+
* `loadGraphToLbug` then RE-READ line-by-line (regex per edge) and re-split
|
|
8
|
+
* into per-pair files — writing and reading the entire ~1M-edge set twice.
|
|
9
|
+
*
|
|
10
|
+
* This router lets the single emit pass route each edge to its per-pair file
|
|
11
|
+
* directly, so the monolithic write + re-read + per-edge regex are all gone.
|
|
12
|
+
* The label-derivation + validTables filtering + per-pair-file format here match
|
|
13
|
+
* the legacy `splitRelCsvByLabelPair`, so the per-pair files are byte-identical
|
|
14
|
+
* for all quote-free ids — see the differential test in
|
|
15
|
+
* `test/integration/csv-pipeline.test.ts`. ONE intentional divergence: this
|
|
16
|
+
* router derives the label from the RAW id, while the oracle re-derives it via a
|
|
17
|
+
* regex over the ESCAPED row — so for an id containing a `"` the router is the
|
|
18
|
+
* more-correct path (it routes the edge to the right pair; the oracle's regex
|
|
19
|
+
* mis-buckets or drops it). `splitRelCsvByLabelPair` is retained as the
|
|
20
|
+
* differential oracle (the quote-in-id divergence is asserted explicitly).
|
|
21
|
+
*
|
|
22
|
+
* Backpressure: at most one stream is awaited at a time (the caller routes
|
|
23
|
+
* edges sequentially and awaits the returned drain promise before the next),
|
|
24
|
+
* mirroring the legacy split's `for await` invariant. The hot path (existing
|
|
25
|
+
* pair, no backpressure) returns `void` — no microtask per edge.
|
|
26
|
+
*/
|
|
27
|
+
import path from 'path';
|
|
28
|
+
import { createWriteStream } from 'fs';
|
|
29
|
+
import { once } from 'events';
|
|
30
|
+
import { finished } from 'stream/promises';
|
|
31
|
+
/**
|
|
32
|
+
* Derive a node's table label from its graph id. Matches the legacy
|
|
33
|
+
* `getNodeLabel` that lived inline in `loadGraphToLbug`:
|
|
34
|
+
* - `comm_*` → Community
|
|
35
|
+
* - `proc_*` → Process
|
|
36
|
+
* - otherwise the prefix before the first `:` (e.g. `Function:…` → Function)
|
|
37
|
+
*/
|
|
38
|
+
export const getNodeLabel = (nodeId) => {
|
|
39
|
+
if (nodeId.startsWith('comm_'))
|
|
40
|
+
return 'Community';
|
|
41
|
+
if (nodeId.startsWith('proc_'))
|
|
42
|
+
return 'Process';
|
|
43
|
+
return nodeId.split(':')[0];
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Routes already-escaped relationship CSV rows to per-FROM→TO-label-pair
|
|
47
|
+
* files. Filters edges whose endpoint labels are not valid node tables
|
|
48
|
+
* (counted as `skipped`), exactly as the legacy split did.
|
|
49
|
+
*/
|
|
50
|
+
export class RelPairRouter {
|
|
51
|
+
csvDir;
|
|
52
|
+
header;
|
|
53
|
+
validTables;
|
|
54
|
+
wsFactory;
|
|
55
|
+
/** pairKey (`From|To`) → { csvPath, rows } */
|
|
56
|
+
byPair = new Map();
|
|
57
|
+
streams = new Map();
|
|
58
|
+
skipped = 0;
|
|
59
|
+
total = 0;
|
|
60
|
+
streamError = null;
|
|
61
|
+
abort = new AbortController();
|
|
62
|
+
constructor(csvDir, header, validTables, wsFactory = (p) => createWriteStream(p, 'utf-8')) {
|
|
63
|
+
this.csvDir = csvDir;
|
|
64
|
+
this.header = header;
|
|
65
|
+
this.validTables = validTables;
|
|
66
|
+
this.wsFactory = wsFactory;
|
|
67
|
+
}
|
|
68
|
+
markError = (err) => {
|
|
69
|
+
this.streamError ??= err;
|
|
70
|
+
this.abort.abort(err);
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The first stream error observed, if any. Lets the emit caller rethrow the
|
|
74
|
+
* real error (EMFILE / disk-full) instead of the generic `AbortError` that a
|
|
75
|
+
* pending `once(ws,'drain',{signal})` rejects with when the abort fires —
|
|
76
|
+
* mirroring the retained `splitRelCsvByLabelPair`'s `throw streamError ?? err`.
|
|
77
|
+
*/
|
|
78
|
+
get lastError() {
|
|
79
|
+
return this.streamError;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Route one already-escaped CSV row (no trailing newline) to its pair file.
|
|
83
|
+
* Returns `void` on the synchronous hot path; a `Promise<void>` only when a
|
|
84
|
+
* stream signals backpressure (or a new pair's header does) — the caller
|
|
85
|
+
* awaits the promise before routing the next edge.
|
|
86
|
+
*/
|
|
87
|
+
route(fromId, toId, row) {
|
|
88
|
+
if (this.streamError)
|
|
89
|
+
throw this.streamError;
|
|
90
|
+
const fromLabel = getNodeLabel(fromId);
|
|
91
|
+
const toLabel = getNodeLabel(toId);
|
|
92
|
+
if (!this.validTables.has(fromLabel) || !this.validTables.has(toLabel)) {
|
|
93
|
+
this.skipped++;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const pairKey = `${fromLabel}|${toLabel}`;
|
|
97
|
+
const ws = this.streams.get(pairKey);
|
|
98
|
+
if (ws === undefined) {
|
|
99
|
+
// First edge for this pair: open the stream, write header + row.
|
|
100
|
+
return this.openAndWrite(pairKey, fromLabel, toLabel, row);
|
|
101
|
+
}
|
|
102
|
+
this.byPair.get(pairKey).rows++;
|
|
103
|
+
this.total++;
|
|
104
|
+
if (!ws.write(row + '\n')) {
|
|
105
|
+
return once(ws, 'drain', { signal: this.abort.signal }).then(() => undefined);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async openAndWrite(pairKey, fromLabel, toLabel, row) {
|
|
109
|
+
const csvPath = path.join(this.csvDir, `rel_${fromLabel}_${toLabel}.csv`);
|
|
110
|
+
const ws = this.wsFactory(csvPath);
|
|
111
|
+
ws.on('error', this.markError);
|
|
112
|
+
this.streams.set(pairKey, ws);
|
|
113
|
+
this.byPair.set(pairKey, { csvPath, rows: 1 });
|
|
114
|
+
this.total++;
|
|
115
|
+
if (!ws.write(this.header + '\n')) {
|
|
116
|
+
await once(ws, 'drain', { signal: this.abort.signal });
|
|
117
|
+
}
|
|
118
|
+
if (!ws.write(row + '\n')) {
|
|
119
|
+
await once(ws, 'drain', { signal: this.abort.signal });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** Flush + close every pair stream. Rejects if any stream errored. */
|
|
123
|
+
async close() {
|
|
124
|
+
if (this.streamError) {
|
|
125
|
+
this.destroy();
|
|
126
|
+
throw this.streamError;
|
|
127
|
+
}
|
|
128
|
+
await Promise.all(Array.from(this.streams.values()).map(async (ws) => {
|
|
129
|
+
ws.end();
|
|
130
|
+
await finished(ws);
|
|
131
|
+
}));
|
|
132
|
+
if (this.streamError)
|
|
133
|
+
throw this.streamError;
|
|
134
|
+
}
|
|
135
|
+
/** Tear down all streams (no flush) — used on the error path. */
|
|
136
|
+
destroy() {
|
|
137
|
+
for (const ws of this.streams.values())
|
|
138
|
+
ws.destroy();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -39,10 +39,10 @@ export declare const ANNOTATION_SCHEMA: string;
|
|
|
39
39
|
export declare const CONSTRUCTOR_SCHEMA: string;
|
|
40
40
|
export declare const TEMPLATE_SCHEMA: string;
|
|
41
41
|
export declare const MODULE_SCHEMA: string;
|
|
42
|
-
export declare const ROUTE_SCHEMA = "\nCREATE NODE TABLE Route (\n id STRING,\n name STRING,\n filePath STRING,\n responseKeys STRING[],\n errorKeys STRING[],\n middleware STRING[],\n PRIMARY KEY (id)\n)";
|
|
42
|
+
export declare const ROUTE_SCHEMA = "\nCREATE NODE TABLE Route (\n id STRING,\n name STRING,\n filePath STRING,\n responseKeys STRING[],\n errorKeys STRING[],\n middleware STRING[],\n method STRING,\n PRIMARY KEY (id)\n)";
|
|
43
43
|
export declare const TOOL_SCHEMA = "\nCREATE NODE TABLE Tool (\n id STRING,\n name STRING,\n filePath STRING,\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
44
44
|
export declare const SECTION_SCHEMA = "\nCREATE NODE TABLE Section (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n level INT64,\n content STRING,\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
45
|
-
export declare const BASICBLOCK_SCHEMA = "\nCREATE NODE TABLE BasicBlock (\n id STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n text STRING,\n PRIMARY KEY (id)\n)";
|
|
45
|
+
export declare const BASICBLOCK_SCHEMA = "\nCREATE NODE TABLE BasicBlock (\n id STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n text STRING,\n callees STRING,\n calleeIds STRING,\n PRIMARY KEY (id)\n)";
|
|
46
46
|
export declare const RELATION_SCHEMA = "\nCREATE REL TABLE CodeRelation (\n FROM File TO File,\n FROM File TO Folder,\n FROM File TO Function,\n FROM File TO Class,\n FROM File TO Interface,\n FROM File TO Method,\n FROM File TO CodeElement,\n FROM File TO `Struct`,\n FROM File TO `Enum`,\n FROM File TO `Macro`,\n FROM File TO `Typedef`,\n FROM File TO `Union`,\n FROM File TO `Namespace`,\n FROM File TO `Trait`,\n FROM File TO `Impl`,\n FROM File TO `TypeAlias`,\n FROM File TO `Const`,\n FROM File TO `Static`,\n FROM File TO `Variable`,\n FROM File TO `Property`,\n FROM File TO `Record`,\n FROM File TO `Delegate`,\n FROM File TO `Annotation`,\n FROM File TO `Constructor`,\n FROM File TO `Template`,\n FROM File TO `Module`,\n FROM File TO Section,\n FROM Folder TO Folder,\n FROM Folder TO File,\n FROM Function TO Function,\n FROM Function TO Method,\n FROM Function TO Class,\n FROM Function TO Community,\n FROM Function TO `Macro`,\n FROM Function TO `Struct`,\n FROM Function TO `Template`,\n FROM Function TO `Enum`,\n FROM Function TO `Namespace`,\n FROM Function TO `TypeAlias`,\n FROM Function TO `Module`,\n FROM Function TO `Impl`,\n FROM Function TO Interface,\n FROM Function TO `Constructor`,\n FROM Function TO `Const`,\n FROM Function TO `Typedef`,\n FROM Function TO `Union`,\n FROM Function TO `Property`,\n FROM Function TO CodeElement,\n FROM Class TO Method,\n FROM Class TO Function,\n FROM Class TO Class,\n FROM Class TO Interface,\n FROM Class TO Community,\n FROM Class TO `Template`,\n FROM Class TO `TypeAlias`,\n FROM Class TO `Struct`,\n FROM Class TO `Enum`,\n FROM Class TO `Annotation`,\n FROM Class TO `Constructor`,\n FROM Class TO `Trait`,\n FROM Class TO `Macro`,\n FROM Class TO `Impl`,\n FROM Class TO `Union`,\n FROM Class TO `Namespace`,\n FROM Class TO `Typedef`,\n FROM Class TO `Property`,\n FROM Method TO Function,\n FROM Method TO Method,\n FROM Method TO Class,\n FROM Method TO Community,\n FROM Method TO `Template`,\n FROM Method TO `Struct`,\n FROM Method TO `TypeAlias`,\n FROM Method TO `Enum`,\n FROM Method TO `Macro`,\n FROM Method TO `Namespace`,\n FROM Method TO `Module`,\n FROM Method TO `Impl`,\n FROM Method TO Interface,\n FROM Method TO `Constructor`,\n FROM Method TO `Property`,\n FROM Method TO CodeElement,\n FROM `Template` TO `Template`,\n FROM `Template` TO Function,\n FROM `Template` TO Method,\n FROM `Template` TO Class,\n FROM `Template` TO `Struct`,\n FROM `Template` TO `TypeAlias`,\n FROM `Template` TO `Enum`,\n FROM `Template` TO `Macro`,\n FROM `Template` TO Interface,\n FROM `Template` TO `Constructor`,\n FROM `Module` TO `Module`,\n FROM Section TO Section,\n FROM Section TO File,\n FROM File TO Route,\n FROM Function TO Route,\n FROM Method TO Route,\n FROM File TO Tool,\n FROM Function TO Tool,\n FROM Method TO Tool,\n FROM CodeElement TO Community,\n FROM Interface TO Community,\n FROM Interface TO Function,\n FROM Interface TO Method,\n FROM Interface TO Class,\n FROM Interface TO Interface,\n FROM Interface TO `TypeAlias`,\n FROM Interface TO `Struct`,\n FROM Interface TO `Constructor`,\n FROM Interface TO `Property`,\n FROM `Struct` TO Community,\n FROM `Struct` TO `Trait`,\n FROM `Struct` TO `Struct`,\n FROM `Struct` TO Class,\n FROM `Struct` TO `Enum`,\n FROM `Struct` TO Function,\n FROM `Struct` TO Method,\n FROM `Struct` TO Interface,\n FROM `Struct` TO `Constructor`,\n FROM `Struct` TO `Property`,\n FROM `Enum` TO `Enum`,\n FROM `Enum` TO Community,\n FROM `Enum` TO Class,\n FROM `Enum` TO Interface,\n FROM `Macro` TO Community,\n FROM `Macro` TO Function,\n FROM `Macro` TO Method,\n FROM `Module` TO Function,\n FROM `Module` TO Method,\n FROM `Typedef` TO Community,\n FROM `Union` TO Community,\n FROM `Namespace` TO Community,\n FROM `Namespace` TO `Struct`,\n FROM `Trait` TO Method,\n FROM `Trait` TO `Constructor`,\n FROM `Trait` TO `Property`,\n FROM `Trait` TO Community,\n FROM `Impl` TO Method,\n FROM `Impl` TO `Constructor`,\n FROM `Impl` TO `Property`,\n FROM `Impl` TO Community,\n FROM `Impl` TO `Trait`,\n FROM `Impl` TO `Struct`,\n FROM `Impl` TO `Impl`,\n FROM `TypeAlias` TO Community,\n FROM `TypeAlias` TO `Trait`,\n FROM `TypeAlias` TO Class,\n FROM `Const` TO Community,\n FROM `Static` TO Community,\n FROM `Variable` TO Community,\n FROM `Property` TO Community,\n FROM `Record` TO Method,\n FROM `Record` TO `Constructor`,\n FROM `Record` TO `Property`,\n FROM `Record` TO Community,\n FROM `Delegate` TO Community,\n FROM `Annotation` TO Community,\n FROM `Constructor` TO Community,\n FROM `Constructor` TO Interface,\n FROM `Constructor` TO Class,\n FROM `Constructor` TO Method,\n FROM `Constructor` TO Function,\n FROM `Constructor` TO `Constructor`,\n FROM `Constructor` TO `Struct`,\n FROM `Constructor` TO `Macro`,\n FROM `Constructor` TO `Template`,\n FROM `Constructor` TO `TypeAlias`,\n FROM `Constructor` TO `Enum`,\n FROM `Constructor` TO `Annotation`,\n FROM `Constructor` TO `Impl`,\n FROM `Constructor` TO `Namespace`,\n FROM `Constructor` TO `Module`,\n FROM `Constructor` TO `Property`,\n FROM `Constructor` TO `Typedef`,\n FROM `Template` TO Community,\n FROM `Module` TO Community,\n FROM Function TO Process,\n FROM Method TO Process,\n FROM Class TO Process,\n FROM Interface TO Process,\n FROM `Struct` TO Process,\n FROM `Constructor` TO Process,\n FROM `Module` TO Process,\n FROM `Macro` TO Process,\n FROM `Impl` TO Process,\n FROM `Typedef` TO Process,\n FROM `TypeAlias` TO Process,\n FROM `Enum` TO Process,\n FROM `Union` TO Process,\n FROM `Namespace` TO Process,\n FROM `Trait` TO Process,\n FROM `Const` TO Process,\n FROM `Static` TO Process,\n FROM `Variable` TO Process,\n FROM `Property` TO Process,\n FROM `Record` TO Process,\n FROM `Delegate` TO Process,\n FROM `Annotation` TO Process,\n FROM `Template` TO Process,\n FROM CodeElement TO Process,\n FROM Route TO Process,\n FROM Tool TO Process,\n FROM BasicBlock TO BasicBlock,\n type STRING,\n confidence DOUBLE,\n reason STRING,\n step INT32\n)";
|
|
47
47
|
export declare const EMBEDDING_DIMS: number;
|
|
48
48
|
/** HNSW vector index name for the CodeEmbedding table. */
|
package/dist/core/lbug/schema.js
CHANGED
|
@@ -177,6 +177,7 @@ CREATE NODE TABLE Route (
|
|
|
177
177
|
responseKeys STRING[],
|
|
178
178
|
errorKeys STRING[],
|
|
179
179
|
middleware STRING[],
|
|
180
|
+
method STRING,
|
|
180
181
|
PRIMARY KEY (id)
|
|
181
182
|
)`;
|
|
182
183
|
// MCP tool definitions
|
|
@@ -215,6 +216,8 @@ CREATE NODE TABLE BasicBlock (
|
|
|
215
216
|
startLine INT64,
|
|
216
217
|
endLine INT64,
|
|
217
218
|
text STRING,
|
|
219
|
+
callees STRING,
|
|
220
|
+
calleeIds STRING,
|
|
218
221
|
PRIMARY KEY (id)
|
|
219
222
|
)`;
|
|
220
223
|
// ============================================================================
|
package/dist/core/logger.d.ts
CHANGED
|
@@ -46,11 +46,6 @@ export interface CreateLoggerOptions {
|
|
|
46
46
|
* test mode (tests use an in-memory destination).
|
|
47
47
|
*/
|
|
48
48
|
export declare function flushLoggerSync(): void;
|
|
49
|
-
/**
|
|
50
|
-
* @internal Test-only reset for the pino-pretty availability cache. Lets
|
|
51
|
-
* unit tests exercise both resolve outcomes within the same vitest worker.
|
|
52
|
-
*/
|
|
53
|
-
export declare function _resetPrettyAvailableCache(): void;
|
|
54
49
|
/**
|
|
55
50
|
* Build the pino-pretty transport options. Internal — exported only so unit
|
|
56
51
|
* tests can exercise the probe path without going through `shouldUsePretty()`
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* IMPORTANT: This module must NEVER call process.exit(). The caller (CLI
|
|
9
9
|
* wrapper or server worker) is responsible for process lifecycle.
|
|
10
10
|
*/
|
|
11
|
+
import { type RepoMeta } from '../storage/repo-manager.js';
|
|
11
12
|
export interface AnalyzeCallbacks {
|
|
12
13
|
onProgress: (phase: string, percent: number, message: string) => void;
|
|
13
14
|
onLog?: (message: string) => void;
|
|
@@ -48,6 +49,52 @@ export interface AnalyzeOptions {
|
|
|
48
49
|
noStats?: boolean;
|
|
49
50
|
/** Skip installing standard GitNexus skill files to .claude/skills/gitnexus/. */
|
|
50
51
|
skipSkills?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Build the CFG/PDG substrate (#2081 M1). Forwarded to `PipelineOptions.pdg`,
|
|
54
|
+
* which threads to BOTH the worker (CFG build, via workerData) AND
|
|
55
|
+
* scope-resolution (BasicBlock/CFG emit gate). Off by default.
|
|
56
|
+
*/
|
|
57
|
+
pdg?: boolean;
|
|
58
|
+
/** Per-function source-line cap for worker-side CFG construction (#2081 M1).
|
|
59
|
+
* Forwarded to `PipelineOptions.pdgMaxFunctionLines`. No CLI flag in M1 —
|
|
60
|
+
* programmatic / server analyze-worker path only; the worker applies
|
|
61
|
+
* `DEFAULT_PDG_MAX_FUNCTION_LINES` when unset. */
|
|
62
|
+
pdgMaxFunctionLines?: number;
|
|
63
|
+
/** Per-function CFG edge cap. Forwarded to `PipelineOptions.pdgMaxEdgesPerFunction`. */
|
|
64
|
+
pdgMaxEdgesPerFunction?: number;
|
|
65
|
+
/** Per-function REACHING_DEF edge cap (#2082 M2). Forwarded to
|
|
66
|
+
* `PipelineOptions.pdgMaxReachingDefEdgesPerFunction`. */
|
|
67
|
+
pdgMaxReachingDefEdgesPerFunction?: number;
|
|
68
|
+
/** Per-function CDG edge cap (#2085 M5). Forwarded to
|
|
69
|
+
* `PipelineOptions.pdgMaxCdgEdgesPerFunction`. No CLI flag or rc key —
|
|
70
|
+
* programmatic / server path only, like the other pdg caps. */
|
|
71
|
+
pdgMaxCdgEdgesPerFunction?: number;
|
|
72
|
+
/** Per-function taint findings cap (#2083 M3). Forwarded to
|
|
73
|
+
* `PipelineOptions.pdgMaxTaintFindingsPerFunction`. No CLI flag or rc key
|
|
74
|
+
* (KTD8) — programmatic / server path only, like the other pdg caps. */
|
|
75
|
+
pdgMaxTaintFindingsPerFunction?: number;
|
|
76
|
+
/** Per-finding taint hop cap (#2083 M3, KTD6). Forwarded to
|
|
77
|
+
* `PipelineOptions.pdgMaxTaintHops`. No CLI flag or rc key (KTD8). */
|
|
78
|
+
pdgMaxTaintHops?: number;
|
|
79
|
+
/** Per-run cross-function findings/hops/edges caps (#2084 review P1-3).
|
|
80
|
+
* Forwarded to the matching `PipelineOptions.pdgMaxInterproc*`; resolved
|
|
81
|
+
* into `RepoMeta.pdg`. No CLI flag or rc key (KTD8). */
|
|
82
|
+
pdgMaxInterprocFindings?: number;
|
|
83
|
+
pdgMaxInterprocHops?: number;
|
|
84
|
+
pdgMaxInterprocEdges?: number;
|
|
85
|
+
/**
|
|
86
|
+
* Stream the BasicBlock + intra-file PDG-edge layer to CSV-on-disk during the
|
|
87
|
+
* emit loop instead of materializing it in the in-memory graph, bounding peak
|
|
88
|
+
* RSS to O(chunk) for full-kernel-scale repos (#2202). Only engages on a full
|
|
89
|
+
* rebuild — `resolveStreamPdgEmit` additionally requires `force === true`
|
|
90
|
+
* (the pre-pipeline guarantee of a full rebuild). May also be enabled via
|
|
91
|
+
* `GITNEXUS_STREAM_PDG_EMIT`. Memory-only; byte-identical output; not stamped
|
|
92
|
+
* into `RepoMeta.pdg`. */
|
|
93
|
+
streamPdgEmit?: boolean;
|
|
94
|
+
/** Streamed PDG-emit write buffer (rows). `undefined` ⇒
|
|
95
|
+
* `DEFAULT_PDG_EMIT_CHUNK_ROWS`. May also be set via
|
|
96
|
+
* `GITNEXUS_PDG_EMIT_CHUNK_SIZE`. Memory-only (#2202). */
|
|
97
|
+
pdgEmitChunkSize?: number;
|
|
51
98
|
/**
|
|
52
99
|
* Default branch threaded into generated AGENTS.md / CLAUDE.md so the
|
|
53
100
|
* regression-compare example uses the configured branch instead of a
|
|
@@ -162,4 +209,53 @@ export declare const collectBranchCacheKeys: (storagePath: string, excludeDir?:
|
|
|
162
209
|
keys: Set<string>;
|
|
163
210
|
complete: boolean;
|
|
164
211
|
}>;
|
|
212
|
+
/**
|
|
213
|
+
* Resolve the requested `--pdg` configuration to the shape recorded in
|
|
214
|
+
* `RepoMeta.pdg`, or `undefined` for a pdg-off run. Caps resolve to their
|
|
215
|
+
* defaults so an explicit-default run compares equal to a default run
|
|
216
|
+
* (`0` = unlimited is preserved as `0`). Pure + exported for testing.
|
|
217
|
+
*/
|
|
218
|
+
type PdgOptions = Pick<AnalyzeOptions, 'pdg' | 'pdgMaxFunctionLines' | 'pdgMaxEdgesPerFunction' | 'pdgMaxReachingDefEdgesPerFunction' | 'pdgMaxCdgEdgesPerFunction' | 'pdgMaxTaintFindingsPerFunction' | 'pdgMaxTaintHops' | 'pdgMaxInterprocFindings' | 'pdgMaxInterprocHops' | 'pdgMaxInterprocEdges'>;
|
|
219
|
+
export declare const resolvePdgConfig: (options: PdgOptions) => RepoMeta["pdg"];
|
|
220
|
+
/**
|
|
221
|
+
* Whether streaming/chunked PDG graph emit (#2202) engages this run.
|
|
222
|
+
*
|
|
223
|
+
* Streaming flushes the BasicBlock + intra-file PDG-edge layer to CSV-on-disk
|
|
224
|
+
* during the emit loop and never lands it in the in-memory graph, bounding peak
|
|
225
|
+
* RSS to O(chunk). It is sound ONLY on a full rebuild: the incremental
|
|
226
|
+
* writeback (`extractChangedSubgraph`) reads BasicBlock nodes back out of the
|
|
227
|
+
* in-memory graph, which streaming has already offloaded. `force === true` is
|
|
228
|
+
* the pre-pipeline guarantee of a full rebuild — `isIncremental` has
|
|
229
|
+
* `!force` as a necessary condition — so gating on it avoids the deliberately
|
|
230
|
+
* absent pre-pipeline incremental prediction (see the `isIncremental` note).
|
|
231
|
+
*
|
|
232
|
+
* Requires `pdg === true` (nothing to stream otherwise). Enabled by either the
|
|
233
|
+
* explicit `streamPdgEmit` option or the `GITNEXUS_STREAM_PDG_EMIT` env toggle.
|
|
234
|
+
* Memory-only — NOT part of {@link resolvePdgConfig}, so toggling it never
|
|
235
|
+
* trips `pdgModeMismatch`. Read every call (not memoized) so `vi.stubEnv`
|
|
236
|
+
* works in tests. Pure + exported for testing.
|
|
237
|
+
*/
|
|
238
|
+
export declare const resolveStreamPdgEmit: (options: {
|
|
239
|
+
pdg?: boolean;
|
|
240
|
+
force?: boolean;
|
|
241
|
+
streamPdgEmit?: boolean;
|
|
242
|
+
}) => boolean;
|
|
243
|
+
/**
|
|
244
|
+
* Resolve the streamed PDG-emit write-buffer size (#2202). Explicit option wins
|
|
245
|
+
* over `GITNEXUS_PDG_EMIT_CHUNK_SIZE`; `undefined` ⇒ the sink's
|
|
246
|
+
* `DEFAULT_PDG_EMIT_CHUNK_ROWS`. Memory-only; does not affect emitted bytes.
|
|
247
|
+
*/
|
|
248
|
+
export declare const resolvePdgEmitChunkSize: (options: {
|
|
249
|
+
pdgEmitChunkSize?: number;
|
|
250
|
+
}) => number | undefined;
|
|
251
|
+
/**
|
|
252
|
+
* Whether the requested `--pdg` configuration differs from the one the
|
|
253
|
+
* existing index's DB rows were built under (#2099 F1). An absent recorded
|
|
254
|
+
* stamp means pdg-off (every legacy meta — `--pdg` shipped opt-in). Any
|
|
255
|
+
* mismatch means the incremental writeback (which only persists changed-file
|
|
256
|
+
* nodes) cannot produce a coherent index: off→on would silently drop the
|
|
257
|
+
* freshly built CFG layer, on→off would strand zombie BasicBlocks — so the
|
|
258
|
+
* caller forces a full writeback. Pure + exported for testing.
|
|
259
|
+
*/
|
|
260
|
+
export declare const pdgModeMismatch: (recorded: RepoMeta["pdg"], options: PdgOptions) => boolean;
|
|
165
261
|
export declare function runFullAnalysis(repoPath: string, options: AnalyzeOptions, callbacks: AnalyzeCallbacks): Promise<AnalyzeResult>;
|
package/dist/core/run-analyze.js
CHANGED
|
@@ -13,11 +13,18 @@ import fs from 'fs/promises';
|
|
|
13
13
|
import { execFileSync } from 'child_process';
|
|
14
14
|
import { runPipelineFromRepo } from './ingestion/pipeline.js';
|
|
15
15
|
import { resetDegradedParseCounter } from './tree-sitter/safe-parse.js';
|
|
16
|
-
import { initLbug, loadGraphToLbug, getLbugStats, executeQuery, executeWithReusedStatement, closeLbug, loadCachedEmbeddings, deleteNodesForFile, deleteAllCommunitiesAndProcesses, queryImporters, loadFTSExtension, } from './lbug/lbug-adapter.js';
|
|
16
|
+
import { initLbug, loadGraphToLbug, getLbugStats, executeQuery, executeWithReusedStatement, closeLbug, loadCachedEmbeddings, deleteNodesForFile, deleteAllCommunitiesAndProcesses, deleteAllInterprocTaintPaths, deleteAllCallSummaries, queryImporters, loadFTSExtension, } from './lbug/lbug-adapter.js';
|
|
17
17
|
import { createSearchFTSIndexes, verifySearchFTSIndexes } from './search/fts-indexes.js';
|
|
18
18
|
import { resolveAnalyzeInstallPolicy } from './lbug/extension-loader.js';
|
|
19
19
|
import { startWalCheckpointDriver, } from './lbug/wal-checkpoint-driver.js';
|
|
20
20
|
import { getStoragePaths, resolveBranchPlacement, saveMeta, loadMeta, ensureGitNexusIgnored, registerRepo, cleanupOldKuzuFiles, INCREMENTAL_SCHEMA_VERSION, } from '../storage/repo-manager.js';
|
|
21
|
+
import { DEFAULT_PDG_MAX_FUNCTION_LINES } from './ingestion/cfg/collect.js';
|
|
22
|
+
import { DEFAULT_MAX_CFG_EDGES_PER_FUNCTION, DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION, DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION, } from './ingestion/cfg/emit.js';
|
|
23
|
+
import { DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION, DEFAULT_PDG_MAX_TAINT_HOPS, } from './ingestion/taint/propagate.js';
|
|
24
|
+
import { DEFAULT_MAX_INTERPROC_HOPS, DEFAULT_PDG_MAX_INTERPROC_FINDINGS, } from './ingestion/taint/interproc-solver.js';
|
|
25
|
+
import { DEFAULT_PDG_MAX_INTERPROC_EDGES } from './ingestion/taint/interproc-emit.js';
|
|
26
|
+
import { taintModelVersion } from './ingestion/taint/typescript-model.js';
|
|
27
|
+
import { parseTruthyEnv, parsePositiveIntEnv } from './ingestion/utils/env.js';
|
|
21
28
|
import { computeFileHashes, diffFileHashes } from '../storage/file-hash.js';
|
|
22
29
|
import { extractChangedSubgraph, computeEffectiveWriteSet, } from './incremental/subgraph-extract.js';
|
|
23
30
|
import { shadowCandidatesFor } from './incremental/shadow-candidates.js';
|
|
@@ -128,6 +135,123 @@ export const collectBranchCacheKeys = async (storagePath, excludeDir) => {
|
|
|
128
135
|
}
|
|
129
136
|
return { keys, complete };
|
|
130
137
|
};
|
|
138
|
+
export const resolvePdgConfig = (options) => options.pdg === true
|
|
139
|
+
? {
|
|
140
|
+
maxFunctionLines: options.pdgMaxFunctionLines ?? DEFAULT_PDG_MAX_FUNCTION_LINES,
|
|
141
|
+
maxEdgesPerFunction: options.pdgMaxEdgesPerFunction ?? DEFAULT_MAX_CFG_EDGES_PER_FUNCTION,
|
|
142
|
+
maxReachingDefEdgesPerFunction: options.pdgMaxReachingDefEdgesPerFunction ??
|
|
143
|
+
DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION,
|
|
144
|
+
// #2085 M5: control-dependence cap. Absent on any pre-M5 (M2/M3/M4-era)
|
|
145
|
+
// stamp → the key-union pdgModeMismatch trips the first CDG-aware run
|
|
146
|
+
// over an existing `--pdg` index and forces the full writeback that
|
|
147
|
+
// materialises CDG edges for every file without `--force`.
|
|
148
|
+
maxCdgEdgesPerFunction: options.pdgMaxCdgEdgesPerFunction ?? DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION,
|
|
149
|
+
// #2083 M3: taint caps + model identity. The key-union comparator in
|
|
150
|
+
// pdgModeMismatch picks these up structurally — an M2-era stamp lacks
|
|
151
|
+
// all three, so the first M3 run over an M2 `--pdg` index trips a full
|
|
152
|
+
// writeback that populates TAINTED/SANITIZES rows without `--force`.
|
|
153
|
+
maxTaintFindingsPerFunction: options.pdgMaxTaintFindingsPerFunction ?? DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION,
|
|
154
|
+
maxTaintHops: options.pdgMaxTaintHops ?? DEFAULT_PDG_MAX_TAINT_HOPS,
|
|
155
|
+
// #2084 review P1-3: cross-function caps. Absent on an M3-era stamp →
|
|
156
|
+
// pdgModeMismatch trips the first run that adds them (key-union),
|
|
157
|
+
// forcing the full writeback that re-materialises TAINT_PATH bounded.
|
|
158
|
+
maxInterprocFindings: options.pdgMaxInterprocFindings ?? DEFAULT_PDG_MAX_INTERPROC_FINDINGS,
|
|
159
|
+
maxInterprocHops: options.pdgMaxInterprocHops ?? DEFAULT_MAX_INTERPROC_HOPS,
|
|
160
|
+
maxInterprocEdges: options.pdgMaxInterprocEdges ?? DEFAULT_PDG_MAX_INTERPROC_EDGES,
|
|
161
|
+
// Built-in model digest (KTD7/R7): persisted findings must never
|
|
162
|
+
// outlive the model that produced them — ANY model-content change
|
|
163
|
+
// ships as a new digest and repopulates the taint edges.
|
|
164
|
+
taintModelVersion,
|
|
165
|
+
// #2201 review R3: reaching-defs solver identity. The SSA-sparse rewrite
|
|
166
|
+
// computes full facts for deep-loop functions the dense worklist used to
|
|
167
|
+
// truncate to empty, so an existing `--pdg` index carries stale-truncated
|
|
168
|
+
// REACHING_DEF rows. Absent on any pre-#2201 stamp → the key-union
|
|
169
|
+
// pdgModeMismatch trips on the first upgraded run and forces the full
|
|
170
|
+
// writeback that recomputes the fuller coverage (no `--force` needed).
|
|
171
|
+
// Bump this tag on any future change to which facts the solver emits.
|
|
172
|
+
reachingDefSolver: 'ssa-sparse-v1',
|
|
173
|
+
// PDG FU-C: this run records CALL_SUMMARY return-value-ascent edges.
|
|
174
|
+
// Absent on any pre-FU-C (v3) stamp → the key-union pdgModeMismatch trips
|
|
175
|
+
// the first FU-C-aware run over an existing `--pdg` index and forces the
|
|
176
|
+
// full writeback that materialises CALL_SUMMARY edges without `--force`;
|
|
177
|
+
// and `impact`'s PDG mode reads its absence to note "no return-value
|
|
178
|
+
// ascent (re-index for CALL_SUMMARY)" on a v3 index (intra slice intact).
|
|
179
|
+
hasCallSummary: true,
|
|
180
|
+
}
|
|
181
|
+
: undefined;
|
|
182
|
+
/**
|
|
183
|
+
* Whether streaming/chunked PDG graph emit (#2202) engages this run.
|
|
184
|
+
*
|
|
185
|
+
* Streaming flushes the BasicBlock + intra-file PDG-edge layer to CSV-on-disk
|
|
186
|
+
* during the emit loop and never lands it in the in-memory graph, bounding peak
|
|
187
|
+
* RSS to O(chunk). It is sound ONLY on a full rebuild: the incremental
|
|
188
|
+
* writeback (`extractChangedSubgraph`) reads BasicBlock nodes back out of the
|
|
189
|
+
* in-memory graph, which streaming has already offloaded. `force === true` is
|
|
190
|
+
* the pre-pipeline guarantee of a full rebuild — `isIncremental` has
|
|
191
|
+
* `!force` as a necessary condition — so gating on it avoids the deliberately
|
|
192
|
+
* absent pre-pipeline incremental prediction (see the `isIncremental` note).
|
|
193
|
+
*
|
|
194
|
+
* Requires `pdg === true` (nothing to stream otherwise). Enabled by either the
|
|
195
|
+
* explicit `streamPdgEmit` option or the `GITNEXUS_STREAM_PDG_EMIT` env toggle.
|
|
196
|
+
* Memory-only — NOT part of {@link resolvePdgConfig}, so toggling it never
|
|
197
|
+
* trips `pdgModeMismatch`. Read every call (not memoized) so `vi.stubEnv`
|
|
198
|
+
* works in tests. Pure + exported for testing.
|
|
199
|
+
*/
|
|
200
|
+
export const resolveStreamPdgEmit = (options) => options.pdg === true &&
|
|
201
|
+
options.force === true &&
|
|
202
|
+
(options.streamPdgEmit === true || parseTruthyEnv(process.env.GITNEXUS_STREAM_PDG_EMIT));
|
|
203
|
+
/**
|
|
204
|
+
* Resolve the streamed PDG-emit write-buffer size (#2202). Explicit option wins
|
|
205
|
+
* over `GITNEXUS_PDG_EMIT_CHUNK_SIZE`; `undefined` ⇒ the sink's
|
|
206
|
+
* `DEFAULT_PDG_EMIT_CHUNK_ROWS`. Memory-only; does not affect emitted bytes.
|
|
207
|
+
*/
|
|
208
|
+
export const resolvePdgEmitChunkSize = (options) => {
|
|
209
|
+
// Only honor a positive-integer explicit option; `0`/negative is NOT nullish
|
|
210
|
+
// so `?? env` would pass it through and make the sink flush every row.
|
|
211
|
+
const opt = options.pdgEmitChunkSize;
|
|
212
|
+
if (opt !== undefined && Number.isInteger(opt) && opt > 0)
|
|
213
|
+
return opt;
|
|
214
|
+
return parsePositiveIntEnv(process.env.GITNEXUS_PDG_EMIT_CHUNK_SIZE);
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* Whether the requested `--pdg` configuration differs from the one the
|
|
218
|
+
* existing index's DB rows were built under (#2099 F1). An absent recorded
|
|
219
|
+
* stamp means pdg-off (every legacy meta — `--pdg` shipped opt-in). Any
|
|
220
|
+
* mismatch means the incremental writeback (which only persists changed-file
|
|
221
|
+
* nodes) cannot produce a coherent index: off→on would silently drop the
|
|
222
|
+
* freshly built CFG layer, on→off would strand zombie BasicBlocks — so the
|
|
223
|
+
* caller forces a full writeback. Pure + exported for testing.
|
|
224
|
+
*/
|
|
225
|
+
export const pdgModeMismatch = (recorded, options) => {
|
|
226
|
+
const requested = resolvePdgConfig(options);
|
|
227
|
+
if (!requested && !recorded)
|
|
228
|
+
return false;
|
|
229
|
+
if (!requested || !recorded)
|
|
230
|
+
return true;
|
|
231
|
+
// Structural comparison over the KEY UNION of both resolved records — not a
|
|
232
|
+
// hand-maintained field list. Both sides come fully resolved from
|
|
233
|
+
// resolvePdgConfig, so any new emit-affecting knob added there joins the
|
|
234
|
+
// comparison automatically (M1's hand-extended comparator was the trap this
|
|
235
|
+
// closes: a knob it missed would silently strand a stale projection). It is
|
|
236
|
+
// also what makes the M1→M2 upgrade work with zero extra code: an M1-era
|
|
237
|
+
// stamp lacks maxReachingDefEdgesPerFunction, so `4000 !== undefined` trips
|
|
238
|
+
// a full writeback that populates REACHING_DEF rows without `--force`.
|
|
239
|
+
const reqRecord = requested;
|
|
240
|
+
const recRecord = recorded;
|
|
241
|
+
// INVARIANT: every value stamped by resolvePdgConfig MUST be a SCALAR (string /
|
|
242
|
+
// number / boolean). This comparison is a shallow `!==`, so an OBJECT or ARRAY
|
|
243
|
+
// value would compare by REFERENCE — two structurally-equal values from
|
|
244
|
+
// different runs would always be `!==`, tripping pdgModeMismatch on every
|
|
245
|
+
// re-analyze and forcing a needless full writeback. e.g. do NOT change
|
|
246
|
+
// `hasCallSummary: true` to a per-language object like `{ ts: true, ... }`; keep
|
|
247
|
+
// the diagnostic per-language refinement in the impact CONSUMER (see
|
|
248
|
+
// pdg-impact.ts assemblePdgImpactResult), not in this version discriminator.
|
|
249
|
+
for (const key of new Set([...Object.keys(reqRecord), ...Object.keys(recRecord)])) {
|
|
250
|
+
if (reqRecord[key] !== recRecord[key])
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
return false;
|
|
254
|
+
};
|
|
131
255
|
export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
132
256
|
const log = (msg) => callbacks.onLog?.(msg);
|
|
133
257
|
const progress = (phase, percent, message) => callbacks.onProgress(phase, percent, message);
|
|
@@ -265,13 +389,37 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
265
389
|
// clear it, the on-disk index may be in a half-state. Cheapest path
|
|
266
390
|
// back to a known-good index is to wipe + rebuild from scratch.
|
|
267
391
|
if (existingMeta?.incrementalInProgress) {
|
|
268
|
-
log(
|
|
392
|
+
log(
|
|
393
|
+
// "analyze run", not "incremental run" — since #2099 F1 the flag is a
|
|
394
|
+
// generic dirty marker written by BOTH writeback branches.
|
|
395
|
+
'Previous analyze run did not complete cleanly (incrementalInProgress flag set); ' +
|
|
269
396
|
'forcing full rebuild to restore a known-good index.');
|
|
270
397
|
options = { ...options, force: true };
|
|
271
398
|
// Reload meta after clearing the flag in-memory; we still want fileHashes
|
|
272
399
|
// for the post-rebuild meta carry-over, but force=true ensures the
|
|
273
400
|
// rebuild path executes.
|
|
274
401
|
}
|
|
402
|
+
// ── pdg-mode flip forces full writeback (#2099 F1) ─────────────────
|
|
403
|
+
// The incremental writeback persists only changed-file nodes, so a pdg
|
|
404
|
+
// config differing from the one the DB rows were built under cannot be
|
|
405
|
+
// reconciled incrementally: off→on silently drops the freshly built CFG
|
|
406
|
+
// layer ("Incremental: changed=0", zero BasicBlock rows), on→off strands
|
|
407
|
+
// zombie blocks for unchanged files. MUST sit before the alreadyUpToDate
|
|
408
|
+
// fast path below — a clean-tree flip would otherwise early-return without
|
|
409
|
+
// running the pipeline at all. The notice is deliberately NOT gated on
|
|
410
|
+
// options.force: --skills implies force with no message of its own, and a
|
|
411
|
+
// mode change deserves a diagnostic regardless of why a rebuild happens.
|
|
412
|
+
if (existingMeta && pdgModeMismatch(existingMeta.pdg, options)) {
|
|
413
|
+
const pdgOn = options.pdg === true;
|
|
414
|
+
const capsOnly = !!existingMeta.pdg && pdgOn; // both-on can only mismatch via caps
|
|
415
|
+
const was = existingMeta.pdg ? 'with --pdg' : 'without --pdg';
|
|
416
|
+
const now = pdgOn ? 'with --pdg' : 'without --pdg';
|
|
417
|
+
log(`pdg mode changed (index built ${was}, this run is ${now}` +
|
|
418
|
+
`${capsOnly ? ', but with different caps' : ''}); forcing a full ` +
|
|
419
|
+
`rebuild so the CFG layer is ${pdgOn ? 'fully persisted' : 'fully removed'}. ` +
|
|
420
|
+
`Tip: set \`pdg: ${pdgOn}\` in .gitnexusrc to pin the mode across runs.`);
|
|
421
|
+
options = { ...options, force: true };
|
|
422
|
+
}
|
|
275
423
|
// ── Early-return: already up to date ──────────────────────────────
|
|
276
424
|
if (existingMeta && !options.force && existingMeta.lastCommit === currentCommit) {
|
|
277
425
|
// Non-git folders have currentCommit = '' — always rebuild since we can't detect changes
|
|
@@ -416,6 +564,23 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
416
564
|
}, {
|
|
417
565
|
parseCache,
|
|
418
566
|
workerPoolSize: options.workerPoolSize,
|
|
567
|
+
// CFG/PDG opt-in (#2081 M1). PipelineOptions.pdg fans out to the worker
|
|
568
|
+
// build gate (workerData.pdg) and the scope-resolution emit gate.
|
|
569
|
+
pdg: options.pdg === true,
|
|
570
|
+
pdgMaxFunctionLines: options.pdgMaxFunctionLines,
|
|
571
|
+
pdgMaxEdgesPerFunction: options.pdgMaxEdgesPerFunction,
|
|
572
|
+
pdgMaxReachingDefEdgesPerFunction: options.pdgMaxReachingDefEdgesPerFunction,
|
|
573
|
+
pdgMaxCdgEdgesPerFunction: options.pdgMaxCdgEdgesPerFunction,
|
|
574
|
+
pdgMaxTaintFindingsPerFunction: options.pdgMaxTaintFindingsPerFunction,
|
|
575
|
+
pdgMaxTaintHops: options.pdgMaxTaintHops,
|
|
576
|
+
pdgMaxInterprocFindings: options.pdgMaxInterprocFindings,
|
|
577
|
+
pdgMaxInterprocHops: options.pdgMaxInterprocHops,
|
|
578
|
+
pdgMaxInterprocEdges: options.pdgMaxInterprocEdges,
|
|
579
|
+
// Streaming/chunked PDG emit (#2202) — gated to full-rebuild runs
|
|
580
|
+
// (force === true) so the incremental writeback never reads back an
|
|
581
|
+
// offloaded BasicBlock layer. Memory-only; byte-identical output.
|
|
582
|
+
streamPdgEmit: resolveStreamPdgEmit(options),
|
|
583
|
+
pdgEmitChunkSize: resolvePdgEmitChunkSize(options),
|
|
419
584
|
fetchWrappers: options.fetchWrappers,
|
|
420
585
|
});
|
|
421
586
|
// ── Phase 2: LadybugDB (60–85%) ──────────────────────────────────
|
|
@@ -465,6 +630,19 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
465
630
|
}
|
|
466
631
|
else {
|
|
467
632
|
// Full rebuild path: wipe DB files first.
|
|
633
|
+
// Set the dirty flag BEFORE the wipe whenever a prior meta exists,
|
|
634
|
+
// mirroring the incremental branch above (#2099 F1, KTD2b). Without it a
|
|
635
|
+
// full rebuild crashing between the wipe and the end-of-run saveMeta
|
|
636
|
+
// leaves a meta that vouches for a DB it no longer matches — the next
|
|
637
|
+
// clean-tree run's fast path would certify a destroyed DB (or, after a
|
|
638
|
+
// pdg flip, certify zombie/missing BasicBlock rows indefinitely).
|
|
639
|
+
// toWriteCount: 0 is the full-path sentinel (no incremental write set).
|
|
640
|
+
if (existingMeta) {
|
|
641
|
+
await saveMeta(metaDir, {
|
|
642
|
+
...existingMeta,
|
|
643
|
+
incrementalInProgress: { startedAt: Date.now(), toWriteCount: 0 },
|
|
644
|
+
});
|
|
645
|
+
}
|
|
468
646
|
await closeLbug();
|
|
469
647
|
const lbugFiles = [lbugPath, `${lbugPath}.wal`, `${lbugPath}.lock`];
|
|
470
648
|
for (const f of lbugFiles) {
|
|
@@ -606,6 +784,21 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
606
784
|
// from the fresh pipeline output below. Required for the
|
|
607
785
|
// "Leiden runs on the FULL graph" correctness invariant.
|
|
608
786
|
await deleteAllCommunitiesAndProcesses();
|
|
787
|
+
// 2b. Drop interprocedural TAINT_PATH edges (#2084 M4 U6) when pdg is on
|
|
788
|
+
// — their validity is a whole-program property (an A→C flow can be
|
|
789
|
+
// invalidated by a change to an intermediate function on a third
|
|
790
|
+
// file), so endpoint-writability extraction can't refresh them.
|
|
791
|
+
// extractChangedSubgraph re-includes all of them from the fresh
|
|
792
|
+
// graph (isGraphWideRelType), mirroring Community/Process.
|
|
793
|
+
if (options.pdg === true) {
|
|
794
|
+
await deleteAllInterprocTaintPaths();
|
|
795
|
+
// 2c. Drop CALL_SUMMARY edges (PDG FU-C) on an incremental `--pdg`
|
|
796
|
+
// writeback. They are re-included from the FULL fresh graph
|
|
797
|
+
// (isGraphWideRelType) and the callSummaries phase recomputes every
|
|
798
|
+
// summary each run, so delete-all-then-rebuild keeps an unchanged
|
|
799
|
+
// function's summary from being lost — same contract as TAINT_PATH.
|
|
800
|
+
await deleteAllCallSummaries();
|
|
801
|
+
}
|
|
609
802
|
// 3. Extract the changed subgraph from the FULL ctx.graph and write
|
|
610
803
|
// only that. Unchanged-file rows in the DB stay untouched. Pass
|
|
611
804
|
// the SAME effectiveWriteSet so the subgraph and the deletes
|
|
@@ -619,11 +812,15 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
619
812
|
}
|
|
620
813
|
else {
|
|
621
814
|
// ── Full rebuild ───────────────────────────────────────────────
|
|
815
|
+
// Pass the streamed PDG-emit manifest (#2202) so the BasicBlock layer that
|
|
816
|
+
// was flushed to CSV during the emit loop is COPY'd alongside the
|
|
817
|
+
// structural CSVs. Only ever set on a full rebuild (streaming is
|
|
818
|
+
// force-gated), so the incremental branch above never carries it.
|
|
622
819
|
await loadGraphToLbug(pipelineResult.graph, pipelineResult.repoPath, storagePath, (msg) => {
|
|
623
820
|
lbugMsgCount++;
|
|
624
821
|
const pct = Math.min(84, 60 + Math.round((lbugMsgCount / (lbugMsgCount + 10)) * 24));
|
|
625
822
|
progress('lbug', pct, msg);
|
|
626
|
-
});
|
|
823
|
+
}, pipelineResult.pdgEmitManifest);
|
|
627
824
|
}
|
|
628
825
|
// ── Phase 3: FTS (85–90%) ─────────────────────────────────────────
|
|
629
826
|
// The analyze (write) path owns building the search indexes, so it uses
|
|
@@ -846,6 +1043,12 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
846
1043
|
// so a sibling branch's prune can union it and not evict our shards.
|
|
847
1044
|
cacheKeys: [...parseCache.usedKeys],
|
|
848
1045
|
incrementalInProgress: undefined,
|
|
1046
|
+
// The effective pdg config this run's DB rows were built under
|
|
1047
|
+
// (#2099 F1). `undefined` on pdg-off runs — this meta is a fresh
|
|
1048
|
+
// literal (no spread of existingMeta), so omission is what CLEARS the
|
|
1049
|
+
// stamp after an on→off flip; the next pdgModeMismatch then compares
|
|
1050
|
+
// off==off and incremental eligibility is restored.
|
|
1051
|
+
pdg: resolvePdgConfig(options),
|
|
849
1052
|
};
|
|
850
1053
|
await saveMeta(metaDir, meta);
|
|
851
1054
|
// Persist the incremental parse cache for the next run. Wraps in
|
|
@@ -938,6 +1141,7 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
938
1141
|
skipSkills: options.skipSkills,
|
|
939
1142
|
noStats: options.noStats,
|
|
940
1143
|
defaultBranch: options.defaultBranch,
|
|
1144
|
+
hasPdg: options.pdg === true,
|
|
941
1145
|
});
|
|
942
1146
|
}
|
|
943
1147
|
catch {
|