gitnexus 1.6.5-rc.2 → 1.6.5-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 +1 -1
- package/dist/_shared/scope-resolution/method-dispatch-index.d.ts +26 -0
- package/dist/_shared/scope-resolution/method-dispatch-index.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/method-dispatch-index.js +22 -3
- package/dist/_shared/scope-resolution/method-dispatch-index.js.map +1 -1
- package/dist/_shared/scope-resolution/registries/lookup-core.js +18 -1
- package/dist/_shared/scope-resolution/registries/lookup-core.js.map +1 -1
- package/dist/cli/ai-context.d.ts +1 -0
- package/dist/cli/ai-context.js +30 -12
- package/dist/cli/analyze.d.ts +18 -0
- package/dist/cli/analyze.js +33 -4
- package/dist/cli/augment.d.ts +1 -1
- package/dist/cli/augment.js +1 -1
- package/dist/cli/index.js +6 -1
- package/dist/cli/setup.js +6 -0
- package/dist/core/augmentation/engine.d.ts +2 -2
- package/dist/core/augmentation/engine.js +26 -6
- package/dist/core/embeddings/ast-utils.js +2 -1
- package/dist/core/embeddings/http-client.js +22 -6
- package/dist/core/group/extractors/grpc-extractor.js +2 -1
- package/dist/core/group/extractors/http-patterns/python.js +175 -0
- package/dist/core/group/extractors/http-route-extractor.js +2 -1
- package/dist/core/group/extractors/include-extractor.js +2 -1
- package/dist/core/group/extractors/thrift-extractor.js +2 -1
- package/dist/core/group/extractors/tree-sitter-scanner.js +2 -1
- package/dist/core/incremental/shadow-candidates.d.ts +44 -0
- package/dist/core/incremental/shadow-candidates.js +74 -0
- package/dist/core/incremental/subgraph-extract.d.ts +64 -0
- package/dist/core/incremental/subgraph-extract.js +111 -0
- package/dist/core/ingestion/call-processor.js +166 -47
- package/dist/core/ingestion/community-processor.js +18 -0
- package/dist/core/ingestion/heritage-processor.js +3 -2
- package/dist/core/ingestion/import-processor.js +2 -1
- package/dist/core/ingestion/import-resolvers/standard.d.ts +5 -0
- package/dist/core/ingestion/import-resolvers/standard.js +27 -1
- package/dist/core/ingestion/import-resolvers/utils.js +4 -0
- package/dist/core/ingestion/languages/c/arity-metadata.d.ts +14 -0
- package/dist/core/ingestion/languages/c/arity-metadata.js +94 -0
- package/dist/core/ingestion/languages/c/arity.d.ts +6 -0
- package/dist/core/ingestion/languages/c/arity.js +18 -0
- package/dist/core/ingestion/languages/c/captures.d.ts +2 -0
- package/dist/core/ingestion/languages/c/captures.js +105 -0
- package/dist/core/ingestion/languages/c/header-scan.d.ts +7 -0
- package/dist/core/ingestion/languages/c/header-scan.js +55 -0
- package/dist/core/ingestion/languages/c/import-decomposer.d.ts +8 -0
- package/dist/core/ingestion/languages/c/import-decomposer.js +50 -0
- package/dist/core/ingestion/languages/c/import-target.d.ts +14 -0
- package/dist/core/ingestion/languages/c/import-target.js +57 -0
- package/dist/core/ingestion/languages/c/index.d.ts +11 -0
- package/dist/core/ingestion/languages/c/index.js +11 -0
- package/dist/core/ingestion/languages/c/interpret.d.ts +14 -0
- package/dist/core/ingestion/languages/c/interpret.js +48 -0
- package/dist/core/ingestion/languages/c/merge-bindings.d.ts +7 -0
- package/dist/core/ingestion/languages/c/merge-bindings.js +23 -0
- package/dist/core/ingestion/languages/c/query.d.ts +3 -0
- package/dist/core/ingestion/languages/c/query.js +161 -0
- package/dist/core/ingestion/languages/c/scope-resolver.d.ts +13 -0
- package/dist/core/ingestion/languages/c/scope-resolver.js +60 -0
- package/dist/core/ingestion/languages/c/simple-hooks.d.ts +14 -0
- package/dist/core/ingestion/languages/c/simple-hooks.js +19 -0
- package/dist/core/ingestion/languages/c/static-linkage.d.ts +13 -0
- package/dist/core/ingestion/languages/c/static-linkage.js +57 -0
- package/dist/core/ingestion/languages/c-cpp.js +10 -0
- package/dist/core/ingestion/languages/csharp/captures.js +2 -1
- package/dist/core/ingestion/languages/csharp/namespace-siblings.js +3 -2
- package/dist/core/ingestion/languages/go/captures.js +2 -1
- package/dist/core/ingestion/languages/go/range-binding.js +2 -1
- package/dist/core/ingestion/languages/java/arity-metadata.d.ts +18 -0
- package/dist/core/ingestion/languages/java/arity-metadata.js +40 -0
- package/dist/core/ingestion/languages/java/arity.d.ts +10 -0
- package/dist/core/ingestion/languages/java/arity.js +24 -0
- package/dist/core/ingestion/languages/java/cache-stats.d.ts +15 -0
- package/dist/core/ingestion/languages/java/cache-stats.js +26 -0
- package/dist/core/ingestion/languages/java/captures.d.ts +17 -0
- package/dist/core/ingestion/languages/java/captures.js +187 -0
- package/dist/core/ingestion/languages/java/import-decomposer.d.ts +18 -0
- package/dist/core/ingestion/languages/java/import-decomposer.js +85 -0
- package/dist/core/ingestion/languages/java/import-target.d.ts +17 -0
- package/dist/core/ingestion/languages/java/import-target.js +100 -0
- package/dist/core/ingestion/languages/java/index.d.ts +29 -0
- package/dist/core/ingestion/languages/java/index.js +29 -0
- package/dist/core/ingestion/languages/java/interpret.d.ts +13 -0
- package/dist/core/ingestion/languages/java/interpret.js +131 -0
- package/dist/core/ingestion/languages/java/merge-bindings.d.ts +12 -0
- package/dist/core/ingestion/languages/java/merge-bindings.js +40 -0
- package/dist/core/ingestion/languages/java/query.d.ts +30 -0
- package/dist/core/ingestion/languages/java/query.js +192 -0
- package/dist/core/ingestion/languages/java/receiver-binding.d.ts +11 -0
- package/dist/core/ingestion/languages/java/receiver-binding.js +95 -0
- package/dist/core/ingestion/languages/java/scope-resolver.d.ts +50 -0
- package/dist/core/ingestion/languages/java/scope-resolver.js +74 -0
- package/dist/core/ingestion/languages/java/simple-hooks.d.ts +13 -0
- package/dist/core/ingestion/languages/java/simple-hooks.js +34 -0
- package/dist/core/ingestion/languages/java.js +11 -0
- package/dist/core/ingestion/languages/php/arity-metadata.d.ts +28 -0
- package/dist/core/ingestion/languages/php/arity-metadata.js +63 -0
- package/dist/core/ingestion/languages/php/arity.d.ts +25 -0
- package/dist/core/ingestion/languages/php/arity.js +40 -0
- package/dist/core/ingestion/languages/php/cache-stats.d.ts +15 -0
- package/dist/core/ingestion/languages/php/cache-stats.js +26 -0
- package/dist/core/ingestion/languages/php/captures.d.ts +34 -0
- package/dist/core/ingestion/languages/php/captures.js +739 -0
- package/dist/core/ingestion/languages/php/import-decomposer.d.ts +28 -0
- package/dist/core/ingestion/languages/php/import-decomposer.js +265 -0
- package/dist/core/ingestion/languages/php/import-target.d.ts +47 -0
- package/dist/core/ingestion/languages/php/import-target.js +100 -0
- package/dist/core/ingestion/languages/php/index.d.ts +68 -0
- package/dist/core/ingestion/languages/php/index.js +72 -0
- package/dist/core/ingestion/languages/php/interpret.d.ts +36 -0
- package/dist/core/ingestion/languages/php/interpret.js +241 -0
- package/dist/core/ingestion/languages/php/merge-bindings.d.ts +19 -0
- package/dist/core/ingestion/languages/php/merge-bindings.js +47 -0
- package/dist/core/ingestion/languages/php/namespace-siblings.d.ts +51 -0
- package/dist/core/ingestion/languages/php/namespace-siblings.js +288 -0
- package/dist/core/ingestion/languages/php/query.d.ts +32 -0
- package/dist/core/ingestion/languages/php/query.js +326 -0
- package/dist/core/ingestion/languages/php/receiver-binding.d.ts +36 -0
- package/dist/core/ingestion/languages/php/receiver-binding.js +128 -0
- package/dist/core/ingestion/languages/php/scope-resolver.d.ts +23 -0
- package/dist/core/ingestion/languages/php/scope-resolver.js +358 -0
- package/dist/core/ingestion/languages/php/simple-hooks.d.ts +42 -0
- package/dist/core/ingestion/languages/php/simple-hooks.js +111 -0
- package/dist/core/ingestion/languages/php.d.ts +0 -7
- package/dist/core/ingestion/languages/php.js +15 -0
- package/dist/core/ingestion/languages/python/captures.js +2 -1
- package/dist/core/ingestion/languages/typescript/captures.js +2 -1
- package/dist/core/ingestion/parsing-processor.d.ts +22 -2
- package/dist/core/ingestion/parsing-processor.js +85 -50
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +5 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +119 -11
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +14 -0
- package/dist/core/ingestion/pipeline.d.ts +13 -0
- package/dist/core/ingestion/registry-primary-flag.js +2 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +65 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.d.ts +1 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +12 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +5 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +25 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +79 -7
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +7 -3
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +24 -4
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +21 -2
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +13 -1
- package/dist/core/ingestion/scope-resolution/pipeline/registry.js +6 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +17 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +31 -7
- package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -1
- package/dist/core/ingestion/tree-sitter-queries.js +10 -0
- package/dist/core/ingestion/workers/parse-worker.js +2 -1
- package/dist/core/lbug/lbug-adapter.d.ts +26 -0
- package/dist/core/lbug/lbug-adapter.js +174 -40
- package/dist/core/lbug/pool-adapter.js +19 -2
- package/dist/core/run-analyze.d.ts +2 -0
- package/dist/core/run-analyze.js +323 -29
- package/dist/core/tree-sitter/safe-parse.d.ts +6 -0
- package/dist/core/tree-sitter/safe-parse.js +32 -0
- package/dist/server/git-clone.js +10 -13
- package/dist/storage/file-hash.d.ts +47 -0
- package/dist/storage/file-hash.js +86 -0
- package/dist/storage/git.d.ts +17 -6
- package/dist/storage/git.js +46 -12
- package/dist/storage/parse-cache.d.ts +67 -0
- package/dist/storage/parse-cache.js +182 -0
- package/dist/storage/repo-manager.d.ts +41 -1
- package/dist/storage/repo-manager.js +17 -2
- package/hooks/claude/gitnexus-hook.cjs +8 -1
- package/hooks/claude/hook-lock.cjs +119 -0
- package/package.json +1 -1
- package/web/assets/{agent-BpHQleHE.js → agent-BG6RCOzz.js} +1 -1
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-F-tujre-.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-2GL7nOvO.js +36 -0
- package/web/assets/blockDiagram-7IZFK4PR-5AjX0pPU.js +132 -0
- package/web/assets/{c4Diagram-DFAF54RM-DeJV1rCn.js → c4Diagram-Y2BXMSZH-hLOeq7xC.js} +2 -2
- package/web/assets/chunk-2T2R6R2M-B_pq_2nf.js +4 -0
- package/web/assets/chunk-2UTLFMKG-CpoohCFN.js +1 -0
- package/web/assets/{chunk-7RZVMHOQ-BdIU-RGO.js → chunk-3SSMPTDK-CfqpR3Nr.js} +1 -1
- package/web/assets/chunk-4R4BOZG6-D3gm7tYj.js +159 -0
- package/web/assets/chunk-6764PJDD-WcI965eO.js +1 -0
- package/web/assets/chunk-AQ6EADP3-BpMj3rQl.js +1 -0
- package/web/assets/{chunk-KSICW3F5-C2tZmXwv.js → chunk-AZZRMDJM-DSoCJlUA.js} +1 -1
- package/web/assets/chunk-C62D2QBJ-CvFF2PnB.js +1 -0
- package/web/assets/chunk-CEXFNPSA-DdNtJtrF.js +1 -0
- package/web/assets/chunk-J5EP6P6S-DtcVaAJI.js +1 -0
- package/web/assets/{chunk-AEOMTBSW-D7qjBMHW.js → chunk-JQRUD6KW-DElaNjc0.js} +1 -1
- package/web/assets/chunk-KGYTTC2M-D0K5or7e.js +1 -0
- package/web/assets/chunk-KRXBNO2N-DpR8iDt8.js +1 -0
- package/web/assets/chunk-LCXTWHL2-DdMObOEk.js +231 -0
- package/web/assets/chunk-LII3EMHJ-I78zXtzi.js +1 -0
- package/web/assets/chunk-RERM46MO-Betu1cSy.js +1 -0
- package/web/assets/chunk-RG4AUYOV-BUCJ2JP5.js +206 -0
- package/web/assets/chunk-RKZBBQEN-Cutpza0t.js +1 -0
- package/web/assets/chunk-RLI5ZMPA-BFUxCvX2.js +1 -0
- package/web/assets/chunk-T5OCTHI4-DKwlkuvB.js +1 -0
- package/web/assets/chunk-UP6H54XL-0YWa0NDg.js +1 -0
- package/web/assets/chunk-UXSXWOXI-CSz0OXpz.js +1 -0
- package/web/assets/chunk-W44A43WB-AOmgoT-X.js +1 -0
- package/web/assets/{chunk-RWUO3TPN-DTWzAhQ1.js → chunk-ZXARS5L4-DIzgxjMw.js} +1 -1
- package/web/assets/classDiagram-KGZ6W3CR-BT-rn7LF.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-uR3nDadY.js +1 -0
- package/web/assets/{cose-bilkent-PNC4W37J-DdZq7Qz_.js → cose-bilkent-UX7MHV2Q-DCSCD1TK.js} +1 -1
- package/web/assets/dagre-ND4H6XIP-CsciHSij.js +4 -0
- package/web/assets/diagram-3NCE3AQN-BKUT5Rpc.js +43 -0
- package/web/assets/diagram-GF46GFSD-Dxb4hZSo.js +24 -0
- package/web/assets/diagram-HNR7UZ2L-D3qus9Cn.js +3 -0
- package/web/assets/diagram-QXG6HAR7-r9BMLGGP.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-BGXqs7-m.js +10 -0
- package/web/assets/{erDiagram-GCSMX5X6-DfdN6iqF.js → erDiagram-L5TCEMPS-LgSWVrkZ.js} +2 -2
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-By7r3bla.js +1 -0
- package/web/assets/flowDiagram-H6V6AXG4-Bj_vV5ky.js +162 -0
- package/web/assets/ganttDiagram-JCBTUEKG-B1eVITSh.js +292 -0
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-ClEP6RdE.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-BP0R-_FD.js +106 -0
- package/web/assets/{index-3NUCUW2s.js → index-oL-ZNYwb.js} +80 -81
- package/web/assets/info-J43DQDTF-KCYPFFUO-bBJRjmP5.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-Dmj4OEO3.js +2 -0
- package/web/assets/{ishikawaDiagram-YMYX4NHK-BF8AtDaj.js → ishikawaDiagram-BNXS4ZKH-B3NgQ4lJ.js} +2 -2
- package/web/assets/{journeyDiagram-SO5T7YLQ-BW8oKa3N.js → journeyDiagram-M6C3CM3L-DALmL4_N.js} +3 -3
- package/web/assets/{kanban-definition-LJHFXRCJ-DzbOsR-2.js → kanban-definition-75IXJCU3-AvVbHpnN.js} +4 -4
- package/web/assets/{katex-GD7MH7QM-CJiOjBBJ.js → katex-K3KEBU37-CqF6_ZN-.js} +1 -1
- package/web/assets/{mindmap-definition-2EUWGEK5-BIXGQALq.js → mindmap-definition-2TDM6QVE-B5c9VOzs.js} +28 -28
- package/web/assets/packet-YPE3B663-LP52Z2RK-1ZCldnu3.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-EhjHC5EE.js +1 -0
- package/web/assets/pieDiagram-CU6KROY3-Po2HSSR4.js +30 -0
- package/web/assets/quadrantDiagram-VICAPDV7-C47UxSZD.js +7 -0
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-CvXjgxlW.js +1 -0
- package/web/assets/{requirementDiagram-M5DCFWZL-CzUUrhQD.js → requirementDiagram-JXO7QTGE-CpECN_Hq.js} +6 -6
- package/web/assets/sankeyDiagram-URQDO5SZ-B3b7cLrS.js +40 -0
- package/web/assets/sequenceDiagram-VS2MUI6T-CRJ95oVP.js +162 -0
- package/web/assets/stateDiagram-7D4R322I-C7U9b3ks.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-BQajbtov.js +1 -0
- package/web/assets/{timeline-definition-5SPVSISX-DkMiGj4Z.js → timeline-definition-O6YCAMPW-rtbk6BBo.js} +4 -4
- package/web/assets/treeView-BLDUP644-QA4HXRO3-R2o5gwfP.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-Cesmac_u.js +1 -0
- package/web/assets/{vennDiagram-IE5QUKF5-BCxMmf9q.js → vennDiagram-MWXL3ELB-W8Yoaayh.js} +3 -3
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-B9HYoRgA.js +1 -0
- package/web/assets/wardleyDiagram-CUQ6CDDI-DIZw5Abj.js +78 -0
- package/web/assets/{xychartDiagram-ZHJ5623Y-DZ7fP1_3.js → xychartDiagram-N2JHSOCM-DGRtrj4P.js} +3 -3
- package/web/index.html +2 -2
- package/web/assets/architecture-YZFGNWBL-S5CXDPWN-BUzkWgDl.js +0 -1
- package/web/assets/architectureDiagram-EMZXCZ2Q-CXbzok1G.js +0 -36
- package/web/assets/blockDiagram-IGV67L2C-DA1QJ4ZB.js +0 -132
- package/web/assets/chunk-3GS5O3IE-B8hpnia8.js +0 -231
- package/web/assets/chunk-3YCYZ6SJ-B-BVu21C.js +0 -1
- package/web/assets/chunk-6NTNNK5N-DW-jYSDr.js +0 -1
- package/web/assets/chunk-A34GCYZU-BbZl-IKy.js +0 -1
- package/web/assets/chunk-DJ7UZH7F-B5tMfF87.js +0 -1
- package/web/assets/chunk-DKKBVRCY-Djm-6K_e.js +0 -4
- package/web/assets/chunk-DU5LTGQ6-QPoynYcp.js +0 -1
- package/web/assets/chunk-FXACKDTF-jieSmbe2.js +0 -159
- package/web/assets/chunk-H3VCZNTA-8EMHZ3SV.js +0 -1
- package/web/assets/chunk-HN6EAY2L-CgE_agsD.js +0 -1
- package/web/assets/chunk-O5ABG6QK-DEZV1O19.js +0 -1
- package/web/assets/chunk-PK6DOVAG-BXv0JnsJ.js +0 -206
- package/web/assets/chunk-RNJOYNJ4-BiBkF9dN.js +0 -1
- package/web/assets/chunk-TBF5ZNIQ-BSl6s9lT.js +0 -1
- package/web/assets/chunk-TU3PZOEN-DE5Qhc0N.js +0 -1
- package/web/assets/chunk-TYMNRAUI-D1NDLIMG.js +0 -1
- package/web/assets/chunk-VELTKBKT-C9dVN39o.js +0 -1
- package/web/assets/chunk-W7ZLLLMY-Bu-cdLzs.js +0 -1
- package/web/assets/chunk-WSB5WSVC-Dor71SOz.js +0 -1
- package/web/assets/chunk-XGPFEOL4-CUonLRle.js +0 -1
- package/web/assets/classDiagram-PPOCWD7C-Cdd6UdVv.js +0 -1
- package/web/assets/classDiagram-v2-23LJLIIU-DNhxY2Ib.js +0 -1
- package/web/assets/dagre-E77IOHMT-Cfj_6e17.js +0 -4
- package/web/assets/diagram-H7BISOXX-BNvpsrBv.js +0 -43
- package/web/assets/diagram-JC5VWROH-Cn0rtDbJ.js +0 -24
- package/web/assets/diagram-LXUTUG65-CHfoVKNm.js +0 -10
- package/web/assets/diagram-WEHSV5V5-BLxHksnu.js +0 -24
- package/web/assets/flowDiagram-OTCZ4VVT-aAZw4c_M.js +0 -162
- package/web/assets/ganttDiagram-MUNLMDZQ-BEfC_7Or.js +0 -292
- package/web/assets/gitGraph-7Q5UKJZL-54BCDZD5-B6ZeRLP0.js +0 -1
- package/web/assets/gitGraphDiagram-3HKGZ4G3-CG0kC8Q5.js +0 -106
- package/web/assets/info-OMHHGYJF-BF2H5H6G-BIOsZy0W.js +0 -1
- package/web/assets/infoDiagram-MN7RKWGX-DUoMH-pq.js +0 -2
- package/web/assets/packet-4T2RLAQJ-EV4IVRXR-Bs7ysNMU.js +0 -1
- package/web/assets/pie-ZZUOXDRM-N23DN5KN-Csi8nnbH.js +0 -1
- package/web/assets/pieDiagram-3IATQBI2-QY-u7P6a.js +0 -30
- package/web/assets/quadrantDiagram-E256RVCF-Di4aNiU8.js +0 -7
- package/web/assets/radar-PYXPWWZC-P6TP7ZYP-DJlyXh2-.js +0 -1
- package/web/assets/sankeyDiagram-L3NBLAOT-D2fbMiIU.js +0 -10
- package/web/assets/sequenceDiagram-ZOUHS735-BNdkqguh.js +0 -157
- package/web/assets/stateDiagram-MLPALWAM-51_Q2w2L.js +0 -1
- package/web/assets/stateDiagram-v2-B5LQ5ZB2-8nHs2aNE.js +0 -1
- package/web/assets/treeView-SZITEDCU-5DXDK3XO-Cy6P0_CZ.js +0 -1
- package/web/assets/treemap-W4RFUUIX-WYLRDWKO-C_pp1R7A.js +0 -1
- package/web/assets/wardley-RL74JXVD-BCRCBASE-CMStJhpn.js +0 -1
- package/web/assets/wardleyDiagram-XU3VSMPF-ijlLF77s.js +0 -20
- /package/web/assets/{context-builder-CqQNhRj1.js → context-builder-CG-ydtp4.js} +0 -0
|
@@ -3,6 +3,7 @@ import { glob } from 'glob';
|
|
|
3
3
|
import Parser from 'tree-sitter';
|
|
4
4
|
import { createIgnoreFilter } from '../../../config/ignore-service.js';
|
|
5
5
|
import { readSafe } from './fs-utils.js';
|
|
6
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
6
7
|
import { logger } from '../../logger.js';
|
|
7
8
|
import { GRPC_SCAN_GLOB, getPluginForFile, hasProtoPlugin, } from './grpc-patterns/index.js';
|
|
8
9
|
/**
|
|
@@ -352,7 +353,7 @@ export class GrpcExtractor {
|
|
|
352
353
|
let detections = [];
|
|
353
354
|
try {
|
|
354
355
|
parser.setLanguage(plugin.language);
|
|
355
|
-
const tree = parser
|
|
356
|
+
const tree = parseSourceSafe(parser, content);
|
|
356
357
|
detections = plugin.scan(tree);
|
|
357
358
|
}
|
|
358
359
|
catch {
|
|
@@ -5,6 +5,7 @@ import { compilePatterns, runCompiledPatterns, unquoteLiteral, } from '../tree-s
|
|
|
5
5
|
* - FastAPI `@app.get("/path")` provider decorators
|
|
6
6
|
* - `requests.get/post/...("url")` consumer calls
|
|
7
7
|
* - Generic `requests.request("METHOD", "url")` consumer calls
|
|
8
|
+
* - `httpx.AsyncClient` instances calling `.get/.post/...("url")`
|
|
8
9
|
*/
|
|
9
10
|
const FASTAPI_VERBS = {
|
|
10
11
|
get: 'GET',
|
|
@@ -65,11 +66,142 @@ const REQUESTS_GENERIC_PATTERNS = compilePatterns({
|
|
|
65
66
|
},
|
|
66
67
|
],
|
|
67
68
|
});
|
|
69
|
+
// ─── Consumer: httpx.AsyncClient assignments ────────────────────────
|
|
70
|
+
// NOTE: This targeted detector only tracks explicit `httpx.AsyncClient(...)`
|
|
71
|
+
// construction. Direct imports (`from httpx import AsyncClient`) and module
|
|
72
|
+
// aliases (`import httpx as hx`) and annotated assignments (`client: httpx.AsyncClient = ...`)
|
|
73
|
+
// are intentionally left for a follow-up. Module-scope clients are only matched
|
|
74
|
+
// at module scope; calls inside functions require a function/class-local tracked
|
|
75
|
+
// client to avoid false positives from same-name local variables.
|
|
76
|
+
const HTTPX_ASYNC_CLIENT_ASSIGN_PATTERNS = compilePatterns({
|
|
77
|
+
name: 'python-httpx-async-client-assign',
|
|
78
|
+
language: Python,
|
|
79
|
+
patterns: [
|
|
80
|
+
{
|
|
81
|
+
meta: {},
|
|
82
|
+
query: `
|
|
83
|
+
(assignment
|
|
84
|
+
left: (_) @client
|
|
85
|
+
right: (call
|
|
86
|
+
function: (attribute
|
|
87
|
+
object: (identifier) @module (#eq? @module "httpx")
|
|
88
|
+
attribute: (identifier) @client_class (#eq? @client_class "AsyncClient"))))
|
|
89
|
+
`,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
});
|
|
93
|
+
// ─── Consumer: async with httpx.AsyncClient() as client ──────────────
|
|
94
|
+
const HTTPX_ASYNC_CLIENT_WITH_ALIAS_PATTERNS = compilePatterns({
|
|
95
|
+
name: 'python-httpx-async-client-with-alias',
|
|
96
|
+
language: Python,
|
|
97
|
+
patterns: [
|
|
98
|
+
{
|
|
99
|
+
meta: {},
|
|
100
|
+
query: `
|
|
101
|
+
(as_pattern
|
|
102
|
+
(call
|
|
103
|
+
function: (attribute
|
|
104
|
+
object: (identifier) @module (#eq? @module "httpx")
|
|
105
|
+
attribute: (identifier) @client_class (#eq? @client_class "AsyncClient")))
|
|
106
|
+
(as_pattern_target (identifier) @client))
|
|
107
|
+
`,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
});
|
|
111
|
+
function getScopeKey(node, preferClass = false) {
|
|
112
|
+
if (preferClass) {
|
|
113
|
+
let current = node;
|
|
114
|
+
while (current) {
|
|
115
|
+
if (current.type === 'class_definition') {
|
|
116
|
+
return `class:${current.startIndex}:${current.endIndex}`;
|
|
117
|
+
}
|
|
118
|
+
current = current.parent;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
let current = node;
|
|
122
|
+
while (current) {
|
|
123
|
+
if (current.type === 'function_definition') {
|
|
124
|
+
return `function:${current.startIndex}:${current.endIndex}`;
|
|
125
|
+
}
|
|
126
|
+
current = current.parent;
|
|
127
|
+
}
|
|
128
|
+
return 'module';
|
|
129
|
+
}
|
|
130
|
+
function trackedClientScopeKey(clientNode) {
|
|
131
|
+
return getScopeKey(clientNode.parent, clientNode.text.includes('.'));
|
|
132
|
+
}
|
|
133
|
+
function callScopeKeys(clientNode) {
|
|
134
|
+
const keys = new Set();
|
|
135
|
+
const preferClass = clientNode.text.includes('.');
|
|
136
|
+
const nearestScope = getScopeKey(clientNode.parent, preferClass);
|
|
137
|
+
keys.add(nearestScope);
|
|
138
|
+
return [...keys];
|
|
139
|
+
}
|
|
140
|
+
function collectHttpxAsyncClients(tree) {
|
|
141
|
+
const clients = new Map();
|
|
142
|
+
const addClient = (clientNode) => {
|
|
143
|
+
if (!clientNode)
|
|
144
|
+
return;
|
|
145
|
+
const scopeKey = trackedClientScopeKey(clientNode);
|
|
146
|
+
const clientText = clientNode.text;
|
|
147
|
+
const scopes = clients.get(clientText) ?? new Set();
|
|
148
|
+
scopes.add(scopeKey);
|
|
149
|
+
clients.set(clientText, scopes);
|
|
150
|
+
};
|
|
151
|
+
for (const match of runCompiledPatterns(HTTPX_ASYNC_CLIENT_ASSIGN_PATTERNS, tree)) {
|
|
152
|
+
addClient(match.captures.client);
|
|
153
|
+
}
|
|
154
|
+
for (const match of runCompiledPatterns(HTTPX_ASYNC_CLIENT_WITH_ALIAS_PATTERNS, tree)) {
|
|
155
|
+
addClient(match.captures.client);
|
|
156
|
+
}
|
|
157
|
+
return clients;
|
|
158
|
+
}
|
|
159
|
+
function hasTrackedHttpxAsyncClient(clients, clientNode) {
|
|
160
|
+
const scopes = clients.get(clientNode.text);
|
|
161
|
+
if (!scopes)
|
|
162
|
+
return false;
|
|
163
|
+
return callScopeKeys(clientNode).some((scopeKey) => scopes.has(scopeKey));
|
|
164
|
+
}
|
|
165
|
+
// ─── Consumer: httpx AsyncClient .get/.post/...("url") ──────────────
|
|
166
|
+
const HTTPX_ASYNC_CLIENT_VERB_PATTERNS = compilePatterns({
|
|
167
|
+
name: 'python-httpx-async-client-verb',
|
|
168
|
+
language: Python,
|
|
169
|
+
patterns: [
|
|
170
|
+
{
|
|
171
|
+
meta: {},
|
|
172
|
+
query: `
|
|
173
|
+
(call
|
|
174
|
+
function: (attribute
|
|
175
|
+
object: (_) @client
|
|
176
|
+
attribute: (identifier) @method (#match? @method "^(get|post|put|delete|patch)$"))
|
|
177
|
+
arguments: (argument_list . (string) @path))
|
|
178
|
+
`,
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
});
|
|
182
|
+
// ─── Consumer: httpx AsyncClient .request("METHOD", "url") ─────────
|
|
183
|
+
const HTTPX_ASYNC_CLIENT_GENERIC_PATTERNS = compilePatterns({
|
|
184
|
+
name: 'python-httpx-async-client-generic',
|
|
185
|
+
language: Python,
|
|
186
|
+
patterns: [
|
|
187
|
+
{
|
|
188
|
+
meta: {},
|
|
189
|
+
query: `
|
|
190
|
+
(call
|
|
191
|
+
function: (attribute
|
|
192
|
+
object: (_) @client
|
|
193
|
+
attribute: (identifier) @method (#eq? @method "request"))
|
|
194
|
+
arguments: (argument_list . (string) @http_method (string) @path))
|
|
195
|
+
`,
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
});
|
|
68
199
|
export const PYTHON_HTTP_PLUGIN = {
|
|
69
200
|
name: 'python-http',
|
|
70
201
|
language: Python,
|
|
71
202
|
scan(tree) {
|
|
72
203
|
const out = [];
|
|
204
|
+
const httpxAsyncClients = collectHttpxAsyncClients(tree);
|
|
73
205
|
// Providers: FastAPI
|
|
74
206
|
for (const match of runCompiledPatterns(FASTAPI_PATTERNS, tree)) {
|
|
75
207
|
const methodNode = match.captures.method;
|
|
@@ -128,6 +260,49 @@ export const PYTHON_HTTP_PLUGIN = {
|
|
|
128
260
|
confidence: 0.7,
|
|
129
261
|
});
|
|
130
262
|
}
|
|
263
|
+
// Consumers: httpx.AsyncClient.<verb>("url")
|
|
264
|
+
for (const match of runCompiledPatterns(HTTPX_ASYNC_CLIENT_VERB_PATTERNS, tree)) {
|
|
265
|
+
const clientNode = match.captures.client;
|
|
266
|
+
const methodNode = match.captures.method;
|
|
267
|
+
const pathNode = match.captures.path;
|
|
268
|
+
if (!clientNode || !methodNode || !pathNode)
|
|
269
|
+
continue;
|
|
270
|
+
if (!hasTrackedHttpxAsyncClient(httpxAsyncClients, clientNode))
|
|
271
|
+
continue;
|
|
272
|
+
const path = unquoteLiteral(pathNode.text);
|
|
273
|
+
if (path === null)
|
|
274
|
+
continue;
|
|
275
|
+
out.push({
|
|
276
|
+
role: 'consumer',
|
|
277
|
+
framework: 'python-httpx',
|
|
278
|
+
method: methodNode.text.toUpperCase(),
|
|
279
|
+
path,
|
|
280
|
+
name: null,
|
|
281
|
+
confidence: 0.7,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
// Consumers: httpx.AsyncClient.request("METHOD", "url")
|
|
285
|
+
for (const match of runCompiledPatterns(HTTPX_ASYNC_CLIENT_GENERIC_PATTERNS, tree)) {
|
|
286
|
+
const clientNode = match.captures.client;
|
|
287
|
+
const methodNode = match.captures.http_method;
|
|
288
|
+
const pathNode = match.captures.path;
|
|
289
|
+
if (!clientNode || !methodNode || !pathNode)
|
|
290
|
+
continue;
|
|
291
|
+
if (!hasTrackedHttpxAsyncClient(httpxAsyncClients, clientNode))
|
|
292
|
+
continue;
|
|
293
|
+
const methodRaw = unquoteLiteral(methodNode.text);
|
|
294
|
+
const path = unquoteLiteral(pathNode.text);
|
|
295
|
+
if (methodRaw === null || path === null)
|
|
296
|
+
continue;
|
|
297
|
+
out.push({
|
|
298
|
+
role: 'consumer',
|
|
299
|
+
framework: 'python-httpx',
|
|
300
|
+
method: methodRaw.toUpperCase(),
|
|
301
|
+
path,
|
|
302
|
+
name: null,
|
|
303
|
+
confidence: 0.7,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
131
306
|
return out;
|
|
132
307
|
},
|
|
133
308
|
};
|
|
@@ -3,6 +3,7 @@ import { glob } from 'glob';
|
|
|
3
3
|
import Parser from 'tree-sitter';
|
|
4
4
|
import { createIgnoreFilter } from '../../../config/ignore-service.js';
|
|
5
5
|
import { readSafe } from './fs-utils.js';
|
|
6
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
6
7
|
import { getPluginForFile, HTTP_SCAN_GLOB } from './http-patterns/index.js';
|
|
7
8
|
/**
|
|
8
9
|
* Language-agnostic orchestrator for HTTP route (provider + consumer)
|
|
@@ -154,7 +155,7 @@ export class HttpRouteExtractor {
|
|
|
154
155
|
}
|
|
155
156
|
try {
|
|
156
157
|
parser.setLanguage(plugin.language);
|
|
157
|
-
const tree = parser
|
|
158
|
+
const tree = parseSourceSafe(parser, content);
|
|
158
159
|
const detections = plugin.scan(tree);
|
|
159
160
|
cachedDetections.set(rel, detections);
|
|
160
161
|
return detections;
|
|
@@ -8,6 +8,7 @@ import { readSafe } from './fs-utils.js';
|
|
|
8
8
|
import { buildSuffixIndex } from '../../ingestion/import-resolvers/utils.js';
|
|
9
9
|
import { createIgnoreFilter } from '../../../config/ignore-service.js';
|
|
10
10
|
import { getMaxFileSizeBytes } from '../../ingestion/utils/max-file-size.js';
|
|
11
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
11
12
|
import { logger } from '../../logger.js';
|
|
12
13
|
/**
|
|
13
14
|
* Cross-repo C/C++ `#include` dependency extractor.
|
|
@@ -457,7 +458,7 @@ export class IncludeExtractor {
|
|
|
457
458
|
let extractionSource;
|
|
458
459
|
try {
|
|
459
460
|
parser.setLanguage(lang);
|
|
460
|
-
const tree = parser
|
|
461
|
+
const tree = parseSourceSafe(parser, content);
|
|
461
462
|
let matches;
|
|
462
463
|
try {
|
|
463
464
|
matches = query.matches(tree.rootNode);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { glob } from 'glob';
|
|
2
2
|
import Parser from 'tree-sitter';
|
|
3
3
|
import { readSafe } from './fs-utils.js';
|
|
4
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
4
5
|
import { getPluginForFile, THRIFT_SCAN_GLOB, } from './thrift-patterns/index.js';
|
|
5
6
|
function normalizeThriftPath(rel) {
|
|
6
7
|
return rel.replace(/\\/g, '/');
|
|
@@ -228,7 +229,7 @@ export class ThriftExtractor {
|
|
|
228
229
|
let detections = [];
|
|
229
230
|
try {
|
|
230
231
|
parser.setLanguage(plugin.language);
|
|
231
|
-
const tree = parser
|
|
232
|
+
const tree = parseSourceSafe(parser, content);
|
|
232
233
|
detections = plugin.scan(tree);
|
|
233
234
|
}
|
|
234
235
|
catch {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Parser from 'tree-sitter';
|
|
2
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
2
3
|
/**
|
|
3
4
|
* Compile a LanguagePatterns bundle. Call this once per plugin, at
|
|
4
5
|
* module load time, and export the result. Throws if any pattern
|
|
@@ -60,7 +61,7 @@ export function scanFile(parser, plugin, content) {
|
|
|
60
61
|
let tree;
|
|
61
62
|
try {
|
|
62
63
|
parser.setLanguage(plugin.language);
|
|
63
|
-
tree = parser
|
|
64
|
+
tree = parseSourceSafe(parser, content);
|
|
64
65
|
}
|
|
65
66
|
catch {
|
|
66
67
|
return [];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shadow-candidate path derivation for incremental indexing.
|
|
3
|
+
*
|
|
4
|
+
* Background — Bugbot review on PR #1479:
|
|
5
|
+
* queryImporters() on a NEWLY ADDED file returns 0 importers in the
|
|
6
|
+
* pre-pipeline DB, because the new file's IMPORTS rows haven't been
|
|
7
|
+
* written yet. But pre-existing files may have IMPORTS edges that
|
|
8
|
+
* *resolved to a sibling path*, and the newcomer can now steal that
|
|
9
|
+
* resolution under standard JS/TS module-resolution rules. Without
|
|
10
|
+
* pulling those pre-existing files into the writable set, their
|
|
11
|
+
* stale CALLS edges remain pointing at the OLD resolution target.
|
|
12
|
+
*
|
|
13
|
+
* Given an added file path, this helper enumerates the pre-existing
|
|
14
|
+
* file paths whose import-resolution claim the newcomer can steal.
|
|
15
|
+
* Caller filters the candidates against the prior-run `fileHashes`
|
|
16
|
+
* map so we only query importers of paths that actually existed.
|
|
17
|
+
*
|
|
18
|
+
* Shadow patterns covered (resolution-priority-aware):
|
|
19
|
+
*
|
|
20
|
+
* (a) Same basename, different extension —
|
|
21
|
+
* added `foo/bar.ts` shadows `foo/bar.{tsx,js,jsx,mjs,cjs,d.ts}`.
|
|
22
|
+
* (b) Bare-file beats directory-style index —
|
|
23
|
+
* added `foo/bar.ts` shadows `foo/bar/index.{ts,tsx,...}`.
|
|
24
|
+
* (c) Directory-index beats bare-file —
|
|
25
|
+
* added `foo/index.ts` shadows `foo.{ts,tsx,...}` (rare but real,
|
|
26
|
+
* e.g. converting a single-file module into a directory module).
|
|
27
|
+
*
|
|
28
|
+
* Resolution-order priority is conservatively wide: we enumerate ALL
|
|
29
|
+
* common extensions because we don't know which the importer actually
|
|
30
|
+
* specified, and over-seeding is harmless (extra BFS work, but the
|
|
31
|
+
* subgraph extract still gates write-back by file membership).
|
|
32
|
+
*
|
|
33
|
+
* Cross-platform path separators: candidates are emitted with both `/`
|
|
34
|
+
* and `\` for shadow pattern (b), since the caller's prior fileHashes
|
|
35
|
+
* map may use either depending on the OS that wrote it.
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* Enumerate pre-existing paths whose import-resolution `added` can steal.
|
|
39
|
+
*
|
|
40
|
+
* @param added — repo-relative path of a newly-added file
|
|
41
|
+
* @returns deduplicated list of candidate paths (NOT filtered against
|
|
42
|
+
* any known-files set — caller does that)
|
|
43
|
+
*/
|
|
44
|
+
export declare const shadowCandidatesFor: (added: string) => string[];
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shadow-candidate path derivation for incremental indexing.
|
|
3
|
+
*
|
|
4
|
+
* Background — Bugbot review on PR #1479:
|
|
5
|
+
* queryImporters() on a NEWLY ADDED file returns 0 importers in the
|
|
6
|
+
* pre-pipeline DB, because the new file's IMPORTS rows haven't been
|
|
7
|
+
* written yet. But pre-existing files may have IMPORTS edges that
|
|
8
|
+
* *resolved to a sibling path*, and the newcomer can now steal that
|
|
9
|
+
* resolution under standard JS/TS module-resolution rules. Without
|
|
10
|
+
* pulling those pre-existing files into the writable set, their
|
|
11
|
+
* stale CALLS edges remain pointing at the OLD resolution target.
|
|
12
|
+
*
|
|
13
|
+
* Given an added file path, this helper enumerates the pre-existing
|
|
14
|
+
* file paths whose import-resolution claim the newcomer can steal.
|
|
15
|
+
* Caller filters the candidates against the prior-run `fileHashes`
|
|
16
|
+
* map so we only query importers of paths that actually existed.
|
|
17
|
+
*
|
|
18
|
+
* Shadow patterns covered (resolution-priority-aware):
|
|
19
|
+
*
|
|
20
|
+
* (a) Same basename, different extension —
|
|
21
|
+
* added `foo/bar.ts` shadows `foo/bar.{tsx,js,jsx,mjs,cjs,d.ts}`.
|
|
22
|
+
* (b) Bare-file beats directory-style index —
|
|
23
|
+
* added `foo/bar.ts` shadows `foo/bar/index.{ts,tsx,...}`.
|
|
24
|
+
* (c) Directory-index beats bare-file —
|
|
25
|
+
* added `foo/index.ts` shadows `foo.{ts,tsx,...}` (rare but real,
|
|
26
|
+
* e.g. converting a single-file module into a directory module).
|
|
27
|
+
*
|
|
28
|
+
* Resolution-order priority is conservatively wide: we enumerate ALL
|
|
29
|
+
* common extensions because we don't know which the importer actually
|
|
30
|
+
* specified, and over-seeding is harmless (extra BFS work, but the
|
|
31
|
+
* subgraph extract still gates write-back by file membership).
|
|
32
|
+
*
|
|
33
|
+
* Cross-platform path separators: candidates are emitted with both `/`
|
|
34
|
+
* and `\` for shadow pattern (b), since the caller's prior fileHashes
|
|
35
|
+
* map may use either depending on the OS that wrote it.
|
|
36
|
+
*/
|
|
37
|
+
const SHADOW_EXTS = ['.d.ts', '.tsx', '.ts', '.jsx', '.js', '.mjs', '.cjs'];
|
|
38
|
+
/**
|
|
39
|
+
* Enumerate pre-existing paths whose import-resolution `added` can steal.
|
|
40
|
+
*
|
|
41
|
+
* @param added — repo-relative path of a newly-added file
|
|
42
|
+
* @returns deduplicated list of candidate paths (NOT filtered against
|
|
43
|
+
* any known-files set — caller does that)
|
|
44
|
+
*/
|
|
45
|
+
export const shadowCandidatesFor = (added) => {
|
|
46
|
+
const ext = SHADOW_EXTS.find((e) => added.endsWith(e));
|
|
47
|
+
if (!ext)
|
|
48
|
+
return [];
|
|
49
|
+
const noExt = added.slice(0, -ext.length);
|
|
50
|
+
const out = new Set();
|
|
51
|
+
// (a) Same basename, different extension.
|
|
52
|
+
for (const alt of SHADOW_EXTS) {
|
|
53
|
+
if (alt !== ext)
|
|
54
|
+
out.add(noExt + alt);
|
|
55
|
+
}
|
|
56
|
+
// (b) Bare file beats sibling directory-style index.
|
|
57
|
+
for (const idx of SHADOW_EXTS) {
|
|
58
|
+
out.add(`${noExt}/index${idx}`);
|
|
59
|
+
out.add(`${noExt}\\index${idx}`);
|
|
60
|
+
}
|
|
61
|
+
// (c) New `foo/index.ext` shadows old `foo.ext`.
|
|
62
|
+
const idxSuffixSlash = '/index';
|
|
63
|
+
const idxSuffixBack = '\\index';
|
|
64
|
+
let dir = null;
|
|
65
|
+
if (noExt.endsWith(idxSuffixSlash))
|
|
66
|
+
dir = noExt.slice(0, -idxSuffixSlash.length);
|
|
67
|
+
else if (noExt.endsWith(idxSuffixBack))
|
|
68
|
+
dir = noExt.slice(0, -idxSuffixBack.length);
|
|
69
|
+
if (dir !== null) {
|
|
70
|
+
for (const alt of SHADOW_EXTS)
|
|
71
|
+
out.add(dir + alt);
|
|
72
|
+
}
|
|
73
|
+
return [...out];
|
|
74
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subgraph extraction for incremental DB writeback.
|
|
3
|
+
*
|
|
4
|
+
* Given the FULL ctx.graph produced by the pipeline (all files parsed,
|
|
5
|
+
* all phases run) and the set of file paths whose DB rows must be
|
|
6
|
+
* replaced, produce a smaller KnowledgeGraph that contains:
|
|
7
|
+
*
|
|
8
|
+
* - Every node whose `properties.filePath` is in `toWriteSet`.
|
|
9
|
+
* - Every graph-wide node (Community, Process) — these are regenerated
|
|
10
|
+
* each run by the communities/processes phases and must be fully
|
|
11
|
+
* rewritten.
|
|
12
|
+
* - Every relationship where AT LEAST ONE endpoint is in the writable
|
|
13
|
+
* set above. Relationships entirely between unchanged-file nodes
|
|
14
|
+
* are skipped — their rows are still in the DB and re-inserting
|
|
15
|
+
* them would PK-conflict at COPY time.
|
|
16
|
+
*
|
|
17
|
+
* The resulting subgraph is what gets passed to `loadGraphToLbug` after
|
|
18
|
+
* the orchestrator has deleted the corresponding DB rows. Hydrated
|
|
19
|
+
* unchanged-file rows are never touched in the DB.
|
|
20
|
+
*
|
|
21
|
+
* # Cross-file edge consistency (Finding 1)
|
|
22
|
+
*
|
|
23
|
+
* `extractChangedSubgraph` intentionally does NOT expand the set it is
|
|
24
|
+
* given — expansion is the orchestrator's job, so the SAME expanded set
|
|
25
|
+
* can be fed to both `deleteNodesForFile` and this function (asymmetry
|
|
26
|
+
* between the delete set and the write set silently corrupts the DB).
|
|
27
|
+
* `computeEffectiveWriteSet` below performs the boundary-crossing 1-hop
|
|
28
|
+
* walk; the orchestrator composes it with its importer-BFS expansion and
|
|
29
|
+
* passes the result here.
|
|
30
|
+
*
|
|
31
|
+
* Why the 1-hop walk is needed: consider a barrel re-export change —
|
|
32
|
+
* file C (a barrel) shifts `export { foo } from './b'` to
|
|
33
|
+
* `export { foo } from './d'`. After scope resolution, file A's CALLS
|
|
34
|
+
* edge to `foo` resolves to D instead of B, even though A's content is
|
|
35
|
+
* byte-for-byte identical:
|
|
36
|
+
*
|
|
37
|
+
* - Old A→B edge survives in DB (neither A nor B is changed → not deleted)
|
|
38
|
+
* - New A→D edge is missing (neither A nor D in writable set → skipped)
|
|
39
|
+
*
|
|
40
|
+
* Pulling the unchanged-side file of every writable-boundary-crossing
|
|
41
|
+
* edge into the write set fixes both halves: the orchestrator's
|
|
42
|
+
* `DETACH DELETE` cleans up the stale unchanged-side rows, and the new
|
|
43
|
+
* cross-file edges land because at least one endpoint is now writable.
|
|
44
|
+
*
|
|
45
|
+
* Limitation (documented): if a file X *stopped* importing from a
|
|
46
|
+
* changed file C, X has no edge to C in the new graph, so this 1-hop
|
|
47
|
+
* walk doesn't catch it. The orchestrator's importer-BFS (which reads
|
|
48
|
+
* IMPORTS from the pre-pipeline DB) covers that case instead.
|
|
49
|
+
*/
|
|
50
|
+
import type { KnowledgeGraph } from '../graph/types.js';
|
|
51
|
+
export declare const extractChangedSubgraph: (fullGraph: KnowledgeGraph, toWriteSet: ReadonlySet<string>) => KnowledgeGraph;
|
|
52
|
+
/**
|
|
53
|
+
* Public — derive the EFFECTIVE write-set: `toWriteSet` expanded by one
|
|
54
|
+
* hop along every edge in the new graph that crosses the writable
|
|
55
|
+
* boundary (one endpoint in a writable file, the other in an unchanged
|
|
56
|
+
* file). The unchanged-side file is pulled in so its stale rows are
|
|
57
|
+
* deleted + rewritten in lockstep with the changed side.
|
|
58
|
+
*
|
|
59
|
+
* Single pass over the edge list. Does NOT mutate `toWriteSet`. The
|
|
60
|
+
* orchestrator MUST feed the returned set to both `deleteNodesForFile`
|
|
61
|
+
* and `extractChangedSubgraph` — feeding the unexpanded set to either
|
|
62
|
+
* one leaves stale rows or PK-conflicts at COPY time.
|
|
63
|
+
*/
|
|
64
|
+
export declare const computeEffectiveWriteSet: (fullGraph: KnowledgeGraph, toWriteSet: ReadonlySet<string>) => Set<string>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subgraph extraction for incremental DB writeback.
|
|
3
|
+
*
|
|
4
|
+
* Given the FULL ctx.graph produced by the pipeline (all files parsed,
|
|
5
|
+
* all phases run) and the set of file paths whose DB rows must be
|
|
6
|
+
* replaced, produce a smaller KnowledgeGraph that contains:
|
|
7
|
+
*
|
|
8
|
+
* - Every node whose `properties.filePath` is in `toWriteSet`.
|
|
9
|
+
* - Every graph-wide node (Community, Process) — these are regenerated
|
|
10
|
+
* each run by the communities/processes phases and must be fully
|
|
11
|
+
* rewritten.
|
|
12
|
+
* - Every relationship where AT LEAST ONE endpoint is in the writable
|
|
13
|
+
* set above. Relationships entirely between unchanged-file nodes
|
|
14
|
+
* are skipped — their rows are still in the DB and re-inserting
|
|
15
|
+
* them would PK-conflict at COPY time.
|
|
16
|
+
*
|
|
17
|
+
* The resulting subgraph is what gets passed to `loadGraphToLbug` after
|
|
18
|
+
* the orchestrator has deleted the corresponding DB rows. Hydrated
|
|
19
|
+
* unchanged-file rows are never touched in the DB.
|
|
20
|
+
*
|
|
21
|
+
* # Cross-file edge consistency (Finding 1)
|
|
22
|
+
*
|
|
23
|
+
* `extractChangedSubgraph` intentionally does NOT expand the set it is
|
|
24
|
+
* given — expansion is the orchestrator's job, so the SAME expanded set
|
|
25
|
+
* can be fed to both `deleteNodesForFile` and this function (asymmetry
|
|
26
|
+
* between the delete set and the write set silently corrupts the DB).
|
|
27
|
+
* `computeEffectiveWriteSet` below performs the boundary-crossing 1-hop
|
|
28
|
+
* walk; the orchestrator composes it with its importer-BFS expansion and
|
|
29
|
+
* passes the result here.
|
|
30
|
+
*
|
|
31
|
+
* Why the 1-hop walk is needed: consider a barrel re-export change —
|
|
32
|
+
* file C (a barrel) shifts `export { foo } from './b'` to
|
|
33
|
+
* `export { foo } from './d'`. After scope resolution, file A's CALLS
|
|
34
|
+
* edge to `foo` resolves to D instead of B, even though A's content is
|
|
35
|
+
* byte-for-byte identical:
|
|
36
|
+
*
|
|
37
|
+
* - Old A→B edge survives in DB (neither A nor B is changed → not deleted)
|
|
38
|
+
* - New A→D edge is missing (neither A nor D in writable set → skipped)
|
|
39
|
+
*
|
|
40
|
+
* Pulling the unchanged-side file of every writable-boundary-crossing
|
|
41
|
+
* edge into the write set fixes both halves: the orchestrator's
|
|
42
|
+
* `DETACH DELETE` cleans up the stale unchanged-side rows, and the new
|
|
43
|
+
* cross-file edges land because at least one endpoint is now writable.
|
|
44
|
+
*
|
|
45
|
+
* Limitation (documented): if a file X *stopped* importing from a
|
|
46
|
+
* changed file C, X has no edge to C in the new graph, so this 1-hop
|
|
47
|
+
* walk doesn't catch it. The orchestrator's importer-BFS (which reads
|
|
48
|
+
* IMPORTS from the pre-pipeline DB) covers that case instead.
|
|
49
|
+
*/
|
|
50
|
+
import { createKnowledgeGraph } from '../graph/graph.js';
|
|
51
|
+
const isGraphWide = (label) => label === 'Community' || label === 'Process';
|
|
52
|
+
/**
|
|
53
|
+
* Build a Map<nodeId, filePath> for every File-bound node in the graph.
|
|
54
|
+
* Graph-wide nodes (Community/Process) have no filePath and are filtered.
|
|
55
|
+
*/
|
|
56
|
+
const indexNodeFilePaths = (fullGraph) => {
|
|
57
|
+
const idx = new Map();
|
|
58
|
+
fullGraph.forEachNode((n) => {
|
|
59
|
+
const fp = n.properties?.filePath;
|
|
60
|
+
if (fp)
|
|
61
|
+
idx.set(n.id, fp);
|
|
62
|
+
});
|
|
63
|
+
return idx;
|
|
64
|
+
};
|
|
65
|
+
export const extractChangedSubgraph = (fullGraph, toWriteSet) => {
|
|
66
|
+
const sub = createKnowledgeGraph();
|
|
67
|
+
const writableNodeIds = new Set();
|
|
68
|
+
fullGraph.forEachNode((n) => {
|
|
69
|
+
const filePath = n.properties?.filePath;
|
|
70
|
+
const include = (filePath && toWriteSet.has(filePath)) || isGraphWide(n.label);
|
|
71
|
+
if (include) {
|
|
72
|
+
sub.addNode(n);
|
|
73
|
+
writableNodeIds.add(n.id);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
fullGraph.forEachRelationship((r) => {
|
|
77
|
+
if (writableNodeIds.has(r.sourceId) || writableNodeIds.has(r.targetId)) {
|
|
78
|
+
sub.addRelationship(r);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return sub;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Public — derive the EFFECTIVE write-set: `toWriteSet` expanded by one
|
|
85
|
+
* hop along every edge in the new graph that crosses the writable
|
|
86
|
+
* boundary (one endpoint in a writable file, the other in an unchanged
|
|
87
|
+
* file). The unchanged-side file is pulled in so its stale rows are
|
|
88
|
+
* deleted + rewritten in lockstep with the changed side.
|
|
89
|
+
*
|
|
90
|
+
* Single pass over the edge list. Does NOT mutate `toWriteSet`. The
|
|
91
|
+
* orchestrator MUST feed the returned set to both `deleteNodesForFile`
|
|
92
|
+
* and `extractChangedSubgraph` — feeding the unexpanded set to either
|
|
93
|
+
* one leaves stale rows or PK-conflicts at COPY time.
|
|
94
|
+
*/
|
|
95
|
+
export const computeEffectiveWriteSet = (fullGraph, toWriteSet) => {
|
|
96
|
+
const nodeFilePaths = indexNodeFilePaths(fullGraph);
|
|
97
|
+
const expanded = new Set(toWriteSet);
|
|
98
|
+
fullGraph.forEachRelationship((r) => {
|
|
99
|
+
const sourcePath = nodeFilePaths.get(r.sourceId);
|
|
100
|
+
const targetPath = nodeFilePaths.get(r.targetId);
|
|
101
|
+
if (!sourcePath || !targetPath)
|
|
102
|
+
return; // skip edges to graph-wide nodes
|
|
103
|
+
const sourceWritable = toWriteSet.has(sourcePath);
|
|
104
|
+
const targetWritable = toWriteSet.has(targetPath);
|
|
105
|
+
if (sourceWritable && !targetWritable)
|
|
106
|
+
expanded.add(targetPath);
|
|
107
|
+
else if (targetWritable && !sourceWritable)
|
|
108
|
+
expanded.add(sourcePath);
|
|
109
|
+
});
|
|
110
|
+
return expanded;
|
|
111
|
+
};
|