@nicia-ai/typegraph 0.45.0 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backend/drizzle/indexes.cjs +11 -11
- package/dist/backend/drizzle/indexes.d.cts +1 -1
- package/dist/backend/drizzle/indexes.d.ts +1 -1
- package/dist/backend/drizzle/indexes.js +7 -7
- package/dist/backend/index.cjs +53 -54
- package/dist/backend/index.d.cts +3 -3
- package/dist/backend/index.d.ts +3 -3
- package/dist/backend/index.js +13 -14
- package/dist/backend/postgres/index.cjs +29 -30
- package/dist/backend/postgres/index.d.cts +7 -7
- package/dist/backend/postgres/index.d.ts +7 -7
- package/dist/backend/postgres/index.js +16 -17
- package/dist/backend/postgres/pglite-store.cjs +48 -42
- package/dist/backend/postgres/pglite-store.cjs.map +1 -1
- package/dist/backend/postgres/pglite-store.d.cts +15 -9
- package/dist/backend/postgres/pglite-store.d.ts +15 -9
- package/dist/backend/postgres/pglite-store.js +44 -38
- package/dist/backend/postgres/pglite-store.js.map +1 -1
- package/dist/backend/postgres/pglite.cjs +18 -19
- package/dist/backend/postgres/pglite.d.cts +4 -4
- package/dist/backend/postgres/pglite.d.ts +4 -4
- package/dist/backend/postgres/pglite.js +17 -18
- package/dist/backend/sqlite/index.cjs +26 -27
- package/dist/backend/sqlite/index.d.cts +6 -6
- package/dist/backend/sqlite/index.d.ts +6 -6
- package/dist/backend/sqlite/index.js +14 -15
- package/dist/backend/sqlite/libsql.cjs +21 -22
- package/dist/backend/sqlite/libsql.cjs.map +1 -1
- package/dist/backend/sqlite/libsql.d.cts +15 -8
- package/dist/backend/sqlite/libsql.d.ts +15 -8
- package/dist/backend/sqlite/libsql.js +17 -18
- package/dist/backend/sqlite/libsql.js.map +1 -1
- package/dist/backend/sqlite/local-store.cjs +49 -43
- package/dist/backend/sqlite/local-store.cjs.map +1 -1
- package/dist/backend/sqlite/local-store.d.cts +15 -10
- package/dist/backend/sqlite/local-store.d.ts +15 -10
- package/dist/backend/sqlite/local-store.js +45 -39
- package/dist/backend/sqlite/local-store.js.map +1 -1
- package/dist/backend/sqlite/local.cjs +19 -20
- package/dist/backend/sqlite/local.d.cts +3 -3
- package/dist/backend/sqlite/local.d.ts +3 -3
- package/dist/backend/sqlite/local.js +17 -18
- package/dist/{chunk-S3ZRKJHY.js → chunk-2LG2XB2M.js} +3 -3
- package/dist/{chunk-S3ZRKJHY.js.map → chunk-2LG2XB2M.js.map} +1 -1
- package/dist/{chunk-7PF2L3H6.cjs → chunk-2NA5DYLO.cjs} +4 -4
- package/dist/{chunk-7PF2L3H6.cjs.map → chunk-2NA5DYLO.cjs.map} +1 -1
- package/dist/{chunk-VVQM4CZD.cjs → chunk-3DHZCOT7.cjs} +20 -20
- package/dist/{chunk-VVQM4CZD.cjs.map → chunk-3DHZCOT7.cjs.map} +1 -1
- package/dist/{chunk-JXUTCSXX.cjs → chunk-4UGOKMI5.cjs} +250 -158
- package/dist/chunk-4UGOKMI5.cjs.map +1 -0
- package/dist/{chunk-RFRM3Q5K.js → chunk-5262ZMTR.js} +14 -5
- package/dist/chunk-5262ZMTR.js.map +1 -0
- package/dist/{chunk-QRNYDV5Z.js → chunk-5763DULU.js} +214 -69
- package/dist/chunk-5763DULU.js.map +1 -0
- package/dist/{chunk-BGYJW37L.js → chunk-5UVRGXD3.js} +277 -7
- package/dist/chunk-5UVRGXD3.js.map +1 -0
- package/dist/{chunk-QR24DJDF.cjs → chunk-62ZP23AW.cjs} +15 -15
- package/dist/{chunk-QR24DJDF.cjs.map → chunk-62ZP23AW.cjs.map} +1 -1
- package/dist/{chunk-S4KQ5LV4.js → chunk-775A4ZMN.js} +40 -6
- package/dist/chunk-775A4ZMN.js.map +1 -0
- package/dist/{chunk-J2ICGNHO.cjs → chunk-7BQXPCGN.cjs} +830 -169
- package/dist/chunk-7BQXPCGN.cjs.map +1 -0
- package/dist/{chunk-FJMPR3OH.cjs → chunk-7EO3TCQB.cjs} +33 -7
- package/dist/chunk-7EO3TCQB.cjs.map +1 -0
- package/dist/{chunk-UCQ3BFSY.cjs → chunk-7GT72YHH.cjs} +682 -332
- package/dist/chunk-7GT72YHH.cjs.map +1 -0
- package/dist/{chunk-DXEEHSGN.js → chunk-7VQXLT5O.js} +436 -43
- package/dist/chunk-7VQXLT5O.js.map +1 -0
- package/dist/{chunk-ID4WXTKL.js → chunk-7Z5OR7KO.js} +2360 -605
- package/dist/chunk-7Z5OR7KO.js.map +1 -0
- package/dist/chunk-A4OC4DVN.cjs +12 -0
- package/dist/{chunk-4SZ6XPTG.cjs.map → chunk-A4OC4DVN.cjs.map} +1 -1
- package/dist/{chunk-TDXIBCGY.cjs → chunk-A7J2YDDI.cjs} +5 -3
- package/dist/chunk-A7J2YDDI.cjs.map +1 -0
- package/dist/{chunk-55ITBQJI.js → chunk-AKLS3BYZ.js} +56 -5
- package/dist/chunk-AKLS3BYZ.js.map +1 -0
- package/dist/{chunk-D7PG5D5K.js → chunk-AMKPPFUO.js} +32 -6
- package/dist/chunk-AMKPPFUO.js.map +1 -0
- package/dist/{chunk-WUFASQUO.js → chunk-ASTI57H3.js} +3 -3
- package/dist/{chunk-WUFASQUO.js.map → chunk-ASTI57H3.js.map} +1 -1
- package/dist/{chunk-4QIKLIGG.js → chunk-BKCUOV7A.js} +15 -5
- package/dist/chunk-BKCUOV7A.js.map +1 -0
- package/dist/{chunk-JQXSZHF2.cjs → chunk-BSFJMMV3.cjs} +134 -7
- package/dist/chunk-BSFJMMV3.cjs.map +1 -0
- package/dist/{chunk-4GUTQPVO.js → chunk-C23WSN5E.js} +185 -24
- package/dist/chunk-C23WSN5E.js.map +1 -0
- package/dist/{chunk-QLUXRWKL.js → chunk-CBTIUB76.js} +3 -3
- package/dist/{chunk-QLUXRWKL.js.map → chunk-CBTIUB76.js.map} +1 -1
- package/dist/chunk-CNV4TXJG.js +58 -0
- package/dist/chunk-CNV4TXJG.js.map +1 -0
- package/dist/{chunk-QB6VMOJ2.cjs → chunk-CXBHOOIQ.cjs} +45 -10
- package/dist/chunk-CXBHOOIQ.cjs.map +1 -0
- package/dist/{chunk-FL5UQRES.js → chunk-DCQVHAYQ.js} +5 -5
- package/dist/{chunk-FL5UQRES.js.map → chunk-DCQVHAYQ.js.map} +1 -1
- package/dist/chunk-DLNROMQ7.js +306 -0
- package/dist/chunk-DLNROMQ7.js.map +1 -0
- package/dist/chunk-DYATYRY4.js +47 -0
- package/dist/chunk-DYATYRY4.js.map +1 -0
- package/dist/chunk-E4WNQBEF.cjs +217 -0
- package/dist/chunk-E4WNQBEF.cjs.map +1 -0
- package/dist/{chunk-G6Q5UM7U.js → chunk-FWJKWH6U.js} +5 -3
- package/dist/chunk-FWJKWH6U.js.map +1 -0
- package/dist/{chunk-VTN3C3CH.js → chunk-HFHTMECK.js} +7 -7
- package/dist/{chunk-VTN3C3CH.js.map → chunk-HFHTMECK.js.map} +1 -1
- package/dist/{chunk-FLEQ2HBK.js → chunk-I5MOXA4H.js} +20 -14
- package/dist/chunk-I5MOXA4H.js.map +1 -0
- package/dist/{chunk-4MB3AQAQ.js → chunk-J3WZ3FA2.js} +77 -3
- package/dist/chunk-J3WZ3FA2.js.map +1 -0
- package/dist/{chunk-UR7W5YQK.js → chunk-JBQQ7THH.js} +5 -3
- package/dist/chunk-JBQQ7THH.js.map +1 -0
- package/dist/chunk-JIVMTW7W.js +3393 -0
- package/dist/chunk-JIVMTW7W.js.map +1 -0
- package/dist/{chunk-TKP5T34P.js → chunk-JXA2ZP2Q.js} +6 -16
- package/dist/chunk-JXA2ZP2Q.js.map +1 -0
- package/dist/{chunk-GYA4JRP5.js → chunk-JXXDZTMN.js} +2 -2
- package/dist/chunk-JXXDZTMN.js.map +1 -0
- package/dist/chunk-JZUR7ZWE.js +254 -0
- package/dist/chunk-JZUR7ZWE.js.map +1 -0
- package/dist/{chunk-42PYUGLS.js → chunk-K5ELX2GT.js} +108 -8
- package/dist/chunk-K5ELX2GT.js.map +1 -0
- package/dist/{chunk-D54WH24V.cjs → chunk-LBJKZXDE.cjs} +115 -13
- package/dist/chunk-LBJKZXDE.cjs.map +1 -0
- package/dist/{chunk-4MEWSUVM.cjs → chunk-M4BDU5RX.cjs} +12 -12
- package/dist/chunk-M4BDU5RX.cjs.map +1 -0
- package/dist/{chunk-MIJKEVV7.js → chunk-MSY7FSX4.js} +37 -4
- package/dist/chunk-MSY7FSX4.js.map +1 -0
- package/dist/{chunk-H7VE3FL4.cjs → chunk-MUK4BU7K.cjs} +519 -125
- package/dist/chunk-MUK4BU7K.cjs.map +1 -0
- package/dist/{chunk-D56XG4EI.cjs → chunk-MXJDTH5B.cjs} +56 -45
- package/dist/chunk-MXJDTH5B.cjs.map +1 -0
- package/dist/{chunk-ZI6VQSZA.cjs → chunk-N3257XE6.cjs} +724 -577
- package/dist/chunk-N3257XE6.cjs.map +1 -0
- package/dist/chunk-N66HCGCY.cjs +57 -0
- package/dist/chunk-N66HCGCY.cjs.map +1 -0
- package/dist/{chunk-CPEL3YIR.cjs → chunk-NFCVHQ5P.cjs} +55 -22
- package/dist/chunk-NFCVHQ5P.cjs.map +1 -0
- package/dist/{chunk-C4F7VJ5D.cjs → chunk-NI72YOJB.cjs} +84 -2
- package/dist/chunk-NI72YOJB.cjs.map +1 -0
- package/dist/{chunk-BNS75YNF.cjs → chunk-NK5Q7UNE.cjs} +10 -20
- package/dist/chunk-NK5Q7UNE.cjs.map +1 -0
- package/dist/{chunk-YMTXMPV6.js → chunk-NMWDXFPH.js} +4 -4
- package/dist/{chunk-YMTXMPV6.js.map → chunk-NMWDXFPH.js.map} +1 -1
- package/dist/{chunk-TKORQCG4.js → chunk-NQ6BRJBE.js} +386 -862
- package/dist/chunk-NQ6BRJBE.js.map +1 -0
- package/dist/chunk-OH5E5KIO.js +2057 -0
- package/dist/chunk-OH5E5KIO.js.map +1 -0
- package/dist/chunk-ONU3HIED.cjs +2082 -0
- package/dist/chunk-ONU3HIED.cjs.map +1 -0
- package/dist/{chunk-NAAMUYMS.cjs → chunk-PNN7RHVR.cjs} +58 -48
- package/dist/chunk-PNN7RHVR.cjs.map +1 -0
- package/dist/{chunk-6DCB664D.js → chunk-PQBQG7IM.js} +3 -3
- package/dist/{chunk-6DCB664D.js.map → chunk-PQBQG7IM.js.map} +1 -1
- package/dist/{chunk-ACSVZPK7.cjs → chunk-PWLJ77UV.cjs} +5 -3
- package/dist/chunk-PWLJ77UV.cjs.map +1 -0
- package/dist/chunk-Q7Q4WSLJ.cjs +328 -0
- package/dist/chunk-Q7Q4WSLJ.cjs.map +1 -0
- package/dist/{chunk-FQ7ZPOTZ.js → chunk-QLRESYPU.js} +637 -493
- package/dist/chunk-QLRESYPU.js.map +1 -0
- package/dist/{chunk-Q6EDCUXV.js → chunk-QWX5YA3K.js} +554 -204
- package/dist/chunk-QWX5YA3K.js.map +1 -0
- package/dist/{chunk-5EKPX6QU.js → chunk-RJS7DECT.js} +8 -9
- package/dist/chunk-RJS7DECT.js.map +1 -0
- package/dist/{chunk-Z3WO6MND.cjs → chunk-RMQLSPA2.cjs} +297 -27
- package/dist/chunk-RMQLSPA2.cjs.map +1 -0
- package/dist/{chunk-SJDMVITW.cjs → chunk-RT5ZY4XA.cjs} +6 -5
- package/dist/chunk-RT5ZY4XA.cjs.map +1 -0
- package/dist/{chunk-4GUBTVPV.js → chunk-T4XNKYXB.js} +780 -126
- package/dist/chunk-T4XNKYXB.js.map +1 -0
- package/dist/{chunk-YDWLUT5V.cjs → chunk-TQR4KBY2.cjs} +323 -178
- package/dist/chunk-TQR4KBY2.cjs.map +1 -0
- package/dist/chunk-TTAITEPJ.cjs +755 -0
- package/dist/chunk-TTAITEPJ.cjs.map +1 -0
- package/dist/{chunk-OOA273IJ.cjs → chunk-U5SON7R2.cjs} +27 -27
- package/dist/{chunk-OOA273IJ.cjs.map → chunk-U5SON7R2.cjs.map} +1 -1
- package/dist/{chunk-IX64T5OL.cjs → chunk-U63GDNRC.cjs} +32 -26
- package/dist/chunk-U63GDNRC.cjs.map +1 -0
- package/dist/{chunk-WDBXJOU5.cjs → chunk-UDISNXDL.cjs} +56 -47
- package/dist/chunk-UDISNXDL.cjs.map +1 -0
- package/dist/{chunk-EFEOOCJ3.js → chunk-UV3SN74I.js} +5 -5
- package/dist/{chunk-EFEOOCJ3.js.map → chunk-UV3SN74I.js.map} +1 -1
- package/dist/{chunk-U5W4LKZV.cjs → chunk-VCRRKBLN.cjs} +9 -9
- package/dist/{chunk-U5W4LKZV.cjs.map → chunk-VCRRKBLN.cjs.map} +1 -1
- package/dist/{chunk-ISLPNELU.js → chunk-VGTJPTIC.js} +16 -5
- package/dist/chunk-VGTJPTIC.js.map +1 -0
- package/dist/chunk-VQH4VAWD.cjs +12 -0
- package/dist/{chunk-B3F2D3SP.cjs.map → chunk-VQH4VAWD.cjs.map} +1 -1
- package/dist/{chunk-SNXVDZAJ.js → chunk-W6OG3HDG.js} +5 -4
- package/dist/chunk-W6OG3HDG.js.map +1 -0
- package/dist/chunk-WDGA7IYB.js +207 -0
- package/dist/chunk-WDGA7IYB.js.map +1 -0
- package/dist/chunk-WEVQJ5LH.js +736 -0
- package/dist/chunk-WEVQJ5LH.js.map +1 -0
- package/dist/{chunk-EKFUG4G7.cjs → chunk-XBYVV3MP.cjs} +60 -5
- package/dist/chunk-XBYVV3MP.cjs.map +1 -0
- package/dist/{chunk-5GAONX5G.cjs → chunk-XCAGZAKP.cjs} +7 -7
- package/dist/{chunk-5GAONX5G.cjs.map → chunk-XCAGZAKP.cjs.map} +1 -1
- package/dist/{chunk-YOALGKRE.cjs → chunk-XDF2UPEQ.cjs} +3521 -1766
- package/dist/chunk-XDF2UPEQ.cjs.map +1 -0
- package/dist/{chunk-J7LXTUTP.cjs → chunk-XMQSEJCF.cjs} +604 -1094
- package/dist/chunk-XMQSEJCF.cjs.map +1 -0
- package/dist/chunk-XNLIZYRZ.cjs +3432 -0
- package/dist/chunk-XNLIZYRZ.cjs.map +1 -0
- package/dist/{chunk-KMXWZLQX.cjs → chunk-XNSI2FJO.cjs} +99 -100
- package/dist/chunk-XNSI2FJO.cjs.map +1 -0
- package/dist/chunk-XQSCL77R.cjs +60 -0
- package/dist/chunk-XQSCL77R.cjs.map +1 -0
- package/dist/{chunk-SVJ5GEXW.cjs → chunk-XUO3KQFO.cjs} +2 -2
- package/dist/chunk-XUO3KQFO.cjs.map +1 -0
- package/dist/{chunk-F4NHQHEZ.cjs → chunk-YAAM3M2S.cjs} +10 -10
- package/dist/{chunk-F4NHQHEZ.cjs.map → chunk-YAAM3M2S.cjs.map} +1 -1
- package/dist/{chunk-RUQS6M7G.js → chunk-YBFHZUXX.js} +6 -6
- package/dist/chunk-YBFHZUXX.js.map +1 -0
- package/dist/{chunk-PVUI6KGR.js → chunk-YDFDBE6D.js} +93 -6
- package/dist/chunk-YDFDBE6D.js.map +1 -0
- package/dist/{chunk-P7GTYOLB.cjs → chunk-YVWGEQJE.cjs} +297 -135
- package/dist/chunk-YVWGEQJE.cjs.map +1 -0
- package/dist/{chunk-QT6V3YRH.js → chunk-YWGVVALJ.js} +3 -3
- package/dist/{chunk-QT6V3YRH.js.map → chunk-YWGVVALJ.js.map} +1 -1
- package/dist/core/index.cjs +40 -40
- package/dist/core/index.d.cts +4 -5
- package/dist/core/index.d.ts +4 -5
- package/dist/core/index.js +8 -8
- package/dist/{ddl-BG4J805L.d.cts → ddl-BJcOp4WZ.d.cts} +3 -3
- package/dist/{ddl-CgiS9QLj.d.ts → ddl-BXfGHbPN.d.ts} +3 -3
- package/dist/graph-extension/index.cjs +26 -22
- package/dist/graph-extension/index.d.cts +16 -6
- package/dist/graph-extension/index.d.ts +16 -6
- package/dist/graph-extension/index.js +7 -7
- package/dist/graph-merge/index.cjs +2459 -654
- package/dist/graph-merge/index.cjs.map +1 -1
- package/dist/graph-merge/index.d.cts +170 -33
- package/dist/graph-merge/index.d.ts +170 -33
- package/dist/graph-merge/index.js +2269 -467
- package/dist/graph-merge/index.js.map +1 -1
- package/dist/{index-C3y_98iN.d.cts → index-BSHvKfok.d.ts} +221 -10
- package/dist/{index-BBxZCUdu.d.ts → index-DxaYCv8Y.d.cts} +221 -10
- package/dist/index.cjs +330 -268
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +590 -576
- package/dist/index.d.ts +590 -576
- package/dist/index.js +73 -49
- package/dist/index.js.map +1 -1
- package/dist/indexes/index.cjs +17 -17
- package/dist/indexes/index.d.cts +4 -4
- package/dist/indexes/index.d.ts +4 -4
- package/dist/indexes/index.js +10 -10
- package/dist/interchange/index.cjs +165 -51
- package/dist/interchange/index.cjs.map +1 -1
- package/dist/interchange/index.d.cts +261 -16
- package/dist/interchange/index.d.ts +261 -16
- package/dist/interchange/index.js +128 -25
- package/dist/interchange/index.js.map +1 -1
- package/dist/{manager-YoLEfcc1.d.ts → manager-CfZAimti.d.ts} +36 -5
- package/dist/{manager-KS7CGQQT.d.cts → manager-HGk6E_HW.d.cts} +36 -5
- package/dist/{materialize-indexes-Bhhyb1B3.d.ts → materialize-indexes-6A7dWGtb.d.cts} +10 -2
- package/dist/{materialize-indexes-OHRWypW6.d.cts → materialize-indexes-BMJP6Tms.d.ts} +10 -2
- package/dist/{postgres-DpkW3R5Y.d.cts → postgres-DFYWENdR.d.cts} +1961 -439
- package/dist/{postgres-DwqyIniy.d.ts → postgres-e7a9TdvR.d.ts} +1961 -439
- package/dist/profiler/index.cjs +15 -15
- package/dist/profiler/index.d.cts +9 -10
- package/dist/profiler/index.d.ts +9 -10
- package/dist/profiler/index.js +4 -4
- package/dist/provenance/index.cjs +46 -48
- package/dist/provenance/index.cjs.map +1 -1
- package/dist/provenance/index.d.cts +7 -7
- package/dist/provenance/index.d.ts +7 -7
- package/dist/provenance/index.js +12 -14
- package/dist/provenance/index.js.map +1 -1
- package/dist/schema/index.cjs +50 -48
- package/dist/schema/index.d.cts +9 -16
- package/dist/schema/index.d.ts +9 -16
- package/dist/schema/index.js +23 -21
- package/dist/{searchable-DLWEfC4a.d.ts → searchable-9OQoPuRs.d.ts} +1 -2
- package/dist/{searchable-CIZL8Hyw.d.cts → searchable-CIje5XYD.d.cts} +1 -2
- package/dist/{sqlite-DY0WODUK.d.cts → sqlite-DerU5tc7.d.ts} +2029 -347
- package/dist/{sqlite-L-VIRzqA.d.ts → sqlite-DitnISa9.d.cts} +2029 -347
- package/dist/{store-view-66p92IPi.d.ts → store-DawaWWjJ.d.ts} +1280 -767
- package/dist/{store-view-A85FFRnk.d.cts → store-RwTJx8LX.d.cts} +1280 -767
- package/dist/{temporal-BNbjXqer.d.cts → temporal-Bn-Fi8FJ.d.cts} +1 -1
- package/dist/{temporal-Bob6Nfbp.d.ts → temporal-BtM4UALv.d.ts} +1 -1
- package/dist/{types-DeORZhxn.d.cts → types-CoIx8HX5.d.cts} +1 -1
- package/dist/{types-Ch9a0Dx6.d.ts → types-HkveCCx0.d.cts} +726 -5
- package/dist/{types-Ch9a0Dx6.d.cts → types-HkveCCx0.d.ts} +726 -5
- package/dist/{types-ClCzT-dT.d.ts → types-KFfk-8Ah.d.ts} +1 -1
- package/dist/{where-DPw52ksb.d.cts → where--fk7_0kv.d.cts} +1 -1
- package/dist/{where-kWUZPvEA.d.ts → where-ws5hf-Ov.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-2L54C2C2.js +0 -144
- package/dist/chunk-2L54C2C2.js.map +0 -1
- package/dist/chunk-35S6P5ZU.js +0 -27
- package/dist/chunk-35S6P5ZU.js.map +0 -1
- package/dist/chunk-42PYUGLS.js.map +0 -1
- package/dist/chunk-4GUBTVPV.js.map +0 -1
- package/dist/chunk-4GUTQPVO.js.map +0 -1
- package/dist/chunk-4MB3AQAQ.js.map +0 -1
- package/dist/chunk-4MEWSUVM.cjs.map +0 -1
- package/dist/chunk-4QIKLIGG.js.map +0 -1
- package/dist/chunk-4SZ6XPTG.cjs +0 -12
- package/dist/chunk-55ITBQJI.js.map +0 -1
- package/dist/chunk-5EKPX6QU.js.map +0 -1
- package/dist/chunk-6RYPD3NJ.cjs +0 -1282
- package/dist/chunk-6RYPD3NJ.cjs.map +0 -1
- package/dist/chunk-764JHTLT.cjs +0 -15
- package/dist/chunk-764JHTLT.cjs.map +0 -1
- package/dist/chunk-ACSVZPK7.cjs.map +0 -1
- package/dist/chunk-B3F2D3SP.cjs +0 -12
- package/dist/chunk-BGYJW37L.js.map +0 -1
- package/dist/chunk-BNS75YNF.cjs.map +0 -1
- package/dist/chunk-C4F7VJ5D.cjs.map +0 -1
- package/dist/chunk-CBKG6HEP.js +0 -1263
- package/dist/chunk-CBKG6HEP.js.map +0 -1
- package/dist/chunk-CPEL3YIR.cjs.map +0 -1
- package/dist/chunk-D54WH24V.cjs.map +0 -1
- package/dist/chunk-D56XG4EI.cjs.map +0 -1
- package/dist/chunk-D7PG5D5K.js.map +0 -1
- package/dist/chunk-DI74SMXS.cjs +0 -29
- package/dist/chunk-DI74SMXS.cjs.map +0 -1
- package/dist/chunk-DK2S42XB.js +0 -77
- package/dist/chunk-DK2S42XB.js.map +0 -1
- package/dist/chunk-DRACN6XG.js +0 -27
- package/dist/chunk-DRACN6XG.js.map +0 -1
- package/dist/chunk-DXEEHSGN.js.map +0 -1
- package/dist/chunk-EKFUG4G7.cjs.map +0 -1
- package/dist/chunk-EQ7JKLZO.cjs +0 -157
- package/dist/chunk-EQ7JKLZO.cjs.map +0 -1
- package/dist/chunk-FJMPR3OH.cjs.map +0 -1
- package/dist/chunk-FLEQ2HBK.js.map +0 -1
- package/dist/chunk-FQ7ZPOTZ.js.map +0 -1
- package/dist/chunk-G6Q5UM7U.js.map +0 -1
- package/dist/chunk-GYA4JRP5.js.map +0 -1
- package/dist/chunk-H7VE3FL4.cjs.map +0 -1
- package/dist/chunk-ID4WXTKL.js.map +0 -1
- package/dist/chunk-ISLPNELU.js.map +0 -1
- package/dist/chunk-ITE4IXAK.js +0 -25
- package/dist/chunk-ITE4IXAK.js.map +0 -1
- package/dist/chunk-IX64T5OL.cjs.map +0 -1
- package/dist/chunk-J2ICGNHO.cjs.map +0 -1
- package/dist/chunk-J7LXTUTP.cjs.map +0 -1
- package/dist/chunk-JQXSZHF2.cjs.map +0 -1
- package/dist/chunk-JXUTCSXX.cjs.map +0 -1
- package/dist/chunk-KCO5EFJU.js +0 -79
- package/dist/chunk-KCO5EFJU.js.map +0 -1
- package/dist/chunk-KKYELPZ2.cjs +0 -83
- package/dist/chunk-KKYELPZ2.cjs.map +0 -1
- package/dist/chunk-KMXWZLQX.cjs.map +0 -1
- package/dist/chunk-MIJKEVV7.js.map +0 -1
- package/dist/chunk-NAAMUYMS.cjs.map +0 -1
- package/dist/chunk-P7GTYOLB.cjs.map +0 -1
- package/dist/chunk-PVUI6KGR.js.map +0 -1
- package/dist/chunk-Q6EDCUXV.js.map +0 -1
- package/dist/chunk-QB6VMOJ2.cjs.map +0 -1
- package/dist/chunk-QC4MCOFV.cjs +0 -83
- package/dist/chunk-QC4MCOFV.cjs.map +0 -1
- package/dist/chunk-QMQLUA66.js +0 -12
- package/dist/chunk-QMQLUA66.js.map +0 -1
- package/dist/chunk-QRNYDV5Z.js.map +0 -1
- package/dist/chunk-RFRM3Q5K.js.map +0 -1
- package/dist/chunk-RUQS6M7G.js.map +0 -1
- package/dist/chunk-S4KQ5LV4.js.map +0 -1
- package/dist/chunk-SJDMVITW.cjs.map +0 -1
- package/dist/chunk-SNXVDZAJ.js.map +0 -1
- package/dist/chunk-SVJ5GEXW.cjs.map +0 -1
- package/dist/chunk-TDXIBCGY.cjs.map +0 -1
- package/dist/chunk-TKORQCG4.js.map +0 -1
- package/dist/chunk-TKP5T34P.js.map +0 -1
- package/dist/chunk-TRF4EBJT.cjs +0 -30
- package/dist/chunk-TRF4EBJT.cjs.map +0 -1
- package/dist/chunk-UCQ3BFSY.cjs.map +0 -1
- package/dist/chunk-UR7W5YQK.js.map +0 -1
- package/dist/chunk-V34A6R5V.js +0 -134
- package/dist/chunk-V34A6R5V.js.map +0 -1
- package/dist/chunk-WDAVPX46.js +0 -81
- package/dist/chunk-WDAVPX46.js.map +0 -1
- package/dist/chunk-WDBXJOU5.cjs.map +0 -1
- package/dist/chunk-YDWLUT5V.cjs.map +0 -1
- package/dist/chunk-YOALGKRE.cjs.map +0 -1
- package/dist/chunk-Z3WO6MND.cjs.map +0 -1
- package/dist/chunk-ZDH3DX3C.cjs +0 -30
- package/dist/chunk-ZDH3DX3C.cjs.map +0 -1
- package/dist/chunk-ZI6VQSZA.cjs.map +0 -1
- package/dist/chunk-ZTAJL4DT.cjs +0 -85
- package/dist/chunk-ZTAJL4DT.cjs.map +0 -1
- package/dist/define-graph-BGrJahvp.d.ts +0 -173
- package/dist/define-graph-alREY2wj.d.cts +0 -173
|
@@ -1,47 +1,45 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
5
|
-
var
|
|
6
|
-
require('../chunk-
|
|
7
|
-
var
|
|
8
|
-
require('../chunk-
|
|
9
|
-
require('../chunk-
|
|
10
|
-
require('../chunk-
|
|
11
|
-
require('../chunk-
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
var
|
|
15
|
-
require('../chunk-
|
|
16
|
-
var
|
|
17
|
-
require('../chunk-
|
|
18
|
-
var
|
|
19
|
-
require('../chunk-
|
|
20
|
-
require('../chunk-
|
|
21
|
-
require('../chunk-
|
|
22
|
-
require('../chunk-IX64T5OL.cjs');
|
|
3
|
+
var chunkXDF2UPEQ_cjs = require('../chunk-XDF2UPEQ.cjs');
|
|
4
|
+
require('../chunk-YAAM3M2S.cjs');
|
|
5
|
+
var chunkONU3HIED_cjs = require('../chunk-ONU3HIED.cjs');
|
|
6
|
+
require('../chunk-7GT72YHH.cjs');
|
|
7
|
+
var chunkTTAITEPJ_cjs = require('../chunk-TTAITEPJ.cjs');
|
|
8
|
+
var chunkN3257XE6_cjs = require('../chunk-N3257XE6.cjs');
|
|
9
|
+
var chunkNK5Q7UNE_cjs = require('../chunk-NK5Q7UNE.cjs');
|
|
10
|
+
var chunkXNLIZYRZ_cjs = require('../chunk-XNLIZYRZ.cjs');
|
|
11
|
+
var chunkXMQSEJCF_cjs = require('../chunk-XMQSEJCF.cjs');
|
|
12
|
+
var chunkPWLJ77UV_cjs = require('../chunk-PWLJ77UV.cjs');
|
|
13
|
+
require('../chunk-BSFJMMV3.cjs');
|
|
14
|
+
var chunkNFCVHQ5P_cjs = require('../chunk-NFCVHQ5P.cjs');
|
|
15
|
+
var chunkXBYVV3MP_cjs = require('../chunk-XBYVV3MP.cjs');
|
|
16
|
+
var chunkCXBHOOIQ_cjs = require('../chunk-CXBHOOIQ.cjs');
|
|
17
|
+
var chunkE4WNQBEF_cjs = require('../chunk-E4WNQBEF.cjs');
|
|
18
|
+
var chunkQ7Q4WSLJ_cjs = require('../chunk-Q7Q4WSLJ.cjs');
|
|
19
|
+
require('../chunk-62ZP23AW.cjs');
|
|
20
|
+
require('../chunk-XCAGZAKP.cjs');
|
|
21
|
+
require('../chunk-U63GDNRC.cjs');
|
|
23
22
|
var chunkZY4GXIVN_cjs = require('../chunk-ZY4GXIVN.cjs');
|
|
24
23
|
require('../chunk-NAUA4PW5.cjs');
|
|
25
|
-
require('../chunk-
|
|
26
|
-
require('../chunk-
|
|
27
|
-
require('../chunk-
|
|
28
|
-
require('../chunk-
|
|
29
|
-
var chunk764JHTLT_cjs = require('../chunk-764JHTLT.cjs');
|
|
24
|
+
require('../chunk-4UGOKMI5.cjs');
|
|
25
|
+
var chunkVCRRKBLN_cjs = require('../chunk-VCRRKBLN.cjs');
|
|
26
|
+
require('../chunk-7EO3TCQB.cjs');
|
|
27
|
+
require('../chunk-RT5ZY4XA.cjs');
|
|
30
28
|
require('../chunk-HAHNRASW.cjs');
|
|
31
|
-
var
|
|
32
|
-
require('../chunk-
|
|
33
|
-
require('../chunk-
|
|
34
|
-
require('../chunk-
|
|
35
|
-
|
|
36
|
-
require('../chunk-
|
|
29
|
+
var chunk7BQXPCGN_cjs = require('../chunk-7BQXPCGN.cjs');
|
|
30
|
+
var chunkXUO3KQFO_cjs = require('../chunk-XUO3KQFO.cjs');
|
|
31
|
+
require('../chunk-LBJKZXDE.cjs');
|
|
32
|
+
var chunkNI72YOJB_cjs = require('../chunk-NI72YOJB.cjs');
|
|
33
|
+
require('../chunk-A7J2YDDI.cjs');
|
|
34
|
+
var chunkN66HCGCY_cjs = require('../chunk-N66HCGCY.cjs');
|
|
37
35
|
var zod = require('zod');
|
|
38
36
|
|
|
39
37
|
// src/graph-merge/canonical-props.ts
|
|
40
38
|
function canonicalizeProps(props) {
|
|
41
|
-
return JSON.stringify(props,
|
|
39
|
+
return JSON.stringify(props, chunkPWLJ77UV_cjs.sortedReplacer);
|
|
42
40
|
}
|
|
43
41
|
function canonicalValueKey(value) {
|
|
44
|
-
return JSON.stringify(value,
|
|
42
|
+
return JSON.stringify(value, chunkPWLJ77UV_cjs.sortedReplacer);
|
|
45
43
|
}
|
|
46
44
|
function edgeStateSignature(edge) {
|
|
47
45
|
return JSON.stringify([
|
|
@@ -102,8 +100,834 @@ function compareMergeKeys(left, right) {
|
|
|
102
100
|
return leftKind < rightKind ? -1 : leftKind > rightKind ? 1 : 0;
|
|
103
101
|
}
|
|
104
102
|
|
|
103
|
+
// src/graph-merge/errors.ts
|
|
104
|
+
var MERGE_ERROR_CODES = {
|
|
105
|
+
merge: "GRAPH_MERGE_ERROR",
|
|
106
|
+
invalidOptions: "GRAPH_MERGE_INVALID_OPTIONS",
|
|
107
|
+
branch: "GRAPH_MERGE_BRANCH_ERROR",
|
|
108
|
+
similarityUnavailable: "GRAPH_MERGE_SIMILARITY_UNAVAILABLE",
|
|
109
|
+
conflict: "GRAPH_MERGE_CONFLICT",
|
|
110
|
+
identityConflict: "GRAPH_MERGE_IDENTITY_CONFLICT",
|
|
111
|
+
baseVersionMismatch: "GRAPH_MERGE_BASE_VERSION_MISMATCH"
|
|
112
|
+
};
|
|
113
|
+
function toTypeGraphErrorOptions(category, options) {
|
|
114
|
+
return {
|
|
115
|
+
category,
|
|
116
|
+
...options.details === void 0 ? {} : { details: options.details },
|
|
117
|
+
...options.suggestion === void 0 ? {} : { suggestion: options.suggestion },
|
|
118
|
+
...options.cause === void 0 ? {} : { cause: options.cause }
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
var MergeError = class extends chunkNI72YOJB_cjs.TypeGraphError {
|
|
122
|
+
static errorCategory = "system";
|
|
123
|
+
constructor(message, options = {}) {
|
|
124
|
+
const errorClass = new.target;
|
|
125
|
+
super(
|
|
126
|
+
message,
|
|
127
|
+
MERGE_ERROR_CODES.merge,
|
|
128
|
+
toTypeGraphErrorOptions(errorClass.errorCategory, options)
|
|
129
|
+
);
|
|
130
|
+
this.name = "MergeError";
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
var InvalidMergeOptionsError = class extends MergeError {
|
|
134
|
+
static errorCategory = "user";
|
|
135
|
+
code = MERGE_ERROR_CODES.invalidOptions;
|
|
136
|
+
constructor(message, options = {}) {
|
|
137
|
+
super(message, options);
|
|
138
|
+
this.name = "InvalidMergeOptionsError";
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
var BranchError = class extends chunkNI72YOJB_cjs.TypeGraphError {
|
|
142
|
+
constructor(message, options = {}) {
|
|
143
|
+
super(
|
|
144
|
+
message,
|
|
145
|
+
MERGE_ERROR_CODES.branch,
|
|
146
|
+
toTypeGraphErrorOptions("system", options)
|
|
147
|
+
);
|
|
148
|
+
this.name = "BranchError";
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
var SimilarityUnavailableError = class extends MergeError {
|
|
152
|
+
code = MERGE_ERROR_CODES.similarityUnavailable;
|
|
153
|
+
constructor(message, options = {}) {
|
|
154
|
+
super(message, {
|
|
155
|
+
...options,
|
|
156
|
+
suggestion: options.suggestion ?? "Pass MergeOptions.embedder (a local model), or use a fulltext/custom similarity strategy."
|
|
157
|
+
});
|
|
158
|
+
this.name = "SimilarityUnavailableError";
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
var MergeConflictError = class extends MergeError {
|
|
162
|
+
code = MERGE_ERROR_CODES.conflict;
|
|
163
|
+
constructor(message, options = {}) {
|
|
164
|
+
super(message, options);
|
|
165
|
+
this.name = "MergeConflictError";
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
var IdentityMergeConflictError = class extends MergeError {
|
|
169
|
+
code = MERGE_ERROR_CODES.identityConflict;
|
|
170
|
+
constructor(message, options = {}) {
|
|
171
|
+
super(message, options);
|
|
172
|
+
this.name = "IdentityMergeConflictError";
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
var BaseVersionMismatchError = class extends MergeError {
|
|
176
|
+
code = MERGE_ERROR_CODES.baseVersionMismatch;
|
|
177
|
+
constructor(message, options = {}) {
|
|
178
|
+
super(message, {
|
|
179
|
+
...options,
|
|
180
|
+
suggestion: options.suggestion ?? "Re-branch from the current target so the branch base matches before merging."
|
|
181
|
+
});
|
|
182
|
+
this.name = "BaseVersionMismatchError";
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
function describeCause(cause) {
|
|
186
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/graph-merge/union-find.ts
|
|
190
|
+
var UnionFind = class {
|
|
191
|
+
constructor(compare) {
|
|
192
|
+
this.compare = compare;
|
|
193
|
+
}
|
|
194
|
+
compare;
|
|
195
|
+
parent = /* @__PURE__ */ new Map();
|
|
196
|
+
/** Adds `value` as its own singleton set if it is not already present. */
|
|
197
|
+
add(value) {
|
|
198
|
+
if (!this.parent.has(value)) {
|
|
199
|
+
this.parent.set(value, value);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/** Returns the representative of `value`'s set, compressing the path to it. */
|
|
203
|
+
find(value) {
|
|
204
|
+
this.add(value);
|
|
205
|
+
let root = value;
|
|
206
|
+
while (this.parent.get(root) !== root) {
|
|
207
|
+
root = chunkN66HCGCY_cjs.requireDefined(this.parent.get(root));
|
|
208
|
+
}
|
|
209
|
+
let cursor = value;
|
|
210
|
+
while (cursor !== root) {
|
|
211
|
+
const next = chunkN66HCGCY_cjs.requireDefined(this.parent.get(cursor));
|
|
212
|
+
this.parent.set(cursor, root);
|
|
213
|
+
cursor = next;
|
|
214
|
+
}
|
|
215
|
+
return root;
|
|
216
|
+
}
|
|
217
|
+
/** Merges the sets of `left` and `right`; the `compare`-minimal root wins. */
|
|
218
|
+
union(left, right) {
|
|
219
|
+
const leftRoot = this.find(left);
|
|
220
|
+
const rightRoot = this.find(right);
|
|
221
|
+
if (leftRoot === rightRoot) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (this.compare(leftRoot, rightRoot) <= 0) {
|
|
225
|
+
this.parent.set(rightRoot, leftRoot);
|
|
226
|
+
} else {
|
|
227
|
+
this.parent.set(leftRoot, rightRoot);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/** Every value seen by {@link add}/{@link find}/{@link union}, insertion order. */
|
|
231
|
+
members() {
|
|
232
|
+
return [...this.parent.keys()];
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// src/graph-merge/merge-identity.ts
|
|
237
|
+
function endpointTuple(assertion) {
|
|
238
|
+
return [assertion.a.kind, assertion.a.id, assertion.b.kind, assertion.b.id];
|
|
239
|
+
}
|
|
240
|
+
function identityEndpointKey(assertion) {
|
|
241
|
+
return chunkXNLIZYRZ_cjs.encodeTupleKey(endpointTuple(assertion));
|
|
242
|
+
}
|
|
243
|
+
function identitySemanticKey(assertion) {
|
|
244
|
+
return chunkXNLIZYRZ_cjs.identityAssertionSemanticKey(
|
|
245
|
+
assertion.relation,
|
|
246
|
+
assertion.a,
|
|
247
|
+
assertion.b
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
function compareIdentitySurvivors(left, right) {
|
|
251
|
+
const byValidity = chunkXMQSEJCF_cjs.compareCodePoints(left.validFrom, right.validFrom);
|
|
252
|
+
return byValidity === 0 ? chunkXMQSEJCF_cjs.compareCodePoints(left.id, right.id) : byValidity;
|
|
253
|
+
}
|
|
254
|
+
var DUPLICATE_IDENTITY_ASSERTION_DROP_REASON = "identity:duplicate-assertion";
|
|
255
|
+
var REDUNDANT_IDENTITY_ASSERTION_DROP_REASON = "identity:endpoints-collapsed";
|
|
256
|
+
function droppedIdentityAssertion(assertion, reason) {
|
|
257
|
+
return { kind: "identity", id: assertion.id, reason };
|
|
258
|
+
}
|
|
259
|
+
function dedupeIdentityAssertions(assertions, committedIds) {
|
|
260
|
+
const survivorBySemantic = /* @__PURE__ */ new Map();
|
|
261
|
+
const dropped = [];
|
|
262
|
+
for (const assertion of assertions) {
|
|
263
|
+
const key = identitySemanticKey(assertion);
|
|
264
|
+
const previous = survivorBySemantic.get(key);
|
|
265
|
+
if (previous === void 0) {
|
|
266
|
+
survivorBySemantic.set(key, assertion);
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const assertionCommitted = committedIds.has(assertion.id);
|
|
270
|
+
const previousCommitted = committedIds.has(previous.id);
|
|
271
|
+
const [survivor, loser] = assertionCommitted === previousCommitted ? compareIdentitySurvivors(assertion, previous) < 0 ? [assertion, previous] : [previous, assertion] : assertionCommitted ? [assertion, previous] : [previous, assertion];
|
|
272
|
+
survivorBySemantic.set(key, survivor);
|
|
273
|
+
if (loser.id === survivor.id && loser.validFrom === survivor.validFrom && (loser.validTo ?? void 0) === (survivor.validTo ?? void 0)) {
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
dropped.push(
|
|
277
|
+
droppedIdentityAssertion(loser, DUPLICATE_IDENTITY_ASSERTION_DROP_REASON)
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
survivors: [...survivorBySemantic.values()].toSorted(
|
|
282
|
+
(left, right) => chunkXMQSEJCF_cjs.compareCodePoints(identitySemanticKey(left), identitySemanticKey(right))
|
|
283
|
+
),
|
|
284
|
+
dropped
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function assertNoOpposingIdentityRelations(assertions) {
|
|
288
|
+
const byEndpoint = /* @__PURE__ */ new Map();
|
|
289
|
+
for (const assertion of assertions) {
|
|
290
|
+
const key = identityEndpointKey(assertion);
|
|
291
|
+
const group = byEndpoint.get(key) ?? [];
|
|
292
|
+
group.push(assertion);
|
|
293
|
+
byEndpoint.set(key, group);
|
|
294
|
+
}
|
|
295
|
+
for (const [endpoint, group] of byEndpoint) {
|
|
296
|
+
if (new Set(group.map((assertion) => assertion.relation)).size < 2) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
throw new IdentityMergeConflictError(
|
|
300
|
+
"Branches asserted opposing identity relations for one endpoint pair.",
|
|
301
|
+
{ details: { endpoint, assertions: group } }
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function assertNoRetractReassertRace(staging) {
|
|
306
|
+
const retractedBySemantic = /* @__PURE__ */ new Map();
|
|
307
|
+
for (const staged of staging.retractedIdentityAssertions) {
|
|
308
|
+
const key = identitySemanticKey(staged.assertion);
|
|
309
|
+
const retractions = retractedBySemantic.get(key) ?? [];
|
|
310
|
+
retractions.push(staged);
|
|
311
|
+
retractedBySemantic.set(key, retractions);
|
|
312
|
+
}
|
|
313
|
+
for (const staged of staging.newIdentityAssertions) {
|
|
314
|
+
const retractions = retractedBySemantic.get(identitySemanticKey(staged.assertion)) ?? [];
|
|
315
|
+
const selfRetracted = retractions.some(
|
|
316
|
+
(retraction) => retraction.branchId === staged.branchId
|
|
317
|
+
);
|
|
318
|
+
if (selfRetracted) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
const crossBranchRetraction = retractions.find(
|
|
322
|
+
(retraction) => retraction.assertion.id !== staged.assertion.id
|
|
323
|
+
);
|
|
324
|
+
if (crossBranchRetraction !== void 0) {
|
|
325
|
+
throw new IdentityMergeConflictError(
|
|
326
|
+
"Branches contain a retract/reassert race for one identity pair.",
|
|
327
|
+
{
|
|
328
|
+
details: {
|
|
329
|
+
retractedAssertion: crossBranchRetraction.assertion,
|
|
330
|
+
retractedBy: crossBranchRetraction.branchId,
|
|
331
|
+
reassertedAssertion: staged.assertion,
|
|
332
|
+
reassertedBy: staged.branchId
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
var RETRACTION_TARGET_MISMATCH_DROP_REASON = "identity:retraction-target-mismatch";
|
|
340
|
+
var RETRACTION_DELETION_OVERRULED_DROP_REASON = "identity:deletion-overruled";
|
|
341
|
+
var NO_STORED_ASSERTIONS = /* @__PURE__ */ new Map();
|
|
342
|
+
function planIdentityChanges(staging, storedIdentityRowsById) {
|
|
343
|
+
assertNoOpposingIdentityRelations(
|
|
344
|
+
staging.newIdentityAssertions.map((staged) => staged.assertion)
|
|
345
|
+
);
|
|
346
|
+
assertNoRetractReassertRace(staging);
|
|
347
|
+
assertOneIdOneTruth(
|
|
348
|
+
staging.newIdentityAssertions.map((staged) => staged.assertion),
|
|
349
|
+
NO_STORED_ASSERTIONS
|
|
350
|
+
);
|
|
351
|
+
const committedIds = new Set(
|
|
352
|
+
staging.newIdentityAssertions.map((staged) => staged.assertion).filter((assertion) => {
|
|
353
|
+
const stored = storedIdentityRowsById.get(assertion.id);
|
|
354
|
+
return stored !== void 0 && assertionTruthKey(stored) === assertionTruthKey(assertion);
|
|
355
|
+
}).map((assertion) => assertion.id)
|
|
356
|
+
);
|
|
357
|
+
const deduped = dedupeIdentityAssertions(
|
|
358
|
+
staging.newIdentityAssertions.map((staged) => staged.assertion),
|
|
359
|
+
committedIds
|
|
360
|
+
);
|
|
361
|
+
const retractionById = /* @__PURE__ */ new Map();
|
|
362
|
+
for (const staged of staging.retractedIdentityAssertions) {
|
|
363
|
+
const previous = retractionById.get(staged.assertion.id);
|
|
364
|
+
if (previous !== void 0 && assertionIdentityKey(previous) !== assertionIdentityKey(staged.assertion)) {
|
|
365
|
+
throw new IdentityMergeConflictError(
|
|
366
|
+
"One assertion id was staged for retraction with two different identity truths.",
|
|
367
|
+
{
|
|
368
|
+
details: {
|
|
369
|
+
assertionId: staged.assertion.id,
|
|
370
|
+
first: previous,
|
|
371
|
+
second: staged.assertion
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
retractionById.set(staged.assertion.id, staged.assertion);
|
|
377
|
+
}
|
|
378
|
+
const retractions = [];
|
|
379
|
+
const retractionDropped = [];
|
|
380
|
+
for (const [assertionId, retraction] of retractionById) {
|
|
381
|
+
const stored = storedIdentityRowsById.get(assertionId);
|
|
382
|
+
if (stored !== void 0 && stored.validTo === void 0 && assertionIdentityKey(stored) !== assertionIdentityKey(retraction)) {
|
|
383
|
+
retractionDropped.push({
|
|
384
|
+
kind: "identity",
|
|
385
|
+
id: assertionId,
|
|
386
|
+
reason: RETRACTION_TARGET_MISMATCH_DROP_REASON
|
|
387
|
+
});
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
retractions.push(retraction);
|
|
391
|
+
}
|
|
392
|
+
const survivingIds = new Set(
|
|
393
|
+
deduped.survivors.map((survivor) => survivor.id)
|
|
394
|
+
);
|
|
395
|
+
for (const retraction of retractions) {
|
|
396
|
+
if (survivingIds.has(retraction.id)) {
|
|
397
|
+
throw new IdentityMergeConflictError(
|
|
398
|
+
"One assertion id was staged as both a new assertion and a retraction.",
|
|
399
|
+
{ details: { assertionId: retraction.id } }
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
assertions: deduped.survivors,
|
|
405
|
+
retractions: retractions.toSorted(
|
|
406
|
+
(left, right) => chunkXMQSEJCF_cjs.compareCodePoints(left.id, right.id)
|
|
407
|
+
),
|
|
408
|
+
dropped: [...deduped.dropped, ...retractionDropped]
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
function resolveIdentityEndpoint(endpoint, canonicalOf, retypeMap) {
|
|
412
|
+
const key = mergeKeyOf(endpoint);
|
|
413
|
+
const canonical = canonicalOf.get(key) ?? key;
|
|
414
|
+
return {
|
|
415
|
+
kind: retypeMap.get(canonical) ?? kindOf(canonical),
|
|
416
|
+
id: idOf(canonical)
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
function remapIdentityAssertionEndpoints(assertions, canonicalOf, retypeMap, storedRowsById) {
|
|
420
|
+
const remapped = [];
|
|
421
|
+
const dropped = [];
|
|
422
|
+
for (const assertion of assertions) {
|
|
423
|
+
const remappedA = resolveIdentityEndpoint(
|
|
424
|
+
assertion.a,
|
|
425
|
+
canonicalOf,
|
|
426
|
+
retypeMap
|
|
427
|
+
);
|
|
428
|
+
const remappedB = resolveIdentityEndpoint(
|
|
429
|
+
assertion.b,
|
|
430
|
+
canonicalOf,
|
|
431
|
+
retypeMap
|
|
432
|
+
);
|
|
433
|
+
if (mergeKeyOf(remappedA) === mergeKeyOf(remappedB)) {
|
|
434
|
+
if (assertion.relation === "different") {
|
|
435
|
+
throw new IdentityMergeConflictError(
|
|
436
|
+
"Node reconciliation collapsed a different-identity assertion onto one survivor.",
|
|
437
|
+
{ details: { assertion, survivor: remappedA } }
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
dropped.push(
|
|
441
|
+
droppedIdentityAssertion(
|
|
442
|
+
assertion,
|
|
443
|
+
REDUNDANT_IDENTITY_ASSERTION_DROP_REASON
|
|
444
|
+
)
|
|
445
|
+
);
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
const [a, b] = chunkXNLIZYRZ_cjs.normalizeIdentityPair(remappedA, remappedB);
|
|
449
|
+
const result = { ...assertion, a, b };
|
|
450
|
+
const stored = storedRowsById.get(assertion.id);
|
|
451
|
+
if (stored !== void 0 && assertionTruthKey(stored) === assertionTruthKey(assertion) && assertionTruthKey(result) !== assertionTruthKey(assertion)) {
|
|
452
|
+
throw new IdentityMergeConflictError(
|
|
453
|
+
"Node reconciliation moved the endpoints of an assertion already committed on the target; committed identity rows cannot be rewritten by a merge.",
|
|
454
|
+
{
|
|
455
|
+
details: { assertionId: assertion.id, stored, remapped: result },
|
|
456
|
+
suggestion: "Exclude the colliding nodes from entity resolution, or manually retract the committed assertion and re-assert the canonical pair under a new id before merging."
|
|
457
|
+
}
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
remapped.push(result);
|
|
461
|
+
}
|
|
462
|
+
const committedIds = new Set(
|
|
463
|
+
remapped.filter((assertion) => {
|
|
464
|
+
const stored = storedRowsById.get(assertion.id);
|
|
465
|
+
return stored !== void 0 && assertionTruthKey(stored) === assertionTruthKey(assertion);
|
|
466
|
+
}).map((assertion) => assertion.id)
|
|
467
|
+
);
|
|
468
|
+
const deduped = dedupeIdentityAssertions(remapped, committedIds);
|
|
469
|
+
assertNoOpposingIdentityRelations(deduped.survivors);
|
|
470
|
+
return {
|
|
471
|
+
assertions: deduped.survivors,
|
|
472
|
+
dropped: [...dropped, ...deduped.dropped]
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
function assertIdentityEndpointsNotDeleted(assertions, nodeDeletions, retypeMap) {
|
|
476
|
+
const deletedIdentities = /* @__PURE__ */ new Set();
|
|
477
|
+
for (const key of nodeDeletions.keys()) {
|
|
478
|
+
deletedIdentities.add(key);
|
|
479
|
+
const retyped = retypeMap.get(key);
|
|
480
|
+
if (retyped !== void 0) {
|
|
481
|
+
deletedIdentities.add(mergeKey(retyped, idOf(key)));
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
for (const assertion of assertions) {
|
|
485
|
+
for (const endpoint of [assertion.a, assertion.b]) {
|
|
486
|
+
if (!deletedIdentities.has(mergeKeyOf(endpoint))) {
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
throw new IdentityMergeConflictError(
|
|
490
|
+
"A branch asserted an identity relation over a node another branch deleted.",
|
|
491
|
+
{ details: { assertion, deletedEndpoint: endpoint } }
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function assertNoContradictoryIdentityClosure(plannedAssertions, retractions, baseAssertions, deletedNodes, canonicalOf, retypeMap, identityContext, nodeUniverse) {
|
|
497
|
+
const retracted = new Set(retractions);
|
|
498
|
+
const survivesDeletion = (assertion) => !deletedNodes.has(mergeKey(assertion.a.kind, assertion.a.id)) && !deletedNodes.has(mergeKey(assertion.b.kind, assertion.b.id));
|
|
499
|
+
const mergedLedger = [
|
|
500
|
+
...plannedAssertions,
|
|
501
|
+
...baseAssertions.filter(
|
|
502
|
+
(assertion) => !retracted.has(assertion.id) && survivesDeletion(assertion)
|
|
503
|
+
).map((assertion) => ({
|
|
504
|
+
...assertion,
|
|
505
|
+
a: resolveIdentityEndpoint(assertion.a, canonicalOf, retypeMap),
|
|
506
|
+
b: resolveIdentityEndpoint(assertion.b, canonicalOf, retypeMap)
|
|
507
|
+
}))
|
|
508
|
+
];
|
|
509
|
+
const sameClasses = new UnionFind(
|
|
510
|
+
(left, right) => compareMergeKeys(left, right)
|
|
511
|
+
);
|
|
512
|
+
for (const node of nodeUniverse) {
|
|
513
|
+
sameClasses.add(mergeKey(node.kind, node.id));
|
|
514
|
+
}
|
|
515
|
+
for (const assertion of mergedLedger) {
|
|
516
|
+
if (assertion.relation === "same") {
|
|
517
|
+
sameClasses.union(mergeKeyOf(assertion.a), mergeKeyOf(assertion.b));
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
const membersOfClass = (root) => sameClasses.members().filter((member) => sameClasses.find(member) === root).map((member) => ({ kind: kindOf(member), id: idOf(member) })).toSorted(
|
|
521
|
+
(left, right) => compareMergeKeys(mergeKeyOf(left), mergeKeyOf(right))
|
|
522
|
+
);
|
|
523
|
+
const firstDisjointPair = (kinds) => {
|
|
524
|
+
for (const [index, left] of kinds.entries()) {
|
|
525
|
+
for (const right of kinds.slice(index + 1)) {
|
|
526
|
+
if (identityContext.areDisjoint(left, right)) return [left, right];
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return void 0;
|
|
530
|
+
};
|
|
531
|
+
const refsById = /* @__PURE__ */ new Map();
|
|
532
|
+
const addRef = (kind, id) => {
|
|
533
|
+
const keys = refsById.get(id) ?? [];
|
|
534
|
+
keys.push(mergeKey(kind, id));
|
|
535
|
+
refsById.set(id, keys);
|
|
536
|
+
};
|
|
537
|
+
for (const node of nodeUniverse) addRef(node.kind, node.id);
|
|
538
|
+
for (const assertion of mergedLedger) {
|
|
539
|
+
addRef(assertion.a.kind, assertion.a.id);
|
|
540
|
+
addRef(assertion.b.kind, assertion.b.id);
|
|
541
|
+
}
|
|
542
|
+
for (const keys of refsById.values()) {
|
|
543
|
+
const disjointKinds = firstDisjointPair([
|
|
544
|
+
...new Set(keys.map((key) => kindOf(key)))
|
|
545
|
+
]);
|
|
546
|
+
if (disjointKinds === void 0) continue;
|
|
547
|
+
throw new IdentityMergeConflictError(
|
|
548
|
+
"The merged graph would give one id to two ontology-disjoint kinds.",
|
|
549
|
+
{
|
|
550
|
+
details: {
|
|
551
|
+
disjointKinds,
|
|
552
|
+
sharedId: idOf(chunkN66HCGCY_cjs.requireDefined(keys[0]))
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
if (identityContext.sameIdAcrossKinds === "fold") {
|
|
558
|
+
for (const keys of refsById.values()) {
|
|
559
|
+
const [first, ...rest] = keys;
|
|
560
|
+
if (first === void 0) continue;
|
|
561
|
+
for (const other of rest) sameClasses.union(first, other);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
for (const assertion of mergedLedger) {
|
|
565
|
+
if (assertion.relation !== "different") {
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
const root = sameClasses.find(mergeKeyOf(assertion.a));
|
|
569
|
+
if (root !== sameClasses.find(mergeKeyOf(assertion.b))) {
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
throw new IdentityMergeConflictError(
|
|
573
|
+
"The merged identity ledger would assert one pair of nodes is both the same and different.",
|
|
574
|
+
{ details: { assertion, sameClass: membersOfClass(root) } }
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
const kindsByRoot = /* @__PURE__ */ new Map();
|
|
578
|
+
for (const member of sameClasses.members()) {
|
|
579
|
+
const root = sameClasses.find(member);
|
|
580
|
+
const kinds = kindsByRoot.get(root) ?? /* @__PURE__ */ new Set();
|
|
581
|
+
kinds.add(kindOf(member));
|
|
582
|
+
kindsByRoot.set(root, kinds);
|
|
583
|
+
}
|
|
584
|
+
for (const [root, kinds] of kindsByRoot) {
|
|
585
|
+
const disjointKinds = firstDisjointPair([...kinds]);
|
|
586
|
+
if (disjointKinds === void 0) continue;
|
|
587
|
+
throw new IdentityMergeConflictError(
|
|
588
|
+
"The merged identity ledger would join two ontology-disjoint kinds into one class.",
|
|
589
|
+
{ details: { disjointKinds, sameClass: membersOfClass(root) } }
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
async function buildIdentityPeerProbe(target, probedIds, targetPeers, plan, profile) {
|
|
594
|
+
const finalIds = /* @__PURE__ */ new Set([
|
|
595
|
+
...plan.canonicalEntities.filter(
|
|
596
|
+
(entity) => !plan.nodeDeletions.has(mergeKey(entity.kind, entity.canonicalId))
|
|
597
|
+
).map((entity) => entity.canonicalId),
|
|
598
|
+
...plan.identityAssertions.flatMap((assertion) => [
|
|
599
|
+
assertion.a.id,
|
|
600
|
+
assertion.b.id
|
|
601
|
+
])
|
|
602
|
+
]);
|
|
603
|
+
const plannedDeletions = new Set(plan.nodeDeletions.keys());
|
|
604
|
+
const relevantPeers = targetPeers.filter(
|
|
605
|
+
(peer) => finalIds.has(peer.id) && !plannedDeletions.has(mergeKey(peer.kind, peer.id))
|
|
606
|
+
);
|
|
607
|
+
const seedsByKey = /* @__PURE__ */ new Map();
|
|
608
|
+
const addSeed = (kind, id) => {
|
|
609
|
+
seedsByKey.set(mergeKey(kind, id), { kind, id });
|
|
610
|
+
};
|
|
611
|
+
for (const entity of plan.canonicalEntities) {
|
|
612
|
+
const sourceKey = mergeKey(entity.kind, entity.canonicalId);
|
|
613
|
+
if (plan.nodeDeletions.has(sourceKey)) continue;
|
|
614
|
+
addSeed(plan.retypeMap.get(sourceKey) ?? entity.kind, entity.canonicalId);
|
|
615
|
+
}
|
|
616
|
+
for (const assertion of plan.identityAssertions) {
|
|
617
|
+
addSeed(assertion.a.kind, assertion.a.id);
|
|
618
|
+
addSeed(assertion.b.kind, assertion.b.id);
|
|
619
|
+
}
|
|
620
|
+
for (const peer of relevantPeers) addSeed(peer.kind, peer.id);
|
|
621
|
+
const seeds = [...seedsByKey.values()];
|
|
622
|
+
const liveKeys = new Set(
|
|
623
|
+
targetPeers.map((peer) => mergeKey(peer.kind, peer.id)).filter((key) => !plannedDeletions.has(key))
|
|
624
|
+
);
|
|
625
|
+
const snapshot = await snapshotIdentityClasses(
|
|
626
|
+
target,
|
|
627
|
+
seeds,
|
|
628
|
+
liveKeys,
|
|
629
|
+
plannedDeletions
|
|
630
|
+
);
|
|
631
|
+
const memberKeys = /* @__PURE__ */ new Set([
|
|
632
|
+
...seeds.map((seed) => mergeKey(seed.kind, seed.id)),
|
|
633
|
+
...snapshot.groups.flatMap(
|
|
634
|
+
(group) => group.map((member) => mergeKey(member.kind, member.id))
|
|
635
|
+
)
|
|
636
|
+
]);
|
|
637
|
+
const ledger = (await relevantLedgerAssertions(target, memberKeys, chunkTTAITEPJ_cjs.storeBackend(target))).filter(
|
|
638
|
+
(assertion) => !plannedDeletions.has(mergeKey(assertion.a.kind, assertion.a.id)) && !plannedDeletions.has(mergeKey(assertion.b.kind, assertion.b.id))
|
|
639
|
+
);
|
|
640
|
+
return {
|
|
641
|
+
probe: {
|
|
642
|
+
profile,
|
|
643
|
+
plannedDeletions,
|
|
644
|
+
ids: probedIds.filter((id) => finalIds.has(id)),
|
|
645
|
+
observed: new Set(
|
|
646
|
+
relevantPeers.map((peer) => mergeKey(peer.kind, peer.id))
|
|
647
|
+
),
|
|
648
|
+
memberKeys,
|
|
649
|
+
differentFingerprint: differentLedgerFingerprint(ledger),
|
|
650
|
+
classFingerprints: snapshot.fingerprints,
|
|
651
|
+
seeds
|
|
652
|
+
},
|
|
653
|
+
snapshot,
|
|
654
|
+
ledger
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
async function snapshotIdentityClasses(target, seeds, liveKeys, plannedDeletions, txBackend) {
|
|
658
|
+
const classes = await chunkTTAITEPJ_cjs.storeRuntime(target).structuralIdentityClasses(
|
|
659
|
+
seeds,
|
|
660
|
+
txBackend
|
|
661
|
+
);
|
|
662
|
+
const fingerprints = /* @__PURE__ */ new Map();
|
|
663
|
+
const groups = [];
|
|
664
|
+
for (const seed of seeds) {
|
|
665
|
+
const key = mergeKey(seed.kind, seed.id);
|
|
666
|
+
const members = (classes.get(chunkXNLIZYRZ_cjs.identityReferenceKey(seed)) ?? [seed]).filter(
|
|
667
|
+
(member) => !plannedDeletions.has(mergeKey(member.kind, member.id))
|
|
668
|
+
);
|
|
669
|
+
groups.push(members);
|
|
670
|
+
fingerprints.set(key, encodeClassFingerprint(liveKeys.has(key), members));
|
|
671
|
+
}
|
|
672
|
+
return { fingerprints, groups };
|
|
673
|
+
}
|
|
674
|
+
async function relevantLedgerAssertions(target, memberKeys, backend) {
|
|
675
|
+
const current = await chunkTTAITEPJ_cjs.storeRuntime(target).identityAssertionsAtTarget(
|
|
676
|
+
backend,
|
|
677
|
+
"state"
|
|
678
|
+
);
|
|
679
|
+
return current.filter(
|
|
680
|
+
(assertion) => memberKeys.has(mergeKey(assertion.a.kind, assertion.a.id)) || memberKeys.has(mergeKey(assertion.b.kind, assertion.b.id))
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
function differentLedgerFingerprint(assertions) {
|
|
684
|
+
return JSON.stringify(
|
|
685
|
+
assertions.filter((assertion) => assertion.relation === "different").map((assertion) => [assertion.id, ...endpointTuple(assertion)]).toSorted(
|
|
686
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(chunkXNLIZYRZ_cjs.encodeTupleKey(left), chunkXNLIZYRZ_cjs.encodeTupleKey(right))
|
|
687
|
+
)
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
function encodeClassFingerprint(live, members) {
|
|
691
|
+
return JSON.stringify([
|
|
692
|
+
live,
|
|
693
|
+
members.map((member) => [member.kind, member.id]).toSorted(
|
|
694
|
+
([leftKind, leftId], [rightKind, rightId]) => compareMergeKeys(
|
|
695
|
+
mergeKey(leftKind, leftId),
|
|
696
|
+
mergeKey(rightKind, rightId)
|
|
697
|
+
)
|
|
698
|
+
)
|
|
699
|
+
]);
|
|
700
|
+
}
|
|
701
|
+
function assertionTruthKey(assertion) {
|
|
702
|
+
return JSON.stringify([
|
|
703
|
+
assertion.relation,
|
|
704
|
+
...endpointTuple(assertion),
|
|
705
|
+
assertion.validFrom,
|
|
706
|
+
assertion.validTo ?? null
|
|
707
|
+
]);
|
|
708
|
+
}
|
|
709
|
+
function assertionIdentityKey(assertion) {
|
|
710
|
+
return JSON.stringify([
|
|
711
|
+
assertion.relation,
|
|
712
|
+
...endpointTuple(assertion),
|
|
713
|
+
assertion.validFrom
|
|
714
|
+
]);
|
|
715
|
+
}
|
|
716
|
+
function assertOneIdOneTruth(planned, storedById) {
|
|
717
|
+
const plannedById = /* @__PURE__ */ new Map();
|
|
718
|
+
for (const assertion of planned) {
|
|
719
|
+
const previous = plannedById.get(assertion.id);
|
|
720
|
+
if (previous !== void 0 && assertionTruthKey(previous) !== assertionTruthKey(assertion)) {
|
|
721
|
+
throw new IdentityMergeConflictError(
|
|
722
|
+
"One assertion id was staged for two different identity truths.",
|
|
723
|
+
{
|
|
724
|
+
details: {
|
|
725
|
+
assertionId: assertion.id,
|
|
726
|
+
first: previous,
|
|
727
|
+
second: assertion
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
plannedById.set(assertion.id, assertion);
|
|
733
|
+
const stored = storedById.get(assertion.id);
|
|
734
|
+
if (stored !== void 0 && assertionTruthKey(stored) !== assertionTruthKey(assertion)) {
|
|
735
|
+
throw new IdentityMergeConflictError(
|
|
736
|
+
"A staged assertion id already identifies different truth in the target ledger.",
|
|
737
|
+
{ details: { assertionId: assertion.id, staged: assertion, stored } }
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
async function assertPlannedIdentityIdsFresh(target, txBackend, plan) {
|
|
743
|
+
const plannedIds = [
|
|
744
|
+
...plan.identityAssertions.map((assertion) => assertion.id),
|
|
745
|
+
...plan.identityRetractions.map((retraction) => retraction.id)
|
|
746
|
+
];
|
|
747
|
+
if (plannedIds.length === 0) return;
|
|
748
|
+
const storedById = await chunkTTAITEPJ_cjs.storeRuntime(target).identityAssertionRowsByIds(
|
|
749
|
+
plannedIds,
|
|
750
|
+
txBackend
|
|
751
|
+
);
|
|
752
|
+
for (const assertion of plan.identityAssertions) {
|
|
753
|
+
const stored = storedById.get(assertion.id);
|
|
754
|
+
if (stored !== void 0 && assertionTruthKey(stored) !== assertionTruthKey(assertion)) {
|
|
755
|
+
throw new BaseVersionMismatchError(
|
|
756
|
+
"The merge validated its assertion ids as of planning, but a row identifying different truth under a planned id was committed before the commit transaction.",
|
|
757
|
+
{
|
|
758
|
+
details: { assertionId: assertion.id },
|
|
759
|
+
suggestion: "Retry the merge \u2014 the plan is recomputed from current state. A persistent refusal means the branch's assertion id conflicts with target truth and needs manual resolution."
|
|
760
|
+
}
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
for (const retraction of plan.identityRetractions) {
|
|
765
|
+
const stored = storedById.get(retraction.id);
|
|
766
|
+
if (stored !== void 0 && stored.validTo === void 0 && assertionIdentityKey(stored) !== assertionIdentityKey(retraction)) {
|
|
767
|
+
throw new BaseVersionMismatchError(
|
|
768
|
+
"The merge validated each planned retraction against the target row its id identified at planning, but that row's truth changed before the commit transaction.",
|
|
769
|
+
{
|
|
770
|
+
details: { assertionId: retraction.id },
|
|
771
|
+
suggestion: "Retry the merge \u2014 the plan is recomputed from current state."
|
|
772
|
+
}
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
function affectedIdentityClassSeeds(plan, profile) {
|
|
778
|
+
const seedsByKey = /* @__PURE__ */ new Map();
|
|
779
|
+
const addSeed = (kind, id) => {
|
|
780
|
+
const key = mergeKey(kind, id);
|
|
781
|
+
if (plan.nodeDeletions.has(key)) return;
|
|
782
|
+
seedsByKey.set(key, { kind, id });
|
|
783
|
+
};
|
|
784
|
+
for (const assertion of [
|
|
785
|
+
...plan.identityAssertions,
|
|
786
|
+
...plan.identityRetractions
|
|
787
|
+
]) {
|
|
788
|
+
addSeed(assertion.a.kind, assertion.a.id);
|
|
789
|
+
addSeed(assertion.b.kind, assertion.b.id);
|
|
790
|
+
}
|
|
791
|
+
if (profile === "fold") {
|
|
792
|
+
for (const entity of plan.canonicalEntities) {
|
|
793
|
+
const sourceKey = mergeKey(entity.kind, entity.canonicalId);
|
|
794
|
+
if (plan.nodeDeletions.has(sourceKey)) continue;
|
|
795
|
+
addSeed(plan.retypeMap.get(sourceKey) ?? entity.kind, entity.canonicalId);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
return [...seedsByKey.values()];
|
|
799
|
+
}
|
|
800
|
+
async function assertMergedIdentityClassesConsistent(target, txBackend, plan) {
|
|
801
|
+
await chunkTTAITEPJ_cjs.storeRuntime(target).assertIdentityClassesConsistentAtTarget(
|
|
802
|
+
txBackend,
|
|
803
|
+
affectedIdentityClassSeeds(plan, target.graph.identity?.sameIdAcrossKinds)
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
var IDENTITY_ENVIRONMENT_CODES = /* @__PURE__ */ new Set([
|
|
807
|
+
"IDENTITY_MERGE_REQUIRES_PROFILE",
|
|
808
|
+
"IDENTITY_REQUIRES_ATOMIC_BACKEND",
|
|
809
|
+
"IDENTITY_REQUIRES_STATEMENT_EXECUTION",
|
|
810
|
+
"IDENTITY_BIND_BUDGET_TOO_SMALL",
|
|
811
|
+
// Environment/corruption statements — translating one into "re-plan against
|
|
812
|
+
// the current target" would be advice that can never succeed. The applier
|
|
813
|
+
// reaches the last two through the current different-ness probe (see
|
|
814
|
+
// `identity/separation`), which refuses rather than guessing when the derived
|
|
815
|
+
// separation relation is missing or disagrees with the ledger.
|
|
816
|
+
"IDENTITY_NOT_ENABLED",
|
|
817
|
+
"IDENTITY_STORAGE_MISSING",
|
|
818
|
+
"IDENTITY_SCHEMA_CONTRADICTION",
|
|
819
|
+
"IDENTITY_IMPORT_REQUIRES_PROFILE"
|
|
820
|
+
]);
|
|
821
|
+
function identityRefusalCode(error) {
|
|
822
|
+
const detailCode = error.details["code"];
|
|
823
|
+
if (typeof detailCode === "string" && detailCode.startsWith("IDENTITY_")) {
|
|
824
|
+
return detailCode;
|
|
825
|
+
}
|
|
826
|
+
if (error.code.startsWith("IDENTITY_")) return error.code;
|
|
827
|
+
const issues = error.details["issues"];
|
|
828
|
+
if (Array.isArray(issues)) {
|
|
829
|
+
for (const issue of issues) {
|
|
830
|
+
const code = issue["code"];
|
|
831
|
+
if (typeof code === "string" && code.startsWith("IDENTITY_")) {
|
|
832
|
+
return code;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
return void 0;
|
|
837
|
+
}
|
|
838
|
+
function translateIdentityCommitError(error) {
|
|
839
|
+
if (error instanceof MergeError) return error;
|
|
840
|
+
if (!(error instanceof chunkNI72YOJB_cjs.TypeGraphError)) return error;
|
|
841
|
+
const identityCode = identityRefusalCode(error);
|
|
842
|
+
const identityRefusal = error instanceof chunkNI72YOJB_cjs.IdentityContradictionError || error instanceof chunkNI72YOJB_cjs.NodeNotFoundError || identityCode !== void 0 && !IDENTITY_ENVIRONMENT_CODES.has(identityCode);
|
|
843
|
+
if (!identityRefusal) return error;
|
|
844
|
+
return new IdentityMergeConflictError(
|
|
845
|
+
`The identity applier refused the resolved plan inside the commit transaction \u2014 identity truth on the target is incompatible with the plan. Cause: ${describeCause(error)}`,
|
|
846
|
+
{
|
|
847
|
+
cause: error,
|
|
848
|
+
details: { ...identityCode === void 0 ? {} : { identityCode } },
|
|
849
|
+
suggestion: "Retry once \u2014 the plan is recomputed from current state. If the refusal persists, the branches' identity truth conflicts with the target and needs manual resolution (change the branch's assertion, or resolve the target's truth first)."
|
|
850
|
+
}
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
async function assertIdentityPeersStable(target, txBackend, probe, plan) {
|
|
854
|
+
if (probe === void 0) return;
|
|
855
|
+
const live = (await chunkTTAITEPJ_cjs.storeRuntime(target).liveNodesSharingIds(probe.ids, txBackend)).filter((peer) => !probe.plannedDeletions.has(mergeKey(peer.kind, peer.id)));
|
|
856
|
+
const seedKindsById = /* @__PURE__ */ new Map();
|
|
857
|
+
for (const seed of probe.seeds) {
|
|
858
|
+
const kinds = seedKindsById.get(seed.id) ?? /* @__PURE__ */ new Set();
|
|
859
|
+
kinds.add(seed.kind);
|
|
860
|
+
seedKindsById.set(seed.id, kinds);
|
|
861
|
+
}
|
|
862
|
+
const appeared = live.filter(
|
|
863
|
+
(peer) => probe.profile === "fold" || [...seedKindsById.get(peer.id) ?? []].some(
|
|
864
|
+
(kind) => target.registry.areDisjoint(peer.kind, kind)
|
|
865
|
+
)
|
|
866
|
+
).map((peer) => mergeKey(peer.kind, peer.id)).filter((key) => !probe.observed.has(key)).sort((left, right) => compareMergeKeys(left, right));
|
|
867
|
+
if (appeared.length > 0) {
|
|
868
|
+
throw new BaseVersionMismatchError(
|
|
869
|
+
`mergeIncremental() simulated identity folding against the target's live same-id peers as of planning, but ${appeared.length} committed row(s) sharing a planned node's id appeared before the commit transaction. Committing the plan could fold nodes into classes the plan never validated.`,
|
|
870
|
+
{ details: { appeared } }
|
|
871
|
+
);
|
|
872
|
+
}
|
|
873
|
+
const { fingerprints: liveFingerprints, groups: liveGroups } = await snapshotIdentityClasses(
|
|
874
|
+
target,
|
|
875
|
+
probe.seeds,
|
|
876
|
+
new Set(live.map((peer) => mergeKey(peer.kind, peer.id))),
|
|
877
|
+
probe.plannedDeletions,
|
|
878
|
+
txBackend
|
|
879
|
+
);
|
|
880
|
+
const drifted = [...probe.classFingerprints].filter(([key, fingerprint]) => liveFingerprints.get(key) !== fingerprint).map(([key]) => key).sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
881
|
+
if (drifted.length > 0) {
|
|
882
|
+
throw new BaseVersionMismatchError(
|
|
883
|
+
`mergeIncremental() validated identity against the classes visible at planning, but the identity class of ${drifted.length} node(s) the plan folds on changed before the commit transaction. Committing the plan could contradict identity truth it never validated.`,
|
|
884
|
+
{ details: { drifted } }
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
const ledger = (await relevantLedgerAssertions(target, probe.memberKeys, txBackend)).filter(
|
|
888
|
+
(assertion) => !probe.plannedDeletions.has(mergeKey(assertion.a.kind, assertion.a.id)) && !probe.plannedDeletions.has(mergeKey(assertion.b.kind, assertion.b.id))
|
|
889
|
+
);
|
|
890
|
+
if (differentLedgerFingerprint(ledger) !== probe.differentFingerprint) {
|
|
891
|
+
throw new BaseVersionMismatchError(
|
|
892
|
+
"mergeIncremental() validated identity against the `different` assertions visible at planning, but that ledger changed before the commit transaction. Committing the plan could contradict identity truth it never validated.",
|
|
893
|
+
{ details: {} }
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
try {
|
|
897
|
+
assertNoContradictoryIdentityClosure(
|
|
898
|
+
plan.identityAssertions,
|
|
899
|
+
plan.identityRetractions.map((retraction) => retraction.id),
|
|
900
|
+
ledger,
|
|
901
|
+
probe.plannedDeletions,
|
|
902
|
+
plan.canonicalOf,
|
|
903
|
+
plan.retypeMap,
|
|
904
|
+
{
|
|
905
|
+
sameIdAcrossKinds: probe.profile,
|
|
906
|
+
areDisjoint: (left, right) => target.registry.areDisjoint(left, right)
|
|
907
|
+
},
|
|
908
|
+
[...probe.seeds, ...liveGroups.flat()]
|
|
909
|
+
);
|
|
910
|
+
} catch (error) {
|
|
911
|
+
if (!(error instanceof IdentityMergeConflictError)) throw error;
|
|
912
|
+
throw new BaseVersionMismatchError(
|
|
913
|
+
"mergeIncremental() validated identity as of planning, but identity truth committed before the commit transaction invalidates the plan. Re-plan against the current target.",
|
|
914
|
+
{ details: { conflict: error.message } }
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
|
|
105
919
|
// src/graph-merge/state-diff.ts
|
|
106
920
|
var ENUMERATION_PAGE_SIZE = 1e3;
|
|
921
|
+
var EXPLICIT_RETRACTION = { kind: "explicit" };
|
|
922
|
+
function validWindowOf(row) {
|
|
923
|
+
return {
|
|
924
|
+
validFrom: chunkQ7Q4WSLJ_cjs.canonicalizeDatabaseTimestamp(row.valid_from),
|
|
925
|
+
validTo: chunkQ7Q4WSLJ_cjs.canonicalizeDatabaseTimestamp(row.valid_to)
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
function windowsDiffer(left, right) {
|
|
929
|
+
return left.validFrom !== right.validFrom || left.validTo !== right.validTo;
|
|
930
|
+
}
|
|
107
931
|
async function enumerateAllNodes(backend, graphId, kind) {
|
|
108
932
|
const collected = [];
|
|
109
933
|
let after;
|
|
@@ -122,7 +946,7 @@ async function enumerateAllNodes(backend, graphId, kind) {
|
|
|
122
946
|
if (page.length < ENUMERATION_PAGE_SIZE) {
|
|
123
947
|
break;
|
|
124
948
|
}
|
|
125
|
-
after =
|
|
949
|
+
after = chunkN66HCGCY_cjs.requireDefined(page.at(-1)).id;
|
|
126
950
|
}
|
|
127
951
|
return collected;
|
|
128
952
|
}
|
|
@@ -144,7 +968,7 @@ async function enumerateAllEdges(backend, graphId, kind) {
|
|
|
144
968
|
if (page.length < ENUMERATION_PAGE_SIZE) {
|
|
145
969
|
break;
|
|
146
970
|
}
|
|
147
|
-
after =
|
|
971
|
+
after = chunkN66HCGCY_cjs.requireDefined(page.at(-1)).id;
|
|
148
972
|
}
|
|
149
973
|
return collected;
|
|
150
974
|
}
|
|
@@ -164,6 +988,7 @@ function diffNodeKind(kind, baseRows, forkRows) {
|
|
|
164
988
|
const created = [];
|
|
165
989
|
const modified = [];
|
|
166
990
|
const deleted = [];
|
|
991
|
+
const windowed = [];
|
|
167
992
|
for (const forkRow of forkRows) {
|
|
168
993
|
if (!isLive(forkRow)) {
|
|
169
994
|
continue;
|
|
@@ -189,6 +1014,16 @@ function diffNodeKind(kind, baseRows, forkRows) {
|
|
|
189
1014
|
row: forkRow
|
|
190
1015
|
});
|
|
191
1016
|
}
|
|
1017
|
+
const baseWindow = validWindowOf(baseRow);
|
|
1018
|
+
const forkWindow = validWindowOf(forkRow);
|
|
1019
|
+
if (windowsDiffer(baseWindow, forkWindow)) {
|
|
1020
|
+
windowed.push({
|
|
1021
|
+
id: forkRow.id,
|
|
1022
|
+
kind,
|
|
1023
|
+
base: baseWindow,
|
|
1024
|
+
fork: forkWindow
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
192
1027
|
}
|
|
193
1028
|
for (const baseRow of baseRows) {
|
|
194
1029
|
if (!isLive(baseRow)) {
|
|
@@ -196,10 +1031,14 @@ function diffNodeKind(kind, baseRows, forkRows) {
|
|
|
196
1031
|
}
|
|
197
1032
|
const forkRow = forkIndex.get(baseRow.id);
|
|
198
1033
|
if (forkRow === void 0 || !isLive(forkRow)) {
|
|
199
|
-
deleted.push({
|
|
1034
|
+
deleted.push({
|
|
1035
|
+
id: baseRow.id,
|
|
1036
|
+
kind,
|
|
1037
|
+
deletedAt: forkRow === void 0 ? void 0 : chunkQ7Q4WSLJ_cjs.canonicalizeDatabaseTimestamp(forkRow.deleted_at)
|
|
1038
|
+
});
|
|
200
1039
|
}
|
|
201
1040
|
}
|
|
202
|
-
return { new: created, modified, deleted };
|
|
1041
|
+
return { new: created, modified, deleted, windowed };
|
|
203
1042
|
}
|
|
204
1043
|
function diffEdgeKind(kind, baseRows, forkRows) {
|
|
205
1044
|
const baseIndex = indexById(baseRows);
|
|
@@ -207,6 +1046,7 @@ function diffEdgeKind(kind, baseRows, forkRows) {
|
|
|
207
1046
|
const created = [];
|
|
208
1047
|
const modified = [];
|
|
209
1048
|
const deleted = [];
|
|
1049
|
+
const windowed = [];
|
|
210
1050
|
for (const forkRow of forkRows) {
|
|
211
1051
|
if (!isLive(forkRow)) {
|
|
212
1052
|
continue;
|
|
@@ -240,6 +1080,22 @@ function diffEdgeKind(kind, baseRows, forkRows) {
|
|
|
240
1080
|
row: forkRow
|
|
241
1081
|
});
|
|
242
1082
|
}
|
|
1083
|
+
const baseWindow = validWindowOf(baseRow);
|
|
1084
|
+
const forkWindow = validWindowOf(forkRow);
|
|
1085
|
+
if (windowsDiffer(baseWindow, forkWindow)) {
|
|
1086
|
+
windowed.push({
|
|
1087
|
+
id: forkRow.id,
|
|
1088
|
+
kind,
|
|
1089
|
+
fromId: forkRow.from_id,
|
|
1090
|
+
toId: forkRow.to_id,
|
|
1091
|
+
fromKind: forkRow.from_kind,
|
|
1092
|
+
toKind: forkRow.to_kind,
|
|
1093
|
+
props: forkProps,
|
|
1094
|
+
baseProps,
|
|
1095
|
+
base: baseWindow,
|
|
1096
|
+
fork: forkWindow
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
243
1099
|
}
|
|
244
1100
|
for (const baseRow of baseRows) {
|
|
245
1101
|
if (!isLive(baseRow)) {
|
|
@@ -250,27 +1106,82 @@ function diffEdgeKind(kind, baseRows, forkRows) {
|
|
|
250
1106
|
deleted.push({ id: baseRow.id, kind });
|
|
251
1107
|
}
|
|
252
1108
|
}
|
|
253
|
-
return { new: created, modified, deleted };
|
|
1109
|
+
return { new: created, modified, deleted, windowed };
|
|
1110
|
+
}
|
|
1111
|
+
function classifyRetraction(assertion, deletedByKey, forkAssertion) {
|
|
1112
|
+
if (forkAssertion !== void 0) {
|
|
1113
|
+
const stamp = forkAssertion.endedBy;
|
|
1114
|
+
if (stamp !== void 0 && deletedByKey.has(mergeKey(stamp.kind, stamp.id))) {
|
|
1115
|
+
return { kind: "cascade", deletedNode: { ...stamp } };
|
|
1116
|
+
}
|
|
1117
|
+
return EXPLICIT_RETRACTION;
|
|
1118
|
+
}
|
|
1119
|
+
for (const endpoint of [assertion.a, assertion.b]) {
|
|
1120
|
+
const deletion = deletedByKey.get(mergeKey(endpoint.kind, endpoint.id));
|
|
1121
|
+
if (deletion !== void 0 && deletion.deletedAt === void 0) {
|
|
1122
|
+
return {
|
|
1123
|
+
kind: "cascade",
|
|
1124
|
+
deletedNode: { kind: deletion.kind, id: deletion.id }
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
return EXPLICIT_RETRACTION;
|
|
1129
|
+
}
|
|
1130
|
+
async function classifyRetractions(forkStore, retracted, deletedNodes) {
|
|
1131
|
+
if (retracted.length === 0 || deletedNodes.length === 0) {
|
|
1132
|
+
return retracted.map((assertion) => ({
|
|
1133
|
+
assertion,
|
|
1134
|
+
cause: EXPLICIT_RETRACTION
|
|
1135
|
+
}));
|
|
1136
|
+
}
|
|
1137
|
+
const deletedByKey = new Map(
|
|
1138
|
+
deletedNodes.map((deletion) => [
|
|
1139
|
+
mergeKey(deletion.kind, deletion.id),
|
|
1140
|
+
deletion
|
|
1141
|
+
])
|
|
1142
|
+
);
|
|
1143
|
+
const forkRowsById = await chunkTTAITEPJ_cjs.storeRuntime(forkStore).identityAssertionRowsByIds(
|
|
1144
|
+
retracted.map((assertion) => assertion.id)
|
|
1145
|
+
);
|
|
1146
|
+
return retracted.map((assertion) => ({
|
|
1147
|
+
assertion,
|
|
1148
|
+
cause: classifyRetraction(
|
|
1149
|
+
assertion,
|
|
1150
|
+
deletedByKey,
|
|
1151
|
+
forkRowsById.get(assertion.id)
|
|
1152
|
+
)
|
|
1153
|
+
}));
|
|
254
1154
|
}
|
|
255
1155
|
function byId(left, right) {
|
|
256
|
-
return
|
|
1156
|
+
return chunkXMQSEJCF_cjs.compareStrings(left.id, right.id);
|
|
257
1157
|
}
|
|
258
1158
|
async function diffAgainstBase(baseStore, forkStore, captureForkState = true) {
|
|
259
1159
|
const graph = baseStore.graph;
|
|
260
|
-
const nodeKinds =
|
|
261
|
-
const edgeKinds =
|
|
1160
|
+
const nodeKinds = chunkCXBHOOIQ_cjs.getNodeKinds(graph);
|
|
1161
|
+
const edgeKinds = chunkCXBHOOIQ_cjs.getEdgeKinds(graph);
|
|
1162
|
+
const [baseIdentity, forkIdentity] = await Promise.all([
|
|
1163
|
+
chunkTTAITEPJ_cjs.storeRuntime(baseStore).readCurrentIdentityAssertions("state"),
|
|
1164
|
+
chunkTTAITEPJ_cjs.storeRuntime(forkStore).readCurrentIdentityAssertions("state")
|
|
1165
|
+
]);
|
|
1166
|
+
const baseIdentityById = new Map(
|
|
1167
|
+
baseIdentity.map((assertion) => [assertion.id, assertion])
|
|
1168
|
+
);
|
|
1169
|
+
const forkIdentityById = new Map(
|
|
1170
|
+
forkIdentity.map((assertion) => [assertion.id, assertion])
|
|
1171
|
+
);
|
|
262
1172
|
const newNodes = [];
|
|
263
1173
|
const modifiedNodes = [];
|
|
264
1174
|
const deletedNodes = [];
|
|
1175
|
+
const windowedNodes = [];
|
|
265
1176
|
const forkNodeVersions = /* @__PURE__ */ new Map();
|
|
266
1177
|
for (const kind of nodeKinds) {
|
|
267
1178
|
const baseRows = await enumerateAllNodes(
|
|
268
|
-
|
|
1179
|
+
chunkTTAITEPJ_cjs.storeBackend(baseStore),
|
|
269
1180
|
baseStore.graphId,
|
|
270
1181
|
kind
|
|
271
1182
|
);
|
|
272
1183
|
const forkRows = await enumerateAllNodes(
|
|
273
|
-
|
|
1184
|
+
chunkTTAITEPJ_cjs.storeBackend(forkStore),
|
|
274
1185
|
forkStore.graphId,
|
|
275
1186
|
kind
|
|
276
1187
|
);
|
|
@@ -289,19 +1200,23 @@ async function diffAgainstBase(baseStore, forkStore, captureForkState = true) {
|
|
|
289
1200
|
for (const entry of delta.deleted) {
|
|
290
1201
|
deletedNodes.push(entry);
|
|
291
1202
|
}
|
|
1203
|
+
for (const entry of delta.windowed) {
|
|
1204
|
+
windowedNodes.push(entry);
|
|
1205
|
+
}
|
|
292
1206
|
}
|
|
293
1207
|
const newEdges = [];
|
|
294
1208
|
const modifiedEdges = [];
|
|
295
1209
|
const deletedEdges = [];
|
|
1210
|
+
const windowedEdges = [];
|
|
296
1211
|
const forkEdgeSignatures = /* @__PURE__ */ new Map();
|
|
297
1212
|
for (const kind of edgeKinds) {
|
|
298
1213
|
const baseRows = await enumerateAllEdges(
|
|
299
|
-
|
|
1214
|
+
chunkTTAITEPJ_cjs.storeBackend(baseStore),
|
|
300
1215
|
baseStore.graphId,
|
|
301
1216
|
kind
|
|
302
1217
|
);
|
|
303
1218
|
const forkRows = await enumerateAllEdges(
|
|
304
|
-
|
|
1219
|
+
chunkTTAITEPJ_cjs.storeBackend(forkStore),
|
|
305
1220
|
forkStore.graphId,
|
|
306
1221
|
kind
|
|
307
1222
|
);
|
|
@@ -330,17 +1245,46 @@ async function diffAgainstBase(baseStore, forkStore, captureForkState = true) {
|
|
|
330
1245
|
for (const entry of delta.deleted) {
|
|
331
1246
|
deletedEdges.push(entry);
|
|
332
1247
|
}
|
|
1248
|
+
for (const entry of delta.windowed) {
|
|
1249
|
+
windowedEdges.push(entry);
|
|
1250
|
+
}
|
|
333
1251
|
}
|
|
1252
|
+
const retractedAssertions = baseIdentity.filter((assertion) => {
|
|
1253
|
+
const fork = forkIdentityById.get(assertion.id);
|
|
1254
|
+
return fork === void 0 || assertionTruthKey(fork) !== assertionTruthKey(assertion);
|
|
1255
|
+
}).toSorted((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id));
|
|
1256
|
+
const classifiedRetractions = await classifyRetractions(
|
|
1257
|
+
forkStore,
|
|
1258
|
+
retractedAssertions,
|
|
1259
|
+
deletedNodes
|
|
1260
|
+
);
|
|
334
1261
|
return {
|
|
335
1262
|
nodes: {
|
|
336
1263
|
new: newNodes.sort((left, right) => byId(left, right)),
|
|
337
1264
|
modified: modifiedNodes.sort((left, right) => byId(left, right)),
|
|
338
|
-
deleted: deletedNodes.sort((left, right) => byId(left, right))
|
|
1265
|
+
deleted: deletedNodes.sort((left, right) => byId(left, right)),
|
|
1266
|
+
windowed: windowedNodes.sort((left, right) => byId(left, right))
|
|
339
1267
|
},
|
|
340
1268
|
edges: {
|
|
341
1269
|
new: newEdges.sort((left, right) => byId(left, right)),
|
|
342
1270
|
modified: modifiedEdges.sort((left, right) => byId(left, right)),
|
|
343
|
-
deleted: deletedEdges.sort((left, right) => byId(left, right))
|
|
1271
|
+
deleted: deletedEdges.sort((left, right) => byId(left, right)),
|
|
1272
|
+
windowed: windowedEdges.sort((left, right) => byId(left, right))
|
|
1273
|
+
},
|
|
1274
|
+
identity: {
|
|
1275
|
+
// Ids present on BOTH sides are compared by COMPLETE truth, not
|
|
1276
|
+
// presence: a fork can hard-delete an assertion's endpoint (physically
|
|
1277
|
+
// removing the row), recreate it, and legally import the same id for
|
|
1278
|
+
// different truth. Presence-only comparison would diff that replacement
|
|
1279
|
+
// as empty and the merge would silently keep the base truth. A shared
|
|
1280
|
+
// id with changed truth surfaces as BOTH retracted (the base row) and
|
|
1281
|
+
// new (the fork row), so planning sees the replacement and can refuse
|
|
1282
|
+
// unsupported id reuse as a typed conflict.
|
|
1283
|
+
new: forkIdentity.filter((assertion) => {
|
|
1284
|
+
const base = baseIdentityById.get(assertion.id);
|
|
1285
|
+
return base === void 0 || assertionTruthKey(base) !== assertionTruthKey(assertion);
|
|
1286
|
+
}).toSorted((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)),
|
|
1287
|
+
retracted: classifiedRetractions
|
|
344
1288
|
},
|
|
345
1289
|
forkNodeVersions,
|
|
346
1290
|
forkEdgeSignatures
|
|
@@ -354,9 +1298,11 @@ function asBranchId(value) {
|
|
|
354
1298
|
function asBaseVersion(value) {
|
|
355
1299
|
return value;
|
|
356
1300
|
}
|
|
1301
|
+
var VALIDITY_END_TARGET_PRECEDENCE = "target";
|
|
357
1302
|
|
|
358
1303
|
// src/graph-merge/base-version.ts
|
|
359
1304
|
var TOKEN_SEPARATOR = "\0";
|
|
1305
|
+
var SCHEMA_VERSION_TAG = "#s";
|
|
360
1306
|
var REVISION_COMPONENT_PREFIX = "revision:";
|
|
361
1307
|
var REVISION_COMPONENT_SEPARATOR = ":";
|
|
362
1308
|
var INITIAL_REVISION = "initial";
|
|
@@ -367,19 +1313,19 @@ async function readActiveSchemaVersion(backend, graphId) {
|
|
|
367
1313
|
}
|
|
368
1314
|
async function computeSchemaComponent(store) {
|
|
369
1315
|
const version = await readActiveSchemaVersion(
|
|
370
|
-
|
|
1316
|
+
chunkTTAITEPJ_cjs.storeBackend(store),
|
|
371
1317
|
store.graphId
|
|
372
1318
|
);
|
|
373
|
-
return
|
|
1319
|
+
return chunkN3257XE6_cjs.computeSchemaHash(chunkN3257XE6_cjs.serializeSchema(store.graph, version));
|
|
374
1320
|
}
|
|
375
1321
|
function byDigestEntry(left, right) {
|
|
376
|
-
const byKind =
|
|
377
|
-
return byKind === 0 ?
|
|
1322
|
+
const byKind = chunkXMQSEJCF_cjs.compareStrings(left.kind, right.kind);
|
|
1323
|
+
return byKind === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.id, right.id) : byKind;
|
|
378
1324
|
}
|
|
379
1325
|
var CONTENT_FINGERPRINT_BYTES = 16;
|
|
380
|
-
async function computeContentComponent(backend, graphId, graph) {
|
|
381
|
-
const nodeKinds =
|
|
382
|
-
const edgeKinds =
|
|
1326
|
+
async function computeContentComponent(backend, graphId, graph, identityAssertions) {
|
|
1327
|
+
const nodeKinds = chunkCXBHOOIQ_cjs.getNodeKinds(graph);
|
|
1328
|
+
const edgeKinds = chunkCXBHOOIQ_cjs.getEdgeKinds(graph);
|
|
383
1329
|
const nodeDigest = [];
|
|
384
1330
|
for (const kind of nodeKinds) {
|
|
385
1331
|
const rows = await enumerateAllNodes(backend, graphId, kind);
|
|
@@ -417,30 +1363,41 @@ async function computeContentComponent(backend, graphId, graph) {
|
|
|
417
1363
|
return chunkZY4GXIVN_cjs.sha256Hex(
|
|
418
1364
|
canonicalizeProps({
|
|
419
1365
|
nodes: nodeDigest.sort((left, right) => byDigestEntry(left, right)),
|
|
420
|
-
edges: edgeDigest.sort((left, right) => byDigestEntry(left, right))
|
|
1366
|
+
edges: edgeDigest.sort((left, right) => byDigestEntry(left, right)),
|
|
1367
|
+
...identityAssertions.length === 0 ? {} : { identity: identityAssertions }
|
|
421
1368
|
}),
|
|
422
1369
|
CONTENT_FINGERPRINT_BYTES
|
|
423
1370
|
);
|
|
424
1371
|
}
|
|
425
1372
|
async function computeBaseVersion(store) {
|
|
426
1373
|
if (store.revisionTrackingEnabled) {
|
|
427
|
-
const [schemaComponent2, origin, revision] = await Promise.all([
|
|
1374
|
+
const [schemaComponent2, origin, revision, activeVersion] = await Promise.all([
|
|
428
1375
|
computeSchemaComponent(store),
|
|
429
1376
|
store.revisionOriginNow(),
|
|
430
|
-
store.revisionNow()
|
|
1377
|
+
store.revisionNow(),
|
|
1378
|
+
readActiveSchemaVersion(chunkTTAITEPJ_cjs.storeBackend(store), store.graphId)
|
|
431
1379
|
]);
|
|
432
1380
|
return asBaseVersion(
|
|
433
|
-
`${schemaComponent2}${TOKEN_SEPARATOR}${revisionComponent(origin, revision)}`
|
|
1381
|
+
`${schemaComponent2}${SCHEMA_VERSION_TAG}${activeVersion}${TOKEN_SEPARATOR}${revisionComponent(origin, revision)}`
|
|
434
1382
|
);
|
|
435
1383
|
}
|
|
436
1384
|
const [schemaComponent, contentComponent] = await Promise.all([
|
|
437
1385
|
computeSchemaComponent(store),
|
|
438
|
-
|
|
1386
|
+
computeStoreContentComponent(store)
|
|
439
1387
|
]);
|
|
440
1388
|
return asBaseVersion(
|
|
441
1389
|
`${schemaComponent}${TOKEN_SEPARATOR}${contentComponent}`
|
|
442
1390
|
);
|
|
443
1391
|
}
|
|
1392
|
+
async function computeStoreContentComponent(store) {
|
|
1393
|
+
const identityAssertions = await chunkTTAITEPJ_cjs.storeRuntime(store).readCurrentIdentityAssertions("state");
|
|
1394
|
+
return computeContentComponent(
|
|
1395
|
+
chunkTTAITEPJ_cjs.storeBackend(store),
|
|
1396
|
+
store.graphId,
|
|
1397
|
+
store.graph,
|
|
1398
|
+
identityAssertions
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
444
1401
|
function revisionComponent(origin, revision) {
|
|
445
1402
|
return `${REVISION_COMPONENT_PREFIX}${origin}${REVISION_COMPONENT_SEPARATOR}${revision ?? INITIAL_REVISION}`;
|
|
446
1403
|
}
|
|
@@ -470,70 +1427,6 @@ function contentComponentOf(version) {
|
|
|
470
1427
|
return separatorIndex === -1 ? version : version.slice(separatorIndex + 1);
|
|
471
1428
|
}
|
|
472
1429
|
|
|
473
|
-
// src/graph-merge/errors.ts
|
|
474
|
-
var MERGE_ERROR_CODES = {
|
|
475
|
-
merge: "GRAPH_MERGE_ERROR",
|
|
476
|
-
branch: "GRAPH_MERGE_BRANCH_ERROR",
|
|
477
|
-
similarityUnavailable: "GRAPH_MERGE_SIMILARITY_UNAVAILABLE",
|
|
478
|
-
conflict: "GRAPH_MERGE_CONFLICT",
|
|
479
|
-
baseVersionMismatch: "GRAPH_MERGE_BASE_VERSION_MISMATCH"
|
|
480
|
-
};
|
|
481
|
-
function toTypeGraphErrorOptions(category, options) {
|
|
482
|
-
return {
|
|
483
|
-
category,
|
|
484
|
-
...options.details === void 0 ? {} : { details: options.details },
|
|
485
|
-
...options.suggestion === void 0 ? {} : { suggestion: options.suggestion },
|
|
486
|
-
...options.cause === void 0 ? {} : { cause: options.cause }
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
var MergeError = class extends chunkC4F7VJ5D_cjs.TypeGraphError {
|
|
490
|
-
constructor(message, options = {}) {
|
|
491
|
-
super(
|
|
492
|
-
message,
|
|
493
|
-
MERGE_ERROR_CODES.merge,
|
|
494
|
-
toTypeGraphErrorOptions("system", options)
|
|
495
|
-
);
|
|
496
|
-
this.name = "MergeError";
|
|
497
|
-
}
|
|
498
|
-
};
|
|
499
|
-
var BranchError = class extends chunkC4F7VJ5D_cjs.TypeGraphError {
|
|
500
|
-
constructor(message, options = {}) {
|
|
501
|
-
super(
|
|
502
|
-
message,
|
|
503
|
-
MERGE_ERROR_CODES.branch,
|
|
504
|
-
toTypeGraphErrorOptions("system", options)
|
|
505
|
-
);
|
|
506
|
-
this.name = "BranchError";
|
|
507
|
-
}
|
|
508
|
-
};
|
|
509
|
-
var SimilarityUnavailableError = class extends MergeError {
|
|
510
|
-
code = MERGE_ERROR_CODES.similarityUnavailable;
|
|
511
|
-
constructor(message, options = {}) {
|
|
512
|
-
super(message, {
|
|
513
|
-
...options,
|
|
514
|
-
suggestion: options.suggestion ?? "Pass MergeOptions.embedder (a local model), or use a fulltext/custom similarity strategy."
|
|
515
|
-
});
|
|
516
|
-
this.name = "SimilarityUnavailableError";
|
|
517
|
-
}
|
|
518
|
-
};
|
|
519
|
-
var MergeConflictError = class extends MergeError {
|
|
520
|
-
code = MERGE_ERROR_CODES.conflict;
|
|
521
|
-
constructor(message, options = {}) {
|
|
522
|
-
super(message, options);
|
|
523
|
-
this.name = "MergeConflictError";
|
|
524
|
-
}
|
|
525
|
-
};
|
|
526
|
-
var BaseVersionMismatchError = class extends MergeError {
|
|
527
|
-
code = MERGE_ERROR_CODES.baseVersionMismatch;
|
|
528
|
-
constructor(message, options = {}) {
|
|
529
|
-
super(message, {
|
|
530
|
-
...options,
|
|
531
|
-
suggestion: options.suggestion ?? "Re-branch from the current target so the branch base matches before merging."
|
|
532
|
-
});
|
|
533
|
-
this.name = "BaseVersionMismatchError";
|
|
534
|
-
}
|
|
535
|
-
};
|
|
536
|
-
|
|
537
1430
|
// src/graph-merge/working-copy.ts
|
|
538
1431
|
var CLONE_IMPORT_BATCH_SIZE = 1e3;
|
|
539
1432
|
function cloneWorkingCopyStrategy(makeBackend) {
|
|
@@ -541,7 +1434,7 @@ function cloneWorkingCopyStrategy(makeBackend) {
|
|
|
541
1434
|
create: async (baseStore) => {
|
|
542
1435
|
const backend = await makeBackend();
|
|
543
1436
|
try {
|
|
544
|
-
const [freshStore] = await
|
|
1437
|
+
const [freshStore] = await chunkXDF2UPEQ_cjs.createStoreWithSchema(
|
|
545
1438
|
baseStore.graph,
|
|
546
1439
|
backend,
|
|
547
1440
|
{
|
|
@@ -550,20 +1443,29 @@ function cloneWorkingCopyStrategy(makeBackend) {
|
|
|
550
1443
|
revisionTracking: baseStore.revisionTrackingEnabled
|
|
551
1444
|
}
|
|
552
1445
|
);
|
|
553
|
-
const
|
|
1446
|
+
const exportOptions = {
|
|
1447
|
+
includeMeta: true,
|
|
1448
|
+
includeTemporal: true,
|
|
1449
|
+
includeDeleted: false,
|
|
1450
|
+
batchSize: CLONE_IMPORT_BATCH_SIZE
|
|
1451
|
+
};
|
|
1452
|
+
const importOptions = {
|
|
1453
|
+
onConflict: "error",
|
|
1454
|
+
onUnknownProperty: "error",
|
|
1455
|
+
validateReferences: true,
|
|
1456
|
+
batchSize: CLONE_IMPORT_BATCH_SIZE
|
|
1457
|
+
};
|
|
1458
|
+
const result = chunkXBYVV3MP_cjs.snapshotExportContention(
|
|
1459
|
+
chunkTTAITEPJ_cjs.storeBackend(baseStore),
|
|
1460
|
+
chunkTTAITEPJ_cjs.storeBackend(freshStore)
|
|
1461
|
+
) === void 0 ? await chunkONU3HIED_cjs.importGraphStream(
|
|
554
1462
|
freshStore,
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
{
|
|
562
|
-
onConflict: "error",
|
|
563
|
-
onUnknownProperty: "error",
|
|
564
|
-
validateReferences: true,
|
|
565
|
-
batchSize: CLONE_IMPORT_BATCH_SIZE
|
|
566
|
-
}
|
|
1463
|
+
chunkONU3HIED_cjs.exportGraphStream(baseStore, exportOptions),
|
|
1464
|
+
importOptions
|
|
1465
|
+
) : await chunkONU3HIED_cjs.importGraph(
|
|
1466
|
+
freshStore,
|
|
1467
|
+
await chunkONU3HIED_cjs.exportGraph(baseStore, exportOptions),
|
|
1468
|
+
importOptions
|
|
567
1469
|
);
|
|
568
1470
|
if (!result.success) {
|
|
569
1471
|
throw new BranchError(
|
|
@@ -587,18 +1489,36 @@ function cloneWorkingCopyStrategy(makeBackend) {
|
|
|
587
1489
|
async function branch(baseStore, makeBackend, options, strategy) {
|
|
588
1490
|
try {
|
|
589
1491
|
const base = await computeBaseVersion(baseStore);
|
|
590
|
-
const id = options?.id ?? asBranchId(
|
|
1492
|
+
const id = options?.id ?? asBranchId(chunkXMQSEJCF_cjs.generateId());
|
|
591
1493
|
const workingCopyStrategy = strategy ?? cloneWorkingCopyStrategy(makeBackend);
|
|
592
1494
|
const store = await workingCopyStrategy.create(baseStore);
|
|
593
|
-
|
|
1495
|
+
const schemaAnchor = await readSchemaAnchor(store);
|
|
1496
|
+
return chunk7BQXPCGN_cjs.ok({
|
|
1497
|
+
id,
|
|
1498
|
+
base,
|
|
1499
|
+
store,
|
|
1500
|
+
...schemaAnchor === void 0 ? { schemaAnchor: void 0 } : { schemaAnchor }
|
|
1501
|
+
});
|
|
594
1502
|
} catch (error) {
|
|
595
|
-
return
|
|
1503
|
+
return chunk7BQXPCGN_cjs.err(
|
|
596
1504
|
new BranchError("Failed to create working-copy branch of base store", {
|
|
597
1505
|
cause: error
|
|
598
1506
|
})
|
|
599
1507
|
);
|
|
600
1508
|
}
|
|
601
1509
|
}
|
|
1510
|
+
async function readSchemaAnchor(store) {
|
|
1511
|
+
try {
|
|
1512
|
+
const schemaRow = await chunkTTAITEPJ_cjs.storeBackend(store).getActiveSchema(store.graphId);
|
|
1513
|
+
return schemaRow === void 0 ? void 0 : { version: schemaRow.version, hash: schemaRow.schema_hash };
|
|
1514
|
+
} catch (error) {
|
|
1515
|
+
try {
|
|
1516
|
+
await chunkTTAITEPJ_cjs.storeBackend(store).close();
|
|
1517
|
+
} catch {
|
|
1518
|
+
}
|
|
1519
|
+
throw error;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
602
1522
|
|
|
603
1523
|
// src/graph-merge/blocking.ts
|
|
604
1524
|
var UNBLOCKED_BUCKET_KEY = "unblocked";
|
|
@@ -611,12 +1531,12 @@ function isUniqueBucketKey(key) {
|
|
|
611
1531
|
function constraintSignature(node, constraint) {
|
|
612
1532
|
const props = node;
|
|
613
1533
|
for (const field of constraint.fields) {
|
|
614
|
-
const value = props
|
|
1534
|
+
const value = chunkN66HCGCY_cjs.readOwnProperty(props, field);
|
|
615
1535
|
if (value === void 0 || value === null) {
|
|
616
1536
|
return void 0;
|
|
617
1537
|
}
|
|
618
1538
|
}
|
|
619
|
-
return `${constraint.name}${KEY_PART_SEPARATOR}${
|
|
1539
|
+
return `${constraint.name}${KEY_PART_SEPARATOR}${chunkE4WNQBEF_cjs.computeUniqueKey(
|
|
620
1540
|
props,
|
|
621
1541
|
constraint.fields,
|
|
622
1542
|
constraint.collation
|
|
@@ -653,12 +1573,12 @@ function blockNodes(newNodes, resolveConfig, uniqueConstraints = []) {
|
|
|
653
1573
|
}
|
|
654
1574
|
}
|
|
655
1575
|
const sortedKeys = [...buckets.keys()].sort(
|
|
656
|
-
(left, right) =>
|
|
1576
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
657
1577
|
);
|
|
658
1578
|
const ordered = /* @__PURE__ */ new Map();
|
|
659
1579
|
for (const key of sortedKeys) {
|
|
660
|
-
const members = [...
|
|
661
|
-
(left, right) =>
|
|
1580
|
+
const members = [...chunkN66HCGCY_cjs.requireDefined(buckets.get(key))].sort(
|
|
1581
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
662
1582
|
);
|
|
663
1583
|
ordered.set(key, members);
|
|
664
1584
|
}
|
|
@@ -675,7 +1595,7 @@ function buildBranchRank(branchOrder, allBranchIds) {
|
|
|
675
1595
|
next += 1;
|
|
676
1596
|
}
|
|
677
1597
|
}
|
|
678
|
-
const remaining = allBranchIds.filter((branchId) => !rank.has(branchId)).sort((left, right) =>
|
|
1598
|
+
const remaining = allBranchIds.filter((branchId) => !rank.has(branchId)).sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
679
1599
|
for (const branchId of remaining) {
|
|
680
1600
|
if (!rank.has(branchId)) {
|
|
681
1601
|
rank.set(branchId, next);
|
|
@@ -685,7 +1605,7 @@ function buildBranchRank(branchOrder, allBranchIds) {
|
|
|
685
1605
|
return rank;
|
|
686
1606
|
}
|
|
687
1607
|
function pickByPriority(values, branchRank) {
|
|
688
|
-
let chosen =
|
|
1608
|
+
let chosen = chunkN66HCGCY_cjs.requireDefined(values[0]);
|
|
689
1609
|
let chosenRank = branchRank.get(chosen.branchId) ?? Number.MAX_SAFE_INTEGER;
|
|
690
1610
|
for (const candidate of values.slice(1)) {
|
|
691
1611
|
const candidateRank = branchRank.get(candidate.branchId) ?? Number.MAX_SAFE_INTEGER;
|
|
@@ -699,7 +1619,7 @@ function pickByPriority(values, branchRank) {
|
|
|
699
1619
|
return chosen.value;
|
|
700
1620
|
}
|
|
701
1621
|
function pickByWeight(values, weights, branchRank) {
|
|
702
|
-
let chosen =
|
|
1622
|
+
let chosen = chunkN66HCGCY_cjs.requireDefined(values[0]);
|
|
703
1623
|
let chosenWeight = weights.get(chosen.branchId) ?? 0;
|
|
704
1624
|
let chosenRank = branchRank.get(chosen.branchId) ?? Number.MAX_SAFE_INTEGER;
|
|
705
1625
|
for (const candidate of values.slice(1)) {
|
|
@@ -726,7 +1646,7 @@ function allValuesEqual(values) {
|
|
|
726
1646
|
if (values.length <= 1) {
|
|
727
1647
|
return true;
|
|
728
1648
|
}
|
|
729
|
-
const first = canonicalValueKey(
|
|
1649
|
+
const first = canonicalValueKey(chunkN66HCGCY_cjs.requireDefined(values[0]).value);
|
|
730
1650
|
return values.every(
|
|
731
1651
|
(candidate) => canonicalValueKey(candidate.value) === first
|
|
732
1652
|
);
|
|
@@ -735,7 +1655,7 @@ function collectConflictingValues(property, contributions) {
|
|
|
735
1655
|
const seen = /* @__PURE__ */ new Set();
|
|
736
1656
|
const values = [];
|
|
737
1657
|
for (const { branchId, props } of contributions) {
|
|
738
|
-
if (!(property
|
|
1658
|
+
if (!chunkN66HCGCY_cjs.hasOwnKey(props, property)) {
|
|
739
1659
|
continue;
|
|
740
1660
|
}
|
|
741
1661
|
const value = props[property];
|
|
@@ -747,8 +1667,8 @@ function collectConflictingValues(property, contributions) {
|
|
|
747
1667
|
values.push({ branchId, value });
|
|
748
1668
|
}
|
|
749
1669
|
return [...values].sort((left, right) => {
|
|
750
|
-
const byBranch =
|
|
751
|
-
return byBranch === 0 ?
|
|
1670
|
+
const byBranch = chunkXMQSEJCF_cjs.compareStrings(left.branchId, right.branchId);
|
|
1671
|
+
return byBranch === 0 ? chunkXMQSEJCF_cjs.compareStrings(
|
|
752
1672
|
canonicalValueKey(left.value),
|
|
753
1673
|
canonicalValueKey(right.value)
|
|
754
1674
|
) : byBranch;
|
|
@@ -808,11 +1728,14 @@ function resolvePropertyUnion(input, context, branchRank) {
|
|
|
808
1728
|
|
|
809
1729
|
// src/graph-merge/canonicalize.ts
|
|
810
1730
|
var BASE_PROVENANCE_BRANCH = asBranchId("__committed_base__");
|
|
1731
|
+
var COMMITTED_TARGET_BRANCH = asBranchId(
|
|
1732
|
+
"__committed_target__"
|
|
1733
|
+
);
|
|
811
1734
|
function pickClusterSurvivor(members, cluster, canonicalOverride, preferKind) {
|
|
812
1735
|
const byKey = (left, right) => compareMergeKeys(mergeKeyOf(left), mergeKeyOf(right));
|
|
813
1736
|
const baseMembers = members.filter((member) => member.origin === "base").sort(byKey);
|
|
814
1737
|
if (baseMembers.length > 0) {
|
|
815
|
-
return
|
|
1738
|
+
return chunkN66HCGCY_cjs.requireDefined(baseMembers[0]);
|
|
816
1739
|
}
|
|
817
1740
|
let canonicalId;
|
|
818
1741
|
if (canonicalOverride !== void 0) {
|
|
@@ -825,26 +1748,26 @@ function pickClusterSurvivor(members, cluster, canonicalOverride, preferKind) {
|
|
|
825
1748
|
const minIdentity = [...cluster.members].sort(
|
|
826
1749
|
(left, right) => compareMergeKeys(left, right)
|
|
827
1750
|
)[0];
|
|
828
|
-
canonicalId = minIdentity === void 0 ?
|
|
1751
|
+
canonicalId = minIdentity === void 0 ? chunkN66HCGCY_cjs.requireDefined(members[0]).id : idOf(minIdentity);
|
|
829
1752
|
}
|
|
830
1753
|
const membersAtId = members.filter((member) => member.id === canonicalId);
|
|
831
1754
|
if (membersAtId.length === 0) {
|
|
832
|
-
return
|
|
1755
|
+
return chunkN66HCGCY_cjs.requireDefined([...members].sort(byKey)[0]);
|
|
833
1756
|
}
|
|
834
1757
|
const kinds = [...new Set(membersAtId.map((member) => member.kind))];
|
|
835
1758
|
const chosenKind = preferKind !== void 0 && kinds.length > 1 ? preferKind(kinds) : void 0;
|
|
836
|
-
return (chosenKind === void 0 ? void 0 : membersAtId.find((member) => member.kind === chosenKind)) ??
|
|
1759
|
+
return (chosenKind === void 0 ? void 0 : membersAtId.find((member) => member.kind === chosenKind)) ?? chunkN66HCGCY_cjs.requireDefined([...membersAtId].sort(byKey)[0]);
|
|
837
1760
|
}
|
|
838
1761
|
function findPreferredMember(members, property, preferredBranchId) {
|
|
839
1762
|
if (preferredBranchId === void 0) {
|
|
840
1763
|
return void 0;
|
|
841
1764
|
}
|
|
842
1765
|
return members.find(
|
|
843
|
-
(member) => member.branchId === preferredBranchId &&
|
|
1766
|
+
(member) => member.branchId === preferredBranchId && chunkN66HCGCY_cjs.hasOwnKey(member.props, property)
|
|
844
1767
|
);
|
|
845
1768
|
}
|
|
846
1769
|
function memberPropertyValue(member, property) {
|
|
847
|
-
if (!(
|
|
1770
|
+
if (!chunkN66HCGCY_cjs.hasOwnKey(member.props, property)) {
|
|
848
1771
|
return void 0;
|
|
849
1772
|
}
|
|
850
1773
|
return member.props[property];
|
|
@@ -860,7 +1783,7 @@ function pickCanonicalPropertyValue(canonicalMember, members, property, values,
|
|
|
860
1783
|
return preferredValue;
|
|
861
1784
|
}
|
|
862
1785
|
const canonicalValue = memberPropertyValue(canonicalMember, property);
|
|
863
|
-
return canonicalValue === void 0 ?
|
|
1786
|
+
return canonicalValue === void 0 ? chunkN66HCGCY_cjs.requireDefined(values[0]).value : canonicalValue;
|
|
864
1787
|
}
|
|
865
1788
|
function unionProperties(canonicalMember, members, context, baseContext, branchRank, preferredBranchId) {
|
|
866
1789
|
const canonicalId = canonicalMember.id;
|
|
@@ -872,10 +1795,10 @@ function unionProperties(canonicalMember, members, context, baseContext, branchR
|
|
|
872
1795
|
propertyNames.add(name);
|
|
873
1796
|
}
|
|
874
1797
|
}
|
|
875
|
-
const props =
|
|
1798
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
876
1799
|
const conflicts = [];
|
|
877
1800
|
for (const property of [...propertyNames].sort(
|
|
878
|
-
(left, right) =>
|
|
1801
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
879
1802
|
)) {
|
|
880
1803
|
const values = collectConflictingValues(property, members);
|
|
881
1804
|
if (values.length === 0) {
|
|
@@ -889,7 +1812,7 @@ function unionProperties(canonicalMember, members, context, baseContext, branchR
|
|
|
889
1812
|
preferredBranchId
|
|
890
1813
|
);
|
|
891
1814
|
const baseInvolved = hasBaseMember && members.some(
|
|
892
|
-
(member) => member.origin === "base" &&
|
|
1815
|
+
(member) => member.origin === "base" && chunkN66HCGCY_cjs.hasOwnKey(member.props, property)
|
|
893
1816
|
);
|
|
894
1817
|
const reportedValues = values.filter(
|
|
895
1818
|
(value2) => value2.branchId !== BASE_PROVENANCE_BRANCH && value2.branchId !== preferredBranchId
|
|
@@ -930,89 +1853,56 @@ function canonicalizeCluster(cluster, members, policy, branchRank, weights, cano
|
|
|
930
1853
|
policy: basePolicy,
|
|
931
1854
|
...weights === void 0 ? {} : { weights }
|
|
932
1855
|
};
|
|
933
|
-
const { props, conflicts } = unionProperties(
|
|
934
|
-
survivor,
|
|
935
|
-
members,
|
|
936
|
-
context,
|
|
937
|
-
baseContext,
|
|
938
|
-
branchRank,
|
|
939
|
-
preferredBranchId
|
|
940
|
-
);
|
|
941
|
-
const memberIds = [
|
|
942
|
-
...new Set(cluster.members.map((member) => idOf(member)))
|
|
943
|
-
].sort((left, right) =>
|
|
944
|
-
const branchOrigins = [
|
|
945
|
-
...new Set(
|
|
946
|
-
members.map((member) => member.branchId).filter(
|
|
947
|
-
(branchId) => branchId !== BASE_PROVENANCE_BRANCH && branchId !== preferredBranchId
|
|
948
|
-
)
|
|
949
|
-
)
|
|
950
|
-
].sort((left, right) =>
|
|
951
|
-
const resolution = {
|
|
952
|
-
canonicalId,
|
|
953
|
-
memberIds,
|
|
954
|
-
kind,
|
|
955
|
-
branchOrigins
|
|
956
|
-
};
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
this.parent.set(value, value);
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
/** Returns the representative of `value`'s set, compressing the path to it. */
|
|
974
|
-
find(value) {
|
|
975
|
-
this.add(value);
|
|
976
|
-
let root = value;
|
|
977
|
-
while (this.parent.get(root) !== root) {
|
|
978
|
-
root = chunk764JHTLT_cjs.requireDefined(this.parent.get(root));
|
|
979
|
-
}
|
|
980
|
-
let cursor = value;
|
|
981
|
-
while (cursor !== root) {
|
|
982
|
-
const next = chunk764JHTLT_cjs.requireDefined(this.parent.get(cursor));
|
|
983
|
-
this.parent.set(cursor, root);
|
|
984
|
-
cursor = next;
|
|
985
|
-
}
|
|
986
|
-
return root;
|
|
987
|
-
}
|
|
988
|
-
/** Merges the sets of `left` and `right`; the `compare`-minimal root wins. */
|
|
989
|
-
union(left, right) {
|
|
990
|
-
const leftRoot = this.find(left);
|
|
991
|
-
const rightRoot = this.find(right);
|
|
992
|
-
if (leftRoot === rightRoot) {
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
|
-
if (this.compare(leftRoot, rightRoot) <= 0) {
|
|
996
|
-
this.parent.set(rightRoot, leftRoot);
|
|
997
|
-
} else {
|
|
998
|
-
this.parent.set(leftRoot, rightRoot);
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
/** Every value seen by {@link add}/{@link find}/{@link union}, insertion order. */
|
|
1002
|
-
members() {
|
|
1003
|
-
return [...this.parent.keys()];
|
|
1004
|
-
}
|
|
1005
|
-
};
|
|
1856
|
+
const { props, conflicts } = unionProperties(
|
|
1857
|
+
survivor,
|
|
1858
|
+
members,
|
|
1859
|
+
context,
|
|
1860
|
+
baseContext,
|
|
1861
|
+
branchRank,
|
|
1862
|
+
preferredBranchId
|
|
1863
|
+
);
|
|
1864
|
+
const memberIds = [
|
|
1865
|
+
...new Set(cluster.members.map((member) => idOf(member)))
|
|
1866
|
+
].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
1867
|
+
const branchOrigins = [
|
|
1868
|
+
...new Set(
|
|
1869
|
+
members.map((member) => member.branchId).filter(
|
|
1870
|
+
(branchId) => branchId !== BASE_PROVENANCE_BRANCH && branchId !== preferredBranchId
|
|
1871
|
+
)
|
|
1872
|
+
)
|
|
1873
|
+
].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
1874
|
+
const resolution = {
|
|
1875
|
+
canonicalId,
|
|
1876
|
+
memberIds,
|
|
1877
|
+
kind,
|
|
1878
|
+
branchOrigins
|
|
1879
|
+
};
|
|
1880
|
+
const windowSource = members.find(
|
|
1881
|
+
(member) => member.branchId === COMMITTED_TARGET_BRANCH && member.kind === kind && member.id === canonicalId
|
|
1882
|
+
) ?? survivor;
|
|
1883
|
+
return {
|
|
1884
|
+
canonicalId,
|
|
1885
|
+
kind,
|
|
1886
|
+
props,
|
|
1887
|
+
resolution,
|
|
1888
|
+
conflicts,
|
|
1889
|
+
...windowSource.validFrom === void 0 ? {} : { validFrom: windowSource.validFrom },
|
|
1890
|
+
...windowSource.validTo === void 0 ? {} : { validTo: windowSource.validTo }
|
|
1891
|
+
};
|
|
1892
|
+
}
|
|
1006
1893
|
|
|
1007
1894
|
// src/graph-merge/closures.ts
|
|
1008
1895
|
var SUB_CLASS_OF_META_EDGE = "subClassOf";
|
|
1009
|
-
var
|
|
1896
|
+
var EQUIVALENCE_META_EDGES = /* @__PURE__ */ new Set([
|
|
1897
|
+
chunkXUO3KQFO_cjs.META_EDGE_EQUIVALENT_TO,
|
|
1898
|
+
chunkXUO3KQFO_cjs.META_EDGE_SAME_AS
|
|
1899
|
+
]);
|
|
1010
1900
|
function buildSubClassClosure(ontology) {
|
|
1011
|
-
const unionFind = new UnionFind(
|
|
1901
|
+
const unionFind = new UnionFind(chunkXMQSEJCF_cjs.compareStrings);
|
|
1012
1902
|
for (const relation of ontology) {
|
|
1013
1903
|
unionFind.add(relation.from);
|
|
1014
1904
|
unionFind.add(relation.to);
|
|
1015
|
-
if (relation.metaEdge
|
|
1905
|
+
if (EQUIVALENCE_META_EDGES.has(relation.metaEdge)) {
|
|
1016
1906
|
unionFind.union(relation.from, relation.to);
|
|
1017
1907
|
}
|
|
1018
1908
|
}
|
|
@@ -1039,7 +1929,7 @@ function buildSubClassClosure(ontology) {
|
|
|
1039
1929
|
relations.push([child, parent]);
|
|
1040
1930
|
}
|
|
1041
1931
|
return {
|
|
1042
|
-
closure:
|
|
1932
|
+
closure: chunk7BQXPCGN_cjs.computeTransitiveClosure(relations),
|
|
1043
1933
|
canonicalOf
|
|
1044
1934
|
};
|
|
1045
1935
|
}
|
|
@@ -1052,7 +1942,7 @@ function isReachable2(closure, from, to) {
|
|
|
1052
1942
|
if (fromRep === toRep) {
|
|
1053
1943
|
return from !== to;
|
|
1054
1944
|
}
|
|
1055
|
-
return
|
|
1945
|
+
return chunk7BQXPCGN_cjs.isReachable(closure.closure, fromRep, toRep);
|
|
1056
1946
|
}
|
|
1057
1947
|
|
|
1058
1948
|
// src/graph-merge/similarity.ts
|
|
@@ -1074,7 +1964,7 @@ function clampScore(value) {
|
|
|
1074
1964
|
return value;
|
|
1075
1965
|
}
|
|
1076
1966
|
function readField(node, field) {
|
|
1077
|
-
return node
|
|
1967
|
+
return chunkN66HCGCY_cjs.readOwnProperty(node, field);
|
|
1078
1968
|
}
|
|
1079
1969
|
function fieldText(node, fields) {
|
|
1080
1970
|
const parts = [];
|
|
@@ -1165,8 +2055,8 @@ function cosineSimilarity(left, right) {
|
|
|
1165
2055
|
let leftMagnitude = 0;
|
|
1166
2056
|
let rightMagnitude = 0;
|
|
1167
2057
|
for (let index = 0; index < left.length; index += 1) {
|
|
1168
|
-
const leftComponent =
|
|
1169
|
-
const rightComponent =
|
|
2058
|
+
const leftComponent = chunkN66HCGCY_cjs.requireDefined(left[index]);
|
|
2059
|
+
const rightComponent = chunkN66HCGCY_cjs.requireDefined(right[index]);
|
|
1170
2060
|
dot += leftComponent * rightComponent;
|
|
1171
2061
|
leftMagnitude += leftComponent * leftComponent;
|
|
1172
2062
|
rightMagnitude += rightComponent * rightComponent;
|
|
@@ -1235,37 +2125,37 @@ function scorePrepared(left, right, strategy, ctx) {
|
|
|
1235
2125
|
switch (strategy.kind) {
|
|
1236
2126
|
case "custom": {
|
|
1237
2127
|
const raw = strategy.score(left.node, right.node);
|
|
1238
|
-
return
|
|
2128
|
+
return chunk7BQXPCGN_cjs.ok(clampScore(raw));
|
|
1239
2129
|
}
|
|
1240
2130
|
case "fulltext": {
|
|
1241
2131
|
if (left.text.length === 0 || right.text.length === 0) {
|
|
1242
|
-
return
|
|
2132
|
+
return chunk7BQXPCGN_cjs.ok(NO_EVIDENCE_SCORE);
|
|
1243
2133
|
}
|
|
1244
|
-
return
|
|
2134
|
+
return chunk7BQXPCGN_cjs.ok(clampScore(diceFromMultisets(left.grams, right.grams)));
|
|
1245
2135
|
}
|
|
1246
2136
|
case "vector": {
|
|
1247
2137
|
if (ctx.embeddings === void 0) {
|
|
1248
|
-
return
|
|
2138
|
+
return chunk7BQXPCGN_cjs.err(embedderUnavailable("vector", ctx));
|
|
1249
2139
|
}
|
|
1250
2140
|
if (left.text.length === 0 || right.text.length === 0) {
|
|
1251
|
-
return
|
|
2141
|
+
return chunk7BQXPCGN_cjs.ok(NO_EVIDENCE_SCORE);
|
|
1252
2142
|
}
|
|
1253
2143
|
const cosine = cosineFromLookup(ctx.embeddings, left.text, right.text);
|
|
1254
|
-
return
|
|
2144
|
+
return chunk7BQXPCGN_cjs.ok(clampScore(cosine));
|
|
1255
2145
|
}
|
|
1256
2146
|
case "hybrid": {
|
|
1257
2147
|
if (ctx.embeddings === void 0) {
|
|
1258
|
-
return
|
|
2148
|
+
return chunk7BQXPCGN_cjs.err(embedderUnavailable("hybrid", ctx));
|
|
1259
2149
|
}
|
|
1260
2150
|
if (left.text.length === 0 || right.text.length === 0) {
|
|
1261
|
-
return
|
|
2151
|
+
return chunk7BQXPCGN_cjs.ok(NO_EVIDENCE_SCORE);
|
|
1262
2152
|
}
|
|
1263
2153
|
const vectorScore = clampScore(
|
|
1264
2154
|
cosineFromLookup(ctx.embeddings, left.text, right.text)
|
|
1265
2155
|
);
|
|
1266
2156
|
const fulltextScore = diceFromMultisets(left.grams, right.grams);
|
|
1267
2157
|
const weights = normalizeHybridWeights(strategy.weights);
|
|
1268
|
-
return
|
|
2158
|
+
return chunk7BQXPCGN_cjs.ok(
|
|
1269
2159
|
clampScore(
|
|
1270
2160
|
weights.vector * vectorScore + weights.fulltext * fulltextScore
|
|
1271
2161
|
)
|
|
@@ -1323,7 +2213,7 @@ function scoreCandidates(input, resolveConfig, ctx, ceilingPolicy, maxComparison
|
|
|
1323
2213
|
}
|
|
1324
2214
|
if (maxComparisonsPerKind !== void 0 && fuzzy.length > maxComparisonsPerKind) {
|
|
1325
2215
|
if (ceilingPolicy === "error") {
|
|
1326
|
-
return
|
|
2216
|
+
return chunk7BQXPCGN_cjs.err(
|
|
1327
2217
|
new MergeError(
|
|
1328
2218
|
`Comparison ceiling exceeded: ${fuzzy.length} candidate pairs > maxComparisonsPerKind ${maxComparisonsPerKind}.`,
|
|
1329
2219
|
{
|
|
@@ -1336,7 +2226,7 @@ function scoreCandidates(input, resolveConfig, ctx, ceilingPolicy, maxComparison
|
|
|
1336
2226
|
)
|
|
1337
2227
|
);
|
|
1338
2228
|
}
|
|
1339
|
-
return
|
|
2229
|
+
return chunk7BQXPCGN_cjs.ok({
|
|
1340
2230
|
edges: [...forced].sort(
|
|
1341
2231
|
(left, right) => compareCandidateEdges(left, right)
|
|
1342
2232
|
),
|
|
@@ -1354,14 +2244,14 @@ function scoreCandidates(input, resolveConfig, ctx, ceilingPolicy, maxComparison
|
|
|
1354
2244
|
const edges = [...forced];
|
|
1355
2245
|
for (const { left, right, a, b } of fuzzy) {
|
|
1356
2246
|
const scored = scorer(a, left, b, right);
|
|
1357
|
-
if (
|
|
1358
|
-
return
|
|
2247
|
+
if (chunk7BQXPCGN_cjs.isErr(scored)) {
|
|
2248
|
+
return chunk7BQXPCGN_cjs.err(scored.error);
|
|
1359
2249
|
}
|
|
1360
2250
|
if (scored.data >= threshold) {
|
|
1361
2251
|
edges.push({ a, b, score: scored.data });
|
|
1362
2252
|
}
|
|
1363
2253
|
}
|
|
1364
|
-
return
|
|
2254
|
+
return chunk7BQXPCGN_cjs.ok({
|
|
1365
2255
|
edges: edges.sort((left, right) => compareCandidateEdges(left, right)),
|
|
1366
2256
|
warnings: []
|
|
1367
2257
|
});
|
|
@@ -1401,8 +2291,8 @@ function buildComponents(edges, nodeIds, edgesSorted = false) {
|
|
|
1401
2291
|
}
|
|
1402
2292
|
clusters.sort(
|
|
1403
2293
|
(left, right) => compareMergeKeys(
|
|
1404
|
-
|
|
1405
|
-
|
|
2294
|
+
chunkN66HCGCY_cjs.requireDefined(left.members[0]),
|
|
2295
|
+
chunkN66HCGCY_cjs.requireDefined(right.members[0])
|
|
1406
2296
|
)
|
|
1407
2297
|
);
|
|
1408
2298
|
return clusters;
|
|
@@ -1415,8 +2305,8 @@ function adjacencyOf(members, edges) {
|
|
|
1415
2305
|
}
|
|
1416
2306
|
for (const edge of edges) {
|
|
1417
2307
|
if (memberSet.has(edge.a) && memberSet.has(edge.b)) {
|
|
1418
|
-
|
|
1419
|
-
|
|
2308
|
+
chunkN66HCGCY_cjs.requireDefined(adjacency.get(edge.a)).add(edge.b);
|
|
2309
|
+
chunkN66HCGCY_cjs.requireDefined(adjacency.get(edge.b)).add(edge.a);
|
|
1420
2310
|
}
|
|
1421
2311
|
}
|
|
1422
2312
|
return adjacency;
|
|
@@ -1431,10 +2321,10 @@ function exceedsDiameter(members, edges, maxDiameter) {
|
|
|
1431
2321
|
const queue = [source];
|
|
1432
2322
|
let head = 0;
|
|
1433
2323
|
while (head < queue.length) {
|
|
1434
|
-
const current =
|
|
2324
|
+
const current = chunkN66HCGCY_cjs.requireDefined(queue[head]);
|
|
1435
2325
|
head += 1;
|
|
1436
|
-
const currentDistance =
|
|
1437
|
-
for (const neighbor of
|
|
2326
|
+
const currentDistance = chunkN66HCGCY_cjs.requireDefined(distance.get(current));
|
|
2327
|
+
for (const neighbor of chunkN66HCGCY_cjs.requireDefined(adjacency.get(current))) {
|
|
1438
2328
|
if (!distance.has(neighbor)) {
|
|
1439
2329
|
const neighborDistance = currentDistance + 1;
|
|
1440
2330
|
if (neighborDistance > maxDiameter) {
|
|
@@ -1518,8 +2408,8 @@ function enforceDiameter(clusters, candidateEdges, clusterMaxDiameter) {
|
|
|
1518
2408
|
}
|
|
1519
2409
|
guarded.sort(
|
|
1520
2410
|
(left, right) => compareMergeKeys(
|
|
1521
|
-
|
|
1522
|
-
|
|
2411
|
+
chunkN66HCGCY_cjs.requireDefined(left.members[0]),
|
|
2412
|
+
chunkN66HCGCY_cjs.requireDefined(right.members[0])
|
|
1523
2413
|
)
|
|
1524
2414
|
);
|
|
1525
2415
|
return guarded;
|
|
@@ -1566,8 +2456,8 @@ function enforceBaseGuard(clusters, candidateEdges, baseIds) {
|
|
|
1566
2456
|
}
|
|
1567
2457
|
result.sort(
|
|
1568
2458
|
(left, right) => compareMergeKeys(
|
|
1569
|
-
|
|
1570
|
-
|
|
2459
|
+
chunkN66HCGCY_cjs.requireDefined(left.members[0]),
|
|
2460
|
+
chunkN66HCGCY_cjs.requireDefined(right.members[0])
|
|
1571
2461
|
)
|
|
1572
2462
|
);
|
|
1573
2463
|
return { clusters: result, events };
|
|
@@ -1576,11 +2466,11 @@ function enforceBaseGuard(clusters, candidateEdges, baseIds) {
|
|
|
1576
2466
|
// src/graph-merge/delete-modify.ts
|
|
1577
2467
|
var DELETED_NODE_DROP_REASON = "delete-modify:deleteWins";
|
|
1578
2468
|
function pickHighestPriorityBranch(branchIds, branchRank) {
|
|
1579
|
-
let chosen =
|
|
2469
|
+
let chosen = chunkN66HCGCY_cjs.requireDefined(branchIds[0]);
|
|
1580
2470
|
let chosenRank = branchRank.get(chosen) ?? Number.MAX_SAFE_INTEGER;
|
|
1581
2471
|
for (const candidate of branchIds.slice(1)) {
|
|
1582
2472
|
const candidateRank = branchRank.get(candidate) ?? Number.MAX_SAFE_INTEGER;
|
|
1583
|
-
if (candidateRank < chosenRank || candidateRank === chosenRank &&
|
|
2473
|
+
if (candidateRank < chosenRank || candidateRank === chosenRank && chunkXMQSEJCF_cjs.compareStrings(candidate, chosen) < 0) {
|
|
1584
2474
|
chosen = candidate;
|
|
1585
2475
|
chosenRank = candidateRank;
|
|
1586
2476
|
}
|
|
@@ -1612,7 +2502,7 @@ function groupByEntity(items, entityOf) {
|
|
|
1612
2502
|
}
|
|
1613
2503
|
return grouped;
|
|
1614
2504
|
}
|
|
1615
|
-
function resolveDeleteModifyOver(modified, deleted, modifiedEntity, deletedEntity,
|
|
2505
|
+
function resolveDeleteModifyOver(modified, deleted, modifiedEntity, deletedEntity, dropDeleted, policy, branchRank, preferredBranchId) {
|
|
1616
2506
|
const modifiedByKey = groupByEntity(modified, modifiedEntity);
|
|
1617
2507
|
const deletedByKey = groupByEntity(deleted, deletedEntity);
|
|
1618
2508
|
const survivingModifications = [];
|
|
@@ -1632,8 +2522,8 @@ function resolveDeleteModifyOver(modified, deleted, modifiedEntity, deletedEntit
|
|
|
1632
2522
|
}
|
|
1633
2523
|
continue;
|
|
1634
2524
|
}
|
|
1635
|
-
const deletionsForKey =
|
|
1636
|
-
const { id, kind } = modifiedEntity(
|
|
2525
|
+
const deletionsForKey = chunkN66HCGCY_cjs.requireDefined(deletedByKey.get(key));
|
|
2526
|
+
const { id, kind } = modifiedEntity(chunkN66HCGCY_cjs.requireDefined(modifications[0]));
|
|
1637
2527
|
const deletedBy = pickHighestPriorityBranch(
|
|
1638
2528
|
deletionsForKey.map((deletion) => deletion.branchId),
|
|
1639
2529
|
branchRank
|
|
@@ -1657,7 +2547,7 @@ function resolveDeleteModifyOver(modified, deleted, modifiedEntity, deletedEntit
|
|
|
1657
2547
|
});
|
|
1658
2548
|
if (effectivePolicy === "deleteWins") {
|
|
1659
2549
|
deletions.push({ id, kind });
|
|
1660
|
-
dropped.push(
|
|
2550
|
+
dropped.push(dropDeleted(id));
|
|
1661
2551
|
continue;
|
|
1662
2552
|
}
|
|
1663
2553
|
for (const modification of modifications) {
|
|
@@ -1668,25 +2558,25 @@ function resolveDeleteModifyOver(modified, deleted, modifiedEntity, deletedEntit
|
|
|
1668
2558
|
if (conflictedKeys.has(key)) {
|
|
1669
2559
|
continue;
|
|
1670
2560
|
}
|
|
1671
|
-
const { id, kind } = deletedEntity(
|
|
2561
|
+
const { id, kind } = deletedEntity(chunkN66HCGCY_cjs.requireDefined(deletionsForKey[0]));
|
|
1672
2562
|
deletions.push({ id, kind });
|
|
1673
2563
|
}
|
|
1674
2564
|
return {
|
|
1675
2565
|
survivingModifications: [...survivingModifications].sort((left, right) => {
|
|
1676
|
-
const byId2 =
|
|
2566
|
+
const byId2 = chunkXMQSEJCF_cjs.compareStrings(
|
|
1677
2567
|
modifiedEntity(left).id,
|
|
1678
2568
|
modifiedEntity(right).id
|
|
1679
2569
|
);
|
|
1680
|
-
return byId2 === 0 ?
|
|
2570
|
+
return byId2 === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.branchId, right.branchId) : byId2;
|
|
1681
2571
|
}),
|
|
1682
2572
|
deletions: [...deletions].sort(
|
|
1683
|
-
(left, right) =>
|
|
2573
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
1684
2574
|
),
|
|
1685
2575
|
conflicts: [...conflicts].sort(
|
|
1686
|
-
(left, right) =>
|
|
2576
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.entityId, right.entityId)
|
|
1687
2577
|
),
|
|
1688
2578
|
dropped: [...dropped].sort(
|
|
1689
|
-
(left, right) =>
|
|
2579
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
1690
2580
|
)
|
|
1691
2581
|
};
|
|
1692
2582
|
}
|
|
@@ -1700,10 +2590,10 @@ function reconcileOver(survivingModifications, entityOf, rebuild, policy, branch
|
|
|
1700
2590
|
const conflicts = [];
|
|
1701
2591
|
for (const modifications of grouped.values()) {
|
|
1702
2592
|
if (modifications.length === 1) {
|
|
1703
|
-
out.push(
|
|
2593
|
+
out.push(chunkN66HCGCY_cjs.requireDefined(modifications[0]));
|
|
1704
2594
|
continue;
|
|
1705
2595
|
}
|
|
1706
|
-
const first = entityOf(
|
|
2596
|
+
const first = entityOf(chunkN66HCGCY_cjs.requireDefined(modifications[0]));
|
|
1707
2597
|
const { props, conflicts: propertyConflicts } = threeWayMergeProps(
|
|
1708
2598
|
first.id,
|
|
1709
2599
|
first.kind,
|
|
@@ -1722,7 +2612,7 @@ function reconcileOver(survivingModifications, entityOf, rebuild, policy, branch
|
|
|
1722
2612
|
);
|
|
1723
2613
|
const representative = modifications.find(
|
|
1724
2614
|
(modification) => modification.branchId === chosenBranch
|
|
1725
|
-
) ??
|
|
2615
|
+
) ?? chunkN66HCGCY_cjs.requireDefined(modifications[0]);
|
|
1726
2616
|
out.push(rebuild(representative, chosenBranch, props));
|
|
1727
2617
|
for (const conflict of propertyConflicts) {
|
|
1728
2618
|
conflicts.push(conflict);
|
|
@@ -1730,11 +2620,11 @@ function reconcileOver(survivingModifications, entityOf, rebuild, policy, branch
|
|
|
1730
2620
|
}
|
|
1731
2621
|
return {
|
|
1732
2622
|
survivingModifications: [...out].sort((left, right) => {
|
|
1733
|
-
const byId2 =
|
|
1734
|
-
return byId2 === 0 ?
|
|
2623
|
+
const byId2 = chunkXMQSEJCF_cjs.compareStrings(entityOf(left).id, entityOf(right).id);
|
|
2624
|
+
return byId2 === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.branchId, right.branchId) : byId2;
|
|
1735
2625
|
}),
|
|
1736
2626
|
conflicts: conflicts.sort(
|
|
1737
|
-
(left, right) =>
|
|
2627
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(
|
|
1738
2628
|
`${left.entityId}|${left.property}`,
|
|
1739
2629
|
`${right.entityId}|${right.property}`
|
|
1740
2630
|
)
|
|
@@ -1747,7 +2637,7 @@ function resolveDeleteModify(staging, policy, branchRank, preferredBranchId) {
|
|
|
1747
2637
|
staging.deletedNodes,
|
|
1748
2638
|
(item) => item.node,
|
|
1749
2639
|
(item) => item.node,
|
|
1750
|
-
"node",
|
|
2640
|
+
(id) => ({ kind: "node", id, reason: DELETED_NODE_DROP_REASON }),
|
|
1751
2641
|
policy,
|
|
1752
2642
|
branchRank,
|
|
1753
2643
|
preferredBranchId
|
|
@@ -1760,7 +2650,7 @@ function resolveDeleteModify(staging, policy, branchRank, preferredBranchId) {
|
|
|
1760
2650
|
};
|
|
1761
2651
|
}
|
|
1762
2652
|
function threeWayMergeProps(entityId, kind, baseProps, contributions, context, branchRank, preferredBranchId) {
|
|
1763
|
-
const merged =
|
|
2653
|
+
const merged = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
1764
2654
|
const conflicts = [];
|
|
1765
2655
|
const propertyNames = new Set(Object.keys(baseProps));
|
|
1766
2656
|
for (const contribution of contributions) {
|
|
@@ -1768,11 +2658,11 @@ function threeWayMergeProps(entityId, kind, baseProps, contributions, context, b
|
|
|
1768
2658
|
propertyNames.add(name);
|
|
1769
2659
|
}
|
|
1770
2660
|
}
|
|
1771
|
-
for (const property of [...propertyNames].sort(
|
|
1772
|
-
const baseHas = property
|
|
1773
|
-
const baseKey = baseHas ? canonicalValueKey(
|
|
2661
|
+
for (const property of [...propertyNames].sort(chunkXMQSEJCF_cjs.compareStrings)) {
|
|
2662
|
+
const baseHas = chunkN66HCGCY_cjs.hasOwnKey(baseProps, property);
|
|
2663
|
+
const baseKey = baseHas ? canonicalValueKey(chunkN66HCGCY_cjs.requireDefined(baseProps[property])) : void 0;
|
|
1774
2664
|
const changed = contributions.filter((contribution) => {
|
|
1775
|
-
if (!(
|
|
2665
|
+
if (!chunkN66HCGCY_cjs.hasOwnKey(contribution.forkProps, property)) {
|
|
1776
2666
|
return false;
|
|
1777
2667
|
}
|
|
1778
2668
|
const value2 = contribution.forkProps[property];
|
|
@@ -1784,10 +2674,10 @@ function threeWayMergeProps(entityId, kind, baseProps, contributions, context, b
|
|
|
1784
2674
|
const values = collectConflictingValues(property, changed);
|
|
1785
2675
|
if (values.length === 0) {
|
|
1786
2676
|
const deletedByFork = baseHas && contributions.some(
|
|
1787
|
-
(contribution) => !(
|
|
2677
|
+
(contribution) => !chunkN66HCGCY_cjs.hasOwnKey(contribution.forkProps, property)
|
|
1788
2678
|
);
|
|
1789
2679
|
if (baseHas && !deletedByFork) {
|
|
1790
|
-
merged[property] =
|
|
2680
|
+
merged[property] = chunkN66HCGCY_cjs.requireDefined(baseProps[property]);
|
|
1791
2681
|
}
|
|
1792
2682
|
continue;
|
|
1793
2683
|
}
|
|
@@ -1795,13 +2685,13 @@ function threeWayMergeProps(entityId, kind, baseProps, contributions, context, b
|
|
|
1795
2685
|
values.map((candidate) => canonicalValueKey(candidate.value))
|
|
1796
2686
|
);
|
|
1797
2687
|
if (distinctValues.size === 1) {
|
|
1798
|
-
merged[property] =
|
|
2688
|
+
merged[property] = chunkN66HCGCY_cjs.requireDefined(values[0]).value;
|
|
1799
2689
|
continue;
|
|
1800
2690
|
}
|
|
1801
2691
|
const preferredValue = values.find(
|
|
1802
2692
|
(value2) => value2.branchId === preferredBranchId
|
|
1803
2693
|
)?.value;
|
|
1804
|
-
const canonicalValue = preferredValue ?? (baseHas ?
|
|
2694
|
+
const canonicalValue = preferredValue ?? (baseHas ? chunkN66HCGCY_cjs.requireDefined(baseProps[property]) : chunkN66HCGCY_cjs.requireDefined(values[0]).value);
|
|
1805
2695
|
const reportedValues = preferredBranchId === void 0 ? values : values.filter((value2) => value2.branchId !== preferredBranchId);
|
|
1806
2696
|
const { value, conflict } = resolvePropertyUnion(
|
|
1807
2697
|
{ entityId, kind, property, values, reportedValues, canonicalValue },
|
|
@@ -1835,7 +2725,7 @@ function resolveEdgeDeleteModify(staging, policy, branchRank, preferredBranchId)
|
|
|
1835
2725
|
staging.deletedEdges,
|
|
1836
2726
|
(item) => item.edge,
|
|
1837
2727
|
(item) => item.edge,
|
|
1838
|
-
"edge",
|
|
2728
|
+
(id) => ({ kind: "edge", id, reason: DELETED_NODE_DROP_REASON }),
|
|
1839
2729
|
policy,
|
|
1840
2730
|
branchRank,
|
|
1841
2731
|
preferredBranchId
|
|
@@ -1862,8 +2752,166 @@ function reconcileEdgeModifications(survivingModifications, policy, branchRank,
|
|
|
1862
2752
|
);
|
|
1863
2753
|
}
|
|
1864
2754
|
|
|
2755
|
+
// src/graph-merge/valid-window.ts
|
|
2756
|
+
var WINDOW_NOT_APPLICABLE_DROP_REASON = "window-not-applicable";
|
|
2757
|
+
function earliestEnd(claims) {
|
|
2758
|
+
let earliest;
|
|
2759
|
+
for (const claim of claims) {
|
|
2760
|
+
if (earliest === void 0 || chunkXMQSEJCF_cjs.compareStrings(claim.validTo, earliest) < 0) {
|
|
2761
|
+
earliest = claim.validTo;
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
return earliest;
|
|
2765
|
+
}
|
|
2766
|
+
function resolveEndClaims(claims, preferredBranchId) {
|
|
2767
|
+
const preferred = claims.filter(
|
|
2768
|
+
(claim) => claim.branchId === preferredBranchId
|
|
2769
|
+
);
|
|
2770
|
+
return earliestEnd(preferred.length > 0 ? preferred : claims);
|
|
2771
|
+
}
|
|
2772
|
+
function claimingBranches(claims) {
|
|
2773
|
+
return [...new Set(claims.map((claim) => claim.branchId))].sort(
|
|
2774
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
2775
|
+
);
|
|
2776
|
+
}
|
|
2777
|
+
function classifyDelta(base, fork) {
|
|
2778
|
+
const endCleared = fork.validTo === void 0 && base.validTo !== void 0;
|
|
2779
|
+
return {
|
|
2780
|
+
applicableEnd: fork.validTo !== void 0 && fork.validTo !== base.validTo ? fork.validTo : void 0,
|
|
2781
|
+
unapplicable: endCleared || fork.validFrom !== base.validFrom
|
|
2782
|
+
};
|
|
2783
|
+
}
|
|
2784
|
+
function resolvePopulation(entity, deltas, deletions, preferredBranchId, dropItem) {
|
|
2785
|
+
const byIdentity = /* @__PURE__ */ new Map();
|
|
2786
|
+
for (const delta of deltas) {
|
|
2787
|
+
const identity = mergeKey(delta.kind, delta.id);
|
|
2788
|
+
if (deletions.has(identity)) {
|
|
2789
|
+
continue;
|
|
2790
|
+
}
|
|
2791
|
+
const bucket = byIdentity.get(identity);
|
|
2792
|
+
if (bucket === void 0) {
|
|
2793
|
+
byIdentity.set(identity, [delta]);
|
|
2794
|
+
} else {
|
|
2795
|
+
bucket.push(delta);
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
const ends = /* @__PURE__ */ new Map();
|
|
2799
|
+
const credits = /* @__PURE__ */ new Map();
|
|
2800
|
+
const resolutions = [];
|
|
2801
|
+
const dropped = [];
|
|
2802
|
+
for (const [identity, group] of byIdentity) {
|
|
2803
|
+
const claims = [];
|
|
2804
|
+
let reportedUnapplicable = false;
|
|
2805
|
+
let targetEnd;
|
|
2806
|
+
for (const delta of group) {
|
|
2807
|
+
const { applicableEnd, unapplicable } = classifyDelta(
|
|
2808
|
+
delta.base,
|
|
2809
|
+
delta.fork
|
|
2810
|
+
);
|
|
2811
|
+
if (delta.branchId === preferredBranchId) {
|
|
2812
|
+
targetEnd ??= applicableEnd;
|
|
2813
|
+
continue;
|
|
2814
|
+
}
|
|
2815
|
+
if (applicableEnd !== void 0) {
|
|
2816
|
+
claims.push({ branchId: delta.branchId, validTo: applicableEnd });
|
|
2817
|
+
}
|
|
2818
|
+
if (unapplicable && !reportedUnapplicable) {
|
|
2819
|
+
reportedUnapplicable = true;
|
|
2820
|
+
dropped.push(dropItem(delta.id));
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
const first = chunkN66HCGCY_cjs.requireDefined(group[0]);
|
|
2824
|
+
if (targetEnd !== void 0) {
|
|
2825
|
+
if (claims.length > 0) {
|
|
2826
|
+
resolutions.push({
|
|
2827
|
+
entity,
|
|
2828
|
+
kind: first.kind,
|
|
2829
|
+
id: first.id,
|
|
2830
|
+
validTo: targetEnd,
|
|
2831
|
+
claimedBy: claimingBranches(claims),
|
|
2832
|
+
precedence: VALIDITY_END_TARGET_PRECEDENCE
|
|
2833
|
+
});
|
|
2834
|
+
}
|
|
2835
|
+
continue;
|
|
2836
|
+
}
|
|
2837
|
+
const resolved = earliestEnd(claims);
|
|
2838
|
+
if (resolved === void 0) {
|
|
2839
|
+
continue;
|
|
2840
|
+
}
|
|
2841
|
+
ends.set(identity, resolved);
|
|
2842
|
+
credits.set(
|
|
2843
|
+
identity,
|
|
2844
|
+
claimingBranches(claims.filter((claim) => claim.validTo === resolved))
|
|
2845
|
+
);
|
|
2846
|
+
resolutions.push({
|
|
2847
|
+
entity,
|
|
2848
|
+
kind: first.kind,
|
|
2849
|
+
id: first.id,
|
|
2850
|
+
validTo: resolved,
|
|
2851
|
+
claimedBy: claimingBranches(claims)
|
|
2852
|
+
});
|
|
2853
|
+
}
|
|
2854
|
+
return {
|
|
2855
|
+
ends,
|
|
2856
|
+
credits,
|
|
2857
|
+
resolutions: resolutions.sort(
|
|
2858
|
+
(left, right) => compareMergeKeys(
|
|
2859
|
+
mergeKey(left.kind, left.id),
|
|
2860
|
+
mergeKey(right.kind, right.id)
|
|
2861
|
+
)
|
|
2862
|
+
),
|
|
2863
|
+
dropped: dropped.sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id))
|
|
2864
|
+
};
|
|
2865
|
+
}
|
|
2866
|
+
function resolveValidWindows(staging, nodeDeletions, edgeDeletions, preferredBranchId) {
|
|
2867
|
+
const nodes = resolvePopulation(
|
|
2868
|
+
"node",
|
|
2869
|
+
staging.windowedNodes.map((staged) => ({
|
|
2870
|
+
branchId: staged.branchId,
|
|
2871
|
+
kind: staged.node.kind,
|
|
2872
|
+
id: staged.node.id,
|
|
2873
|
+
base: staged.node.base,
|
|
2874
|
+
fork: staged.node.fork
|
|
2875
|
+
})),
|
|
2876
|
+
nodeDeletions,
|
|
2877
|
+
preferredBranchId,
|
|
2878
|
+
(id) => ({
|
|
2879
|
+
kind: "node",
|
|
2880
|
+
id,
|
|
2881
|
+
reason: WINDOW_NOT_APPLICABLE_DROP_REASON
|
|
2882
|
+
})
|
|
2883
|
+
);
|
|
2884
|
+
const edges = resolvePopulation(
|
|
2885
|
+
"edge",
|
|
2886
|
+
staging.windowedEdges.map((staged) => ({
|
|
2887
|
+
branchId: staged.branchId,
|
|
2888
|
+
kind: staged.edge.kind,
|
|
2889
|
+
id: staged.edge.id,
|
|
2890
|
+
base: staged.edge.base,
|
|
2891
|
+
fork: staged.edge.fork
|
|
2892
|
+
})),
|
|
2893
|
+
edgeDeletions,
|
|
2894
|
+
preferredBranchId,
|
|
2895
|
+
(id) => ({
|
|
2896
|
+
kind: "edge",
|
|
2897
|
+
id,
|
|
2898
|
+
reason: WINDOW_NOT_APPLICABLE_DROP_REASON
|
|
2899
|
+
})
|
|
2900
|
+
);
|
|
2901
|
+
return {
|
|
2902
|
+
nodeEnds: nodes.ends,
|
|
2903
|
+
edgeEnds: edges.ends,
|
|
2904
|
+
nodeCredits: nodes.credits,
|
|
2905
|
+
edgeCredits: edges.credits,
|
|
2906
|
+
resolutions: [...nodes.resolutions, ...edges.resolutions],
|
|
2907
|
+
dropped: [...nodes.dropped, ...edges.dropped]
|
|
2908
|
+
};
|
|
2909
|
+
}
|
|
2910
|
+
|
|
1865
2911
|
// src/graph-merge/edge-repoint.ts
|
|
1866
2912
|
var ENDPOINT_DELETED_DROP_REASON = "edge:endpoint-deleted";
|
|
2913
|
+
var INHERITED_EDGE_ORIGIN = "inherited";
|
|
2914
|
+
var BRANCH_CREATED_EDGE_ORIGIN = "branch-created";
|
|
1867
2915
|
function buildCanonicalMap(clusters, canonicalOf) {
|
|
1868
2916
|
const map = /* @__PURE__ */ new Map();
|
|
1869
2917
|
for (const cluster of clusters) {
|
|
@@ -1883,16 +2931,97 @@ function dedupeKey(fromKey, type, toKey, props) {
|
|
|
1883
2931
|
function groupKey(fromKey, type, toKey) {
|
|
1884
2932
|
return JSON.stringify([fromKey, type, toKey]);
|
|
1885
2933
|
}
|
|
2934
|
+
function sourcePairKey(fromKey, toKey) {
|
|
2935
|
+
return JSON.stringify([fromKey, toKey]);
|
|
2936
|
+
}
|
|
2937
|
+
function rowsById(groupEdges) {
|
|
2938
|
+
const rows = /* @__PURE__ */ new Map();
|
|
2939
|
+
for (const edge of groupEdges) {
|
|
2940
|
+
const row = rows.get(edge.staged.id);
|
|
2941
|
+
if (row === void 0) {
|
|
2942
|
+
rows.set(edge.staged.id, [edge]);
|
|
2943
|
+
} else {
|
|
2944
|
+
row.push(edge);
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
return rows;
|
|
2948
|
+
}
|
|
2949
|
+
function sourcePairByRow(rows) {
|
|
2950
|
+
const pairs = /* @__PURE__ */ new Map();
|
|
2951
|
+
for (const [id, members] of rows) {
|
|
2952
|
+
const sorted = members.map((member) => member.sourcePair).sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
2953
|
+
pairs.set(id, chunkN66HCGCY_cjs.requireDefined(sorted[0]));
|
|
2954
|
+
}
|
|
2955
|
+
return pairs;
|
|
2956
|
+
}
|
|
2957
|
+
function foldSets(groupEdges) {
|
|
2958
|
+
const rows = rowsById(groupEdges);
|
|
2959
|
+
const sourcePairs = sourcePairByRow(rows);
|
|
2960
|
+
const representatives = /* @__PURE__ */ new Map();
|
|
2961
|
+
for (const [id, pair] of sourcePairs) {
|
|
2962
|
+
const representative = representatives.get(pair);
|
|
2963
|
+
if (representative === void 0 || chunkXMQSEJCF_cjs.compareStrings(id, representative) < 0) {
|
|
2964
|
+
representatives.set(pair, id);
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
const collapsed = [];
|
|
2968
|
+
const parallel = [];
|
|
2969
|
+
for (const id of [...rows.keys()].sort(
|
|
2970
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
2971
|
+
)) {
|
|
2972
|
+
const members = chunkN66HCGCY_cjs.requireDefined(rows.get(id));
|
|
2973
|
+
const pair = chunkN66HCGCY_cjs.requireDefined(sourcePairs.get(id));
|
|
2974
|
+
if (representatives.get(pair) === id) {
|
|
2975
|
+
collapsed.push(...members);
|
|
2976
|
+
} else {
|
|
2977
|
+
parallel.push(members);
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
return [collapsed, ...parallel];
|
|
2981
|
+
}
|
|
2982
|
+
function compareMembers(left, right, preferredBranchId) {
|
|
2983
|
+
const byId2 = chunkXMQSEJCF_cjs.compareStrings(left.staged.id, right.staged.id);
|
|
2984
|
+
if (byId2 !== 0) {
|
|
2985
|
+
return byId2;
|
|
2986
|
+
}
|
|
2987
|
+
const leftPreferred = left.staged.branchId === preferredBranchId;
|
|
2988
|
+
const rightPreferred = right.staged.branchId === preferredBranchId;
|
|
2989
|
+
if (leftPreferred !== rightPreferred) {
|
|
2990
|
+
return leftPreferred ? -1 : 1;
|
|
2991
|
+
}
|
|
2992
|
+
return chunkXMQSEJCF_cjs.compareStrings(left.staged.branchId, right.staged.branchId);
|
|
2993
|
+
}
|
|
1886
2994
|
function pickSurvivor(edges, preferredBranchId) {
|
|
2995
|
+
const inherited = edges.filter(
|
|
2996
|
+
(edge) => edge.staged.origin === INHERITED_EDGE_ORIGIN
|
|
2997
|
+
);
|
|
1887
2998
|
const preferred = preferredBranchId === void 0 ? [] : edges.filter((edge) => edge.staged.branchId === preferredBranchId);
|
|
1888
|
-
const candidates = preferred.length > 0 ? preferred : edges;
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
2999
|
+
const candidates = inherited.length > 0 ? inherited : preferred.length > 0 ? preferred : edges;
|
|
3000
|
+
return chunkN66HCGCY_cjs.requireDefined(
|
|
3001
|
+
[...candidates].sort(
|
|
3002
|
+
(left, right) => compareMembers(left, right, preferredBranchId)
|
|
3003
|
+
)[0]
|
|
3004
|
+
);
|
|
3005
|
+
}
|
|
3006
|
+
function authoredProperty(edge, property) {
|
|
3007
|
+
const { props, baseProps } = edge.staged;
|
|
3008
|
+
if (!chunkN66HCGCY_cjs.hasOwnKey(props, property)) {
|
|
3009
|
+
return false;
|
|
3010
|
+
}
|
|
3011
|
+
if (baseProps === void 0 || !chunkN66HCGCY_cjs.hasOwnKey(baseProps, property)) {
|
|
3012
|
+
return true;
|
|
1894
3013
|
}
|
|
1895
|
-
return
|
|
3014
|
+
return canonicalValueKey(props[property]) !== canonicalValueKey(baseProps[property]);
|
|
3015
|
+
}
|
|
3016
|
+
function unauthoredValue(property, edges) {
|
|
3017
|
+
const carriers = edges.filter((edge) => chunkN66HCGCY_cjs.hasOwnKey(edge.staged.props, property)).sort((left, right) => {
|
|
3018
|
+
const byId2 = chunkXMQSEJCF_cjs.compareStrings(left.staged.id, right.staged.id);
|
|
3019
|
+
return byId2 === 0 ? chunkXMQSEJCF_cjs.compareStrings(
|
|
3020
|
+
canonicalValueKey(left.staged.props[property]),
|
|
3021
|
+
canonicalValueKey(right.staged.props[property])
|
|
3022
|
+
) : byId2;
|
|
3023
|
+
});
|
|
3024
|
+
return chunkN66HCGCY_cjs.requireDefined(carriers[0]).staged.props[property];
|
|
1896
3025
|
}
|
|
1897
3026
|
function unionEdgeProps(survivorId, kind, survivor, edges, context, branchRank, preferredBranchId) {
|
|
1898
3027
|
const propertyNames = /* @__PURE__ */ new Set();
|
|
@@ -1901,17 +3030,18 @@ function unionEdgeProps(survivorId, kind, survivor, edges, context, branchRank,
|
|
|
1901
3030
|
propertyNames.add(name);
|
|
1902
3031
|
}
|
|
1903
3032
|
}
|
|
1904
|
-
const props =
|
|
3033
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
1905
3034
|
const conflicts = [];
|
|
1906
|
-
const contributions = edges.map((edge) => edge.staged);
|
|
1907
3035
|
for (const property of [...propertyNames].sort(
|
|
1908
|
-
(left, right) =>
|
|
3036
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
1909
3037
|
)) {
|
|
1910
|
-
const
|
|
3038
|
+
const claimants = edges.filter((edge) => authoredProperty(edge, property)).map((edge) => edge.staged);
|
|
3039
|
+
const values = collectConflictingValues(property, claimants);
|
|
1911
3040
|
if (values.length === 0) {
|
|
3041
|
+
props[property] = chunkN66HCGCY_cjs.hasOwnKey(survivor.staged.props, property) ? survivor.staged.props[property] : unauthoredValue(property, edges);
|
|
1912
3042
|
continue;
|
|
1913
3043
|
}
|
|
1914
|
-
const survivorValue =
|
|
3044
|
+
const survivorValue = chunkN66HCGCY_cjs.hasOwnKey(survivor.staged.props, property) ? survivor.staged.props[property] : chunkN66HCGCY_cjs.requireDefined(values[0]).value;
|
|
1915
3045
|
const canonicalValue = values.find((value2) => value2.branchId === preferredBranchId)?.value ?? survivorValue;
|
|
1916
3046
|
const reportedValues = preferredBranchId === void 0 ? values : values.filter((value2) => value2.branchId !== preferredBranchId);
|
|
1917
3047
|
const { value, conflict } = resolvePropertyUnion(
|
|
@@ -1933,16 +3063,75 @@ function unionEdgeProps(survivorId, kind, survivor, edges, context, branchRank,
|
|
|
1933
3063
|
}
|
|
1934
3064
|
return { props, conflicts };
|
|
1935
3065
|
}
|
|
3066
|
+
function foldEdgeSet(foldSet, context, branchRank, preferredBranchId) {
|
|
3067
|
+
const survivor = pickSurvivor(foldSet, preferredBranchId);
|
|
3068
|
+
const survivorId = survivor.staged.id;
|
|
3069
|
+
const mergedIds = foldSet.map((edge) => edge.staged.id).sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
3070
|
+
const fromId = idOf(survivor.fromKey);
|
|
3071
|
+
const fromKind = kindOf(survivor.fromKey);
|
|
3072
|
+
const toId = idOf(survivor.toKey);
|
|
3073
|
+
const toKind = kindOf(survivor.toKey);
|
|
3074
|
+
const preferredSurvivorEnd = survivor.staged.branchId === preferredBranchId ? survivor.staged.validTo : void 0;
|
|
3075
|
+
const foldedEnd = preferredSurvivorEnd ?? resolveEndClaims(
|
|
3076
|
+
foldSet.filter((edge) => edge.staged.validTo !== void 0).map((edge) => ({
|
|
3077
|
+
branchId: edge.staged.branchId,
|
|
3078
|
+
validTo: chunkN66HCGCY_cjs.requireDefined(edge.staged.validTo)
|
|
3079
|
+
})),
|
|
3080
|
+
preferredBranchId
|
|
3081
|
+
);
|
|
3082
|
+
const window = {
|
|
3083
|
+
...survivor.staged.validFrom === void 0 ? {} : { validFrom: survivor.staged.validFrom },
|
|
3084
|
+
...foldedEnd === void 0 ? {} : { validTo: foldedEnd }
|
|
3085
|
+
};
|
|
3086
|
+
const contentKeys = new Set(foldSet.map((edge) => edge.dedupeKey));
|
|
3087
|
+
if (contentKeys.size === 1) {
|
|
3088
|
+
return {
|
|
3089
|
+
edge: {
|
|
3090
|
+
id: survivorId,
|
|
3091
|
+
kind: survivor.staged.kind,
|
|
3092
|
+
fromId,
|
|
3093
|
+
toId,
|
|
3094
|
+
fromKind,
|
|
3095
|
+
toKind,
|
|
3096
|
+
props: survivor.staged.props,
|
|
3097
|
+
mergedIds,
|
|
3098
|
+
...window
|
|
3099
|
+
},
|
|
3100
|
+
conflicts: []
|
|
3101
|
+
};
|
|
3102
|
+
}
|
|
3103
|
+
const { props, conflicts } = unionEdgeProps(
|
|
3104
|
+
survivorId,
|
|
3105
|
+
survivor.staged.kind,
|
|
3106
|
+
survivor,
|
|
3107
|
+
foldSet,
|
|
3108
|
+
context,
|
|
3109
|
+
branchRank,
|
|
3110
|
+
preferredBranchId
|
|
3111
|
+
);
|
|
3112
|
+
return {
|
|
3113
|
+
edge: {
|
|
3114
|
+
id: survivorId,
|
|
3115
|
+
kind: survivor.staged.kind,
|
|
3116
|
+
fromId,
|
|
3117
|
+
toId,
|
|
3118
|
+
fromKind,
|
|
3119
|
+
toKind,
|
|
3120
|
+
props,
|
|
3121
|
+
mergedIds,
|
|
3122
|
+
...window
|
|
3123
|
+
},
|
|
3124
|
+
conflicts
|
|
3125
|
+
};
|
|
3126
|
+
}
|
|
1936
3127
|
function repointEdges(stagedEdges, canonicalOf, deletedNodeIds, policy, branchRank, weights, preferredBranchId) {
|
|
1937
3128
|
const dropped = [];
|
|
1938
|
-
const
|
|
1939
|
-
const dedupeKeyByGroup = /* @__PURE__ */ new Map();
|
|
3129
|
+
const liveByGroup = /* @__PURE__ */ new Map();
|
|
1940
3130
|
for (const staged of stagedEdges) {
|
|
1941
|
-
const
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
);
|
|
1945
|
-
const toKey = repoint(mergeKey(staged.toKind, staged.toId), canonicalOf);
|
|
3131
|
+
const sourceFromKey = mergeKey(staged.fromKind, staged.fromId);
|
|
3132
|
+
const sourceToKey = mergeKey(staged.toKind, staged.toId);
|
|
3133
|
+
const fromKey = repoint(sourceFromKey, canonicalOf);
|
|
3134
|
+
const toKey = repoint(sourceToKey, canonicalOf);
|
|
1946
3135
|
if (deletedNodeIds.has(fromKey) || deletedNodeIds.has(toKey)) {
|
|
1947
3136
|
dropped.push({
|
|
1948
3137
|
kind: "edge",
|
|
@@ -1951,21 +3140,20 @@ function repointEdges(stagedEdges, canonicalOf, deletedNodeIds, policy, branchRa
|
|
|
1951
3140
|
});
|
|
1952
3141
|
continue;
|
|
1953
3142
|
}
|
|
1954
|
-
const repointed = {
|
|
1955
|
-
|
|
1956
|
-
|
|
3143
|
+
const repointed = {
|
|
3144
|
+
staged,
|
|
3145
|
+
fromKey,
|
|
3146
|
+
toKey,
|
|
3147
|
+
sourcePair: sourcePairKey(sourceFromKey, sourceToKey),
|
|
3148
|
+
dedupeKey: dedupeKey(fromKey, staged.kind, toKey, staged.props)
|
|
3149
|
+
};
|
|
3150
|
+
const group = groupKey(fromKey, staged.kind, toKey);
|
|
3151
|
+
const bucket = liveByGroup.get(group);
|
|
1957
3152
|
if (bucket === void 0) {
|
|
1958
|
-
|
|
3153
|
+
liveByGroup.set(group, [repointed]);
|
|
1959
3154
|
} else {
|
|
1960
3155
|
bucket.push(repointed);
|
|
1961
3156
|
}
|
|
1962
|
-
const group = groupKey(fromKey, staged.kind, toKey);
|
|
1963
|
-
const keysForGroup = dedupeKeyByGroup.get(group);
|
|
1964
|
-
if (keysForGroup === void 0) {
|
|
1965
|
-
dedupeKeyByGroup.set(group, /* @__PURE__ */ new Set([key]));
|
|
1966
|
-
} else {
|
|
1967
|
-
keysForGroup.add(key);
|
|
1968
|
-
}
|
|
1969
3157
|
}
|
|
1970
3158
|
const context = {
|
|
1971
3159
|
policy,
|
|
@@ -1973,74 +3161,41 @@ function repointEdges(stagedEdges, canonicalOf, deletedNodeIds, policy, branchRa
|
|
|
1973
3161
|
};
|
|
1974
3162
|
const merged = [];
|
|
1975
3163
|
const conflicts = [];
|
|
1976
|
-
const sortedGroups = [...
|
|
1977
|
-
(left, right) =>
|
|
3164
|
+
const sortedGroups = [...liveByGroup.keys()].sort(
|
|
3165
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
1978
3166
|
);
|
|
1979
3167
|
for (const group of sortedGroups) {
|
|
1980
|
-
const
|
|
1981
|
-
const groupEdges
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
3168
|
+
const groupEdges = chunkN66HCGCY_cjs.requireDefined(liveByGroup.get(group));
|
|
3169
|
+
for (const foldSet of foldSets(groupEdges)) {
|
|
3170
|
+
const folded = foldEdgeSet(
|
|
3171
|
+
foldSet,
|
|
3172
|
+
context,
|
|
3173
|
+
branchRank,
|
|
3174
|
+
preferredBranchId
|
|
3175
|
+
);
|
|
3176
|
+
merged.push(folded.edge);
|
|
3177
|
+
for (const conflict of folded.conflicts) {
|
|
3178
|
+
conflicts.push(conflict);
|
|
1985
3179
|
}
|
|
1986
3180
|
}
|
|
1987
|
-
const survivor = pickSurvivor(groupEdges, preferredBranchId);
|
|
1988
|
-
const survivorId = survivor.staged.id;
|
|
1989
|
-
const mergedIds = [...groupEdges].map((edge) => edge.staged.id).sort((left, right) => chunkTRF4EBJT_cjs.compareStrings(left, right));
|
|
1990
|
-
const fromId = idOf(survivor.fromKey);
|
|
1991
|
-
const fromKind = kindOf(survivor.fromKey);
|
|
1992
|
-
const toId = idOf(survivor.toKey);
|
|
1993
|
-
const toKind = kindOf(survivor.toKey);
|
|
1994
|
-
if (dedupeKeys.length === 1) {
|
|
1995
|
-
merged.push({
|
|
1996
|
-
id: survivorId,
|
|
1997
|
-
kind: survivor.staged.kind,
|
|
1998
|
-
fromId,
|
|
1999
|
-
toId,
|
|
2000
|
-
fromKind,
|
|
2001
|
-
toKind,
|
|
2002
|
-
props: survivor.staged.props,
|
|
2003
|
-
mergedIds
|
|
2004
|
-
});
|
|
2005
|
-
continue;
|
|
2006
|
-
}
|
|
2007
|
-
const { props, conflicts: groupConflicts } = unionEdgeProps(
|
|
2008
|
-
survivorId,
|
|
2009
|
-
survivor.staged.kind,
|
|
2010
|
-
survivor,
|
|
2011
|
-
groupEdges,
|
|
2012
|
-
context,
|
|
2013
|
-
branchRank,
|
|
2014
|
-
preferredBranchId
|
|
2015
|
-
);
|
|
2016
|
-
for (const conflict of groupConflicts) {
|
|
2017
|
-
conflicts.push(conflict);
|
|
2018
|
-
}
|
|
2019
|
-
merged.push({
|
|
2020
|
-
id: survivorId,
|
|
2021
|
-
kind: survivor.staged.kind,
|
|
2022
|
-
fromId,
|
|
2023
|
-
toId,
|
|
2024
|
-
fromKind,
|
|
2025
|
-
toKind,
|
|
2026
|
-
props,
|
|
2027
|
-
mergedIds
|
|
2028
|
-
});
|
|
2029
3181
|
}
|
|
2030
3182
|
const sortedEdges = merged.map((edge) => ({
|
|
2031
3183
|
edge,
|
|
2032
|
-
sortKey:
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
3184
|
+
sortKey: JSON.stringify([
|
|
3185
|
+
dedupeKey(
|
|
3186
|
+
mergeKey(edge.fromKind, edge.fromId),
|
|
3187
|
+
edge.kind,
|
|
3188
|
+
mergeKey(edge.toKind, edge.toId),
|
|
3189
|
+
edge.props
|
|
3190
|
+
),
|
|
3191
|
+
edge.id
|
|
3192
|
+
])
|
|
3193
|
+
})).sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.sortKey, right.sortKey)).map(({ edge }) => edge);
|
|
2039
3194
|
return {
|
|
2040
3195
|
edges: sortedEdges,
|
|
2041
|
-
dropped: dropped.sort((left, right) =>
|
|
3196
|
+
dropped: dropped.sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)),
|
|
2042
3197
|
conflicts: conflicts.sort(
|
|
2043
|
-
(left, right) =>
|
|
3198
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(
|
|
2044
3199
|
`${left.entityId}|${left.property}`,
|
|
2045
3200
|
`${right.entityId}|${right.property}`
|
|
2046
3201
|
)
|
|
@@ -2086,7 +3241,7 @@ function validateResolveMap(resolve) {
|
|
|
2086
3241
|
return {};
|
|
2087
3242
|
}
|
|
2088
3243
|
const configs = resolve;
|
|
2089
|
-
const validated =
|
|
3244
|
+
const validated = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
2090
3245
|
for (const [kind, config] of Object.entries(configs)) {
|
|
2091
3246
|
const parsed = resolveConfigScalarSchema.safeParse({
|
|
2092
3247
|
threshold: config.threshold
|
|
@@ -2114,7 +3269,7 @@ function validateResolveMap(resolve) {
|
|
|
2114
3269
|
}
|
|
2115
3270
|
validated[kind] = config;
|
|
2116
3271
|
}
|
|
2117
|
-
return validated;
|
|
3272
|
+
return { ...validated };
|
|
2118
3273
|
}
|
|
2119
3274
|
function validateProvenanceWeights(weights) {
|
|
2120
3275
|
for (const [branchId, weight] of weights) {
|
|
@@ -2169,7 +3324,9 @@ function normalizeMergeOptions(options = {}) {
|
|
|
2169
3324
|
...provenanceWeights === void 0 ? {} : { provenanceWeights }
|
|
2170
3325
|
};
|
|
2171
3326
|
}
|
|
2172
|
-
var
|
|
3327
|
+
var PROVENANCE_KIND = "Provenance";
|
|
3328
|
+
var PROVENANCE_OWNER_KIND = "ProvenanceOwner";
|
|
3329
|
+
var Provenance = chunkNK5Q7UNE_cjs.defineNode(PROVENANCE_KIND, {
|
|
2173
3330
|
schema: zod.z.object({
|
|
2174
3331
|
targetGraphId: zod.z.string(),
|
|
2175
3332
|
role: zod.z.enum(["node", "edge"]),
|
|
@@ -2179,38 +3336,308 @@ var Provenance = chunkBNS75YNF_cjs.defineNode("Provenance", {
|
|
|
2179
3336
|
sourceId: zod.z.string()
|
|
2180
3337
|
})
|
|
2181
3338
|
});
|
|
3339
|
+
var PROVENANCE_OWNER = "@nicia-ai/typegraph/merge-provenance";
|
|
3340
|
+
var PROVENANCE_OWNER_VERSION = 1;
|
|
3341
|
+
var PROVENANCE_OWNER_ID = "merge-provenance-owner";
|
|
3342
|
+
var ProvenanceOwner = chunkNK5Q7UNE_cjs.defineNode(PROVENANCE_OWNER_KIND, {
|
|
3343
|
+
schema: zod.z.object({
|
|
3344
|
+
owner: zod.z.literal(PROVENANCE_OWNER),
|
|
3345
|
+
version: zod.z.literal(PROVENANCE_OWNER_VERSION),
|
|
3346
|
+
targetGraphId: zod.z.string()
|
|
3347
|
+
})
|
|
3348
|
+
});
|
|
2182
3349
|
function provenanceGraphId(targetGraphId) {
|
|
2183
3350
|
return `${targetGraphId}::merge-provenance`;
|
|
2184
3351
|
}
|
|
2185
|
-
function
|
|
2186
|
-
return
|
|
2187
|
-
id: provenanceGraphId(targetGraphId),
|
|
2188
|
-
nodes: {
|
|
2189
|
-
|
|
3352
|
+
function buildOwnedProvenanceGraph(targetGraphId) {
|
|
3353
|
+
return chunkCXBHOOIQ_cjs.defineInternalGraph({
|
|
3354
|
+
id: provenanceGraphId(targetGraphId),
|
|
3355
|
+
nodes: {
|
|
3356
|
+
Provenance: { type: Provenance },
|
|
3357
|
+
ProvenanceOwner: { type: ProvenanceOwner }
|
|
3358
|
+
},
|
|
3359
|
+
edges: {}
|
|
3360
|
+
});
|
|
3361
|
+
}
|
|
3362
|
+
function buildProvenanceGraph(targetGraphId) {
|
|
3363
|
+
return chunkCXBHOOIQ_cjs.defineInternalGraph({
|
|
3364
|
+
id: provenanceGraphId(targetGraphId),
|
|
3365
|
+
nodes: { Provenance: { type: Provenance } },
|
|
3366
|
+
edges: {}
|
|
3367
|
+
});
|
|
3368
|
+
}
|
|
3369
|
+
async function openProvenanceStore(...args) {
|
|
3370
|
+
const [backend, targetGraphId] = args.length === 1 ? [chunkTTAITEPJ_cjs.storeBackend(args[0]), args[0].graphId] : args;
|
|
3371
|
+
const graph = buildOwnedProvenanceGraph(targetGraphId);
|
|
3372
|
+
const preflight = await inspectSidecarGraphId(backend, graph, targetGraphId);
|
|
3373
|
+
if (preflight.state === "refuse") {
|
|
3374
|
+
throw provenanceGraphIdCollision(graph.id, targetGraphId, preflight.reason);
|
|
3375
|
+
}
|
|
3376
|
+
if (preflight.state !== "owned") {
|
|
3377
|
+
const claim = await claimSidecarOwnership(backend, graph, targetGraphId);
|
|
3378
|
+
if (claim.state === "refuse") {
|
|
3379
|
+
throw provenanceGraphIdCollision(graph.id, targetGraphId, claim.reason);
|
|
3380
|
+
}
|
|
3381
|
+
}
|
|
3382
|
+
const [store] = await chunkXDF2UPEQ_cjs.createStoreWithSchema(graph, backend);
|
|
3383
|
+
return store;
|
|
3384
|
+
}
|
|
3385
|
+
async function claimSidecarOwnership(backend, graph, targetGraphId) {
|
|
3386
|
+
const fence = backend.schemaWriteTransaction;
|
|
3387
|
+
if (fence === void 0) {
|
|
3388
|
+
throw provenanceClaimUnfenced(graph.id, targetGraphId);
|
|
3389
|
+
}
|
|
3390
|
+
return fence(graph.id, async (tx) => {
|
|
3391
|
+
await drainUnfencedRowWriters(tx);
|
|
3392
|
+
const verdict = await inspectSidecarGraphId(tx, graph, targetGraphId);
|
|
3393
|
+
if (verdict.state === "refuse" || verdict.state === "owned") return verdict;
|
|
3394
|
+
await tx.insertNode({
|
|
3395
|
+
graphId: graph.id,
|
|
3396
|
+
kind: PROVENANCE_OWNER_KIND,
|
|
3397
|
+
id: PROVENANCE_OWNER_ID,
|
|
3398
|
+
props: {
|
|
3399
|
+
owner: PROVENANCE_OWNER,
|
|
3400
|
+
version: PROVENANCE_OWNER_VERSION,
|
|
3401
|
+
targetGraphId
|
|
3402
|
+
}
|
|
3403
|
+
});
|
|
3404
|
+
return verdict;
|
|
3405
|
+
});
|
|
3406
|
+
}
|
|
3407
|
+
async function drainUnfencedRowWriters(tx) {
|
|
3408
|
+
if (tx.dialect !== "postgres") return;
|
|
3409
|
+
const schema = chunkNFCVHQ5P_cjs.createSqlSchema(tx.tableNames);
|
|
3410
|
+
await tx.executeStatement(
|
|
3411
|
+
chunkVCRRKBLN_cjs.asCompiledStatementSql(
|
|
3412
|
+
chunkVCRRKBLN_cjs.sql`LOCK TABLE ${schema.nodesTable}, ${schema.edgesTable} IN SHARE ROW EXCLUSIVE MODE`
|
|
3413
|
+
)
|
|
3414
|
+
);
|
|
3415
|
+
}
|
|
3416
|
+
async function inspectSidecarGraphId(port, graph, targetGraphId) {
|
|
3417
|
+
const activeSchema = await port.getActiveSchema(graph.id);
|
|
3418
|
+
if (activeSchema === void 0 && !await hasRowsUnderGraphId(port, graph.id, "any")) {
|
|
3419
|
+
return { state: "create" };
|
|
3420
|
+
}
|
|
3421
|
+
const marker = await inspectOwnerMarker(port, graph.id, targetGraphId);
|
|
3422
|
+
if (marker === "foreign") {
|
|
3423
|
+
return { state: "refuse", reason: "corrupt-ownership-marker" };
|
|
3424
|
+
}
|
|
3425
|
+
if (marker === "ours") {
|
|
3426
|
+
return { state: "owned" };
|
|
3427
|
+
}
|
|
3428
|
+
if (activeSchema === void 0) {
|
|
3429
|
+
return { state: "refuse", reason: "application-graph" };
|
|
3430
|
+
}
|
|
3431
|
+
const ownedHash = await chunkN3257XE6_cjs.computeSchemaHash(
|
|
3432
|
+
chunkN3257XE6_cjs.serializeSchema(graph, activeSchema.version)
|
|
3433
|
+
);
|
|
3434
|
+
if (activeSchema.schema_hash === ownedHash) {
|
|
3435
|
+
return { state: "refuse", reason: "unowned-exact-schema-graph" };
|
|
3436
|
+
}
|
|
3437
|
+
const legacyHash = await chunkN3257XE6_cjs.computeSchemaHash(
|
|
3438
|
+
chunkN3257XE6_cjs.serializeSchema(buildProvenanceGraph(targetGraphId), activeSchema.version)
|
|
3439
|
+
);
|
|
3440
|
+
if (activeSchema.schema_hash !== legacyHash) {
|
|
3441
|
+
return { state: "refuse", reason: "application-graph" };
|
|
3442
|
+
}
|
|
3443
|
+
return LEGACY_SCHEMA_DISPOSITION[await inspectSidecarContents(port, graph.id, targetGraphId)];
|
|
3444
|
+
}
|
|
3445
|
+
var LEGACY_SCHEMA_DISPOSITION = {
|
|
3446
|
+
provenance: { state: "upgrade" },
|
|
3447
|
+
empty: { state: "refuse", reason: "empty-legacy-sidecar" },
|
|
3448
|
+
"unrecognized-provenance": {
|
|
3449
|
+
state: "refuse",
|
|
3450
|
+
reason: "unupgradeable-legacy-sidecar"
|
|
3451
|
+
},
|
|
3452
|
+
"foreign-rows": { state: "refuse", reason: "application-graph" }
|
|
3453
|
+
};
|
|
3454
|
+
var SIDECAR_REFUSALS = {
|
|
3455
|
+
"application-graph": {
|
|
3456
|
+
describe: (graphId) => `Graph id "${graphId}" is already used by an application graph and cannot host merge provenance.`,
|
|
3457
|
+
suggestion: () => "Rename the colliding application graph before enabling persisted merge provenance for this target."
|
|
3458
|
+
},
|
|
3459
|
+
"corrupt-ownership-marker": {
|
|
3460
|
+
describe: (graphId, targetGraphId) => `Graph id "${graphId}" holds a "${PROVENANCE_OWNER_KIND}" row that is not a valid ownership claim for target "${targetGraphId}" \u2014 it is soft-deleted, does not validate against the marker schema, names a different target, or sits under a different row id.`,
|
|
3461
|
+
suggestion: (graphId) => `Do not re-run: an unverifiable marker is never overwritten or resurrected, because it may be an application's row. Inspect the "${PROVENANCE_OWNER_KIND}" rows under graph id "${graphId}" and hard-delete the invalid one, or drop that graph id entirely \u2014 persisted provenance is derived, so re-running the merge rebuilds it.`
|
|
3462
|
+
},
|
|
3463
|
+
"empty-legacy-sidecar": {
|
|
3464
|
+
describe: (graphId) => `Graph id "${graphId}" holds an EMPTY provenance sidecar from a release that wrote no ownership marker, which cannot be told apart from an application graph of the same shape.`,
|
|
3465
|
+
suggestion: (graphId) => `Drop graph id "${graphId}" \u2014 it holds no provenance records, so nothing is lost \u2014 and re-run the merge to create an owned sidecar.`
|
|
3466
|
+
},
|
|
3467
|
+
"unupgradeable-legacy-sidecar": {
|
|
3468
|
+
describe: (graphId, targetGraphId) => `Graph id "${graphId}" holds a pre-marker provenance sidecar whose rows do not verify as provenance for target "${targetGraphId}", so it cannot be upgraded to an owned sidecar.`,
|
|
3469
|
+
suggestion: (graphId) => `Export anything you still need from graph id "${graphId}", then drop it: provenance is derived, and re-running the merge rebuilds an owned sidecar.`
|
|
3470
|
+
},
|
|
3471
|
+
"unowned-exact-schema-graph": {
|
|
3472
|
+
describe: (graphId) => `Graph id "${graphId}" carries the merge-provenance schema but no ownership marker, so this library did not create it.`,
|
|
3473
|
+
suggestion: (graphId) => `Drop graph id "${graphId}" (or rename the graph that occupies it) and re-run the merge: a sidecar this library owns writes its "${PROVENANCE_OWNER}" marker row BEFORE the schema, so a marker-less one carrying this schema was written either by an application \u2014 which is never adopted \u2014 or by a crash of an unreleased build between those two writes. Persisted provenance is derived, so re-running the merge rebuilds it.`
|
|
3474
|
+
}
|
|
3475
|
+
};
|
|
3476
|
+
function provenanceGraphIdCollision(graphId, targetGraphId, reason) {
|
|
3477
|
+
const refusal = SIDECAR_REFUSALS[reason];
|
|
3478
|
+
return new chunkNI72YOJB_cjs.ConfigurationError(
|
|
3479
|
+
refusal.describe(graphId, targetGraphId),
|
|
3480
|
+
{
|
|
3481
|
+
code: "GRAPH_MERGE_PROVENANCE_ID_COLLISION",
|
|
3482
|
+
reason,
|
|
3483
|
+
graphId,
|
|
3484
|
+
targetGraphId
|
|
3485
|
+
},
|
|
3486
|
+
{ suggestion: refusal.suggestion(graphId) }
|
|
3487
|
+
);
|
|
3488
|
+
}
|
|
3489
|
+
function provenanceClaimUnfenced(graphId, targetGraphId) {
|
|
3490
|
+
return new chunkNI72YOJB_cjs.ConfigurationError(
|
|
3491
|
+
`Claiming graph id "${graphId}" for merge provenance requires a transactional schema fence, which this backend does not provide.`,
|
|
3492
|
+
{
|
|
3493
|
+
code: "GRAPH_MERGE_PROVENANCE_CLAIM_UNFENCED",
|
|
3494
|
+
graphId,
|
|
3495
|
+
targetGraphId
|
|
3496
|
+
},
|
|
3497
|
+
{
|
|
3498
|
+
suggestion: "Use a backend that implements schemaWriteTransaction (both bundled Drizzle backends do when transactions are enabled); without it the sidecar's emptiness check and its ownership write cannot be committed as one unit. An ALREADY-owned sidecar opens without a claim."
|
|
3499
|
+
}
|
|
3500
|
+
);
|
|
3501
|
+
}
|
|
3502
|
+
function isOwnedMarkerRow(row, targetGraphId) {
|
|
3503
|
+
if (row.id !== PROVENANCE_OWNER_ID) return false;
|
|
3504
|
+
if (row.deleted_at !== void 0) return false;
|
|
3505
|
+
const parsed = ProvenanceOwner.schema.safeParse(parseRowProps(row.props));
|
|
3506
|
+
return parsed.success && parsed.data.targetGraphId === targetGraphId;
|
|
3507
|
+
}
|
|
3508
|
+
async function inspectOwnerMarker(port, graphId, targetGraphId) {
|
|
3509
|
+
let ours = false;
|
|
3510
|
+
for await (const row of readRowsOfKind(
|
|
3511
|
+
port,
|
|
3512
|
+
graphId,
|
|
3513
|
+
PROVENANCE_OWNER_KIND
|
|
3514
|
+
)) {
|
|
3515
|
+
if (!isOwnedMarkerRow(row, targetGraphId)) return "foreign";
|
|
3516
|
+
ours = true;
|
|
3517
|
+
}
|
|
3518
|
+
return ours ? "ours" : "absent";
|
|
3519
|
+
}
|
|
3520
|
+
var SIDECAR_PAGE_SIZE = 500;
|
|
3521
|
+
async function* readRowsOfKind(port, graphId, kind) {
|
|
3522
|
+
let after;
|
|
3523
|
+
for (; ; ) {
|
|
3524
|
+
const rows = await port.findNodesByKind({
|
|
3525
|
+
graphId,
|
|
3526
|
+
kind,
|
|
3527
|
+
temporalMode: "includeTombstones",
|
|
3528
|
+
excludeDeleted: false,
|
|
3529
|
+
orderBy: "id",
|
|
3530
|
+
...after === void 0 ? {} : { after },
|
|
3531
|
+
limit: SIDECAR_PAGE_SIZE
|
|
3532
|
+
});
|
|
3533
|
+
for (const row of rows) {
|
|
3534
|
+
yield row;
|
|
3535
|
+
}
|
|
3536
|
+
if (rows.length < SIDECAR_PAGE_SIZE) return;
|
|
3537
|
+
after = rows.at(-1)?.id;
|
|
3538
|
+
if (after === void 0) return;
|
|
3539
|
+
}
|
|
3540
|
+
}
|
|
3541
|
+
async function hasRowsUnderGraphId(port, graphId, scope) {
|
|
3542
|
+
const schema = chunkNFCVHQ5P_cjs.createSqlSchema(port.tableNames);
|
|
3543
|
+
const kindFilter = scope === "any" ? chunkVCRRKBLN_cjs.sql.empty() : chunkVCRRKBLN_cjs.sql` AND kind <> ${PROVENANCE_KIND}`;
|
|
3544
|
+
if (await hasRowsInTable(port, schema.tables.nodes, graphId, kindFilter)) {
|
|
3545
|
+
return true;
|
|
3546
|
+
}
|
|
3547
|
+
if (await hasRowsInTable(port, schema.tables.edges, graphId, chunkVCRRKBLN_cjs.sql.empty())) {
|
|
3548
|
+
return true;
|
|
3549
|
+
}
|
|
3550
|
+
for (const tableName of secondaryRowTableNames(schema.tables)) {
|
|
3551
|
+
if (await hasRowsInSecondaryTable(port, tableName, graphId)) return true;
|
|
3552
|
+
}
|
|
3553
|
+
return false;
|
|
3554
|
+
}
|
|
3555
|
+
function secondaryRowTableNames(tables) {
|
|
3556
|
+
return [
|
|
3557
|
+
.../* @__PURE__ */ new Set([
|
|
3558
|
+
tables.recordedNodes,
|
|
3559
|
+
tables.recordedEdges,
|
|
3560
|
+
tables.recordedClock,
|
|
3561
|
+
tables.revisionOrigins,
|
|
3562
|
+
tables.identityAssertions,
|
|
3563
|
+
tables.recordedIdentityAssertions,
|
|
3564
|
+
tables.identityClosure,
|
|
3565
|
+
tables.identitySeparation,
|
|
3566
|
+
tables.fulltext,
|
|
3567
|
+
tables.uniques
|
|
3568
|
+
])
|
|
3569
|
+
];
|
|
3570
|
+
}
|
|
3571
|
+
async function hasRowsInTable(port, tableName, graphId, filter) {
|
|
3572
|
+
const rows = await port.execute(
|
|
3573
|
+
chunkVCRRKBLN_cjs.asCompiledRowsSql(
|
|
3574
|
+
chunkVCRRKBLN_cjs.sql`SELECT 1 AS present FROM ${chunkVCRRKBLN_cjs.sql.identifier(tableName)} WHERE graph_id = ${graphId}${filter} LIMIT 1`
|
|
3575
|
+
)
|
|
3576
|
+
);
|
|
3577
|
+
return rows.length > 0;
|
|
3578
|
+
}
|
|
3579
|
+
async function hasRowsInSecondaryTable(port, tableName, graphId) {
|
|
3580
|
+
const tableExists = port.tableExists;
|
|
3581
|
+
if (tableExists !== void 0) {
|
|
3582
|
+
return await tableExists(tableName) && await hasRowsInTable(port, tableName, graphId, chunkVCRRKBLN_cjs.sql.empty());
|
|
3583
|
+
}
|
|
3584
|
+
try {
|
|
3585
|
+
return await hasRowsInTable(port, tableName, graphId, chunkVCRRKBLN_cjs.sql.empty());
|
|
3586
|
+
} catch {
|
|
3587
|
+
return false;
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3590
|
+
async function inspectSidecarContents(port, graphId, targetGraphId) {
|
|
3591
|
+
if (await hasRowsUnderGraphId(port, graphId, "foreign")) {
|
|
3592
|
+
return "foreign-rows";
|
|
3593
|
+
}
|
|
3594
|
+
let rowCount = 0;
|
|
3595
|
+
for await (const row of readRowsOfKind(port, graphId, PROVENANCE_KIND)) {
|
|
3596
|
+
if (!await isOwnedProvenanceRow(row, targetGraphId)) {
|
|
3597
|
+
return "unrecognized-provenance";
|
|
3598
|
+
}
|
|
3599
|
+
rowCount += 1;
|
|
3600
|
+
}
|
|
3601
|
+
return rowCount > 0 ? "provenance" : "empty";
|
|
3602
|
+
}
|
|
3603
|
+
async function isOwnedProvenanceRow(row, targetGraphId) {
|
|
3604
|
+
if (row.deleted_at !== void 0) return false;
|
|
3605
|
+
const parsed = Provenance.schema.safeParse(parseRowProps(row.props));
|
|
3606
|
+
if (!parsed.success || parsed.data.targetGraphId !== targetGraphId) {
|
|
3607
|
+
return false;
|
|
3608
|
+
}
|
|
3609
|
+
const expectedId = await provenanceNodeId(targetGraphId, {
|
|
3610
|
+
role: parsed.data.role,
|
|
3611
|
+
canonicalId: parsed.data.canonicalId,
|
|
3612
|
+
canonicalKind: parsed.data.canonicalKind,
|
|
3613
|
+
branchId: asBranchId(parsed.data.branchId),
|
|
3614
|
+
sourceId: parsed.data.sourceId
|
|
2190
3615
|
});
|
|
2191
|
-
|
|
2192
|
-
async function openProvenanceStore(...args) {
|
|
2193
|
-
const [backend, targetGraphId] = args.length === 1 ? [chunkJ7LXTUTP_cjs.storeBackend(args[0]), args[0].graphId] : args;
|
|
2194
|
-
const [store] = await chunkYOALGKRE_cjs.createStoreWithSchema(
|
|
2195
|
-
buildProvenanceGraph(targetGraphId),
|
|
2196
|
-
backend
|
|
2197
|
-
);
|
|
2198
|
-
return store;
|
|
3616
|
+
return row.id === expectedId;
|
|
2199
3617
|
}
|
|
2200
3618
|
var ID_SEPARATOR = "\0";
|
|
2201
3619
|
var ID_DIGEST_BYTES = 16;
|
|
3620
|
+
function contributionKey(record) {
|
|
3621
|
+
return encodeProvenanceTuple([
|
|
3622
|
+
record.role,
|
|
3623
|
+
record.canonicalKind,
|
|
3624
|
+
record.canonicalId,
|
|
3625
|
+
record.branchId,
|
|
3626
|
+
record.sourceId
|
|
3627
|
+
]);
|
|
3628
|
+
}
|
|
3629
|
+
function encodeProvenanceTuple(values) {
|
|
3630
|
+
return values.some((value) => value.includes(ID_SEPARATOR)) ? chunkXNLIZYRZ_cjs.encodeTupleKey(values) : values.join(ID_SEPARATOR);
|
|
3631
|
+
}
|
|
2202
3632
|
async function provenanceNodeId(targetGraphId, record) {
|
|
2203
|
-
const tuple = [
|
|
3633
|
+
const tuple = encodeProvenanceTuple([
|
|
2204
3634
|
targetGraphId,
|
|
2205
3635
|
record.role,
|
|
2206
|
-
// canonicalKind is part of node identity: two contributions to different-kind
|
|
2207
|
-
// canonicals that share a bare id (e.g. base Patient:x and Encounter:x) must NOT
|
|
2208
|
-
// hash to the same sidecar row and clobber each other (the (kind,id) identity model).
|
|
2209
3636
|
record.canonicalKind,
|
|
2210
3637
|
record.canonicalId,
|
|
2211
3638
|
record.branchId,
|
|
2212
3639
|
record.sourceId
|
|
2213
|
-
]
|
|
3640
|
+
]);
|
|
2214
3641
|
const digest = await chunkZY4GXIVN_cjs.sha256Hex(tuple, ID_DIGEST_BYTES);
|
|
2215
3642
|
return `prov_${digest}`;
|
|
2216
3643
|
}
|
|
@@ -2218,7 +3645,7 @@ async function persistProvenanceRecords(store, targetGraphId, records) {
|
|
|
2218
3645
|
if (records.length === 0) {
|
|
2219
3646
|
return 0;
|
|
2220
3647
|
}
|
|
2221
|
-
const
|
|
3648
|
+
const identified = await Promise.all(
|
|
2222
3649
|
records.map(async (record) => ({
|
|
2223
3650
|
id: await provenanceNodeId(targetGraphId, record),
|
|
2224
3651
|
props: {
|
|
@@ -2231,6 +3658,11 @@ async function persistProvenanceRecords(store, targetGraphId, records) {
|
|
|
2231
3658
|
}
|
|
2232
3659
|
}))
|
|
2233
3660
|
);
|
|
3661
|
+
const itemsById = /* @__PURE__ */ new Map();
|
|
3662
|
+
for (const item of identified) {
|
|
3663
|
+
itemsById.set(item.id, item);
|
|
3664
|
+
}
|
|
3665
|
+
const items = [...itemsById.values()];
|
|
2234
3666
|
await store.nodes.Provenance.bulkUpsertById(items);
|
|
2235
3667
|
return items.length;
|
|
2236
3668
|
}
|
|
@@ -2238,7 +3670,7 @@ async function readProvenance(store, query = {}) {
|
|
|
2238
3670
|
const all = await store.nodes.Provenance.find();
|
|
2239
3671
|
return all.filter(
|
|
2240
3672
|
(node) => (query.branchId === void 0 || node.branchId === query.branchId) && (query.canonicalId === void 0 || node.canonicalId === query.canonicalId) && (query.role === void 0 || node.role === query.role)
|
|
2241
|
-
).sort((left, right) =>
|
|
3673
|
+
).sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id));
|
|
2242
3674
|
}
|
|
2243
3675
|
|
|
2244
3676
|
// src/graph-merge/sources.ts
|
|
@@ -2248,14 +3680,14 @@ function orderEndpoints(left, right) {
|
|
|
2248
3680
|
return compareMergeKeys(leftKey, rightKey) <= 0 ? { a: leftKey, b: rightKey, left, right } : { a: rightKey, b: leftKey, left: right, right: left };
|
|
2249
3681
|
}
|
|
2250
3682
|
function sortMembersById(members) {
|
|
2251
|
-
return [...members].sort((left, right) =>
|
|
3683
|
+
return [...members].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id));
|
|
2252
3684
|
}
|
|
2253
3685
|
function sortedBucketKeys(blocks) {
|
|
2254
|
-
return [...blocks.keys()].sort((left, right) =>
|
|
3686
|
+
return [...blocks.keys()].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
2255
3687
|
}
|
|
2256
3688
|
var NODE_SYSTEM_FIELDS = /* @__PURE__ */ new Set(["id", "kind", "meta"]);
|
|
2257
3689
|
function nodeProps(node) {
|
|
2258
|
-
const props =
|
|
3690
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
2259
3691
|
for (const [key, value] of Object.entries(
|
|
2260
3692
|
node
|
|
2261
3693
|
)) {
|
|
@@ -2279,7 +3711,7 @@ function windowedPairs(members, config) {
|
|
|
2279
3711
|
key: fieldText(node, config.sortFields)
|
|
2280
3712
|
}));
|
|
2281
3713
|
keyed.sort(
|
|
2282
|
-
(left, right) => left.key === right.key ?
|
|
3714
|
+
(left, right) => left.key === right.key ? chunkXMQSEJCF_cjs.compareStrings(left.node.id, right.node.id) : chunkXMQSEJCF_cjs.compareStrings(left.key, right.key)
|
|
2283
3715
|
);
|
|
2284
3716
|
const pairs = [];
|
|
2285
3717
|
for (let index = 0; index < keyed.length; index += 1) {
|
|
@@ -2287,8 +3719,8 @@ function windowedPairs(members, config) {
|
|
|
2287
3719
|
for (let index_ = index + 1; index_ <= last; index_ += 1) {
|
|
2288
3720
|
pairs.push(
|
|
2289
3721
|
orderEndpoints(
|
|
2290
|
-
|
|
2291
|
-
|
|
3722
|
+
chunkN66HCGCY_cjs.requireDefined(keyed[index]).node,
|
|
3723
|
+
chunkN66HCGCY_cjs.requireDefined(keyed[index_]).node
|
|
2292
3724
|
)
|
|
2293
3725
|
);
|
|
2294
3726
|
}
|
|
@@ -2310,8 +3742,8 @@ function pairsFromBlocks(blocks, keyless) {
|
|
|
2310
3742
|
for (let index_ = index + 1; index_ < members.length; index_ += 1) {
|
|
2311
3743
|
pairs.push(
|
|
2312
3744
|
orderEndpoints(
|
|
2313
|
-
|
|
2314
|
-
|
|
3745
|
+
chunkN66HCGCY_cjs.requireDefined(members[index]),
|
|
3746
|
+
chunkN66HCGCY_cjs.requireDefined(members[index_])
|
|
2315
3747
|
)
|
|
2316
3748
|
);
|
|
2317
3749
|
}
|
|
@@ -2329,8 +3761,8 @@ function forcedEdgesFromBlocks(blocks) {
|
|
|
2329
3761
|
for (let index = 0; index < members.length; index += 1) {
|
|
2330
3762
|
for (let index_ = index + 1; index_ < members.length; index_ += 1) {
|
|
2331
3763
|
const { a, b } = orderEndpoints(
|
|
2332
|
-
|
|
2333
|
-
|
|
3764
|
+
chunkN66HCGCY_cjs.requireDefined(members[index]),
|
|
3765
|
+
chunkN66HCGCY_cjs.requireDefined(members[index_])
|
|
2334
3766
|
);
|
|
2335
3767
|
edges.push({ a, b, score: FORCED_MATCH_SCORE });
|
|
2336
3768
|
}
|
|
@@ -2350,7 +3782,7 @@ function ontologyRetypeEdges(stagedIdentities, isRetypeCompatible) {
|
|
|
2350
3782
|
}
|
|
2351
3783
|
}
|
|
2352
3784
|
const edges = [];
|
|
2353
|
-
for (const id of [...identitiesById.keys()].sort(
|
|
3785
|
+
for (const id of [...identitiesById.keys()].sort(chunkXMQSEJCF_cjs.compareStrings)) {
|
|
2354
3786
|
const identities = [...new Set(identitiesById.get(id))].sort(
|
|
2355
3787
|
compareMergeKeys
|
|
2356
3788
|
);
|
|
@@ -2364,8 +3796,8 @@ function ontologyRetypeEdges(stagedIdentities, isRetypeCompatible) {
|
|
|
2364
3796
|
}
|
|
2365
3797
|
for (let index = 1; index < members.length; index += 1) {
|
|
2366
3798
|
edges.push({
|
|
2367
|
-
a:
|
|
2368
|
-
b:
|
|
3799
|
+
a: chunkN66HCGCY_cjs.requireDefined(members[0]),
|
|
3800
|
+
b: chunkN66HCGCY_cjs.requireDefined(members[index]),
|
|
2369
3801
|
score: FORCED_MATCH_SCORE
|
|
2370
3802
|
});
|
|
2371
3803
|
}
|
|
@@ -2381,12 +3813,12 @@ function unionByCompatibility(identities, isRetypeCompatible) {
|
|
|
2381
3813
|
for (let index = 0; index < identities.length; index += 1) {
|
|
2382
3814
|
for (let index_ = index + 1; index_ < identities.length; index_ += 1) {
|
|
2383
3815
|
if (isRetypeCompatible([
|
|
2384
|
-
kindOf(
|
|
2385
|
-
kindOf(
|
|
3816
|
+
kindOf(chunkN66HCGCY_cjs.requireDefined(identities[index])),
|
|
3817
|
+
kindOf(chunkN66HCGCY_cjs.requireDefined(identities[index_]))
|
|
2386
3818
|
])) {
|
|
2387
3819
|
forest.union(
|
|
2388
|
-
|
|
2389
|
-
|
|
3820
|
+
chunkN66HCGCY_cjs.requireDefined(identities[index]),
|
|
3821
|
+
chunkN66HCGCY_cjs.requireDefined(identities[index_])
|
|
2390
3822
|
);
|
|
2391
3823
|
}
|
|
2392
3824
|
}
|
|
@@ -2398,7 +3830,7 @@ function unionByCompatibility(identities, isRetypeCompatible) {
|
|
|
2398
3830
|
function groupsOf(identities, representativeOf) {
|
|
2399
3831
|
const byRoot = /* @__PURE__ */ new Map();
|
|
2400
3832
|
for (const identity of identities) {
|
|
2401
|
-
const root =
|
|
3833
|
+
const root = chunkN66HCGCY_cjs.requireDefined(representativeOf.get(identity));
|
|
2402
3834
|
const bucket = byRoot.get(root);
|
|
2403
3835
|
if (bucket === void 0) {
|
|
2404
3836
|
byRoot.set(root, [identity]);
|
|
@@ -2445,7 +3877,7 @@ var baseUniqueSource = {
|
|
|
2445
3877
|
const forcedEdges = [];
|
|
2446
3878
|
const baseMembers = /* @__PURE__ */ new Map();
|
|
2447
3879
|
const constraints = [...uniqueConstraints].sort(
|
|
2448
|
-
(left, right) =>
|
|
3880
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.name, right.name)
|
|
2449
3881
|
);
|
|
2450
3882
|
const items = nodes.map((node) => ({ props: nodeProps(node) }));
|
|
2451
3883
|
const matchesByConstraint = await Promise.all(
|
|
@@ -2488,7 +3920,7 @@ var baseUniqueSource = {
|
|
|
2488
3920
|
pairs: [],
|
|
2489
3921
|
forcedEdges,
|
|
2490
3922
|
baseMembers: [...baseMembers.values()].sort(
|
|
2491
|
-
(left, right) =>
|
|
3923
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
2492
3924
|
)
|
|
2493
3925
|
};
|
|
2494
3926
|
}
|
|
@@ -2545,7 +3977,7 @@ var baseKeySource = {
|
|
|
2545
3977
|
pairs,
|
|
2546
3978
|
forcedEdges: [],
|
|
2547
3979
|
baseMembers: [...baseMembers.values()].sort(
|
|
2548
|
-
(left, right) =>
|
|
3980
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
2549
3981
|
)
|
|
2550
3982
|
};
|
|
2551
3983
|
}
|
|
@@ -2557,16 +3989,16 @@ var CANDIDATE_SOURCES = [
|
|
|
2557
3989
|
|
|
2558
3990
|
// src/graph-merge/staging.ts
|
|
2559
3991
|
function compareByIdThenBranch(left, right) {
|
|
2560
|
-
const byId2 =
|
|
2561
|
-
return byId2 === 0 ?
|
|
3992
|
+
const byId2 = chunkXMQSEJCF_cjs.compareStrings(left.id, right.id);
|
|
3993
|
+
return byId2 === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.branchId, right.branchId) : byId2;
|
|
2562
3994
|
}
|
|
2563
3995
|
function compareByKindIdBranch(left, right) {
|
|
2564
|
-
const byKind =
|
|
3996
|
+
const byKind = chunkXMQSEJCF_cjs.compareStrings(left.kind, right.kind);
|
|
2565
3997
|
if (byKind !== 0) {
|
|
2566
3998
|
return byKind;
|
|
2567
3999
|
}
|
|
2568
|
-
const byId2 =
|
|
2569
|
-
return byId2 === 0 ?
|
|
4000
|
+
const byId2 = chunkXMQSEJCF_cjs.compareStrings(left.id, right.id);
|
|
4001
|
+
return byId2 === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.branchId, right.branchId) : byId2;
|
|
2570
4002
|
}
|
|
2571
4003
|
function groupByKind(items) {
|
|
2572
4004
|
const buckets = /* @__PURE__ */ new Map();
|
|
@@ -2580,11 +4012,11 @@ function groupByKind(items) {
|
|
|
2580
4012
|
}
|
|
2581
4013
|
const ordered = /* @__PURE__ */ new Map();
|
|
2582
4014
|
for (const kind of [...buckets.keys()].sort(
|
|
2583
|
-
(left, right) =>
|
|
4015
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
2584
4016
|
)) {
|
|
2585
4017
|
ordered.set(
|
|
2586
4018
|
kind,
|
|
2587
|
-
[...
|
|
4019
|
+
[...chunkN66HCGCY_cjs.requireDefined(buckets.get(kind))].sort(
|
|
2588
4020
|
(left, right) => compareByIdThenBranch(left, right)
|
|
2589
4021
|
)
|
|
2590
4022
|
);
|
|
@@ -2598,6 +4030,11 @@ async function stageBranches(baseStore, branches, captureTargetStateFor) {
|
|
|
2598
4030
|
const newEdges = [];
|
|
2599
4031
|
const modifiedEdges = [];
|
|
2600
4032
|
const deletedEdges = [];
|
|
4033
|
+
const windowedNodes = [];
|
|
4034
|
+
const windowedEdges = [];
|
|
4035
|
+
const newIdentityAssertions = [];
|
|
4036
|
+
const retractedIdentityAssertions = [];
|
|
4037
|
+
const baseIdentityAssertions = await chunkTTAITEPJ_cjs.storeRuntime(baseStore).readCurrentIdentityAssertions("state");
|
|
2601
4038
|
let targetNodeVersions = /* @__PURE__ */ new Map();
|
|
2602
4039
|
let targetEdgeSignatures = /* @__PURE__ */ new Map();
|
|
2603
4040
|
for (const branch2 of branches) {
|
|
@@ -2629,6 +4066,22 @@ async function stageBranches(baseStore, branches, captureTargetStateFor) {
|
|
|
2629
4066
|
for (const edge of diff.edges.deleted) {
|
|
2630
4067
|
deletedEdges.push({ branchId, edge, kind: edge.kind, id: edge.id });
|
|
2631
4068
|
}
|
|
4069
|
+
for (const node of diff.nodes.windowed) {
|
|
4070
|
+
windowedNodes.push({ branchId, node, kind: node.kind, id: node.id });
|
|
4071
|
+
}
|
|
4072
|
+
for (const edge of diff.edges.windowed) {
|
|
4073
|
+
windowedEdges.push({ branchId, edge, kind: edge.kind, id: edge.id });
|
|
4074
|
+
}
|
|
4075
|
+
for (const assertion of diff.identity.new) {
|
|
4076
|
+
newIdentityAssertions.push({ branchId, assertion });
|
|
4077
|
+
}
|
|
4078
|
+
for (const retraction of diff.identity.retracted) {
|
|
4079
|
+
retractedIdentityAssertions.push({
|
|
4080
|
+
branchId,
|
|
4081
|
+
assertion: retraction.assertion,
|
|
4082
|
+
cause: retraction.cause
|
|
4083
|
+
});
|
|
4084
|
+
}
|
|
2632
4085
|
}
|
|
2633
4086
|
return {
|
|
2634
4087
|
newNodesByKind: groupByKind(newNodes),
|
|
@@ -2645,6 +4098,25 @@ async function stageBranches(baseStore, branches, captureTargetStateFor) {
|
|
|
2645
4098
|
deletedEdges: [...deletedEdges].sort(
|
|
2646
4099
|
(left, right) => compareByKindIdBranch(left, right)
|
|
2647
4100
|
),
|
|
4101
|
+
windowedNodes: [...windowedNodes].sort(
|
|
4102
|
+
(left, right) => compareByKindIdBranch(left, right)
|
|
4103
|
+
),
|
|
4104
|
+
windowedEdges: [...windowedEdges].sort(
|
|
4105
|
+
(left, right) => compareByKindIdBranch(left, right)
|
|
4106
|
+
),
|
|
4107
|
+
newIdentityAssertions: newIdentityAssertions.toSorted((left, right) => {
|
|
4108
|
+
const byId2 = chunkXMQSEJCF_cjs.compareStrings(left.assertion.id, right.assertion.id);
|
|
4109
|
+
return byId2 === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.branchId, right.branchId) : byId2;
|
|
4110
|
+
}),
|
|
4111
|
+
retractedIdentityAssertions: retractedIdentityAssertions.toSorted(
|
|
4112
|
+
(left, right) => {
|
|
4113
|
+
const byId2 = chunkXMQSEJCF_cjs.compareStrings(left.assertion.id, right.assertion.id);
|
|
4114
|
+
return byId2 === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.branchId, right.branchId) : byId2;
|
|
4115
|
+
}
|
|
4116
|
+
),
|
|
4117
|
+
baseIdentityAssertions: baseIdentityAssertions.toSorted(
|
|
4118
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
4119
|
+
),
|
|
2648
4120
|
targetNodeVersions,
|
|
2649
4121
|
targetEdgeSignatures
|
|
2650
4122
|
};
|
|
@@ -2695,7 +4167,7 @@ async function withTxConflictRetry(commit) {
|
|
|
2695
4167
|
// src/graph-merge/type-reconcile.ts
|
|
2696
4168
|
var INCOMPATIBLE_TYPES_FLAG_REASON = "type-reconcile:incompatible-kinds";
|
|
2697
4169
|
function distinctKinds(kinds) {
|
|
2698
|
-
return [...new Set(kinds)].sort((left, right) =>
|
|
4170
|
+
return [...new Set(kinds)].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
2699
4171
|
}
|
|
2700
4172
|
function areEquivalent(closure, left, right) {
|
|
2701
4173
|
return left !== right && isReachable2(closure, left, right) && isReachable2(closure, right, left);
|
|
@@ -2713,8 +4185,8 @@ function mostSpecificCommonKind(closure, kinds) {
|
|
|
2713
4185
|
if (qualifiers.length === 0) {
|
|
2714
4186
|
return void 0;
|
|
2715
4187
|
}
|
|
2716
|
-
return
|
|
2717
|
-
[...qualifiers].sort((left, right) =>
|
|
4188
|
+
return chunkN66HCGCY_cjs.requireDefined(
|
|
4189
|
+
[...qualifiers].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right))[0]
|
|
2718
4190
|
);
|
|
2719
4191
|
}
|
|
2720
4192
|
function reconcileTypes(clusters, closure, mode) {
|
|
@@ -2752,15 +4224,14 @@ function reconcileTypes(clusters, closure, mode) {
|
|
|
2752
4224
|
}
|
|
2753
4225
|
return {
|
|
2754
4226
|
reconciliations: reconciliations.sort(
|
|
2755
|
-
(left, right) =>
|
|
4227
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.entityId, right.entityId)
|
|
2756
4228
|
),
|
|
2757
4229
|
retypeMap,
|
|
2758
|
-
dropped: dropped.sort((left, right) =>
|
|
4230
|
+
dropped: dropped.sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id))
|
|
2759
4231
|
};
|
|
2760
4232
|
}
|
|
2761
4233
|
|
|
2762
4234
|
// src/graph-merge/merge.ts
|
|
2763
|
-
var COMMITTED_TARGET_BRANCH = asBranchId("__committed_target__");
|
|
2764
4235
|
function asNode(staged) {
|
|
2765
4236
|
return {
|
|
2766
4237
|
kind: staged.node.kind,
|
|
@@ -2774,8 +4245,8 @@ function newNodesByKind(staging) {
|
|
|
2774
4245
|
ordered.set(
|
|
2775
4246
|
kind,
|
|
2776
4247
|
[...items].sort((left, right) => {
|
|
2777
|
-
const byId2 =
|
|
2778
|
-
return byId2 === 0 ?
|
|
4248
|
+
const byId2 = chunkXMQSEJCF_cjs.compareStrings(left.node.id, right.node.id);
|
|
4249
|
+
return byId2 === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.branchId, right.branchId) : byId2;
|
|
2779
4250
|
})
|
|
2780
4251
|
);
|
|
2781
4252
|
}
|
|
@@ -2802,12 +4273,14 @@ async function precomputeEmbeddings(byKind, resolve, embedder) {
|
|
|
2802
4273
|
}
|
|
2803
4274
|
}
|
|
2804
4275
|
}
|
|
2805
|
-
const lookup = /* @__PURE__ */ new Map();
|
|
2806
4276
|
if (texts.size === 0) {
|
|
2807
|
-
return
|
|
4277
|
+
return /* @__PURE__ */ new Map();
|
|
2808
4278
|
}
|
|
4279
|
+
return embedSortedTexts(texts, embedder);
|
|
4280
|
+
}
|
|
4281
|
+
async function embedSortedTexts(texts, embedder) {
|
|
2809
4282
|
const orderedTexts = [...texts].sort(
|
|
2810
|
-
(left, right) =>
|
|
4283
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
2811
4284
|
);
|
|
2812
4285
|
const vectors = await embedder(orderedTexts);
|
|
2813
4286
|
if (vectors.length !== orderedTexts.length) {
|
|
@@ -2819,8 +4292,9 @@ async function precomputeEmbeddings(byKind, resolve, embedder) {
|
|
|
2819
4292
|
}
|
|
2820
4293
|
);
|
|
2821
4294
|
}
|
|
4295
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
2822
4296
|
for (const [index, text] of orderedTexts.entries()) {
|
|
2823
|
-
lookup.set(text,
|
|
4297
|
+
lookup.set(text, chunkN66HCGCY_cjs.requireDefined(vectors[index]));
|
|
2824
4298
|
}
|
|
2825
4299
|
return lookup;
|
|
2826
4300
|
}
|
|
@@ -2842,24 +4316,7 @@ async function embedMissingPairTexts(base, pairs, strategy, embedder) {
|
|
|
2842
4316
|
if (missing.size === 0) {
|
|
2843
4317
|
return existing;
|
|
2844
4318
|
}
|
|
2845
|
-
|
|
2846
|
-
(left, right) => chunkTRF4EBJT_cjs.compareStrings(left, right)
|
|
2847
|
-
);
|
|
2848
|
-
const vectors = await embedder(orderedTexts);
|
|
2849
|
-
if (vectors.length !== orderedTexts.length) {
|
|
2850
|
-
throw new MergeError(
|
|
2851
|
-
`Embedder returned ${vectors.length} vectors for ${orderedTexts.length} texts; expected exactly one per text.`,
|
|
2852
|
-
{
|
|
2853
|
-
details: { texts: orderedTexts.length, vectors: vectors.length },
|
|
2854
|
-
suggestion: "Ensure MergeOptions.embedder returns one vector per input text, in order."
|
|
2855
|
-
}
|
|
2856
|
-
);
|
|
2857
|
-
}
|
|
2858
|
-
const augmented = new Map(existing);
|
|
2859
|
-
for (const [index, text] of orderedTexts.entries()) {
|
|
2860
|
-
augmented.set(text, chunk764JHTLT_cjs.requireDefined(vectors[index]));
|
|
2861
|
-
}
|
|
2862
|
-
return augmented;
|
|
4319
|
+
return new Map([...existing, ...await embedSortedTexts(missing, embedder)]);
|
|
2863
4320
|
}
|
|
2864
4321
|
async function generateAllCandidates(target, staging, options, introspectionKinds, ctx, useBaseSources, embedder) {
|
|
2865
4322
|
const allEdges = [];
|
|
@@ -2873,7 +4330,7 @@ async function generateAllCandidates(target, staging, options, introspectionKind
|
|
|
2873
4330
|
async ([kind, items]) => {
|
|
2874
4331
|
const resolveConfig = options.resolve[kind];
|
|
2875
4332
|
if (resolveConfig === void 0) {
|
|
2876
|
-
return
|
|
4333
|
+
return chunk7BQXPCGN_cjs.ok({ edges: [], warnings: [], baseMembers: [] });
|
|
2877
4334
|
}
|
|
2878
4335
|
const nodes = items.map((staged) => asNode(staged));
|
|
2879
4336
|
const uniqueConstraints = uniqueConstraintsFor(
|
|
@@ -2916,10 +4373,10 @@ async function generateAllCandidates(target, staging, options, introspectionKind
|
|
|
2916
4373
|
options.onComparisonCeiling,
|
|
2917
4374
|
options.maxComparisonsPerKind
|
|
2918
4375
|
);
|
|
2919
|
-
if (
|
|
2920
|
-
return
|
|
4376
|
+
if (chunk7BQXPCGN_cjs.isErr(scored)) {
|
|
4377
|
+
return chunk7BQXPCGN_cjs.err(scored.error);
|
|
2921
4378
|
}
|
|
2922
|
-
return
|
|
4379
|
+
return chunk7BQXPCGN_cjs.ok({
|
|
2923
4380
|
edges: scored.data.edges,
|
|
2924
4381
|
warnings: scored.data.warnings.map(
|
|
2925
4382
|
(warning) => `[${kind}] ${warning.message}`
|
|
@@ -2930,14 +4387,14 @@ async function generateAllCandidates(target, staging, options, introspectionKind
|
|
|
2930
4387
|
)
|
|
2931
4388
|
);
|
|
2932
4389
|
for (const result of perKind) {
|
|
2933
|
-
if (
|
|
2934
|
-
return
|
|
4390
|
+
if (chunk7BQXPCGN_cjs.isErr(result)) {
|
|
4391
|
+
return chunk7BQXPCGN_cjs.err(result.error);
|
|
2935
4392
|
}
|
|
2936
4393
|
allEdges.push(...result.data.edges);
|
|
2937
4394
|
warnings.push(...result.data.warnings);
|
|
2938
4395
|
baseMembers.push(...result.data.baseMembers);
|
|
2939
4396
|
}
|
|
2940
|
-
return
|
|
4397
|
+
return chunk7BQXPCGN_cjs.ok({
|
|
2941
4398
|
// The ONE shared `(a, b)` edge comparator (id-first `(kind, id)` order), so this
|
|
2942
4399
|
// stage emits edges in exactly the order clustering consumes them.
|
|
2943
4400
|
edges: allEdges.sort((left, right) => compareCandidateEdges(left, right)),
|
|
@@ -2958,7 +4415,9 @@ function clusterMembersFor(cluster, newNodesById, baseMembersById) {
|
|
|
2958
4415
|
id: staged.node.id,
|
|
2959
4416
|
kind: staged.node.kind,
|
|
2960
4417
|
branchId: staged.branchId,
|
|
2961
|
-
props: staged.node.props
|
|
4418
|
+
props: staged.node.props,
|
|
4419
|
+
...staged.node.row.valid_from === void 0 ? {} : { validFrom: staged.node.row.valid_from },
|
|
4420
|
+
...staged.node.row.valid_to === void 0 ? {} : { validTo: staged.node.row.valid_to }
|
|
2962
4421
|
});
|
|
2963
4422
|
}
|
|
2964
4423
|
const base = baseMembersById.get(key);
|
|
@@ -2989,37 +4448,70 @@ function indexNewNodesById(staging) {
|
|
|
2989
4448
|
}
|
|
2990
4449
|
return index;
|
|
2991
4450
|
}
|
|
2992
|
-
function buildStagedEdges(staging, modifiedEdges) {
|
|
4451
|
+
function buildStagedEdges(staging, modifiedEdges, edgeValidityEnds, edgeDeletions) {
|
|
2993
4452
|
const staged = [];
|
|
4453
|
+
const stagedIdentities = /* @__PURE__ */ new Set();
|
|
4454
|
+
const windowOnlyCarried = /* @__PURE__ */ new Set();
|
|
2994
4455
|
for (const items of staging.newEdgesByKind.values()) {
|
|
2995
4456
|
for (const item of items) {
|
|
2996
4457
|
staged.push(toStagedEdge(item.branchId, item));
|
|
2997
4458
|
}
|
|
2998
4459
|
}
|
|
2999
4460
|
for (const item of modifiedEdges) {
|
|
4461
|
+
const identity = mergeKeyOf(item.edge);
|
|
4462
|
+
stagedIdentities.add(identity);
|
|
4463
|
+
const validTo = edgeValidityEnds.get(identity);
|
|
3000
4464
|
staged.push({
|
|
3001
4465
|
id: item.edge.id,
|
|
3002
4466
|
kind: item.edge.kind,
|
|
4467
|
+
origin: INHERITED_EDGE_ORIGIN,
|
|
3003
4468
|
fromId: item.edge.fromId,
|
|
3004
4469
|
toId: item.edge.toId,
|
|
3005
4470
|
fromKind: item.edge.fromKind,
|
|
3006
4471
|
toKind: item.edge.toKind,
|
|
3007
4472
|
props: item.edge.forkProps,
|
|
3008
|
-
|
|
4473
|
+
baseProps: item.edge.baseProps,
|
|
4474
|
+
branchId: item.branchId,
|
|
4475
|
+
...validTo === void 0 ? {} : { validTo }
|
|
4476
|
+
});
|
|
4477
|
+
}
|
|
4478
|
+
for (const item of staging.windowedEdges) {
|
|
4479
|
+
const identity = mergeKeyOf(item.edge);
|
|
4480
|
+
const validTo = edgeValidityEnds.get(identity);
|
|
4481
|
+
if (validTo === void 0 || stagedIdentities.has(identity) || edgeDeletions.has(identity)) {
|
|
4482
|
+
continue;
|
|
4483
|
+
}
|
|
4484
|
+
stagedIdentities.add(identity);
|
|
4485
|
+
windowOnlyCarried.add(identity);
|
|
4486
|
+
staged.push({
|
|
4487
|
+
id: item.edge.id,
|
|
4488
|
+
kind: item.edge.kind,
|
|
4489
|
+
origin: INHERITED_EDGE_ORIGIN,
|
|
4490
|
+
fromId: item.edge.fromId,
|
|
4491
|
+
toId: item.edge.toId,
|
|
4492
|
+
fromKind: item.edge.fromKind,
|
|
4493
|
+
toKind: item.edge.toKind,
|
|
4494
|
+
props: item.edge.props,
|
|
4495
|
+
baseProps: item.edge.baseProps,
|
|
4496
|
+
branchId: item.branchId,
|
|
4497
|
+
validTo
|
|
3009
4498
|
});
|
|
3010
4499
|
}
|
|
3011
|
-
return staged;
|
|
4500
|
+
return { edges: staged, windowOnlyCarried };
|
|
3012
4501
|
}
|
|
3013
4502
|
function toStagedEdge(branchId, item) {
|
|
3014
4503
|
return {
|
|
3015
4504
|
id: item.edge.id,
|
|
3016
4505
|
kind: item.edge.kind,
|
|
4506
|
+
origin: BRANCH_CREATED_EDGE_ORIGIN,
|
|
3017
4507
|
fromId: item.edge.fromId,
|
|
3018
4508
|
toId: item.edge.toId,
|
|
3019
4509
|
fromKind: item.edge.fromKind,
|
|
3020
4510
|
toKind: item.edge.toKind,
|
|
3021
4511
|
props: item.edge.props,
|
|
3022
|
-
branchId
|
|
4512
|
+
branchId,
|
|
4513
|
+
...item.edge.row.valid_from === void 0 ? {} : { validFrom: item.edge.row.valid_from },
|
|
4514
|
+
...item.edge.row.valid_to === void 0 ? {} : { validTo: item.edge.row.valid_to }
|
|
3023
4515
|
};
|
|
3024
4516
|
}
|
|
3025
4517
|
function buildProvenanceIndex(records) {
|
|
@@ -3040,34 +4532,38 @@ function buildProvenanceIndex(records) {
|
|
|
3040
4532
|
for (const [branchId, sets] of byBranch) {
|
|
3041
4533
|
frozen.set(branchId, {
|
|
3042
4534
|
nodeIds: [...sets.nodeIds].sort(
|
|
3043
|
-
(left, right) =>
|
|
4535
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
3044
4536
|
),
|
|
3045
|
-
edgeIds: [...sets.edgeIds].sort((left, right) =>
|
|
4537
|
+
edgeIds: [...sets.edgeIds].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)).map((id) => id)
|
|
3046
4538
|
});
|
|
3047
4539
|
}
|
|
3048
4540
|
return {
|
|
3049
4541
|
byBranch: (branchId) => frozen.get(branchId) ?? { nodeIds: [], edgeIds: [] }
|
|
3050
4542
|
};
|
|
3051
4543
|
}
|
|
3052
|
-
function pushProvenance(records, role, branchId, canonicalId, canonicalKind, sourceId) {
|
|
3053
|
-
records.push({ role, canonicalId, canonicalKind, branchId, sourceId });
|
|
3054
|
-
}
|
|
3055
4544
|
var EMPTY_WEIGHTS = /* @__PURE__ */ new Map();
|
|
3056
|
-
function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, options, branchRank, subClassClosure, preferredBranchId) {
|
|
4545
|
+
function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, options, branchRank, subClassClosure, identityContext, storedIdentityRowsById, targetPeers, preferredBranchId) {
|
|
4546
|
+
const identity = planIdentityChanges(staging, storedIdentityRowsById);
|
|
3057
4547
|
const provenanceRecords = [];
|
|
4548
|
+
const recordedContributions = /* @__PURE__ */ new Set();
|
|
3058
4549
|
const weights = options.provenanceWeights ?? EMPTY_WEIGHTS;
|
|
3059
4550
|
const recordProvenance = (role, branchId, canonicalId, canonicalKind, sourceId) => {
|
|
3060
4551
|
if (branchId === preferredBranchId) {
|
|
3061
4552
|
return;
|
|
3062
4553
|
}
|
|
3063
|
-
|
|
3064
|
-
provenanceRecords,
|
|
4554
|
+
const record = {
|
|
3065
4555
|
role,
|
|
3066
|
-
branchId,
|
|
3067
4556
|
canonicalId,
|
|
3068
4557
|
canonicalKind,
|
|
4558
|
+
branchId,
|
|
3069
4559
|
sourceId
|
|
3070
|
-
|
|
4560
|
+
};
|
|
4561
|
+
const key = contributionKey(record);
|
|
4562
|
+
if (recordedContributions.has(key)) {
|
|
4563
|
+
return;
|
|
4564
|
+
}
|
|
4565
|
+
recordedContributions.add(key);
|
|
4566
|
+
provenanceRecords.push(record);
|
|
3071
4567
|
};
|
|
3072
4568
|
const newNodesById = indexNewNodesById(staging);
|
|
3073
4569
|
const acceptedEndpointKeys = /* @__PURE__ */ new Set();
|
|
@@ -3160,6 +4656,34 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3160
4656
|
for (const deletion of deleteModify.nodeDeletions) {
|
|
3161
4657
|
nodeDeletions.set(mergeKey(deletion.kind, deletion.id), deletion.kind);
|
|
3162
4658
|
}
|
|
4659
|
+
const anyDeletionOverruled = staging.deletedNodes.some(
|
|
4660
|
+
(deletion) => !nodeDeletions.has(mergeKey(deletion.node.kind, deletion.node.id))
|
|
4661
|
+
);
|
|
4662
|
+
const stagedRetractionsById = /* @__PURE__ */ new Map();
|
|
4663
|
+
for (const staged of staging.retractedIdentityAssertions) {
|
|
4664
|
+
const contributions = stagedRetractionsById.get(staged.assertion.id) ?? [];
|
|
4665
|
+
contributions.push(staged);
|
|
4666
|
+
stagedRetractionsById.set(staged.assertion.id, contributions);
|
|
4667
|
+
}
|
|
4668
|
+
const overruledRetractionDrops = [];
|
|
4669
|
+
const survivingRetractions = anyDeletionOverruled ? identity.retractions.filter((retraction) => {
|
|
4670
|
+
const contributions = stagedRetractionsById.get(retraction.id) ?? [];
|
|
4671
|
+
const everyContributionOverruled = contributions.length > 0 && contributions.every(
|
|
4672
|
+
(staged) => staged.cause.kind === "cascade" && !nodeDeletions.has(
|
|
4673
|
+
mergeKey(
|
|
4674
|
+
staged.cause.deletedNode.kind,
|
|
4675
|
+
staged.cause.deletedNode.id
|
|
4676
|
+
)
|
|
4677
|
+
)
|
|
4678
|
+
);
|
|
4679
|
+
if (!everyContributionOverruled) return true;
|
|
4680
|
+
overruledRetractionDrops.push({
|
|
4681
|
+
kind: "identity",
|
|
4682
|
+
id: retraction.id,
|
|
4683
|
+
reason: RETRACTION_DELETION_OVERRULED_DROP_REASON
|
|
4684
|
+
});
|
|
4685
|
+
return false;
|
|
4686
|
+
}) : identity.retractions;
|
|
3163
4687
|
for (const modification of deleteModify.survivingModifications) {
|
|
3164
4688
|
recordProvenance(
|
|
3165
4689
|
"node",
|
|
@@ -3208,6 +4732,31 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3208
4732
|
for (const conflict of reconciledEdgeModifications.conflicts) {
|
|
3209
4733
|
propertyConflicts.push(conflict);
|
|
3210
4734
|
}
|
|
4735
|
+
const validWindows = resolveValidWindows(
|
|
4736
|
+
staging,
|
|
4737
|
+
new Set(nodeDeletions.keys()),
|
|
4738
|
+
new Set(edgeDeletions.keys()),
|
|
4739
|
+
preferredBranchId
|
|
4740
|
+
);
|
|
4741
|
+
const creditedNodeIdentities = /* @__PURE__ */ new Map();
|
|
4742
|
+
for (const record of provenanceRecords) {
|
|
4743
|
+
if (record.role !== "node" || record.sourceId !== record.canonicalId) {
|
|
4744
|
+
continue;
|
|
4745
|
+
}
|
|
4746
|
+
const identity2 = mergeKey(record.canonicalKind, record.canonicalId);
|
|
4747
|
+
const credited = creditedNodeIdentities.get(identity2) ?? /* @__PURE__ */ new Set();
|
|
4748
|
+
credited.add(record.branchId);
|
|
4749
|
+
creditedNodeIdentities.set(identity2, credited);
|
|
4750
|
+
}
|
|
4751
|
+
for (const [identity2, branchIds] of validWindows.nodeCredits) {
|
|
4752
|
+
for (const branchId of branchIds) {
|
|
4753
|
+
if (creditedNodeIdentities.get(identity2)?.has(branchId) === true) {
|
|
4754
|
+
continue;
|
|
4755
|
+
}
|
|
4756
|
+
const id = idOf(identity2);
|
|
4757
|
+
recordProvenance("node", branchId, id, kindOf(identity2), id);
|
|
4758
|
+
}
|
|
4759
|
+
}
|
|
3211
4760
|
const reconciliation = reconcileTypes(
|
|
3212
4761
|
reconcileInputs,
|
|
3213
4762
|
subClassClosure,
|
|
@@ -3221,18 +4770,57 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3221
4770
|
clusters,
|
|
3222
4771
|
(cluster) => pickClusterCanonical(cluster, entityByIdentity)
|
|
3223
4772
|
);
|
|
3224
|
-
const
|
|
4773
|
+
const identityRemap = remapIdentityAssertionEndpoints(
|
|
4774
|
+
identity.assertions,
|
|
4775
|
+
canonicalOf,
|
|
4776
|
+
reconciliation.retypeMap,
|
|
4777
|
+
storedIdentityRowsById
|
|
4778
|
+
);
|
|
4779
|
+
assertIdentityEndpointsNotDeleted(
|
|
4780
|
+
identityRemap.assertions,
|
|
4781
|
+
nodeDeletions,
|
|
4782
|
+
reconciliation.retypeMap
|
|
4783
|
+
);
|
|
4784
|
+
const identityNodeUniverse = [
|
|
4785
|
+
...canonicalEntities.filter(
|
|
4786
|
+
(entity) => !nodeDeletions.has(mergeKey(entity.kind, entity.canonicalId))
|
|
4787
|
+
).map((entity) => ({
|
|
4788
|
+
kind: reconciliation.retypeMap.get(
|
|
4789
|
+
mergeKey(entity.kind, entity.canonicalId)
|
|
4790
|
+
) ?? entity.kind,
|
|
4791
|
+
id: entity.canonicalId
|
|
4792
|
+
})),
|
|
4793
|
+
...targetPeers.filter(
|
|
4794
|
+
(node) => !nodeDeletions.has(mergeKey(node.kind, node.id))
|
|
4795
|
+
)
|
|
4796
|
+
];
|
|
4797
|
+
assertNoContradictoryIdentityClosure(
|
|
4798
|
+
identityRemap.assertions,
|
|
4799
|
+
survivingRetractions.map((retraction) => retraction.id),
|
|
4800
|
+
staging.baseIdentityAssertions,
|
|
4801
|
+
new Set(nodeDeletions.keys()),
|
|
4802
|
+
canonicalOf,
|
|
4803
|
+
reconciliation.retypeMap,
|
|
4804
|
+
identityContext,
|
|
4805
|
+
identityNodeUniverse
|
|
4806
|
+
);
|
|
4807
|
+
const { edges: stagedEdges, windowOnlyCarried } = buildStagedEdges(
|
|
3225
4808
|
staging,
|
|
3226
|
-
reconciledEdgeModifications.survivingModifications
|
|
4809
|
+
reconciledEdgeModifications.survivingModifications,
|
|
4810
|
+
validWindows.edgeEnds,
|
|
4811
|
+
edgeDeletions
|
|
3227
4812
|
);
|
|
3228
4813
|
const stagedEdgeBranches = /* @__PURE__ */ new Map();
|
|
3229
4814
|
for (const staged of stagedEdges) {
|
|
3230
|
-
const
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
} else {
|
|
4815
|
+
const identity2 = mergeKeyOf(staged);
|
|
4816
|
+
const branches = stagedEdgeBranches.get(staged.id) ?? /* @__PURE__ */ new Set();
|
|
4817
|
+
if (!windowOnlyCarried.has(identity2)) {
|
|
3234
4818
|
branches.add(staged.branchId);
|
|
3235
4819
|
}
|
|
4820
|
+
for (const branchId of validWindows.edgeCredits.get(identity2) ?? []) {
|
|
4821
|
+
branches.add(branchId);
|
|
4822
|
+
}
|
|
4823
|
+
stagedEdgeBranches.set(staged.id, branches);
|
|
3236
4824
|
}
|
|
3237
4825
|
const deletedNodeIdSet = new Set(nodeDeletions.keys());
|
|
3238
4826
|
const repoint2 = repointEdges(
|
|
@@ -3255,9 +4843,13 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3255
4843
|
...deleteModify.dropped,
|
|
3256
4844
|
...edgeDeleteModify.dropped,
|
|
3257
4845
|
...repoint2.dropped,
|
|
3258
|
-
...reconciliation.dropped
|
|
4846
|
+
...reconciliation.dropped,
|
|
4847
|
+
...identity.dropped,
|
|
4848
|
+
...overruledRetractionDrops,
|
|
4849
|
+
...identityRemap.dropped,
|
|
4850
|
+
...validWindows.dropped
|
|
3259
4851
|
].sort(
|
|
3260
|
-
(left, right) =>
|
|
4852
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(`${left.kind}|${left.id}`, `${right.kind}|${right.id}`)
|
|
3261
4853
|
);
|
|
3262
4854
|
return {
|
|
3263
4855
|
canonicalEntities,
|
|
@@ -3272,6 +4864,10 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3272
4864
|
])
|
|
3273
4865
|
),
|
|
3274
4866
|
retypeMap: reconciliation.retypeMap,
|
|
4867
|
+
canonicalOf,
|
|
4868
|
+
nodeValidityEnds: validWindows.nodeEnds,
|
|
4869
|
+
edgeValidityEnds: validWindows.edgeEnds,
|
|
4870
|
+
validityEnds: validWindows.resolutions,
|
|
3275
4871
|
// Order report arrays by the composite (kind, id) identity — never a bare id
|
|
3276
4872
|
// or a `|`-joined string. A bare id ties two different-kind entities that
|
|
3277
4873
|
// share an id, and a `|` separator collides on caller-supplied ids/property
|
|
@@ -3290,7 +4886,7 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3290
4886
|
mergeKey(left.kind, left.entityId),
|
|
3291
4887
|
mergeKey(right.kind, right.entityId)
|
|
3292
4888
|
);
|
|
3293
|
-
return byEntity === 0 ?
|
|
4889
|
+
return byEntity === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.property, right.property) : byEntity;
|
|
3294
4890
|
}
|
|
3295
4891
|
),
|
|
3296
4892
|
deleteModifyConflicts: [
|
|
@@ -3307,17 +4903,19 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3307
4903
|
baseAmbiguities: baseAmbiguities.sort(
|
|
3308
4904
|
(left, right) => compareMergeKeys(
|
|
3309
4905
|
mergeKey(
|
|
3310
|
-
|
|
3311
|
-
|
|
4906
|
+
chunkN66HCGCY_cjs.requireDefined(left.baseIds[0]).kind,
|
|
4907
|
+
chunkN66HCGCY_cjs.requireDefined(left.baseIds[0]).id
|
|
3312
4908
|
),
|
|
3313
4909
|
mergeKey(
|
|
3314
|
-
|
|
3315
|
-
|
|
4910
|
+
chunkN66HCGCY_cjs.requireDefined(right.baseIds[0]).kind,
|
|
4911
|
+
chunkN66HCGCY_cjs.requireDefined(right.baseIds[0]).id
|
|
3316
4912
|
)
|
|
3317
4913
|
)
|
|
3318
4914
|
),
|
|
3319
4915
|
provenanceRecords,
|
|
3320
|
-
warnings: candidateWarnings
|
|
4916
|
+
warnings: candidateWarnings,
|
|
4917
|
+
identityAssertions: identityRemap.assertions,
|
|
4918
|
+
identityRetractions: survivingRetractions
|
|
3321
4919
|
};
|
|
3322
4920
|
}
|
|
3323
4921
|
function pickClusterCanonical(cluster, entityByIdentity) {
|
|
@@ -3332,78 +4930,125 @@ function pickClusterCanonical(cluster, entityByIdentity) {
|
|
|
3332
4930
|
);
|
|
3333
4931
|
}
|
|
3334
4932
|
function commitModificationProps(baseProps, forkProps) {
|
|
3335
|
-
const props =
|
|
4933
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
4934
|
+
for (const key of Object.keys(forkProps)) {
|
|
4935
|
+
props[key] = forkProps[key];
|
|
4936
|
+
}
|
|
3336
4937
|
for (const key of Object.keys(baseProps)) {
|
|
3337
|
-
if (!(key
|
|
4938
|
+
if (!chunkN66HCGCY_cjs.hasOwnKey(forkProps, key)) {
|
|
3338
4939
|
props[key] = void 0;
|
|
3339
4940
|
}
|
|
3340
4941
|
}
|
|
3341
4942
|
return props;
|
|
3342
4943
|
}
|
|
3343
|
-
|
|
3344
|
-
|
|
4944
|
+
function finalEdgeEndpoint(plan, kind, id) {
|
|
4945
|
+
return { kind: plan.retypeMap.get(mergeKey(kind, id)) ?? kind, id };
|
|
4946
|
+
}
|
|
4947
|
+
function plannedNodeWrites(plan) {
|
|
3345
4948
|
const canonicalIdentities = /* @__PURE__ */ new Set();
|
|
3346
4949
|
for (const entity of plan.canonicalEntities) {
|
|
3347
4950
|
canonicalIdentities.add(mergeKey(entity.kind, entity.canonicalId));
|
|
3348
4951
|
}
|
|
3349
|
-
const
|
|
4952
|
+
const modificationsByIdentity = /* @__PURE__ */ new Map();
|
|
3350
4953
|
for (const modification of plan.survivingModifications) {
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
4954
|
+
modificationsByIdentity.set(
|
|
4955
|
+
mergeKeyOf(modification.node),
|
|
4956
|
+
modification.node
|
|
4957
|
+
);
|
|
3355
4958
|
}
|
|
4959
|
+
const writes = [];
|
|
4960
|
+
const written = /* @__PURE__ */ new Set();
|
|
3356
4961
|
for (const modification of plan.survivingModifications) {
|
|
3357
4962
|
const identity = mergeKeyOf(modification.node);
|
|
3358
4963
|
if (plan.nodeDeletions.has(identity) || canonicalIdentities.has(identity)) {
|
|
3359
4964
|
continue;
|
|
3360
4965
|
}
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
4966
|
+
written.add(identity);
|
|
4967
|
+
const validTo = plan.nodeValidityEnds.get(identity);
|
|
4968
|
+
writes.push({
|
|
4969
|
+
identity,
|
|
4970
|
+
kind: modification.node.kind,
|
|
4971
|
+
id: modification.node.id,
|
|
4972
|
+
modification: modification.node,
|
|
4973
|
+
...validTo === void 0 ? {} : { validTo }
|
|
4974
|
+
});
|
|
3370
4975
|
}
|
|
3371
4976
|
for (const entity of plan.canonicalEntities) {
|
|
3372
|
-
const
|
|
3373
|
-
if (plan.nodeDeletions.has(
|
|
4977
|
+
const sourceIdentity = mergeKey(entity.kind, entity.canonicalId);
|
|
4978
|
+
if (plan.nodeDeletions.has(sourceIdentity)) {
|
|
3374
4979
|
continue;
|
|
3375
4980
|
}
|
|
3376
|
-
const kind = plan.retypeMap.get(
|
|
3377
|
-
const modification =
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
4981
|
+
const kind = plan.retypeMap.get(sourceIdentity) ?? entity.kind;
|
|
4982
|
+
const modification = modificationsByIdentity.get(sourceIdentity);
|
|
4983
|
+
written.add(sourceIdentity);
|
|
4984
|
+
const validTo = entity.validTo ?? plan.nodeValidityEnds.get(sourceIdentity);
|
|
4985
|
+
writes.push({
|
|
4986
|
+
identity: mergeKey(kind, entity.canonicalId),
|
|
4987
|
+
kind,
|
|
4988
|
+
id: entity.canonicalId,
|
|
4989
|
+
entity,
|
|
4990
|
+
...modification === void 0 ? {} : { modification },
|
|
4991
|
+
...entity.validFrom === void 0 ? {} : { validFrom: entity.validFrom },
|
|
4992
|
+
...validTo === void 0 ? {} : { validTo }
|
|
4993
|
+
});
|
|
4994
|
+
}
|
|
4995
|
+
for (const identity of [...plan.nodeValidityEnds.keys()].sort(
|
|
4996
|
+
(left, right) => compareMergeKeys(left, right)
|
|
4997
|
+
)) {
|
|
4998
|
+
if (written.has(identity) || plan.nodeDeletions.has(identity)) {
|
|
4999
|
+
continue;
|
|
5000
|
+
}
|
|
5001
|
+
const kind = plan.retypeMap.get(identity) ?? kindOf(identity);
|
|
5002
|
+
writes.push({
|
|
5003
|
+
identity: mergeKey(kind, idOf(identity)),
|
|
5004
|
+
kind,
|
|
5005
|
+
id: idOf(identity),
|
|
5006
|
+
validTo: chunkN66HCGCY_cjs.requireDefined(plan.nodeValidityEnds.get(identity))
|
|
5007
|
+
});
|
|
3388
5008
|
}
|
|
5009
|
+
return writes;
|
|
5010
|
+
}
|
|
5011
|
+
function nodeWriteProps(write, modificationProps) {
|
|
5012
|
+
return {
|
|
5013
|
+
...write.entity?.props,
|
|
5014
|
+
...write.modification === void 0 ? void 0 : modificationProps(write.modification)
|
|
5015
|
+
};
|
|
5016
|
+
}
|
|
5017
|
+
async function applyMergePlan(plan, nodesApi, edgesApi, target, txBackend) {
|
|
5018
|
+
const committedNodeIds = /* @__PURE__ */ new Set();
|
|
3389
5019
|
for (const [identity, kind] of plan.nodeDeletions) {
|
|
3390
5020
|
const collection = nodeCollection(nodesApi, kind);
|
|
3391
5021
|
await collection.delete(idOf(identity));
|
|
3392
5022
|
}
|
|
5023
|
+
for (const write of plannedNodeWrites(plan)) {
|
|
5024
|
+
const collection = nodeCollection(nodesApi, write.kind);
|
|
5025
|
+
await collection.upsertByIdFromRecord(
|
|
5026
|
+
write.id,
|
|
5027
|
+
nodeWriteProps(
|
|
5028
|
+
write,
|
|
5029
|
+
(modification) => commitModificationProps(modification.baseProps, modification.forkProps)
|
|
5030
|
+
),
|
|
5031
|
+
{
|
|
5032
|
+
...write.validFrom === void 0 ? {} : { validFrom: write.validFrom },
|
|
5033
|
+
...write.validTo === void 0 ? {} : { validTo: write.validTo }
|
|
5034
|
+
}
|
|
5035
|
+
);
|
|
5036
|
+
committedNodeIds.add(write.identity);
|
|
5037
|
+
}
|
|
3393
5038
|
for (const [identity, kind] of plan.edgeDeletions) {
|
|
3394
5039
|
await edgeCollection(edgesApi, kind).delete(idOf(identity));
|
|
3395
5040
|
}
|
|
3396
5041
|
const edgesByKind = /* @__PURE__ */ new Map();
|
|
3397
5042
|
for (const edge of plan.mergedEdges) {
|
|
3398
|
-
const fromKind = plan.retypeMap.get(mergeKey(edge.fromKind, edge.fromId));
|
|
3399
|
-
const toKind = plan.retypeMap.get(mergeKey(edge.toKind, edge.toId));
|
|
3400
5043
|
const edgeBaseProps = plan.inheritedEdgeBaseProps.get(edge.id);
|
|
3401
5044
|
const props = edgeBaseProps === void 0 ? edge.props : commitModificationProps(edgeBaseProps, edge.props);
|
|
3402
5045
|
const item = {
|
|
3403
5046
|
id: edge.id,
|
|
3404
|
-
from:
|
|
3405
|
-
to:
|
|
3406
|
-
props
|
|
5047
|
+
from: finalEdgeEndpoint(plan, edge.fromKind, edge.fromId),
|
|
5048
|
+
to: finalEdgeEndpoint(plan, edge.toKind, edge.toId),
|
|
5049
|
+
props,
|
|
5050
|
+
...edge.validFrom === void 0 ? {} : { validFrom: edge.validFrom },
|
|
5051
|
+
...edge.validTo === void 0 ? {} : { validTo: edge.validTo }
|
|
3407
5052
|
};
|
|
3408
5053
|
const existing = edgesByKind.get(edge.kind);
|
|
3409
5054
|
if (existing === void 0) {
|
|
@@ -3417,10 +5062,34 @@ async function applyMergePlan(plan, nodesApi, edgesApi) {
|
|
|
3417
5062
|
await edgeCollection(edgesApi, kind).bulkUpsertById(items);
|
|
3418
5063
|
committedEdges += items.length;
|
|
3419
5064
|
}
|
|
3420
|
-
|
|
5065
|
+
let appliedIdentity;
|
|
5066
|
+
try {
|
|
5067
|
+
appliedIdentity = await chunkTTAITEPJ_cjs.storeRuntime(target).applyIdentityMergeAtTarget(
|
|
5068
|
+
txBackend,
|
|
5069
|
+
plan.identityRetractions.map((retraction) => retraction.id),
|
|
5070
|
+
plan.identityAssertions
|
|
5071
|
+
);
|
|
5072
|
+
await assertMergedIdentityClassesConsistent(target, txBackend, plan);
|
|
5073
|
+
} catch (error) {
|
|
5074
|
+
throw translateIdentityCommitError(error);
|
|
5075
|
+
}
|
|
5076
|
+
return {
|
|
5077
|
+
nodes: committedNodeIds.size,
|
|
5078
|
+
edges: committedEdges,
|
|
5079
|
+
// ACTUAL ledger effects from the applier: rows created (idempotent
|
|
5080
|
+
// exact/pair matches the target already held are excluded — the normal
|
|
5081
|
+
// incremental case, where the target's own additions are staged back at
|
|
5082
|
+
// it) and rows ended (already-ended or unknown ids excluded). Any apply
|
|
5083
|
+
// failure aborts the whole merge, so the counts never describe a
|
|
5084
|
+
// partial commit.
|
|
5085
|
+
identity: {
|
|
5086
|
+
asserted: appliedIdentity.created,
|
|
5087
|
+
retracted: appliedIdentity.retracted
|
|
5088
|
+
}
|
|
5089
|
+
};
|
|
3421
5090
|
}
|
|
3422
5091
|
async function commitPlan(target, plan, expectedBaseVersion) {
|
|
3423
|
-
if (!
|
|
5092
|
+
if (!chunkTTAITEPJ_cjs.storeBackend(target).capabilities.transactions) {
|
|
3424
5093
|
throw new MergeError(
|
|
3425
5094
|
"merge() requires a transaction-capable target backend. The merged plan (canonical upserts, soft-deletes, edge upserts) must commit atomically; a non-transactional fallback would leave a partially-merged graph on a mid-commit failure. (mergeIncremental() enforces the same requirement.)",
|
|
3426
5095
|
{ details: { capability: "transactions" } }
|
|
@@ -3430,15 +5099,18 @@ async function commitPlan(target, plan, expectedBaseVersion) {
|
|
|
3430
5099
|
() => target.transaction(async (tx) => {
|
|
3431
5100
|
if (expectedBaseVersion !== void 0) {
|
|
3432
5101
|
await assertTargetUnchanged(
|
|
3433
|
-
|
|
5102
|
+
chunkTTAITEPJ_cjs.transactionBackend(tx),
|
|
3434
5103
|
target,
|
|
3435
5104
|
expectedBaseVersion
|
|
3436
5105
|
);
|
|
3437
5106
|
}
|
|
5107
|
+
await assertPlannedIdentityIdsFresh(target, chunkTTAITEPJ_cjs.transactionBackend(tx), plan);
|
|
3438
5108
|
return applyMergePlan(
|
|
3439
5109
|
plan,
|
|
3440
5110
|
tx.nodes,
|
|
3441
|
-
tx.edges
|
|
5111
|
+
tx.edges,
|
|
5112
|
+
target,
|
|
5113
|
+
chunkTTAITEPJ_cjs.transactionBackend(tx)
|
|
3442
5114
|
);
|
|
3443
5115
|
}, mergeCommitTransactionOptions(target))
|
|
3444
5116
|
);
|
|
@@ -3451,9 +5123,9 @@ function mergeCommitTransactionOptions(target) {
|
|
|
3451
5123
|
}
|
|
3452
5124
|
async function assertTargetUnchanged(txBackend, target, expectedBaseVersion) {
|
|
3453
5125
|
if (hasRevisionAnchor(expectedBaseVersion)) {
|
|
3454
|
-
await
|
|
5126
|
+
await chunkXMQSEJCF_cjs.lockRecordedGraphWrite(txBackend, target.graphId);
|
|
3455
5127
|
const expectedOrigin = revisionOriginOf(expectedBaseVersion);
|
|
3456
|
-
const liveOrigin = await
|
|
5128
|
+
const liveOrigin = await chunkXMQSEJCF_cjs.readRevisionOrigin(
|
|
3457
5129
|
txBackend,
|
|
3458
5130
|
target.revisionSchema,
|
|
3459
5131
|
target.graphId
|
|
@@ -3467,7 +5139,7 @@ async function assertTargetUnchanged(txBackend, target, expectedBaseVersion) {
|
|
|
3467
5139
|
}
|
|
3468
5140
|
);
|
|
3469
5141
|
}
|
|
3470
|
-
const liveRevision = await
|
|
5142
|
+
const liveRevision = await chunkXMQSEJCF_cjs.readRecordedClock(
|
|
3471
5143
|
txBackend,
|
|
3472
5144
|
target.revisionSchema,
|
|
3473
5145
|
target.graphId
|
|
@@ -3487,7 +5159,8 @@ async function assertTargetUnchanged(txBackend, target, expectedBaseVersion) {
|
|
|
3487
5159
|
const liveContent = await computeContentComponent(
|
|
3488
5160
|
txBackend,
|
|
3489
5161
|
target.graphId,
|
|
3490
|
-
target.graph
|
|
5162
|
+
target.graph,
|
|
5163
|
+
await chunkTTAITEPJ_cjs.storeRuntime(target).identityAssertionsAtTarget(txBackend, "state")
|
|
3491
5164
|
);
|
|
3492
5165
|
const expectedContent = contentComponentOf(expectedBaseVersion);
|
|
3493
5166
|
if (liveContent !== expectedContent) {
|
|
@@ -3525,7 +5198,7 @@ async function validateBaseVersions(target, branches) {
|
|
|
3525
5198
|
const targetVersion = await computeBaseVersion(target);
|
|
3526
5199
|
for (const branch2 of branches) {
|
|
3527
5200
|
if (branch2.base !== targetVersion) {
|
|
3528
|
-
return
|
|
5201
|
+
return chunk7BQXPCGN_cjs.err(
|
|
3529
5202
|
new BaseVersionMismatchError(
|
|
3530
5203
|
`Branch "${branch2.id}" forked from base@V "${branch2.base}", which does not match the merge target's current base@V "${targetVersion}".`,
|
|
3531
5204
|
{
|
|
@@ -3539,20 +5212,50 @@ async function validateBaseVersions(target, branches) {
|
|
|
3539
5212
|
);
|
|
3540
5213
|
}
|
|
3541
5214
|
}
|
|
3542
|
-
return
|
|
5215
|
+
return chunk7BQXPCGN_cjs.ok(targetVersion);
|
|
5216
|
+
}
|
|
5217
|
+
function tryNormalize(optionsInput, refusedOptions = []) {
|
|
5218
|
+
const refusedOption = refusedOptions.find(
|
|
5219
|
+
(option) => chunkN66HCGCY_cjs.hasOwnKey(optionsInput, option)
|
|
5220
|
+
);
|
|
5221
|
+
if (refusedOption !== void 0) {
|
|
5222
|
+
return chunk7BQXPCGN_cjs.err(
|
|
5223
|
+
new InvalidMergeOptionsError(
|
|
5224
|
+
`This merge operation does not accept options.${refusedOption}.`,
|
|
5225
|
+
{ details: { option: refusedOption } }
|
|
5226
|
+
)
|
|
5227
|
+
);
|
|
5228
|
+
}
|
|
5229
|
+
try {
|
|
5230
|
+
return chunk7BQXPCGN_cjs.ok(normalizeMergeOptions(optionsInput));
|
|
5231
|
+
} catch (error) {
|
|
5232
|
+
return chunk7BQXPCGN_cjs.err(
|
|
5233
|
+
new InvalidMergeOptionsError("Invalid merge options.", { cause: error })
|
|
5234
|
+
);
|
|
5235
|
+
}
|
|
3543
5236
|
}
|
|
3544
|
-
function
|
|
5237
|
+
async function tryOpenProvenanceStore(target) {
|
|
3545
5238
|
try {
|
|
3546
|
-
return
|
|
5239
|
+
return chunk7BQXPCGN_cjs.ok(await openProvenanceStore(target));
|
|
3547
5240
|
} catch (error) {
|
|
3548
|
-
|
|
5241
|
+
const code = error instanceof chunkNI72YOJB_cjs.TypeGraphError ? error.details?.code : void 0;
|
|
5242
|
+
const details = {
|
|
5243
|
+
option: "persistProvenance",
|
|
5244
|
+
graphId: provenanceGraphId(target.graphId),
|
|
5245
|
+
targetGraphId: target.graphId,
|
|
5246
|
+
...typeof code === "string" ? { provenanceErrorCode: code } : {}
|
|
5247
|
+
};
|
|
5248
|
+
const message = `options.persistProvenance was requested but the merge-provenance sidecar cannot be opened: ${describeCause(error)}`;
|
|
5249
|
+
return chunk7BQXPCGN_cjs.err(
|
|
5250
|
+
code === "GRAPH_MERGE_PROVENANCE_ID_COLLISION" || code === "GRAPH_MERGE_PROVENANCE_CLAIM_UNFENCED" ? new InvalidMergeOptionsError(message, { details, cause: error }) : new MergeError(message, { details, cause: error })
|
|
5251
|
+
);
|
|
3549
5252
|
}
|
|
3550
5253
|
}
|
|
3551
5254
|
async function resolveMerge(store, target, branches, options, useBaseSources, incremental, expectedBaseVersion) {
|
|
3552
5255
|
let targetBranchSeen = false;
|
|
3553
5256
|
for (const branch2 of branches) {
|
|
3554
5257
|
if (branch2.id === BASE_PROVENANCE_BRANCH) {
|
|
3555
|
-
return
|
|
5258
|
+
return chunk7BQXPCGN_cjs.err(
|
|
3556
5259
|
new MergeError(
|
|
3557
5260
|
`Branch id "${BASE_PROVENANCE_BRANCH}" is reserved for committed-base provenance and cannot be used as a branch id.`,
|
|
3558
5261
|
{ details: { branchId: branch2.id } }
|
|
@@ -3561,7 +5264,7 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3561
5264
|
}
|
|
3562
5265
|
if (branch2.id === COMMITTED_TARGET_BRANCH) {
|
|
3563
5266
|
if (incremental?.targetBranchId !== COMMITTED_TARGET_BRANCH || targetBranchSeen) {
|
|
3564
|
-
return
|
|
5267
|
+
return chunk7BQXPCGN_cjs.err(
|
|
3565
5268
|
new MergeError(
|
|
3566
5269
|
`Branch id "${COMMITTED_TARGET_BRANCH}" is reserved for the committed incremental target and cannot be used as a branch id.`,
|
|
3567
5270
|
{ details: { branchId: branch2.id } }
|
|
@@ -3571,9 +5274,44 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3571
5274
|
targetBranchSeen = true;
|
|
3572
5275
|
}
|
|
3573
5276
|
}
|
|
5277
|
+
for (const branch2 of branches) {
|
|
5278
|
+
const branchSchemaRow = await chunkTTAITEPJ_cjs.storeBackend(branch2.store).getActiveSchema(
|
|
5279
|
+
branch2.store.graphId
|
|
5280
|
+
);
|
|
5281
|
+
let drifted;
|
|
5282
|
+
if ("schemaAnchor" in branch2) {
|
|
5283
|
+
const anchor = branch2.schemaAnchor;
|
|
5284
|
+
drifted = anchor === void 0 ? branchSchemaRow !== void 0 : branchSchemaRow?.version !== anchor.version || branchSchemaRow.schema_hash !== anchor.hash;
|
|
5285
|
+
} else {
|
|
5286
|
+
const sourceSchemaRow = await chunkTTAITEPJ_cjs.storeBackend(store).getActiveSchema(
|
|
5287
|
+
store.graphId
|
|
5288
|
+
);
|
|
5289
|
+
drifted = branchSchemaRow?.schema_hash !== sourceSchemaRow?.schema_hash;
|
|
5290
|
+
}
|
|
5291
|
+
if (drifted) {
|
|
5292
|
+
return chunk7BQXPCGN_cjs.err(
|
|
5293
|
+
new BaseVersionMismatchError(
|
|
5294
|
+
`Branch "${branch2.id}"'s store has a committed schema different from its at-fork state \u2014 a schema operation ran on the branch after forking. Merge carries data changes only; apply the schema change to the target first (or re-fork), then merge.`,
|
|
5295
|
+
{
|
|
5296
|
+
details: {
|
|
5297
|
+
branchId: branch2.id,
|
|
5298
|
+
branchSchemaVersion: branchSchemaRow?.version,
|
|
5299
|
+
branchSchemaHash: branchSchemaRow?.schema_hash,
|
|
5300
|
+
anchor: "schemaAnchor" in branch2 ? branch2.schemaAnchor : "absent"
|
|
5301
|
+
}
|
|
5302
|
+
}
|
|
5303
|
+
)
|
|
5304
|
+
);
|
|
5305
|
+
}
|
|
5306
|
+
}
|
|
5307
|
+
const provenanceStore = options.persistProvenance ? await tryOpenProvenanceStore(target) : void 0;
|
|
5308
|
+
if (provenanceStore !== void 0 && chunk7BQXPCGN_cjs.isErr(provenanceStore)) {
|
|
5309
|
+
return provenanceStore;
|
|
5310
|
+
}
|
|
3574
5311
|
try {
|
|
3575
5312
|
const preferredBranchId = incremental?.targetBranchId;
|
|
3576
5313
|
const staging = await stageBranches(store, branches, preferredBranchId);
|
|
5314
|
+
const stagedNewByKind = newNodesByKind(staging);
|
|
3577
5315
|
const branchIds = branches.map((branch2) => branch2.id);
|
|
3578
5316
|
const branchOrder = preferredBranchId === void 0 ? options.branchOrder ?? [] : [
|
|
3579
5317
|
preferredBranchId,
|
|
@@ -3589,12 +5327,12 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3589
5327
|
}
|
|
3590
5328
|
const subClassClosure = buildSubClassClosure(introspection.ontology);
|
|
3591
5329
|
const embeddings = options.embedder === void 0 ? void 0 : await precomputeEmbeddings(
|
|
3592
|
-
|
|
5330
|
+
stagedNewByKind,
|
|
3593
5331
|
options.resolve,
|
|
3594
5332
|
options.embedder
|
|
3595
5333
|
);
|
|
3596
5334
|
const ctx = {
|
|
3597
|
-
backend:
|
|
5335
|
+
backend: chunkTTAITEPJ_cjs.storeBackend(store),
|
|
3598
5336
|
...embeddings === void 0 ? {} : { embeddings }
|
|
3599
5337
|
};
|
|
3600
5338
|
const candidates = await generateAllCandidates(
|
|
@@ -3606,9 +5344,38 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3606
5344
|
useBaseSources,
|
|
3607
5345
|
options.embedder
|
|
3608
5346
|
);
|
|
3609
|
-
if (
|
|
3610
|
-
return
|
|
5347
|
+
if (chunk7BQXPCGN_cjs.isErr(candidates)) {
|
|
5348
|
+
return chunk7BQXPCGN_cjs.err(candidates.error);
|
|
3611
5349
|
}
|
|
5350
|
+
const identityProbeIds = target.graph.identity === void 0 ? void 0 : [
|
|
5351
|
+
.../* @__PURE__ */ new Set([
|
|
5352
|
+
...[...stagedNewByKind.values()].flatMap(
|
|
5353
|
+
(entries) => entries.map((entry) => entry.node.id)
|
|
5354
|
+
),
|
|
5355
|
+
...staging.modifiedNodes.map((entry) => entry.node.id),
|
|
5356
|
+
...candidates.data.baseMembers.map((member) => member.id),
|
|
5357
|
+
...staging.newIdentityAssertions.flatMap((staged) => [
|
|
5358
|
+
staged.assertion.a.id,
|
|
5359
|
+
staged.assertion.b.id
|
|
5360
|
+
])
|
|
5361
|
+
])
|
|
5362
|
+
];
|
|
5363
|
+
const targetPeers = identityProbeIds === void 0 ? [] : await chunkTTAITEPJ_cjs.storeRuntime(target).liveNodesSharingIds(identityProbeIds);
|
|
5364
|
+
const stagedIdentityIds = [
|
|
5365
|
+
.../* @__PURE__ */ new Set([
|
|
5366
|
+
...staging.newIdentityAssertions.map((staged) => staged.assertion.id),
|
|
5367
|
+
...staging.retractedIdentityAssertions.map(
|
|
5368
|
+
(staged) => staged.assertion.id
|
|
5369
|
+
)
|
|
5370
|
+
])
|
|
5371
|
+
];
|
|
5372
|
+
const storedIdentityRowsById = stagedIdentityIds.length === 0 || target.graph.identity === void 0 ? NO_STORED_ASSERTIONS : await chunkTTAITEPJ_cjs.storeRuntime(target).identityAssertionRowsByIds(
|
|
5373
|
+
stagedIdentityIds
|
|
5374
|
+
);
|
|
5375
|
+
const identityContext = {
|
|
5376
|
+
sameIdAcrossKinds: target.graph.identity?.sameIdAcrossKinds,
|
|
5377
|
+
areDisjoint: (left, right) => target.registry.areDisjoint(left, right)
|
|
5378
|
+
};
|
|
3612
5379
|
const plan = planMerge(
|
|
3613
5380
|
staging,
|
|
3614
5381
|
candidates.data.edges,
|
|
@@ -3617,12 +5384,63 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3617
5384
|
options,
|
|
3618
5385
|
branchRank,
|
|
3619
5386
|
subClassClosure,
|
|
5387
|
+
identityContext,
|
|
5388
|
+
storedIdentityRowsById,
|
|
5389
|
+
targetPeers,
|
|
3620
5390
|
preferredBranchId
|
|
3621
5391
|
);
|
|
5392
|
+
if (plan.identityAssertions.length > 0) {
|
|
5393
|
+
assertOneIdOneTruth(
|
|
5394
|
+
plan.identityAssertions,
|
|
5395
|
+
await chunkTTAITEPJ_cjs.storeRuntime(target).identityAssertionRowsByIds(
|
|
5396
|
+
plan.identityAssertions.map((assertion) => assertion.id)
|
|
5397
|
+
)
|
|
5398
|
+
);
|
|
5399
|
+
}
|
|
5400
|
+
let identityGuard;
|
|
5401
|
+
if (identityProbeIds !== void 0 && incremental !== void 0) {
|
|
5402
|
+
const freshPeers = await chunkTTAITEPJ_cjs.storeRuntime(target).liveNodesSharingIds(identityProbeIds);
|
|
5403
|
+
const built = await buildIdentityPeerProbe(
|
|
5404
|
+
target,
|
|
5405
|
+
identityProbeIds,
|
|
5406
|
+
freshPeers,
|
|
5407
|
+
plan,
|
|
5408
|
+
target.graph.identity?.sameIdAcrossKinds ?? "ignore"
|
|
5409
|
+
);
|
|
5410
|
+
const canonicalIdentityOf = plan.canonicalOf;
|
|
5411
|
+
assertNoContradictoryIdentityClosure(
|
|
5412
|
+
plan.identityAssertions,
|
|
5413
|
+
plan.identityRetractions.map((retraction) => retraction.id),
|
|
5414
|
+
// The FRESH target ledger, not the pre-planning staging capture —
|
|
5415
|
+
// a `different` committed in the window must invalidate the plan
|
|
5416
|
+
// here, as a typed conflict, before it can become the baseline.
|
|
5417
|
+
// Connectivity is REBUILT from this deletion-filtered ledger (plus
|
|
5418
|
+
// the fold unions inside the checker) rather than from the old
|
|
5419
|
+
// closure's member lists: filtering a deleted member out of a class
|
|
5420
|
+
// does not model the post-deletion state — deleting a bridge ends
|
|
5421
|
+
// its assertions and SPLITS the class, so pre-linking the filtered
|
|
5422
|
+
// remainder would falsely reject a plan that deletes the bridge and
|
|
5423
|
+
// asserts the ends different.
|
|
5424
|
+
built.ledger,
|
|
5425
|
+
new Set(plan.nodeDeletions.keys()),
|
|
5426
|
+
canonicalIdentityOf,
|
|
5427
|
+
plan.retypeMap,
|
|
5428
|
+
identityContext,
|
|
5429
|
+
// The snapshot's (deletion-filtered) class MEMBERS join the universe
|
|
5430
|
+
// as unlinked refs: their same-id fold links at ids outside the probe
|
|
5431
|
+
// range are re-derived by the checker's fold union, and their
|
|
5432
|
+
// assertion links come from the fresh ledger — never from the old
|
|
5433
|
+
// class shape itself.
|
|
5434
|
+
[...built.probe.seeds, ...built.snapshot.groups.flat()]
|
|
5435
|
+
);
|
|
5436
|
+
identityGuard = built.probe;
|
|
5437
|
+
}
|
|
3622
5438
|
const merged = incremental === void 0 ? await commitPlan(target, plan, expectedBaseVersion) : await commitIncrementalPlan(target, plan, {
|
|
3623
|
-
stagedNewByKind
|
|
5439
|
+
stagedNewByKind,
|
|
3624
5440
|
options,
|
|
3625
5441
|
introspectionKinds,
|
|
5442
|
+
forkPoint: incremental.forkPoint,
|
|
5443
|
+
...identityGuard === void 0 ? {} : { identityPeerProbe: identityGuard },
|
|
3626
5444
|
// The committed (kind, id) keys the base sources matched at PLAN time;
|
|
3627
5445
|
// anything NEW the in-tx re-probe surfaces is a window write.
|
|
3628
5446
|
plannedBaseMatchKeys: new Set(
|
|
@@ -3634,11 +5452,10 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3634
5452
|
const provenance = options.provenance ? buildProvenanceIndex(plan.provenanceRecords) : { byBranch: () => ({ nodeIds: [], edgeIds: [] }) };
|
|
3635
5453
|
const warnings = [...plan.warnings];
|
|
3636
5454
|
let provenancePersisted;
|
|
3637
|
-
if (
|
|
5455
|
+
if (provenanceStore !== void 0 && !chunk7BQXPCGN_cjs.isErr(provenanceStore)) {
|
|
3638
5456
|
try {
|
|
3639
|
-
const provenanceStore = await openProvenanceStore(target);
|
|
3640
5457
|
const count = await persistProvenanceRecords(
|
|
3641
|
-
provenanceStore,
|
|
5458
|
+
provenanceStore.data,
|
|
3642
5459
|
target.graphId,
|
|
3643
5460
|
plan.provenanceRecords
|
|
3644
5461
|
);
|
|
@@ -3659,17 +5476,18 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3659
5476
|
deleteModifyConflicts: plan.deleteModifyConflicts,
|
|
3660
5477
|
typeReconciliations: plan.typeReconciliations,
|
|
3661
5478
|
dropped: plan.dropped,
|
|
5479
|
+
validityEnds: plan.validityEnds,
|
|
3662
5480
|
baseAmbiguities: plan.baseAmbiguities,
|
|
3663
5481
|
provenance,
|
|
3664
5482
|
warnings,
|
|
3665
5483
|
...provenancePersisted === void 0 ? {} : { provenancePersisted }
|
|
3666
5484
|
};
|
|
3667
|
-
return
|
|
5485
|
+
return chunk7BQXPCGN_cjs.ok(report);
|
|
3668
5486
|
} catch (error) {
|
|
3669
5487
|
if (error instanceof MergeError) {
|
|
3670
|
-
return
|
|
5488
|
+
return chunk7BQXPCGN_cjs.err(error);
|
|
3671
5489
|
}
|
|
3672
|
-
return
|
|
5490
|
+
return chunk7BQXPCGN_cjs.err(
|
|
3673
5491
|
new MergeError(
|
|
3674
5492
|
`Merge failed while staging or committing: ${describeCause(error)}`,
|
|
3675
5493
|
{ cause: error }
|
|
@@ -3679,14 +5497,14 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3679
5497
|
}
|
|
3680
5498
|
async function merge(store, branches, optionsInput = {}) {
|
|
3681
5499
|
const normalized = tryNormalize(optionsInput);
|
|
3682
|
-
if (
|
|
3683
|
-
return
|
|
5500
|
+
if (chunk7BQXPCGN_cjs.isErr(normalized)) {
|
|
5501
|
+
return chunk7BQXPCGN_cjs.err(normalized.error);
|
|
3684
5502
|
}
|
|
3685
5503
|
const options = normalized.data;
|
|
3686
5504
|
const target = options.target ?? store;
|
|
3687
5505
|
const precondition = await validateBaseVersions(target, branches);
|
|
3688
|
-
if (
|
|
3689
|
-
return
|
|
5506
|
+
if (chunk7BQXPCGN_cjs.isErr(precondition)) {
|
|
5507
|
+
return chunk7BQXPCGN_cjs.err(precondition.error);
|
|
3690
5508
|
}
|
|
3691
5509
|
return resolveMerge(
|
|
3692
5510
|
store,
|
|
@@ -3702,7 +5520,7 @@ async function validateForkPointVersions(forkPoint, branches) {
|
|
|
3702
5520
|
const forkVersion = await computeBaseVersion(forkPoint);
|
|
3703
5521
|
for (const branch2 of branches) {
|
|
3704
5522
|
if (branch2.base !== forkVersion) {
|
|
3705
|
-
return
|
|
5523
|
+
return chunk7BQXPCGN_cjs.err(
|
|
3706
5524
|
new BaseVersionMismatchError(
|
|
3707
5525
|
`Branch "${branch2.id}" forked from base@V "${branch2.base}", which does not match the fork-point's base@V "${forkVersion}". mergeIncremental() requires every branch to have forked from the supplied forkPoint.`,
|
|
3708
5526
|
{
|
|
@@ -3716,7 +5534,7 @@ async function validateForkPointVersions(forkPoint, branches) {
|
|
|
3716
5534
|
);
|
|
3717
5535
|
}
|
|
3718
5536
|
}
|
|
3719
|
-
return
|
|
5537
|
+
return chunk7BQXPCGN_cjs.ok(forkVersion);
|
|
3720
5538
|
}
|
|
3721
5539
|
function nodeSchemaFor(target, kind) {
|
|
3722
5540
|
const registry = target.graph.nodes;
|
|
@@ -3752,7 +5570,7 @@ function analyzeRevalidatingWrite(schema, current, planned) {
|
|
|
3752
5570
|
};
|
|
3753
5571
|
}
|
|
3754
5572
|
function nodeProps2(node) {
|
|
3755
|
-
const props =
|
|
5573
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
3756
5574
|
for (const [key, value] of Object.entries(node)) {
|
|
3757
5575
|
if (key === "id" || key === "kind" || key === "meta") continue;
|
|
3758
5576
|
props[key] = value;
|
|
@@ -3760,7 +5578,7 @@ function nodeProps2(node) {
|
|
|
3760
5578
|
return props;
|
|
3761
5579
|
}
|
|
3762
5580
|
function edgeProps(edge) {
|
|
3763
|
-
const props =
|
|
5581
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
3764
5582
|
for (const [key, value] of Object.entries(edge)) {
|
|
3765
5583
|
if (key === "id" || key === "kind" || key === "fromKind" || key === "fromId" || key === "toKind" || key === "toId" || key === "meta") {
|
|
3766
5584
|
continue;
|
|
@@ -3770,70 +5588,14 @@ function edgeProps(edge) {
|
|
|
3770
5588
|
return props;
|
|
3771
5589
|
}
|
|
3772
5590
|
var INCLUDE_TOMBSTONES = { temporalMode: "includeTombstones" };
|
|
3773
|
-
function finalEdgeFrom(edge, plan) {
|
|
3774
|
-
return {
|
|
3775
|
-
kind: plan.retypeMap.get(mergeKey(edge.fromKind, edge.fromId)) ?? edge.fromKind,
|
|
3776
|
-
id: edge.fromId
|
|
3777
|
-
};
|
|
3778
|
-
}
|
|
3779
|
-
function finalEdgeTo(edge, plan) {
|
|
3780
|
-
return {
|
|
3781
|
-
kind: plan.retypeMap.get(mergeKey(edge.toKind, edge.toId)) ?? edge.toKind,
|
|
3782
|
-
id: edge.toId
|
|
3783
|
-
};
|
|
3784
|
-
}
|
|
3785
5591
|
function assertValidRevalidatingWrite(analysis, message, details) {
|
|
3786
5592
|
if (analysis.status === "invalid") {
|
|
3787
5593
|
throw new MergeError(message, { details });
|
|
3788
5594
|
}
|
|
3789
5595
|
}
|
|
3790
|
-
function describeCause(cause) {
|
|
3791
|
-
return cause instanceof Error ? cause.message : String(cause);
|
|
3792
|
-
}
|
|
3793
|
-
function plannedNodeWrites(plan) {
|
|
3794
|
-
const canonicalIdentities = /* @__PURE__ */ new Set();
|
|
3795
|
-
for (const entity of plan.canonicalEntities) {
|
|
3796
|
-
canonicalIdentities.add(mergeKey(entity.kind, entity.canonicalId));
|
|
3797
|
-
}
|
|
3798
|
-
const survivingModProps = /* @__PURE__ */ new Map();
|
|
3799
|
-
for (const modification of plan.survivingModifications) {
|
|
3800
|
-
survivingModProps.set(
|
|
3801
|
-
mergeKeyOf(modification.node),
|
|
3802
|
-
modification.node.forkProps
|
|
3803
|
-
);
|
|
3804
|
-
}
|
|
3805
|
-
const writes = [];
|
|
3806
|
-
for (const modification of plan.survivingModifications) {
|
|
3807
|
-
const identity = mergeKeyOf(modification.node);
|
|
3808
|
-
if (plan.nodeDeletions.has(identity) || canonicalIdentities.has(identity)) {
|
|
3809
|
-
continue;
|
|
3810
|
-
}
|
|
3811
|
-
writes.push({
|
|
3812
|
-
identity,
|
|
3813
|
-
kind: modification.node.kind,
|
|
3814
|
-
id: modification.node.id,
|
|
3815
|
-
props: modification.node.forkProps
|
|
3816
|
-
});
|
|
3817
|
-
}
|
|
3818
|
-
for (const entity of plan.canonicalEntities) {
|
|
3819
|
-
const sourceIdentity = mergeKey(entity.kind, entity.canonicalId);
|
|
3820
|
-
if (plan.nodeDeletions.has(sourceIdentity)) {
|
|
3821
|
-
continue;
|
|
3822
|
-
}
|
|
3823
|
-
const kind = plan.retypeMap.get(sourceIdentity) ?? entity.kind;
|
|
3824
|
-
const forkProps = survivingModProps.get(sourceIdentity);
|
|
3825
|
-
writes.push({
|
|
3826
|
-
identity: mergeKey(kind, entity.canonicalId),
|
|
3827
|
-
kind,
|
|
3828
|
-
id: entity.canonicalId,
|
|
3829
|
-
props: forkProps === void 0 ? entity.props : { ...entity.props, ...forkProps }
|
|
3830
|
-
});
|
|
3831
|
-
}
|
|
3832
|
-
return writes;
|
|
3833
|
-
}
|
|
3834
5596
|
function edgeWriteSignature(edge, plan) {
|
|
3835
|
-
const from =
|
|
3836
|
-
const to =
|
|
5597
|
+
const from = finalEdgeEndpoint(plan, edge.fromKind, edge.fromId);
|
|
5598
|
+
const to = finalEdgeEndpoint(plan, edge.toKind, edge.toId);
|
|
3837
5599
|
return JSON.stringify([
|
|
3838
5600
|
edge.kind,
|
|
3839
5601
|
from.kind,
|
|
@@ -3875,7 +5637,7 @@ async function validateIncrementalNodeWrites(target, nodesApi, plan) {
|
|
|
3875
5637
|
const analysis = analyzeRevalidatingWrite(
|
|
3876
5638
|
nodeSchemaFor(target, write.kind),
|
|
3877
5639
|
nodeProps2(current),
|
|
3878
|
-
write.
|
|
5640
|
+
nodeWriteProps(write, (modification) => modification.forkProps)
|
|
3879
5641
|
);
|
|
3880
5642
|
assertValidRevalidatingWrite(
|
|
3881
5643
|
analysis,
|
|
@@ -3927,7 +5689,7 @@ async function validateIncrementalEdgeWrites(target, edgesApi, plan) {
|
|
|
3927
5689
|
}
|
|
3928
5690
|
}
|
|
3929
5691
|
}
|
|
3930
|
-
const notFound = [...plannedKindById.keys()].filter((id) => !existingById.has(id)).sort((left, right) =>
|
|
5692
|
+
const notFound = [...plannedKindById.keys()].filter((id) => !existingById.has(id)).sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
3931
5693
|
if (notFound.length > 0) {
|
|
3932
5694
|
const crossKindById = /* @__PURE__ */ new Map();
|
|
3933
5695
|
for (const kind of Object.keys(target.graph.edges)) {
|
|
@@ -3954,12 +5716,12 @@ async function validateIncrementalEdgeWrites(target, edgesApi, plan) {
|
|
|
3954
5716
|
);
|
|
3955
5717
|
}
|
|
3956
5718
|
throw new MergeError(
|
|
3957
|
-
`mergeIncremental() would overwrite committed edge "${id}" (kind "${row.kind}") with a different-kind edge "${
|
|
5719
|
+
`mergeIncremental() would overwrite committed edge "${id}" (kind "${row.kind}") with a different-kind edge "${chunkN66HCGCY_cjs.requireDefined(plannedKindById.get(id))}" of the same id.`,
|
|
3958
5720
|
{
|
|
3959
5721
|
details: {
|
|
3960
5722
|
id,
|
|
3961
5723
|
committedKind: row.kind,
|
|
3962
|
-
plannedKind:
|
|
5724
|
+
plannedKind: chunkN66HCGCY_cjs.requireDefined(plannedKindById.get(id))
|
|
3963
5725
|
}
|
|
3964
5726
|
}
|
|
3965
5727
|
);
|
|
@@ -3976,8 +5738,8 @@ async function validateIncrementalEdgeWrites(target, edgesApi, plan) {
|
|
|
3976
5738
|
{ details: { id: edge.id, committedKind: current.kind } }
|
|
3977
5739
|
);
|
|
3978
5740
|
}
|
|
3979
|
-
const from =
|
|
3980
|
-
const to =
|
|
5741
|
+
const from = finalEdgeEndpoint(plan, edge.fromKind, edge.fromId);
|
|
5742
|
+
const to = finalEdgeEndpoint(plan, edge.toKind, edge.toId);
|
|
3981
5743
|
if (current.fromId !== from.id || current.fromKind !== from.kind || current.toId !== to.id || current.toKind !== to.kind) {
|
|
3982
5744
|
throw new MergeError(
|
|
3983
5745
|
`mergeIncremental() would overwrite committed edge "${edge.id}" (kind "${edge.kind}") with different endpoints.`,
|
|
@@ -4079,7 +5841,7 @@ async function assertInheritedUnchanged(args) {
|
|
|
4079
5841
|
for (const [kind, ids] of idsByKind) {
|
|
4080
5842
|
const rows = await args.fetchRows(kind, ids);
|
|
4081
5843
|
for (const [index, id] of ids.entries()) {
|
|
4082
|
-
const expected =
|
|
5844
|
+
const expected = chunkN66HCGCY_cjs.requireDefined(args.expected.get(mergeKey(kind, id)));
|
|
4083
5845
|
const current = args.deriveValue(rows[index]);
|
|
4084
5846
|
if (current === expected) {
|
|
4085
5847
|
continue;
|
|
@@ -4149,8 +5911,22 @@ async function assertInheritedEdgesUnchanged(edgesApi, guard, plan) {
|
|
|
4149
5911
|
)
|
|
4150
5912
|
});
|
|
4151
5913
|
}
|
|
5914
|
+
async function assertForkPointUnchanged(precondition) {
|
|
5915
|
+
const liveVersion = await computeBaseVersion(precondition.store);
|
|
5916
|
+
if (liveVersion === precondition.version) return;
|
|
5917
|
+
throw new BaseVersionMismatchError(
|
|
5918
|
+
"The mergeIncremental() fork point was modified between the fork-point precondition and the commit transaction; every branch diff was computed against the previous fork-point state, so the resolved plan was not applied.",
|
|
5919
|
+
{
|
|
5920
|
+
details: {
|
|
5921
|
+
expectedForkPointBase: precondition.version,
|
|
5922
|
+
liveForkPointBase: liveVersion
|
|
5923
|
+
},
|
|
5924
|
+
suggestion: "Keep the fork-point store immutable for the duration of the merge (it is the diff reference, not a merge target), then re-run mergeIncremental()."
|
|
5925
|
+
}
|
|
5926
|
+
);
|
|
5927
|
+
}
|
|
4152
5928
|
async function commitIncrementalPlan(target, plan, guard) {
|
|
4153
|
-
if (!
|
|
5929
|
+
if (!chunkTTAITEPJ_cjs.storeBackend(target).capabilities.transactions) {
|
|
4154
5930
|
throw new MergeError(
|
|
4155
5931
|
"mergeIncremental() requires a transaction-capable target backend. Incremental writes must preflight existing rows and commit atomically; non-transactional fallback would allow partial graph writes.",
|
|
4156
5932
|
{ details: { capability: "transactions" } }
|
|
@@ -4159,36 +5935,56 @@ async function commitIncrementalPlan(target, plan, guard) {
|
|
|
4159
5935
|
return withTxConflictRetry(
|
|
4160
5936
|
() => target.transaction(async (tx) => {
|
|
4161
5937
|
if (target.revisionTrackingEnabled) {
|
|
4162
|
-
await
|
|
5938
|
+
await chunkXMQSEJCF_cjs.lockRecordedGraphWrite(chunkTTAITEPJ_cjs.transactionBackend(tx), target.graphId);
|
|
4163
5939
|
}
|
|
5940
|
+
await assertForkPointUnchanged(guard.forkPoint);
|
|
4164
5941
|
const nodesApi = tx.nodes;
|
|
4165
5942
|
const edgesApi = tx.edges;
|
|
4166
5943
|
await assertBaseResolutionStable(tx, guard);
|
|
5944
|
+
await assertPlannedIdentityIdsFresh(target, chunkTTAITEPJ_cjs.transactionBackend(tx), plan);
|
|
5945
|
+
await assertIdentityPeersStable(
|
|
5946
|
+
target,
|
|
5947
|
+
chunkTTAITEPJ_cjs.transactionBackend(tx),
|
|
5948
|
+
guard.identityPeerProbe,
|
|
5949
|
+
plan
|
|
5950
|
+
);
|
|
4167
5951
|
await assertInheritedTargetUnchanged(nodesApi, edgesApi, guard, plan);
|
|
4168
5952
|
await validateIncrementalNodeWrites(target, nodesApi, plan);
|
|
4169
5953
|
await validateIncrementalEdgeWrites(target, edgesApi, plan);
|
|
4170
|
-
return applyMergePlan(
|
|
5954
|
+
return applyMergePlan(
|
|
5955
|
+
plan,
|
|
5956
|
+
nodesApi,
|
|
5957
|
+
edgesApi,
|
|
5958
|
+
target,
|
|
5959
|
+
chunkTTAITEPJ_cjs.transactionBackend(tx)
|
|
5960
|
+
);
|
|
4171
5961
|
}, mergeCommitTransactionOptions(target))
|
|
4172
5962
|
);
|
|
4173
5963
|
}
|
|
4174
5964
|
async function mergeIncremental(args) {
|
|
4175
5965
|
const { forkPoint, target, branches } = args;
|
|
4176
|
-
const normalized = tryNormalize(args.options ?? {});
|
|
4177
|
-
if (
|
|
4178
|
-
return
|
|
5966
|
+
const normalized = tryNormalize(args.options ?? {}, ["target"]);
|
|
5967
|
+
if (chunk7BQXPCGN_cjs.isErr(normalized)) {
|
|
5968
|
+
return chunk7BQXPCGN_cjs.err(normalized.error);
|
|
4179
5969
|
}
|
|
4180
5970
|
const options = normalized.data;
|
|
4181
5971
|
if (options.onBasePropertyConflict !== "flag") {
|
|
4182
|
-
return
|
|
4183
|
-
new
|
|
5972
|
+
return chunk7BQXPCGN_cjs.err(
|
|
5973
|
+
new InvalidMergeOptionsError(
|
|
4184
5974
|
'mergeIncremental() requires onBasePropertyConflict: "flag" (keep-base); a non-keep-base policy could overwrite a newer committed base value with a stale branch value.',
|
|
4185
|
-
{
|
|
5975
|
+
{
|
|
5976
|
+
details: {
|
|
5977
|
+
option: "onBasePropertyConflict",
|
|
5978
|
+
accepted: "flag",
|
|
5979
|
+
received: options.onBasePropertyConflict
|
|
5980
|
+
}
|
|
5981
|
+
}
|
|
4186
5982
|
)
|
|
4187
5983
|
);
|
|
4188
5984
|
}
|
|
4189
5985
|
const forkPrecondition = await validateForkPointVersions(forkPoint, branches);
|
|
4190
|
-
if (
|
|
4191
|
-
return
|
|
5986
|
+
if (chunk7BQXPCGN_cjs.isErr(forkPrecondition)) {
|
|
5987
|
+
return chunk7BQXPCGN_cjs.err(forkPrecondition.error);
|
|
4192
5988
|
}
|
|
4193
5989
|
const forkVersion = forkPrecondition.data;
|
|
4194
5990
|
const [forkSchema, targetSchema] = await Promise.all([
|
|
@@ -4196,7 +5992,7 @@ async function mergeIncremental(args) {
|
|
|
4196
5992
|
computeSchemaComponent(target)
|
|
4197
5993
|
]);
|
|
4198
5994
|
if (forkSchema !== targetSchema) {
|
|
4199
|
-
return
|
|
5995
|
+
return chunk7BQXPCGN_cjs.err(
|
|
4200
5996
|
new MergeError(
|
|
4201
5997
|
"mergeIncremental() requires target and forkPoint to share a schema; schema drift is not supported (the target content may differ \u2014 only the schema must match).",
|
|
4202
5998
|
{ details: {} }
|
|
@@ -4214,29 +6010,38 @@ async function mergeIncremental(args) {
|
|
|
4214
6010
|
[targetBranch, ...branches],
|
|
4215
6011
|
options,
|
|
4216
6012
|
true,
|
|
4217
|
-
{
|
|
6013
|
+
{
|
|
6014
|
+
targetBranchId: COMMITTED_TARGET_BRANCH,
|
|
6015
|
+
// The fork-point precondition just validated, carried to the commit so
|
|
6016
|
+
// it is re-established there rather than assumed to have held for the
|
|
6017
|
+
// whole of planning (see `assertForkPointUnchanged`).
|
|
6018
|
+
forkPoint: { store: forkPoint, version: forkVersion }
|
|
6019
|
+
}
|
|
4218
6020
|
);
|
|
4219
6021
|
}
|
|
4220
6022
|
|
|
4221
6023
|
Object.defineProperty(exports, "isErr", {
|
|
4222
6024
|
enumerable: true,
|
|
4223
|
-
get: function () { return
|
|
6025
|
+
get: function () { return chunk7BQXPCGN_cjs.isErr; }
|
|
4224
6026
|
});
|
|
4225
6027
|
Object.defineProperty(exports, "isOk", {
|
|
4226
6028
|
enumerable: true,
|
|
4227
|
-
get: function () { return
|
|
6029
|
+
get: function () { return chunk7BQXPCGN_cjs.isOk; }
|
|
4228
6030
|
});
|
|
4229
6031
|
Object.defineProperty(exports, "unwrap", {
|
|
4230
6032
|
enumerable: true,
|
|
4231
|
-
get: function () { return
|
|
6033
|
+
get: function () { return chunk7BQXPCGN_cjs.unwrap; }
|
|
4232
6034
|
});
|
|
4233
6035
|
exports.BaseVersionMismatchError = BaseVersionMismatchError;
|
|
4234
6036
|
exports.BranchError = BranchError;
|
|
6037
|
+
exports.IdentityMergeConflictError = IdentityMergeConflictError;
|
|
6038
|
+
exports.InvalidMergeOptionsError = InvalidMergeOptionsError;
|
|
4235
6039
|
exports.MERGE_ERROR_CODES = MERGE_ERROR_CODES;
|
|
4236
6040
|
exports.MERGE_OPTION_DEFAULTS = MERGE_OPTION_DEFAULTS;
|
|
4237
6041
|
exports.MergeConflictError = MergeConflictError;
|
|
4238
6042
|
exports.MergeError = MergeError;
|
|
4239
6043
|
exports.SimilarityUnavailableError = SimilarityUnavailableError;
|
|
6044
|
+
exports.VALIDITY_END_TARGET_PRECEDENCE = VALIDITY_END_TARGET_PRECEDENCE;
|
|
4240
6045
|
exports.asBaseVersion = asBaseVersion;
|
|
4241
6046
|
exports.asBranchId = asBranchId;
|
|
4242
6047
|
exports.branch = branch;
|