gitnexus 1.6.10-rc.2 → 1.6.10-rc.21
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 +56 -12
- package/dist/cli/analyze.js +166 -5
- package/dist/cli/clean.js +17 -3
- package/dist/cli/cli-message.d.ts +1 -1
- package/dist/cli/doctor.d.ts +18 -0
- package/dist/cli/doctor.js +76 -3
- package/dist/cli/embeddings.d.ts +12 -0
- package/dist/cli/embeddings.js +49 -0
- package/dist/cli/help-i18n.js +4 -0
- package/dist/cli/i18n/en.d.ts +10 -5
- package/dist/cli/i18n/en.js +10 -5
- package/dist/cli/i18n/resources.d.ts +15 -5
- package/dist/cli/i18n/zh-CN.d.ts +5 -0
- package/dist/cli/i18n/zh-CN.js +10 -5
- package/dist/cli/index.js +12 -1
- package/dist/core/augmentation/engine.js +4 -3
- package/dist/core/embeddings/embedder.js +16 -2
- package/dist/core/embeddings/embedding-pipeline.d.ts +20 -0
- package/dist/core/embeddings/embedding-pipeline.js +10 -2
- package/dist/core/embeddings/http-client.d.ts +28 -1
- package/dist/core/embeddings/http-client.js +107 -15
- package/dist/core/embeddings/node-module-compat.d.ts +23 -0
- package/dist/core/embeddings/node-module-compat.js +23 -0
- package/dist/core/embeddings/onnxruntime-common-resolver.js +6 -3
- package/dist/core/embeddings/onnxruntime-node-resolver.js +31 -5
- package/dist/core/embeddings/runtime-install.d.ts +119 -0
- package/dist/core/embeddings/runtime-install.js +372 -0
- package/dist/core/embeddings/runtime-support.d.ts +48 -17
- package/dist/core/embeddings/runtime-support.js +96 -0
- package/dist/core/group/extractors/http-patterns/python.js +246 -108
- package/dist/core/group/extractors/manifest-extractor.js +4 -0
- package/dist/core/incremental/escalation-gate.d.ts +38 -0
- package/dist/core/incremental/escalation-gate.js +48 -0
- package/dist/core/incremental/shadow-candidates.d.ts +3 -3
- package/dist/core/incremental/shadow-candidates.js +3 -3
- package/dist/core/incremental/subgraph-extract.d.ts +2 -2
- package/dist/core/incremental/subgraph-extract.js +2 -2
- package/dist/core/ingestion/cobol/jcl-processor.js +9 -8
- package/dist/core/ingestion/cobol-processor.js +27 -26
- package/dist/core/ingestion/community-processor.d.ts +51 -1
- package/dist/core/ingestion/community-processor.js +316 -63
- package/dist/core/ingestion/emit-references.js +3 -2
- package/dist/core/ingestion/languages/cpp/captures.js +157 -74
- package/dist/core/ingestion/markdown-processor.js +3 -2
- package/dist/core/ingestion/parsing-processor.d.ts +3 -1
- package/dist/core/ingestion/parsing-processor.js +4 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +42 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +83 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.js +131 -0
- package/dist/core/ingestion/route-extractors/python-const-resolver.d.ts +75 -0
- package/dist/core/ingestion/route-extractors/python-const-resolver.js +299 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -1
- package/dist/core/ingestion/tree-sitter-queries.js +12 -1
- package/dist/core/ingestion/utils/line-base.d.ts +20 -0
- package/dist/core/ingestion/utils/line-base.js +20 -0
- package/dist/core/ingestion/utils/symbol-labels.d.ts +21 -0
- package/dist/core/ingestion/utils/symbol-labels.js +45 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +34 -0
- package/dist/core/ingestion/workers/parse-worker.js +40 -5
- package/dist/core/ingestion/workers/result-merge.js +4 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +14 -0
- package/dist/core/ingestion/workers/worker-pool.js +85 -5
- package/dist/core/lbug/csv-generator.js +8 -2
- package/dist/core/lbug/cypher-escape.d.ts +20 -0
- package/dist/core/lbug/cypher-escape.js +20 -0
- package/dist/core/lbug/extension-load-error.d.ts +67 -0
- package/dist/core/lbug/extension-load-error.js +320 -0
- package/dist/core/lbug/extension-loader.d.ts +17 -2
- package/dist/core/lbug/extension-loader.js +38 -13
- package/dist/core/lbug/lbug-adapter.d.ts +147 -1
- package/dist/core/lbug/lbug-adapter.js +390 -70
- package/dist/core/lbug/lbug-config.d.ts +28 -0
- package/dist/core/lbug/lbug-config.js +114 -4
- package/dist/core/lbug/native-check.d.ts +22 -0
- package/dist/core/lbug/native-check.js +66 -0
- package/dist/core/lbug/pool-adapter.js +10 -1
- package/dist/core/lbug/sidecar-recovery.d.ts +172 -0
- package/dist/core/lbug/sidecar-recovery.js +418 -16
- package/dist/core/platform/capabilities.js +27 -1
- package/dist/core/run-analyze.js +470 -108
- package/dist/core/search/fts-indexes.d.ts +7 -0
- package/dist/core/search/fts-indexes.js +37 -0
- package/dist/core/tree-sitter/safe-parse.d.ts +8 -3
- package/dist/core/tree-sitter/safe-parse.js +21 -7
- package/dist/core/wiki/graph-queries.js +6 -5
- package/dist/mcp/core/embedder.js +16 -2
- package/dist/mcp/local/line-display.d.ts +22 -0
- package/dist/mcp/local/line-display.js +3 -0
- package/dist/mcp/local/local-backend.d.ts +14 -0
- package/dist/mcp/local/local-backend.js +63 -19
- package/dist/mcp/local/pdg-impact.d.ts +5 -3
- package/dist/mcp/local/pdg-impact.js +5 -2
- package/dist/mcp/resources.js +1 -0
- package/dist/mcp/tools.js +1 -1
- package/dist/server/analyze-launch.d.ts +6 -0
- package/dist/server/analyze-launch.js +82 -6
- package/dist/server/api.d.ts +30 -0
- package/dist/server/api.js +63 -21
- package/dist/storage/parse-cache.js +1 -1
- package/dist/storage/repo-manager.d.ts +65 -1
- package/dist/storage/repo-manager.js +18 -1
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +50 -3
- package/hooks/claude/gitnexus-hook.cjs +59 -9
- package/package.json +5 -3
- package/scripts/cross-platform-tests.ts +43 -0
- package/scripts/ensure-fts.ts +32 -0
- package/scripts/install-duckdb-extension.mjs +85 -24
- package/scripts/run-cross-platform.ts +46 -6
- package/scripts/shard-arg.ts +30 -0
- package/web/assets/ProcessFlowModal-Dna7GkwO.js +22 -0
- package/web/assets/{agent-Dli_x7bU.js → agent-DNYDy-KA.js} +49 -49
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-BVWFvYz2.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-BU5ZRITg.js +36 -0
- package/web/assets/{blockDiagram-7IZFK4PR-BkWhpzWB.js → blockDiagram-7IZFK4PR-Dut1BpTV.js} +2 -2
- package/web/assets/{c4Diagram-Y2BXMSZH-DtBvpzWD.js → c4Diagram-Y2BXMSZH-DOXVs7-C.js} +2 -2
- package/web/assets/chunk-2T2R6R2M-pkw2oXHH.js +4 -0
- package/web/assets/chunk-2UTLFMKG-CXlhF3Pt.js +1 -0
- package/web/assets/chunk-3SSMPTDK-rPsRM1x0.js +321 -0
- package/web/assets/chunk-4R4BOZG6-Be_F0JoX.js +159 -0
- package/web/assets/{chunk-6764PJDD-DpIS7hxD.js → chunk-6764PJDD-C7xxk063.js} +1 -1
- package/web/assets/{chunk-67TQ5CYL-4sNPJU1q.js → chunk-67TQ5CYL-zxhDWgyF.js} +3 -3
- package/web/assets/chunk-7FYTHRHK-CsmYIswB.js +32 -0
- package/web/assets/chunk-7J6CGLKN-AmkN8jJN.js +10 -0
- package/web/assets/chunk-7W6UQGC5-pyKGssV3.js +1 -0
- package/web/assets/chunk-C62D2QBJ-3gdL8EKc.js +1 -0
- package/web/assets/chunk-CEXFNPSA-CjwtMDkc.js +1 -0
- package/web/assets/{chunk-INKRHTLW-Nu4ri9P-.js → chunk-INKRHTLW-D9BM9HWZ.js} +1 -1
- package/web/assets/chunk-J5EP6P6S-L19oz55R.js +1 -0
- package/web/assets/{chunk-KGFNY3KK-JGMJvKCK.js → chunk-KGFNY3KK-tD2F6wxK.js} +1 -1
- package/web/assets/chunk-KGYTTC2M-zm6n242I.js +1 -0
- package/web/assets/{chunk-KRXBNO2N-BW5o0KUN.js → chunk-KRXBNO2N-C-UNuKKf.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-CfLLCywY.js → chunk-LCXTWHL2-Ba9JK-6F.js} +2 -2
- package/web/assets/{chunk-LII3EMHJ-D-jm-dLa.js → chunk-LII3EMHJ-EGx-eBIu.js} +1 -1
- package/web/assets/chunk-LRIF4GLE-C3_PqUBq.js +1 -0
- package/web/assets/{chunk-QA3QBVWF-BgRW3SXd.js → chunk-QA3QBVWF-D4cSJBf6.js} +1 -1
- package/web/assets/chunk-RERM46MO-B5dAdWpP.js +1 -0
- package/web/assets/{chunk-RG4AUYOV-CqWzWsV3.js → chunk-RG4AUYOV-OqBBMwuQ.js} +4 -4
- package/web/assets/chunk-RKZBBQEN-MyIQbGgD.js +1 -0
- package/web/assets/chunk-RLI5ZMPA-CkXZ0y0U.js +1 -0
- package/web/assets/{chunk-T2UQINTJ-DSBqkzH7.js → chunk-T2UQINTJ-BJusEiGe.js} +1 -1
- package/web/assets/chunk-UP6H54XL-BG-n7qDp.js +1 -0
- package/web/assets/chunk-UXSXWOXI-CW1_r5cS.js +1 -0
- package/web/assets/{chunk-UY5QBCOK-DyF0vyGd.js → chunk-UY5QBCOK-BCpUlARQ.js} +1 -1
- package/web/assets/chunk-VU6ZFW4Y-BeXVk45_.js +2 -0
- package/web/assets/{chunk-W44A43WB-JqMLIpR0.js → chunk-W44A43WB-BN8EQc_u.js} +1 -1
- package/web/assets/{chunk-ZXARS5L4-CxN8oiwI.js → chunk-ZXARS5L4-BI_qR2Nm.js} +1 -1
- package/web/assets/classDiagram-KGZ6W3CR-D9zSIg0x.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-D9zSIg0x.js +1 -0
- package/web/assets/cose-bilkent-UX7MHV2Q-BmnZ7Mvj.js +1 -0
- package/web/assets/dagre-ND4H6XIP-CpcV5kbl.js +4 -0
- package/web/assets/diagram-3NCE3AQN-6SMxBRpj.js +43 -0
- package/web/assets/diagram-GF46GFSD-BZEdNcRZ.js +24 -0
- package/web/assets/{diagram-HNR7UZ2L-DFCfd5LI.js → diagram-HNR7UZ2L-DxKW2a2Y.js} +2 -2
- package/web/assets/diagram-QXG6HAR7-HfTHcXX_.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-CyijUS8r.js +10 -0
- package/web/assets/{erDiagram-L5TCEMPS-8X1y6R4Y.js → erDiagram-L5TCEMPS-D0fvpWEX.js} +3 -3
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-CgFBM7e-.js +1 -0
- package/web/assets/flowDiagram-H6V6AXG4-Bvr9bbhk.js +162 -0
- package/web/assets/{ganttDiagram-JCBTUEKG-D3iL2Aet.js → ganttDiagram-JCBTUEKG-TzODrLzv.js} +2 -2
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DCJv7SII.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-ONQSwJIY.js +106 -0
- package/web/assets/index-B4eB4dNZ.js +575 -0
- package/web/assets/index-CX_fADmQ.css +2 -0
- package/web/assets/info-J43DQDTF-KCYPFFUO-BfNy-9Nd.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-DIPVUIQ6.js +2 -0
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-DfYpxnE5.js → ishikawaDiagram-BNXS4ZKH-BLjivjXL.js} +3 -3
- package/web/assets/{journeyDiagram-M6C3CM3L-CvArszLo.js → journeyDiagram-M6C3CM3L-Cetgs3NH.js} +3 -3
- package/web/assets/{kanban-definition-75IXJCU3-CpfVLLf9.js → kanban-definition-75IXJCU3-DMlCaIpf.js} +5 -5
- package/web/assets/{katex-K3KEBU37-CTc5BslQ.js → katex-K3KEBU37-qRQBy-EZ.js} +2 -2
- package/web/assets/{mindmap-definition-2TDM6QVE-DypvbOMQ.js → mindmap-definition-2TDM6QVE-B4GbXQBc.js} +3 -3
- package/web/assets/packet-YPE3B663-LP52Z2RK-D4qkeG9k.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-B_yMKyQa.js +1 -0
- package/web/assets/{pieDiagram-CU6KROY3-s27EFWgP.js → pieDiagram-CU6KROY3-D3YC_xyg.js} +2 -2
- package/web/assets/{quadrantDiagram-VICAPDV7-yXSZ2lLz.js → quadrantDiagram-VICAPDV7-B1TQnlm0.js} +2 -2
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DeD6yN_0.js +1 -0
- package/web/assets/{requirementDiagram-JXO7QTGE-CWhqInuf.js → requirementDiagram-JXO7QTGE-f8wczLQf.js} +3 -3
- package/web/assets/rolldown-runtime-QTnfLwEv.js +1 -0
- package/web/assets/{sankeyDiagram-URQDO5SZ-1qEjlFIB.js → sankeyDiagram-URQDO5SZ-BTxzG5j0.js} +2 -2
- package/web/assets/{sequenceDiagram-VS2MUI6T-RyTlZ5cR.js → sequenceDiagram-VS2MUI6T-DuamM-IR.js} +5 -5
- package/web/assets/src-BNCXICdA.js +1 -0
- package/web/assets/stateDiagram-7D4R322I-Ch2pEUcw.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-7ANuoZLL.js +1 -0
- package/web/assets/{timeline-definition-O6YCAMPW-DrrqLYAf.js → timeline-definition-O6YCAMPW-07BR8R8G.js} +3 -3
- package/web/assets/treeView-BLDUP644-QA4HXRO3-CDuSYnd4.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-imazucyJ.js +1 -0
- package/web/assets/{vennDiagram-MWXL3ELB-B0RkWAim.js → vennDiagram-MWXL3ELB-BQX2ossk.js} +4 -4
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-DqrT9tB8.js +1 -0
- package/web/assets/{wardleyDiagram-CUQ6CDDI-boUxiQ5F.js → wardleyDiagram-CUQ6CDDI-CGIJBBiK.js} +3 -3
- package/web/assets/{xychartDiagram-N2JHSOCM-BOLm0eNm.js → xychartDiagram-N2JHSOCM-B3HNMuWp.js} +4 -4
- package/web/index.html +17 -10
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +0 -1
- package/web/assets/architectureDiagram-UL44E2DR-dEkqUZN9.js +0 -36
- package/web/assets/chunk-3SSMPTDK-B4_etUhr.js +0 -321
- package/web/assets/chunk-7W6UQGC5-KyEG0HQg.js +0 -1
- package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +0 -161
- package/web/assets/classDiagram-KGZ6W3CR-CMne4tG9.js +0 -1
- package/web/assets/classDiagram-v2-72OJOZXJ-CMne4tG9.js +0 -1
- package/web/assets/cose-bilkent-UX7MHV2Q-D71wNYRJ.js +0 -1
- package/web/assets/dagre-ND4H6XIP-Co5rRx9X.js +0 -4
- package/web/assets/diagram-3NCE3AQN-DBp4O00j.js +0 -43
- package/web/assets/diagram-GF46GFSD-6N_8yS0i.js +0 -24
- package/web/assets/diagram-QXG6HAR7-Di093rFg.js +0 -24
- package/web/assets/diagram-WEQXMOUZ-DZWi4SUN.js +0 -10
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +0 -1
- package/web/assets/flowDiagram-H6V6AXG4-CMpY8Ufn.js +0 -162
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +0 -1
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +0 -106
- package/web/assets/index-KctnI3Vq.js +0 -635
- package/web/assets/index-_lgn7hs5.css +0 -2
- package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +0 -1
- package/web/assets/infoDiagram-3YFTVSEB-BaLMZkUg.js +0 -2
- package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +0 -1
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +0 -1
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +0 -1
- package/web/assets/stateDiagram-7D4R322I-DTjVfX4A.js +0 -1
- package/web/assets/stateDiagram-v2-36443NZ5-xY9_k9_Q.js +0 -1
- package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +0 -1
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +0 -1
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +0 -1
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warning attached to search responses when BM25/FTS is degraded. Prefers the
|
|
3
|
+
* live extension-load failure (with LadybugDB's real reason, #2374) over the
|
|
4
|
+
* generic indexes-missing message, so "indexes exist but the extension broke"
|
|
5
|
+
* is not misreported as missing indexes.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ftsDegradedWarning: () => string;
|
|
1
8
|
export declare const SUPPORTED_FTS_STEMMERS: ReadonlySet<string>;
|
|
2
9
|
export interface CreateSearchFTSIndexesOptions {
|
|
3
10
|
onIndexStart?: (table: string, indexName: string) => void;
|
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
import { createFTSIndex, dropFTSIndex, DEFAULT_FTS_STEMMER } from '../lbug/lbug-adapter.js';
|
|
2
|
+
import { getExtensionCapabilities } from '../lbug/extension-loader.js';
|
|
3
|
+
import { classifyExtensionLoadError } from '../lbug/extension-load-error.js';
|
|
2
4
|
import { FTS_INDEXES } from './fts-schema.js';
|
|
5
|
+
/**
|
|
6
|
+
* Strip filesystem paths from a LadybugDB error before it reaches the HTTP
|
|
7
|
+
* `/api/search` and MCP query surfaces (#2374, PR #2375): the raw LOAD error
|
|
8
|
+
* embeds the absolute extension path (username, home dir) which must not leak to
|
|
9
|
+
* a network client. The error class words ("Failed to load library", "invalid
|
|
10
|
+
* ELF header", "has not been installed") have no leading path separator and
|
|
11
|
+
* survive. CLI/doctor/log surfaces keep the full path (they read the reason
|
|
12
|
+
* directly, not through this function).
|
|
13
|
+
*/
|
|
14
|
+
const redactPaths = (reason) => reason.replace(/(?:[A-Za-z]:\\|\/)[^\s'"]+/g, '<path>');
|
|
15
|
+
/**
|
|
16
|
+
* Warning attached to search responses when BM25/FTS is degraded. Prefers the
|
|
17
|
+
* live extension-load failure (with LadybugDB's real reason, #2374) over the
|
|
18
|
+
* generic indexes-missing message, so "indexes exist but the extension broke"
|
|
19
|
+
* is not misreported as missing indexes.
|
|
20
|
+
*/
|
|
21
|
+
export const ftsDegradedWarning = () => {
|
|
22
|
+
const fts = getExtensionCapabilities().find((c) => c.name === 'fts');
|
|
23
|
+
if (fts && !fts.loaded) {
|
|
24
|
+
const reason = fts.reason ? redactPaths(fts.reason).replace(/\.$/, '') : undefined;
|
|
25
|
+
// A missing *runtime dependency* (Windows error 126, etc.) is not healed by
|
|
26
|
+
// reinstalling (#2374) — surface the classified remedy instead of the generic
|
|
27
|
+
// reinstall tail. Read the diagnosis cached at mark-unavailable time so this
|
|
28
|
+
// per-request path (HTTP /api/search + MCP query) does NO file I/O (#2383 F3);
|
|
29
|
+
// fall back to the pure, no-I/O string classifier if it is somehow absent.
|
|
30
|
+
const { kind, remedy } = fts.diagnosis ?? classifyExtensionLoadError(fts.reason);
|
|
31
|
+
const tail = kind === 'missing_dependency'
|
|
32
|
+
? ` ${remedy}`
|
|
33
|
+
: '. Run `gitnexus doctor` for details, then `gitnexus analyze --repair-fts` with network access to reinstall.';
|
|
34
|
+
return ('FTS extension failed to load — keyword search degraded' +
|
|
35
|
+
(reason ? ` (${reason})` : '') +
|
|
36
|
+
tail);
|
|
37
|
+
}
|
|
38
|
+
return 'FTS indexes missing — keyword search degraded. Run: gitnexus analyze --repair-fts (or gitnexus analyze --force) to rebuild indexes.';
|
|
39
|
+
};
|
|
3
40
|
// Stemmers shipped by the LadybugDB FTS extension. Mirrors the lowercase token
|
|
4
41
|
// set in the extension bundled with @ladybugdb/core 0.18.x (see package.json).
|
|
5
42
|
// Keep in sync on a LadybugDB minor bump — a value here that the installed
|
|
@@ -42,7 +42,7 @@ export declare function getParseDiagnostics(tree: Parser.Tree): {
|
|
|
42
42
|
/**
|
|
43
43
|
* Parse `sourceText` safely on every platform.
|
|
44
44
|
*
|
|
45
|
-
* This is the single "parse safely" entry point and its contract covers
|
|
45
|
+
* This is the single "parse safely" entry point and its contract covers four
|
|
46
46
|
* concerns:
|
|
47
47
|
*
|
|
48
48
|
* 1. **Windows crash workaround.** Inputs longer than 32 767 chars are fed
|
|
@@ -62,7 +62,12 @@ export declare function getParseDiagnostics(tree: Parser.Tree): {
|
|
|
62
62
|
* the tree is **returned anyway** — error recovery is a downgrade, never a
|
|
63
63
|
* drop. Callers wanting the boolean use {@link parseHadErrors}.
|
|
64
64
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
65
|
+
* 4. **Embedded NUL recovery.** U+0000 is replaced with one ASCII space in
|
|
66
|
+
* the parser-only input. The one-for-one substitution keeps tree indices
|
|
67
|
+
* aligned with the original source while preventing language lexers from
|
|
68
|
+
* swallowing declarations during error recovery.
|
|
69
|
+
*
|
|
70
|
+
* @param label optional context (e.g. file path) attached to timeout errors,
|
|
71
|
+
* recovery warnings, and degraded-parse logs. Non-breaking trailing param.
|
|
67
72
|
*/
|
|
68
73
|
export declare function parseSourceSafe(parser: Parser, sourceText: string, oldTree?: Parser.Tree, options?: Parser.Options, label?: string): Parser.Tree;
|
|
@@ -155,7 +155,7 @@ export function getParseDiagnostics(tree) {
|
|
|
155
155
|
/**
|
|
156
156
|
* Parse `sourceText` safely on every platform.
|
|
157
157
|
*
|
|
158
|
-
* This is the single "parse safely" entry point and its contract covers
|
|
158
|
+
* This is the single "parse safely" entry point and its contract covers four
|
|
159
159
|
* concerns:
|
|
160
160
|
*
|
|
161
161
|
* 1. **Windows crash workaround.** Inputs longer than 32 767 chars are fed
|
|
@@ -175,22 +175,36 @@ export function getParseDiagnostics(tree) {
|
|
|
175
175
|
* the tree is **returned anyway** — error recovery is a downgrade, never a
|
|
176
176
|
* drop. Callers wanting the boolean use {@link parseHadErrors}.
|
|
177
177
|
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
178
|
+
* 4. **Embedded NUL recovery.** U+0000 is replaced with one ASCII space in
|
|
179
|
+
* the parser-only input. The one-for-one substitution keeps tree indices
|
|
180
|
+
* aligned with the original source while preventing language lexers from
|
|
181
|
+
* swallowing declarations during error recovery.
|
|
182
|
+
*
|
|
183
|
+
* @param label optional context (e.g. file path) attached to timeout errors,
|
|
184
|
+
* recovery warnings, and degraded-parse logs. Non-breaking trailing param.
|
|
180
185
|
*/
|
|
181
186
|
export function parseSourceSafe(parser, sourceText, oldTree, options, label) {
|
|
187
|
+
let parserInput = sourceText;
|
|
188
|
+
if (sourceText.includes('\0')) {
|
|
189
|
+
let nullByteCount = 0;
|
|
190
|
+
parserInput = sourceText.replaceAll('\0', () => {
|
|
191
|
+
nullByteCount += 1;
|
|
192
|
+
return ' ';
|
|
193
|
+
});
|
|
194
|
+
logger.warn({ ...(label ? { file: label } : {}), nullByteCount }, 'replaced embedded NUL bytes before tree-sitter parsing');
|
|
195
|
+
}
|
|
182
196
|
const budgetMs = resolveParseTimeoutMs();
|
|
183
197
|
const armed = armParseBudget(parser, budgetMs);
|
|
184
198
|
let tree;
|
|
185
199
|
try {
|
|
186
|
-
if (
|
|
187
|
-
tree = parser.parse(
|
|
200
|
+
if (parserInput.length <= DIRECT_PARSE_LIMIT_CHARS) {
|
|
201
|
+
tree = parser.parse(parserInput, oldTree, options);
|
|
188
202
|
}
|
|
189
203
|
else {
|
|
190
204
|
const input = (index) => {
|
|
191
|
-
if (index >=
|
|
205
|
+
if (index >= parserInput.length)
|
|
192
206
|
return null;
|
|
193
|
-
return
|
|
207
|
+
return parserInput.slice(index, index + SAFE_PARSE_CHUNK_CHARS);
|
|
194
208
|
};
|
|
195
209
|
tree = parser.parse(input, oldTree, options);
|
|
196
210
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Uses the MCP-style pooled lbug-adapter for connection management.
|
|
6
6
|
*/
|
|
7
7
|
import { initLbug, executeQuery, closeLbug, touchRepo, pinRepo } from '../lbug/pool-adapter.js';
|
|
8
|
+
import { escapeCypherString } from '../lbug/cypher-escape.js';
|
|
8
9
|
const REPO_ID = '__wiki__';
|
|
9
10
|
/**
|
|
10
11
|
* Touch the wiki DB connection to prevent idle timeout during long LLM calls.
|
|
@@ -98,7 +99,7 @@ export async function getInterFileCallEdges() {
|
|
|
98
99
|
export async function getIntraModuleCallEdges(filePaths) {
|
|
99
100
|
if (filePaths.length === 0)
|
|
100
101
|
return [];
|
|
101
|
-
const fileList = filePaths.map((f) => `'${f
|
|
102
|
+
const fileList = filePaths.map((f) => `'${escapeCypherString(f)}'`).join(', ');
|
|
102
103
|
const rows = await executeQuery(REPO_ID, `
|
|
103
104
|
MATCH (a)-[:CodeRelation {type: 'CALLS'}]->(b)
|
|
104
105
|
WHERE a.filePath IN [${fileList}] AND b.filePath IN [${fileList}]
|
|
@@ -118,7 +119,7 @@ export async function getIntraModuleCallEdges(filePaths) {
|
|
|
118
119
|
export async function getInterModuleCallEdges(filePaths) {
|
|
119
120
|
if (filePaths.length === 0)
|
|
120
121
|
return { outgoing: [], incoming: [] };
|
|
121
|
-
const fileList = filePaths.map((f) => `'${f
|
|
122
|
+
const fileList = filePaths.map((f) => `'${escapeCypherString(f)}'`).join(', ');
|
|
122
123
|
const outRows = await executeQuery(REPO_ID, `
|
|
123
124
|
MATCH (a)-[:CodeRelation {type: 'CALLS'}]->(b)
|
|
124
125
|
WHERE a.filePath IN [${fileList}] AND NOT b.filePath IN [${fileList}]
|
|
@@ -155,7 +156,7 @@ export async function getInterModuleCallEdges(filePaths) {
|
|
|
155
156
|
export async function getProcessesForFiles(filePaths, limit = 5) {
|
|
156
157
|
if (filePaths.length === 0)
|
|
157
158
|
return [];
|
|
158
|
-
const fileList = filePaths.map((f) => `'${f
|
|
159
|
+
const fileList = filePaths.map((f) => `'${escapeCypherString(f)}'`).join(', ');
|
|
159
160
|
// Find processes that have steps in the given files
|
|
160
161
|
const procRows = await executeQuery(REPO_ID, `
|
|
161
162
|
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
|
|
@@ -173,7 +174,7 @@ export async function getProcessesForFiles(filePaths, limit = 5) {
|
|
|
173
174
|
const stepCount = row.stepCount || row[3] || 0;
|
|
174
175
|
// Get the full step trace for this process
|
|
175
176
|
const stepRows = await executeQuery(REPO_ID, `
|
|
176
|
-
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${procId
|
|
177
|
+
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${escapeCypherString(procId)}'})
|
|
177
178
|
RETURN s.name AS name, s.filePath AS filePath, labels(s)[0] AS type, r.step AS step
|
|
178
179
|
ORDER BY r.step
|
|
179
180
|
`);
|
|
@@ -210,7 +211,7 @@ export async function getAllProcesses(limit = 20) {
|
|
|
210
211
|
const type = row.type || row[2] || 'unknown';
|
|
211
212
|
const stepCount = row.stepCount || row[3] || 0;
|
|
212
213
|
const stepRows = await executeQuery(REPO_ID, `
|
|
213
|
-
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${procId
|
|
214
|
+
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${escapeCypherString(procId)}'})
|
|
214
215
|
RETURN s.name AS name, s.filePath AS filePath, labels(s)[0] AS type, r.step AS step
|
|
215
216
|
ORDER BY r.step
|
|
216
217
|
`);
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
import { isHttpMode, getHttpDimensions, httpEmbedQuery, } from '../../core/embeddings/http-client.js';
|
|
8
8
|
import { resolveEmbeddingConfig } from '../../core/embeddings/config.js';
|
|
9
9
|
import { applyHfEnvOverrides, isHfDownloadFailure, withHfDownloadRetry, } from '../../core/embeddings/hf-env.js';
|
|
10
|
-
import { getLocalEmbeddingRuntimeBlocker } from '../../core/embeddings/runtime-support.js';
|
|
10
|
+
import { getLocalEmbeddingRuntimeBlocker, getMissingLocalEmbeddingStackMessage, } from '../../core/embeddings/runtime-support.js';
|
|
11
11
|
import { ensureOnnxRuntimeCommonResolvable } from '../../core/embeddings/onnxruntime-common-resolver.js';
|
|
12
|
+
import { ensureEmbeddingStackResolvable } from '../../core/embeddings/runtime-install.js';
|
|
12
13
|
import { ensureOnnxRuntimeNodeMatchesSystem } from '../../core/embeddings/onnxruntime-node-resolver.js';
|
|
13
14
|
import { silenceStdout, restoreStdout, realStderrWrite } from '../../core/lbug/pool-adapter.js';
|
|
14
15
|
import { logger } from '../../core/logger.js';
|
|
@@ -45,6 +46,11 @@ export const initEmbedder = async () => {
|
|
|
45
46
|
try {
|
|
46
47
|
// Lazy-load transformers.js only after the runtime guard has passed, so
|
|
47
48
|
// unsupported platforms never reach the native ONNX import (#1515).
|
|
49
|
+
// Registered FIRST so it sits last in the hook chain (registerHooks runs
|
|
50
|
+
// the most recent hook first): when the optional stack was pruned at
|
|
51
|
+
// install time (#2370), its bare specifiers fall back to the on-demand
|
|
52
|
+
// runtime prefix.
|
|
53
|
+
ensureEmbeddingStackResolvable();
|
|
48
54
|
// Under pnpm-strict / `pnpm dlx`, transformers' phantom `onnxruntime-common`
|
|
49
55
|
// import is unresolvable; register the fallback resolver first (#307).
|
|
50
56
|
ensureOnnxRuntimeCommonResolvable();
|
|
@@ -55,7 +61,15 @@ export const initEmbedder = async () => {
|
|
|
55
61
|
// Windows/DirectML, and macOS. Mirrors the core embedder's call site so
|
|
56
62
|
// MCP query-time embedding gets the same CUDA-13 fix.
|
|
57
63
|
ensureOnnxRuntimeNodeMatchesSystem();
|
|
58
|
-
|
|
64
|
+
// The stack is an optionalDependency: npm prunes it when onnxruntime-node's
|
|
65
|
+
// postinstall can't reach api.nuget.org (#2370). Rethrow with actionable
|
|
66
|
+
// reinstall guidance instead of a raw ERR_MODULE_NOT_FOUND.
|
|
67
|
+
const { pipeline, env } = await import('@huggingface/transformers').catch((err) => {
|
|
68
|
+
const missing = getMissingLocalEmbeddingStackMessage(err);
|
|
69
|
+
if (missing)
|
|
70
|
+
throw new Error(missing);
|
|
71
|
+
throw err;
|
|
72
|
+
});
|
|
59
73
|
env.allowLocalModels = false;
|
|
60
74
|
// Bridge user-controlled env vars to transformers.js: HF_HOME →
|
|
61
75
|
// env.cacheDir, HF_ENDPOINT → env.remoteHost (#1205). Centralised in
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a 0-based GraphNode `startLine`/`endLine` to the 1-based line number
|
|
3
|
+
* shown to humans and LLMs in MCP tool output.
|
|
4
|
+
*
|
|
5
|
+
* Storage is 0-based (tree-sitter `startPosition.row`; see
|
|
6
|
+
* `ingestion/utils/line-base.ts`), which matches editors/`sed`/`less -N` only
|
|
7
|
+
* after `+ 1`. The `context`, `query`, and `impact` tools present line numbers a
|
|
8
|
+
* user cross-references against source, so they convert here at the response
|
|
9
|
+
* boundary (#2377).
|
|
10
|
+
*
|
|
11
|
+
* Apply ONLY to a symbol node's 0-based `startLine`/`endLine`. Do NOT apply to:
|
|
12
|
+
* - BasicBlock / CFG `functionStartLine` and PDG statement lines — already
|
|
13
|
+
* 1-based (they use `startPosition.row + 1`);
|
|
14
|
+
* - the internal `sym.startLine + 1` join params that target the 1-based
|
|
15
|
+
* BasicBlock id space;
|
|
16
|
+
* - raw `cypher` results, which pass LadybugDB columns through verbatim and
|
|
17
|
+
* stay 0-based (documented).
|
|
18
|
+
*
|
|
19
|
+
* `undefined`/`null` pass through so optional line fields stay absent.
|
|
20
|
+
*/
|
|
21
|
+
export declare function toDisplayLine(zeroBasedLine: number): number;
|
|
22
|
+
export declare function toDisplayLine(zeroBasedLine: number | null | undefined): number | undefined;
|
|
@@ -162,10 +162,24 @@ export declare class LocalBackend {
|
|
|
162
162
|
* stderr noisy per DoD §2.8.
|
|
163
163
|
*/
|
|
164
164
|
private warnedVectorUnsupported;
|
|
165
|
+
/**
|
|
166
|
+
* One-shot warning when a pruned or Node-unloadable optional embedding stack
|
|
167
|
+
* (#2370/#2372) forces semantic search to fall back to BM25 — so the
|
|
168
|
+
* degradation is visible once instead of silent.
|
|
169
|
+
*/
|
|
170
|
+
private warnedMissingEmbeddingStack;
|
|
165
171
|
/**
|
|
166
172
|
* Cross-repo group tools (CLI). Shares logic with MCP `group_*` handlers.
|
|
167
173
|
*/
|
|
168
174
|
getGroupService(): GroupService;
|
|
175
|
+
/**
|
|
176
|
+
* Adapt local `trace` to the group port. The assembled group/cross-repo trace
|
|
177
|
+
* presents 1-based endpoints (via resolveSymbolForGroup), so convert the hop
|
|
178
|
+
* lines here too — otherwise one response mixes 1-based endpoints with 0-based
|
|
179
|
+
* hops (#2380). Single-repo `trace` dispatches directly (not through this
|
|
180
|
+
* port) and stays 0-based (documented full-parity follow-up).
|
|
181
|
+
*/
|
|
182
|
+
private traceForGroup;
|
|
169
183
|
/**
|
|
170
184
|
* Adapt the shared symbol resolver to the GroupToolPort contract. Used by the
|
|
171
185
|
* cross-repo trace path to locate which member repo an endpoint lives in and
|
|
@@ -10,6 +10,7 @@ import path from 'path';
|
|
|
10
10
|
import { createHash } from 'crypto';
|
|
11
11
|
import { initLbug, executeQuery, executeParameterized, closeLbug, isLbugReady, } from '../../core/lbug/pool-adapter.js';
|
|
12
12
|
import { isValidQueryParams } from '../../core/lbug/query-params.js';
|
|
13
|
+
import { toDisplayLine } from './line-display.js';
|
|
13
14
|
import { isWalCorruptionError, WAL_RECOVERY_SUGGESTION } from '../../core/lbug/lbug-config.js';
|
|
14
15
|
// Embedding imports are lazy (dynamic import) to avoid loading onnxruntime-node
|
|
15
16
|
// at MCP server startup — crashes on unsupported Node ABI versions (#89)
|
|
@@ -26,9 +27,11 @@ import { rankExactEmbeddingRows, } from '../../core/embeddings/exact-search.js';
|
|
|
26
27
|
import { EMBEDDING_TABLE_NAME, EMBEDDING_INDEX_NAME } from '../../core/lbug/schema.js';
|
|
27
28
|
import { getExactScanLimit, isVectorExtensionSupportedByPlatform, } from '../../core/platform/capabilities.js';
|
|
28
29
|
import { PhaseTimer } from '../../core/search/phase-timer.js';
|
|
30
|
+
import { ftsDegradedWarning } from '../../core/search/fts-indexes.js';
|
|
29
31
|
import { cjkSegmentationModeMismatch, containsSegmentableCjkRun, getSearchFTSCjkSegmentation, isSupportedCjkSegmentationMode, MAX_CJK_SEGMENTATION_QUERY_LENGTH, } from '../../core/search/cjk-segmentation.js';
|
|
30
32
|
import { checkStalenessAsync, checkCwdMatch } from '../../core/git-staleness.js';
|
|
31
33
|
import { logger } from '../../core/logger.js';
|
|
34
|
+
import { isLocalEmbeddingRuntimeBlockerMessage, isMissingLocalEmbeddingStackMessage, } from '../../core/embeddings/runtime-support.js';
|
|
32
35
|
import { LIST_REPOS_DEFAULT_LIMIT, LIST_REPOS_MAX_LIMIT, EXPLAIN_DEFAULT_LIMIT, EXPLAIN_MAX_LIMIT, PDG_QUERY_DEFAULT_LIMIT, PDG_QUERY_MAX_LIMIT, } from '../tools.js';
|
|
33
36
|
import { findImportCycles } from '../../core/graph/import-cycles.js';
|
|
34
37
|
import { decodeTaintPath } from '../../core/ingestion/taint/path-codec.js';
|
|
@@ -434,6 +437,12 @@ export class LocalBackend {
|
|
|
434
437
|
* stderr noisy per DoD §2.8.
|
|
435
438
|
*/
|
|
436
439
|
warnedVectorUnsupported = false;
|
|
440
|
+
/**
|
|
441
|
+
* One-shot warning when a pruned or Node-unloadable optional embedding stack
|
|
442
|
+
* (#2370/#2372) forces semantic search to fall back to BM25 — so the
|
|
443
|
+
* degradation is visible once instead of silent.
|
|
444
|
+
*/
|
|
445
|
+
warnedMissingEmbeddingStack = false;
|
|
437
446
|
/**
|
|
438
447
|
* Cross-repo group tools (CLI). Shares logic with MCP `group_*` handlers.
|
|
439
448
|
*/
|
|
@@ -445,7 +454,7 @@ export class LocalBackend {
|
|
|
445
454
|
query: (r, p) => this.query(r, p),
|
|
446
455
|
impactByUid: (id, uid, d, o) => this.impactByUid(id, uid, d, o),
|
|
447
456
|
context: (r, p) => this.context(r, p),
|
|
448
|
-
trace: (r, p) => this.
|
|
457
|
+
trace: (r, p) => this.traceForGroup(r, p),
|
|
449
458
|
resolveSymbol: (r, q) => this.resolveSymbolForGroup(r, q),
|
|
450
459
|
pdgFlows: (r, anchor, opts) => this.pdgFlowsForGroup(r, anchor, opts),
|
|
451
460
|
};
|
|
@@ -453,6 +462,23 @@ export class LocalBackend {
|
|
|
453
462
|
}
|
|
454
463
|
return this.groupToolSvc;
|
|
455
464
|
}
|
|
465
|
+
/**
|
|
466
|
+
* Adapt local `trace` to the group port. The assembled group/cross-repo trace
|
|
467
|
+
* presents 1-based endpoints (via resolveSymbolForGroup), so convert the hop
|
|
468
|
+
* lines here too — otherwise one response mixes 1-based endpoints with 0-based
|
|
469
|
+
* hops (#2380). Single-repo `trace` dispatches directly (not through this
|
|
470
|
+
* port) and stays 0-based (documented full-parity follow-up).
|
|
471
|
+
*/
|
|
472
|
+
async traceForGroup(repo, params) {
|
|
473
|
+
const result = await this.trace(repo, params);
|
|
474
|
+
const hops = result.hops;
|
|
475
|
+
if (Array.isArray(hops)) {
|
|
476
|
+
for (const hop of hops) {
|
|
477
|
+
hop.startLine = toDisplayLine(hop.startLine);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return result;
|
|
481
|
+
}
|
|
456
482
|
/**
|
|
457
483
|
* Adapt the shared symbol resolver to the GroupToolPort contract. Used by the
|
|
458
484
|
* cross-repo trace path to locate which member repo an endpoint lives in and
|
|
@@ -470,8 +496,8 @@ export class LocalBackend {
|
|
|
470
496
|
name: s.name,
|
|
471
497
|
type: s.type,
|
|
472
498
|
filePath: s.filePath,
|
|
473
|
-
startLine: s.startLine,
|
|
474
|
-
endLine: s.endLine,
|
|
499
|
+
startLine: toDisplayLine(s.startLine),
|
|
500
|
+
endLine: toDisplayLine(s.endLine),
|
|
475
501
|
},
|
|
476
502
|
};
|
|
477
503
|
}
|
|
@@ -483,7 +509,7 @@ export class LocalBackend {
|
|
|
483
509
|
name: c.name,
|
|
484
510
|
type: c.type,
|
|
485
511
|
filePath: c.filePath,
|
|
486
|
-
startLine: c.startLine,
|
|
512
|
+
startLine: toDisplayLine(c.startLine),
|
|
487
513
|
})),
|
|
488
514
|
};
|
|
489
515
|
}
|
|
@@ -1564,8 +1590,8 @@ export class LocalBackend {
|
|
|
1564
1590
|
name: sym.name,
|
|
1565
1591
|
type: sym.type,
|
|
1566
1592
|
filePath: sym.filePath,
|
|
1567
|
-
startLine: sym.startLine,
|
|
1568
|
-
endLine: sym.endLine,
|
|
1593
|
+
startLine: toDisplayLine(sym.startLine),
|
|
1594
|
+
endLine: toDisplayLine(sym.endLine),
|
|
1569
1595
|
...(module ? { module } : {}),
|
|
1570
1596
|
...(includeContent && content ? { content } : {}),
|
|
1571
1597
|
};
|
|
@@ -1652,7 +1678,7 @@ export class LocalBackend {
|
|
|
1652
1678
|
// path, leaving the success-path response shape byte-identical.
|
|
1653
1679
|
const warnings = [];
|
|
1654
1680
|
if (!ftsUsed) {
|
|
1655
|
-
warnings.push(
|
|
1681
|
+
warnings.push(ftsDegradedWarning());
|
|
1656
1682
|
}
|
|
1657
1683
|
// #2331: a CJK query against a server process resolving
|
|
1658
1684
|
// GITNEXUS_FTS_CJK_SEGMENTATION to 'none' silently misses sub-phrase
|
|
@@ -1791,8 +1817,11 @@ export class LocalBackend {
|
|
|
1791
1817
|
name: sym.name || sym[1],
|
|
1792
1818
|
type: sym.type || sym[2],
|
|
1793
1819
|
filePath: sym.filePath || sym[3],
|
|
1794
|
-
|
|
1795
|
-
|
|
1820
|
+
// Raw 0-based here — `bm25Search` is only called from `query()`,
|
|
1821
|
+
// whose aggregation loop applies `toDisplayLine` once (see below).
|
|
1822
|
+
// Converting here too would double-shift BM25-matched lines (#2380).
|
|
1823
|
+
startLine: sym.startLine ?? sym[4],
|
|
1824
|
+
endLine: sym.endLine ?? sym[5],
|
|
1796
1825
|
bm25Score: bm25Result.score,
|
|
1797
1826
|
});
|
|
1798
1827
|
}
|
|
@@ -1927,8 +1956,20 @@ export class LocalBackend {
|
|
|
1927
1956
|
}
|
|
1928
1957
|
return results;
|
|
1929
1958
|
}
|
|
1930
|
-
catch {
|
|
1931
|
-
//
|
|
1959
|
+
catch (err) {
|
|
1960
|
+
// Embeddings disabled is the common, silent case. But a pruned or
|
|
1961
|
+
// Node-unloadable optional stack (#2370/#2372) also lands here — surface it
|
|
1962
|
+
// once so semantic search doesn't silently degrade to BM25 with no hint
|
|
1963
|
+
// (the exact silent-degradation mode #2370 exists to fix). Emitted once per
|
|
1964
|
+
// LocalBackend instance to keep stderr quiet on hot paths (like the VECTOR
|
|
1965
|
+
// fallback above). All other errors stay silent, as before.
|
|
1966
|
+
const message = err instanceof Error ? err.message : '';
|
|
1967
|
+
if (!this.warnedMissingEmbeddingStack &&
|
|
1968
|
+
(isMissingLocalEmbeddingStackMessage(message) ||
|
|
1969
|
+
isLocalEmbeddingRuntimeBlockerMessage(message))) {
|
|
1970
|
+
this.warnedMissingEmbeddingStack = true;
|
|
1971
|
+
logger.warn(`GitNexus [query:vector]: ${message}`);
|
|
1972
|
+
}
|
|
1932
1973
|
return [];
|
|
1933
1974
|
}
|
|
1934
1975
|
}
|
|
@@ -2376,7 +2417,7 @@ export class LocalBackend {
|
|
|
2376
2417
|
name: c.name,
|
|
2377
2418
|
kind: c.type,
|
|
2378
2419
|
filePath: c.filePath,
|
|
2379
|
-
line: c.startLine,
|
|
2420
|
+
line: toDisplayLine(c.startLine),
|
|
2380
2421
|
score: Number(c.score.toFixed(2)),
|
|
2381
2422
|
})),
|
|
2382
2423
|
};
|
|
@@ -2583,8 +2624,8 @@ export class LocalBackend {
|
|
|
2583
2624
|
name: sym.name || sym[1],
|
|
2584
2625
|
kind: symKind,
|
|
2585
2626
|
filePath: sym.filePath || sym[3],
|
|
2586
|
-
startLine: sym.startLine
|
|
2587
|
-
endLine: sym.endLine
|
|
2627
|
+
startLine: toDisplayLine(sym.startLine ?? sym[4]),
|
|
2628
|
+
endLine: toDisplayLine(sym.endLine ?? sym[5]),
|
|
2588
2629
|
...(include_content && (sym.content || sym[6]) ? { content: sym.content || sym[6] } : {}),
|
|
2589
2630
|
...(methodMetadata ? { methodMetadata } : {}),
|
|
2590
2631
|
},
|
|
@@ -2660,7 +2701,7 @@ export class LocalBackend {
|
|
|
2660
2701
|
name: c.name,
|
|
2661
2702
|
kind: c.type,
|
|
2662
2703
|
filePath: c.filePath,
|
|
2663
|
-
line: c.startLine,
|
|
2704
|
+
line: toDisplayLine(c.startLine),
|
|
2664
2705
|
score: Number(c.score.toFixed(2)),
|
|
2665
2706
|
})),
|
|
2666
2707
|
},
|
|
@@ -2678,11 +2719,14 @@ export class LocalBackend {
|
|
|
2678
2719
|
return {
|
|
2679
2720
|
anchorClause: 'a.id STARTS WITH $idPrefix AND a.startLine >= $symStart AND a.startLine <= $symEnd',
|
|
2680
2721
|
queryParams: { idPrefix, symStart: sym.startLine + 1, symEnd: sym.endLine + 1 },
|
|
2722
|
+
// Display anchor is 1-based, matching the ambiguous-candidate branch and
|
|
2723
|
+
// the context/query/impact tools (#2380). This is display-only — the
|
|
2724
|
+
// BasicBlock join above uses the raw `sym.startLine + 1` in `symStart`.
|
|
2681
2725
|
anchor: {
|
|
2682
2726
|
file: sym.filePath,
|
|
2683
2727
|
symbol: sym.name,
|
|
2684
|
-
startLine: sym.startLine,
|
|
2685
|
-
endLine: sym.endLine,
|
|
2728
|
+
startLine: toDisplayLine(sym.startLine),
|
|
2729
|
+
endLine: toDisplayLine(sym.endLine),
|
|
2686
2730
|
},
|
|
2687
2731
|
};
|
|
2688
2732
|
}
|
|
@@ -4016,7 +4060,7 @@ export class LocalBackend {
|
|
|
4016
4060
|
name: c.name,
|
|
4017
4061
|
kind: c.type,
|
|
4018
4062
|
filePath: c.filePath,
|
|
4019
|
-
line: c.startLine,
|
|
4063
|
+
line: toDisplayLine(c.startLine),
|
|
4020
4064
|
score: Number(c.score.toFixed(2)),
|
|
4021
4065
|
})),
|
|
4022
4066
|
};
|
|
@@ -4069,7 +4113,7 @@ export class LocalBackend {
|
|
|
4069
4113
|
name: c.name,
|
|
4070
4114
|
kind: c.type,
|
|
4071
4115
|
filePath: c.filePath,
|
|
4072
|
-
line: c.startLine,
|
|
4116
|
+
line: toDisplayLine(c.startLine),
|
|
4073
4117
|
score: Number(c.score.toFixed(2)),
|
|
4074
4118
|
impactedCount: summary?.impactedCount ?? 0,
|
|
4075
4119
|
risk: summary?.risk ?? 'UNKNOWN',
|
|
@@ -34,8 +34,10 @@ export declare function splitCalleeIds(raw: unknown): string[];
|
|
|
34
34
|
* Contract version of the mode:'pdg' impact result shape. A stable discriminator
|
|
35
35
|
* for external MCP/agent consumers — distinct from the DB INCREMENTAL_SCHEMA_VERSION.
|
|
36
36
|
* Bump on any breaking change to the PDG result fields.
|
|
37
|
+
* v2: `startLine` in the result is now 1-based display (#2380), matching the
|
|
38
|
+
* context/query/impact tools (was 0-based).
|
|
37
39
|
*/
|
|
38
|
-
export declare const PDG_RESULT_VERSION:
|
|
40
|
+
export declare const PDG_RESULT_VERSION: 2;
|
|
39
41
|
/** A reachable dependence block resolved to its source statement. */
|
|
40
42
|
export interface PdgStatement {
|
|
41
43
|
/** 1-based source line where the statement's block starts. */
|
|
@@ -105,7 +107,7 @@ export interface PdgInterproceduralImpact {
|
|
|
105
107
|
export interface PdgImpactBaseResult extends PdgImpactParityFields {
|
|
106
108
|
mode: 'pdg';
|
|
107
109
|
/** Contract version of the mode:'pdg' impact result shape; bump on any breaking change to the PDG result fields. */
|
|
108
|
-
pdgResultVersion:
|
|
110
|
+
pdgResultVersion: 2;
|
|
109
111
|
target: PdgImpactTarget;
|
|
110
112
|
direction: 'upstream' | 'downstream';
|
|
111
113
|
impactedCount: number;
|
|
@@ -172,7 +174,7 @@ export interface PdgImpactDegradedResult extends PdgImpactBaseResult {
|
|
|
172
174
|
export interface PdgImpactErrorResult {
|
|
173
175
|
mode?: 'pdg';
|
|
174
176
|
/** Contract version of the mode:'pdg' impact result shape; bump on any breaking change to the PDG result fields. */
|
|
175
|
-
pdgResultVersion:
|
|
177
|
+
pdgResultVersion: 2;
|
|
176
178
|
error: string;
|
|
177
179
|
target: PdgImpactTarget;
|
|
178
180
|
direction: 'upstream' | 'downstream';
|
|
@@ -9,6 +9,7 @@ import path from 'path';
|
|
|
9
9
|
import { loadMeta } from '../../storage/repo-manager.js';
|
|
10
10
|
import { IMPACT_MAX_DEPTH, PDG_QUERY_DEFAULT_LIMIT, PDG_QUERY_MAX_LIMIT } from '../tools.js';
|
|
11
11
|
import { CALLEES_TRUNCATED_SENTINEL, CALLEE_ID_SEP } from '../../core/ingestion/cfg/emit.js';
|
|
12
|
+
import { toDisplayLine } from './line-display.js';
|
|
12
13
|
import { decodeCallSummary } from '../../core/ingestion/taint/call-summary-codec.js';
|
|
13
14
|
import { decodeReachingDefReason } from '../../core/ingestion/cfg/reaching-def-reason-codec.js';
|
|
14
15
|
import { getProviderForFile } from '../../core/ingestion/languages/index.js';
|
|
@@ -84,8 +85,10 @@ export function splitCalleeIds(raw) {
|
|
|
84
85
|
* Contract version of the mode:'pdg' impact result shape. A stable discriminator
|
|
85
86
|
* for external MCP/agent consumers — distinct from the DB INCREMENTAL_SCHEMA_VERSION.
|
|
86
87
|
* Bump on any breaking change to the PDG result fields.
|
|
88
|
+
* v2: `startLine` in the result is now 1-based display (#2380), matching the
|
|
89
|
+
* context/query/impact tools (was 0-based).
|
|
87
90
|
*/
|
|
88
|
-
export const PDG_RESULT_VERSION =
|
|
91
|
+
export const PDG_RESULT_VERSION = 2;
|
|
89
92
|
/**
|
|
90
93
|
* FU-B-2 intra-block def→use line walk. Given a block's self REACHING_DEF
|
|
91
94
|
* def→use line PAIRS (every `defLine → useLine` step decoded from the edge
|
|
@@ -519,7 +522,7 @@ function assemblePdgImpactResult(input) {
|
|
|
519
522
|
name: s.name,
|
|
520
523
|
type: s.type,
|
|
521
524
|
filePath: s.filePath,
|
|
522
|
-
...(s.startLine !== undefined ? { startLine: s.startLine } : {}),
|
|
525
|
+
...(s.startLine !== undefined ? { startLine: toDisplayLine(s.startLine) } : {}),
|
|
523
526
|
...(s.ambiguous ? { ambiguous: true } : {}),
|
|
524
527
|
...(s.id === null ? { unresolved: true } : {}),
|
|
525
528
|
pdgEvidence: (s.id === null ? 'degraded' : 'owner-projection'),
|
package/dist/mcp/resources.js
CHANGED
|
@@ -365,6 +365,7 @@ additional_node_types: "Multi-language: Struct, Enum, Macro, Typedef, Union, Nam
|
|
|
365
365
|
|
|
366
366
|
node_properties:
|
|
367
367
|
common: "name (STRING), filePath (STRING), startLine (INT32), endLine (INT32)"
|
|
368
|
+
line_numbers: "startLine/endLine on symbol nodes are 0-BASED (tree-sitter rows) in storage AND in raw Cypher results. The context, query, impact, group/cross-repo trace, and explain/pdg_query (symbol anchor) tools present them 1-BASED (editor / sed / less -N aligned), so a symbol spans editor lines (startLine+1)..(endLine+1) — e.g. sed '<startLine+1>,<endLine+1>!d' <file>. Single-repo trace symbol lines stay 0-BASED for now (full-parity follow-up). content holds the exact symbol span. (BasicBlock / PDG statement lines are separately 1-based.) (#2377, #2380)"
|
|
368
369
|
Method: "parameterCount (INT32), returnType (STRING), isVariadic (BOOL), visibility (STRING), isStatic (BOOL), isAbstract (BOOL), isFinal (BOOL), isVirtual (BOOL), isOverride (BOOL), isAsync (BOOL), isPartial (BOOL), requiredParameterCount (INT32), parameterTypes (STRING[]), annotations (STRING[])"
|
|
369
370
|
Function: "parameterCount (INT32), returnType (STRING), isVariadic (BOOL), visibility (STRING), isStatic (BOOL), isAbstract (BOOL), isFinal (BOOL), isAsync (BOOL), parameterTypes (STRING[]), annotations (STRING[])"
|
|
370
371
|
Property: "declaredType (STRING) — the field's type annotation (e.g., 'Address', 'City'). Used for field-access chain resolution."
|
package/dist/mcp/tools.js
CHANGED
|
@@ -379,7 +379,7 @@ MODE (opt-in): "callgraph" (default) walks symbol→symbol edges (CALLS/IMPORTS/
|
|
|
379
379
|
|
|
380
380
|
STATEMENT-ANCHORED PDG SLICE: with mode:'pdg', pass "line" (1-based source line within the target symbol) to seed the dependence slice on the statement at that line and return what depends on it in affectedStatements (line + text). Inter-procedural symbols are still reported through interproceduralByDepth/pdgInterprocedural and the compatibility byDepth bucket. Without "line", pdg returns whole-symbol inter-procedural reach plus local whole-symbol PDG diagnostics.
|
|
381
381
|
|
|
382
|
-
PDG OUTPUT CONTRACT: every mode:'pdg' result (success, empty, degraded, or error) carries pdgResultVersion:
|
|
382
|
+
PDG OUTPUT CONTRACT: every mode:'pdg' result (success, empty, degraded, or error) carries pdgResultVersion:2 — a stable discriminator for external consumers that bumps on any breaking change to the PDG result shape (distinct from the DB schema version). Successful PDG results include mode:'pdg', a full target envelope (id/name/type/filePath), affectedStatements, affectedStatementCount, interproceduralByDepth/pdgInterprocedural for cross-function reach, compatibility byDepth/byDepthCounts, risk:'UNKNOWN', and a note describing the unified contract. Degraded PDG results (no-layer, sub-layer-missing, unknown) keep mode:'pdg', pdgResultVersion:2, target metadata when the target resolves, risk:'UNKNOWN', note/remediation, and empty byDepth parity fields — never a false-safe zero. If depth and limit both bound the slice, truncatedByReasons reports both causes while truncatedBy remains scalar.
|
|
383
383
|
|
|
384
384
|
WHEN TO USE: Before making code changes — especially refactoring, renaming, or modifying shared code. Shows what would break.
|
|
385
385
|
AFTER THIS: Review d=1 items (WILL BREAK). Use context() on high-risk symbols.
|
|
@@ -17,6 +17,12 @@ export interface LaunchDeps {
|
|
|
17
17
|
};
|
|
18
18
|
acquireRepoLock: (key: string) => string | null;
|
|
19
19
|
releaseRepoLock: (key: string) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Drops the server's cached LadybugDB handle (closeLbug). The worker
|
|
22
|
+
* process rewrites the repo's DB files on disk, so a connection opened
|
|
23
|
+
* before the rewrite keeps reading the pre-rewrite state until evicted.
|
|
24
|
+
*/
|
|
25
|
+
closeDbHandle: () => Promise<void>;
|
|
20
26
|
}
|
|
21
27
|
export interface LaunchOptions {
|
|
22
28
|
force?: boolean;
|